bevy_ecs/system/
observer_system.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use crate::{
    prelude::{Bundle, Trigger},
    system::System,
};

use super::IntoSystem;

/// Implemented for [`System`]s that have a [`Trigger`] as the first argument.
pub trait ObserverSystem<E: 'static, B: Bundle, Out = ()>:
    System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static
{
}

impl<
        E: 'static,
        B: Bundle,
        Out,
        T: System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static,
    > ObserverSystem<E, B, Out> for T
{
}

/// Implemented for systems that convert into [`ObserverSystem`].
#[diagnostic::on_unimplemented(
    message = "`{Self}` cannot become an `ObserverSystem`",
    label = "the trait `IntoObserverSystem` is not implemented",
    note = "for function `ObserverSystem`s, ensure the first argument is a `Trigger<T>` and any subsequent ones are `SystemParam`"
)]
pub trait IntoObserverSystem<E: 'static, B: Bundle, M, Out = ()>: Send + 'static {
    /// The type of [`System`] that this instance converts into.
    type System: ObserverSystem<E, B, Out>;

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

impl<
        S: IntoSystem<Trigger<'static, E, B>, Out, M> + Send + 'static,
        M,
        Out,
        E: 'static,
        B: Bundle,
    > IntoObserverSystem<E, B, M, Out> for S
where
    S::System: ObserverSystem<E, B, Out>,
{
    type System = <S as IntoSystem<Trigger<'static, E, B>, Out, M>>::System;

    fn into_system(this: Self) -> Self::System {
        IntoSystem::into_system(this)
    }
}

#[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<TriggerEvent>) {}
        fn b() {}

        let mut world = World::new();
        world.add_observer(a.pipe(b));
    }

    #[test]
    fn test_piped_observer_systems_with_inputs() {
        fn a(_: Trigger<TriggerEvent>) -> u32 {
            3
        }
        fn b(_: In<u32>) {}

        let mut world = World::new();
        world.add_observer(a.pipe(b));
    }
}