use std::cell::UnsafeCell;
use crate::{
change_detection::ChangeTicks,
world::{ComponentDescriptor, ComponentId, ComponentInfo, Entity, EntityIdSet},
};
use super::{DenseStorage, Resources, SparseArray};
#[derive(Debug)]
pub struct StorageSet<T> {
storage_sets: SparseArray<T>,
}
impl<T> Default for StorageSet<T> {
#[inline]
fn default() -> Self {
Self {
storage_sets: SparseArray::new(),
}
}
}
impl<T> StorageSet<T>
where
T: ComponentStorage,
{
#[inline]
pub fn get(&self, id: ComponentId) -> Option<&T> {
self.storage_sets.get(id.index())
}
#[inline]
pub fn get_mut(&mut self, id: ComponentId) -> Option<&mut T> {
self.storage_sets.get_mut(id.index())
}
#[inline]
pub unsafe fn get_unchecked(&self, id: ComponentId) -> &T {
unsafe { self.storage_sets.get_unchecked(id.index()) }
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, id: ComponentId) -> &mut T {
unsafe { self.storage_sets.get_unchecked_mut(id.index()) }
}
pub fn get_or_init(&mut self, info: &ComponentInfo) -> &mut T {
self.storage_sets.get_or_insert_with(info.id.index(), || {
ComponentStorage::new(info.descriptor.clone(), 0)
})
}
#[inline]
pub fn initialize(&mut self, info: &ComponentInfo) {
if !self.storage_sets.contains(info.id().index()) {
let set = ComponentStorage::new(info.descriptor().clone(), 0);
self.storage_sets.insert(info.id().index(), set);
}
}
#[inline]
pub fn remove_and_drop(&mut self, entity: Entity, id: ComponentId) {
if let Some(storage) = self.get_mut(id) {
storage.remove_and_drop(entity);
}
}
#[inline]
pub fn remove(&mut self, entity: Entity) {
for (_, storage) in self.storage_sets.iter_mut() {
storage.remove_and_drop(entity);
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum StorageType {
Dense,
Resource,
}
#[derive(Debug, Default)]
pub struct Storages {
pub dense: StorageSet<DenseStorage>,
pub resources: Resources,
}
impl Storages {
#[inline]
pub fn remove(&mut self, entity: Entity) {
self.dense.remove(entity);
}
#[inline]
pub fn contains(&self, id: ComponentId, entity: Entity) -> bool {
if let Some(storage) = self.dense.get(id) {
return storage.contains(entity);
}
false
}
#[inline]
pub fn entity_ids(&self, id: ComponentId) -> EntityIdSet {
if let Some(sparse) = self.dense.get(id) {
return sparse.entity_ids();
}
EntityIdSet::default()
}
#[inline]
pub fn check_change_ticks(&mut self, tick: u32) {
for (_, storage) in self.dense.storage_sets.iter_mut() {
storage.check_change_ticks(tick);
}
}
}
pub trait ComponentStorage: Send + Sync + 'static {
fn new(desc: ComponentDescriptor, capacity: usize) -> Self;
fn contains(&self, entity: Entity) -> bool;
fn entity_ids(&self) -> EntityIdSet;
unsafe fn insert(&mut self, entity: Entity, data: *mut u8, change_ticks: u32);
unsafe fn remove_unchecked(&mut self, entity: Entity, data: *mut u8);
fn remove_and_drop(&mut self, entity: Entity);
unsafe fn get_unchecked(&self, entity: Entity) -> *mut u8;
#[inline]
fn get(&self, entity: Entity) -> Option<*mut u8> {
if self.contains(entity) {
unsafe { Some(self.get_unchecked(entity)) }
} else {
None
}
}
unsafe fn get_ticks_unchecked(&self, entity: Entity) -> &UnsafeCell<ChangeTicks>;
unsafe fn get_with_ticks_unchecked(
&self,
entity: Entity,
) -> (*mut u8, &UnsafeCell<ChangeTicks>);
}