diff options
Diffstat (limited to 'ecs/src/query.rs')
-rw-r--r-- | ecs/src/query.rs | 279 |
1 files changed, 163 insertions, 116 deletions
diff --git a/ecs/src/query.rs b/ecs/src/query.rs index 2fcd2cc..1889e00 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -10,42 +10,42 @@ use crate::query::flexible::{ Iter as FlexibleQueryIter, Query as FlexibleQuery, }; -use crate::query::options::Options; use crate::system::{Param as SystemParam, System}; use crate::uid::Uid; use crate::util::VecExt; -use crate::{EntityComponent, World}; +use crate::World; pub mod flexible; -pub mod options; +pub mod term; #[derive(Debug)] -pub struct Query<'world, Terms, OptionsT = ()> +pub struct Query<'world, FieldTerms, FieldlessTerms = ()> where - Terms: TermSequence, + FieldTerms: TermWithFieldTuple, + FieldlessTerms: TermWithoutFieldTuple, { world: &'world World, inner: FlexibleQuery<'world, 'static>, - _pd: PhantomData<(Terms, OptionsT)>, + _pd: PhantomData<(FieldTerms, FieldlessTerms)>, } -impl<'world, Terms, OptionsT> Query<'world, Terms, OptionsT> +impl<'world, FieldTerms, FieldlessTerms> Query<'world, FieldTerms, FieldlessTerms> where - Terms: TermSequence, - OptionsT: Options, + FieldTerms: TermWithFieldTuple, + FieldlessTerms: TermWithoutFieldTuple, { /// Iterates over the entities matching this query, the iterator item being the entity /// components. #[must_use] pub fn iter<'query>( &'query self, - ) -> ComponentIter<'query, 'world, Terms, FlexibleQueryIter<'query>> + ) -> ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>> { - tracing::trace!("Searching for {}", std::any::type_name::<Terms>()); + tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); ComponentIter { world: self.world, - iter: self.inner.iter::<OptionsT>(), + iter: self.inner.iter(), comps_pd: PhantomData, } } @@ -55,13 +55,13 @@ where #[must_use] pub fn iter_with_euids<'query>( &'query self, - ) -> ComponentAndEuidIter<'query, 'world, Terms, FlexibleQueryIter<'query>> + ) -> ComponentAndEuidIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>> { - tracing::trace!("Searching for {}", std::any::type_name::<Terms>()); + tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); ComponentAndEuidIter { world: self.world, - iter: self.inner.iter::<OptionsT>(), + iter: self.inner.iter(), comps_pd: PhantomData, } } @@ -75,15 +75,15 @@ where pub fn iter_with<'query, OutIter>( &'query self, func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter, - ) -> ComponentIter<'query, 'world, Terms, OutIter> + ) -> ComponentIter<'query, 'world, FieldTerms, OutIter> where OutIter: Iterator<Item = EntityHandle<'query>>, { - tracing::trace!("Searching for {}", std::any::type_name::<Terms>()); + tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); ComponentIter { world: self.world, - iter: func(self.inner.iter::<OptionsT>()), + iter: func(self.inner.iter()), comps_pd: PhantomData, } } @@ -92,27 +92,32 @@ where #[must_use] pub fn get_entity_uid(&self, entity_index: usize) -> Option<Uid> { - Some(self.inner.iter::<OptionsT>().nth(entity_index)?.uid()) + Some(self.inner.iter().nth(entity_index)?.uid()) } pub(crate) fn new(world: &'world World) -> Self { + let mut terms_builder = Terms::builder(); + + FieldTerms::apply_terms_to_builder(&mut terms_builder); + FieldlessTerms::apply_terms_to_builder(&mut terms_builder); + Self { world, - inner: world.flexible_query(Terms::build_terms()), + inner: world.flexible_query(terms_builder.build()), _pd: PhantomData, } } } -impl<'query, 'world, Terms, OptionsT> IntoIterator - for &'query Query<'world, Terms, OptionsT> +impl<'query, 'world, FieldTerms, FieldlessTerms> IntoIterator + for &'query Query<'world, FieldTerms, FieldlessTerms> where - Terms: TermSequence + 'world, - OptionsT: Options, + FieldTerms: TermWithFieldTuple + 'world, + FieldlessTerms: TermWithoutFieldTuple, { - type IntoIter = ComponentIter<'query, 'world, Terms, FlexibleQueryIter<'query>>; - type Item = Terms::Handles<'query>; + type IntoIter = ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>; + type Item = FieldTerms::Fields<'query>; fn into_iter(self) -> Self::IntoIter { @@ -120,10 +125,11 @@ where } } -impl<'world, Terms, OptionsT> SystemParam<'world> for Query<'world, Terms, OptionsT> +impl<'world, FieldTerms, FieldlessTerms> SystemParam<'world> + for Query<'world, FieldTerms, FieldlessTerms> where - Terms: TermSequence, - OptionsT: Options, + FieldTerms: TermWithFieldTuple, + FieldlessTerms: TermWithoutFieldTuple, { type Input = (); @@ -147,7 +153,7 @@ where pub struct Terms<'a> { required_components: Cow<'a, [Uid]>, - //optional_components: Cow<'a, [Uid]>, + excluded_components: Cow<'a, [Uid]>, } impl<'a> Terms<'a> @@ -162,18 +168,35 @@ impl<'a> Terms<'a> pub struct TermsBuilder<'a> { required_components: Cow<'a, [Uid]>, - //optional_components: Cow<'a, [Uid]>, + excluded_components: Cow<'a, [Uid]>, } -impl<'a> TermsBuilder<'a> +pub trait TermsBuilderInterface<'a> { - pub fn with<ComponentT: Component>(mut self) -> Self + fn with<ComponentT: Component>(self) -> Self; + + fn without<ComponentT: Component>(self) -> Self; + + fn with_required_ids(self, ids: &'a mut [Uid]) -> Self; +} + +macro_rules! impl_terms_builder { + ($($impl_content: tt)*) => { + impl<'a> TermsBuilderInterface<'a> for TermsBuilder<'a> { + $($impl_content)* + } + + impl<'a> TermsBuilderInterface<'a> for &mut TermsBuilder<'a> { + $($impl_content)* + } + }; +} + +impl_terms_builder! { + #[allow(unused_mut)] + fn with<ComponentT: Component>(mut self) -> Self { if ComponentT::is_optional() { - //self.optional_components - // .to_mut() - // .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); - return self; } @@ -181,12 +204,28 @@ impl<'a> TermsBuilder<'a> .to_mut() .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); - assert!(self.required_components.is_sorted()); + self + } + + #[allow(unused_mut)] + fn without<ComponentT: Component>(mut self) -> Self + { + if ComponentT::is_optional() { + panic!( + "{}::without cannot take optional component", + type_name::<Self>() + ); + } + + self.excluded_components + .to_mut() + .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); self } - pub fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self + #[allow(unused_mut)] + fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self { if ids.is_empty() { return self; @@ -215,47 +254,56 @@ impl<'a> TermsBuilder<'a> self } +} +impl<'a> TermsBuilder<'a> +{ pub fn build(self) -> Terms<'a> { assert!(self.required_components.is_sorted()); - //assert!(self.optional_components.is_sorted()); + assert!(self.excluded_components.is_sorted()); Terms { required_components: self.required_components, - //optional_components: self.optional_components, + excluded_components: self.excluded_components, } } } -pub trait Term +pub trait TermWithoutField +{ + fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); +} + +pub trait TermWithField { - type Handle<'a>; + type Field<'a>; - fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder; + fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); - fn create_handle<'world>( - get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>, + fn get_field<'world>( + entity_handle: &EntityHandle<'world>, world: &'world World, - ) -> Self::Handle<'world>; + ) -> Self::Field<'world>; } -impl<ComponentRefT: ComponentRef> Term for ComponentRefT +impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT { - type Handle<'a> = ComponentRefT::Handle<'a>; + type Field<'a> = ComponentRefT::Handle<'a>; - fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder + fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>) { - terms_builder.with::<ComponentRefT::Component>() + terms_builder.with::<ComponentRefT::Component>(); } - fn create_handle<'world>( - get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>, + fn get_field<'world>( + entity_handle: &EntityHandle<'world>, world: &'world World, - ) -> Self::Handle<'world> + ) -> Self::Field<'world> { - Self::Handle::from_locked_optional_component( - get_component(ComponentRefT::Component::id()) + Self::Field::from_locked_optional_component( + entity_handle + .get_component(ComponentRefT::Component::id()) .map(|component| &component.component), world, ) @@ -268,32 +316,37 @@ impl<ComponentRefT: ComponentRef> Term for ComponentRefT } } -/// A sequence of references (immutable or mutable) to components. -pub trait TermSequence +pub trait TermWithoutFieldTuple { - type Handles<'component>; + fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); +} + +pub trait TermWithFieldTuple +{ + type Fields<'component>; - fn build_terms() -> Terms<'static>; + fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); - fn from_components<'component>( - get_component: impl Fn(Uid) -> Option<&'component EntityComponent>, + fn get_fields<'component>( + entity_handle: &EntityHandle<'component>, world: &'component World, - ) -> Self::Handles<'component>; + ) -> Self::Fields<'component>; } -pub struct ComponentIter<'query, 'world, Terms, EntityHandleIter> +pub struct ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> where + FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, { world: &'world World, iter: EntityHandleIter, - comps_pd: PhantomData<Terms>, + comps_pd: PhantomData<FieldTerms>, } -impl<'query, 'world, Terms, EntityHandleIter> - ComponentIter<'query, 'world, Terms, EntityHandleIter> +impl<'query, 'world, FieldTerms, EntityHandleIter> + ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> where - Terms: TermSequence + 'world, + FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, 'world: 'query, { @@ -309,47 +362,41 @@ where } } -impl<'query, 'world, Terms, EntityHandleIter> Iterator - for ComponentIter<'query, 'world, Terms, EntityHandleIter> +impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator + for ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> where - Terms: TermSequence + 'world, + FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, 'world: 'query, { - type Item = Terms::Handles<'query>; + type Item = FieldTerms::Fields<'query>; fn next(&mut self) -> Option<Self::Item> { let entity_handle = self.iter.next()?; - Some(Terms::from_components( - |component_uid| { - entity_handle - .components() - .get(entity_handle.get_component_index(component_uid)?) - }, - self.world, - )) + Some(FieldTerms::get_fields(&entity_handle, self.world)) } } -pub struct ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter> +pub struct ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter> where + FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, { world: &'world World, iter: EntityHandleIter, - comps_pd: PhantomData<Terms>, + comps_pd: PhantomData<FieldTerms>, } -impl<'query, 'world, Terms, EntityHandleIter> Iterator - for ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter> +impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator + for ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter> where - Terms: TermSequence + 'world, + FieldTerms: TermWithFieldTuple + 'world, EntityHandleIter: Iterator<Item = EntityHandle<'query>>, 'world: 'query, { - type Item = (Uid, Terms::Handles<'query>); + type Item = (Uid, FieldTerms::Fields<'query>); fn next(&mut self) -> Option<Self::Item> { @@ -357,14 +404,7 @@ where Some(( entity_handle.uid(), - Terms::from_components( - |component_uid| { - entity_handle - .components() - .get(entity_handle.get_component_index(component_uid)?) - }, - self.world, - ), + FieldTerms::get_fields(&entity_handle, self.world), )) } } @@ -372,28 +412,33 @@ where macro_rules! impl_term_sequence { ($c: tt) => { seq!(I in 0..=$c { - impl<#(Term~I: Term,)*> TermSequence for (#(Term~I,)*) + impl<#(Term~I: TermWithoutField,)*> TermWithoutFieldTuple for (#(Term~I,)*) { - type Handles<'component> = (#(Term~I::Handle<'component>,)*); - - fn build_terms() -> Terms<'static> + fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) { - let mut term_builder = Terms::builder(); - #( - term_builder = - Term~I::apply_to_terms_builder(term_builder); + Term~I::apply_to_terms_builder(terms_builder); )* + } + } + + impl<#(Term~I: TermWithField,)*> TermWithFieldTuple for (#(Term~I,)*) + { + type Fields<'component> = (#(Term~I::Field<'component>,)*); - term_builder.build() + fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) + { + #( + Term~I::apply_to_terms_builder(terms_builder); + )* } - fn from_components<'component>( - get_component: impl Fn(Uid) -> Option<&'component EntityComponent>, + fn get_fields<'component>( + entity_handle: &EntityHandle<'component>, world: &'component World, - ) -> Self::Handles<'component> + ) -> Self::Fields<'component> { - (#(Term~I::create_handle(&get_component, world),)*) + (#(Term~I::get_field(entity_handle, world),)*) } } }); @@ -404,19 +449,21 @@ seq!(C in 0..=16 { impl_term_sequence!(C); }); -impl TermSequence for () +impl TermWithoutFieldTuple for () { - type Handles<'component> = (); + fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} +} - fn build_terms() -> Terms<'static> - { - Terms::builder().build() - } +impl TermWithFieldTuple for () +{ + type Fields<'component> = (); + + fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} - fn from_components<'component>( - _get_component: impl Fn(Uid) -> Option<&'component EntityComponent>, + fn get_fields<'component>( + _entity_handle: &EntityHandle<'_>, _world: &'component World, - ) -> Self::Handles<'component> + ) -> Self::Fields<'component> { } } |