From b3105bc6681f2b42a78ff49c593d01d7cc5dbe62 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Fri, 8 Mar 2024 00:19:23 -0500 Subject: [PATCH] ecs: fix filters --- lyra-ecs/src/query/borrow.rs | 4 +-- lyra-ecs/src/query/filter/has_component.rs | 40 ++++++++++++++++++++++ lyra-ecs/src/query/filter/mod.rs | 5 +++ lyra-ecs/src/query/filter/or.rs | 40 ++++++++++++++++++++++ lyra-ecs/src/query/mod.rs | 2 ++ lyra-ecs/src/query/view.rs | 2 +- lyra-ecs/src/world.rs | 7 ++++ 7 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 lyra-ecs/src/query/filter/has_component.rs create mode 100644 lyra-ecs/src/query/filter/mod.rs create mode 100644 lyra-ecs/src/query/filter/or.rs diff --git a/lyra-ecs/src/query/borrow.rs b/lyra-ecs/src/query/borrow.rs index d5a1493..989e72c 100644 --- a/lyra-ecs/src/query/borrow.rs +++ b/lyra-ecs/src/query/borrow.rs @@ -177,10 +177,10 @@ where unsafe fn fetch<'a>(&self, _world: &'a World, archetype: &'a crate::archetype::Archetype, tick: crate::Tick) -> Self::Fetch<'a> { let col = archetype.get_column(self.type_id) .expect("You ignored 'can_visit_archetype'!"); - let col = NonNull::from(col); - + // TODO: find a way to get the component column mutable with a borrowed archetype so its tick can be updated. // the fetcher needs to tick the entities tick in the archetype + let col = NonNull::from(col); FetchBorrowMut { col, diff --git a/lyra-ecs/src/query/filter/has_component.rs b/lyra-ecs/src/query/filter/has_component.rs new file mode 100644 index 0000000..1ef455a --- /dev/null +++ b/lyra-ecs/src/query/filter/has_component.rs @@ -0,0 +1,40 @@ +use std::marker::PhantomData; + +use crate::{query::{AsQuery, Query}, Archetype, Component, DynTypeId, World}; + +#[derive(Default)] +pub struct Has { + _marker: PhantomData +} + +impl Copy for Has {} + +impl Clone for Has { + fn clone(&self) -> Self { + Self { _marker: self._marker.clone() } + } +} + +impl Query for Has { + type Item<'a> = (); + + type Fetch<'a> = (); + + fn new() -> Self { + Has { + _marker: PhantomData + } + } + + fn can_visit_archetype(&self, archetype: &Archetype) -> bool { + archetype.has_column(DynTypeId::of::()) + } + + unsafe fn fetch<'a>(&self, _world: &'a World, _: &'a Archetype, _: crate::Tick) -> Self::Fetch<'a> { + () + } +} + +impl AsQuery for Has { + type Query = Self; +} \ No newline at end of file diff --git a/lyra-ecs/src/query/filter/mod.rs b/lyra-ecs/src/query/filter/mod.rs new file mode 100644 index 0000000..149de6d --- /dev/null +++ b/lyra-ecs/src/query/filter/mod.rs @@ -0,0 +1,5 @@ +pub mod has_component; +pub use has_component::*; + +pub mod or; +pub use or::*; \ No newline at end of file diff --git a/lyra-ecs/src/query/filter/or.rs b/lyra-ecs/src/query/filter/or.rs new file mode 100644 index 0000000..c76d9d8 --- /dev/null +++ b/lyra-ecs/src/query/filter/or.rs @@ -0,0 +1,40 @@ +use crate::{query::{AsQuery, Query}, Archetype, World}; + +#[derive(Default)] +pub struct Or { + left: Q1::Query, + right: Q2::Query, +} + +impl Copy for Or {} + +impl Clone for Or { + fn clone(&self) -> Self { + Self { left: self.left.clone(), right: self.right.clone() } + } +} + +impl Query for Or { + type Item<'a> = (); + + type Fetch<'a> = (); + + fn new() -> Self { + Or { + left: Q1::Query::new(), + right: Q2::Query::new(), + } + } + + fn can_visit_archetype(&self, archetype: &Archetype) -> bool { + self.left.can_visit_archetype(archetype) || self.right.can_visit_archetype(archetype) + } + + unsafe fn fetch<'a>(&self, _world: &'a World, _: &'a Archetype, _: crate::Tick) -> Self::Fetch<'a> { + () + } +} + +impl AsQuery for Or { + type Query = Self; +} \ No newline at end of file diff --git a/lyra-ecs/src/query/mod.rs b/lyra-ecs/src/query/mod.rs index a71e5c8..8738608 100644 --- a/lyra-ecs/src/query/mod.rs +++ b/lyra-ecs/src/query/mod.rs @@ -29,6 +29,8 @@ pub use world::*; pub mod dynamic; +pub mod filter; + /// A [`Fetch`]er implementation gets data out of an archetype. pub trait Fetch<'a> { /// The type that this Fetch yields diff --git a/lyra-ecs/src/query/view.rs b/lyra-ecs/src/query/view.rs index 93c67a0..d212295 100644 --- a/lyra-ecs/src/query/view.rs +++ b/lyra-ecs/src/query/view.rs @@ -90,7 +90,7 @@ where fn next(&mut self) -> Option { loop { - if Q::ALWAYS_FETCHES && F::ALWAYS_FETCHES { + if Q::ALWAYS_FETCHES { // only fetch this query once. // fetcher gets set to Some after this `next` call. if self.fetcher.is_none() { diff --git a/lyra-ecs/src/world.rs b/lyra-ecs/src/world.rs index 5965898..31abb31 100644 --- a/lyra-ecs/src/world.rs +++ b/lyra-ecs/src/world.rs @@ -254,6 +254,13 @@ impl World { v.into_iter() } + /// View into the world for a set of entities that satisfy the queries. + pub fn filtered_view_iter(&self) -> ViewIter { + let archetypes = self.archetypes.values().collect(); + let v = ViewState::new(self, Q::Query::new(), F::Query::new(), archetypes); + v.into_iter() + } + pub fn dynamic_view(&self) -> DynamicView { DynamicView::new(self) }