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