From 29ee29b3887773e36fb7ad55ab44392dae7f8412 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 20 Aug 2025 17:09:08 +0200 Subject: feat(ecs): add funcs for getting target comp of wildcard pairs --- ecs/src/pair.rs | 96 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 19 deletions(-) (limited to 'ecs/src/pair.rs') diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs index 77b6da7..3dc9f36 100644 --- a/ecs/src/pair.rs +++ b/ecs/src/pair.rs @@ -3,6 +3,7 @@ use std::convert::Infallible; use crate::component::{ Handle as ComponentHandle, + HandleError as ComponentHandleError, HandleMut as ComponentHandleMut, IntoParts as IntoComponentParts, Parts as ComponentParts, @@ -17,7 +18,7 @@ use crate::query::{ TermsBuilderInterface, }; use crate::uid::{PairParams as UidPairParams, Uid, With as WithUid}; -use crate::{Component, World}; +use crate::{Component, EntityComponentRef, World}; #[derive(Debug)] pub struct Pair @@ -107,7 +108,7 @@ where .next() .expect("Not possible"); - Self::Field::from_entity_component_ref(target_component).unwrap_or_else(|err| { + Self::Field::from_entity_component_ref(&target_component).unwrap_or_else(|err| { panic!( "Creating handle to target component {} failed: {err}", type_name::() @@ -140,7 +141,7 @@ where .next() .expect("Not possible"); - Self::Field::from_entity_component_ref(target_component).unwrap_or_else(|err| { + Self::Field::from_entity_component_ref(&target_component).unwrap_or_else(|err| { panic!( "Creating handle to target component {} failed: {err}", type_name::() @@ -153,7 +154,7 @@ impl QueryTermWithField for Pair where Relation: Component, { - type Field<'a> = EntityTargetHandle<'a>; + type Field<'a> = WildcardTargetHandle<'a>; fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, @@ -172,9 +173,9 @@ where .next() .expect("Not possible"); - EntityTargetHandle { + WildcardTargetHandle { world, - pair_uid: first_matching_comp.id(), + component_ref: first_matching_comp, } } } @@ -224,7 +225,7 @@ impl QueryTermWithField for &'static [Pair] where Relation: Component, { - type Field<'a> = HandleIter<'a>; + type Field<'a> = WildcardTargetIter<'a>; fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, @@ -238,7 +239,7 @@ where world: &'world World, ) -> Self::Field<'world> { - HandleIter { + WildcardTargetIter { inner: entity_handle .get_matching_components(Pair::::uid()), world, @@ -246,50 +247,107 @@ where } } -pub struct EntityTargetHandle<'world> +pub struct WildcardTargetHandle<'world> { world: &'world World, - pair_uid: Uid, + component_ref: EntityComponentRef<'world>, } -impl EntityTargetHandle<'_> +impl WildcardTargetHandle<'_> { + /// Attempts to retrieve the target as a entity, returning `None` if not found. #[must_use] - pub fn get_target_entity(&self) -> Option> + pub fn get_entity(&self) -> Option> { let archetype = self .world .data .component_storage - .get_entity_archetype(self.pair_uid.target_entity())?; + .get_entity_archetype(self.component_ref.id().target_entity())?; let Some(archetype_entity) = - archetype.get_entity_by_id(self.pair_uid.target_entity()) + archetype.get_entity_by_id(self.component_ref.id().target_entity()) else { unreachable!(); }; Some(EntityHandle::new(archetype, archetype_entity)) } + + /// Attempts to retrieve the target as a component, returning `None` if the component + /// type is incorrect. + /// + /// # Panics + /// Will panic if: + /// - The component is mutably borrowed elsewhere + pub fn get_component( + &self, + ) -> Option> + where + ComponentData: 'static, + { + ComponentHandle::::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::() + ); + } + }, + |handle| Some(handle), + ) + } + + /// Attempts to retrieve the target as a component, returning `None` if the component + /// type is incorrect. + /// + /// # Panics + /// Will panic if: + /// - The component is borrowed elsewhere + pub fn get_component_mut( + &self, + ) -> Option> + where + ComponentData: 'static, + { + ComponentHandleMut::::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::() + ); + } + }, + |handle| Some(handle), + ) + } } -pub struct HandleIter<'a> +pub struct WildcardTargetIter<'a> { inner: EntityMatchingComponentIter<'a>, world: &'a World, } -impl<'a> Iterator for HandleIter<'a> +impl<'a> Iterator for WildcardTargetIter<'a> { - type Item = EntityTargetHandle<'a>; + type Item = WildcardTargetHandle<'a>; fn next(&mut self) -> Option { let matching_comp = self.inner.next()?; - Some(EntityTargetHandle { + Some(WildcardTargetHandle { world: self.world, - pair_uid: matching_comp.id(), + component_ref: matching_comp, }) } } -- cgit v1.2.3-18-g5258