summaryrefslogtreecommitdiff
path: root/ecs/src/query.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/query.rs')
-rw-r--r--ecs/src/query.rs279
1 files changed, 163 insertions, 116 deletions
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index 2fcd2cc..1889e00 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -10,42 +10,42 @@ use crate::query::flexible::{
Iter as FlexibleQueryIter,
Query as FlexibleQuery,
};
-use crate::query::options::Options;
use crate::system::{Param as SystemParam, System};
use crate::uid::Uid;
use crate::util::VecExt;
-use crate::{EntityComponent, World};
+use crate::World;
pub mod flexible;
-pub mod options;
+pub mod term;
#[derive(Debug)]
-pub struct Query<'world, Terms, OptionsT = ()>
+pub struct Query<'world, FieldTerms, FieldlessTerms = ()>
where
- Terms: TermSequence,
+ FieldTerms: TermWithFieldTuple,
+ FieldlessTerms: TermWithoutFieldTuple,
{
world: &'world World,
inner: FlexibleQuery<'world, 'static>,
- _pd: PhantomData<(Terms, OptionsT)>,
+ _pd: PhantomData<(FieldTerms, FieldlessTerms)>,
}
-impl<'world, Terms, OptionsT> Query<'world, Terms, OptionsT>
+impl<'world, FieldTerms, FieldlessTerms> Query<'world, FieldTerms, FieldlessTerms>
where
- Terms: TermSequence,
- OptionsT: Options,
+ 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, Terms, FlexibleQueryIter<'query>>
+ ) -> ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>
{
- tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
+ tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>());
ComponentIter {
world: self.world,
- iter: self.inner.iter::<OptionsT>(),
+ iter: self.inner.iter(),
comps_pd: PhantomData,
}
}
@@ -55,13 +55,13 @@ where
#[must_use]
pub fn iter_with_euids<'query>(
&'query self,
- ) -> ComponentAndEuidIter<'query, 'world, Terms, FlexibleQueryIter<'query>>
+ ) -> ComponentAndEuidIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>
{
- tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
+ tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>());
ComponentAndEuidIter {
world: self.world,
- iter: self.inner.iter::<OptionsT>(),
+ iter: self.inner.iter(),
comps_pd: PhantomData,
}
}
@@ -75,15 +75,15 @@ where
pub fn iter_with<'query, OutIter>(
&'query self,
func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter,
- ) -> ComponentIter<'query, 'world, Terms, OutIter>
+ ) -> ComponentIter<'query, 'world, FieldTerms, OutIter>
where
OutIter: Iterator<Item = EntityHandle<'query>>,
{
- tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
+ tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>());
ComponentIter {
world: self.world,
- iter: func(self.inner.iter::<OptionsT>()),
+ iter: func(self.inner.iter()),
comps_pd: PhantomData,
}
}
@@ -92,27 +92,32 @@ where
#[must_use]
pub fn get_entity_uid(&self, entity_index: usize) -> Option<Uid>
{
- Some(self.inner.iter::<OptionsT>().nth(entity_index)?.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::build_terms()),
+ inner: world.flexible_query(terms_builder.build()),
_pd: PhantomData,
}
}
}
-impl<'query, 'world, Terms, OptionsT> IntoIterator
- for &'query Query<'world, Terms, OptionsT>
+impl<'query, 'world, FieldTerms, FieldlessTerms> IntoIterator
+ for &'query Query<'world, FieldTerms, FieldlessTerms>
where
- Terms: TermSequence + 'world,
- OptionsT: Options,
+ FieldTerms: TermWithFieldTuple + 'world,
+ FieldlessTerms: TermWithoutFieldTuple,
{
- type IntoIter = ComponentIter<'query, 'world, Terms, FlexibleQueryIter<'query>>;
- type Item = Terms::Handles<'query>;
+ type IntoIter = ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>;
+ type Item = FieldTerms::Fields<'query>;
fn into_iter(self) -> Self::IntoIter
{
@@ -120,10 +125,11 @@ where
}
}
-impl<'world, Terms, OptionsT> SystemParam<'world> for Query<'world, Terms, OptionsT>
+impl<'world, FieldTerms, FieldlessTerms> SystemParam<'world>
+ for Query<'world, FieldTerms, FieldlessTerms>
where
- Terms: TermSequence,
- OptionsT: Options,
+ FieldTerms: TermWithFieldTuple,
+ FieldlessTerms: TermWithoutFieldTuple,
{
type Input = ();
@@ -147,7 +153,7 @@ where
pub struct Terms<'a>
{
required_components: Cow<'a, [Uid]>,
- //optional_components: Cow<'a, [Uid]>,
+ excluded_components: Cow<'a, [Uid]>,
}
impl<'a> Terms<'a>
@@ -162,18 +168,35 @@ impl<'a> Terms<'a>
pub struct TermsBuilder<'a>
{
required_components: Cow<'a, [Uid]>,
- //optional_components: Cow<'a, [Uid]>,
+ excluded_components: Cow<'a, [Uid]>,
}
-impl<'a> TermsBuilder<'a>
+pub trait TermsBuilderInterface<'a>
{
- pub fn with<ComponentT: Component>(mut self) -> Self
+ 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() {
- //self.optional_components
- // .to_mut()
- // .insert_at_partition_point_by_key(ComponentT::id(), |id| *id);
-
return self;
}
@@ -181,12 +204,28 @@ impl<'a> TermsBuilder<'a>
.to_mut()
.insert_at_partition_point_by_key(ComponentT::id(), |id| *id);
- assert!(self.required_components.is_sorted());
+ 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
}
- pub fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self
+ #[allow(unused_mut)]
+ fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self
{
if ids.is_empty() {
return self;
@@ -215,47 +254,56 @@ impl<'a> TermsBuilder<'a>
self
}
+}
+impl<'a> TermsBuilder<'a>
+{
pub fn build(self) -> Terms<'a>
{
assert!(self.required_components.is_sorted());
- //assert!(self.optional_components.is_sorted());
+ assert!(self.excluded_components.is_sorted());
Terms {
required_components: self.required_components,
- //optional_components: self.optional_components,
+ excluded_components: self.excluded_components,
}
}
}
-pub trait Term
+pub trait TermWithoutField
+{
+ fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>);
+}
+
+pub trait TermWithField
{
- type Handle<'a>;
+ type Field<'a>;
- fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder;
+ fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>);
- fn create_handle<'world>(
- get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>,
+ fn get_field<'world>(
+ entity_handle: &EntityHandle<'world>,
world: &'world World,
- ) -> Self::Handle<'world>;
+ ) -> Self::Field<'world>;
}
-impl<ComponentRefT: ComponentRef> Term for ComponentRefT
+impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT
{
- type Handle<'a> = ComponentRefT::Handle<'a>;
+ type Field<'a> = ComponentRefT::Handle<'a>;
- fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder
+ fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
{
- terms_builder.with::<ComponentRefT::Component>()
+ terms_builder.with::<ComponentRefT::Component>();
}
- fn create_handle<'world>(
- get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>,
+ fn get_field<'world>(
+ entity_handle: &EntityHandle<'world>,
world: &'world World,
- ) -> Self::Handle<'world>
+ ) -> Self::Field<'world>
{
- Self::Handle::from_locked_optional_component(
- get_component(ComponentRefT::Component::id())
+ Self::Field::from_locked_optional_component(
+ entity_handle
+ .get_component(ComponentRefT::Component::id())
.map(|component| &component.component),
world,
)
@@ -268,32 +316,37 @@ impl<ComponentRefT: ComponentRef> Term for ComponentRefT
}
}
-/// A sequence of references (immutable or mutable) to components.
-pub trait TermSequence
+pub trait TermWithoutFieldTuple
{
- type Handles<'component>;
+ fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>);
+}
+
+pub trait TermWithFieldTuple
+{
+ type Fields<'component>;
- fn build_terms() -> Terms<'static>;
+ fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>);
- fn from_components<'component>(
- get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ fn get_fields<'component>(
+ entity_handle: &EntityHandle<'component>,
world: &'component World,
- ) -> Self::Handles<'component>;
+ ) -> Self::Fields<'component>;
}
-pub struct ComponentIter<'query, 'world, Terms, EntityHandleIter>
+pub struct ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
where
+ FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
{
world: &'world World,
iter: EntityHandleIter,
- comps_pd: PhantomData<Terms>,
+ comps_pd: PhantomData<FieldTerms>,
}
-impl<'query, 'world, Terms, EntityHandleIter>
- ComponentIter<'query, 'world, Terms, EntityHandleIter>
+impl<'query, 'world, FieldTerms, EntityHandleIter>
+ ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
where
- Terms: TermSequence + 'world,
+ FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
@@ -309,47 +362,41 @@ where
}
}
-impl<'query, 'world, Terms, EntityHandleIter> Iterator
- for ComponentIter<'query, 'world, Terms, EntityHandleIter>
+impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator
+ for ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
where
- Terms: TermSequence + 'world,
+ FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
- type Item = Terms::Handles<'query>;
+ type Item = FieldTerms::Fields<'query>;
fn next(&mut self) -> Option<Self::Item>
{
let entity_handle = self.iter.next()?;
- Some(Terms::from_components(
- |component_uid| {
- entity_handle
- .components()
- .get(entity_handle.get_component_index(component_uid)?)
- },
- self.world,
- ))
+ Some(FieldTerms::get_fields(&entity_handle, self.world))
}
}
-pub struct ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter>
+pub struct ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter>
where
+ FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
{
world: &'world World,
iter: EntityHandleIter,
- comps_pd: PhantomData<Terms>,
+ comps_pd: PhantomData<FieldTerms>,
}
-impl<'query, 'world, Terms, EntityHandleIter> Iterator
- for ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter>
+impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator
+ for ComponentAndEuidIter<'query, 'world, FieldTerms, EntityHandleIter>
where
- Terms: TermSequence + 'world,
+ FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
- type Item = (Uid, Terms::Handles<'query>);
+ type Item = (Uid, FieldTerms::Fields<'query>);
fn next(&mut self) -> Option<Self::Item>
{
@@ -357,14 +404,7 @@ where
Some((
entity_handle.uid(),
- Terms::from_components(
- |component_uid| {
- entity_handle
- .components()
- .get(entity_handle.get_component_index(component_uid)?)
- },
- self.world,
- ),
+ FieldTerms::get_fields(&entity_handle, self.world),
))
}
}
@@ -372,28 +412,33 @@ where
macro_rules! impl_term_sequence {
($c: tt) => {
seq!(I in 0..=$c {
- impl<#(Term~I: Term,)*> TermSequence for (#(Term~I,)*)
+ impl<#(Term~I: TermWithoutField,)*> TermWithoutFieldTuple for (#(Term~I,)*)
{
- type Handles<'component> = (#(Term~I::Handle<'component>,)*);
-
- fn build_terms() -> Terms<'static>
+ fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>)
{
- let mut term_builder = Terms::builder();
-
#(
- term_builder =
- Term~I::apply_to_terms_builder(term_builder);
+ Term~I::apply_to_terms_builder(terms_builder);
)*
+ }
+ }
+
+ impl<#(Term~I: TermWithField,)*> TermWithFieldTuple for (#(Term~I,)*)
+ {
+ type Fields<'component> = (#(Term~I::Field<'component>,)*);
- term_builder.build()
+ fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>)
+ {
+ #(
+ Term~I::apply_to_terms_builder(terms_builder);
+ )*
}
- fn from_components<'component>(
- get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ fn get_fields<'component>(
+ entity_handle: &EntityHandle<'component>,
world: &'component World,
- ) -> Self::Handles<'component>
+ ) -> Self::Fields<'component>
{
- (#(Term~I::create_handle(&get_component, world),)*)
+ (#(Term~I::get_field(entity_handle, world),)*)
}
}
});
@@ -404,19 +449,21 @@ seq!(C in 0..=16 {
impl_term_sequence!(C);
});
-impl TermSequence for ()
+impl TermWithoutFieldTuple for ()
{
- type Handles<'component> = ();
+ fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {}
+}
- fn build_terms() -> Terms<'static>
- {
- Terms::builder().build()
- }
+impl TermWithFieldTuple for ()
+{
+ type Fields<'component> = ();
+
+ fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {}
- fn from_components<'component>(
- _get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ fn get_fields<'component>(
+ _entity_handle: &EntityHandle<'_>,
_world: &'component World,
- ) -> Self::Handles<'component>
+ ) -> Self::Fields<'component>
{
}
}