diff options
Diffstat (limited to 'engine-ecs/src/query/flexible.rs')
| -rw-r--r-- | engine-ecs/src/query/flexible.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/engine-ecs/src/query/flexible.rs b/engine-ecs/src/query/flexible.rs new file mode 100644 index 0000000..0198fb4 --- /dev/null +++ b/engine-ecs/src/query/flexible.rs @@ -0,0 +1,101 @@ +//! Low-level querying. +use crate::component::storage::archetype::{Archetype, EntityIter}; +use crate::component::storage::{ArchetypeRefIter, TraversalResult}; +use crate::entity::Handle as EntityHandle; +use crate::query::Terms; +use crate::util::array_vec::ArrayVec; +use crate::World; + +/// Low-level entity query structure. +#[derive(Debug)] +pub struct Query<'world, const TERM_CAP: usize> +{ + world: &'world World, + terms: Terms<TERM_CAP>, +} + +impl<'world, const TERM_CAP: usize> Query<'world, TERM_CAP> +{ + /// Iterates over the entities matching this query. + #[must_use] + pub fn iter<'this>(&'this self) -> Iter<'this, TERM_CAP> + where + 'world: 'this, + { + Iter { + archetype_iter: self + .world + .data + .component_storage + .search_archetypes(&self.terms), + current: None, + world: self.world, + } + } + + #[must_use] + pub fn world(&self) -> &'world World + { + self.world + } + + pub(crate) fn new(world: &'world World, terms: Terms<TERM_CAP>) -> Self + { + Self { world, terms } + } +} + +impl<'query, 'world, const TERM_CAP: usize> IntoIterator + for &'query Query<'world, TERM_CAP> +where + 'world: 'query, +{ + type IntoIter = Iter<'query, TERM_CAP>; + type Item = EntityHandle<'query>; + + fn into_iter(self) -> Self::IntoIter + { + self.iter() + } +} + +pub struct Iter<'query, const TERM_CAP: usize> +{ + archetype_iter: ArchetypeRefIter<'query, 'query, TERM_CAP>, + current: Option<( + &'query Archetype, + ArrayVec<TraversalResult, TERM_CAP>, + EntityIter<'query>, + )>, + world: &'query World, +} + +impl<'query, const TERM_CAP: usize> Iter<'query, TERM_CAP> +{ + pub fn traversal_results(&self) -> Option<&[TraversalResult]> + { + self.current + .as_ref() + .map(|(_, traversal_results, _)| traversal_results.as_ref()) + } +} + +impl<'query, const TERM_CAP: usize> Iterator for Iter<'query, TERM_CAP> +{ + type Item = EntityHandle<'query>; + + fn next(&mut self) -> Option<Self::Item> + { + if let Some((archetype, _, entity_iter)) = self.current.as_mut() { + if let Some(entity) = entity_iter.next() { + return Some(EntityHandle::new(archetype, entity, self.world)); + } + } + + let (archetype, traversal_results) = self.archetype_iter.next()?; + + self.current = Some((archetype, traversal_results, archetype.entities())); + + self.next() + } +} |
