type EntityKey = u32;
type CompKey = (std::any::TypeId, u32);
struct CompRow<T> {
comp: T,
entity_key: u32,
ref_0_row_key: u32,
ref_1_row_key: u32,
}
const ALLOC_SIZE: usize = std::mem::size_of::<slab::Slab<CompRow<()>>>();
struct CompColumn {
comp_rows: stack_any::StackAny<ALLOC_SIZE>,
get_row_fn: fn(&Self, u32) -> Option<CompRow<()>>,
remove_row_fn: fn(&mut Self, u32) -> Option<CompRow<()>>,
}
#[derive(Default)]
pub struct ECS {
entities: slab::Slab<()>,
comp_cols: ahash::AHashMap<std::any::TypeId, CompColumn>,
ref_0_cols: ahash::AHashMap<EntityKey, slab::Slab<(std::any::TypeId, u32)>>,
ref_1_cols: ahash::AHashMap<(EntityKey, std::any::TypeId), slab::Slab<u32>>,
}
impl ECS {
pub fn new() -> Self {
Default::default()
}
pub fn insert_entity(&mut self) -> EntityKey {
self.entities.insert(()) as u32
}
pub fn remove_entity(&mut self, entity_key: EntityKey) -> Option<()> {
self.entities.try_remove(entity_key as usize)?;
if let Some(ref_0_col) = self.ref_0_cols.remove(&entity_key) {
for (_, (type_key, row_key)) in ref_0_col {
let comp_col = self.comp_cols.get_mut(&type_key).unwrap();
let comp_row = (comp_col.remove_row_fn)(comp_col, row_key).unwrap();
self.ref_1_cols
.get_mut(&(entity_key, type_key))
.unwrap()
.try_remove(comp_row.ref_1_row_key as usize)
.unwrap();
}
}
Some(())
}
pub fn get_entity(&self, entity_key: EntityKey) -> Option<()> {
self.entities.get(entity_key as usize)?;
Some(())
}
pub fn iter_entity(&self) -> impl Iterator<Item = EntityKey> + '_ {
self.entities.iter().map(|(key, _)| key as u32)
}
pub fn register<T>(&mut self) -> Option<()>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
if self.comp_cols.contains_key(&type_key) {
return None;
}
let comp_col = CompColumn {
comp_rows: stack_any::StackAny::try_new(slab::Slab::<CompRow<T>>::new()).unwrap(),
get_row_fn: |comp_col, row_key| {
let comp_row = comp_col
.comp_rows
.downcast_ref::<slab::Slab<CompRow<T>>>()
.unwrap()
.get(row_key as usize)?;
Some(CompRow {
comp: (),
entity_key: comp_row.entity_key,
ref_0_row_key: comp_row.ref_0_row_key,
ref_1_row_key: comp_row.ref_1_row_key,
})
},
remove_row_fn: |comp_col, row_key| {
let comp_row = comp_col
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap()
.try_remove(row_key as usize)?;
Some(CompRow {
comp: (),
entity_key: comp_row.entity_key,
ref_0_row_key: comp_row.ref_0_row_key,
ref_1_row_key: comp_row.ref_1_row_key,
})
},
};
self.comp_cols.insert(type_key, comp_col);
Some(())
}
pub fn unregister<T>(&mut self) -> Option<()>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
if !self.comp_cols.contains_key(&type_key) {
return None;
}
self.comp_cols.remove(&type_key);
Some(())
}
pub fn insert_comp<T>(&mut self, entity_key: EntityKey, comp: T) -> Option<CompKey>
where
T: std::any::Any,
{
self.entities.get(entity_key as usize)?;
let type_key = std::any::TypeId::of::<T>();
let comp_rows = self
.comp_cols
.get_mut(&type_key)?
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap();
let row_key = comp_rows.vacant_key() as u32;
let ref_0_row_key = self
.ref_0_cols
.entry(entity_key)
.or_default()
.insert((type_key, row_key)) as u32;
let ref_1_row_key = self
.ref_1_cols
.entry((entity_key, type_key))
.or_default()
.insert(row_key) as u32;
comp_rows.insert(CompRow {
comp,
entity_key,
ref_0_row_key,
ref_1_row_key,
});
Some((type_key, row_key))
}
pub fn remove_comp<T>(&mut self, comp_key: CompKey) -> Option<T>
where
T: std::any::Any,
{
let (type_key, row_key) = comp_key;
if type_key != std::any::TypeId::of::<T>() {
return None;
}
let comp_rows = self
.comp_cols
.get_mut(&type_key)?
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap();
let comp_row = comp_rows.try_remove(row_key as usize)?;
self.ref_0_cols
.get_mut(&comp_row.entity_key)
.unwrap()
.try_remove(comp_row.ref_0_row_key as usize)
.unwrap();
self.ref_1_cols
.get_mut(&(comp_row.entity_key, type_key))
.unwrap()
.try_remove(comp_row.ref_1_row_key as usize)
.unwrap();
Some(comp_row.comp)
}
pub fn get_comp<T>(&self, comp_key: CompKey) -> Option<&T>
where
T: std::any::Any,
{
let (type_key, row_key) = comp_key;
if type_key != std::any::TypeId::of::<T>() {
return None;
}
let comp_rows = self
.comp_cols
.get(&type_key)?
.comp_rows
.downcast_ref::<slab::Slab<CompRow<T>>>()
.unwrap();
let comp_row = comp_rows.get(row_key as usize)?;
Some(&comp_row.comp)
}
pub fn get_comp_mut<T>(&mut self, comp_key: CompKey) -> Option<&mut T>
where
T: std::any::Any,
{
let (type_key, row_key) = comp_key;
if type_key != std::any::TypeId::of::<T>() {
return None;
}
let comp_rows = self
.comp_cols
.get_mut(&type_key)?
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap();
let comp = comp_rows.get_mut(row_key as usize)?;
Some(&mut comp.comp)
}
pub fn iter_comp<T>(&self) -> Option<impl Iterator<Item = &T>>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
let comp_rows = self
.comp_cols
.get(&type_key)?
.comp_rows
.downcast_ref::<slab::Slab<CompRow<T>>>()
.unwrap();
let iter = comp_rows.iter().map(|(_, comp_row)| &comp_row.comp);
Some(iter)
}
pub fn iter_comp_mut<T>(&mut self) -> Option<impl Iterator<Item = &mut T>>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
let comp_rows = self
.comp_cols
.get_mut(&type_key)?
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap();
let iter = comp_rows.iter_mut().map(|(_, comp_row)| &mut comp_row.comp);
Some(iter)
}
pub fn get_entity_by_comp(&self, comp_key: CompKey) -> Option<EntityKey> {
let (type_key, row_key) = comp_key;
let comp_col = self.comp_cols.get(&type_key)?;
let comp_row = (comp_col.get_row_fn)(comp_col, row_key)?;
Some(comp_row.entity_key)
}
pub fn iter_comp_by_entity<T>(&self, entity_key: EntityKey) -> Option<impl Iterator<Item = &T>>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
let comp_rows = self
.comp_cols
.get(&type_key)?
.comp_rows
.downcast_ref::<slab::Slab<CompRow<T>>>()
.unwrap();
let ref_1_col = self.ref_1_cols.get(&(entity_key, type_key))?;
let iter = ref_1_col
.iter()
.map(|(_, row_key)| &comp_rows.get(*row_key as usize).unwrap().comp);
Some(iter)
}
pub fn iter_comp_mut_by_entity<T>(
&mut self,
entity_key: EntityKey,
) -> Option<impl Iterator<Item = &mut T>>
where
T: std::any::Any,
{
let type_key = std::any::TypeId::of::<T>();
let comp_rows = self
.comp_cols
.get_mut(&type_key)?
.comp_rows
.downcast_mut::<slab::Slab<CompRow<T>>>()
.unwrap();
let ref_1_col = self.ref_1_cols.get(&(entity_key, type_key))?;
let iter = ref_1_col
.iter()
.map(|(_, row_key)| &mut comp_rows.get_mut(*row_key as usize).unwrap().comp as *mut T)
.map(|ptr| unsafe { &mut *ptr });
Some(iter)
}
pub fn clear(&mut self) {
self.entities.clear();
self.comp_cols.clear();
self.ref_0_cols.clear();
self.ref_1_cols.clear();
}
}