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}