summaryrefslogtreecommitdiff
path: root/ecs/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-03-18 16:59:53 +0100
committerHampusM <hampus@hampusmat.com>2025-03-19 20:24:12 +0100
commit76e7e612e7b516bf52b508ae5bb367b1ddc3babc (patch)
tree1975b4db0eecb74583ab78e58afa50b5326347b2 /ecs/src
parent44cd47fd67102902b649c98b85c5abb9a0da39f8 (diff)
refactor(ecs): replace component::RefSequence with query terms
Diffstat (limited to 'ecs/src')
-rw-r--r--ecs/src/component.rs75
-rw-r--r--ecs/src/component/storage.rs75
-rw-r--r--ecs/src/lib.rs50
-rw-r--r--ecs/src/query.rs295
-rw-r--r--ecs/src/query/flexible.rs46
5 files changed, 309 insertions, 232 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 9257c41..265eb9e 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -13,7 +13,7 @@ use crate::system::Input as SystemInput;
use crate::type_name::TypeName;
use crate::uid::Uid;
use crate::util::Array;
-use crate::{EntityComponent, World};
+use crate::World;
pub mod local;
@@ -170,22 +170,6 @@ pub trait Sequence
fn removed_event_ids() -> Vec<Uid>;
}
-/// A sequence of references (immutable or mutable) to components.
-pub trait RefSequence
-{
- type Handles<'component>;
-
- type Metadata: Array<Metadata>;
-
- fn metadata() -> Self::Metadata;
-
- fn from_components<'component>(
- components: &'component [EntityComponent],
- component_index_lookup: impl Fn(Uid) -> Option<usize>,
- world: &'component World,
- ) -> Self::Handles<'component>;
-}
-
/// A mutable or immutable reference to a component.
pub trait Ref
{
@@ -317,44 +301,6 @@ macro_rules! inner {
]
}
}
-
- impl<#(CompRef~I: Ref,)*> RefSequence for (#(CompRef~I,)*)
- {
- type Handles<'component> = (#(CompRef~I::Handle<'component>,)*);
-
- type Metadata = [Metadata; $c + 1];
-
- fn metadata() -> Self::Metadata
- {
- [#(
- Metadata {
- id: CompRef~I::Component::id(),
- is_optional: CompRef~I::Component::is_optional(),
- },
- )*]
- }
-
- fn from_components<'component>(
- components: &'component [EntityComponent],
- component_index_lookup: impl Fn(Uid) -> Option<usize>,
- world: &'component World,
- ) -> Self::Handles<'component>
- {
- (#(
- CompRef~I::Handle::from_locked_optional_component(
- component_index_lookup(CompRef~I::Component::id())
- .and_then(|component_index| components.get(component_index))
- .map(|component| &component.component),
- world,
- ).unwrap_or_else(|err| {
- panic!(
- "Taking component {} lock failed: {err}",
- type_name::<CompRef~I::Component>()
- );
- }),
- )*)
- }
- }
});
};
}
@@ -390,25 +336,6 @@ impl Sequence for ()
}
}
-impl RefSequence for ()
-{
- type Handles<'component> = ();
- type Metadata = [Metadata; 0];
-
- fn metadata() -> Self::Metadata
- {
- []
- }
-
- fn from_components<'component>(
- _components: &'component [EntityComponent],
- _component_index_lookup: impl Fn(Uid) -> Option<usize>,
- _world: &'component World,
- ) -> Self::Handles<'component>
- {
- }
-}
-
pub trait Into
{
type Component;
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 5b7b101..21f9a37 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -16,7 +16,7 @@ use crate::component::storage::graph::{
ArchetypeEdges,
Graph,
};
-use crate::component::{Component, Metadata as ComponentMetadata};
+use crate::component::Component;
use crate::type_name::TypeName;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::{BorrowedOrOwned, Either, StreamingIterator, VecExt};
@@ -36,12 +36,9 @@ pub struct Storage
impl Storage
{
- pub fn search_archetypes(
- &self,
- component_metadata: &[ComponentMetadata],
- ) -> ArchetypeRefIter<'_>
+ pub fn search_archetypes(&self, component_ids: &[Uid]) -> ArchetypeRefIter<'_>
{
- let archetype_id = ArchetypeId::from_components_metadata(component_metadata);
+ let archetype_id = ArchetypeId::new(&component_ids);
let Some(add_edge_recursive_iter) =
self.graph.dfs_archetype_add_edges(archetype_id)
@@ -50,19 +47,10 @@ impl Storage
.borrow_mut()
.push(ImaginaryArchetype {
id: archetype_id,
- component_ids: component_metadata
- .iter()
- .filter_map(|comp_metadata| {
- if comp_metadata.is_optional {
- return None;
- }
-
- Some(comp_metadata.id)
- })
- .collect::<Vec<_>>(),
+ component_ids: component_ids.to_vec(),
});
- let found_archetypes = self.find_all_archetype_with_comps(component_metadata);
+ let found_archetypes = self.find_all_archetype_with_comps(component_ids);
return ArchetypeRefIter {
storage: self,
@@ -333,16 +321,8 @@ impl Storage
}
}
- fn find_all_archetype_with_comps(
- &self,
- component_metadata: &[ComponentMetadata],
- ) -> Vec<ArchetypeId>
+ fn find_all_archetype_with_comps(&self, component_ids: &[Uid]) -> Vec<ArchetypeId>
{
- let comp_metadata_not_opt_cnt = component_metadata
- .iter()
- .filter(|comp_metadata| !comp_metadata.is_optional)
- .count();
-
let Some(mut search_iter) =
self.graph.dfs_archetype_add_edges(ArchetypeId::new(&[]))
else {
@@ -362,16 +342,13 @@ impl Storage
.get_node_by_id(node_id)
.expect("Graph node found through DFS doesn't exist");
- if node.archetype().component_cnt() < comp_metadata_not_opt_cnt {
+ if node.archetype().component_cnt() < component_ids.len() {
continue;
}
- if !component_metadata
+ if !component_ids
.iter()
- .filter(|comp_metadata| !comp_metadata.is_optional)
- .all(|comp_metadata| {
- node.archetype().has_component_with_id(comp_metadata.id)
- })
+ .all(|comp_id| node.archetype().has_component_with_id(*comp_id))
{
continue;
}
@@ -431,14 +408,12 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
add_edge_archetype_id,
add_edge_component_id,
} => {
- let mut add_edge_archetype_comps = archetype
- .component_ids_sorted()
- .map(|id| ComponentMetadata { id, is_optional: false })
- .collect::<Vec<_>>();
+ let mut add_edge_archetype_comps =
+ archetype.component_ids_sorted().collect::<Vec<_>>();
add_edge_archetype_comps.insert_at_partition_point_by_key(
- ComponentMetadata::new_non_optional(add_edge_component_id),
- |comp_metadata| comp_metadata.id,
+ add_edge_component_id,
+ |comp_id| *comp_id,
);
self.storage.imaginary_archetypes.borrow_mut().push(
@@ -446,7 +421,7 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
id: add_edge_archetype_id,
component_ids: add_edge_archetype_comps
.iter()
- .map(|comp_metadata| comp_metadata.id)
+ .map(|comp_id| *comp_id)
.collect::<Vec<_>>(),
},
);
@@ -457,10 +432,7 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
self.dfs_iter.push((
BorrowedOrOwned::Owned(Archetype::new(
add_edge_archetype_id,
- add_edge_archetype_comps
- .iter()
- .map(|metadata| metadata.id)
- .collect::<Vec<_>>(),
+ add_edge_archetype_comps.clone(),
)),
found.into_iter(),
));
@@ -485,7 +457,7 @@ impl ArchetypeRefIter<'_>
{
fn find_edges_of_imaginary_archetype(
&self,
- imaginary_archetype_comps: &[ComponentMetadata],
+ imaginary_archetype_comps: &[Uid],
) -> Vec<(Uid, ArchetypeEdges)>
{
self.storage
@@ -500,17 +472,16 @@ impl ArchetypeRefIter<'_>
let unique_comp_id = found_archetype
.component_ids_sorted()
- .find(|id| {
- !imaginary_archetype_comps
- .iter()
- .any(|comp_metadata| comp_metadata.id == *id)
+ .find(|found_archetype_comp_id| {
+ !imaginary_archetype_comps.iter().any(
+ |imaginary_archetype_comp_id| {
+ *imaginary_archetype_comp_id == *found_archetype_comp_id
+ },
+ )
})
.expect("Oh noooo");
- let mut add_edge_comp_ids = imaginary_archetype_comps
- .iter()
- .map(|comp_metadata| comp_metadata.id)
- .collect::<Vec<_>>();
+ let mut add_edge_comp_ids = imaginary_archetype_comps.to_vec();
add_edge_comp_ids
.insert_at_partition_point_by_key(unique_comp_id, |id| *id);
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index ad83d1e..cb2059b 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -11,12 +11,7 @@ use hashbrown::HashMap;
use crate::actions::Action;
use crate::component::storage::Storage as ComponentStorage;
-use crate::component::{
- Component,
- Metadata as ComponentMetadata,
- RefSequence as ComponentRefSequence,
- Sequence as ComponentSequence,
-};
+use crate::component::{Component, Sequence as ComponentSequence};
use crate::entity::CREATE_STATIC_ENTITIES;
use crate::event::component::Kind as ComponentEventKind;
use crate::extension::{Collector as ExtensionCollector, Extension};
@@ -24,13 +19,17 @@ use crate::lock::{Lock, WriteGuard};
use crate::phase::{Phase, START as START_PHASE};
use crate::query::flexible::Query as FlexibleQuery;
use crate::query::options::{Not, Options as QueryOptions, With};
+use crate::query::{
+ ComponentIter,
+ TermSequence as QueryTermSequence,
+ Terms as QueryTerms,
+};
use crate::relationship::{ChildOf, DependsOn, Relationship};
use crate::sole::Sole;
use crate::stats::Stats;
use crate::system::{System, SystemComponent};
use crate::type_name::TypeName;
use crate::uid::{Kind as UidKind, Uid};
-use crate::util::Sortable;
pub mod actions;
pub mod component;
@@ -174,22 +173,20 @@ impl World
extension.collect(extension_collector);
}
- pub fn query<Comps, OptionsT>(&self) -> Query<Comps, OptionsT>
+ pub fn query<Terms, OptionsT>(&self) -> Query<Terms, OptionsT>
where
- Comps: ComponentRefSequence,
+ Terms: QueryTermSequence,
OptionsT: QueryOptions,
{
Query::new(self)
}
- pub fn flexible_query<CompMetadata>(
+ pub fn flexible_query<'terms>(
&self,
- comp_metadata: CompMetadata,
- ) -> FlexibleQuery<CompMetadata>
- where
- CompMetadata: Sortable<Item = ComponentMetadata> + AsRef<[ComponentMetadata]>,
+ terms: QueryTerms<'terms>,
+ ) -> FlexibleQuery<'_, 'terms>
{
- FlexibleQuery::new(self, comp_metadata)
+ FlexibleQuery::new(self, terms)
}
/// Performs a single tick.
@@ -482,14 +479,21 @@ impl World
fn emit_event_by_id(&self, event_id: Uid)
{
- let query = self.flexible_query([
- ComponentMetadata::of::<SystemComponent>(),
- ComponentMetadata { id: event_id, is_optional: false },
- ]);
-
- for (system,) in query
- .iter::<()>()
- .into_component_iter::<(&SystemComponent,)>(self)
+ //let query = self.flexible_query([
+ // ComponentMetadata::of::<SystemComponent>(),
+ // ComponentMetadata { id: event_id, is_optional: false },
+ //]);
+
+ let mut query_required_ids = [SystemComponent::id(), event_id];
+
+ let query = self.flexible_query(
+ QueryTerms::builder()
+ .with_required_ids(&mut query_required_ids)
+ .build(),
+ );
+
+ for (system,) in
+ ComponentIter::<(&SystemComponent,), _>::new(self, query.iter::<()>())
{
unsafe {
system.system.run(self);
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index ca9345c..2fcd2cc 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -1,6 +1,10 @@
+use std::any::type_name;
+use std::borrow::Cow;
use std::marker::PhantomData;
-use crate::component::RefSequence as ComponentRefSequence;
+use seq_macro::seq;
+
+use crate::component::{Component, FromLockedOptional, Ref as ComponentRef};
use crate::query::flexible::{
EntityHandle,
Iter as FlexibleQueryIter,
@@ -9,24 +13,25 @@ use crate::query::flexible::{
use crate::query::options::Options;
use crate::system::{Param as SystemParam, System};
use crate::uid::Uid;
-use crate::World;
+use crate::util::VecExt;
+use crate::{EntityComponent, World};
pub mod flexible;
pub mod options;
#[derive(Debug)]
-pub struct Query<'world, Comps, OptionsT = ()>
+pub struct Query<'world, Terms, OptionsT = ()>
where
- Comps: ComponentRefSequence,
+ Terms: TermSequence,
{
world: &'world World,
- inner: FlexibleQuery<'world, Comps::Metadata>,
- _pd: PhantomData<(Comps, OptionsT)>,
+ inner: FlexibleQuery<'world, 'static>,
+ _pd: PhantomData<(Terms, OptionsT)>,
}
-impl<'world, Comps, OptionsT> Query<'world, Comps, OptionsT>
+impl<'world, Terms, OptionsT> Query<'world, Terms, OptionsT>
where
- Comps: ComponentRefSequence,
+ Terms: TermSequence,
OptionsT: Options,
{
/// Iterates over the entities matching this query, the iterator item being the entity
@@ -34,9 +39,9 @@ where
#[must_use]
pub fn iter<'query>(
&'query self,
- ) -> ComponentIter<'query, 'world, Comps, FlexibleQueryIter<'query>>
+ ) -> ComponentIter<'query, 'world, Terms, FlexibleQueryIter<'query>>
{
- tracing::trace!("Searching for {}", std::any::type_name::<Comps>());
+ tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
ComponentIter {
world: self.world,
@@ -50,9 +55,9 @@ where
#[must_use]
pub fn iter_with_euids<'query>(
&'query self,
- ) -> ComponentAndEuidIter<'query, 'world, Comps, FlexibleQueryIter<'query>>
+ ) -> ComponentAndEuidIter<'query, 'world, Terms, FlexibleQueryIter<'query>>
{
- tracing::trace!("Searching for {}", std::any::type_name::<Comps>());
+ tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
ComponentAndEuidIter {
world: self.world,
@@ -70,11 +75,11 @@ where
pub fn iter_with<'query, OutIter>(
&'query self,
func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter,
- ) -> ComponentIter<'query, 'world, Comps, OutIter>
+ ) -> ComponentIter<'query, 'world, Terms, OutIter>
where
OutIter: Iterator<Item = EntityHandle<'query>>,
{
- tracing::trace!("Searching for {}", std::any::type_name::<Comps>());
+ tracing::trace!("Searching for {}", std::any::type_name::<Terms>());
ComponentIter {
world: self.world,
@@ -94,20 +99,20 @@ where
{
Self {
world,
- inner: world.flexible_query(Comps::metadata()),
+ inner: world.flexible_query(Terms::build_terms()),
_pd: PhantomData,
}
}
}
-impl<'query, 'world, Comps, OptionsT> IntoIterator
- for &'query Query<'world, Comps, OptionsT>
+impl<'query, 'world, Terms, OptionsT> IntoIterator
+ for &'query Query<'world, Terms, OptionsT>
where
- Comps: ComponentRefSequence + 'world,
+ Terms: TermSequence + 'world,
OptionsT: Options,
{
- type IntoIter = ComponentIter<'query, 'world, Comps, FlexibleQueryIter<'query>>;
- type Item = Comps::Handles<'query>;
+ type IntoIter = ComponentIter<'query, 'world, Terms, FlexibleQueryIter<'query>>;
+ type Item = Terms::Handles<'query>;
fn into_iter(self) -> Self::IntoIter
{
@@ -115,9 +120,9 @@ where
}
}
-impl<'world, Comps, OptionsT> SystemParam<'world> for Query<'world, Comps, OptionsT>
+impl<'world, Terms, OptionsT> SystemParam<'world> for Query<'world, Terms, OptionsT>
where
- Comps: ComponentRefSequence,
+ Terms: TermSequence,
OptionsT: Options,
{
type Input = ();
@@ -138,66 +143,213 @@ where
}
}
-pub struct ComponentIter<'query, 'world, Comps, EntityHandleIter>
+#[derive(Debug)]
+pub struct Terms<'a>
+{
+ required_components: Cow<'a, [Uid]>,
+ //optional_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]>,
+ //optional_components: Cow<'a, [Uid]>,
+}
+
+impl<'a> TermsBuilder<'a>
+{
+ pub 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;
+ }
+
+ self.required_components
+ .to_mut()
+ .insert_at_partition_point_by_key(ComponentT::id(), |id| *id);
+
+ assert!(self.required_components.is_sorted());
+
+ self
+ }
+
+ pub 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
+ }
+
+ pub fn build(self) -> Terms<'a>
+ {
+ assert!(self.required_components.is_sorted());
+ //assert!(self.optional_components.is_sorted());
+
+ Terms {
+ required_components: self.required_components,
+ //optional_components: self.optional_components,
+ }
+ }
+}
+
+pub trait Term
+{
+ type Handle<'a>;
+
+ fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder;
+
+ fn create_handle<'world>(
+ get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>,
+ world: &'world World,
+ ) -> Self::Handle<'world>;
+}
+
+impl<ComponentRefT: ComponentRef> Term for ComponentRefT
+{
+ type Handle<'a> = ComponentRefT::Handle<'a>;
+
+ fn apply_to_terms_builder(terms_builder: TermsBuilder) -> TermsBuilder
+ {
+ terms_builder.with::<ComponentRefT::Component>()
+ }
+
+ fn create_handle<'world>(
+ get_component: &impl Fn(Uid) -> Option<&'world EntityComponent>,
+ world: &'world World,
+ ) -> Self::Handle<'world>
+ {
+ Self::Handle::from_locked_optional_component(
+ get_component(ComponentRefT::Component::id())
+ .map(|component| &component.component),
+ world,
+ )
+ .unwrap_or_else(|err| {
+ panic!(
+ "Taking component {} lock failed: {err}",
+ type_name::<ComponentRefT::Component>()
+ );
+ })
+ }
+}
+
+/// A sequence of references (immutable or mutable) to components.
+pub trait TermSequence
+{
+ type Handles<'component>;
+
+ fn build_terms() -> Terms<'static>;
+
+ fn from_components<'component>(
+ get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ world: &'component World,
+ ) -> Self::Handles<'component>;
+}
+
+pub struct ComponentIter<'query, 'world, Terms, EntityHandleIter>
where
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
{
world: &'world World,
iter: EntityHandleIter,
- comps_pd: PhantomData<Comps>,
+ comps_pd: PhantomData<Terms>,
}
-impl<'query, 'world, Comps, EntityHandleIter>
- ComponentIter<'query, 'world, Comps, EntityHandleIter>
+impl<'query, 'world, Terms, EntityHandleIter>
+ ComponentIter<'query, 'world, Terms, EntityHandleIter>
where
- Comps: ComponentRefSequence + 'world,
+ Terms: TermSequence + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
- pub(crate) fn new(world: &'world World, iter: EntityHandleIter) -> Self
+ /// 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, Comps, EntityHandleIter> Iterator
- for ComponentIter<'query, 'world, Comps, EntityHandleIter>
+impl<'query, 'world, Terms, EntityHandleIter> Iterator
+ for ComponentIter<'query, 'world, Terms, EntityHandleIter>
where
- Comps: ComponentRefSequence + 'world,
+ Terms: TermSequence + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
- type Item = Comps::Handles<'query>;
+ type Item = Terms::Handles<'query>;
fn next(&mut self) -> Option<Self::Item>
{
let entity_handle = self.iter.next()?;
- Some(Comps::from_components(
- entity_handle.components(),
- |component_uid| entity_handle.get_component_index(component_uid),
+ Some(Terms::from_components(
+ |component_uid| {
+ entity_handle
+ .components()
+ .get(entity_handle.get_component_index(component_uid)?)
+ },
self.world,
))
}
}
-pub struct ComponentAndEuidIter<'query, 'world, Comps, EntityHandleIter>
+pub struct ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter>
where
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
{
world: &'world World,
iter: EntityHandleIter,
- comps_pd: PhantomData<Comps>,
+ comps_pd: PhantomData<Terms>,
}
-impl<'query, 'world, Comps, EntityHandleIter> Iterator
- for ComponentAndEuidIter<'query, 'world, Comps, EntityHandleIter>
+impl<'query, 'world, Terms, EntityHandleIter> Iterator
+ for ComponentAndEuidIter<'query, 'world, Terms, EntityHandleIter>
where
- Comps: ComponentRefSequence + 'world,
+ Terms: TermSequence + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
'world: 'query,
{
- type Item = (Uid, Comps::Handles<'query>);
+ type Item = (Uid, Terms::Handles<'query>);
fn next(&mut self) -> Option<Self::Item>
{
@@ -205,11 +357,66 @@ where
Some((
entity_handle.uid(),
- Comps::from_components(
- entity_handle.components(),
- |component_uid| entity_handle.get_component_index(component_uid),
+ Terms::from_components(
+ |component_uid| {
+ entity_handle
+ .components()
+ .get(entity_handle.get_component_index(component_uid)?)
+ },
self.world,
),
))
}
}
+
+macro_rules! impl_term_sequence {
+ ($c: tt) => {
+ seq!(I in 0..=$c {
+ impl<#(Term~I: Term,)*> TermSequence for (#(Term~I,)*)
+ {
+ type Handles<'component> = (#(Term~I::Handle<'component>,)*);
+
+ fn build_terms() -> Terms<'static>
+ {
+ let mut term_builder = Terms::builder();
+
+ #(
+ term_builder =
+ Term~I::apply_to_terms_builder(term_builder);
+ )*
+
+ term_builder.build()
+ }
+
+ fn from_components<'component>(
+ get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ world: &'component World,
+ ) -> Self::Handles<'component>
+ {
+ (#(Term~I::create_handle(&get_component, world),)*)
+ }
+ }
+ });
+ };
+}
+
+seq!(C in 0..=16 {
+ impl_term_sequence!(C);
+});
+
+impl TermSequence for ()
+{
+ type Handles<'component> = ();
+
+ fn build_terms() -> Terms<'static>
+ {
+ Terms::builder().build()
+ }
+
+ fn from_components<'component>(
+ _get_component: impl Fn(Uid) -> Option<&'component EntityComponent>,
+ _world: &'component World,
+ ) -> Self::Handles<'component>
+ {
+ }
+}
diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs
index c42ec25..a3e8701 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -3,30 +3,21 @@ use std::iter::{repeat_n, Filter, FlatMap, RepeatN, Zip};
use crate::component::storage::archetype::{Archetype, ArchetypeEntity, EntityIter};
use crate::component::storage::{ArchetypeRefIter, Storage as ComponentStorage};
-use crate::component::{
- Metadata as ComponentMetadata,
- RefSequence as ComponentRefSequence,
-};
use crate::lock::ReadGuard;
use crate::query::options::Options;
-use crate::query::ComponentIter;
+use crate::query::Terms;
use crate::uid::Uid;
-use crate::util::Sortable;
use crate::{EntityComponent, World};
/// Low-level entity query structure.
#[derive(Debug)]
-pub struct Query<'world, CompMetadata>
-where
- CompMetadata: Sortable<Item = ComponentMetadata> + AsRef<[ComponentMetadata]>,
+pub struct Query<'world, 'terms>
{
component_storage: ReadGuard<'world, ComponentStorage>,
- comp_metadata: CompMetadata,
+ terms: Terms<'terms>,
}
-impl<'world, CompMetadata> Query<'world, CompMetadata>
-where
- CompMetadata: Sortable<Item = ComponentMetadata> + AsRef<[ComponentMetadata]>,
+impl<'world, 'terms> Query<'world, 'terms>
{
/// Iterates over the entities matching this query.
#[must_use]
@@ -35,7 +26,7 @@ where
Iter {
iter: self
.component_storage
- .search_archetypes(self.comp_metadata.as_ref())
+ .search_archetypes(self.terms.required_components.as_ref())
.flat_map(
(|archetype| {
repeat_n(archetype, archetype.entity_cnt())
@@ -46,17 +37,15 @@ where
}
}
- pub(crate) fn new(world: &'world World, mut comp_metadata: CompMetadata) -> Self
+ pub(crate) fn new(world: &'world World, terms: Terms<'terms>) -> Self
{
- comp_metadata.sort_by_key_b(|metadata| metadata.id);
-
Self {
component_storage: world
.data
.component_storage
.read_nonblock()
.expect("Failed to acquire read-only component storage lock"),
- comp_metadata,
+ terms,
}
}
}
@@ -66,27 +55,6 @@ pub struct Iter<'query>
iter: QueryEntityIter<'query>,
}
-impl<'query> Iter<'query>
-{
- /// Converts this iterator into a [`ComponentIter`].
- ///
- /// Note: The matching entities of this iterator should have all of the non-[`Option`]
- /// components in `Comps`, otherwise iterating the [`ComponentIter`] will cause a
- /// panic.
- #[must_use]
- #[inline]
- pub fn into_component_iter<'world, Comps>(
- self,
- world: &'world World,
- ) -> ComponentIter<'query, 'world, Comps, Self>
- where
- Comps: ComponentRefSequence + 'world,
- 'world: 'query,
- {
- ComponentIter::new(world, self)
- }
-}
-
impl<'query> Iterator for Iter<'query>
{
type Item = EntityHandle<'query>;