diff options
Diffstat (limited to 'engine-ecs/src')
| -rw-r--r-- | engine-ecs/src/actions.rs | 13 | ||||
| -rw-r--r-- | engine-ecs/src/component.rs | 70 | ||||
| -rw-r--r-- | engine-ecs/src/lib.rs | 1 | ||||
| -rw-r--r-- | engine-ecs/src/pair.rs | 61 | ||||
| -rw-r--r-- | engine-ecs/src/phase.rs | 1 | ||||
| -rw-r--r-- | engine-ecs/src/query/term.rs | 113 | ||||
| -rw-r--r-- | engine-ecs/src/sole.rs | 34 | ||||
| -rw-r--r-- | engine-ecs/src/uid.rs | 45 |
8 files changed, 195 insertions, 143 deletions
diff --git a/engine-ecs/src/actions.rs b/engine-ecs/src/actions.rs index 69605b3..cef51cc 100644 --- a/engine-ecs/src/actions.rs +++ b/engine-ecs/src/actions.rs @@ -1,12 +1,17 @@ use std::borrow::Cow; use crate::bundle::Bundle; -use crate::component::{Component, IntoParts, Parts as ComponentParts}; +use crate::component::{ + Component, + IntoParts, + Parts as ComponentParts, + RemovableTuple as RemovableComponentTuple, +}; use crate::entity::Name as EntityName; use crate::event::component::Removed; use crate::pair::Pair; use crate::system::{Metadata as SystemMetadata, Param as SystemParam}; -use crate::uid::{Uid, WithUidTuple}; +use crate::uid::Uid; use crate::{ActionQueue, World}; /// Used to to queue up actions for a [`World`] to perform. @@ -174,9 +179,9 @@ impl Actions<'_> } /// Queues up removing component(s) from a entity at the end of the current tick. - pub fn remove_comps<Ids: WithUidTuple>(&mut self, entity_uid: Uid) + pub fn remove_comps<Components: RemovableComponentTuple>(&mut self, entity_uid: Uid) { - self.remove_components(entity_uid, Ids::uids()); + self.remove_components(entity_uid, Components::ids()); } /// Queues up setting the target of a entity's pair at the end of the current tick. diff --git a/engine-ecs/src/component.rs b/engine-ecs/src/component.rs index 400b12c..d424e16 100644 --- a/engine-ecs/src/component.rs +++ b/engine-ecs/src/component.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::ops::{Deref, DerefMut}; use engine_ecs_macros::Component; +use seq_macro::seq; use crate::event::component::Changed; use crate::event::Submitter as EventSubmitter; @@ -23,13 +24,9 @@ pub mod local; pub(crate) mod storage; -pub trait Component: SystemInput + Any + IntoParts +/// A component that is not a pair and is not a sole. +pub trait Component: WithAssociatedId + SystemInput + Any + IntoParts { - /// Returns the ID of this component. - fn id() -> Uid - where - Self: Sized; - fn type_reflection() -> Option<&'static TypeReflection> where Self: Sized; @@ -38,32 +35,50 @@ pub trait Component: SystemInput + Any + IntoParts fn name(&self) -> &'static str; } -impl dyn Component +pub trait WithAssociatedId { - pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real> - { - (self as &mut dyn Any).downcast_mut() - } + /// Returns the ID of this component. + fn id() -> Uid; +} - pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real> - { - (self as &dyn Any).downcast_ref() - } +/// A component that is removable from it's entity. +/// +/// This trait is implemented for [`crate::pair::Pair`] so it does not have [`Component`] +/// as supertrait. +pub trait Removable: WithAssociatedId {} - pub fn is<Other: 'static>(&self) -> bool - { - (self as &dyn Any).is::<Other>() - } -} +impl<ComponentT: Component> Removable for ComponentT {} -impl Debug for dyn Component +/// Implemented by tuples of types implementing [`Removable`]. +/// +/// This trait is sealed so it cannot be implemented by types outside of this module. +pub trait RemovableTuple: sealed::Sealed { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - formatter.debug_struct("Component").finish_non_exhaustive() - } + fn ids() -> impl IntoIterator<Item = Uid>; +} + +macro_rules! gen_removable_tuple_impl { + ($c: tt) => { + seq!(I in 0..=$c { + impl<#(RemovableT~I: Removable,)*> RemovableTuple for (#(RemovableT~I,)*) + { + fn ids() -> impl IntoIterator<Item = Uid> + { + [#(RemovableT~I::id(),)*] + } + } + + impl<#(RemovableT~I: Removable,)*> sealed::Sealed for (#(RemovableT~I,)*) + { + } + }); + }; } +seq!(C in 0..=16 { + gen_removable_tuple_impl!(C); +}); + #[derive(Debug)] pub struct Handle<'a, DataT: ?Sized + 'static> { @@ -394,3 +409,8 @@ pub struct Info pub name: &'static str, pub is_sole: bool, } + +mod sealed +{ + pub trait Sealed {} +} diff --git a/engine-ecs/src/lib.rs b/engine-ecs/src/lib.rs index a752f6a..6028cf7 100644 --- a/engine-ecs/src/lib.rs +++ b/engine-ecs/src/lib.rs @@ -22,6 +22,7 @@ use crate::component::{ Info as ComponentInfo, IntoParts as IntoComponentParts, Parts as ComponentParts, + WithAssociatedId, }; use crate::entity::{ Declaration as EntityDeclaration, diff --git a/engine-ecs/src/pair.rs b/engine-ecs/src/pair.rs index 834077c..efeead9 100644 --- a/engine-ecs/src/pair.rs +++ b/engine-ecs/src/pair.rs @@ -8,6 +8,8 @@ use crate::component::{ HandleMut as ComponentHandleMut, IntoParts as IntoComponentParts, Parts as ComponentParts, + Removable as RemovableComponent, + WithAssociatedId as ComponentWithAssociatedId, }; use crate::entity::{ Handle as EntityHandle, @@ -21,7 +23,7 @@ use crate::query::{ TermsBuilderInterface, }; use crate::reflection::Type as TypeReflection; -use crate::uid::{PairParams as UidPairParams, Uid, With as WithUid}; +use crate::uid::{PairParams as UidPairParams, Uid}; use crate::util::impl_multiple; use crate::{Component, EntityComponentRef, World}; @@ -265,7 +267,7 @@ where _term_metadata: QueryTermMetadata, ) { - terms_builder.present([Pair::<Relation, Target>::uid()]); + terms_builder.present([Pair::<Relation, Target>::id()]); } fn fields( @@ -276,7 +278,7 @@ where { let target_component = search_result .entity_handle - .get_matching_components(Pair::<Relation, Target>::uid()) + .get_matching_components(Pair::<Relation, Target>::id()) .next() .expect("Not possible"); @@ -308,7 +310,7 @@ where _term_metadata: QueryTermMetadata, ) { - terms_builder.present([Pair::<Relation, Target>::uid()]); + terms_builder.present([Pair::<Relation, Target>::id()]); } fn fields( @@ -319,7 +321,7 @@ where { let target_component = search_result .entity_handle - .get_matching_components(Pair::<Relation, Target>::uid()) + .get_matching_components(Pair::<Relation, Target>::id()) .next() .expect("Not possible"); @@ -355,7 +357,7 @@ where _term_metadata: QueryTermMetadata, ) { - terms_builder.present([Self::uid()]); + terms_builder.present([Self::id()]); } fn fields( @@ -366,7 +368,7 @@ where { let first_matching_comp = search_result .entity_handle - .get_matching_components(Self::uid()) + .get_matching_components(Self::id()) .next() .expect("Not possible"); @@ -378,12 +380,12 @@ where } } -impl<Relation, Target> WithUid for Pair<Relation, Target> +impl<Relation, Target> ComponentWithAssociatedId for Pair<Relation, Target> where Relation: Component, Target: Component, { - fn uid() -> Uid + fn id() -> Uid { Uid::new_pair(&UidPairParams { relation: Relation::id(), @@ -392,15 +394,28 @@ where } } -impl<Relation> WithUid for Pair<Relation, Wildcard> +impl<Relation, Target> RemovableComponent for Pair<Relation, Target> where Relation: Component, + Target: Component, { - fn uid() -> Uid +} + +// TODO: Implement RemovableComponent for Pair<Relation, Wildcard> +// and Pair<Wildcard, Target>. +// +// This should only be done after removal of wildcard pairs is added in lib.rs + +impl<Relation> Pair<Relation, Wildcard> +where + Relation: Component, +{ + #[must_use] + pub fn id() -> Uid { Uid::new_pair(&UidPairParams { relation: Relation::id(), - target: Wildcard::uid(), + target: Wildcard::id(), }) } } @@ -464,19 +479,17 @@ impl<'query, Relation, Target> WithWildcard<'query, Relation, Target> assert!(component_id.is_pair()); assert!( - Relation::uid() == Wildcard::uid() + Relation::uid() == Wildcard::id() || component_id.relation() == Relation::uid() ); assert!( - Target::uid() == Wildcard::uid() || component_id.target() == Target::uid() + Target::uid() == Wildcard::id() || component_id.target() == Target::uid() ); - assert!(Relation::uid() == Wildcard::uid() || Target::uid() == Wildcard::uid()); + assert!(Relation::uid() == Wildcard::id() || Target::uid() == Wildcard::id()); - assert!( - !(Relation::uid() == Wildcard::uid() && Target::uid() == Wildcard::uid()) - ); + assert!(!(Relation::uid() == Wildcard::id() && Target::uid() == Wildcard::id())); WithWildcard { world, @@ -641,11 +654,9 @@ impl<'query, Relation, Target> MultipleWithWildcard<'query, Relation, Target> Relation: ComponentOrWildcard, Target: ComponentOrWildcard, { - assert!(Relation::uid() == Wildcard::uid() || Target::uid() == Wildcard::uid()); + assert!(Relation::uid() == Wildcard::id() || Target::uid() == Wildcard::id()); - assert!( - !(Relation::uid() == Wildcard::uid() && Target::uid() == Wildcard::uid()) - ); + assert!(!(Relation::uid() == Wildcard::id() && Target::uid() == Wildcard::id())); MultipleWithWildcard { entity_handle, @@ -691,7 +702,7 @@ impl<'a, Relation: Component> IntoIterator WithWildcardIter { inner: self .entity_handle - .get_matching_components(Pair::<Relation, Wildcard>::uid()), + .get_matching_components(Pair::<Relation, Wildcard>::id()), world: self.world, _pd: PhantomData, } @@ -736,7 +747,7 @@ pub struct Wildcard(Infallible); impl Wildcard { #[must_use] - pub fn uid() -> Uid + pub fn id() -> Uid { Uid::wildcard() } @@ -761,7 +772,7 @@ impl ComponentOrWildcard for Wildcard { fn uid() -> Uid { - Wildcard::uid() + Wildcard::id() } } diff --git a/engine-ecs/src/phase.rs b/engine-ecs/src/phase.rs index 64c1593..e5008ad 100644 --- a/engine-ecs/src/phase.rs +++ b/engine-ecs/src/phase.rs @@ -1,3 +1,4 @@ +use crate::component::WithAssociatedId as _; use crate::{declare_entity, Component, World}; #[cfg(debug_assertions)] use crate::{ diff --git a/engine-ecs/src/query/term.rs b/engine-ecs/src/query/term.rs index 980ee87..f5fd531 100644 --- a/engine-ecs/src/query/term.rs +++ b/engine-ecs/src/query/term.rs @@ -5,7 +5,9 @@ use crate::component::{ Component, Handle as ComponentHandle, HandleMut as ComponentHandleMut, + WithAssociatedId as _, }; +use crate::pair::{Pair, Wildcard}; use crate::query::{ FoundByTraversal, SearchResult, @@ -17,19 +19,61 @@ use crate::query::{ Traversal, TraversalKind, }; -use crate::uid::With as WithUid; use crate::World; -pub struct With<WithUidT> +pub struct With<T> +{ + _pd: PhantomData<T>, +} + +impl<'query, ComponentT: Component> Term<'query> for With<ComponentT> +{ + type Fields = (); + + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + _term_metadata: TermMetadata, + ) + { + terms_builder.present([ComponentT::id()]); + } + + fn fields( + _world: &'query World, + _search_result: &SearchResult<'query, '_>, + _term_metadata: TermMetadata, + ) -> Self::Fields + { + } +} + +impl<'query, Relation, Target> Term<'query> for With<Pair<Relation, Target>> where - WithUidT: WithUid, + Relation: Component, + Target: Component, { - _pd: PhantomData<WithUidT>, + type Fields = (); + + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + _term_metadata: TermMetadata, + ) + { + terms_builder.present([Pair::<Relation, Target>::id()]); + } + + fn fields( + _world: &'query World, + _search_result: &SearchResult<'query, '_>, + _term_metadata: TermMetadata, + ) -> Self::Fields + { + } } -impl<'query, WithUidT> Term<'query> for With<WithUidT> +impl<'query, Relation> Term<'query> for With<Pair<Relation, Wildcard>> where - WithUidT: WithUid, + Relation: Component, { type Fields = (); @@ -38,7 +82,7 @@ where _term_metadata: TermMetadata, ) { - terms_builder.present([WithUidT::uid()]); + terms_builder.present([Pair::<Relation, Wildcard>::id()]); } fn fields( @@ -50,16 +94,59 @@ where } } -pub struct Without<WithUidT> +pub struct Without<T> +{ + _pd: PhantomData<T>, +} + +impl<'query, ComponentT: Component> Term<'query> for Without<ComponentT> +{ + type Fields = (); + + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + _term_metadata: TermMetadata, + ) + { + terms_builder.absent([ComponentT::id()]); + } + + fn fields( + _world: &'query World, + _search_result: &SearchResult<'query, '_>, + _term_metadata: TermMetadata, + ) -> Self::Fields + { + } +} + +impl<'query, Relation, Target> Term<'query> for Without<Pair<Relation, Target>> where - WithUidT: WithUid, + Relation: Component, + Target: Component, { - _pd: PhantomData<WithUidT>, + type Fields = (); + + fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( + terms_builder: &mut TermsBuilder<MAX_TERM_CNT>, + _term_metadata: TermMetadata, + ) + { + terms_builder.absent([Pair::<Relation, Target>::id()]); + } + + fn fields( + _world: &'query World, + _search_result: &SearchResult<'query, '_>, + _term_metadata: TermMetadata, + ) -> Self::Fields + { + } } -impl<'query, WithUidT> Term<'query> for Without<WithUidT> +impl<'query, Relation> Term<'query> for Without<Pair<Relation, Wildcard>> where - WithUidT: WithUid, + Relation: Component, { type Fields = (); @@ -68,7 +155,7 @@ where _term_metadata: TermMetadata, ) { - terms_builder.absent([WithUidT::uid()]); + terms_builder.absent([Pair::<Relation, Wildcard>::id()]); } fn fields( diff --git a/engine-ecs/src/sole.rs b/engine-ecs/src/sole.rs index 4047b48..9168414 100644 --- a/engine-ecs/src/sole.rs +++ b/engine-ecs/src/sole.rs @@ -4,18 +4,14 @@ use std::fmt::Debug; use crate::component::{ HandleMut as ComponentHandleMut, IntoParts as IntoComponentParts, + WithAssociatedId as ComponentWithAssociatedId, }; use crate::system::{Metadata as SystemMetadata, Param as SystemParam}; -use crate::uid::Uid; use crate::World; /// A component which has a single instance in the [`World`]. -pub trait Sole: Any + IntoComponentParts +pub trait Sole: Any + IntoComponentParts + ComponentWithAssociatedId { - fn id() -> Uid - where - Self: Sized; - fn type_reflection() -> Option<&'static crate::reflection::Type> where Self: Sized; @@ -24,32 +20,6 @@ pub trait Sole: Any + IntoComponentParts fn name(&self) -> &'static str; } -impl dyn Sole -{ - pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real> - { - (self as &mut dyn Any).downcast_mut() - } - - pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real> - { - (self as &dyn Any).downcast_ref() - } - - pub fn is<Other: 'static>(&self) -> bool - { - (self as &dyn Any).is::<Other>() - } -} - -impl Debug for dyn Sole -{ - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - formatter.debug_struct("Sole").finish_non_exhaustive() - } -} - /// Holds a reference to a singleton component. #[derive(Debug)] pub struct Single<'world, SoleT: Sole> diff --git a/engine-ecs/src/uid.rs b/engine-ecs/src/uid.rs index 78ca2ad..6b1a4b5 100644 --- a/engine-ecs/src/uid.rs +++ b/engine-ecs/src/uid.rs @@ -1,10 +1,7 @@ use std::fmt::{Debug, Display, Formatter}; use std::sync::atomic::{AtomicU32, Ordering}; -use seq_macro::seq; - -use crate::component::Component; -use crate::util::{gen_mask_64, Array, BitMask, NumberExt}; +use crate::util::{gen_mask_64, BitMask, NumberExt}; static NEXT: AtomicU32 = AtomicU32::new(Uid::FIRST_UNIQUE_ID); @@ -165,43 +162,3 @@ pub struct PairParams pub relation: Uid, pub target: Uid, } - -pub trait With: 'static -{ - fn uid() -> Uid; -} - -impl<ComponentT: Component> With for ComponentT -{ - fn uid() -> Uid - { - Self::id() - } -} - -pub trait WithUidTuple -{ - type UidsArray: Array<Uid>; - - fn uids() -> Self::UidsArray; -} - -macro_rules! impl_with_uid_tuple { - ($c: tt) => { - seq!(I in 0..=$c { - impl<#(WithUid~I: With,)*> WithUidTuple for (#(WithUid~I,)*) - { - type UidsArray = [Uid; $c + 1]; - - fn uids() -> Self::UidsArray - { - [#(WithUid~I::uid(),)*] - } - } - }); - }; -} - -seq!(C in 0..=16 { - impl_with_uid_tuple!(C); -}); |
