From 9226356b7b54c4c5b036b6fee00bba376245c5f3 Mon Sep 17 00:00:00 2001 From: HampusM Date: Fri, 24 Jul 2026 22:32:21 +0200 Subject: feat(engine-ecs): add traversal query term --- engine-ecs/src/pair.rs | 164 +++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 79 deletions(-) (limited to 'engine-ecs/src/pair.rs') diff --git a/engine-ecs/src/pair.rs b/engine-ecs/src/pair.rs index 1168f67..00c6a72 100644 --- a/engine-ecs/src/pair.rs +++ b/engine-ecs/src/pair.rs @@ -14,11 +14,12 @@ use crate::entity::{ MatchingComponentIter as EntityMatchingComponentIter, }; use crate::query::{ + SearchResult, Term as QueryTerm, + TermMetadata as QueryTermMetadata, TermsBuilder as QueryTermsBuilder, TermsBuilderInterface, }; -use crate::tuple::Tuple; use crate::uid::{PairParams as UidPairParams, Uid, With as WithUid}; use crate::util::impl_multiple; use crate::{Component, EntityComponentRef, World}; @@ -192,121 +193,128 @@ where } } -impl<'world, Relation, Target> QueryTerm<'world> for Pair +impl<'query, Relation, Target> QueryTerm<'query> for Pair where Relation: Component, Target: Component, { - type AddField = - Fields::WithElementAtEnd>; + type Fields = (ComponentHandle<'query, Target>,); fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, + _term_metadata: QueryTermMetadata, ) { terms_builder.present([Pair::::uid()]); } - fn add_field( - entity_handle: &EntityHandle<'world>, - _world: &'world World, - fields: Fields, - ) -> Self::AddField + fn fields( + _world: &'query World, + search_result: &SearchResult<'query, '_>, + _term_metadata: QueryTermMetadata, + ) -> Self::Fields { - let target_component = entity_handle + let target_component = search_result + .entity_handle .get_matching_components(Pair::::uid()) .next() .expect("Not possible"); - let target_component = match ComponentHandle::::from_entity_component_ref(&target_component) { - Ok(target_component) => target_component, - Err(err) => { - panic!( - "Creating handle to target component {} failed: {err}", - type_name::() - ); - } - }; + let target_component = + match ComponentHandle::::from_entity_component_ref(&target_component) + { + Ok(target_component) => target_component, + Err(err) => { + panic!( + "Creating handle to target component {} failed: {err}", + type_name::() + ); + } + }; - fields.with_elem(target_component) + (target_component,) } } -impl<'world, Relation, Target> QueryTerm<'world> for Pair +impl<'query, Relation, Target> QueryTerm<'query> for Pair where Relation: Component, Target: Component, { - type AddField = - Fields::WithElementAtEnd>; + type Fields = (ComponentHandleMut<'query, Target>,); fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, + _term_metadata: QueryTermMetadata, ) { terms_builder.present([Pair::::uid()]); } - fn add_field( - entity_handle: &EntityHandle<'world>, - world: &'world World, - fields: Fields, - ) -> Self::AddField + fn fields( + world: &'query World, + search_result: &SearchResult<'query, '_>, + _term_metadata: QueryTermMetadata, + ) -> Self::Fields { - let target_component = entity_handle + let target_component = search_result + .entity_handle .get_matching_components(Pair::::uid()) .next() .expect("Not possible"); - let target_component = match ComponentHandleMut::::from_entity_component_ref(&target_component, world) { - Ok(target_component) => target_component, - Err(err) => { - panic!( - "Creating mut handle to target component {} failed: {err}", - type_name::() - ); - } - }; + let target_component = + match ComponentHandleMut::::from_entity_component_ref( + &target_component, + world, + ) { + Ok(target_component) => target_component, + Err(err) => { + panic!( + "Creating mut handle to target component {} failed: {err}", + type_name::() + ); + } + }; - fields.with_elem(target_component) + (target_component,) } } // TODO: implement QueryTerm for Pair<&Relation, Target> (or equivalent) // TODO: implement QueryTerm for Pair<&mut Relation, Target> (or equivalent) -impl<'world, Relation> QueryTerm<'world> for Pair +impl<'query, Relation> QueryTerm<'query> for Pair where Relation: Component, { - type AddField = - Fields::WithElementAtEnd>; + type Fields = (WithWildcard<'query, Relation, Wildcard>,); fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, + _term_metadata: QueryTermMetadata, ) { terms_builder.present([Self::uid()]); } - fn add_field( - entity_handle: &EntityHandle<'world>, - world: &'world World, - fields: Fields, - ) -> Self::AddField + fn fields( + world: &'query World, + search_result: &SearchResult<'query, '_>, + _term_metadata: QueryTermMetadata, + ) -> Self::Fields { - let first_matching_comp = entity_handle + let first_matching_comp = search_result + .entity_handle .get_matching_components(Self::uid()) .next() .expect("Not possible"); - fields.with_elem( - WithWildcard { - world, - component_ref: first_matching_comp, - _pd: PhantomData, - } - ) + (WithWildcard { + world, + component_ref: first_matching_comp, + _pd: PhantomData, + },) } } @@ -337,45 +345,43 @@ where } } -impl<'world, Relation> QueryTerm<'world> for &[Pair] +impl<'query, Relation> QueryTerm<'query> for &[Pair] where Relation: Component, { - type AddField = - Fields::WithElementAtEnd>; + type Fields = (MultipleWithWildcard<'query, Relation, Wildcard>,); fn apply_to_terms_builder( _terms_builder: &mut QueryTermsBuilder, + _term_metadata: QueryTermMetadata, ) { } - fn add_field( - entity_handle: &EntityHandle<'world>, - world: &'world World, - fields: Fields, - ) -> Self::AddField + fn fields( + world: &'query World, + search_result: &SearchResult<'query, '_>, + _term_metadata: QueryTermMetadata, + ) -> Self::Fields { - fields.with_elem( - MultipleWithWildcard { - entity_handle: entity_handle.clone(), - world, - _pd: PhantomData, - } - ) + (MultipleWithWildcard { + entity_handle: search_result.entity_handle.clone(), + world, + _pd: PhantomData, + },) } } /// Reference to a pair with a wildcard relation/target. #[derive(Debug)] -pub struct WithWildcard<'world, Relation, Target> +pub struct WithWildcard<'query, Relation, Target> { - world: &'world World, - component_ref: EntityComponentRef<'world>, + world: &'query World, + component_ref: EntityComponentRef<'query>, _pd: PhantomData<(Relation, Target)>, } -impl<'world, Relation, Target> WithWildcard<'world, Relation, Target> +impl<'query, Relation, Target> WithWildcard<'query, Relation, Target> { /// Returns a new `WithWildcard`. /// @@ -388,7 +394,7 @@ impl<'world, Relation, Target> WithWildcard<'world, Relation, Target> /// component's ID /// - Both `Relation::uid()` and `Target::uid()` are wildcards /// - Neither `Relation::uid()` or `Target::uid()` are wildcards - pub fn new(world: &'world World, component_ref: EntityComponentRef<'world>) -> Self + pub fn new(world: &'query World, component_ref: EntityComponentRef<'query>) -> Self where Relation: ComponentOrWildcard, Target: ComponentOrWildcard, @@ -480,13 +486,13 @@ impl<'world, Relation, Target> WithWildcard<'world, Relation, Target> } } -impl<'world, Relation> WithWildcard<'world, Relation, Wildcard> +impl<'query, Relation> WithWildcard<'query, Relation, Wildcard> where Relation: Component, { /// Attempts to retrieve the target as a entity, returning `None` if not found. #[must_use] - pub fn get_target_ent(&self) -> Option> + pub fn get_target_ent(&self) -> Option> { let archetype = self .world @@ -562,7 +568,7 @@ pub struct MultipleWithWildcard<'a, Relation, Target> _pd: PhantomData<(Relation, Target)>, } -impl<'world, Relation, Target> MultipleWithWildcard<'world, Relation, Target> +impl<'query, Relation, Target> MultipleWithWildcard<'query, Relation, Target> { /// Returns a new `MultipleWithWildcard`. /// @@ -570,7 +576,7 @@ impl<'world, Relation, Target> MultipleWithWildcard<'world, Relation, Target> /// This function will panic if: /// - Both `Relation::uid()` and `Target::uid()` are wildcards /// - Neither `Relation::uid()` or `Target::uid()` are wildcards - pub fn new(world: &'world World, entity_handle: EntityHandle<'world>) -> Self + pub fn new(world: &'query World, entity_handle: EntityHandle<'query>) -> Self where Relation: ComponentOrWildcard, Target: ComponentOrWildcard, -- cgit v1.2.3-18-g5258