diff options
author | HampusM <hampus@hampusmat.com> | 2025-10-13 18:05:16 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-10-13 18:05:16 +0200 |
commit | d7d07c6437ead8b3ef2b6c967268d6d151ac4237 (patch) | |
tree | 40185bcd93f17d6c0c1986e9280c087b7997b938 | |
parent | 88a33aed4115984d496fcd12a965f9c4aaa0faf6 (diff) |
feat(ecs): add get_first_wildcard_pair_match fn to entity::Handle
-rw-r--r-- | ecs/src/entity.rs | 20 | ||||
-rw-r--r-- | ecs/src/pair.rs | 83 |
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 {} +} |