diff options
author | HampusM <hampus@hampusmat.com> | 2025-09-24 14:41:50 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-09-25 22:42:13 +0200 |
commit | 8d76fe6be211dfc8fc57d4e2f7e312e757ca899c (patch) | |
tree | def2d5fe4add23fa4f5557170363d16af1314812 /ecs/src/pair.rs | |
parent | 463f5df64005e63142f1e05bc973dd81d7cd793f (diff) |
refactor(ecs): improve pair with wildcard API
Diffstat (limited to 'ecs/src/pair.rs')
-rw-r--r-- | ecs/src/pair.rs | 151 |
1 files changed, 101 insertions, 50 deletions
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs index caf55db..85be9f6 100644 --- a/ecs/src/pair.rs +++ b/ecs/src/pair.rs @@ -1,5 +1,6 @@ use std::any::type_name; use std::convert::Infallible; +use std::marker::PhantomData; use crate::component::{ Handle as ComponentHandle, @@ -156,7 +157,7 @@ impl<Relation> QueryTermWithField for Pair<Relation, Wildcard> where Relation: Component, { - type Field<'a> = WildcardTargetHandle<'a>; + type Field<'a> = WithWildcard<'a, Relation, Wildcard>; fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>, @@ -175,9 +176,10 @@ where .next() .expect("Not possible"); - WildcardTargetHandle { + WithWildcard { world, component_ref: first_matching_comp, + _pd: PhantomData, } } } @@ -227,10 +229,10 @@ impl<Relation> QueryTermWithField for &'_ [Pair<Relation, Wildcard>] where Relation: Component, { - type Field<'a> = WildcardTargetIter<'a>; + type Field<'a> = MultipleWithWildcard<'a, Relation, Wildcard>; fn apply_to_terms_builder<const MAX_TERM_CNT: usize>( - terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>, + _terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>, ) { } @@ -240,62 +242,43 @@ where world: &'world World, ) -> Self::Field<'world> { - WildcardTargetIter { - inner: entity_handle - .get_matching_components(Pair::<Relation, Wildcard>::uid()), + MultipleWithWildcard { + entity_handle: entity_handle.clone(), world, + _pd: PhantomData, } } } -pub struct WildcardTargetHandle<'world> +/// Reference to a pair with a wildcard relation/target. +#[derive(Debug)] +pub struct WithWildcard<'world, Relation, Target> { world: &'world World, component_ref: EntityComponentRef<'world>, + _pd: PhantomData<(Relation, Target)>, } -impl WildcardTargetHandle<'_> +impl<Relation, Target> WithWildcard<'_, Relation, Target> { - /// Attempts to retrieve the target as a entity, returning `None` if not found. - #[must_use] - pub fn get_entity(&self) -> Option<EntityHandle<'_>> - { - let archetype = self - .world - .data - .component_storage - .get_entity_archetype(self.component_ref.id().target_entity())?; - - let Some(archetype_entity) = - archetype.get_entity_by_id(self.component_ref.id().target_entity()) - else { - unreachable!(); - }; - - Some(EntityHandle::new(archetype, archetype_entity, self.world)) - } - - /// Attempts to retrieve the target as a component, returning `None` if the component + /// Attempts to get the component data of this pair, returning `None` if the `Data` /// type is incorrect. /// /// # Panics - /// Will panic if: - /// - The component is mutably borrowed elsewhere + /// Will panic if the component data is mutably borrowed elsewhere. #[must_use] - pub fn get_component<ComponentData>( - &self, - ) -> Option<ComponentHandle<'_, ComponentData>> + pub fn get_data<Data>(&self) -> Option<ComponentHandle<'_, Data>> where - ComponentData: 'static, + Data: 'static, { - ComponentHandle::<ComponentData>::from_entity_component_ref(&self.component_ref) + ComponentHandle::<Data>::from_entity_component_ref(&self.component_ref) .map_or_else( |err| match err { ComponentHandleError::IncorrectType => None, err @ ComponentHandleError::AcquireLockFailed(_) => { panic!( "Creating handle to component {} failed: {err}", - type_name::<ComponentData>() + type_name::<Data>() ); } }, @@ -303,20 +286,17 @@ impl WildcardTargetHandle<'_> ) } - /// Attempts to retrieve the target as a component, returning `None` if the component + /// Attempts to get the component data of this pair, returning `None` if the `Data` /// type is incorrect. /// /// # Panics - /// Will panic if: - /// - The component is borrowed elsewhere + /// Will panic if the component data is borrowed elsewhere. #[must_use] - pub fn get_component_mut<ComponentData>( - &self, - ) -> Option<ComponentHandleMut<'_, ComponentData>> + pub fn get_data_mut<Data>(&self) -> Option<ComponentHandleMut<'_, Data>> where - ComponentData: 'static, + Data: 'static, { - ComponentHandleMut::<ComponentData>::from_entity_component_ref( + ComponentHandleMut::<Data>::from_entity_component_ref( &self.component_ref, self.world, ) @@ -326,7 +306,7 @@ impl WildcardTargetHandle<'_> err @ ComponentHandleError::AcquireLockFailed(_) => { panic!( "Creating handle to component {} failed: {err}", - type_name::<ComponentData>() + type_name::<Data>() ); } }, @@ -335,23 +315,94 @@ impl WildcardTargetHandle<'_> } } -pub struct WildcardTargetIter<'a> +impl<Relation> WithWildcard<'_, Relation, Wildcard> +{ + /// Attempts to retrieve the target as a entity, returning `None` if not found. + #[must_use] + pub fn get_target_ent(&self) -> Option<EntityHandle<'_>> + { + let archetype = self + .world + .data + .component_storage + .get_entity_archetype(self.component_ref.id().target_entity())?; + + let Some(archetype_entity) = + archetype.get_entity_by_id(self.component_ref.id().target_entity()) + else { + unreachable!(); + }; + + Some(EntityHandle::new(archetype, archetype_entity, self.world)) + } +} + +/// Used to access matching pairs in a entity containing zero or more matching pairs. +#[derive(Debug)] +pub struct MultipleWithWildcard<'a, Relation, Target> +{ + entity_handle: EntityHandle<'a>, + world: &'a World, + _pd: PhantomData<(Relation, Target)>, +} + +impl<'a, Relation: Component> MultipleWithWildcard<'a, Relation, Wildcard> +{ + #[must_use] + pub fn get_with_target_id( + &self, + target_id: Uid, + ) -> Option<WithWildcard<'a, Relation, Wildcard>> + { + Some(WithWildcard { + world: self.world, + component_ref: self + .entity_handle + .get_matching_components(Pair::new::<Relation>(target_id).id()) + .next()?, + _pd: PhantomData, + }) + } +} + +impl<'a, Relation: Component> IntoIterator + for MultipleWithWildcard<'a, Relation, Wildcard> +{ + type IntoIter = WithWildcardIter<'a, Relation, Wildcard>; + type Item = <Self::IntoIter as Iterator>::Item; + + fn into_iter(self) -> Self::IntoIter + { + WithWildcardIter { + inner: self + .entity_handle + .get_matching_components(Pair::<Relation, Wildcard>::uid()), + world: self.world, + _pd: PhantomData, + } + } +} + +/// Iterator of matching pairs in a entity. +pub struct WithWildcardIter<'a, Relation, Target> { inner: EntityMatchingComponentIter<'a>, world: &'a World, + _pd: PhantomData<(Relation, Target)>, } -impl<'a> Iterator for WildcardTargetIter<'a> +impl<'a, Relation, Target> Iterator for WithWildcardIter<'a, Relation, Target> { - type Item = WildcardTargetHandle<'a>; + type Item = WithWildcard<'a, Relation, Target>; fn next(&mut self) -> Option<Self::Item> { let matching_comp = self.inner.next()?; - Some(WildcardTargetHandle { + Some(WithWildcard { world: self.world, component_ref: matching_comp, + _pd: PhantomData, }) } } |