use std::mem::MaybeUninit;
use std::collections::HashMap;
use crate::component::{Component, ComponentId};
use crate::entity::{EntityId, EntityStore};
macro_rules! get_entity_ids_enumerate_iter {
($arch:tt, $ent_store:tt) => {
$arch.entities.iter()
.enumerate()
.filter(|(_, id)| $ent_store.is_alive(**id))
}
}
pub(crate) type ArchRowId = u32;
struct ComponentColumn {
components: Vec<MaybeUninit<u8>>,
}
impl ComponentColumn {
fn new() -> Self {
Self {
components: Vec::new(),
}
}
}
struct ComponentColumnWrapper {
val: Option<ComponentColumn>,
size: usize
}
impl ComponentColumnWrapper {
fn new(size: usize) -> Self {
Self {
val: if size == 0 {
None
} else {
Some(ComponentColumn::new())
},
size,
}
}
}
pub(crate) struct Archetype {
components: HashMap<ComponentId, ComponentColumnWrapper>,
available_ent_ids: Vec<ArchRowId>,
entities: Vec<EntityId>,
}
impl Archetype {
pub(crate) fn new(components: &Vec<ComponentId>, sizes: &Vec<usize>) -> Self {
let mut comps = HashMap::with_capacity(components.len());
for i in 0..components.len() {
comps.insert(components[i], ComponentColumnWrapper::new(sizes[i]));
}
Self {
components: comps,
available_ent_ids: Vec::new(),
entities: Vec::new()
}
}
#[inline]
pub(crate) fn new_archrow_id(&mut self, entity: EntityId) -> ArchRowId {
if let Some(id) = self.available_ent_ids.pop() {
self.entities[id as usize] = entity;
return id;
} else {
let id = self.entities.len();
self.entities.push(entity);
return id as ArchRowId;
}
}
#[inline]
pub(crate) fn set_component<T: Component + 'static>(&mut self, entity_id: ArchRowId, component: T) {
let component_col_wrap = self.components.get_mut(&T::id())
.expect(&format!("Component {} does not exist for entity with id {}", std::any::type_name::<T>(), entity_id));
if component_col_wrap.size == 0 {
return;
}
let component_col = unsafe { component_col_wrap.val.as_mut().unwrap_unchecked() };
if component_col.components.len() <= entity_id as usize * component_col_wrap.size {
component_col.components.resize_with((entity_id as usize) * component_col_wrap.size + component_col_wrap.size, MaybeUninit::uninit);
}
let comps_ptr: *mut MaybeUninit<u8> = component_col.components.as_mut_ptr();
let comps_ptr: *mut MaybeUninit<T> = comps_ptr.cast();
unsafe { *(comps_ptr.offset(entity_id as isize)) = MaybeUninit::new(component); }
}
#[inline]
pub(crate) unsafe fn get_component<T: Component + 'static>(&self, entity_id: ArchRowId) -> &T {
let component_col_wrap = self.components.get(&T::id())
.expect(&format!("Component {} does not exist for entity with id {}", std::any::type_name::<T>(), entity_id));
let component_col = component_col_wrap.val.as_ref().unwrap_unchecked();
let comps_ptr: *const MaybeUninit<u8> = component_col.components.as_ptr();
let comps_ptr: *const MaybeUninit<T> = comps_ptr.cast();
(comps_ptr.offset(entity_id as isize)).as_ref().unwrap_unchecked().assume_init_ref()
}
#[inline]
pub(crate) unsafe fn get_component_mut<T: Component + 'static>(&mut self, entity_id: ArchRowId) -> &mut T {
let component_col_wrap = self.components.get_mut(&T::id())
.expect(&format!("Component {} does not exist for entity with id {}", std::any::type_name::<T>(), entity_id));
let component_col = component_col_wrap.val.as_mut().unwrap_unchecked();
let comps_ptr: *mut MaybeUninit<u8> = component_col.components.as_mut_ptr();
let comps_ptr: *mut MaybeUninit<T> = comps_ptr.cast();
(comps_ptr.offset(entity_id as isize)).as_mut().unwrap_unchecked().assume_init_mut()
}
#[inline]
pub(crate) unsafe fn get_all_components
<'a, T: Component + 'static>
(
&'a self,
ent_ids: impl std::iter::Iterator<Item = ArchRowId>
)
-> impl std::iter::Iterator<Item = &'a T>
{
let component_col_wrap = self.components.get(&T::id())
.unwrap();
let component_col = component_col_wrap.val.as_ref().unwrap_unchecked();
let comps_ptr: *const MaybeUninit<u8> = component_col.components.as_ptr();
let comps_ptr: *const MaybeUninit<T> = comps_ptr.cast();
ent_ids.into_iter()
.map(move |ent_id| { let comp = comps_ptr.offset(ent_id as isize).as_ref().unwrap_unchecked();
comp.assume_init_ref()
})
}
#[inline]
pub(crate) unsafe fn get_all_components_mut<
'a, T: Component + 'static
>(
&'a mut self,
ent_ids: impl std::iter::Iterator<Item = ArchRowId>,
) -> impl std::iter::Iterator<Item = &'a mut T>
{
let component_col_wrap = self.components.get_mut(&T::id())
.unwrap();
let component_col = component_col_wrap.val.as_mut().unwrap_unchecked();
let comps_ptr: *mut MaybeUninit<u8> = component_col.components.as_mut_ptr();
let comps_ptr: *mut MaybeUninit<T> = comps_ptr.cast();
ent_ids
.map(move |ent_id| {
let comp = comps_ptr.offset(ent_id as isize).as_mut().unwrap_unchecked();
comp.assume_init_mut()
})
}
#[inline]
#[allow(unused)] pub(crate) unsafe fn get_all_components_mut_ptr<T: Component + 'static>(&mut self, ent_ids: &Vec<EntityId>) -> Vec<*mut T> {
let component_col_wrap = self.components.get_mut(&T::id())
.expect(&format!("Component {} does not exist for the entities with ids {:?}", std::any::type_name::<T>(), ent_ids));
let component_col = component_col_wrap.val.as_mut().unwrap_unchecked();
let comps_ptr: *mut MaybeUninit<u8> = component_col.components.as_mut_ptr();
let comps_ptr: *mut MaybeUninit<T> = comps_ptr.cast();
ent_ids.iter()
.map(|ent_id| {
let comp = comps_ptr.offset(*ent_id as isize).as_mut().unwrap_unchecked();
let comp: *mut T = comp.assume_init_mut();
comp
}).collect()
}
#[inline]
pub(crate) fn get_arch_rows<'a>(&'a self, ent_store: &'a EntityStore)
-> impl std::iter::Iterator<Item = ArchRowId> + 'a
{
get_entity_ids_enumerate_iter!(self, ent_store)
.map(|(row, _)| row as u32)
}
#[inline]
pub(crate) fn has_component(&self, id: ComponentId) -> bool {
self.components.contains_key(&id)
}
#[inline]
pub(crate) fn remove_entity(&mut self, arch_row: ArchRowId) {
self.available_ent_ids.push(arch_row);
}
}