use std::marker::PhantomData; use crate::component::RefSequence as ComponentRefSequence; use crate::query::flexible::{ EntityHandle, Iter as FlexibleQueryIter, Query as FlexibleQuery, }; use crate::query::options::Options; use crate::system::{Param as SystemParam, System}; use crate::uid::Uid; use crate::World; pub mod flexible; pub mod options; #[derive(Debug)] pub struct Query<'world, Comps, OptionsT = ()> where Comps: ComponentRefSequence, { world: &'world World, inner: FlexibleQuery<'world, Comps::Metadata>, _pd: PhantomData<(Comps, OptionsT)>, } impl<'world, Comps, OptionsT> Query<'world, Comps, OptionsT> where Comps: ComponentRefSequence, OptionsT: Options, { /// Iterates over the entities matching this query. #[must_use] pub fn iter<'query>( &'query self, ) -> ComponentIter<'query, 'world, Comps, FlexibleQueryIter<'query>> { #[cfg(feature = "debug")] tracing::debug!("Searching for {}", std::any::type_name::()); ComponentIter { 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, Comps, OutIter> where OutIter: Iterator>, { #[cfg(feature = "debug")] tracing::debug!("Searching for {}", std::any::type_name::()); 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 { Some(self.inner.iter::().nth(entity_index)?.uid()) } pub(crate) fn new(world: &'world World) -> Self { Self { world, inner: world.flexible_query(Comps::metadata()), _pd: PhantomData, } } } impl<'query, 'world, Comps, OptionsT> IntoIterator for &'query Query<'world, Comps, OptionsT> where Comps: ComponentRefSequence + 'world, OptionsT: Options, { type IntoIter = ComponentIter<'query, 'world, Comps, FlexibleQueryIter<'query>>; type Item = Comps::Handles<'query>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'world, Comps, OptionsT> SystemParam<'world> for Query<'world, Comps, OptionsT> where Comps: ComponentRefSequence, OptionsT: Options, { type Input = (); fn initialize( _system: &mut impl System<'world, SystemImpl>, _input: Self::Input, ) { } fn new( _system: &'world impl System<'world, SystemImpl>, world: &'world World, ) -> Self { Self::new(world) } } pub struct ComponentIter<'query, 'world, Comps, EntityHandleIter> where EntityHandleIter: Iterator>, { world: &'world World, iter: EntityHandleIter, comps_pd: PhantomData, } impl<'query, 'world, Comps, EntityHandleIter> ComponentIter<'query, 'world, Comps, EntityHandleIter> where Comps: ComponentRefSequence + 'world, EntityHandleIter: Iterator>, 'world: 'query, { pub(crate) fn new(world: &'world World, iter: EntityHandleIter) -> Self { Self { world, iter, comps_pd: PhantomData } } } impl<'query, 'world, Comps, EntityHandleIter> Iterator for ComponentIter<'query, 'world, Comps, EntityHandleIter> where Comps: ComponentRefSequence + 'world, EntityHandleIter: Iterator>, 'world: 'query, { type Item = Comps::Handles<'query>; fn next(&mut self) -> Option { let entity_handle = self.iter.next()?; Some(Comps::from_components( entity_handle.components(), |component_uid| entity_handle.get_component_index(component_uid), self.world, )) } }