Skip to main content

bevy_ecs/observer/
system_param.rs

1//! System parameters for working with observers.
2
3use crate::{
4    change_detection::MaybeLocation,
5    event::{Event, EventKey, EventPattern, EventPatternTrigger, PropagateEntityTrigger},
6    prelude::*,
7    traversal::Traversal,
8};
9use bevy_ptr::Ptr;
10use core::{
11    fmt::Debug,
12    ops::{Deref, DerefMut},
13};
14
15/// A [system parameter] used by an observer to process events. See [`Observer`] and [`Event`] for examples.
16///
17/// `On` contains the triggered [`Event`] data for a given run of an `Observer`. It also provides access to the
18/// [`Trigger`](crate::event::Trigger), which for things like [`EntityEvent`] with a [`PropagateEntityTrigger`],
19/// includes control over event propagation.
20///
21/// [system parameter]: crate::system::SystemParam
22// SAFETY WARNING!
23// this type must _never_ expose anything with the 'w lifetime
24// See the safety discussion on `Trigger` for more details.
25pub struct On<'w, 't, E: EventPattern> {
26    observer: Entity,
27    // SAFETY WARNING: never expose this 'w lifetime
28    event: &'w mut E::Event,
29    // SAFETY WARNING: never expose this 'w lifetime
30    trigger: &'w mut EventPatternTrigger<'t, E>,
31    // SAFETY WARNING: never expose this 'w lifetime
32    trigger_context: &'w TriggerContext,
33}
34
35impl<'w, 't, E: EventPattern> On<'w, 't, E> {
36    /// Creates a new instance of [`On`] for the given triggered event.
37    pub fn new(
38        event: &'w mut E::Event,
39        observer: Entity,
40        trigger: &'w mut EventPatternTrigger<'t, E>,
41        trigger_context: &'w TriggerContext,
42    ) -> Self {
43        Self {
44            event,
45            observer,
46            trigger,
47            trigger_context,
48        }
49    }
50
51    /// Returns the event type of this [`On`] instance.
52    pub fn event_key(&self) -> EventKey {
53        self.trigger_context.event_key
54    }
55
56    /// Returns a reference to the triggered event.
57    pub fn event(&self) -> &E::Event {
58        self.event
59    }
60
61    /// Returns a mutable reference to the triggered event.
62    pub fn event_mut(&mut self) -> &mut E::Event {
63        self.event
64    }
65
66    /// Returns a pointer to the triggered event.
67    pub fn event_ptr(&self) -> Ptr<'_> {
68        Ptr::from(&self.event)
69    }
70
71    /// Returns the [`Trigger`](crate::event::Trigger) context for this event.
72    pub fn trigger(&self) -> &EventPatternTrigger<'t, E> {
73        self.trigger
74    }
75
76    /// Returns the mutable [`Trigger`](crate::event::Trigger) context for this event.
77    pub fn trigger_mut(&mut self) -> &mut EventPatternTrigger<'t, E> {
78        self.trigger
79    }
80
81    /// Returns the [`Entity`] of the [`Observer`] of the triggered event.
82    /// This allows you to despawn the observer, ceasing observation.
83    ///
84    /// # Examples
85    ///
86    /// ```rust
87    /// # use bevy_ecs::prelude::*;
88    ///
89    /// #[derive(EntityEvent)]  
90    /// struct AssertEvent {
91    ///     entity: Entity,
92    /// }
93    ///
94    /// fn assert_observer(event: On<AssertEvent>) {  
95    ///     assert_eq!(event.observer(), event.entity);  
96    /// }  
97    ///
98    /// let mut world = World::new();  
99    /// let entity = world.spawn(Observer::new(assert_observer)).id();  
100    ///
101    /// world.trigger(AssertEvent { entity });  
102    /// ```
103    pub fn observer(&self) -> Entity {
104        self.observer
105    }
106
107    /// Returns the source code location that triggered this observer, if the `track_location` cargo feature is enabled.
108    pub fn caller(&self) -> MaybeLocation {
109        self.trigger_context.caller
110    }
111}
112
113impl<'w, 't, const AUTO_PROPAGATE: bool, E, T> On<'w, 't, E>
114where
115    E: EventPattern<
116        Event: EntityEvent<Trigger<'t> = PropagateEntityTrigger<AUTO_PROPAGATE, E::Event, T>>,
117    >,
118    T: Traversal<E::Event>,
119{
120    /// Returns the original [`Entity`] that this [`EntityEvent`] targeted via [`EntityEvent::event_target`] when it was _first_ triggered,
121    /// prior to any propagation logic.
122    pub fn original_event_target(&self) -> Entity {
123        self.trigger.original_event_target
124    }
125
126    /// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.
127    ///
128    /// The path an [`EntityEvent`] will propagate along is specified by the [`Traversal`] component defined in [`PropagateEntityTrigger`].
129    ///
130    /// [`EntityEvent`] does not propagate by default. To enable propagation, you must:
131    /// + Enable propagation in [`EntityEvent`] using `#[entity_event(propagate)]`. See [`EntityEvent`] for details.
132    /// + Either call `propagate(true)` in the first observer or in the [`EntityEvent`] derive add `#[entity_event(auto_propagate)]`.
133    ///
134    /// You can prevent an event from propagating further using `propagate(false)`. This will prevent the event from triggering on the next
135    /// [`Entity`] in the [`Traversal`], but note that all remaining observers for the _current_ entity will still run.
136    ///
137    ///
138    /// [`Traversal`]: crate::traversal::Traversal
139    pub fn propagate(&mut self, should_propagate: bool) {
140        self.trigger.propagate = should_propagate;
141    }
142
143    /// Returns the value of the flag that controls event propagation. See [`propagate`] for more information.
144    ///
145    /// [`propagate`]: On::propagate
146    pub fn get_propagate(&self) -> bool {
147        self.trigger.propagate
148    }
149}
150
151impl<'w, 't, E> Debug for On<'w, 't, E>
152where
153    E: EventPattern,
154    E::Event: Event<Trigger<'t>: Debug> + Debug,
155{
156    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
157        f.debug_struct("On")
158            .field("event", &self.event)
159            .field("trigger", &self.trigger)
160            .finish()
161    }
162}
163
164impl<'w, 't, E: EventPattern> Deref for On<'w, 't, E> {
165    type Target = E::Event;
166
167    fn deref(&self) -> &Self::Target {
168        self.event
169    }
170}
171
172impl<'w, 't, E: EventPattern> DerefMut for On<'w, 't, E> {
173    fn deref_mut(&mut self) -> &mut Self::Target {
174        self.event
175    }
176}
177
178/// Metadata about a specific [`Event`] that triggered an observer.
179///
180/// This information is exposed via methods on [`On`].
181pub struct TriggerContext {
182    /// The [`EventKey`] the trigger targeted.
183    pub event_key: EventKey,
184    /// The location of the source code that triggered the observer.
185    pub caller: MaybeLocation,
186}