diff --git a/crates/bevy_ecs/src/system/observer_system.rs b/crates/bevy_ecs/src/system/observer_system.rs index fdd3f36dd5058..c5a04f25dd4eb 100644 --- a/crates/bevy_ecs/src/system/observer_system.rs +++ b/crates/bevy_ecs/src/system/observer_system.rs @@ -10,31 +10,40 @@ use super::IntoSystem; /// Implemented for systems that have an [`Observer`] as the first argument. /// /// [`Observer`]: crate::observer::Observer -pub trait ObserverSystem: - System, Out = ()> + Send + 'static +pub trait ObserverSystem: + System, Out = Out> + Send + 'static { } -impl, Out = ()> + Send + 'static> - ObserverSystem for T +impl< + E: 'static, + B: Bundle, + Out, + T: System, Out = Out> + Send + 'static, + > ObserverSystem for T { } /// Implemented for systems that convert into [`ObserverSystem`]. -pub trait IntoObserverSystem: Send + 'static { +pub trait IntoObserverSystem: Send + 'static { /// The type of [`System`] that this instance converts into. - type System: ObserverSystem; + type System: ObserverSystem; /// Turns this value into its corresponding [`System`]. fn into_system(this: Self) -> Self::System; } -impl, (), M> + Send + 'static, M, E: 'static, B: Bundle> - IntoObserverSystem for S +impl< + S: IntoSystem, Out, M> + Send + 'static, + M, + Out, + E: 'static, + B: Bundle, + > IntoObserverSystem for S where - S::System: ObserverSystem, + S::System: ObserverSystem, { - type System = , (), M>>::System; + type System = , Out, M>>::System; fn into_system(this: Self) -> Self::System { IntoSystem::into_system(this) @@ -44,23 +53,23 @@ where macro_rules! impl_system_function { ($($param: ident),*) => { #[allow(non_snake_case)] - impl SystemParamFunction, $($param,)*)> for Func + impl SystemParamFunction, $($param,)*)> for Func where for <'a> &'a mut Func: - FnMut(Trigger, $($param),*) + - FnMut(Trigger, $(SystemParamItem<$param>),*) + FnMut(Trigger, $($param),*) -> Out + + FnMut(Trigger, $(SystemParamItem<$param>),*) -> Out, Out: 'static { type In = Trigger<'static, E, B>; - type Out = (); + type Out = Out; type Param = ($($param,)*); #[inline] - fn run(&mut self, input: Trigger<'static, E, B>, param_value: SystemParamItem< ($($param,)*)>) { + fn run(&mut self, input: Trigger<'static, E, B>, param_value: SystemParamItem< ($($param,)*)>) -> Out { #[allow(clippy::too_many_arguments)] - fn call_inner( - mut f: impl FnMut(Trigger<'static, E, B>, $($param,)*), + fn call_inner( + mut f: impl FnMut(Trigger<'static, E, B>, $($param,)*) -> Out, input: Trigger<'static, E, B>, $($param: $param,)* - ){ + ) -> Out{ f(input, $($param,)*) } let ($($param,)*) = param_value; @@ -71,3 +80,37 @@ macro_rules! impl_system_function { } all_tuples!(impl_system_function, 0, 16, F); + +#[cfg(test)] +mod tests { + use crate::{ + self as bevy_ecs, + event::Event, + observer::Trigger, + system::{In, IntoSystem}, + world::World, + }; + + #[derive(Event)] + struct TriggerEvent; + + #[test] + fn test_piped_observer_systems_no_input() { + fn a(_: Trigger) {} + fn b() {} + + let mut world = World::new(); + world.observe(a.pipe(b)); + } + + #[test] + fn test_piped_observer_systems_with_inputs() { + fn a(_: Trigger) -> u32 { + 3 + } + fn b(_: In) {} + + let mut world = World::new(); + world.observe(a.pipe(b)); + } +}