From 0fe88ca6d34aee03e5b84fdf181c1a7cb2bd32af Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 25 Sep 2025 22:41:18 +0200 Subject: feat(ecs): add support for pairs with relation component as data --- ecs/src/pair.rs | 116 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 21 deletions(-) (limited to 'ecs/src/pair.rs') diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs index 985a2b3..f6d33d2 100644 --- a/ecs/src/pair.rs +++ b/ecs/src/pair.rs @@ -76,6 +76,23 @@ impl_multiple!( } ); +impl_multiple!( + Builder, + (impl _, impl _) + (ty_param_1, ty_param_2) => { + pub fn relation_as_data( + self, + data: NewRelation, + ) -> Builder + { + Builder { + relation: data, + target: self.target, + } + } + } +); + impl_multiple!( Builder, ( @@ -157,6 +174,23 @@ where } } +impl IntoComponentParts for Pair +where + Relation: Component, +{ + fn into_parts(self) -> ComponentParts + { + let id = Uid::new_pair(&UidPairParams { + relation: Relation::id(), + target: self.target, + }); + + ComponentParts::builder() + .name("Pair") + .build(id, self.relation) + } +} + impl QueryTermWithField for Pair where Relation: Component, @@ -168,7 +202,7 @@ where terms_builder: &mut QueryTermsBuilder, ) { - terms_builder.with_required([Self::uid()]); + terms_builder.with_required([Pair::::uid()]); } fn get_field<'world>( @@ -177,7 +211,7 @@ where ) -> Self::Field<'world> { let target_component = entity_handle - .get_matching_components(Self::uid()) + .get_matching_components(Pair::::uid()) .next() .expect("Not possible"); @@ -201,7 +235,7 @@ where terms_builder: &mut QueryTermsBuilder, ) { - terms_builder.with_required([Self::uid()]); + terms_builder.with_required([Pair::::uid()]); } fn get_field<'world>( @@ -210,7 +244,7 @@ where ) -> Self::Field<'world> { let target_component = entity_handle - .get_matching_components(Self::uid()) + .get_matching_components(Pair::::uid()) .next() .expect("Not possible"); @@ -225,6 +259,9 @@ where } } +// TODO: implement QueryTermWithField for Pair<&Relation, Target> (or equivalent) +// TODO: implement QueryTermWithField for Pair<&mut Relation, Target> (or equivalent) + impl QueryTermWithField for Pair where Relation: Component, @@ -256,21 +293,7 @@ where } } -impl WithUid for Pair -where - Relation: Component, - Target: Component, -{ - fn uid() -> Uid - { - Uid::new_pair(&UidPairParams { - relation: Relation::uid(), - target: Target::uid(), - }) - } -} - -impl WithUid for Pair +impl WithUid for Pair where Relation: Component, Target: Component, @@ -349,7 +372,7 @@ impl WithWildcard<'_, Relation, Target> ComponentHandleError::IncorrectType => None, err @ ComponentHandleError::AcquireLockFailed(_) => { panic!( - "Creating handle to component {} failed: {err}", + "Creating handle to pair data as component {} failed: {err}", type_name::() ); } @@ -377,7 +400,7 @@ impl WithWildcard<'_, Relation, Target> ComponentHandleError::IncorrectType => None, err @ ComponentHandleError::AcquireLockFailed(_) => { panic!( - "Creating handle to component {} failed: {err}", + "Creating handle to pair data as component {} failed: {err}", type_name::() ); } @@ -388,6 +411,8 @@ impl WithWildcard<'_, Relation, Target> } impl WithWildcard<'_, Relation, Wildcard> +where + Relation: Component, { /// Attempts to retrieve the target as a entity, returning `None` if not found. #[must_use] @@ -407,6 +432,55 @@ impl WithWildcard<'_, Relation, Wildcard> Some(EntityHandle::new(archetype, archetype_entity, self.world)) } + + /// Attempts to get the component data of this pair, returning `None` if the + /// `Relation` type is incorrect. + /// + /// # Panics + /// Will panic if the component data is mutably borrowed elsewhere. + #[must_use] + pub fn get_data_as_relation(&self) -> Option> + { + ComponentHandle::::from_entity_component_ref(&self.component_ref) + .map_or_else( + |err| match err { + ComponentHandleError::IncorrectType => None, + err @ ComponentHandleError::AcquireLockFailed(_) => { + panic!( + "Creating handle to pair data as component {} failed: {err}", + type_name::() + ); + } + }, + Some, + ) + } + + /// Attempts to get the component data of this pair, returning `None` if the + /// `Relation` type is incorrect. + /// + /// # Panics + /// Will panic if the component data is borrowed elsewhere. + #[must_use] + pub fn get_data_as_relation_mut(&self) -> Option> + { + ComponentHandleMut::::from_entity_component_ref( + &self.component_ref, + self.world, + ) + .map_or_else( + |err| match err { + ComponentHandleError::IncorrectType => None, + err @ ComponentHandleError::AcquireLockFailed(_) => { + panic!( + "Creating handle to pair data as component {} failed: {err}", + type_name::() + ); + } + }, + Some, + ) + } } /// Used to access matching pairs in a entity containing zero or more matching pairs. -- cgit v1.2.3-18-g5258