use super::{
component::{Component, ComponentKey},
entity::{
ContainEntity, Entity, EntityId, EntityIndex, EntityKey, EntityKeyKind, EntityKeyRef,
EntityName, EntityTag,
},
};
use crate::{ecs::EcsError, util, FxBuildHasher};
use my_utils::{
debug_format,
ds::{
BorrowResult, Borrowed, DescribeGroup, Getter, GetterMut, GroupDesc, GroupMap,
SimpleHolder, TypeInfo,
},
With,
};
use std::{
any::TypeId,
collections::HashMap,
fmt,
hash::BuildHasher,
marker::PhantomData,
ops::{Deref, DerefMut},
ptr::NonNull,
sync::Arc,
};
pub trait AsEntityReg {
fn entity_descriptor() -> EntityReg;
}
#[derive(Debug)]
pub(crate) struct EntityStorage<S = FxBuildHasher> {
map: GroupMap<Arc<[ComponentKey]>, EntityContainer, ComponentKey, TypeInfo, S>,
name_to_index: HashMap<EntityName, EntityIndex, S>,
ent_gens: Vec<u64>,
generation: u64,
}
impl EntityStorage {
#[cfg(test)]
pub(crate) fn new() -> Self {
Self {
map: GroupMap::new(),
name_to_index: HashMap::with_hasher(FxBuildHasher::default()),
ent_gens: Vec::new(),
generation: 1,
}
}
}
impl<S> EntityStorage<S> {
pub(crate) fn with_hasher<F: FnMut() -> S>(mut hasher: F) -> Self {
Self {
map: GroupMap::with_hasher(&mut hasher),
name_to_index: HashMap::with_hasher(hasher()),
ent_gens: Vec::new(),
generation: 1,
}
}
}
impl<S> EntityStorage<S>
where
S: BuildHasher + Default,
{
#[inline]
pub(crate) fn convert_entity_key<'r, K>(&self, key: K, to: EntityKeyKind) -> Option<EntityKey>
where
K: Into<EntityKeyRef<'r>>,
{
fn inner<S>(
this: &EntityStorage<S>,
key: EntityKeyRef<'_>,
to: EntityKeyKind,
) -> Option<EntityKey>
where
S: BuildHasher + Default,
{
let ei = this.entity_index(key)?;
let res = match to {
EntityKeyKind::Name => {
let cont = unsafe { this.map.get_group(ei).unwrap_unchecked() };
let name = cont.get_tag().get_name()?.clone();
EntityKey::Name(name)
}
EntityKeyKind::Index => {
let ei = EntityIndex::new(With::new(
ei,
unsafe { *this.ent_gens.get_unchecked(ei) },
));
EntityKey::Index(ei)
}
EntityKeyKind::Ckeys => {
let ckeys = unsafe { this.map.get_group_key(ei).unwrap_unchecked() };
EntityKey::Ckeys(Arc::clone(ckeys))
}
};
Some(res)
}
inner(self, key.into(), to)
}
pub(crate) fn get_component_keys<'r, K>(&self, key: K) -> Option<&Arc<[ComponentKey]>>
where
K: Into<EntityKeyRef<'r>>,
{
let ei = self.entity_index(key)?;
let ckeys = unsafe { self.map.get_group_key(ei).unwrap_unchecked() };
Some(ckeys)
}
pub(crate) fn get_entity_container<'r, K>(&self, key: K) -> Option<&EntityContainer>
where
K: Into<EntityKeyRef<'r>>,
{
let ei = self.entity_index(key)?;
let cont = unsafe { self.map.get_group(ei).unwrap_unchecked() };
Some(cont)
}
pub(crate) fn get_entity_container_mut<'r, K>(&mut self, key: K) -> Option<&mut EntityContainer>
where
K: Into<EntityKeyRef<'r>>,
{
let ei = self.entity_index(key)?;
let cont = unsafe { self.map.get_group_mut(ei).unwrap_unchecked() };
Some(cont)
}
pub(crate) fn get_two_entity_container_mut<'r, K1, K2>(
&mut self,
key1: K1,
key2: K2,
) -> Option<(&mut EntityContainer, &mut EntityContainer)>
where
K1: Into<EntityKeyRef<'r>>,
K2: Into<EntityKeyRef<'r>>,
{
let ei1 = self.entity_index(key1)?;
let ei2 = self.entity_index(key2)?;
let groups = unsafe { self.map.as_mut_groups() };
unsafe {
let (slot1, slot2) = util::get_two_mut(groups, ei1, ei2).unwrap_unchecked();
let cont1 = slot1.as_mut().unwrap_unchecked();
let cont2 = slot2.as_mut().unwrap_unchecked();
Some((cont1, cont2))
}
}
#[allow(unused)]
pub(crate) fn get_two_enitty_containers_mut<'r, K1, K2>(
&mut self,
key1: K1,
key2: K2,
) -> Option<(&mut EntityContainer, &mut EntityContainer)>
where
K1: Into<EntityKeyRef<'r>>,
K2: Into<EntityKeyRef<'r>>,
{
let ei1 = self.entity_index(key1)?;
let ei2 = self.entity_index(key2)?;
todo!()
}
pub(crate) fn iter_entity_container(
&self,
) -> impl Iterator<Item = (&Arc<[ComponentKey]>, EntityIndex, &EntityContainer)> {
self.map.iter_group().map(|(ckeys, index, cont)| {
(
ckeys,
EntityIndex::new(With::new(index, self.ent_gens[index])),
cont,
)
})
}
pub(crate) fn register(&mut self, mut desc: EntityReg) -> Result<EntityIndex, EcsError> {
if desc.is_empty() {
let reason = debug_format!(
"failed to register an entity: `{:?}` has no components",
desc.get_name()
);
return Err(EcsError::InvalidEntity(reason, ()));
}
let gkey = desc
.get_key_info_pairs()
.iter()
.map(|(ckey, _)| *ckey)
.collect::<Vec<_>>();
let index = self.map.next_index(&*gkey);
let ei = EntityIndex::new(With::new(index, self.generation));
desc.set_index(ei);
let ename = desc.get_name().cloned();
match self.map.add_group(desc) {
Ok(i) => {
debug_assert_eq!(i, index);
self.generation += 1;
if let Some(name) = ename {
self.name_to_index.insert(name, ei);
}
while self.ent_gens.len() <= index {
self.ent_gens.push(0);
}
self.ent_gens[index] = ei.generation();
Ok(ei)
}
Err(desc) => {
let cont = self.map.get_group2(&desc.group_key).unwrap();
let reason = debug_format!(
"failed to register an entity: two entities `{:?}` and `{:?}` are the same",
ename,
cont.get_tag().get_name()
);
Err(EcsError::InvalidEntity(reason, ()))
}
}
}
pub(crate) fn unregister<'r, K>(
&mut self,
key: K,
) -> Option<(Arc<[ComponentKey]>, EntityContainer)>
where
K: Into<EntityKeyRef<'r>>,
{
return inner(self, key.into());
fn inner<S>(
this: &mut EntityStorage<S>,
key: EntityKeyRef<'_>,
) -> Option<(Arc<[ComponentKey]>, EntityContainer)>
where
S: BuildHasher + Default,
{
let index = this.entity_index(key)?;
let ckeys_cont = this.map.remove_group(index);
debug_assert!(ckeys_cont.is_some());
if let Some((_ckeys, cont)) = ckeys_cont.as_ref() {
if let Some(name) = cont.get_tag().get_name() {
this.name_to_index.remove(name);
}
}
ckeys_cont
}
}
pub(crate) fn entity_index<'r, K>(&self, key: K) -> Option<usize>
where
K: Into<EntityKeyRef<'r>>,
{
return inner(self, key.into());
fn inner<S>(this: &EntityStorage<S>, key: EntityKeyRef<'_>) -> Option<usize>
where
S: BuildHasher + Default,
{
match key {
EntityKeyRef::Ckeys(ckeys) => this.map.get_group_index(ckeys),
EntityKeyRef::Index(ei) => this.is_valid_index(ei).then_some(ei.index()),
EntityKeyRef::Name(name) => {
let ei = this.name_to_index.get(name)?;
this.is_valid_index(ei).then_some(ei.index())
}
}
}
}
#[allow(dead_code)]
pub(crate) unsafe fn get_ptr(&self, ei: &EntityIndex) -> Option<NonNull<dyn ContainEntity>> {
let ekey = EntityKeyRef::from(ei);
let cont = self.get_entity_container(ekey)?;
let ptr = *cont.cont_ptr.borrow().unwrap();
Some(ptr)
}
fn is_valid_index(&self, ei: &EntityIndex) -> bool {
self.map.contains_group(ei.index()) && ei.generation() == self.ent_gens[ei.index()]
}
}
impl<S> Default for EntityStorage<S>
where
S: Default,
{
fn default() -> Self {
Self::with_hasher(|| S::default())
}
}
pub struct EntityReg {
name: Option<EntityName>,
index: Option<EntityIndex>,
cont: Box<dyn ContainEntity>,
key_info_pairs: Vec<(ComponentKey, TypeInfo)>,
}
impl fmt::Debug for EntityReg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EntityReg")
.field("name", &self.get_name())
.field("index", &self.get_index())
.field("key_info_pairs", &self.get_key_info_pairs())
.finish_non_exhaustive()
}
}
impl EntityReg {
pub fn new(name: Option<EntityName>, mut cont: Box<dyn ContainEntity>) -> Self {
for ci in (0..cont.num_columns()).rev() {
cont.remove_column(ci);
}
Self {
name,
index: None,
cont,
key_info_pairs: Vec::new(),
}
}
pub(crate) const fn get_name(&self) -> Option<&EntityName> {
self.name.as_ref()
}
pub(crate) const fn get_index(&self) -> Option<&EntityIndex> {
self.index.as_ref()
}
pub(crate) const fn get_key_info_pairs(&self) -> &Vec<(ComponentKey, TypeInfo)> {
&self.key_info_pairs
}
pub fn add_component_of<C: Component>(&mut self) {
self.add_component(C::type_info());
}
pub fn add_component(&mut self, tinfo: TypeInfo) {
let pair = (ComponentKey::from(&tinfo), tinfo);
self.key_info_pairs.push(pair);
}
fn is_empty(&self) -> bool {
self.key_info_pairs.is_empty()
}
fn set_index(&mut self, index: EntityIndex) {
self.index = Some(index);
}
fn finish(self) -> GroupDesc<Arc<[ComponentKey]>, EntityContainer, ComponentKey, TypeInfo> {
let Self {
name,
index,
mut cont,
mut key_info_pairs,
} = self;
let index = index.unwrap();
let old_len = key_info_pairs.len();
key_info_pairs.sort_unstable_by_key(|(key, _)| *key);
key_info_pairs.dedup_by_key(|(key, _)| *key);
assert_eq!(
key_info_pairs.len(),
old_len,
"entity cannot have duplicated components"
);
let mut ckeys = Vec::new();
let mut cnames = Vec::new();
for (ckey, tinfo) in key_info_pairs.iter() {
cnames.push(tinfo.name);
ckeys.push(*ckey);
cont.add_column(*tinfo);
}
let ckeys: Arc<[ComponentKey]> = ckeys.into();
let cnames: Box<[&'static str]> = cnames.into();
let tag = EntityTag::new(index, name, Arc::clone(&ckeys), cnames);
let tag = Arc::new(tag);
let cont = EntityContainer::new(tag, cont);
GroupDesc {
group_key: ckeys,
group_value: cont,
items: key_info_pairs,
}
}
}
impl DescribeGroup<Arc<[ComponentKey]>, EntityContainer, ComponentKey, TypeInfo> for EntityReg {
fn into_group_and_items(
self,
) -> GroupDesc<Arc<[ComponentKey]>, EntityContainer, ComponentKey, TypeInfo> {
self.finish()
}
}
pub(crate) struct EntityContainer {
tag: Arc<EntityTag>,
cont: Box<dyn ContainEntity>,
cont_ptr: SimpleHolder<NonNull<dyn ContainEntity>>,
}
impl fmt::Debug for EntityContainer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EntityContainer")
.field("tag", &self.get_tag())
.field("cont_ptr", &self.cont_ptr)
.finish_non_exhaustive()
}
}
impl EntityContainer {
pub(crate) fn new(tag: Arc<EntityTag>, mut cont: Box<dyn ContainEntity>) -> Self {
let cont_ptr = unsafe { NonNull::new_unchecked(&mut *cont as *mut _) };
let cont_ptr = SimpleHolder::new(cont_ptr);
Self {
tag,
cont,
cont_ptr,
}
}
pub(crate) fn into_inner(self) -> Box<dyn ContainEntity> {
self.cont
}
pub(crate) const fn get_tag(&self) -> &Arc<EntityTag> {
&self.tag
}
pub(crate) fn borrow(&self) -> BorrowResult<NonNull<dyn ContainEntity>> {
self.cont_ptr.borrow()
}
}
impl Deref for EntityContainer {
type Target = dyn ContainEntity;
fn deref(&self) -> &Self::Target {
&*self.cont
}
}
impl DerefMut for EntityContainer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.cont
}
}
pub struct EntityContainerRef<'buf, T> {
etag: &'buf EntityTag,
cont: &'buf mut dyn ContainEntity,
_marker: PhantomData<&'buf mut T>,
}
impl<T> fmt::Debug for EntityContainerRef<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EntityContainerRef")
.field("etag", &self.get_entity_tag())
.finish_non_exhaustive()
}
}
impl<'buf, T> EntityContainerRef<'buf, T> {
pub(crate) fn new(etag: &'buf EntityTag, cont: &'buf mut dyn ContainEntity) -> Self {
Self {
etag,
cont,
_marker: PhantomData,
}
}
pub const fn get_entity_tag(&self) -> &EntityTag {
self.etag
}
pub fn len(&self) -> usize {
self.cont.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
self.cont.capacity()
}
pub fn num_columns(&self) -> usize {
self.cont.num_columns()
}
pub fn is_default(&self) -> bool {
(0..self.num_columns()).all(|ci| {
let tinfo = unsafe { self.cont.get_column_info(ci).unwrap_unchecked() };
tinfo.is_default
})
}
pub fn is_clone(&self) -> bool {
(0..self.num_columns()).all(|ci| {
let tinfo = unsafe { self.cont.get_column_info(ci).unwrap_unchecked() };
tinfo.is_clone
})
}
pub fn reserve(&mut self, additional: usize) {
self.cont.reserve(additional);
}
pub fn shrink_to_fit(&mut self) {
self.cont.shrink_to_fit();
}
pub fn get_column_of<C: Component>(&self) -> Option<Borrowed<Getter<'_, C>>> {
let ci = self.cont.get_column_index(&TypeId::of::<C>())?;
self.cont.borrow_column(ci).ok().map(|col| {
col.map(|raw_getter| unsafe { Getter::from_raw(raw_getter) })
})
}
pub fn get_column_mut_of<C: Component>(&mut self) -> Option<Borrowed<GetterMut<'_, C>>> {
let ci = self.cont.get_column_index(&TypeId::of::<C>())?;
self.cont.borrow_column_mut(ci).ok().map(|col| {
col.map(|raw_getter| unsafe { GetterMut::from_raw(raw_getter) })
})
}
pub fn remove(&mut self, eid: &EntityId) {
if eid.container_index() == self.get_entity_tag().index() {
if let Some(vi) = self.cont.to_value_index(eid.row_index()) {
self.remove_by_value_index(vi);
}
}
}
pub fn remove_by_value_index(&mut self, vi: usize) {
self.cont.remove_row_by_value_index(vi);
}
}
impl<T> EntityContainerRef<'_, T>
where
T: Entity,
{
pub fn get(&self, eid: &EntityId) -> Option<T::Ref<'_>> {
if eid.container_index() == self.get_entity_tag().index() {
let vi = self.cont.to_value_index(eid.row_index())?;
Some(self.get_by_value_index(vi))
} else {
None
}
}
pub fn get_mut(&mut self, eid: &EntityId) -> Option<T::Mut<'_>> {
if eid.container_index() == self.get_entity_tag().index() {
let vi = self.cont.to_value_index(eid.row_index())?;
Some(self.get_mut_by_value_index(vi))
} else {
None
}
}
pub fn get_by_value_index(&self, vi: usize) -> T::Ref<'_> {
T::get_ref_from(self.cont, vi)
}
pub fn get_mut_by_value_index(&mut self, vi: usize) -> T::Mut<'_> {
T::get_mut_from(self.cont, vi)
}
pub fn add(&mut self, value: T) -> EntityId {
let ei = self.get_entity_tag().index();
let ri = value.move_to(self.cont);
EntityId::new(ei, ri)
}
pub fn take(&mut self, eid: &EntityId) -> Option<T> {
if eid.container_index() == self.get_entity_tag().index() {
let vi = self.cont.to_value_index(eid.row_index())?;
Some(self.take_by_value_index(vi))
} else {
None
}
}
pub fn take_by_value_index(&mut self, vi: usize) -> T {
T::take_from(self.cont, vi)
}
pub fn resize(&mut self, new_len: usize, value: T) {
for ci in 0..T::num_components() {
unsafe {
self.cont
.resize_column(ci, new_len, value.component_ptr(ci));
}
}
}
}