diff options
Diffstat (limited to 'ecs/src/query.rs')
-rw-r--r-- | ecs/src/query.rs | 126 |
1 files changed, 79 insertions, 47 deletions
diff --git a/ecs/src/query.rs b/ecs/src/query.rs index d7d2d1c..b29db3d 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -1,5 +1,4 @@ use std::any::type_name; -use std::borrow::Cow; use std::marker::PhantomData; use seq_macro::seq; @@ -9,7 +8,8 @@ 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)* } }; @@ -197,9 +202,11 @@ impl_terms_builder! { 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 } @@ -214,48 +221,51 @@ impl_terms_builder! { ); } + 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; + } - assert_eq!(removed.count(), 0); + self.required_components + .insert(insert_index, id); + + } 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 +279,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 +302,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>(); } @@ -315,14 +331,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 +431,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 +445,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 +472,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<'_>, |