diff options
-rw-r--r-- | ecs-macros/src/lib.rs | 34 | ||||
-rw-r--r-- | ecs/examples/optional_component.rs | 2 | ||||
-rw-r--r-- | ecs/src/component.rs | 243 | ||||
-rw-r--r-- | ecs/src/component/storage.rs | 68 | ||||
-rw-r--r-- | ecs/src/component/storage/archetype.rs | 22 | ||||
-rw-r--r-- | ecs/src/component/storage/graph.rs | 17 | ||||
-rw-r--r-- | ecs/src/lib.rs | 100 | ||||
-rw-r--r-- | ecs/src/lock.rs | 95 | ||||
-rw-r--r-- | ecs/src/query.rs | 143 | ||||
-rw-r--r-- | ecs/src/query/flexible.rs | 8 | ||||
-rw-r--r-- | ecs/src/query/term.rs | 50 | ||||
-rw-r--r-- | ecs/src/relationship.rs | 76 | ||||
-rw-r--r-- | ecs/src/sole.rs | 11 | ||||
-rw-r--r-- | ecs/src/system/stateful.rs | 9 | ||||
-rw-r--r-- | ecs/src/type_name.rs | 15 | ||||
-rw-r--r-- | ecs/src/util.rs | 2 | ||||
-rw-r--r-- | ecs/src/util/array_vec.rs | 115 | ||||
-rw-r--r-- | ecs/tests/query.rs | 4 | ||||
-rw-r--r-- | engine/src/renderer/opengl.rs | 10 |
19 files changed, 475 insertions, 549 deletions
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs index 5af10b9..a5acc2b 100644 --- a/ecs-macros/src/lib.rs +++ b/ecs-macros/src/lib.rs @@ -120,7 +120,6 @@ pub fn component_derive(input: TokenStream) -> TokenStream }; use #ecs_path::uid::{Uid, Kind as UidKind}; use #ecs_path::system::Input as SystemInput; - use #ecs_path::type_name::TypeName; use super::*; @@ -139,6 +138,11 @@ pub fn component_derive(input: TokenStream) -> TokenStream #get_id } + fn name(&self) -> &'static str + { + std::any::type_name::<Self>() + } + fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid { match event_kind { @@ -150,31 +154,12 @@ pub fn component_derive(input: TokenStream) -> TokenStream } } } - - fn as_any_mut(&mut self) -> &mut dyn Any - { - self - } - - fn as_any(&self) -> &dyn Any - { - self - } } impl #impl_generics SystemInput for #item_ident #type_generics #where_clause { } - - impl #impl_generics TypeName for #item_ident #type_generics - #where_clause - { - fn type_name(&self) -> &'static str - { - std::any::type_name::<Self>() - } - } } } .into() @@ -214,15 +199,6 @@ pub fn sole_derive(input: TokenStream) -> TokenStream self } } - - impl #impl_generics #ecs_path::type_name::TypeName for #item_ident #type_generics - #where_clause - { - fn type_name(&self) -> &'static str - { - std::any::type_name::<Self>() - } - } } .into() } diff --git a/ecs/examples/optional_component.rs b/ecs/examples/optional_component.rs index 488dad2..ebc9115 100644 --- a/ecs/examples/optional_component.rs +++ b/ecs/examples/optional_component.rs @@ -21,7 +21,7 @@ pub struct CatName name: String, } -fn pet_cats(query: Query<(&CatName, &mut PettingCapacity, &Option<Aggressivity>)>) +fn pet_cats(query: Query<(&CatName, &mut PettingCapacity, Option<&Aggressivity>)>) { for (cat_name, mut petting_capacity, aggressivity) in &query { let Some(aggressivity) = aggressivity else { diff --git a/ecs/src/component.rs b/ecs/src/component.rs index 46fbf8a..49265b3 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -1,4 +1,5 @@ use std::any::{type_name, Any}; +use std::error::Error; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; @@ -11,34 +12,32 @@ use crate::event::component::{ }; 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; use crate::util::Array; -use crate::World; +use crate::{EntityComponentRef, World}; pub mod local; pub(crate) mod storage; -pub trait Component: SystemInput + Any + TypeName +pub trait Component: SystemInput + Any { /// The component type in question. Will usually be `Self` type Component: Component where Self: Sized; - type HandleMut<'component>: FromLockedOptional<'component> + type HandleMut<'component>: HandleFromEntityComponentRef<'component> where Self: Sized; - type Handle<'component>: FromLockedOptional<'component> + type Handle<'component>: HandleFromEntityComponentRef<'component> where Self: Sized; @@ -47,46 +46,28 @@ pub trait Component: SystemInput + Any + TypeName where Self: Sized; + /// Returns the name of this component. + fn name(&self) -> &'static str; + /// Returns the component UID of a component event for this component. fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid; - - #[doc(hidden)] - fn as_any_mut(&mut self) -> &mut dyn Any; - - #[doc(hidden)] - fn as_any(&self) -> &dyn Any; - - /// Returns whether the component `self` is optional. - fn self_is_optional(&self) -> bool - { - false - } - - /// Returns whether this component is optional. - #[must_use] - fn is_optional() -> bool - where - Self: Sized, - { - false - } } impl dyn Component { pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real> { - self.as_any_mut().downcast_mut() + (self as &mut dyn Any).downcast_mut() } pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real> { - self.as_any().downcast_ref() + (self as &dyn Any).downcast_ref() } pub fn is<Other: 'static>(&self) -> bool { - self.as_any().is::<Other>() + (self as &dyn Any).is::<Other>() } } @@ -98,69 +79,6 @@ impl Debug for dyn Component } } -impl TypeName for Box<dyn Component> -{ - fn type_name(&self) -> &'static str - { - self.as_ref().type_name() - } -} - -impl<ComponentT> Component for Option<ComponentT> -where - ComponentT: Component, - for<'a> Option<ComponentT::Handle<'a>>: FromLockedOptional<'a>, - for<'a> Option<ComponentT::HandleMut<'a>>: FromLockedOptional<'a>, -{ - type Component = ComponentT; - type Handle<'component> = Option<ComponentT::Handle<'component>>; - type HandleMut<'component> = Option<ComponentT::HandleMut<'component>>; - - fn id() -> Uid - { - ComponentT::id() - } - - fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid - { - match event_kind { - ComponentEventKind::Removed => ComponentRemovedEvent::<Self>::id(), - } - } - - fn as_any_mut(&mut self) -> &mut dyn Any - { - self - } - - fn as_any(&self) -> &dyn Any - { - self - } - - fn self_is_optional(&self) -> bool - { - true - } - - fn is_optional() -> bool - { - true - } -} - -impl<ComponentT> TypeName for Option<ComponentT> -where - ComponentT: Component, -{ - fn type_name(&self) -> &'static str - { - type_name::<Self>() - } -} - -impl<ComponentT> SystemInput for Option<ComponentT> where ComponentT: Component {} - /// A sequence of components. pub trait Sequence { @@ -182,7 +100,7 @@ pub trait Sequence pub trait Ref { type Component: Component; - type Handle<'component>: FromLockedOptional<'component>; + type Handle<'component>: HandleFromEntityComponentRef<'component>; } impl<ComponentT> Ref for &ComponentT @@ -207,37 +125,26 @@ where pub struct Metadata { pub id: Uid, - pub is_optional: bool, } impl Metadata { #[must_use] - pub fn new_non_optional(id: Uid) -> Self - { - Self { id, is_optional: false } - } - - #[must_use] pub fn of<ComponentT: Component>() -> Self { - Self { - id: ComponentT::id(), - is_optional: ComponentT::is_optional(), - } + Self { id: ComponentT::id() } } } -pub trait FromLockedOptional<'comp>: Sized +pub trait HandleFromEntityComponentRef<'comp>: Sized { - /// Converts a reference to a optional locked boxed component to a instance of `Self`. - /// - /// # Errors - /// Returns `Err` if taking the lock (in a non-blocking way) fails. - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, + type Error: Error; + + /// Creates a new handle instance from a [`EntityComponentRef`]. + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, world: &'comp World, - ) -> Result<Self, LockError>; + ) -> Result<Self, Self::Error>; } #[derive(Debug)] @@ -248,14 +155,13 @@ pub struct Handle<'a, ComponentT: Component> impl<'a, ComponentT: Component> Handle<'a, ComponentT> { - pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self + pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Any>>) -> Self { Self { inner: inner.map(|component| { component.downcast_ref::<ComponentT>().unwrap_or_else(|| { panic!( - "Cannot downcast component {} to type {}", - component.type_name(), + "Failed to downcast component to type {}", type_name::<ComponentT>() ); }) @@ -264,37 +170,25 @@ impl<'a, ComponentT: Component> Handle<'a, ComponentT> } } -impl<'component, ComponentT: Component> FromLockedOptional<'component> - for Handle<'component, ComponentT> +impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp> + for Handle<'comp, 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>() - ); - }); + type Error = HandleError; - 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>>>, + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, _world: &'comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - optional_component - .map(|lock| Ok(Handle::new(lock.read_nonblock()?))) - .transpose() + let entity_comp = + entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; + + Ok(Self::new( + entity_comp + .component() + .read_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) } } @@ -316,15 +210,13 @@ pub struct HandleMut<'a, ComponentT: Component> impl<'a, ComponentT: Component> HandleMut<'a, ComponentT> { - pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self + pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Any>>) -> 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 {}", + "Failed to downcast component to type {}", type_name::<ComponentT>() ); }) @@ -333,37 +225,25 @@ impl<'a, ComponentT: Component> HandleMut<'a, ComponentT> } } -impl<'component, ComponentT: Component> FromLockedOptional<'component> - for HandleMut<'component, ComponentT> +impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp> + for HandleMut<'comp, 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>() - ); - }); + type Error = HandleError; - 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>>>, + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, _world: &'comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - optional_component - .map(|lock| Ok(HandleMut::new(lock.write_nonblock()?))) - .transpose() + let entity_comp = + entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; + + Ok(Self::new( + entity_comp + .component() + .write_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) } } @@ -385,6 +265,20 @@ impl<ComponentT: Component> DerefMut for HandleMut<'_, ComponentT> } } +#[derive(Debug, thiserror::Error)] +pub enum HandleError +{ + #[error(transparent)] + AcquireComponentLockFailed(#[from] AcquireComponentLockFailed), + + #[error("Component does not exist")] + ComponentDoesNotExist, +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct AcquireComponentLockFailed(LockError); + macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { @@ -413,7 +307,6 @@ macro_rules! inner { #( Metadata { id: IntoComp~I::Component::id(), - is_optional: IntoComp~I::Component::is_optional(), }, )* ] diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index 4a00510..53f51f2 100644 --- a/ecs/src/component/storage.rs +++ b/ecs/src/component/storage.rs @@ -1,4 +1,4 @@ -use std::any::type_name; +use std::any::Any; use std::array::IntoIter as ArrayIter; use std::cell::RefCell; use std::vec::IntoIter as VecIntoIter; @@ -17,8 +17,6 @@ use crate::component::storage::graph::{ ArchetypeEdges, Graph, }; -use crate::component::Component; -use crate::type_name::TypeName; use crate::uid::{Kind as UidKind, Uid}; use crate::util::{BorrowedOrOwned, Either, StreamingIterator, VecExt}; @@ -161,16 +159,9 @@ impl Storage pub fn add_entity_component( &mut self, entity_uid: Uid, - component: (Uid, Box<dyn Component>), + (component_id, component_name, component): (Uid, &'static str, Box<dyn Any>), ) -> Result<(), Error> { - let (component_id, component) = component; - - debug_assert!( - !component.self_is_optional(), - "Adding a optional component to a entity is not supported" - ); - let Some(archetype_id) = self.entity_archetype_lookup.get(&entity_uid) else { return Err(Error::EntityDoesNotExist(entity_uid)); }; @@ -192,41 +183,39 @@ 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) + .get_node_by_id(archetype_id) .expect("Archetype should exist"); let (add_edge_id, add_edge_comp_ids) = archetype_node.make_add_edge(component_id); - archetype_node - .get_edges_mut(component_id) - .expect("Edges for component in archetype should exist") - .add = Some(add_edge_id); - if !self.graph.contains_archetype(add_edge_id) { self.graph.create_node(add_edge_id, &add_edge_comp_ids); } add_edge_id - }); - - { - let add_edge_archetype_node = self - .graph - .get_node_by_id_mut(add_edge_archetype_id) - .expect("Add edge archetype should exist"); - - let add_edge_archetype_edges = add_edge_archetype_node - .get_or_insert_edges(component_id, ArchetypeEdges::default); - - add_edge_archetype_edges.remove = Some(archetype_id); - } + } + }; let archetype_node = self .graph @@ -246,7 +235,7 @@ impl Storage entity.insert_component( component_id, - ArchetypeEntityComponent::new(component), + ArchetypeEntityComponent::new(component, component_name), add_edge_archetype, ); @@ -297,11 +286,6 @@ impl Storage let (remove_edge_id, remove_edge_comp_ids) = archetype_node.make_remove_edge(component_id); - archetype_node - .get_edges_mut(component_id) - .expect("Edges for component in archetype should exist") - .remove = Some(remove_edge_id); - if !self.graph.contains_archetype(remove_edge_id) { self.graph .create_node(remove_edge_id, &remove_edge_comp_ids); @@ -400,14 +384,6 @@ impl Storage } } -impl TypeName for Storage -{ - fn type_name(&self) -> &'static str - { - type_name::<Self>() - } -} - #[cfg(feature = "vizoxide")] impl Storage { diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs index 5306cf9..b8ac826 100644 --- a/ecs/src/component/storage/archetype.rs +++ b/ecs/src/component/storage/archetype.rs @@ -1,9 +1,10 @@ +use std::any::Any; use std::hash::{DefaultHasher, Hash, Hasher}; use std::slice::Iter as SliceIter; use hashbrown::HashMap; -use crate::component::{Component, Metadata as ComponentMetadata}; +use crate::component::Metadata as ComponentMetadata; use crate::lock::Lock; use crate::uid::{Kind as UidKind, Uid}; use crate::util::HashMapExt; @@ -209,26 +210,19 @@ impl Entity #[derive(Debug)] pub struct EntityComponent { - name: &'static str, - component: Lock<Box<dyn Component>>, + component: Lock<Box<dyn Any>>, } impl EntityComponent { - pub fn new(component: Box<dyn Component>) -> Self + pub fn new(component: Box<dyn Any>, component_name: &'static str) -> Self { Self { - name: component.type_name(), - component: Lock::new(component), + component: Lock::new(component, component_name), } } - pub fn name(&self) -> &str - { - self.name - } - - pub fn component(&self) -> &Lock<Box<dyn Component>> + pub fn component(&self) -> &Lock<Box<dyn Any>> { &self.component } @@ -288,10 +282,6 @@ impl Id prev_component_id = Some(comp_metadata.id); - if comp_metadata.is_optional { - continue; - } - comp_metadata.id.hash(&mut hasher); } diff --git a/ecs/src/component/storage/graph.rs b/ecs/src/component/storage/graph.rs index 11160e7..d38223a 100644 --- a/ecs/src/component/storage/graph.rs +++ b/ecs/src/component/storage/graph.rs @@ -140,7 +140,7 @@ impl Graph } fn create_missing_subset_node_edges( - target_node: &ArchetypeNode, + target_node: &mut ArchetypeNode, subset_node: &mut ArchetypeNode, ) { @@ -153,6 +153,14 @@ impl Graph subset_node .get_or_insert_edges(uniq_comp_id, ArchetypeEdges::default) .add = Some(subset_node.make_add_edge(uniq_comp_id).0); + + if target_node.archetype().component_cnt() + == subset_node.archetype().component_cnt() + 1 + { + target_node + .get_or_insert_edges(uniq_comp_id, ArchetypeEdges::default) + .remove = Some(subset_node.archetype().id()); + } } fn create_missing_superset_node_edges( @@ -245,13 +253,6 @@ impl ArchetypeNode self.edges.iter() } - pub fn get_edges_mut(&mut self, component_id: Uid) -> Option<&mut ArchetypeEdges> - { - debug_assert_eq!(component_id.kind(), UidKind::Component); - - self.edges.get_mut(&component_id) - } - pub fn make_add_edge(&self, component_id: Uid) -> (ArchetypeId, Vec<Uid>) { let mut edge_comp_ids = self diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 3caaa6b..2c88eef 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -1,6 +1,6 @@ #![deny(clippy::all, clippy::pedantic)] -use std::any::{type_name, TypeId}; +use std::any::{type_name, Any, TypeId}; use std::cell::RefCell; use std::fmt::Debug; use std::mem::ManuallyDrop; @@ -14,7 +14,6 @@ use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComp use crate::component::storage::Storage as ComponentStorage; use crate::component::{Component, Sequence as ComponentSequence}; use crate::entity::CREATE_STATIC_ENTITIES; -use crate::event::component::Kind as ComponentEventKind; use crate::extension::{Collector as ExtensionCollector, Extension}; use crate::lock::{Lock, WriteGuard}; use crate::phase::{Phase, START as START_PHASE}; @@ -31,7 +30,6 @@ use crate::relationship::{ChildOf, DependsOn, Relationship}; use crate::sole::Sole; use crate::stats::Stats; use crate::system::{System, SystemComponent}; -use crate::type_name::TypeName; use crate::uid::{Kind as UidKind, Uid}; pub mod actions; @@ -39,7 +37,7 @@ pub mod component; pub mod entity; pub mod event; pub mod extension; -pub mod lock; +mod lock; pub mod phase; pub mod query; pub mod relationship; @@ -47,7 +45,6 @@ pub mod sole; pub mod stats; pub mod system; pub mod tuple; -pub mod type_name; pub mod uid; pub mod util; @@ -184,10 +181,10 @@ impl World Query::new(self) } - pub fn flexible_query<'terms>( + pub fn flexible_query<const MAX_TERM_CNT: usize>( &self, - terms: QueryTerms<'terms>, - ) -> FlexibleQuery<'_, 'terms> + terms: QueryTerms<MAX_TERM_CNT>, + ) -> FlexibleQuery<'_, MAX_TERM_CNT> { FlexibleQuery::new(self, terms) } @@ -468,7 +465,7 @@ impl World { let mut component_storage_lock = self.lock_component_storage_rw(); - let removed_entity = 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}"); @@ -476,32 +473,17 @@ impl World } }; - let component_removed_event_uids = removed_entity - .components() - .iter() - .map(|component| { - component - .component() - .read_nonblock() - .unwrap_or_else(|_| { - panic!( - "Failed to acquire read-only {} component lock", - component.name() - ) - }) - .get_event_uid(ComponentEventKind::Removed) - }) - .collect::<Vec<_>>(); - drop(component_storage_lock); if !*has_swapped_active_queue { self.swap_event_queue(has_swapped_active_queue); } - for comp_removed_event_id in component_removed_event_uids { - self.emit_event_by_id(comp_removed_event_id); - } + // TODO: Emit component removed events here + + // for comp_removed_event_id in component_removed_event_uids { + // self.emit_event_by_id(comp_removed_event_id); + // } } fn add_entity_components( @@ -511,9 +493,10 @@ impl World ) { for (component_id, component) in components { - if let Err(err) = component_storage - .add_entity_component(entity_uid, (component_id, component)) - { + if let Err(err) = component_storage.add_entity_component( + entity_uid, + (component_id, component.name(), component), + ) { tracing::error!("Failed to add component to entity: {err}"); } } @@ -536,11 +519,9 @@ impl World fn emit_event_by_id(&self, event_id: Uid) { - let mut query_required_ids = [SystemComponent::id(), event_id]; - let query = self.flexible_query( - QueryTerms::builder() - .with_required_ids(&mut query_required_ids) + QueryTerms::<2>::builder() + .with_required([SystemComponent::id(), event_id]) .build(), ); @@ -590,7 +571,7 @@ pub enum StepResult Stop, } -#[derive(Debug, Default)] +#[derive(Debug)] pub struct WorldData { component_storage: Arc<Lock<ComponentStorage>>, @@ -598,6 +579,21 @@ pub struct WorldData action_queue: Arc<ActionQueue>, } +impl Default for WorldData +{ + fn default() -> Self + { + Self { + component_storage: Arc::new(Lock::new( + ComponentStorage::default(), + type_name::<ComponentStorage>(), + )), + sole_storage: SoleStorage::default(), + action_queue: Arc::new(ActionQueue::default()), + } + } +} + #[derive(Debug)] pub struct EntityComponentRef<'a> { @@ -606,7 +602,7 @@ pub struct EntityComponentRef<'a> impl<'a> EntityComponentRef<'a> { - pub fn component(&self) -> &'a Lock<Box<dyn Component>> + fn component(&self) -> &'a Lock<Box<dyn Any>> { self.comp.component() } @@ -625,7 +621,7 @@ enum ActiveActionQueue B, } -#[derive(Debug, Default)] +#[derive(Debug)] struct ActionQueue { queue_a: Lock<Vec<Action>>, @@ -652,11 +648,15 @@ impl ActionQueue } } -impl TypeName for ActionQueue +impl Default for ActionQueue { - fn type_name(&self) -> &'static str + fn default() -> Self { - type_name::<Self>() + Self { + queue_a: Lock::new(Vec::new(), type_name::<Vec<Action>>()), + queue_b: Lock::new(Vec::new(), type_name::<Vec<Action>>()), + active_queue: RefCell::new(ActiveActionQueue::default()), + } } } @@ -701,7 +701,7 @@ impl SoleStorage self.storage.insert( sole_type_id, ManuallyDrop::new(StoredSole { - sole: Arc::new(Lock::new(Box::new(sole))), + sole: Arc::new(Lock::new(Box::new(sole), type_name::<SoleT>())), drop_last, }), ); @@ -718,18 +718,9 @@ impl Drop for SoleStorage for sole in self.storage.values_mut() { if sole.drop_last { - tracing::trace!( - "Sole {} pushed to dropping last queue", - sole.sole.read_nonblock().unwrap().type_name() - ); - soles_to_drop_last.push(sole); continue; } - tracing::trace!( - "Dropping sole {}", - sole.sole.read_nonblock().unwrap().type_name() - ); unsafe { ManuallyDrop::drop(sole); @@ -737,11 +728,6 @@ impl Drop for SoleStorage } for sole in &mut soles_to_drop_last { - tracing::trace!( - "Dropping sole {} last", - sole.sole.read_nonblock().unwrap().type_name() - ); - unsafe { ManuallyDrop::drop(sole); } diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs index d6ed40e..0b36922 100644 --- a/ecs/src/lock.rs +++ b/ecs/src/lock.rs @@ -9,23 +9,21 @@ use parking_lot::{ RwLockWriteGuard, }; -use crate::type_name::TypeName; - -#[derive(Debug, Default)] +#[derive(Debug)] pub struct Lock<Value> -where - Value: TypeName, { inner: RwLock<Value>, + value_type_name: &'static str, } impl<Value> Lock<Value> -where - Value: TypeName, { - pub fn new(value: Value) -> Self + pub fn new(value: Value, value_type_name: &'static str) -> Self { - Self { inner: RwLock::new(value) } + Self { + inner: RwLock::new(value), + value_type_name, + } } /// Tries to a acquire a handle to the resource with read access. @@ -36,9 +34,12 @@ where { let guard = self.inner.try_read().ok_or(Error::ReadUnavailable)?; - tracing::trace!("Acquired lock to value of type {}", guard.type_name()); + tracing::trace!("Acquired lock to value of type {}", self.value_type_name); - Ok(ReadGuard { inner: guard }) + Ok(ReadGuard { + inner: guard, + value_type_name: self.value_type_name, + }) } /// Tries to a acquire a handle to the resource with mutable access. @@ -51,15 +52,13 @@ where tracing::trace!( "Acquired mutable lock to value of type {}", - guard.type_name() + self.value_type_name ); - Ok(WriteGuard { inner: guard }) - } - - pub fn into_inner(self) -> Value - { - self.inner.into_inner() + Ok(WriteGuard { + inner: guard, + value_type_name: self.value_type_name, + }) } } @@ -75,23 +74,20 @@ pub enum Error #[derive(Debug)] pub struct ReadGuard<'guard, Value> -where - Value: TypeName, { inner: RwLockReadGuard<'guard, Value>, + value_type_name: &'static str, } impl<'guard, Value> ReadGuard<'guard, Value> -where - Value: TypeName, { pub fn map<NewValue>( self, func: impl FnOnce(&Value) -> &NewValue, ) -> MappedReadGuard<'guard, NewValue> - where - NewValue: TypeName, { + let value_type_name = self.value_type_name; + // The 'inner' field cannot be moved out of ReadGuard in a normal way since // ReadGuard implements Drop let inner = unsafe { std::ptr::read(&self.inner) }; @@ -99,13 +95,12 @@ where MappedReadGuard { inner: RwLockReadGuard::map(inner, func), + value_type_name, } } } impl<Value> Deref for ReadGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -116,26 +111,21 @@ where } impl<Value> Drop for ReadGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped lock to value of type {}", self.type_name()); + tracing::trace!("Dropped lock to value of type {}", self.value_type_name); } } #[derive(Debug)] pub struct MappedReadGuard<'guard, Value> -where - Value: TypeName, { inner: MappedRwLockReadGuard<'guard, Value>, + value_type_name: &'static str, } impl<Value> Deref for MappedReadGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -146,34 +136,32 @@ where } impl<Value> Drop for MappedReadGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped mapped lock to value of type {}", self.type_name()); + tracing::trace!( + "Dropped mapped lock to value of type {}", + self.value_type_name + ); } } #[derive(Debug)] pub struct WriteGuard<'guard, Value> -where - Value: TypeName, { inner: RwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, } impl<'guard, Value> WriteGuard<'guard, Value> -where - Value: TypeName, { pub fn map<NewValue>( self, func: impl FnOnce(&mut Value) -> &mut NewValue, ) -> MappedWriteGuard<'guard, NewValue> - where - NewValue: TypeName, { + let value_type_name = self.value_type_name; + // The 'inner' field cannot be moved out of ReadGuard in a normal way since // ReadGuard implements Drop let inner = unsafe { std::ptr::read(&self.inner) }; @@ -181,13 +169,12 @@ where MappedWriteGuard { inner: RwLockWriteGuard::map(inner, func), + value_type_name, } } } impl<Value> Deref for WriteGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -198,8 +185,6 @@ where } impl<Value> DerefMut for WriteGuard<'_, Value> -where - Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { @@ -208,26 +193,24 @@ where } impl<Value> Drop for WriteGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { - tracing::trace!("Dropped mutable lock to value of type {}", self.type_name()); + tracing::trace!( + "Dropped mutable lock to value of type {}", + self.value_type_name + ); } } #[derive(Debug)] pub struct MappedWriteGuard<'guard, Value> -where - Value: TypeName, { inner: MappedRwLockWriteGuard<'guard, Value>, + value_type_name: &'static str, } impl<Value> Deref for MappedWriteGuard<'_, Value> -where - Value: TypeName, { type Target = Value; @@ -238,8 +221,6 @@ where } impl<Value> DerefMut for MappedWriteGuard<'_, Value> -where - Value: TypeName, { fn deref_mut(&mut self) -> &mut Self::Target { @@ -248,14 +229,12 @@ where } impl<Value> Drop for MappedWriteGuard<'_, Value> -where - Value: TypeName, { fn drop(&mut self) { tracing::trace!( "Dropped mapped mutable lock to value of type {}", - self.type_name() + self.value_type_name ); } } diff --git a/ecs/src/query.rs b/ecs/src/query.rs index d7d2d1c..7542f0d 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -1,15 +1,15 @@ use std::any::type_name; -use std::borrow::Cow; use std::marker::PhantomData; use seq_macro::seq; -use crate::component::{Component, FromLockedOptional, Ref as ComponentRef}; +use crate::component::{Component, HandleFromEntityComponentRef, Ref as ComponentRef}; use crate::entity::Handle as EntityHandle; use crate::query::flexible::{Iter as FlexibleQueryIter, Query as FlexibleQuery}; use crate::system::{Param as SystemParam, System}; use crate::uid::Uid; -use crate::util::VecExt; +use crate::util::array_vec::ArrayVec; +use crate::util::Array; use crate::World; pub mod flexible; @@ -22,7 +22,8 @@ where FieldlessTerms: TermWithoutFieldTuple, { world: &'world World, - inner: FlexibleQuery<'world, 'static>, + // A term tuple type can have a maximum of 17 elements + inner: FlexibleQuery<'world, 17>, _pd: PhantomData<(FieldTerms, FieldlessTerms)>, } @@ -147,43 +148,47 @@ where } #[derive(Debug)] -pub struct Terms<'a> +pub struct Terms<const MAX_TERM_CNT: usize> { - required_components: Cow<'a, [Uid]>, - excluded_components: Cow<'a, [Uid]>, + required_components: ArrayVec<Uid, MAX_TERM_CNT>, + excluded_components: ArrayVec<Uid, MAX_TERM_CNT>, } -impl<'a> Terms<'a> +impl<const MAX_TERM_CNT: usize> Terms<MAX_TERM_CNT> { - pub fn builder() -> TermsBuilder<'a> + pub fn builder() -> TermsBuilder<MAX_TERM_CNT> { TermsBuilder::default() } } #[derive(Debug, Default)] -pub struct TermsBuilder<'a> +pub struct TermsBuilder<const MAX_TERM_CNT: usize> { - required_components: Cow<'a, [Uid]>, - excluded_components: Cow<'a, [Uid]>, + required_components: ArrayVec<Uid, MAX_TERM_CNT>, + excluded_components: ArrayVec<Uid, MAX_TERM_CNT>, } -pub trait TermsBuilderInterface<'a> +pub trait TermsBuilderInterface { fn with<ComponentT: Component>(self) -> Self; fn without<ComponentT: Component>(self) -> Self; - fn with_required_ids(self, ids: &'a mut [Uid]) -> Self; + fn with_required(self, ids: impl Array<Uid>) -> Self; } macro_rules! impl_terms_builder { ($($impl_content: tt)*) => { - impl<'a> TermsBuilderInterface<'a> for TermsBuilder<'a> { + impl<const MAX_TERM_CNT: usize> + TermsBuilderInterface for TermsBuilder<MAX_TERM_CNT> + { $($impl_content)* } - impl<'a> TermsBuilderInterface<'a> for &mut TermsBuilder<'a> { + impl<const MAX_TERM_CNT: usize> + TermsBuilderInterface for &mut TermsBuilder<MAX_TERM_CNT> + { $($impl_content)* } }; @@ -193,13 +198,11 @@ impl_terms_builder! { #[allow(unused_mut)] fn with<ComponentT: Component>(mut self) -> Self { - if ComponentT::is_optional() { - return self; - } + let insert_index = self.required_components + .partition_point(|id| *id <= ComponentT::id()); self.required_components - .to_mut() - .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); + .insert(insert_index, ComponentT::id()); self } @@ -207,55 +210,51 @@ impl_terms_builder! { #[allow(unused_mut)] fn without<ComponentT: Component>(mut self) -> Self { - if ComponentT::is_optional() { - panic!( - "{}::without cannot take optional component", - type_name::<Self>() - ); - } + let insert_index = self.excluded_components + .partition_point(|id| *id <= ComponentT::id()); self.excluded_components - .to_mut() - .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); + .insert(insert_index, ComponentT::id()); self } #[allow(unused_mut)] - fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self + fn with_required(mut self, mut ids: impl Array<Uid>) -> Self { - if ids.is_empty() { - return self; + if !ids.as_ref().is_sorted() { + ids.as_mut().sort(); } - if !ids.is_sorted() { - ids.sort(); + if self.required_components.len() == 0 { + self.required_components.extend(ids); + return self; } - if self.required_components.is_empty() { - self.required_components = Cow::Borrowed(ids); + let mut id_iter = ids.into_iter(); - return self; - } + while let Some(id) = id_iter.next() { + let insert_index = self.required_components + .partition_point(|other_id| *other_id <= id); - let first_id_pp_index = self.required_components.partition_point(|req_comp_id| { - req_comp_id <= ids.first().expect("Cannot happend since not empty") - }); + if insert_index == self.required_components.len() { + self.required_components.extend([id].into_iter().chain(id_iter)); - let removed = self - .required_components - .to_mut() - .splice(first_id_pp_index..first_id_pp_index, ids.iter().copied()); + return self; + } + + self.required_components + .insert(insert_index, id); - assert_eq!(removed.count(), 0); + } self } } -impl<'a> TermsBuilder<'a> +impl<const MAX_TERM_CNT: usize> TermsBuilder<MAX_TERM_CNT> { - pub fn build(self) -> Terms<'a> + pub fn build(self) -> Terms<MAX_TERM_CNT> { assert!(self.required_components.is_sorted()); assert!(self.excluded_components.is_sorted()); @@ -269,14 +268,18 @@ impl<'a> TermsBuilder<'a> pub trait TermWithoutField { - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ); } pub trait TermWithField { type Field<'a>; - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ); fn get_field<'world>( entity_handle: &EntityHandle<'world>, @@ -288,7 +291,9 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT { type Field<'a> = ComponentRefT::Handle<'a>; - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>) + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) { terms_builder.with::<ComponentRefT::Component>(); } @@ -298,15 +303,13 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT world: &'world World, ) -> Self::Field<'world> { - Self::Field::from_locked_optional_component( - entity_handle - .get_component(ComponentRefT::Component::id()) - .map(|component| component.component()), + Self::Field::from_entity_component_ref( + entity_handle.get_component(ComponentRefT::Component::id()), world, ) .unwrap_or_else(|err| { panic!( - "Taking component {} lock failed: {err}", + "Creating handle to component {} failed: {err}", type_name::<ComponentRefT::Component>() ); }) @@ -315,14 +318,18 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT pub trait TermWithoutFieldTuple { - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ); } pub trait TermWithFieldTuple { type Fields<'component>; - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ); fn get_fields<'component>( entity_handle: &EntityHandle<'component>, @@ -411,7 +418,9 @@ macro_rules! impl_term_sequence { seq!(I in 0..=$c { impl<#(Term~I: TermWithoutField,)*> TermWithoutFieldTuple for (#(Term~I,)*) { - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT> + ) { #( Term~I::apply_to_terms_builder(terms_builder); @@ -423,7 +432,9 @@ macro_rules! impl_term_sequence { { type Fields<'component> = (#(Term~I::Field<'component>,)*); - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT> + ) { #( Term~I::apply_to_terms_builder(terms_builder); @@ -448,14 +459,22 @@ seq!(C in 0..=16 { impl TermWithoutFieldTuple for () { - fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) + { + } } impl TermWithFieldTuple for () { type Fields<'component> = (); - fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} + fn apply_terms_to_builder<const MAX_TERM_CNT: usize>( + _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) + { + } fn get_fields<'component>( _entity_handle: &EntityHandle<'_>, diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs index 652b96f..2f0b5e7 100644 --- a/ecs/src/query/flexible.rs +++ b/ecs/src/query/flexible.rs @@ -14,13 +14,13 @@ use crate::World; /// Low-level entity query structure. #[derive(Debug)] -pub struct Query<'world, 'terms> +pub struct Query<'world, const MAX_TERM_CNT: usize> { component_storage: ReadGuard<'world, ComponentStorage>, - terms: Terms<'terms>, + terms: Terms<MAX_TERM_CNT>, } -impl<'world, 'terms> Query<'world, 'terms> +impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT> { /// Iterates over the entities matching this query. #[must_use] @@ -42,7 +42,7 @@ impl<'world, 'terms> Query<'world, 'terms> } } - pub(crate) fn new(world: &'world World, terms: Terms<'terms>) -> Self + pub(crate) fn new(world: &'world World, terms: Terms<MAX_TERM_CNT>) -> Self { Self { component_storage: world diff --git a/ecs/src/query/term.rs b/ecs/src/query/term.rs index 7f24147..78668c5 100644 --- a/ecs/src/query/term.rs +++ b/ecs/src/query/term.rs @@ -1,7 +1,13 @@ +use std::any::type_name; use std::marker::PhantomData; -use crate::component::Component; -use crate::query::{TermWithoutField, TermsBuilder, TermsBuilderInterface}; +use crate::component::{Component, HandleFromEntityComponentRef, Ref as ComponentRef}; +use crate::query::{ + TermWithField, + TermWithoutField, + TermsBuilder, + TermsBuilderInterface, +}; pub struct With<ComponentT> where @@ -14,7 +20,9 @@ impl<ComponentT> TermWithoutField for With<ComponentT> where ComponentT: Component, { - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>) + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) { terms_builder.with::<ComponentT>(); } @@ -31,8 +39,42 @@ impl<ComponentT> TermWithoutField for Without<ComponentT> where ComponentT: Component, { - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>) + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) { terms_builder.without::<ComponentT>(); } } + +impl<ComponentRefT> TermWithField for Option<ComponentRefT> +where + ComponentRefT: ComponentRef, +{ + type Field<'a> = Option<ComponentRefT::Handle<'a>>; + + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + ) + { + } + + fn get_field<'world>( + entity_handle: &crate::entity::Handle<'world>, + world: &'world crate::World, + ) -> Self::Field<'world> + { + Some( + ComponentRefT::Handle::<'world>::from_entity_component_ref( + Some(entity_handle.get_component(ComponentRefT::Component::id())?), + world, + ) + .unwrap_or_else(|err| { + panic!( + "Creating handle to component {} failed: {err}", + type_name::<ComponentRefT::Component>() + ); + }), + ) + } +} diff --git a/ecs/src/relationship.rs b/ecs/src/relationship.rs index 45fa265..e368dd4 100644 --- a/ecs/src/relationship.rs +++ b/ecs/src/relationship.rs @@ -6,13 +6,14 @@ use ecs_macros::Component; use crate::component::storage::Storage as ComponentStorage; use crate::component::{ Component, - FromLockedOptional as FromLockedOptionalComponent, Handle as ComponentHandle, + HandleError as ComponentHandleError, + HandleFromEntityComponentRef, HandleMut as ComponentHandleMut, }; -use crate::lock::{Error as LockError, Lock, ReadGuard}; +use crate::lock::ReadGuard; use crate::uid::{Kind as UidKind, Uid}; -use crate::World; +use crate::{EntityComponentRef, World}; /// A relationship to one or more targets. #[derive(Debug, Component)] @@ -70,22 +71,24 @@ where relationship_comp: ComponentHandleMut<'rel_comp, Relationship<Kind, ComponentT>>, } -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> +impl<'rel_comp, Kind, ComponentT> HandleFromEntityComponentRef<'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>>>, + type Error = ComponentHandleError; + + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'rel_comp>>, world: &'rel_comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - let relationship_comp_handle_from_locked_opt_comp = ComponentHandleMut::< + let relationship_comp_handle_from_ent_comp_ref = ComponentHandleMut::< Relationship<Kind, ComponentT>, - >::from_locked_optional_component; + >::from_entity_component_ref; let relationship_comp = - relationship_comp_handle_from_locked_opt_comp(optional_component, world)?; + relationship_comp_handle_from_ent_comp_ref(entity_component_ref, world)?; let component_storage_lock = world .data @@ -100,24 +103,6 @@ where } } -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> - for Option<RelationMut<'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, crate::lock::Error> - { - optional_component - .map(|component| { - RelationMut::from_locked_optional_component(Some(component), world) - }) - .transpose() - } -} - impl<'rel_comp, Kind, ComponentT> RelationMut<'rel_comp, Kind, ComponentT> where ComponentT: Component, @@ -292,22 +277,23 @@ where relationship_comp: ComponentHandle<'rel_comp, Relationship<Kind, ComponentT>>, } -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> +impl<'rel_comp, Kind, ComponentT> HandleFromEntityComponentRef<'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>>>, + type Error = ComponentHandleError; + + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'rel_comp>>, world: &'rel_comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - let relationship_comp_handle_from_locked_opt_comp = ComponentHandle::< - Relationship<Kind, ComponentT>, - >::from_locked_optional_component; + let relationship_comp_handle_from_ent_comp_ref = + ComponentHandle::<Relationship<Kind, ComponentT>>::from_entity_component_ref; let relationship_comp = - relationship_comp_handle_from_locked_opt_comp(optional_component, world)?; + relationship_comp_handle_from_ent_comp_ref(entity_component_ref, world)?; let component_storage_lock = world .data @@ -322,24 +308,6 @@ where } } -impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp> - for Option<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, crate::lock::Error> - { - optional_component - .map(|component| { - Relation::from_locked_optional_component(Some(component), world) - }) - .transpose() - } -} - impl<'rel_comp, Kind, ComponentT> Relation<'rel_comp, Kind, ComponentT> where ComponentT: Component, diff --git a/ecs/src/sole.rs b/ecs/src/sole.rs index 5af5ce3..1cce419 100644 --- a/ecs/src/sole.rs +++ b/ecs/src/sole.rs @@ -6,11 +6,10 @@ use std::sync::{Arc, Weak}; use crate::lock::{Lock, WriteGuard}; use crate::system::{Param as SystemParam, System}; -use crate::type_name::TypeName; use crate::World; /// A type which has a single instance and is shared globally. -pub trait Sole: Any + TypeName +pub trait Sole: Any { fn drop_last(&self) -> bool; @@ -40,14 +39,6 @@ impl Debug for dyn Sole } } -impl TypeName for Box<dyn Sole> -{ - fn type_name(&self) -> &'static str - { - self.as_ref().type_name() - } -} - /// Holds a reference to a globally shared singleton value. #[derive(Debug)] pub struct Single<'world, SoleT: Sole> diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index 9d911ee..54f6979 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -1,4 +1,4 @@ -use std::any::{Any, TypeId}; +use std::any::{type_name, Any, TypeId}; use std::panic::{RefUnwindSafe, UnwindSafe}; use hashbrown::HashMap; @@ -25,7 +25,7 @@ use crate::World; pub struct Stateful<Func> { func: Func, - local_components: HashMap<Uid, Lock<Box<dyn Component>>>, + local_components: HashMap<Uid, Lock<Box<dyn Any>>>, } macro_rules! impl_system { @@ -127,7 +127,10 @@ macro_rules! impl_system { self.local_components .insert( LocalComponent::id(), - Lock::new(Box::new(local_component)) + Lock::new( + Box::new(local_component), + type_name::<LocalComponent>() + ) ); } } diff --git a/ecs/src/type_name.rs b/ecs/src/type_name.rs deleted file mode 100644 index 54179be..0000000 --- a/ecs/src/type_name.rs +++ /dev/null @@ -1,15 +0,0 @@ -use std::any::type_name; - -pub trait TypeName -{ - /// Returns the name of this type. - fn type_name(&self) -> &'static str; -} - -impl<Item> TypeName for Vec<Item> -{ - fn type_name(&self) -> &'static str - { - type_name::<Self>() - } -} diff --git a/ecs/src/util.rs b/ecs/src/util.rs index 6f7aed7..eb06ab4 100644 --- a/ecs/src/util.rs +++ b/ecs/src/util.rs @@ -4,6 +4,8 @@ use std::ops::{BitAnd, Deref}; use hashbrown::HashMap; +pub mod array_vec; + pub trait VecExt<Item> { fn insert_at_partition_point_by_key<Key>( diff --git a/ecs/src/util/array_vec.rs b/ecs/src/util/array_vec.rs new file mode 100644 index 0000000..648c976 --- /dev/null +++ b/ecs/src/util/array_vec.rs @@ -0,0 +1,115 @@ +use std::mem::{transmute, MaybeUninit}; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug)] +pub struct ArrayVec<Item, const CAPACITY: usize> +{ + items: [MaybeUninit<Item>; CAPACITY], + len: usize, +} + +impl<Item, const CAPACITY: usize> ArrayVec<Item, CAPACITY> +{ + pub fn new() -> Self + { + Self::default() + } + + #[inline] + #[must_use] + pub fn len(&self) -> usize + { + self.len + } + + pub fn push(&mut self, item: Item) + { + assert!(self.len < CAPACITY); + + self.items[self.len].write(item); + + self.len += 1; + } + + pub fn insert(&mut self, index: usize, item: Item) + { + assert!(index <= self.len); + assert!(self.len < CAPACITY); + + if index == self.len { + self.push(item); + return; + } + + unsafe { + std::ptr::copy( + &self.items[index], + &mut self.items[index + 1], + self.len - index, + ); + } + + self.items[index].write(item); + + self.len += 1; + } +} + +impl<Item, const CAPACITY: usize> Extend<Item> for ArrayVec<Item, CAPACITY> +{ + fn extend<IntoIter: IntoIterator<Item = Item>>(&mut self, iter: IntoIter) + { + for item in iter { + self.push(item); + } + } +} + +impl<Item, const CAPACITY: usize> AsRef<[Item]> for ArrayVec<Item, CAPACITY> +{ + fn as_ref(&self) -> &[Item] + { + unsafe { transmute::<&[MaybeUninit<Item>], &[Item]>(&self.items[..self.len]) } + } +} + +impl<Item, const CAPACITY: usize> AsMut<[Item]> for ArrayVec<Item, CAPACITY> +{ + fn as_mut(&mut self) -> &mut [Item] + { + unsafe { + transmute::<&mut [MaybeUninit<Item>], &mut [Item]>( + &mut self.items[..self.len], + ) + } + } +} + +impl<Item, const CAPACITY: usize> Deref for ArrayVec<Item, CAPACITY> +{ + type Target = [Item]; + + fn deref(&self) -> &Self::Target + { + self.as_ref() + } +} + +impl<Item, const CAPACITY: usize> DerefMut for ArrayVec<Item, CAPACITY> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + self.as_mut() + } +} + +impl<Item, const CAPACITY: usize> Default for ArrayVec<Item, CAPACITY> +{ + fn default() -> Self + { + Self { + items: [const { MaybeUninit::uninit() }; CAPACITY], + len: 0, + } + } +} diff --git a/ecs/tests/query.rs b/ecs/tests/query.rs index 0f02bd3..6e747e3 100644 --- a/ecs/tests/query.rs +++ b/ecs/tests/query.rs @@ -210,7 +210,7 @@ fn query_archetype_exists_with_4_comps_diff_to_next_archetype_and_opt_comp() let ent_2_id = world.create_entity((A, B, G)); assert_query_finds_ents( - world.query::<(&A, &Option<E>, &G), ()>(), + world.query::<(&A, Option<&E>, &G), ()>(), vec![ent_1_id, ent_2_id], ); } @@ -249,7 +249,7 @@ fn query_archetype_nonexistant_and_opt_comp() world.create_entity((A, B, C, G, F)); assert_query_finds_ents( - world.query::<(&A, &E, &Option<D>), ()>(), + world.query::<(&A, &E, Option<&D>), ()>(), vec![ent_2_id, ent_3_id], ); } diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index 5665860..84af219 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -72,11 +72,11 @@ use crate::window::Window; type RenderableEntity<'a> = ( &'a Mesh, &'a Material, - &'a Option<MaterialFlags>, - &'a Option<Position>, - &'a Option<Scale>, - &'a Option<DrawFlags>, - &'a Option<GlObjects>, + Option<&'a MaterialFlags>, + Option<&'a Position>, + Option<&'a Scale>, + Option<&'a DrawFlags>, + Option<&'a GlObjects>, ); #[derive(Debug, Default)] |