Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/observer/system_param.rs
6849 views
1
//! System parameters for working with observers.
2
3
use crate::{
4
bundle::Bundle,
5
change_detection::MaybeLocation,
6
event::{Event, EventKey, PropagateEntityTrigger},
7
prelude::*,
8
traversal::Traversal,
9
};
10
use bevy_ptr::Ptr;
11
use core::{
12
fmt::Debug,
13
marker::PhantomData,
14
ops::{Deref, DerefMut},
15
};
16
17
/// A [system parameter] used by an observer to process events. See [`Observer`] and [`Event`] for examples.
18
///
19
/// `On` contains the triggered [`Event`] data for a given run of an `Observer`. It also provides access to the
20
/// [`Trigger`](crate::event::Trigger), which for things like [`EntityEvent`] with a [`PropagateEntityTrigger`],
21
/// includes control over event propagation.
22
///
23
/// The generic `B: Bundle` is used to further specialize the events that this observer is interested in.
24
/// The entity involved *does not* have to have these components, but the observer will only be
25
/// triggered if the event matches the components in `B`.
26
///
27
/// This is used to to avoid providing a generic argument in your event, as is done for [`Add`]
28
/// and the other lifecycle events.
29
///
30
/// Providing multiple components in this bundle will cause this event to be triggered by any
31
/// matching component in the bundle,
32
/// [rather than requiring all of them to be present](https://github.com/bevyengine/bevy/issues/15325).
33
///
34
/// [system parameter]: crate::system::SystemParam
35
// SAFETY WARNING!
36
// this type must _never_ expose anything with the 'w lifetime
37
// See the safety discussion on `Trigger` for more details.
38
pub struct On<'w, 't, E: Event, B: Bundle = ()> {
39
observer: Entity,
40
// SAFETY WARNING: never expose this 'w lifetime
41
event: &'w mut E,
42
// SAFETY WARNING: never expose this 'w lifetime
43
trigger: &'w mut E::Trigger<'t>,
44
// SAFETY WARNING: never expose this 'w lifetime
45
trigger_context: &'w TriggerContext,
46
_marker: PhantomData<B>,
47
}
48
49
/// Deprecated in favor of [`On`].
50
#[deprecated(since = "0.17.0", note = "Renamed to `On`.")]
51
pub type Trigger<'w, 't, E, B = ()> = On<'w, 't, E, B>;
52
53
impl<'w, 't, E: Event, B: Bundle> On<'w, 't, E, B> {
54
/// Creates a new instance of [`On`] for the given triggered event.
55
pub fn new(
56
event: &'w mut E,
57
observer: Entity,
58
trigger: &'w mut E::Trigger<'t>,
59
trigger_context: &'w TriggerContext,
60
) -> Self {
61
Self {
62
event,
63
observer,
64
trigger,
65
trigger_context,
66
_marker: PhantomData,
67
}
68
}
69
70
/// Returns the event type of this [`On`] instance.
71
pub fn event_key(&self) -> EventKey {
72
self.trigger_context.event_key
73
}
74
75
/// Returns a reference to the triggered event.
76
pub fn event(&self) -> &E {
77
self.event
78
}
79
80
/// Returns a mutable reference to the triggered event.
81
pub fn event_mut(&mut self) -> &mut E {
82
self.event
83
}
84
85
/// Returns a pointer to the triggered event.
86
pub fn event_ptr(&self) -> Ptr<'_> {
87
Ptr::from(&self.event)
88
}
89
90
/// Returns the [`Trigger`](crate::event::Trigger) context for this event.
91
pub fn trigger(&self) -> &E::Trigger<'t> {
92
self.trigger
93
}
94
95
/// Returns the mutable [`Trigger`](crate::event::Trigger) context for this event.
96
pub fn trigger_mut(&mut self) -> &mut E::Trigger<'t> {
97
self.trigger
98
}
99
100
/// Returns the [`Entity`] of the [`Observer`] of the triggered event.
101
/// This allows you to despawn the observer, ceasing observation.
102
///
103
/// # Examples
104
///
105
/// ```rust
106
/// # use bevy_ecs::prelude::*;
107
///
108
/// #[derive(EntityEvent)]
109
/// struct AssertEvent {
110
/// entity: Entity,
111
/// }
112
///
113
/// fn assert_observer(event: On<AssertEvent>) {
114
/// assert_eq!(event.observer(), event.entity);
115
/// }
116
///
117
/// let mut world = World::new();
118
/// let entity = world.spawn(Observer::new(assert_observer)).id();
119
///
120
/// world.trigger(AssertEvent { entity });
121
/// ```
122
pub fn observer(&self) -> Entity {
123
self.observer
124
}
125
126
/// Returns the source code location that triggered this observer, if the `track_location` cargo feature is enabled.
127
pub fn caller(&self) -> MaybeLocation {
128
self.trigger_context.caller
129
}
130
}
131
132
impl<'w, 't, E: EntityEvent, B: Bundle> On<'w, 't, E, B> {
133
/// A deprecated way to retrieve the entity that this [`EntityEvent`] targeted at.
134
///
135
/// Access the event via [`On::event`], then read the entity that the event was targeting.
136
/// Prefer using the field name directly for clarity,
137
/// but if you are working in a generic context, you can use [`EntityEvent::event_target`].
138
#[deprecated(
139
since = "0.17.0",
140
note = "Call On::event() to access the event, then read the target entity from the event directly."
141
)]
142
pub fn target(&self) -> Entity {
143
self.event.event_target()
144
}
145
}
146
147
impl<
148
'w,
149
't,
150
const AUTO_PROPAGATE: bool,
151
E: EntityEvent + for<'a> Event<Trigger<'a> = PropagateEntityTrigger<AUTO_PROPAGATE, E, T>>,
152
B: Bundle,
153
T: Traversal<E>,
154
> On<'w, 't, E, B>
155
{
156
/// Returns the original [`Entity`] that this [`EntityEvent`] targeted via [`EntityEvent::event_target`] when it was _first_ triggered,
157
/// prior to any propagation logic.
158
pub fn original_event_target(&self) -> Entity {
159
self.trigger.original_event_target
160
}
161
162
/// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.
163
///
164
/// The path an [`EntityEvent`] will propagate along is specified by the [`Traversal`] component defined in [`PropagateEntityTrigger`].
165
///
166
/// [`EntityEvent`] does not propagate by default. To enable propagation, you must:
167
/// + Enable propagation in [`EntityEvent`] using `#[entity_event(propagate)]`. See [`EntityEvent`] for details.
168
/// + Either call `propagate(true)` in the first observer or in the [`EntityEvent`] derive add `#[entity_event(auto_propagate)]`.
169
///
170
/// You can prevent an event from propagating further using `propagate(false)`. This will prevent the event from triggering on the next
171
/// [`Entity`] in the [`Traversal`], but note that all remaining observers for the _current_ entity will still run.
172
///
173
///
174
/// [`Traversal`]: crate::traversal::Traversal
175
pub fn propagate(&mut self, should_propagate: bool) {
176
self.trigger.propagate = should_propagate;
177
}
178
179
/// Returns the value of the flag that controls event propagation. See [`propagate`] for more information.
180
///
181
/// [`propagate`]: On::propagate
182
pub fn get_propagate(&self) -> bool {
183
self.trigger.propagate
184
}
185
}
186
187
impl<'w, 't, E: for<'a> Event<Trigger<'a>: Debug> + Debug, B: Bundle> Debug for On<'w, 't, E, B> {
188
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189
f.debug_struct("On")
190
.field("event", &self.event)
191
.field("trigger", &self.trigger)
192
.field("_marker", &self._marker)
193
.finish()
194
}
195
}
196
197
impl<'w, 't, E: Event, B: Bundle> Deref for On<'w, 't, E, B> {
198
type Target = E;
199
200
fn deref(&self) -> &Self::Target {
201
self.event
202
}
203
}
204
205
impl<'w, 't, E: Event, B: Bundle> DerefMut for On<'w, 't, E, B> {
206
fn deref_mut(&mut self) -> &mut Self::Target {
207
self.event
208
}
209
}
210
211
/// Metadata about a specific [`Event`] that triggered an observer.
212
///
213
/// This information is exposed via methods on [`On`].
214
pub struct TriggerContext {
215
/// The [`EventKey`] the trigger targeted.
216
pub event_key: EventKey,
217
/// The location of the source code that triggered the observer.
218
pub caller: MaybeLocation,
219
}
220
221