From b582c5d6fa9cf4ecedfe17bebe903a21d2945989 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Fri, 11 Nov 2022 03:09:16 -0500
Subject: [PATCH 1/5] support `In`/`Out` for exclusive systems
---
.../src/system/exclusive_function_system.rs | 89 ++++++++++++++-----
1 file changed, 66 insertions(+), 23 deletions(-)
diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs
index 8b1607c75898e..c6fe8acba1fcf 100644
--- a/crates/bevy_ecs/src/system/exclusive_function_system.rs
+++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs
@@ -6,7 +6,8 @@ use crate::{
schedule::{SystemLabel, SystemLabelId},
system::{
check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamItem,
- ExclusiveSystemParamState, IntoSystem, System, SystemMeta, SystemTypeIdLabel,
+ ExclusiveSystemParamState, In, InputMarker, IntoSystem, System, SystemMeta,
+ SystemTypeIdLabel,
},
world::{World, WorldId},
};
@@ -19,7 +20,7 @@ use std::{borrow::Cow, marker::PhantomData};
/// [`ExclusiveSystemParam`]s.
///
/// [`ExclusiveFunctionSystem`] must be `.initialized` before they can be run.
-pub struct ExclusiveFunctionSystem
+pub struct ExclusiveFunctionSystem
where
Param: ExclusiveSystemParam,
{
@@ -28,18 +29,21 @@ where
system_meta: SystemMeta,
world_id: Option,
// NOTE: PhantomData T> gives this safe Send/Sync impls
- marker: PhantomData Marker>,
+ marker: PhantomData (In, Out, Marker)>,
}
pub struct IsExclusiveFunctionSystem;
-impl IntoSystem<(), (), (IsExclusiveFunctionSystem, Param, Marker)> for F
+impl IntoSystem
+ for F
where
+ In: 'static,
+ Out: 'static,
Param: ExclusiveSystemParam + 'static,
Marker: 'static,
- F: ExclusiveSystemParamFunction + Send + Sync + 'static,
+ F: ExclusiveSystemParamFunction + Send + Sync + 'static,
{
- type System = ExclusiveFunctionSystem;
+ type System = ExclusiveFunctionSystem;
fn into_system(func: Self) -> Self::System {
ExclusiveFunctionSystem {
func,
@@ -53,14 +57,16 @@ where
const PARAM_MESSAGE: &str = "System's param_state was not found. Did you forget to initialize this system before running it?";
-impl System for ExclusiveFunctionSystem
+impl System for ExclusiveFunctionSystem
where
+ In: 'static,
+ Out: 'static,
Param: ExclusiveSystemParam + 'static,
Marker: 'static,
- F: ExclusiveSystemParamFunction + Send + Sync + 'static,
+ F: ExclusiveSystemParamFunction + Send + Sync + 'static,
{
- type In = ();
- type Out = ();
+ type In = In;
+ type Out = Out;
#[inline]
fn name(&self) -> Cow<'static, str> {
@@ -90,7 +96,7 @@ where
panic!("Cannot run exclusive systems with a shared World reference");
}
- fn run(&mut self, _input: Self::In, world: &mut World) -> Self::Out {
+ fn run(&mut self, input: Self::In, world: &mut World) -> Self::Out {
let saved_last_tick = world.last_change_tick;
world.last_change_tick = self.system_meta.last_change_tick;
@@ -98,12 +104,14 @@ where
self.param_state.as_mut().expect(PARAM_MESSAGE),
&self.system_meta,
);
- self.func.run(world, params);
+ let out = self.func.run(world, input, params);
let change_tick = world.change_tick.get_mut();
self.system_meta.last_change_tick = *change_tick;
*change_tick += 1;
world.last_change_tick = saved_last_tick;
+
+ out
}
#[inline]
@@ -150,8 +158,11 @@ where
}
}
-impl>
- AsSystemLabel<(Param, Marker, IsExclusiveFunctionSystem)> for T
+impl AsSystemLabel<(In, Out, Param, Marker, IsExclusiveFunctionSystem)>
+ for T
+where
+ Param: ExclusiveSystemParam,
+ T: ExclusiveSystemParamFunction,
{
#[inline]
fn as_system_label(&self) -> SystemLabelId {
@@ -163,38 +174,70 @@ impl:
+pub trait ExclusiveSystemParamFunction:
Send + Sync + 'static
{
- fn run(&mut self, world: &mut World, param_value: ExclusiveSystemParamItem);
+ fn run(
+ &mut self,
+ world: &mut World,
+ input: In,
+ param_value: ExclusiveSystemParamItem,
+ ) -> Out;
}
macro_rules! impl_exclusive_system_function {
($($param: ident),*) => {
#[allow(non_snake_case)]
- impl ExclusiveSystemParamFunction<($($param,)*), ()> for Func
+ impl ExclusiveSystemParamFunction<(), Out, ($($param,)*), ()> for Func
where
for <'a> &'a mut Func:
- FnMut(&mut World, $($param),*) +
- FnMut(&mut World, $(ExclusiveSystemParamItem<$param>),*)
+ FnMut(&mut World, $($param),*) -> Out +
+ FnMut(&mut World, $(ExclusiveSystemParamItem<$param>),*) -> Out,
+ Out: 'static,
{
#[inline]
- fn run(&mut self, world: &mut World, param_value: ExclusiveSystemParamItem< ($($param,)*)>) {
+ fn run(&mut self, world: &mut World, _in: (), param_value: ExclusiveSystemParamItem< ($($param,)*)>) -> Out {
// Yes, this is strange, but `rustc` fails to compile this impl
// without using this function. It fails to recognise that `func`
// is a function, potentially because of the multiple impls of `FnMut`
#[allow(clippy::too_many_arguments)]
- fn call_inner<$($param,)*>(
- mut f: impl FnMut(&mut World, $($param,)*),
+ fn call_inner(
+ mut f: impl FnMut(&mut World, $($param,)*) -> Out,
world: &mut World,
$($param: $param,)*
- ) {
+ ) -> Out {
f(world, $($param,)*)
}
let ($($param,)*) = param_value;
call_inner(self, world, $($param),*)
}
}
+ #[allow(non_snake_case)]
+ impl ExclusiveSystemParamFunction for Func
+ where
+ for <'a> &'a mut Func:
+ FnMut(&mut World, In, $($param),*) -> Out +
+ FnMut(&mut World, In, $(ExclusiveSystemParamItem<$param>),*) -> Out,
+ Out: 'static,
+ {
+ #[inline]
+ fn run(&mut self, world: &mut World, input: Input, param_value: ExclusiveSystemParamItem< ($($param,)*)>) -> Out {
+ // Yes, this is strange, but `rustc` fails to compile this impl
+ // without using this function. It fails to recognise that `func`
+ // is a function, potentially because of the multiple impls of `FnMut`
+ #[allow(clippy::too_many_arguments)]
+ fn call_inner(
+ mut f: impl FnMut(&mut World, In, $($param,)*) -> Out,
+ world: &mut World,
+ input: Input,
+ $($param: $param,)*
+ ) -> Out {
+ f(world, In(input), $($param,)*)
+ }
+ let ($($param,)*) = param_value;
+ call_inner(self, world, input, $($param),*)
+ }
+ }
};
}
// Note that we rely on the highest impl to be <= the highest order of the tuple impls
From 05e68a93ad2d1e429bae9163a941b84865828e97 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Sat, 24 Dec 2022 08:58:18 -0500
Subject: [PATCH 2/5] add a test case for piping exclusive systems
---
crates/bevy_ecs/src/system/system_piping.rs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/crates/bevy_ecs/src/system/system_piping.rs b/crates/bevy_ecs/src/system/system_piping.rs
index d28158b697836..fc89e10a7c561 100644
--- a/crates/bevy_ecs/src/system/system_piping.rs
+++ b/crates/bevy_ecs/src/system/system_piping.rs
@@ -423,8 +423,15 @@ pub mod adapter {
unimplemented!()
}
+ /// Mocks an exclusive system that returns a value of type `T`.
+ fn exclusive_in_out(_: &mut World, _: In) -> B {
+ unimplemented!()
+ }
+
assert_is_system(returning::>.pipe(unwrap));
assert_is_system(returning::