summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs/examples/relationship.rs2
-rw-r--r--ecs/src/entity.rs2
-rw-r--r--ecs/src/pair.rs151
3 files changed, 103 insertions, 52 deletions
diff --git a/ecs/examples/relationship.rs b/ecs/examples/relationship.rs
index 6ad08e7..dd2f77a 100644
--- a/ecs/examples/relationship.rs
+++ b/ecs/examples/relationship.rs
@@ -25,7 +25,7 @@ fn print_player_stats(player_query: Query<(&Player, &Health, Pair<Holding, Wildc
for (_, health, target_sword) in &player_query {
println!("Player health: {}", health.health);
- if let Some(sword_ent) = target_sword.get_entity() {
+ if let Some(sword_ent) = target_sword.get_target_ent() {
let sword = sword_ent
.get::<Sword>()
.expect("Sword entity is missing sword component");
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index 6ee5ad8..d7e5945 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -18,7 +18,7 @@ use crate::{EntityComponentRef, World};
pub mod obtainer;
/// A handle to a entity.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct Handle<'a>
{
archetype: &'a Archetype,
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs
index caf55db..85be9f6 100644
--- a/ecs/src/pair.rs
+++ b/ecs/src/pair.rs
@@ -1,5 +1,6 @@
use std::any::type_name;
use std::convert::Infallible;
+use std::marker::PhantomData;
use crate::component::{
Handle as ComponentHandle,
@@ -156,7 +157,7 @@ impl<Relation> QueryTermWithField for Pair<Relation, Wildcard>
where
Relation: Component,
{
- type Field<'a> = WildcardTargetHandle<'a>;
+ type Field<'a> = WithWildcard<'a, Relation, Wildcard>;
fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>,
@@ -175,9 +176,10 @@ where
.next()
.expect("Not possible");
- WildcardTargetHandle {
+ WithWildcard {
world,
component_ref: first_matching_comp,
+ _pd: PhantomData,
}
}
}
@@ -227,10 +229,10 @@ impl<Relation> QueryTermWithField for &'_ [Pair<Relation, Wildcard>]
where
Relation: Component,
{
- type Field<'a> = WildcardTargetIter<'a>;
+ type Field<'a> = MultipleWithWildcard<'a, Relation, Wildcard>;
fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
- terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>,
+ _terms_builder: &mut QueryTermsBuilder<MAX_TERM_CNT>,
)
{
}
@@ -240,62 +242,43 @@ where
world: &'world World,
) -> Self::Field<'world>
{
- WildcardTargetIter {
- inner: entity_handle
- .get_matching_components(Pair::<Relation, Wildcard>::uid()),
+ MultipleWithWildcard {
+ entity_handle: entity_handle.clone(),
world,
+ _pd: PhantomData,
}
}
}
-pub struct WildcardTargetHandle<'world>
+/// Reference to a pair with a wildcard relation/target.
+#[derive(Debug)]
+pub struct WithWildcard<'world, Relation, Target>
{
world: &'world World,
component_ref: EntityComponentRef<'world>,
+ _pd: PhantomData<(Relation, Target)>,
}
-impl WildcardTargetHandle<'_>
+impl<Relation, Target> WithWildcard<'_, Relation, Target>
{
- /// Attempts to retrieve the target as a entity, returning `None` if not found.
- #[must_use]
- pub fn get_entity(&self) -> Option<EntityHandle<'_>>
- {
- let archetype = self
- .world
- .data
- .component_storage
- .get_entity_archetype(self.component_ref.id().target_entity())?;
-
- let Some(archetype_entity) =
- archetype.get_entity_by_id(self.component_ref.id().target_entity())
- else {
- unreachable!();
- };
-
- Some(EntityHandle::new(archetype, archetype_entity, self.world))
- }
-
- /// Attempts to retrieve the target as a component, returning `None` if the component
+ /// Attempts to get the component data of this pair, returning `None` if the `Data`
/// type is incorrect.
///
/// # Panics
- /// Will panic if:
- /// - The component is mutably borrowed elsewhere
+ /// Will panic if the component data is mutably borrowed elsewhere.
#[must_use]
- pub fn get_component<ComponentData>(
- &self,
- ) -> Option<ComponentHandle<'_, ComponentData>>
+ pub fn get_data<Data>(&self) -> Option<ComponentHandle<'_, Data>>
where
- ComponentData: 'static,
+ Data: 'static,
{
- ComponentHandle::<ComponentData>::from_entity_component_ref(&self.component_ref)
+ ComponentHandle::<Data>::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::<ComponentData>()
+ type_name::<Data>()
);
}
},
@@ -303,20 +286,17 @@ impl WildcardTargetHandle<'_>
)
}
- /// Attempts to retrieve the target as a component, returning `None` if the component
+ /// Attempts to get the component data of this pair, returning `None` if the `Data`
/// type is incorrect.
///
/// # Panics
- /// Will panic if:
- /// - The component is borrowed elsewhere
+ /// Will panic if the component data is borrowed elsewhere.
#[must_use]
- pub fn get_component_mut<ComponentData>(
- &self,
- ) -> Option<ComponentHandleMut<'_, ComponentData>>
+ pub fn get_data_mut<Data>(&self) -> Option<ComponentHandleMut<'_, Data>>
where
- ComponentData: 'static,
+ Data: 'static,
{
- ComponentHandleMut::<ComponentData>::from_entity_component_ref(
+ ComponentHandleMut::<Data>::from_entity_component_ref(
&self.component_ref,
self.world,
)
@@ -326,7 +306,7 @@ impl WildcardTargetHandle<'_>
err @ ComponentHandleError::AcquireLockFailed(_) => {
panic!(
"Creating handle to component {} failed: {err}",
- type_name::<ComponentData>()
+ type_name::<Data>()
);
}
},
@@ -335,23 +315,94 @@ impl WildcardTargetHandle<'_>
}
}
-pub struct WildcardTargetIter<'a>
+impl<Relation> WithWildcard<'_, Relation, Wildcard>
+{
+ /// Attempts to retrieve the target as a entity, returning `None` if not found.
+ #[must_use]
+ pub fn get_target_ent(&self) -> Option<EntityHandle<'_>>
+ {
+ let archetype = self
+ .world
+ .data
+ .component_storage
+ .get_entity_archetype(self.component_ref.id().target_entity())?;
+
+ let Some(archetype_entity) =
+ archetype.get_entity_by_id(self.component_ref.id().target_entity())
+ else {
+ unreachable!();
+ };
+
+ Some(EntityHandle::new(archetype, archetype_entity, self.world))
+ }
+}
+
+/// Used to access matching pairs in a entity containing zero or more matching pairs.
+#[derive(Debug)]
+pub struct MultipleWithWildcard<'a, Relation, Target>
+{
+ entity_handle: EntityHandle<'a>,
+ world: &'a World,
+ _pd: PhantomData<(Relation, Target)>,
+}
+
+impl<'a, Relation: Component> MultipleWithWildcard<'a, Relation, Wildcard>
+{
+ #[must_use]
+ pub fn get_with_target_id(
+ &self,
+ target_id: Uid,
+ ) -> Option<WithWildcard<'a, Relation, Wildcard>>
+ {
+ Some(WithWildcard {
+ world: self.world,
+ component_ref: self
+ .entity_handle
+ .get_matching_components(Pair::new::<Relation>(target_id).id())
+ .next()?,
+ _pd: PhantomData,
+ })
+ }
+}
+
+impl<'a, Relation: Component> IntoIterator
+ for MultipleWithWildcard<'a, Relation, Wildcard>
+{
+ type IntoIter = WithWildcardIter<'a, Relation, Wildcard>;
+ type Item = <Self::IntoIter as Iterator>::Item;
+
+ fn into_iter(self) -> Self::IntoIter
+ {
+ WithWildcardIter {
+ inner: self
+ .entity_handle
+ .get_matching_components(Pair::<Relation, Wildcard>::uid()),
+ world: self.world,
+ _pd: PhantomData,
+ }
+ }
+}
+
+/// Iterator of matching pairs in a entity.
+pub struct WithWildcardIter<'a, Relation, Target>
{
inner: EntityMatchingComponentIter<'a>,
world: &'a World,
+ _pd: PhantomData<(Relation, Target)>,
}
-impl<'a> Iterator for WildcardTargetIter<'a>
+impl<'a, Relation, Target> Iterator for WithWildcardIter<'a, Relation, Target>
{
- type Item = WildcardTargetHandle<'a>;
+ type Item = WithWildcard<'a, Relation, Target>;
fn next(&mut self) -> Option<Self::Item>
{
let matching_comp = self.inner.next()?;
- Some(WildcardTargetHandle {
+ Some(WithWildcard {
world: self.world,
component_ref: matching_comp,
+ _pd: PhantomData,
})
}
}