summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-09-25 22:41:18 +0200
committerHampusM <hampus@hampusmat.com>2025-09-25 22:42:35 +0200
commit0fe88ca6d34aee03e5b84fdf181c1a7cb2bd32af (patch)
tree868f0af62baf659005b59fd8676fa313c3f442c3
parent3bac271d4baa73844d4a0949946c6d9386d0db46 (diff)
feat(ecs): add support for pairs with relation component as data
-rw-r--r--ecs/src/pair.rs116
1 files changed, 95 insertions, 21 deletions
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
@@ -78,6 +78,23 @@ impl_multiple!(
impl_multiple!(
Builder,
+ (impl<Relation> _<Relation, Uid>, impl<Relation> _<Relation, ()>)
+ (ty_param_1, ty_param_2) => {
+ pub fn relation_as_data<NewRelation: Component>(
+ self,
+ data: NewRelation,
+ ) -> Builder<NewRelation, $ty_param_2>
+ {
+ Builder {
+ relation: data,
+ target: self.target,
+ }
+ }
+ }
+);
+
+impl_multiple!(
+ Builder,
(
impl _<Uid, Uid>,
impl<Relation: Component> _<Relation, Uid>,
@@ -157,6 +174,23 @@ where
}
}
+impl<Relation> IntoComponentParts for Pair<Relation, Uid>
+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<Relation, Target> QueryTermWithField for Pair<Relation, &Target>
where
Relation: Component,
@@ -168,7 +202,7 @@ where
terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>,
)
{
- terms_builder.with_required([Self::uid()]);
+ terms_builder.with_required([Pair::<Relation, Target>::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::<Relation, Target>::uid())
.next()
.expect("Not possible");
@@ -201,7 +235,7 @@ where
terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>,
)
{
- terms_builder.with_required([Self::uid()]);
+ terms_builder.with_required([Pair::<Relation, Target>::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::<Relation, Target>::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<Relation> QueryTermWithField for Pair<Relation, Wildcard>
where
Relation: Component,
@@ -256,21 +293,7 @@ where
}
}
-impl<Relation, Target> WithUid for Pair<Relation, &Target>
-where
- Relation: Component,
- Target: Component,
-{
- fn uid() -> Uid
- {
- Uid::new_pair(&UidPairParams {
- relation: Relation::uid(),
- target: Target::uid(),
- })
- }
-}
-
-impl<Relation, Target> WithUid for Pair<Relation, &mut Target>
+impl<Relation, Target> WithUid for Pair<Relation, Target>
where
Relation: Component,
Target: Component,
@@ -349,7 +372,7 @@ impl<Relation, Target> 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::<Data>()
);
}
@@ -377,7 +400,7 @@ impl<Relation, Target> 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::<Data>()
);
}
@@ -388,6 +411,8 @@ impl<Relation, Target> WithWildcard<'_, Relation, Target>
}
impl<Relation> 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<Relation> 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<'_, Relation>>
+ {
+ ComponentHandle::<Relation>::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::<Relation>()
+ );
+ }
+ },
+ 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<'_, Relation>>
+ {
+ ComponentHandleMut::<Relation>::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::<Relation>()
+ );
+ }
+ },
+ Some,
+ )
+ }
}
/// Used to access matching pairs in a entity containing zero or more matching pairs.