summaryrefslogtreecommitdiff
path: root/ecs/src/query
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/query')
-rw-r--r--ecs/src/query/flexible.rs39
-rw-r--r--ecs/src/query/term.rs109
2 files changed, 113 insertions, 35 deletions
diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs
index 652b96f..add30b0 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -2,25 +2,20 @@
use std::iter::{repeat_n, FlatMap, RepeatN, Zip};
use crate::component::storage::archetype::{Archetype, EntityIter};
-use crate::component::storage::{
- ArchetypeRefIter,
- ArchetypeSearchTerms,
- Storage as ComponentStorage,
-};
+use crate::component::storage::{ArchetypeRefIter, ArchetypeSearchTerms};
use crate::entity::Handle as EntityHandle;
-use crate::lock::ReadGuard;
use crate::query::Terms;
use crate::World;
/// Low-level entity query structure.
#[derive(Debug)]
-pub struct Query<'world, 'terms>
+pub struct Query<'world, const MAX_TERM_CNT: usize>
{
- component_storage: ReadGuard<'world, ComponentStorage>,
- terms: Terms<'terms>,
+ world: &'world World,
+ terms: Terms<MAX_TERM_CNT>,
}
-impl<'world, 'terms> Query<'world, 'terms>
+impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>
{
/// Iterates over the entities matching this query.
#[must_use]
@@ -28,6 +23,8 @@ impl<'world, 'terms> Query<'world, 'terms>
{
Iter {
iter: self
+ .world
+ .data
.component_storage
.search_archetypes(ArchetypeSearchTerms {
required_components: &self.terms.required_components,
@@ -42,16 +39,20 @@ impl<'world, 'terms> Query<'world, 'terms>
}
}
- pub(crate) fn new(world: &'world World, terms: Terms<'terms>) -> Self
+ pub(crate) fn new(world: &'world World, terms: Terms<MAX_TERM_CNT>) -> Self
{
- Self {
- component_storage: world
- .data
- .component_storage
- .read_nonblock()
- .expect("Failed to acquire read-only component storage lock"),
- terms,
- }
+ Self { world, terms }
+ }
+}
+
+impl<'query, const MAX_TERM_CNT: usize> IntoIterator for &'query Query<'_, MAX_TERM_CNT>
+{
+ type IntoIter = Iter<'query>;
+ type Item = EntityHandle<'query>;
+
+ fn into_iter(self) -> Self::IntoIter
+ {
+ self.iter()
}
}
diff --git a/ecs/src/query/term.rs b/ecs/src/query/term.rs
index 7f24147..9c772da 100644
--- a/ecs/src/query/term.rs
+++ b/ecs/src/query/term.rs
@@ -1,38 +1,115 @@
+use std::any::type_name;
use std::marker::PhantomData;
-use crate::component::Component;
-use crate::query::{TermWithoutField, TermsBuilder, TermsBuilderInterface};
+use crate::component::{
+ Component,
+ Handle as ComponentHandle,
+ HandleMut as ComponentHandleMut,
+};
+use crate::query::{
+ TermWithField,
+ TermWithoutField,
+ TermsBuilder,
+ TermsBuilderInterface,
+};
+use crate::uid::With as WithUid;
-pub struct With<ComponentT>
+pub struct With<WithUidT>
where
- ComponentT: Component,
+ WithUidT: WithUid,
{
- _pd: PhantomData<ComponentT>,
+ _pd: PhantomData<WithUidT>,
}
-impl<ComponentT> TermWithoutField for With<ComponentT>
+impl<WithUidT> TermWithoutField for With<WithUidT>
where
- ComponentT: Component,
+ WithUidT: WithUid,
{
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
{
- terms_builder.with::<ComponentT>();
+ terms_builder.with::<WithUidT>();
}
}
-pub struct Without<ComponentT>
+pub struct Without<WithUidT>
where
- ComponentT: Component,
+ WithUidT: WithUid,
{
- _pd: PhantomData<ComponentT>,
+ _pd: PhantomData<WithUidT>,
}
-impl<ComponentT> TermWithoutField for Without<ComponentT>
+impl<WithUidT> TermWithoutField for Without<WithUidT>
where
- ComponentT: Component,
+ WithUidT: WithUid,
{
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
{
- terms_builder.without::<ComponentT>();
+ terms_builder.without::<WithUidT>();
+ }
+}
+
+impl<ComponentT: Component> TermWithField for Option<&ComponentT>
+{
+ type Field<'a> = Option<ComponentHandle<'a, ComponentT>>;
+
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
+ {
+ }
+
+ fn get_field<'world>(
+ entity_handle: &crate::entity::Handle<'world>,
+ _world: &'world crate::World,
+ ) -> Self::Field<'world>
+ {
+ Some(
+ ComponentHandle::<'world, ComponentT>::from_entity_component_ref(
+ entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()?,
+ )
+ .unwrap_or_else(|err| {
+ panic!(
+ "Creating handle to component {} failed: {err}",
+ type_name::<ComponentT>()
+ );
+ }),
+ )
+ }
+}
+
+impl<ComponentT: Component> TermWithField for Option<&mut ComponentT>
+{
+ type Field<'a> = Option<ComponentHandleMut<'a, ComponentT>>;
+
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
+ {
+ }
+
+ fn get_field<'world>(
+ entity_handle: &crate::entity::Handle<'world>,
+ _world: &'world crate::World,
+ ) -> Self::Field<'world>
+ {
+ Some(
+ ComponentHandleMut::<'world, ComponentT>::from_entity_component_ref(
+ entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()?,
+ )
+ .unwrap_or_else(|err| {
+ panic!(
+ "Creating handle to component {} failed: {err}",
+ type_name::<ComponentT>()
+ );
+ }),
+ )
}
}