Skip to content

Commit da997dd

Browse files
Allow observer systems to have outputs (#14159)
# Objective Fixes #14157 ## Solution - Update the ObserverSystem traits to accept an `Out` parameter ## Testing - Added a test where an observer system has a non-empty output which is piped into another system Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
1 parent e727170 commit da997dd

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

crates/bevy_ecs/src/system/observer_system.rs

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,40 @@ use super::IntoSystem;
1010
/// Implemented for systems that have an [`Observer`] as the first argument.
1111
///
1212
/// [`Observer`]: crate::observer::Observer
13-
pub trait ObserverSystem<E: 'static, B: Bundle>:
14-
System<In = Trigger<'static, E, B>, Out = ()> + Send + 'static
13+
pub trait ObserverSystem<E: 'static, B: Bundle, Out = ()>:
14+
System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static
1515
{
1616
}
1717

18-
impl<E: 'static, B: Bundle, T: System<In = Trigger<'static, E, B>, Out = ()> + Send + 'static>
19-
ObserverSystem<E, B> for T
18+
impl<
19+
E: 'static,
20+
B: Bundle,
21+
Out,
22+
T: System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static,
23+
> ObserverSystem<E, B, Out> for T
2024
{
2125
}
2226

2327
/// Implemented for systems that convert into [`ObserverSystem`].
24-
pub trait IntoObserverSystem<E: 'static, B: Bundle, M>: Send + 'static {
28+
pub trait IntoObserverSystem<E: 'static, B: Bundle, M, Out = ()>: Send + 'static {
2529
/// The type of [`System`] that this instance converts into.
26-
type System: ObserverSystem<E, B>;
30+
type System: ObserverSystem<E, B, Out>;
2731

2832
/// Turns this value into its corresponding [`System`].
2933
fn into_system(this: Self) -> Self::System;
3034
}
3135

32-
impl<S: IntoSystem<Trigger<'static, E, B>, (), M> + Send + 'static, M, E: 'static, B: Bundle>
33-
IntoObserverSystem<E, B, M> for S
36+
impl<
37+
S: IntoSystem<Trigger<'static, E, B>, Out, M> + Send + 'static,
38+
M,
39+
Out,
40+
E: 'static,
41+
B: Bundle,
42+
> IntoObserverSystem<E, B, M, Out> for S
3443
where
35-
S::System: ObserverSystem<E, B>,
44+
S::System: ObserverSystem<E, B, Out>,
3645
{
37-
type System = <S as IntoSystem<Trigger<'static, E, B>, (), M>>::System;
46+
type System = <S as IntoSystem<Trigger<'static, E, B>, Out, M>>::System;
3847

3948
fn into_system(this: Self) -> Self::System {
4049
IntoSystem::into_system(this)
@@ -44,23 +53,23 @@ where
4453
macro_rules! impl_system_function {
4554
($($param: ident),*) => {
4655
#[allow(non_snake_case)]
47-
impl<E: 'static, B: Bundle, Func: Send + Sync + 'static, $($param: SystemParam),*> SystemParamFunction<fn(Trigger<E, B>, $($param,)*)> for Func
56+
impl<E: 'static, B: Bundle, Out, Func: Send + Sync + 'static, $($param: SystemParam),*> SystemParamFunction<fn(Trigger<E, B>, $($param,)*)> for Func
4857
where
4958
for <'a> &'a mut Func:
50-
FnMut(Trigger<E, B>, $($param),*) +
51-
FnMut(Trigger<E, B>, $(SystemParamItem<$param>),*)
59+
FnMut(Trigger<E, B>, $($param),*) -> Out +
60+
FnMut(Trigger<E, B>, $(SystemParamItem<$param>),*) -> Out, Out: 'static
5261
{
5362
type In = Trigger<'static, E, B>;
54-
type Out = ();
63+
type Out = Out;
5564
type Param = ($($param,)*);
5665
#[inline]
57-
fn run(&mut self, input: Trigger<'static, E, B>, param_value: SystemParamItem< ($($param,)*)>) {
66+
fn run(&mut self, input: Trigger<'static, E, B>, param_value: SystemParamItem< ($($param,)*)>) -> Out {
5867
#[allow(clippy::too_many_arguments)]
59-
fn call_inner<E: 'static, B: Bundle, $($param,)*>(
60-
mut f: impl FnMut(Trigger<'static, E, B>, $($param,)*),
68+
fn call_inner<E: 'static, B: Bundle, Out, $($param,)*>(
69+
mut f: impl FnMut(Trigger<'static, E, B>, $($param,)*) -> Out,
6170
input: Trigger<'static, E, B>,
6271
$($param: $param,)*
63-
){
72+
) -> Out{
6473
f(input, $($param,)*)
6574
}
6675
let ($($param,)*) = param_value;
@@ -71,3 +80,37 @@ macro_rules! impl_system_function {
7180
}
7281

7382
all_tuples!(impl_system_function, 0, 16, F);
83+
84+
#[cfg(test)]
85+
mod tests {
86+
use crate::{
87+
self as bevy_ecs,
88+
event::Event,
89+
observer::Trigger,
90+
system::{In, IntoSystem},
91+
world::World,
92+
};
93+
94+
#[derive(Event)]
95+
struct TriggerEvent;
96+
97+
#[test]
98+
fn test_piped_observer_systems_no_input() {
99+
fn a(_: Trigger<TriggerEvent>) {}
100+
fn b() {}
101+
102+
let mut world = World::new();
103+
world.observe(a.pipe(b));
104+
}
105+
106+
#[test]
107+
fn test_piped_observer_systems_with_inputs() {
108+
fn a(_: Trigger<TriggerEvent>) -> u32 {
109+
3
110+
}
111+
fn b(_: In<u32>) {}
112+
113+
let mut world = World::new();
114+
world.observe(a.pipe(b));
115+
}
116+
}

0 commit comments

Comments
 (0)