summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs/examples/component_relationship.rs15
-rw-r--r--ecs/examples/event_loop.rs37
-rw-r--r--ecs/examples/relationship.rs5
-rw-r--r--ecs/examples/with_sole.rs8
-rw-r--r--ecs/src/component.rs5
-rw-r--r--ecs/src/component/local.rs12
-rw-r--r--ecs/src/lib.rs42
-rw-r--r--ecs/src/pair.rs114
-rw-r--r--ecs/src/phase.rs2
-rw-r--r--ecs/src/system/observer.rs5
-rw-r--r--ecs/src/util.rs61
-rw-r--r--ecs/tests/query.rs66
12 files changed, 316 insertions, 56 deletions
diff --git a/ecs/examples/component_relationship.rs b/ecs/examples/component_relationship.rs
index 4453e3a..e07b214 100644
--- a/ecs/examples/component_relationship.rs
+++ b/ecs/examples/component_relationship.rs
@@ -39,17 +39,26 @@ fn main()
world.create_entity((
Person { name: "Irving".to_string() },
- Pair::new_with_comp_target::<Likes>(Dogs { large: true }),
+ Pair::builder()
+ .relation::<Likes>()
+ .target_as_data(Dogs { large: true })
+ .build(),
));
world.create_entity((
Person { name: "Mark".to_string() },
- Pair::new_with_comp_target::<Likes>(Cats),
+ Pair::builder()
+ .relation::<Likes>()
+ .target_as_data(Cats)
+ .build(),
));
world.create_entity((
Person { name: "Helena".to_string() },
- Pair::new_with_comp_target::<Likes>(Dogs { large: false }),
+ Pair::builder()
+ .relation::<Likes>()
+ .target_as_data(Dogs { large: false })
+ .build(),
));
world.step();
diff --git a/ecs/examples/event_loop.rs b/ecs/examples/event_loop.rs
index cc2f7f4..bec2c00 100644
--- a/ecs/examples/event_loop.rs
+++ b/ecs/examples/event_loop.rs
@@ -65,11 +65,38 @@ fn age(query: Query<(&mut Health, &Name)>, mut actions: Actions)
}
}
-declare_entity!(SHEER_PHASE, (Phase, Pair::new::<ChildOf>(*UPDATE_PHASE)));
-
-declare_entity!(FEED_PHASE, (Phase, Pair::new::<ChildOf>(*SHEER_PHASE)));
-
-declare_entity!(AGE_PHASE, (Phase, Pair::new::<ChildOf>(*FEED_PHASE)));
+declare_entity!(
+ SHEER_PHASE,
+ (
+ Phase,
+ Pair::builder()
+ .relation::<ChildOf>()
+ .target_id(*UPDATE_PHASE)
+ .build()
+ )
+);
+
+declare_entity!(
+ FEED_PHASE,
+ (
+ Phase,
+ Pair::builder()
+ .relation::<ChildOf>()
+ .target_id(*SHEER_PHASE)
+ .build()
+ )
+);
+
+declare_entity!(
+ AGE_PHASE,
+ (
+ Phase,
+ Pair::builder()
+ .relation::<ChildOf>()
+ .target_id(*FEED_PHASE)
+ .build()
+ )
+);
fn main()
{
diff --git a/ecs/examples/relationship.rs b/ecs/examples/relationship.rs
index dd2f77a..4e94151 100644
--- a/ecs/examples/relationship.rs
+++ b/ecs/examples/relationship.rs
@@ -46,7 +46,10 @@ fn main()
world.create_entity((
Player,
Health { health: 180 },
- Pair::new::<Holding>(sword_uid),
+ Pair::builder()
+ .relation::<Holding>()
+ .target_id(sword_uid)
+ .build(),
));
world.step();
diff --git a/ecs/examples/with_sole.rs b/ecs/examples/with_sole.rs
index a292f06..7e89b0a 100644
--- a/ecs/examples/with_sole.rs
+++ b/ecs/examples/with_sole.rs
@@ -33,7 +33,13 @@ fn print_total_ammo_count(ammo_counter: Single<AmmoCounter>)
declare_entity!(
PRINT_AMMO_COUNT_PHASE,
- (Phase, Pair::new::<ChildOf>(*UPDATE_PHASE))
+ (
+ Phase,
+ Pair::builder()
+ .relation::<ChildOf>()
+ .target_id(*UPDATE_PHASE)
+ .build()
+ )
);
fn main()
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index e4ecfce..17b279b 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -153,7 +153,10 @@ impl<'comp, DataT: 'static> HandleMut<'comp, DataT>
pub fn set_changed(&self)
{
self.event_submitter.submit_event(
- &Pair::new::<Changed>(self.entity_component_ref.id()),
+ &Pair::builder()
+ .relation::<Changed>()
+ .target_id(self.entity_component_ref.id())
+ .build(),
self.entity_component_ref.entity_id(),
);
}
diff --git a/ecs/src/component/local.rs b/ecs/src/component/local.rs
index 6b2463f..b19a30b 100644
--- a/ecs/src/component/local.rs
+++ b/ecs/src/component/local.rs
@@ -37,7 +37,11 @@ where
};
let Some(local_component) = system_ent.get_with_id_mut::<LocalComponent>(
- Pair::new::<IsLocalComponent>(LocalComponent::id()).id(),
+ Pair::builder()
+ .relation::<IsLocalComponent>()
+ .target::<LocalComponent>()
+ .build()
+ .id(),
) else {
panic!(
"Local component {} of system with ID {} is uninitialized",
@@ -60,7 +64,11 @@ where
fn initialize(system: &mut SystemT, input: Self::Input)
{
system.add_local_component(
- Pair::new_with_comp_target::<IsLocalComponent>(input).into_parts(),
+ Pair::builder()
+ .relation::<IsLocalComponent>()
+ .target_as_data(input)
+ .build()
+ .into_parts(),
);
}
}
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 8ce2e7b..fa5a352 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -168,7 +168,10 @@ impl World
let system_ent_id = self.create_entity((
SystemComponent { system: type_erased_system },
- Pair::new::<DependsOn>(phase_euid),
+ Pair::builder()
+ .relation::<DependsOn>()
+ .target_id(phase_euid)
+ .build(),
));
system_callbacks.on_created(self, SystemMetadata { ent_id: system_ent_id });
@@ -344,7 +347,11 @@ impl World
QueryTerms::<QUERY_MAX_TERM_CNT>::builder()
.with_required([
SystemComponent::id(),
- Pair::new::<DependsOn>(phase_euid).id(),
+ Pair::builder()
+ .relation::<DependsOn>()
+ .target_id(phase_euid)
+ .build()
+ .id(),
])
.build(),
),
@@ -366,7 +373,11 @@ impl World
QueryTerms::<2>::builder()
.with_required([
Phase::id(),
- Pair::new::<ChildOf>(parent_phase_euid).id(),
+ Pair::builder()
+ .relation::<ChildOf>()
+ .target_id(parent_phase_euid)
+ .build()
+ .id(),
])
.build(),
);
@@ -461,8 +472,13 @@ impl World
continue;
}
- event_submitter
- .submit_event(&Pair::new::<Removed>(comp_id), entity_uid);
+ event_submitter.submit_event(
+ &Pair::builder()
+ .relation::<Removed>()
+ .target_id(comp_id)
+ .build(),
+ entity_uid,
+ );
}
}
Action::AddComponents(entity_uid, components) => {
@@ -514,7 +530,13 @@ impl World
continue;
}
- event_submitter.submit_event(&Pair::new::<Added>(comp_id), entity_uid);
+ event_submitter.submit_event(
+ &Pair::builder()
+ .relation::<Added>()
+ .target_id(comp_id)
+ .build(),
+ entity_uid,
+ );
}
}
@@ -539,7 +561,13 @@ impl World
continue;
}
- event_submitter.submit_event(&Pair::new::<Removed>(component_id), entity_uid);
+ event_submitter.submit_event(
+ &Pair::builder()
+ .relation::<Removed>()
+ .target_id(component_id)
+ .build(),
+ entity_uid,
+ );
}
}
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs
index 85be9f6..985a2b3 100644
--- a/ecs/src/pair.rs
+++ b/ecs/src/pair.rs
@@ -19,8 +19,91 @@ use crate::query::{
TermsBuilderInterface,
};
use crate::uid::{PairParams as UidPairParams, Uid, With as WithUid};
+use crate::util::impl_multiple;
use crate::{Component, EntityComponentRef, World};
+/// Pair builder.
+#[derive(Debug)]
+pub struct Builder<Relation, Target>
+{
+ relation: Relation,
+ target: Target,
+}
+
+impl<Relation, Target> Builder<Relation, Target>
+{
+ pub fn relation<NewRelation: Component>(self) -> Builder<Uid, Target>
+ {
+ Builder {
+ relation: NewRelation::id(),
+ target: self.target,
+ }
+ }
+
+ pub fn relation_id(self, id: Uid) -> Builder<Uid, Target>
+ {
+ Builder { relation: id, target: self.target }
+ }
+
+ pub fn target<NewTarget: Component>(self) -> Builder<Relation, Uid>
+ {
+ Builder {
+ relation: self.relation,
+ target: NewTarget::id(),
+ }
+ }
+
+ pub fn target_id(self, id: Uid) -> Builder<Relation, Uid>
+ {
+ Builder { relation: self.relation, target: id }
+ }
+}
+
+impl_multiple!(
+ Builder,
+ (impl<Target> _<Uid, Target>, impl<Target> _<(), Target>)
+ (ty_param_1, ty_param_2) => {
+ pub fn target_as_data<NewTarget: Component>(
+ self,
+ data: NewTarget,
+ ) -> Builder<$ty_param_1, NewTarget>
+ {
+ Builder {
+ relation: self.relation,
+ target: data,
+ }
+ }
+ }
+);
+
+impl_multiple!(
+ Builder,
+ (
+ impl _<Uid, Uid>,
+ impl<Relation: Component> _<Relation, Uid>,
+ impl<Target: Component> _<Uid, Target>,
+ impl<Relation: Component, Target: Component> _<Relation, Target>
+ )
+ (ty_param_1, ty_param_2) => {
+ #[must_use]
+ pub fn build(self) -> Pair<$ty_param_1, $ty_param_2>
+ {
+ Pair {
+ relation: self.relation,
+ target: self.target
+ }
+ }
+ }
+);
+
+impl Default for Builder<(), ()>
+{
+ fn default() -> Self
+ {
+ Self { relation: (), target: () }
+ }
+}
+
#[derive(Debug)]
pub struct Pair<Relation, Target>
{
@@ -28,14 +111,17 @@ pub struct Pair<Relation, Target>
target: Target,
}
-impl Pair<Uid, Uid>
+impl Pair<(), ()>
{
#[must_use]
- pub fn new<Relation: Component>(target: Uid) -> Self
+ pub fn builder() -> Builder<(), ()>
{
- Self { relation: Relation::id(), target }
+ Builder { relation: (), target: () }
}
+}
+impl Pair<Uid, Uid>
+{
#[must_use]
pub fn id(&self) -> Uid
{
@@ -46,20 +132,6 @@ impl Pair<Uid, Uid>
}
}
-impl<Target> Pair<Uid, Target>
-where
- Target: Component,
-{
- /// Returns a new pair that contains the target component as data.
- pub fn new_with_comp_target<Relation: Component>(target_component: Target) -> Self
- {
- Self {
- relation: Relation::uid(),
- target: target_component,
- }
- }
-}
-
impl IntoComponentParts for Pair<Uid, Uid>
{
fn into_parts(self) -> ComponentParts
@@ -358,7 +430,13 @@ impl<'a, Relation: Component> MultipleWithWildcard<'a, Relation, Wildcard>
world: self.world,
component_ref: self
.entity_handle
- .get_matching_components(Pair::new::<Relation>(target_id).id())
+ .get_matching_components(
+ Pair::builder()
+ .relation::<Relation>()
+ .target_id(target_id)
+ .build()
+ .id(),
+ )
.next()?,
_pd: PhantomData,
})
diff --git a/ecs/src/phase.rs b/ecs/src/phase.rs
index c13c432..9e3be24 100644
--- a/ecs/src/phase.rs
+++ b/ecs/src/phase.rs
@@ -8,7 +8,7 @@ pub struct Phase;
declare_entity!(pub START, (Phase,));
declare_entity!(pub PRE_UPDATE, (Phase,));
-declare_entity!(pub UPDATE, (Phase, Pair::new::<ChildOf>(*PRE_UPDATE)));
+declare_entity!(pub UPDATE, (Phase, Pair::builder().relation::<ChildOf>().target_id(*PRE_UPDATE).build()));
#[doc(hidden)]
pub(crate) fn spawn_entities(world: &mut World)
diff --git a/ecs/src/system/observer.rs b/ecs/src/system/observer.rs
index 5455fd4..1496d40 100644
--- a/ecs/src/system/observer.rs
+++ b/ecs/src/system/observer.rs
@@ -37,7 +37,10 @@ where
fn events() -> Self::Events
{
- [Pair::new::<Relation>(Target::id())]
+ [Pair::builder()
+ .relation::<Relation>()
+ .target::<Target>()
+ .build()]
}
}
diff --git a/ecs/src/util.rs b/ecs/src/util.rs
index 9ab4dc6..2ab78cd 100644
--- a/ecs/src/util.rs
+++ b/ecs/src/util.rs
@@ -300,6 +300,67 @@ macro_rules! gen_mask_64 {
pub(crate) use gen_mask_64;
+macro_rules! impl_multiple {
+ (
+ $type: ident,
+ ($(impl$(<$($generic: tt$(: $bound: ident)?),*>)? _<$($type_param: ty),*>),*)
+ ($($ty_param_matcher: ident),*) => {
+ $($item_tt: tt)*
+ }
+ ) => {
+ const _: () = {
+ $crate::util::impl_multiple!(
+ @(make_gen_item_macro)
+ _gen_multiple_impl_item,
+ ($($ty_param_matcher),*),
+ ($($item_tt)*)
+ );
+
+ $(
+ impl $(<$($generic$(: $bound)?,)*>)? $type<$($type_param),*>
+ {
+ _gen_multiple_impl_item!($($type_param),*);
+ }
+ )*
+ };
+ };
+
+ (
+ @(make_gen_item_macro)
+ $name: ident,
+ ($($ty_param_matcher: ident),*),
+ ($($transcriber: tt)*)
+ ) => {
+ $crate::util::impl_multiple!(
+ @(make_gen_item_macro)
+ ($), $name, ($($ty_param_matcher),*), ($($transcriber)*)
+ );
+ };
+
+ (
+ @(make_gen_item_macro)
+ ($dollar: tt),
+ $name: ident,
+ ($($ty_param_matcher: ident),*),
+ ($($transcriber: tt)*)
+ ) => {
+ $crate::util::impl_multiple!(
+ @(make_gen_item_macro)
+ $name, ($($dollar$ty_param_matcher: ty),*) => {
+ $($transcriber)*
+ }
+ );
+ };
+
+ (@(make_gen_item_macro) $name: ident, $($rule: tt)*) => {
+ macro_rules! $name {
+ $($rule)*
+ }
+ };
+}
+
+pub(crate) use impl_multiple;
+
mod sealed
{
pub trait Sealed {}
diff --git a/ecs/tests/query.rs b/ecs/tests/query.rs
index 8615e3a..7b218e3 100644
--- a/ecs/tests/query.rs
+++ b/ecs/tests/query.rs
@@ -335,14 +335,32 @@ fn query_with_wildcard_target_pair()
world.create_entity((B,));
- let ent_2_id = world.create_entity((B, Pair::new::<G>(ent_1_id)));
-
- world.create_entity((B, Pair::new::<F>(ent_1_id)));
- world.create_entity((B, A, C, Pair::new::<F>(ent_1_id)));
-
- let ent_3_id = world.create_entity((B, Pair::new::<G>(ent_2_id)));
-
- let ent_4_id = world.create_entity((B, E, Pair::new_with_comp_target::<G>(D)));
+ let ent_2_id = world.create_entity((
+ B,
+ Pair::builder().relation::<G>().target_id(ent_1_id).build(),
+ ));
+
+ world.create_entity((
+ B,
+ Pair::builder().relation::<F>().target_id(ent_1_id).build(),
+ ));
+ world.create_entity((
+ B,
+ A,
+ C,
+ Pair::builder().relation::<F>().target_id(ent_1_id).build(),
+ ));
+
+ let ent_3_id = world.create_entity((
+ B,
+ Pair::builder().relation::<G>().target_id(ent_2_id).build(),
+ ));
+
+ let ent_4_id = world.create_entity((
+ B,
+ E,
+ Pair::builder().relation::<G>().target_as_data(D).build(),
+ ));
assert_query_finds_ents(
world.query::<(&B, Pair<G, Wildcard>), ()>(),
@@ -363,14 +381,30 @@ fn query_with_component_target_pair()
world.create_entity((B,));
- world.create_entity((B, Pair::new::<G>(ent_1_id)));
-
- world.create_entity((B, Pair::new::<F>(ent_1_id)));
- world.create_entity((B, A, C, Pair::new::<F>(ent_1_id)));
-
- let ent_2_id = world.create_entity((B, Pair::new_with_comp_target::<G>(F)));
-
- let ent_3_id = world.create_entity((B, E, Pair::new_with_comp_target::<G>(F)));
+ world.create_entity((
+ B,
+ Pair::builder().relation::<G>().target_id(ent_1_id).build(),
+ ));
+
+ world.create_entity((
+ B,
+ Pair::builder().relation::<F>().target_id(ent_1_id).build(),
+ ));
+ world.create_entity((
+ B,
+ A,
+ C,
+ Pair::builder().relation::<F>().target_id(ent_1_id).build(),
+ ));
+
+ let ent_2_id = world
+ .create_entity((B, Pair::builder().relation::<G>().target_as_data(F).build()));
+
+ let ent_3_id = world.create_entity((
+ B,
+ E,
+ Pair::builder().relation::<G>().target_as_data(F).build(),
+ ));
assert_query_finds_ents(
world.query::<(&B, Pair<G, &F>), ()>(),