summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-10-13 18:05:16 +0200
committerHampusM <hampus@hampusmat.com>2025-10-13 18:05:16 +0200
commitd7d07c6437ead8b3ef2b6c967268d6d151ac4237 (patch)
tree40185bcd93f17d6c0c1986e9280c087b7997b938 /ecs
parent88a33aed4115984d496fcd12a965f9c4aaa0faf6 (diff)
feat(ecs): add get_first_wildcard_pair_match fn to entity::Handle
Diffstat (limited to 'ecs')
-rw-r--r--ecs/src/entity.rs20
-rw-r--r--ecs/src/pair.rs83
2 files changed, 98 insertions, 5 deletions
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index d7e5945..8c07ea8 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -12,6 +12,7 @@ use crate::component::{
Handle as ComponentHandle,
HandleMut as ComponentHandleMut,
};
+use crate::pair::{ComponentOrWildcard, Pair, WithWildcard as PairWithWildcard};
use crate::uid::{Kind as UidKind, Uid};
use crate::{EntityComponentRef, World};
@@ -154,6 +155,25 @@ impl<'a> Handle<'a>
)
}
+ #[must_use]
+ pub fn get_first_wildcard_pair_match<Relation, Target>(
+ &self,
+ ) -> Option<PairWithWildcard<'a, Relation, Target>>
+ where
+ Relation: ComponentOrWildcard,
+ Target: ComponentOrWildcard,
+ {
+ let mut matching_comps = self.get_matching_components(
+ Pair::builder()
+ .relation_id(Relation::uid())
+ .target_id(Target::uid())
+ .build()
+ .id(),
+ );
+
+ Some(PairWithWildcard::new(self.world, matching_comps.next()?))
+ }
+
#[inline]
#[must_use]
pub fn get_matching_components(&self, component_uid: Uid)
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs
index 600c6e4..8bef70a 100644
--- a/ecs/src/pair.rs
+++ b/ecs/src/pair.rs
@@ -18,7 +18,7 @@ use crate::query::{
TermsBuilder as QueryTermsBuilder,
TermsBuilderInterface,
};
-use crate::uid::{PairParams as UidPairParams, Uid, With as WithUid};
+use crate::uid::{Kind as UidKind, PairParams as UidPairParams, Uid, With as WithUid};
use crate::util::impl_multiple;
use crate::{Component, EntityComponentRef, World};
@@ -301,8 +301,8 @@ where
fn uid() -> Uid
{
Uid::new_pair(&UidPairParams {
- relation: Relation::uid(),
- target: Target::uid(),
+ relation: Relation::id(),
+ target: Target::id(),
})
}
}
@@ -314,7 +314,7 @@ where
fn uid() -> Uid
{
Uid::new_pair(&UidPairParams {
- relation: Relation::uid(),
+ relation: Relation::id(),
target: Wildcard::uid(),
})
}
@@ -354,8 +354,51 @@ pub struct WithWildcard<'world, Relation, Target>
_pd: PhantomData<(Relation, Target)>,
}
-impl<Relation, Target> WithWildcard<'_, Relation, Target>
+impl<'world, Relation, Target> WithWildcard<'world, Relation, Target>
{
+ /// Returns a new `WithWildcard`.
+ ///
+ /// # Panics
+ /// This function will panic if:
+ /// - The given component's ID is not a pair ID.
+ /// - `Relation::uid()` is not wildcard and does not equal to the relation of the
+ /// given component's ID
+ /// - `Target::uid()` is not wildcard and does not equal to the target of the given
+ /// 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
+ where
+ Relation: ComponentOrWildcard,
+ Target: ComponentOrWildcard,
+ {
+ let component_id = component_ref.id();
+
+ assert!(component_id.kind() == UidKind::Pair);
+
+ assert!(
+ Relation::uid() == Wildcard::uid()
+ || component_id.relation_component() == Relation::uid()
+ );
+
+ assert!(
+ Target::uid() == Wildcard::uid()
+ || component_id.target_component() == Target::uid()
+ );
+
+ assert!(Relation::uid() == Wildcard::uid() || Target::uid() == Wildcard::uid());
+
+ assert!(
+ !(Relation::uid() == Wildcard::uid() && Target::uid() == Wildcard::uid())
+ );
+
+ WithWildcard {
+ world,
+ component_ref,
+ _pd: PhantomData,
+ }
+ }
+
/// Returns the [`Uid`] of the pair.
#[must_use]
pub fn id(&self) -> Uid
@@ -585,3 +628,33 @@ impl Wildcard
Uid::wildcard()
}
}
+
+pub trait ComponentOrWildcard: sealed::Sealed
+{
+ fn uid() -> Uid;
+}
+
+impl<ComponentT: Component> ComponentOrWildcard for ComponentT
+{
+ fn uid() -> Uid
+ {
+ ComponentT::id()
+ }
+}
+
+impl<ComponentT: Component> sealed::Sealed for ComponentT {}
+
+impl ComponentOrWildcard for Wildcard
+{
+ fn uid() -> Uid
+ {
+ Wildcard::uid()
+ }
+}
+
+impl sealed::Sealed for Wildcard {}
+
+mod sealed
+{
+ pub trait Sealed {}
+}