Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/event/base.rs
6600 views
1
use crate::change_detection::MaybeLocation;
2
use crate::component::ComponentId;
3
use crate::world::World;
4
use crate::{component::Component, traversal::Traversal};
5
#[cfg(feature = "bevy_reflect")]
6
use bevy_reflect::Reflect;
7
use core::{
8
cmp::Ordering,
9
fmt,
10
hash::{Hash, Hasher},
11
marker::PhantomData,
12
};
13
14
/// Something that "happens" and can be processed by app logic.
15
///
16
/// Events can be triggered on a [`World`] using a method like [`trigger`](World::trigger),
17
/// causing any global [`Observer`] watching that event to run. This allows for push-based
18
/// event handling where observers are immediately notified of events as they happen.
19
///
20
/// Additional event handling behavior can be enabled by implementing the [`EntityEvent`]
21
/// and [`BufferedEvent`] traits:
22
///
23
/// - [`EntityEvent`]s support targeting specific entities, triggering any observers watching those targets.
24
/// They are useful for entity-specific event handlers and can even be propagated from one entity to another.
25
/// - [`BufferedEvent`]s support a pull-based event handling system where events are written using an [`EventWriter`]
26
/// and read later using an [`EventReader`]. This is an alternative to observers that allows efficient batch processing
27
/// of events at fixed points in a schedule.
28
///
29
/// Events must be thread-safe.
30
///
31
/// # Usage
32
///
33
/// The [`Event`] trait can be derived:
34
///
35
/// ```
36
/// # use bevy_ecs::prelude::*;
37
/// #
38
/// #[derive(Event)]
39
/// struct Speak {
40
/// message: String,
41
/// }
42
/// ```
43
///
44
/// An [`Observer`] can then be added to listen for this event type:
45
///
46
/// ```
47
/// # use bevy_ecs::prelude::*;
48
/// #
49
/// # #[derive(Event)]
50
/// # struct Speak {
51
/// # message: String,
52
/// # }
53
/// #
54
/// # let mut world = World::new();
55
/// #
56
/// world.add_observer(|event: On<Speak>| {
57
/// println!("{}", event.message);
58
/// });
59
/// ```
60
///
61
/// The event can be triggered on the [`World`] using the [`trigger`](World::trigger) method:
62
///
63
/// ```
64
/// # use bevy_ecs::prelude::*;
65
/// #
66
/// # #[derive(Event)]
67
/// # struct Speak {
68
/// # message: String,
69
/// # }
70
/// #
71
/// # let mut world = World::new();
72
/// #
73
/// # world.add_observer(|event: On<Speak>| {
74
/// # println!("{}", event.message);
75
/// # });
76
/// #
77
/// # world.flush();
78
/// #
79
/// world.trigger(Speak {
80
/// message: "Hello!".to_string(),
81
/// });
82
/// ```
83
///
84
/// For events that additionally need entity targeting or buffering, consider also deriving
85
/// [`EntityEvent`] or [`BufferedEvent`], respectively.
86
///
87
/// [`World`]: crate::world::World
88
/// [`Observer`]: crate::observer::Observer
89
/// [`EventReader`]: super::EventReader
90
/// [`EventWriter`]: super::EventWriter
91
#[diagnostic::on_unimplemented(
92
message = "`{Self}` is not an `Event`",
93
label = "invalid `Event`",
94
note = "consider annotating `{Self}` with `#[derive(Event)]`"
95
)]
96
pub trait Event: Send + Sync + 'static {
97
/// Generates the [`EventKey`] for this event type.
98
///
99
/// If this type has already been registered,
100
/// this will return the existing [`EventKey`].
101
///
102
/// This is used by various dynamically typed observer APIs,
103
/// such as [`World::trigger_targets_dynamic`].
104
///
105
/// # Warning
106
///
107
/// This method should not be overridden by implementers,
108
/// and should always correspond to the implementation of [`event_key`](Event::event_key).
109
fn register_event_key(world: &mut World) -> EventKey {
110
EventKey(world.register_component::<EventWrapperComponent<Self>>())
111
}
112
113
/// Fetches the [`EventKey`] for this event type,
114
/// if it has already been generated.
115
///
116
/// This is used by various dynamically typed observer APIs,
117
/// such as [`World::trigger_targets_dynamic`].
118
///
119
/// # Warning
120
///
121
/// This method should not be overridden by implementers,
122
/// and should always correspond to the implementation of
123
/// [`register_event_key`](Event::register_event_key).
124
fn event_key(world: &World) -> Option<EventKey> {
125
world
126
.component_id::<EventWrapperComponent<Self>>()
127
.map(EventKey)
128
}
129
}
130
131
/// An [`Event`] that can be targeted at specific entities.
132
///
133
/// Entity events can be triggered on a [`World`] with specific entity targets using a method
134
/// like [`trigger_targets`](World::trigger_targets), causing any [`Observer`] watching the event
135
/// for those entities to run.
136
///
137
/// Unlike basic [`Event`]s, entity events can optionally be propagated from one entity target to another
138
/// based on the [`EntityEvent::Traversal`] type associated with the event. This enables use cases
139
/// such as bubbling events to parent entities for UI purposes.
140
///
141
/// Entity events must be thread-safe.
142
///
143
/// # Usage
144
///
145
/// The [`EntityEvent`] trait can be derived. The `event` attribute can be used to further configure
146
/// the propagation behavior: adding `auto_propagate` sets [`EntityEvent::AUTO_PROPAGATE`] to `true`,
147
/// while adding `traversal = X` sets [`EntityEvent::Traversal`] to be of type `X`.
148
///
149
/// ```
150
/// # use bevy_ecs::prelude::*;
151
/// #
152
/// // When the `Damage` event is triggered on an entity, bubble the event up to ancestors.
153
/// #[derive(EntityEvent)]
154
/// #[entity_event(traversal = &'static ChildOf, auto_propagate)]
155
/// struct Damage {
156
/// amount: f32,
157
/// }
158
/// ```
159
///
160
/// An [`Observer`] can then be added to listen for this event type for the desired entity:
161
///
162
/// ```
163
/// # use bevy_ecs::prelude::*;
164
/// #
165
/// # #[derive(EntityEvent)]
166
/// # #[entity_event(traversal = &'static ChildOf, auto_propagate)]
167
/// # struct Damage {
168
/// # amount: f32,
169
/// # }
170
/// #
171
/// # #[derive(Component)]
172
/// # struct Health(f32);
173
/// #
174
/// # #[derive(Component)]
175
/// # struct Enemy;
176
/// #
177
/// # #[derive(Component)]
178
/// # struct ArmorPiece;
179
/// #
180
/// # let mut world = World::new();
181
/// #
182
/// // Spawn an enemy entity.
183
/// let enemy = world.spawn((Enemy, Health(100.0))).id();
184
///
185
/// // Spawn some armor as a child of the enemy entity.
186
/// // When the armor takes damage, it will bubble the event up to the enemy,
187
/// // which can then handle the event with its own observer.
188
/// let armor_piece = world
189
/// .spawn((ArmorPiece, Health(25.0), ChildOf(enemy)))
190
/// .observe(|event: On<Damage>, mut query: Query<&mut Health>| {
191
/// // Note: `On::entity` only exists because this is an `EntityEvent`.
192
/// let mut health = query.get_mut(event.entity()).unwrap();
193
/// health.0 -= event.amount;
194
/// })
195
/// .id();
196
/// ```
197
///
198
/// The event can be triggered on the [`World`] using the [`trigger_targets`](World::trigger_targets) method,
199
/// providing the desired entity target(s):
200
///
201
/// ```
202
/// # use bevy_ecs::prelude::*;
203
/// #
204
/// # #[derive(EntityEvent)]
205
/// # #[entity_event(traversal = &'static ChildOf, auto_propagate)]
206
/// # struct Damage {
207
/// # amount: f32,
208
/// # }
209
/// #
210
/// # #[derive(Component)]
211
/// # struct Health(f32);
212
/// #
213
/// # #[derive(Component)]
214
/// # struct Enemy;
215
/// #
216
/// # #[derive(Component)]
217
/// # struct ArmorPiece;
218
/// #
219
/// # let mut world = World::new();
220
/// #
221
/// # let enemy = world.spawn((Enemy, Health(100.0))).id();
222
/// # let armor_piece = world
223
/// # .spawn((ArmorPiece, Health(25.0), ChildOf(enemy)))
224
/// # .observe(|event: On<Damage>, mut query: Query<&mut Health>| {
225
/// # // Note: `On::entity` only exists because this is an `EntityEvent`.
226
/// # let mut health = query.get_mut(event.entity()).unwrap();
227
/// # health.0 -= event.amount;
228
/// # })
229
/// # .id();
230
/// #
231
/// # world.flush();
232
/// #
233
/// world.trigger_targets(Damage { amount: 10.0 }, armor_piece);
234
/// ```
235
///
236
/// [`World`]: crate::world::World
237
/// [`TriggerTargets`]: crate::observer::TriggerTargets
238
/// [`Observer`]: crate::observer::Observer
239
/// [`Events<E>`]: super::Events
240
/// [`EventReader`]: super::EventReader
241
/// [`EventWriter`]: super::EventWriter
242
#[diagnostic::on_unimplemented(
243
message = "`{Self}` is not an `EntityEvent`",
244
label = "invalid `EntityEvent`",
245
note = "consider annotating `{Self}` with `#[derive(EntityEvent)]`"
246
)]
247
pub trait EntityEvent: Event {
248
/// The component that describes which [`Entity`] to propagate this event to next, when [propagation] is enabled.
249
///
250
/// [`Entity`]: crate::entity::Entity
251
/// [propagation]: crate::observer::On::propagate
252
type Traversal: Traversal<Self>;
253
254
/// When true, this event will always attempt to propagate when [triggered], without requiring a call
255
/// to [`On::propagate`].
256
///
257
/// [triggered]: crate::system::Commands::trigger_targets
258
/// [`On::propagate`]: crate::observer::On::propagate
259
const AUTO_PROPAGATE: bool = false;
260
}
261
262
/// A buffered event for pull-based event handling.
263
///
264
/// Buffered events can be written with [`EventWriter`] and read using the [`EventReader`] system parameter.
265
/// These events are stored in the [`Events<E>`] resource, and require periodically polling the world for new events,
266
/// typically in a system that runs as part of a schedule.
267
///
268
/// While the polling imposes a small overhead, buffered events are useful for efficiently batch processing
269
/// a large number of events at once. This can make them more efficient than [`Event`]s used by [`Observer`]s
270
/// for events that happen at a high frequency or in large quantities.
271
///
272
/// Unlike [`Event`]s triggered for observers, buffered events are evaluated at fixed points in the schedule
273
/// rather than immediately when they are sent. This allows for more predictable scheduling and deferring
274
/// event processing to a later point in time.
275
///
276
/// Buffered events do *not* trigger observers automatically when they are written via an [`EventWriter`].
277
/// However, they can still also be triggered on a [`World`] in case you want both buffered and immediate
278
/// event handling for the same event.
279
///
280
/// Buffered events must be thread-safe.
281
///
282
/// # Usage
283
///
284
/// The [`BufferedEvent`] trait can be derived:
285
///
286
/// ```
287
/// # use bevy_ecs::prelude::*;
288
/// #
289
/// #[derive(BufferedEvent)]
290
/// struct Message(String);
291
/// ```
292
///
293
/// The event can then be written to the event buffer using an [`EventWriter`]:
294
///
295
/// ```
296
/// # use bevy_ecs::prelude::*;
297
/// #
298
/// # #[derive(BufferedEvent)]
299
/// # struct Message(String);
300
/// #
301
/// fn write_hello(mut writer: EventWriter<Message>) {
302
/// writer.write(Message("Hello!".to_string()));
303
/// }
304
/// ```
305
///
306
/// Buffered events can be efficiently read using an [`EventReader`]:
307
///
308
/// ```
309
/// # use bevy_ecs::prelude::*;
310
/// #
311
/// # #[derive(BufferedEvent)]
312
/// # struct Message(String);
313
/// #
314
/// fn read_messages(mut reader: EventReader<Message>) {
315
/// // Process all buffered events of type `Message`.
316
/// for Message(message) in reader.read() {
317
/// println!("{message}");
318
/// }
319
/// }
320
/// ```
321
///
322
/// [`World`]: crate::world::World
323
/// [`Observer`]: crate::observer::Observer
324
/// [`Events<E>`]: super::Events
325
/// [`EventReader`]: super::EventReader
326
/// [`EventWriter`]: super::EventWriter
327
#[diagnostic::on_unimplemented(
328
message = "`{Self}` is not an `BufferedEvent`",
329
label = "invalid `BufferedEvent`",
330
note = "consider annotating `{Self}` with `#[derive(BufferedEvent)]`"
331
)]
332
pub trait BufferedEvent: Send + Sync + 'static {}
333
334
/// An internal type that implements [`Component`] for a given [`Event`] type.
335
///
336
/// This exists so we can easily get access to a unique [`ComponentId`] for each [`Event`] type,
337
/// without requiring that [`Event`] types implement [`Component`] directly.
338
/// [`ComponentId`] is used internally as a unique identifier for events because they are:
339
///
340
/// - Unique to each event type.
341
/// - Can be quickly generated and looked up.
342
/// - Are compatible with dynamic event types, which aren't backed by a Rust type.
343
///
344
/// This type is an implementation detail and should never be made public.
345
// TODO: refactor events to store their metadata on distinct entities, rather than using `ComponentId`
346
#[derive(Component)]
347
struct EventWrapperComponent<E: Event + ?Sized>(PhantomData<E>);
348
349
/// An `EventId` uniquely identifies an event stored in a specific [`World`].
350
///
351
/// An `EventId` can among other things be used to trace the flow of an event from the point it was
352
/// sent to the point it was processed. `EventId`s increase monotonically by send order.
353
///
354
/// [`World`]: crate::world::World
355
#[cfg_attr(
356
feature = "bevy_reflect",
357
derive(Reflect),
358
reflect(Clone, Debug, PartialEq, Hash)
359
)]
360
pub struct EventId<E: BufferedEvent> {
361
/// Uniquely identifies the event associated with this ID.
362
// This value corresponds to the order in which each event was added to the world.
363
pub id: usize,
364
/// The source code location that triggered this event.
365
pub caller: MaybeLocation,
366
#[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
367
pub(super) _marker: PhantomData<E>,
368
}
369
370
impl<E: BufferedEvent> Copy for EventId<E> {}
371
372
impl<E: BufferedEvent> Clone for EventId<E> {
373
fn clone(&self) -> Self {
374
*self
375
}
376
}
377
378
impl<E: BufferedEvent> fmt::Display for EventId<E> {
379
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380
<Self as fmt::Debug>::fmt(self, f)
381
}
382
}
383
384
impl<E: BufferedEvent> fmt::Debug for EventId<E> {
385
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386
write!(
387
f,
388
"event<{}>#{}",
389
core::any::type_name::<E>().split("::").last().unwrap(),
390
self.id,
391
)
392
}
393
}
394
395
impl<E: BufferedEvent> PartialEq for EventId<E> {
396
fn eq(&self, other: &Self) -> bool {
397
self.id == other.id
398
}
399
}
400
401
impl<E: BufferedEvent> Eq for EventId<E> {}
402
403
impl<E: BufferedEvent> PartialOrd for EventId<E> {
404
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
405
Some(self.cmp(other))
406
}
407
}
408
409
impl<E: BufferedEvent> Ord for EventId<E> {
410
fn cmp(&self, other: &Self) -> Ordering {
411
self.id.cmp(&other.id)
412
}
413
}
414
415
impl<E: BufferedEvent> Hash for EventId<E> {
416
fn hash<H: Hasher>(&self, state: &mut H) {
417
Hash::hash(&self.id, state);
418
}
419
}
420
421
#[derive(Debug)]
422
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
423
pub(crate) struct EventInstance<E: BufferedEvent> {
424
pub event_id: EventId<E>,
425
pub event: E,
426
}
427
428
/// A unique identifier for an [`Event`], used by [observers].
429
///
430
/// You can look up the key for your event by calling the [`Event::event_key`] method.
431
///
432
/// [observers]: crate::observer
433
#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
434
pub struct EventKey(pub(crate) ComponentId);
435
436
impl EventKey {
437
/// Returns the internal [`ComponentId`].
438
#[inline]
439
pub(crate) fn component_id(&self) -> ComponentId {
440
self.0
441
}
442
}
443
444