diff options
Diffstat (limited to 'ecs/src/query.rs')
| -rw-r--r-- | ecs/src/query.rs | 469 |
1 files changed, 0 insertions, 469 deletions
diff --git a/ecs/src/query.rs b/ecs/src/query.rs deleted file mode 100644 index 1889e00..0000000 --- a/ecs/src/query.rs +++ /dev/null @@ -1,469 +0,0 @@ -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::query::flexible::{ - EntityHandle, - Iter as FlexibleQueryIter, - Query as FlexibleQuery, -}; -use crate::system::{Param as SystemParam, System}; -use crate::uid::Uid; -use crate::util::VecExt; -use crate::World; - -pub mod flexible; -pub mod term; - -#[derive(Debug)] -pub struct Query<'world, FieldTerms, FieldlessTerms = ()> -where - FieldTerms: TermWithFieldTuple, - FieldlessTerms: TermWithoutFieldTuple, -{ - world: &'world World, - inner: FlexibleQuery<'world, 'static>, - _pd: PhantomData<(FieldTerms, FieldlessTerms)>, -} - -impl<'world, FieldTerms, FieldlessTerms> Query<'world, FieldTerms, FieldlessTerms> -where - 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, FieldTerms, FlexibleQueryIter<'query>> - { - tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); - - ComponentIter { - world: self.world, - iter: self.inner.iter(), - comps_pd: PhantomData, - } - } - - /// Iterates over the entities matching this query, the iterator item being the entity - /// [`Uid`] and the entity components. - #[must_use] - pub fn iter_with_euids<'query>( - &'query self, - ) -> ComponentAndEuidIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>> - { - tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); - - ComponentAndEuidIter { - world: self.world, - iter: self.inner.iter(), - comps_pd: PhantomData, - } - } - - /// Iterates over the entities matching this query using the iterator returned by - /// `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`]. - #[must_use] - pub fn iter_with<'query, OutIter>( - &'query self, - func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter, - ) -> ComponentIter<'query, 'world, FieldTerms, OutIter> - where - OutIter: Iterator<Item = EntityHandle<'query>>, - { - tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>()); - - ComponentIter { - world: self.world, - iter: func(self.inner.iter()), - comps_pd: PhantomData, - } - } - - /// Returns the UID of the entity at the given query iteration index. - #[must_use] - pub fn get_entity_uid(&self, entity_index: usize) -> Option<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_builder.build()), - _pd: PhantomData, - } - } -} - -impl<'query, 'world, FieldTerms, FieldlessTerms> IntoIterator - for &'query Query<'world, FieldTerms, FieldlessTerms> -where - FieldTerms: TermWithFieldTuple + 'world, - FieldlessTerms: TermWithoutFieldTuple, -{ - type IntoIter = ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>; - type Item = FieldTerms::Fields<'query>; - - fn into_iter(self) -> Self::IntoIter - { - self.iter() - } -} - -impl<'world, FieldTerms, FieldlessTerms> SystemParam<'world> - for Query<'world, FieldTerms, FieldlessTerms> -where - FieldTerms: TermWithFieldTuple, - FieldlessTerms: TermWithoutFieldTuple, -{ - type Input = (); - - fn initialize<SystemImpl>( - _system: &mut impl System<'world, SystemImpl>, - _input: Self::Input, - ) - { - } - - fn new<SystemImpl>( - _system: &'world impl System<'world, SystemImpl>, - world: &'world World, - ) -> Self - { - Self::new(world) - } -} - -#[derive(Debug)] -pub struct Terms<'a> -{ - required_components: Cow<'a, [Uid]>, - excluded_components: Cow<'a, [Uid]>, -} - -impl<'a> Terms<'a> -{ - pub fn builder() -> TermsBuilder<'a> - { - TermsBuilder::default() - } -} - -#[derive(Debug, Default)] -pub struct TermsBuilder<'a> -{ - required_components: Cow<'a, [Uid]>, - excluded_components: Cow<'a, [Uid]>, -} - -pub trait TermsBuilderInterface<'a> -{ - 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() { - return self; - } - - self.required_components - .to_mut() - .insert_at_partition_point_by_key(ComponentT::id(), |id| *id); - - 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 - } - - #[allow(unused_mut)] - fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self - { - if ids.is_empty() { - return self; - } - - if !ids.is_sorted() { - ids.sort(); - } - - if self.required_components.is_empty() { - self.required_components = Cow::Borrowed(ids); - - return self; - } - - let first_id_pp_index = self.required_components.partition_point(|req_comp_id| { - req_comp_id <= ids.first().expect("Cannot happend since not empty") - }); - - let removed = self - .required_components - .to_mut() - .splice(first_id_pp_index..first_id_pp_index, ids.iter().copied()); - - assert_eq!(removed.count(), 0); - - self - } -} - -impl<'a> TermsBuilder<'a> -{ - pub fn build(self) -> Terms<'a> - { - assert!(self.required_components.is_sorted()); - assert!(self.excluded_components.is_sorted()); - - Terms { - required_components: self.required_components, - excluded_components: self.excluded_components, - } - } -} - -pub trait TermWithoutField -{ - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); -} - -pub trait TermWithField -{ - type Field<'a>; - - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>); - - fn get_field<'world>( - entity_handle: &EntityHandle<'world>, - world: &'world World, - ) -> Self::Field<'world>; -} - -impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT -{ - type Field<'a> = ComponentRefT::Handle<'a>; - - fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>) - { - terms_builder.with::<ComponentRefT::Component>(); - } - - fn get_field<'world>( - entity_handle: &EntityHandle<'world>, - world: &'world World, - ) -> Self::Field<'world> - { - Self::Field::from_locked_optional_component( - entity_handle - .get_component(ComponentRefT::Component::id()) - .map(|component| &component.component), - world, - ) - .unwrap_or_else(|err| { - panic!( - "Taking component {} lock failed: {err}", - type_name::<ComponentRefT::Component>() - ); - }) - } -} - -pub trait TermWithoutFieldTuple -{ - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); -} - -pub trait TermWithFieldTuple -{ - type Fields<'component>; - - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>); - - fn get_fields<'component>( - entity_handle: &EntityHandle<'component>, - world: &'component World, - ) -> Self::Fields<'component>; -} - -pub struct ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> -where - FieldTerms: TermWithFieldTuple + 'world, - EntityHandleIter: Iterator<Item = EntityHandle<'query>>, -{ - world: &'world World, - iter: EntityHandleIter, - comps_pd: PhantomData<FieldTerms>, -} - -impl<'query, 'world, FieldTerms, EntityHandleIter> - ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> -where - FieldTerms: TermWithFieldTuple + 'world, - EntityHandleIter: Iterator<Item = EntityHandle<'query>>, - 'world: 'query, -{ - /// Creates a new iterator from the given entity handle iterator. - /// - /// # Important - /// All of the yielded entities of the entity handle iterator should match the - /// terms `Terms`. The [`Self::next`] function will panic if it encounters a - /// entity that does not match the terms `Terms`. - pub fn new(world: &'world World, iter: EntityHandleIter) -> Self - { - Self { world, iter, comps_pd: PhantomData } - } -} - -impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator - for ComponentIter<'query, 'world, FieldTerms, EntityHandleIter> -where - FieldTerms: TermWithFieldTuple + 'world, - EntityHandleIter: Iterator<Item = EntityHandle<'query>>, - 'world: 'query, -{ - type Item = FieldTerms::Fields<'query>; - - fn next(&mut self) -> Option<Self::Item> - { - let entity_handle = self.iter.next()?; - - Some(FieldTerms::get_fields(&entity_handle, self.world)) - } -} - -pub struct ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter> -where - FieldTerms: TermWithFieldTuple + 'world, - EntityHandleIter: Iterator<Item = EntityHandle<'query>>, -{ - world: &'world World, - iter: EntityHandleIter, - comps_pd: PhantomData<FieldTerms>, -} - -impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator - for ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter> -where - FieldTerms: TermWithFieldTuple + 'world, - EntityHandleIter: Iterator<Item = EntityHandle<'query>>, - 'world: 'query, -{ - type Item = (Uid, FieldTerms::Fields<'query>); - - fn next(&mut self) -> Option<Self::Item> - { - let entity_handle = self.iter.next()?; - - Some(( - entity_handle.uid(), - FieldTerms::get_fields(&entity_handle, self.world), - )) - } -} - -macro_rules! impl_term_sequence { - ($c: tt) => { - seq!(I in 0..=$c { - impl<#(Term~I: TermWithoutField,)*> TermWithoutFieldTuple for (#(Term~I,)*) - { - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) - { - #( - Term~I::apply_to_terms_builder(terms_builder); - )* - } - } - - impl<#(Term~I: TermWithField,)*> TermWithFieldTuple for (#(Term~I,)*) - { - type Fields<'component> = (#(Term~I::Field<'component>,)*); - - fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>) - { - #( - Term~I::apply_to_terms_builder(terms_builder); - )* - } - - fn get_fields<'component>( - entity_handle: &EntityHandle<'component>, - world: &'component World, - ) -> Self::Fields<'component> - { - (#(Term~I::get_field(entity_handle, world),)*) - } - } - }); - }; -} - -seq!(C in 0..=16 { - impl_term_sequence!(C); -}); - -impl TermWithoutFieldTuple for () -{ - fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} -} - -impl TermWithFieldTuple for () -{ - type Fields<'component> = (); - - fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {} - - fn get_fields<'component>( - _entity_handle: &EntityHandle<'_>, - _world: &'component World, - ) -> Self::Fields<'component> - { - } -} |
