diff options
Diffstat (limited to 'ecs')
-rw-r--r-- | ecs/src/component/storage.rs | 33 | ||||
-rw-r--r-- | ecs/src/component/storage/archetype.rs | 94 | ||||
-rw-r--r-- | ecs/src/entity.rs | 12 | ||||
-rw-r--r-- | ecs/src/lib.rs | 32 | ||||
-rw-r--r-- | ecs/src/query.rs | 2 | ||||
-rw-r--r-- | ecs/src/relationship.rs | 8 |
6 files changed, 121 insertions, 60 deletions
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index c70e7e7..4a00510 100644 --- a/ecs/src/component/storage.rs +++ b/ecs/src/component/storage.rs @@ -7,7 +7,8 @@ use hashbrown::HashMap; use crate::component::storage::archetype::{ Archetype, - ArchetypeEntity, + Entity as ArchetypeEntity, + EntityComponent as ArchetypeEntityComponent, Id as ArchetypeId, }; use crate::component::storage::graph::{ @@ -20,7 +21,6 @@ use crate::component::Component; use crate::type_name::TypeName; use crate::uid::{Kind as UidKind, Uid}; use crate::util::{BorrowedOrOwned, Either, StreamingIterator, VecExt}; -use crate::EntityComponent; pub mod archetype; @@ -123,17 +123,14 @@ impl Storage archetype_node .archetype_mut() - .push_entity(ArchetypeEntity { uid, components: vec![] }); + .push_entity(ArchetypeEntity::new(uid, [])); self.entity_archetype_lookup.insert(uid, empty_archetype_id); Ok(()) } - pub fn remove_entity( - &mut self, - entity_uid: Uid, - ) -> Result<Vec<EntityComponent>, Error> + pub fn remove_entity(&mut self, entity_uid: Uid) -> Result<ArchetypeEntity, Error> { let Some(archetype_id) = self.entity_archetype_lookup.get(&entity_uid) else { return Err(Error::EntityDoesNotExist(entity_uid)); @@ -151,7 +148,7 @@ impl Storage self.entity_archetype_lookup.remove(&entity_uid); - Ok(entity.components) + Ok(entity) } pub fn get_entity_archetype(&self, entity_uid: Uid) -> Option<&Archetype> @@ -247,13 +244,10 @@ impl Storage .expect("Add edge archetype should exist") .archetype_mut(); - let component_index = add_edge_archetype - .get_index_for_component(component_id) - .expect("Archetype should have index for component"); - - entity.components.insert( - component_index, - EntityComponent::new(component_id, component), + entity.insert_component( + component_id, + ArchetypeEntityComponent::new(component), + add_edge_archetype, ); add_edge_archetype.push_entity(entity); @@ -326,14 +320,7 @@ impl Storage .remove_entity(entity_uid) .expect("Entity should exist in archetype"); - let (comp_to_remove_index, _) = entity - .components - .iter() - .enumerate() - .find(|(_, comp)| comp.id == component_id) - .expect("Entity should contain component"); - - entity.components.remove(comp_to_remove_index); + entity.remove_component(component_id, archetype_node.archetype()); self.graph .get_node_by_id_mut(remove_edge_id) diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs index f6f8132..5306cf9 100644 --- a/ecs/src/component/storage/archetype.rs +++ b/ecs/src/component/storage/archetype.rs @@ -3,16 +3,16 @@ use std::slice::Iter as SliceIter; use hashbrown::HashMap; -use crate::component::Metadata as ComponentMetadata; +use crate::component::{Component, Metadata as ComponentMetadata}; +use crate::lock::Lock; use crate::uid::{Kind as UidKind, Uid}; use crate::util::HashMapExt; -use crate::EntityComponent; #[derive(Debug)] pub struct Archetype { id: Id, - entities: Vec<ArchetypeEntity>, + entities: Vec<Entity>, entity_index_lookup: HashMap<Uid, usize>, component_index_lookup: HashMap<Uid, usize>, component_ids: Vec<Uid>, @@ -53,7 +53,7 @@ impl Archetype .keys_is_subset(&other.component_index_lookup) } - pub fn get_entity_by_id(&self, entity_uid: Uid) -> Option<&ArchetypeEntity> + pub fn get_entity_by_id(&self, entity_uid: Uid) -> Option<&Entity> { let index = *self.entity_index_lookup.get(&entity_uid)?; @@ -64,7 +64,7 @@ impl Archetype })) } - pub fn push_entity(&mut self, entity: ArchetypeEntity) + pub fn push_entity(&mut self, entity: Entity) { self.entity_index_lookup .insert(entity.uid, self.entities.len()); @@ -72,7 +72,7 @@ impl Archetype self.entities.push(entity); } - pub fn remove_entity(&mut self, entity_uid: Uid) -> Option<ArchetypeEntity> + pub fn remove_entity(&mut self, entity_uid: Uid) -> Option<Entity> { //debug_assert_eq!(entity_uid.kind(), UidKind::Entity); @@ -142,12 +142,12 @@ impl Archetype #[derive(Debug)] pub struct EntityIter<'archetype> { - iter: SliceIter<'archetype, ArchetypeEntity>, + iter: SliceIter<'archetype, Entity>, } impl<'archetype> Iterator for EntityIter<'archetype> { - type Item = &'archetype ArchetypeEntity; + type Item = &'archetype Entity; fn next(&mut self) -> Option<Self::Item> { @@ -156,10 +156,82 @@ impl<'archetype> Iterator for EntityIter<'archetype> } #[derive(Debug)] -pub struct ArchetypeEntity +pub struct Entity { - pub uid: Uid, - pub components: Vec<EntityComponent>, + uid: Uid, + components: Vec<EntityComponent>, +} + +impl Entity +{ + pub fn new(uid: Uid, components: impl IntoIterator<Item = EntityComponent>) -> Self + { + Self { + uid, + components: components.into_iter().collect(), + } + } + + pub fn uid(&self) -> Uid + { + self.uid + } + + pub fn components(&self) -> &[EntityComponent] + { + &self.components + } + + pub fn remove_component(&mut self, component_id: Uid, archetype: &Archetype) + { + let index = archetype + .get_index_for_component(component_id) + .expect("Archetype should contain component"); + + self.components.remove(index); + } + + pub fn insert_component( + &mut self, + component_id: Uid, + component: EntityComponent, + archetype: &Archetype, + ) + { + let index = archetype + .get_index_for_component(component_id) + .expect("Archetype should contain component"); + + self.components.insert(index, component); + } +} + +#[derive(Debug)] +pub struct EntityComponent +{ + name: &'static str, + component: Lock<Box<dyn Component>>, +} + +impl EntityComponent +{ + pub fn new(component: Box<dyn Component>) -> Self + { + Self { + name: component.type_name(), + component: Lock::new(component), + } + } + + pub fn name(&self) -> &str + { + self.name + } + + pub fn component(&self) -> &Lock<Box<dyn Component>> + { + &self.component + } } /// Archetype ID. diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs index 85e7461..a43f9ce 100644 --- a/ecs/src/entity.rs +++ b/ecs/src/entity.rs @@ -1,8 +1,8 @@ use linkme::distributed_slice; -use crate::component::storage::archetype::{Archetype, ArchetypeEntity}; +use crate::component::storage::archetype::{Archetype, Entity as ArchetypeEntity}; use crate::uid::Uid; -use crate::{EntityComponent, World}; +use crate::{EntityComponentRef, World}; /// A handle to a entity. pub struct Handle<'a> @@ -18,16 +18,18 @@ impl<'a> Handle<'a> #[must_use] pub fn uid(&self) -> Uid { - self.entity.uid + self.entity.uid() } #[inline] #[must_use] - pub fn get_component(&self, component_uid: Uid) -> Option<&'a EntityComponent> + pub fn get_component(&self, component_uid: Uid) -> Option<EntityComponentRef<'a>> { let index = self.archetype.get_index_for_component(component_uid)?; - Some(self.entity.components.get(index).unwrap()) + Some(EntityComponentRef::new( + self.entity.components().get(index).unwrap(), + )) } pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 59129b0..3caaa6b 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use hashbrown::HashMap; use crate::actions::Action; +use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComponent; use crate::component::storage::Storage as ComponentStorage; use crate::component::{Component, Sequence as ComponentSequence}; use crate::entity::CREATE_STATIC_ENTITIES; @@ -467,7 +468,7 @@ impl World { let mut component_storage_lock = self.lock_component_storage_rw(); - let components = match component_storage_lock.remove_entity(entity_uid) { + let removed_entity = match component_storage_lock.remove_entity(entity_uid) { Ok(components) => components, Err(err) => { tracing::error!("Failed to despawn entity: {err}"); @@ -475,16 +476,17 @@ impl World } }; - let component_removed_event_uids = components + let component_removed_event_uids = removed_entity + .components() .iter() .map(|component| { component - .component + .component() .read_nonblock() .unwrap_or_else(|_| { panic!( "Failed to acquire read-only {} component lock", - component.name + component.name() ) }) .get_event_uid(ComponentEventKind::Removed) @@ -597,23 +599,21 @@ pub struct WorldData } #[derive(Debug)] -#[non_exhaustive] -pub struct EntityComponent +pub struct EntityComponentRef<'a> { - pub id: Uid, - pub name: &'static str, - pub component: Lock<Box<dyn Component>>, + comp: &'a ArchetypeEntityComponent, } -impl EntityComponent +impl<'a> EntityComponentRef<'a> { - pub fn new(id: Uid, component: Box<dyn Component>) -> Self + pub fn component(&self) -> &'a Lock<Box<dyn Component>> { - Self { - id, - name: component.type_name(), - component: Lock::new(component), - } + self.comp.component() + } + + fn new(comp: &'a ArchetypeEntityComponent) -> Self + { + Self { comp } } } diff --git a/ecs/src/query.rs b/ecs/src/query.rs index 9b8aeed..d7d2d1c 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -301,7 +301,7 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT Self::Field::from_locked_optional_component( entity_handle .get_component(ComponentRefT::Component::id()) - .map(|component| &component.component), + .map(|component| component.component()), world, ) .unwrap_or_else(|err| { diff --git a/ecs/src/relationship.rs b/ecs/src/relationship.rs index a0ccf4d..e5442c2 100644 --- a/ecs/src/relationship.rs +++ b/ecs/src/relationship.rs @@ -179,9 +179,9 @@ where let component = ComponentRefMut::new( entity - .components + .components() .get(component_index)? - .component + .component() .write_nonblock() .unwrap_or_else(|_| { panic!( @@ -434,9 +434,9 @@ where let component = ComponentRef::new( entity - .components + .components() .get(component_index)? - .component + .component() .read_nonblock() .unwrap_or_else(|_| { panic!( |