bevy_ecs/event/base.rs
1use crate::change_detection::MaybeLocation;
2use crate::component::ComponentId;
3use crate::world::World;
4use crate::{component::Component, traversal::Traversal};
5#[cfg(feature = "bevy_reflect")]
6use bevy_reflect::Reflect;
7use core::{
8 cmp::Ordering,
9 fmt,
10 hash::{Hash, Hasher},
11 marker::PhantomData,
12};
13
14/// Something that "happens" and might be read / observed by app logic.
15///
16/// Events can be stored in an [`Events<E>`] resource
17/// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter.
18///
19/// Events can also be "triggered" on a [`World`], which will then cause any [`Observer`] of that trigger to run.
20///
21/// Events must be thread-safe.
22///
23/// ## Derive
24/// This trait can be derived.
25/// Adding `auto_propagate` sets [`Self::AUTO_PROPAGATE`] to true.
26/// Adding `traversal = "X"` sets [`Self::Traversal`] to be of type "X".
27///
28/// ```
29/// use bevy_ecs::prelude::*;
30///
31/// #[derive(Event)]
32/// #[event(auto_propagate)]
33/// struct MyEvent;
34/// ```
35///
36///
37/// [`World`]: crate::world::World
38/// [`ComponentId`]: crate::component::ComponentId
39/// [`Observer`]: crate::observer::Observer
40/// [`Events<E>`]: super::Events
41/// [`EventReader`]: super::EventReader
42/// [`EventWriter`]: super::EventWriter
43#[diagnostic::on_unimplemented(
44 message = "`{Self}` is not an `Event`",
45 label = "invalid `Event`",
46 note = "consider annotating `{Self}` with `#[derive(Event)]`"
47)]
48pub trait Event: Send + Sync + 'static {
49 /// The component that describes which Entity to propagate this event to next, when [propagation] is enabled.
50 ///
51 /// [propagation]: crate::observer::Trigger::propagate
52 type Traversal: Traversal<Self>;
53
54 /// When true, this event will always attempt to propagate when [triggered], without requiring a call
55 /// to [`Trigger::propagate`].
56 ///
57 /// [triggered]: crate::system::Commands::trigger_targets
58 /// [`Trigger::propagate`]: crate::observer::Trigger::propagate
59 const AUTO_PROPAGATE: bool = false;
60
61 /// Generates the [`ComponentId`] for this event type.
62 ///
63 /// If this type has already been registered,
64 /// this will return the existing [`ComponentId`].
65 ///
66 /// This is used by various dynamically typed observer APIs,
67 /// such as [`World::trigger_targets_dynamic`].
68 ///
69 /// # Warning
70 ///
71 /// This method should not be overridden by implementors,
72 /// and should always correspond to the implementation of [`component_id`](Event::component_id).
73 fn register_component_id(world: &mut World) -> ComponentId {
74 world.register_component::<EventWrapperComponent<Self>>()
75 }
76
77 /// Fetches the [`ComponentId`] for this event type,
78 /// if it has already been generated.
79 ///
80 /// This is used by various dynamically typed observer APIs,
81 /// such as [`World::trigger_targets_dynamic`].
82 ///
83 /// # Warning
84 ///
85 /// This method should not be overridden by implementors,
86 /// and should always correspond to the implementation of [`register_component_id`](Event::register_component_id).
87 fn component_id(world: &World) -> Option<ComponentId> {
88 world.component_id::<EventWrapperComponent<Self>>()
89 }
90}
91
92/// An internal type that implements [`Component`] for a given [`Event`] type.
93///
94/// This exists so we can easily get access to a unique [`ComponentId`] for each [`Event`] type,
95/// without requiring that [`Event`] types implement [`Component`] directly.
96/// [`ComponentId`] is used internally as a unique identitifier for events because they are:
97///
98/// - Unique to each event type.
99/// - Can be quickly generated and looked up.
100/// - Are compatible with dynamic event types, which aren't backed by a Rust type.
101///
102/// This type is an implementation detail and should never be made public.
103// TODO: refactor events to store their metadata on distinct entities, rather than using `ComponentId`
104#[derive(Component)]
105struct EventWrapperComponent<E: Event + ?Sized>(PhantomData<E>);
106
107/// An `EventId` uniquely identifies an event stored in a specific [`World`].
108///
109/// An `EventId` can among other things be used to trace the flow of an event from the point it was
110/// sent to the point it was processed. `EventId`s increase monotonically by send order.
111///
112/// [`World`]: crate::world::World
113#[cfg_attr(
114 feature = "bevy_reflect",
115 derive(Reflect),
116 reflect(Clone, Debug, PartialEq, Hash)
117)]
118pub struct EventId<E: Event> {
119 /// Uniquely identifies the event associated with this ID.
120 // This value corresponds to the order in which each event was added to the world.
121 pub id: usize,
122 /// The source code location that triggered this event.
123 pub caller: MaybeLocation,
124 #[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
125 pub(super) _marker: PhantomData<E>,
126}
127
128impl<E: Event> Copy for EventId<E> {}
129
130impl<E: Event> Clone for EventId<E> {
131 fn clone(&self) -> Self {
132 *self
133 }
134}
135
136impl<E: Event> fmt::Display for EventId<E> {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 <Self as fmt::Debug>::fmt(self, f)
139 }
140}
141
142impl<E: Event> fmt::Debug for EventId<E> {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 write!(
145 f,
146 "event<{}>#{}",
147 core::any::type_name::<E>().split("::").last().unwrap(),
148 self.id,
149 )
150 }
151}
152
153impl<E: Event> PartialEq for EventId<E> {
154 fn eq(&self, other: &Self) -> bool {
155 self.id == other.id
156 }
157}
158
159impl<E: Event> Eq for EventId<E> {}
160
161impl<E: Event> PartialOrd for EventId<E> {
162 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
163 Some(self.cmp(other))
164 }
165}
166
167impl<E: Event> Ord for EventId<E> {
168 fn cmp(&self, other: &Self) -> Ordering {
169 self.id.cmp(&other.id)
170 }
171}
172
173impl<E: Event> Hash for EventId<E> {
174 fn hash<H: Hasher>(&self, state: &mut H) {
175 Hash::hash(&self.id, state);
176 }
177}
178
179#[derive(Debug)]
180#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
181pub(crate) struct EventInstance<E: Event> {
182 pub event_id: EventId<E>,
183 pub event: E,
184}