diff options
Diffstat (limited to 'ecs')
-rw-r--r-- | ecs/src/component.rs | 194 | ||||
-rw-r--r-- | ecs/src/component/local.rs | 6 | ||||
-rw-r--r-- | ecs/src/component/storage.rs | 54 | ||||
-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 | 42 | ||||
-rw-r--r-- | ecs/src/lock.rs | 13 | ||||
-rw-r--r-- | ecs/src/query.rs | 22 | ||||
-rw-r--r-- | ecs/src/relationship.rs | 158 | ||||
-rw-r--r-- | ecs/src/system.rs | 228 | ||||
-rw-r--r-- | ecs/src/system/stateful.rs | 7 |
11 files changed, 365 insertions, 465 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs index 265eb9e..46fbf8a 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -1,5 +1,6 @@ use std::any::{type_name, Any}; use std::fmt::Debug; +use std::ops::{Deref, DerefMut}; use seq_macro::seq; @@ -8,7 +9,14 @@ use crate::event::component::{ Kind as ComponentEventKind, Removed as ComponentRemovedEvent, }; -use crate::lock::{Error as LockError, Lock, ReadGuard, WriteGuard}; +use crate::lock::{ + Error as LockError, + Lock, + MappedReadGuard, + MappedWriteGuard, + ReadGuard, + WriteGuard, +}; use crate::system::Input as SystemInput; use crate::type_name::TypeName; use crate::uid::Uid; @@ -26,11 +34,11 @@ pub trait Component: SystemInput + Any + TypeName where Self: Sized; - type RefMut<'component>: FromOptionalMut<'component> + FromLockedOptional<'component> + type HandleMut<'component>: FromLockedOptional<'component> where Self: Sized; - type Ref<'component>: FromOptional<'component> + FromLockedOptional<'component> + type Handle<'component>: FromLockedOptional<'component> where Self: Sized; @@ -101,12 +109,12 @@ impl TypeName for Box<dyn Component> impl<ComponentT> Component for Option<ComponentT> where ComponentT: Component, - for<'a> Option<ComponentT::Ref<'a>>: FromOptional<'a> + FromLockedOptional<'a>, - for<'a> Option<ComponentT::RefMut<'a>>: FromOptionalMut<'a> + FromLockedOptional<'a>, + for<'a> Option<ComponentT::Handle<'a>>: FromLockedOptional<'a>, + for<'a> Option<ComponentT::HandleMut<'a>>: FromLockedOptional<'a>, { type Component = ComponentT; - type Ref<'component> = Option<ComponentT::Ref<'component>>; - type RefMut<'component> = Option<ComponentT::RefMut<'component>>; + type Handle<'component> = Option<ComponentT::Handle<'component>>; + type HandleMut<'component> = Option<ComponentT::HandleMut<'component>>; fn id() -> Uid { @@ -182,7 +190,7 @@ where ComponentT: Component, { type Component = ComponentT; - type Handle<'component> = ComponentT::Ref<'component>; + type Handle<'component> = ComponentT::Handle<'component>; } impl<ComponentT> Ref for &mut ComponentT @@ -190,7 +198,7 @@ where ComponentT: Component, { type Component = ComponentT; - type Handle<'component> = ComponentT::RefMut<'component>; + type Handle<'component> = ComponentT::HandleMut<'component>; } /// [`Component`] metadata. @@ -220,22 +228,6 @@ impl Metadata } } -pub trait FromOptionalMut<'comp> -{ - fn from_optional_mut_component( - optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>, - world: &'comp World, - ) -> Self; -} - -pub trait FromOptional<'comp> -{ - fn from_optional_component( - optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>, - world: &'comp World, - ) -> Self; -} - pub trait FromLockedOptional<'comp>: Sized { /// Converts a reference to a optional locked boxed component to a instance of `Self`. @@ -248,18 +240,158 @@ pub trait FromLockedOptional<'comp>: Sized ) -> Result<Self, LockError>; } +#[derive(Debug)] +pub struct Handle<'a, ComponentT: Component> +{ + inner: MappedReadGuard<'a, ComponentT>, +} + +impl<'a, ComponentT: Component> Handle<'a, ComponentT> +{ + pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self + { + Self { + inner: inner.map(|component| { + component.downcast_ref::<ComponentT>().unwrap_or_else(|| { + panic!( + "Cannot downcast component {} to type {}", + component.type_name(), + type_name::<ComponentT>() + ); + }) + }), + } + } +} + +impl<'component, ComponentT: Component> FromLockedOptional<'component> + for Handle<'component, ComponentT> +{ + fn from_locked_optional_component( + optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, + _world: &'component World, + ) -> Result<Self, LockError> + { + let component = optional_component.unwrap_or_else(|| { + panic!( + "Component {} was not found in entity", + type_name::<ComponentT>() + ); + }); + + Ok(Self::new(component.read_nonblock()?)) + } +} + +impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<Handle<'comp, ComponentT>> +where + ComponentT: Component, +{ + fn from_locked_optional_component( + optional_component: Option<&'comp Lock<Box<dyn Component>>>, + _world: &'comp World, + ) -> Result<Self, LockError> + { + optional_component + .map(|lock| Ok(Handle::new(lock.read_nonblock()?))) + .transpose() + } +} + +impl<ComponentT: Component> Deref for Handle<'_, ComponentT> +{ + type Target = ComponentT; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +#[derive(Debug)] +pub struct HandleMut<'a, ComponentT: Component> +{ + inner: MappedWriteGuard<'a, ComponentT>, +} + +impl<'a, ComponentT: Component> HandleMut<'a, ComponentT> +{ + pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self + { + Self { + inner: inner.map(|component| { + let component_type_name = component.type_name(); + + component.downcast_mut::<ComponentT>().unwrap_or_else(|| { + panic!( + "Cannot downcast component {component_type_name} to type {}", + type_name::<ComponentT>() + ); + }) + }), + } + } +} + +impl<'component, ComponentT: Component> FromLockedOptional<'component> + for HandleMut<'component, ComponentT> +{ + fn from_locked_optional_component( + optional_component: Option<&'component Lock<Box<dyn Component>>>, + _world: &'component World, + ) -> Result<Self, LockError> + { + let component = optional_component.unwrap_or_else(|| { + panic!( + "Component {} was not found in entity", + type_name::<ComponentT>() + ); + }); + + Ok(Self::new(component.write_nonblock()?)) + } +} + +impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<HandleMut<'comp, ComponentT>> +where + ComponentT: Component, +{ + fn from_locked_optional_component( + optional_component: Option<&'comp Lock<Box<dyn Component>>>, + _world: &'comp World, + ) -> Result<Self, LockError> + { + optional_component + .map(|lock| Ok(HandleMut::new(lock.write_nonblock()?))) + .transpose() + } +} + +impl<ComponentT: Component> Deref for HandleMut<'_, ComponentT> +{ + type Target = ComponentT; + + fn deref(&self) -> &Self::Target + { + &self.inner + } +} + +impl<ComponentT: Component> DerefMut for HandleMut<'_, ComponentT> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + &mut self.inner + } +} + macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { impl<#(IntoComp~I,)*> Sequence for (#(IntoComp~I,)*) where #( - for<'comp> IntoComp~I: Into< - Component: Component< - RefMut<'comp>: FromOptionalMut<'comp>, - Ref<'comp>: FromOptional<'comp> - > - >, + for<'comp> IntoComp~I: Into<Component: Component>, )* { const COUNT: usize = $c + 1; diff --git a/ecs/src/component/local.rs b/ecs/src/component/local.rs index d4e414e..0f6f641 100644 --- a/ecs/src/component/local.rs +++ b/ecs/src/component/local.rs @@ -1,14 +1,14 @@ use std::ops::{Deref, DerefMut}; -use crate::component::Component; -use crate::system::{ComponentRefMut, Param as SystemParam, System}; +use crate::component::{Component, HandleMut as ComponentHandleMut}; +use crate::system::{Param as SystemParam, System}; use crate::World; /// Holds a component which is local to a single system. #[derive(Debug)] pub struct Local<'world, LocalComponent: Component> { - local_component: ComponentRefMut<'world, LocalComponent>, + local_component: ComponentHandleMut<'world, LocalComponent>, } impl<'world, LocalComponent> SystemParam<'world> for Local<'world, LocalComponent> diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index c70e7e7..40909fb 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> @@ -195,10 +192,24 @@ impl Storage }); } - let add_edge_archetype_id = archetype_node + let add_edge_archetype_id = match archetype_node .get_or_insert_edges(component_id, ArchetypeEdges::default) .add - .unwrap_or_else(|| { + { + Some(add_edge_id) => { + if !self.graph.contains_archetype(add_edge_id) { + let (_, add_edge_comp_ids) = self + .graph + .get_node_by_id(archetype_id) + .expect("Archetype should exist") + .make_add_edge(component_id); + + self.graph.create_node(add_edge_id, &add_edge_comp_ids); + } + + add_edge_id + } + None => { let archetype_node = self .graph .get_node_by_id_mut(archetype_id) @@ -217,7 +228,8 @@ impl Storage } add_edge_id - }); + } + }; { let add_edge_archetype_node = self @@ -247,13 +259,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 +335,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 3adc415..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; @@ -20,7 +21,7 @@ use crate::phase::{Phase, START as START_PHASE}; use crate::query::flexible::Query as FlexibleQuery; use crate::query::term::Without; use crate::query::{ - ComponentIter, + Iter as QueryIter, TermWithFieldTuple as QueryTermWithFieldTuple, TermWithoutFieldTuple as QueryTermWithoutFieldTuple, Terms as QueryTerms, @@ -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) @@ -534,11 +536,6 @@ impl World fn emit_event_by_id(&self, event_id: Uid) { - //let query = self.flexible_query([ - // ComponentMetadata::of::<SystemComponent>(), - // ComponentMetadata { id: event_id, is_optional: false }, - //]); - let mut query_required_ids = [SystemComponent::id(), event_id]; let query = self.flexible_query( @@ -547,8 +544,7 @@ impl World .build(), ); - for (system,) in ComponentIter::<(&SystemComponent,), _>::new(self, query.iter()) - { + for (system,) in QueryIter::<(&SystemComponent,), _>::new(self, query.iter()) { unsafe { system.system.run(self); } @@ -603,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/lock.rs b/ecs/src/lock.rs index 1ce13fc..d6ed40e 100644 --- a/ecs/src/lock.rs +++ b/ecs/src/lock.rs @@ -1,4 +1,4 @@ -use std::mem::{forget, transmute}; +use std::mem::forget; use std::ops::{Deref, DerefMut}; use parking_lot::{ @@ -101,17 +101,6 @@ where inner: RwLockReadGuard::map(inner, func), } } - - /// Converts the `ReadGuard` to a `ReadGuard` with a possibly longer lifetime. - /// - /// # Safety - /// The returned `ReadGuard` must **NOT** be used for longer than the original - /// lifetime. - #[must_use] - pub unsafe fn upgrade_lifetime<'new>(self) -> ReadGuard<'new, Value> - { - unsafe { transmute(self) } - } } impl<Value> Deref for ReadGuard<'_, Value> diff --git a/ecs/src/query.rs b/ecs/src/query.rs index 668c573..d7d2d1c 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -36,11 +36,11 @@ where #[must_use] pub fn iter<'query>( &'query self, - ) -> ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>> + ) -> Iter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>> { tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); - ComponentIter { + Iter { world: self.world, iter: self.inner.iter(), comps_pd: PhantomData, @@ -48,7 +48,7 @@ where } /// Iterates over the entities matching this query, the iterator item being the entity - /// [`Uid`] and the entity components. + /// [`Uid`] and the matching entity components. #[must_use] pub fn iter_with_euids<'query>( &'query self, @@ -67,18 +67,18 @@ where /// `func`. /// /// This function exists so that a custom [`EntityHandle`] iterator can be given to - /// [`ComponentIter`] without giving the user access to a reference to the [`World`]. + /// [`Iter`] without giving the user access to a reference to the [`World`]. #[must_use] pub fn iter_with<'query, OutIter>( &'query self, func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter, - ) -> ComponentIter<'query, 'world, FieldTerms, OutIter> + ) -> Iter<'query, 'world, FieldTerms, OutIter> where OutIter: Iterator<Item = EntityHandle<'query>>, { tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); - ComponentIter { + Iter { world: self.world, iter: func(self.inner.iter()), comps_pd: PhantomData, @@ -113,7 +113,7 @@ where FieldTerms: TermWithFieldTuple + 'world, FieldlessTerms: TermWithoutFieldTuple, { - type IntoIter = ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>; + type IntoIter = Iter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>; type Item = FieldTerms::Fields<'query>; fn into_iter(self) -> Self::IntoIter @@ -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| { @@ -330,7 +330,7 @@ pub trait TermWithFieldTuple ) -> Self::Fields<'component>; } -pub struct ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> +pub struct Iter<'query, 'world, FieldTerms, EntityHandleIter> where FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, @@ -341,7 +341,7 @@ where } impl<'query, 'world, FieldTerms, EntityHandleIter> - ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> + Iter<'query, 'world, FieldTerms, EntityHandleIter> where FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, @@ -360,7 +360,7 @@ where } impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator - for ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> + for Iter<'query, 'world, FieldTerms, EntityHandleIter> where FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, diff --git a/ecs/src/relationship.rs b/ecs/src/relationship.rs index a0ccf4d..45fa265 100644 --- a/ecs/src/relationship.rs +++ b/ecs/src/relationship.rs @@ -7,19 +7,18 @@ use crate::component::storage::Storage as ComponentStorage; use crate::component::{ Component, FromLockedOptional as FromLockedOptionalComponent, - FromOptional as FromOptionalComponent, - FromOptionalMut as FromOptionalMutComponent, + Handle as ComponentHandle, + HandleMut as ComponentHandleMut, }; -use crate::lock::{Error as LockError, Lock, ReadGuard, WriteGuard}; -use crate::system::{ComponentRef, ComponentRefMut}; +use crate::lock::{Error as LockError, Lock, ReadGuard}; use crate::uid::{Kind as UidKind, Uid}; use crate::World; /// A relationship to one or more targets. #[derive(Debug, Component)] #[component( - ref_type = Relation<'component, Kind, ComponentT>, - ref_mut_type = RelationMut<'component, Kind, ComponentT>, + handle_type = Relation<'component, Kind, ComponentT>, + handle_mut_type = RelationMut<'component, Kind, ComponentT>, )] pub struct Relationship<Kind, ComponentT: Component> where @@ -67,27 +66,26 @@ where Kind: 'static, ComponentT: Component, { - component_storage_lock: ReadGuard<'static, ComponentStorage>, - relationship_comp: ComponentRefMut<'rel_comp, Relationship<Kind, ComponentT>>, + component_storage_lock: ReadGuard<'rel_comp, ComponentStorage>, + relationship_comp: ComponentHandleMut<'rel_comp, Relationship<Kind, ComponentT>>, } -impl<'rel_comp, Kind, ComponentT> FromOptionalMutComponent<'rel_comp> +impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> for RelationMut<'rel_comp, Kind, ComponentT> where ComponentT: Component, { - fn from_optional_mut_component( - optional_component: Option< - crate::lock::WriteGuard<'rel_comp, Box<dyn Component>>, - >, + fn from_locked_optional_component( + optional_component: Option<&'rel_comp crate::lock::Lock<Box<dyn Component>>>, world: &'rel_comp World, - ) -> Self + ) -> Result<Self, LockError> { + let relationship_comp_handle_from_locked_opt_comp = ComponentHandleMut::< + Relationship<Kind, ComponentT>, + >::from_locked_optional_component; + let relationship_comp = - ComponentRefMut::<Relationship<Kind, ComponentT>>::from_optional_mut_component( - optional_component, - world, - ); + relationship_comp_handle_from_locked_opt_comp(optional_component, world)?; let component_storage_lock = world .data @@ -95,49 +93,14 @@ where .read_nonblock() .expect("Failed to aquire read-only component storage lock"); - Self { + Ok(Self { relationship_comp, - // SAFETY: The component lock is not used for longer than the original - // lifetime - component_storage_lock: unsafe { component_storage_lock.upgrade_lifetime() }, - } - } -} - -impl<'rel_comp, Kind, ComponentT> FromOptionalMutComponent<'rel_comp> - for Option<RelationMut<'rel_comp, Kind, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_mut_component( - optional_component: Option<WriteGuard<'rel_comp, Box<dyn Component>>>, - world: &'rel_comp World, - ) -> Self - { - optional_component.map(|component| { - RelationMut::from_optional_mut_component(Some(component), world) + component_storage_lock, }) } } impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> - for RelationMut<'rel_comp, Kind, ComponentT> -where - ComponentT: Component, -{ - fn from_locked_optional_component( - optional_component: Option<&'rel_comp crate::lock::Lock<Box<dyn Component>>>, - world: &'rel_comp World, - ) -> Result<Self, LockError> - { - Ok(Self::from_optional_mut_component( - optional_component.map(Lock::write_nonblock).transpose()?, - world, - )) - } -} - -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> for Option<RelationMut<'rel_comp, Kind, ComponentT>> where ComponentT: Component, @@ -165,7 +128,7 @@ where /// Will panic if the entity does not exist in the archetype it belongs to. This /// should hopefully never happend. #[must_use] - pub fn get(&self, index: usize) -> Option<ComponentRefMut<'_, ComponentT>> + pub fn get(&self, index: usize) -> Option<ComponentHandleMut<'_, ComponentT>> { let target = self.get_target(index)?; @@ -177,11 +140,11 @@ where let component_index = archetype.get_index_for_component(ComponentT::id())?; - let component = ComponentRefMut::new( + let component = ComponentHandleMut::new( entity - .components + .components() .get(component_index)? - .component + .component() .write_nonblock() .unwrap_or_else(|_| { panic!( @@ -276,7 +239,7 @@ where ComponentT: Component, { type IntoIter = TargetComponentIterMut<'relationship, 'rel_comp, Kind, ComponentT>; - type Item = ComponentRefMut<'rel_comp, ComponentT>; + type Item = ComponentHandleMut<'rel_comp, ComponentT>; fn into_iter(self) -> Self::IntoIter { @@ -301,7 +264,7 @@ where Kind: 'static, ComponentT: Component, { - type Item = ComponentRefMut<'rel_comp, ComponentT>; + type Item = ComponentHandleMut<'rel_comp, ComponentT>; fn next(&mut self) -> Option<Self::Item> { @@ -325,25 +288,26 @@ where Kind: 'static, ComponentT: Component, { - component_storage_lock: ReadGuard<'static, ComponentStorage>, - relationship_comp: ComponentRef<'rel_comp, Relationship<Kind, ComponentT>>, + component_storage_lock: ReadGuard<'rel_comp, ComponentStorage>, + relationship_comp: ComponentHandle<'rel_comp, Relationship<Kind, ComponentT>>, } -impl<'rel_comp, Kind, ComponentT> FromOptionalComponent<'rel_comp> +impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> for Relation<'rel_comp, Kind, ComponentT> where ComponentT: Component, { - fn from_optional_component( - optional_component: Option<ReadGuard<'rel_comp, Box<dyn Component>>>, + fn from_locked_optional_component( + optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>, world: &'rel_comp World, - ) -> Self + ) -> Result<Self, LockError> { + let relationship_comp_handle_from_locked_opt_comp = ComponentHandle::< + Relationship<Kind, ComponentT>, + >::from_locked_optional_component; + let relationship_comp = - ComponentRef::<Relationship<Kind, ComponentT>>::from_optional_component( - optional_component, - world, - ); + relationship_comp_handle_from_locked_opt_comp(optional_component, world)?; let component_storage_lock = world .data @@ -351,44 +315,10 @@ where .read_nonblock() .expect("Failed to aquire read-only component storage lock"); - Self { + Ok(Self { relationship_comp, - // SAFETY: The component lock is not used for longer than the original - // lifetime - component_storage_lock: unsafe { component_storage_lock.upgrade_lifetime() }, - } - } -} - -impl<'rel_comp, Kind, ComponentT> FromOptionalComponent<'rel_comp> - for Option<Relation<'rel_comp, Kind, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_component( - optional_component: Option<ReadGuard<'rel_comp, Box<dyn Component>>>, - world: &'rel_comp World, - ) -> Self - { - optional_component - .map(|component| Relation::from_optional_component(Some(component), world)) - } -} - -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> - for Relation<'rel_comp, Kind, ComponentT> -where - ComponentT: Component, -{ - fn from_locked_optional_component( - optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>, - world: &'rel_comp World, - ) -> Result<Self, LockError> - { - Ok(Self::from_optional_component( - optional_component.map(Lock::read_nonblock).transpose()?, - world, - )) + component_storage_lock, + }) } } @@ -420,7 +350,7 @@ where /// Will panic if the entity does not exist in the archetype it belongs to. This /// should hopefully never happend. #[must_use] - pub fn get(&self, index: usize) -> Option<ComponentRef<'_, ComponentT>> + pub fn get(&self, index: usize) -> Option<ComponentHandle<'_, ComponentT>> { let target = self.get_target(index)?; @@ -432,11 +362,11 @@ where let component_index = archetype.get_index_for_component(ComponentT::id())?; - let component = ComponentRef::new( + let component = ComponentHandle::new( entity - .components + .components() .get(component_index)? - .component + .component() .read_nonblock() .unwrap_or_else(|_| { panic!( @@ -490,7 +420,7 @@ where ComponentT: Component, { type IntoIter = TargetComponentIter<'relationship, 'rel_comp, Kind, ComponentT>; - type Item = ComponentRef<'rel_comp, ComponentT>; + type Item = ComponentHandle<'rel_comp, ComponentT>; fn into_iter(self) -> Self::IntoIter { @@ -515,7 +445,7 @@ where Kind: 'static, ComponentT: Component, { - type Item = ComponentRef<'rel_comp, ComponentT>; + type Item = ComponentHandle<'rel_comp, ComponentT>; fn next(&mut self) -> Option<Self::Item> { diff --git a/ecs/src/system.rs b/ecs/src/system.rs index 40eba8d..603c015 100644 --- a/ecs/src/system.rs +++ b/ecs/src/system.rs @@ -1,26 +1,11 @@ -use std::any::{type_name, Any}; +use std::any::Any; use std::convert::Infallible; use std::fmt::Debug; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; use ecs_macros::Component; use seq_macro::seq; -use crate::component::{ - Component, - FromLockedOptional as FromLockedOptionalComponent, - FromOptional as FromOptionalComponent, - FromOptionalMut as FromOptionalMutComponent, -}; -use crate::lock::{ - Error as LockError, - Lock, - MappedReadGuard, - MappedWriteGuard, - ReadGuard, - WriteGuard, -}; +use crate::component::{Component, HandleMut as ComponentHandleMut}; use crate::tuple::{ReduceElement as TupleReduceElement, Tuple}; use crate::World; @@ -41,7 +26,7 @@ pub trait System<'world, Impl>: 'static fn get_local_component_mut<LocalComponent: Component>( &self, - ) -> Option<ComponentRefMut<LocalComponent>>; + ) -> Option<ComponentHandleMut<LocalComponent>>; fn set_local_component<LocalComponent: Component>( &mut self, @@ -100,7 +85,7 @@ macro_rules! impl_system { fn get_local_component_mut<LocalComponent: Component>( &self, - ) -> Option<ComponentRefMut<LocalComponent>> + ) -> Option<ComponentHandleMut<LocalComponent>> { panic!("System does not have any local components"); } @@ -194,211 +179,6 @@ impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for () type Return = Accumulator; } -#[derive(Debug)] -pub struct ComponentRefMut<'a, ComponentT: Component> -{ - inner: MappedWriteGuard<'a, ComponentT>, - _ph: PhantomData<ComponentT>, -} - -impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT> -{ - pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self - { - Self { - inner: inner.map(|component| { - let component_type_name = component.type_name(); - - component.downcast_mut::<ComponentT>().unwrap_or_else(|| { - panic!( - "Cannot downcast component {component_type_name} to type {}", - type_name::<ComponentT>() - ); - }) - }), - _ph: PhantomData, - } - } -} - -impl<'component, ComponentT: Component> FromOptionalMutComponent<'component> - for ComponentRefMut<'component, ComponentT> -{ - fn from_optional_mut_component( - inner: Option<WriteGuard<'component, Box<dyn Component>>>, - _world: &'component World, - ) -> Self - { - Self::new(inner.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - })) - } -} - -impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component> - for ComponentRefMut<'component, ComponentT> -{ - fn from_locked_optional_component( - optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, - world: &'component World, - ) -> Result<Self, LockError> - { - Ok(Self::from_optional_mut_component( - optional_component.map(Lock::write_nonblock).transpose()?, - world, - )) - } -} - -impl<'comp, ComponentT> FromOptionalMutComponent<'comp> - for Option<ComponentRefMut<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_mut_component( - optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>, - _world: &'comp World, - ) -> Self - { - optional_component.map(|component| ComponentRefMut::new(component)) - } -} - -impl<'comp, ComponentT> FromLockedOptionalComponent<'comp> - for Option<ComponentRefMut<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, - _world: &'comp World, - ) -> Result<Self, LockError> - { - optional_component - .map(|lock| Ok(ComponentRefMut::new(lock.write_nonblock()?))) - .transpose() - } -} - -impl<ComponentT: Component> Deref for ComponentRefMut<'_, ComponentT> -{ - type Target = ComponentT; - - fn deref(&self) -> &Self::Target - { - &self.inner - } -} - -impl<ComponentT: Component> DerefMut for ComponentRefMut<'_, ComponentT> -{ - fn deref_mut(&mut self) -> &mut Self::Target - { - &mut self.inner - } -} - -#[derive(Debug)] -pub struct ComponentRef<'a, ComponentT: Component> -{ - inner: MappedReadGuard<'a, ComponentT>, - _ph: PhantomData<ComponentT>, -} - -impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT> -{ - pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self - { - Self { - inner: inner.map(|component| { - component.downcast_ref::<ComponentT>().unwrap_or_else(|| { - panic!( - "Cannot downcast component {} to type {}", - component.type_name(), - type_name::<ComponentT>() - ); - }) - }), - _ph: PhantomData, - } - } -} - -impl<'component, ComponentT: Component> FromOptionalComponent<'component> - for ComponentRef<'component, ComponentT> -{ - fn from_optional_component( - inner: Option<ReadGuard<'component, Box<dyn Component>>>, - _world: &'component World, - ) -> Self - { - Self::new(inner.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - })) - } -} - -impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component> - for ComponentRef<'component, ComponentT> -{ - fn from_locked_optional_component( - optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, - world: &'component World, - ) -> Result<Self, LockError> - { - Ok(Self::from_optional_component( - optional_component.map(Lock::read_nonblock).transpose()?, - world, - )) - } -} - -impl<'comp, ComponentT> FromOptionalComponent<'comp> - for Option<ComponentRef<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_component( - optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>, - _world: &'comp World, - ) -> Self - { - optional_component.map(|component| ComponentRef::new(component)) - } -} - -impl<'comp, ComponentT> FromLockedOptionalComponent<'comp> - for Option<ComponentRef<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, - _world: &'comp World, - ) -> Result<Self, LockError> - { - optional_component - .map(|lock| Ok(ComponentRef::new(lock.read_nonblock()?))) - .transpose() - } -} - -impl<ComponentT: Component> Deref for ComponentRef<'_, ComponentT> -{ - type Target = ComponentT; - - fn deref(&self) -> &Self::Target - { - &self.inner - } -} - #[derive(Debug, Component)] pub(crate) struct SystemComponent { diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index 80ac346..9d911ee 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -4,10 +4,9 @@ use std::panic::{RefUnwindSafe, UnwindSafe}; use hashbrown::HashMap; use seq_macro::seq; -use crate::component::Component; +use crate::component::{Component, HandleMut as ComponentHandleMut}; use crate::lock::Lock; use crate::system::{ - ComponentRefMut, Into as IntoSystem, Param, ParamWithInputFilter, @@ -110,14 +109,14 @@ macro_rules! impl_system { fn get_local_component_mut<LocalComponent: Component>( &self, - ) -> Option<ComponentRefMut<LocalComponent>> + ) -> Option<ComponentHandleMut<LocalComponent>> { let local_component = self.local_components .get(&LocalComponent::id())? .write_nonblock() .expect("Failed to aquire read-write local component lock"); - Some(ComponentRefMut::new(local_component)) + Some(ComponentHandleMut::new(local_component)) } fn set_local_component<LocalComponent: Component>( |