bevy_ecs/reflect/event.rs
1//! Definitions for [`Event`] reflection.
2//! This allows triggering events whose type is only known at runtime.
3//!
4//! This module exports two types: [`ReflectEventFns`] and [`ReflectEvent`].
5//!
6//! Same as [`component`](`super::component`), but for events.
7
8use alloc::boxed::Box;
9
10use crate::{
11 event::{Event, EventKey},
12 observer::{Observer, On},
13 reflect::from_reflect_with_fallback,
14 world::{DeferredWorld, World},
15};
16use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry};
17
18/// A struct used to operate on reflected [`Event`] trait of a type.
19///
20/// A [`ReflectEvent`] for type `T` can be obtained via
21/// [`bevy_reflect::TypeRegistration::data`].
22#[derive(Clone)]
23pub struct ReflectEvent(ReflectEventFns);
24
25/// The raw function pointers needed to make up a [`ReflectEvent`].
26///
27/// This is used when creating custom implementations of [`ReflectEvent`] with
28/// [`ReflectEvent::new()`].
29///
30/// > **Note:**
31/// > Creating custom implementations of [`ReflectEvent`] is an advanced feature
32/// > that most users will not need. Usually a [`ReflectEvent`] is created for a
33/// > type by deriving [`Reflect`] and adding the `#[reflect(Event)]` attribute.
34/// > After adding the event to the [`TypeRegistry`], its [`ReflectEvent`] can
35/// > then be retrieved when needed.
36///
37/// Creating a custom [`ReflectEvent`] may be useful if you need to create new
38/// event types at runtime, for example, for scripting implementations.
39///
40/// By creating a custom [`ReflectEvent`] and inserting it into a type's
41/// [`TypeRegistration`][bevy_reflect::TypeRegistration], you can modify the way
42/// that reflected event of that type will be triggered in the Bevy world.
43#[derive(Clone)]
44pub struct ReflectEventFns {
45 /// Function pointer implementing [`ReflectEvent::trigger`].
46 pub trigger: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
47 /// Function pointer implementing [`ReflectEvent::create_observer`].
48 pub create_observer: fn(Box<dyn Fn(&dyn Reflect, DeferredWorld) + Send + Sync>) -> Observer,
49 /// Function pointer implementing [`ReflectEvent::register_event_key`].
50 pub register_event_key: fn(&mut World) -> EventKey,
51}
52
53impl ReflectEventFns {
54 /// Get the default set of [`ReflectEventFns`] for a specific event type
55 /// using its [`FromType`] implementation.
56 ///
57 /// This is useful if you want to start with the default implementation
58 /// before overriding some of the functions to create a custom implementation.
59 pub fn new<'a, T: Event + FromReflect + TypePath>() -> Self
60 where
61 T::Trigger<'a>: Default,
62 {
63 <ReflectEvent as FromType<T>>::from_type().0
64 }
65}
66
67impl ReflectEvent {
68 /// Triggers a reflected [`Event`] like [`trigger()`](World::trigger).
69 pub fn trigger(&self, world: &mut World, event: &dyn PartialReflect, registry: &TypeRegistry) {
70 (self.0.trigger)(world, event, registry);
71 }
72
73 /// Creates an [`Observer`] for this [`Event`] that calls the given callback.
74 pub fn create_observer(
75 &self,
76 callback: Box<dyn Fn(&dyn Reflect, DeferredWorld) + Send + Sync>,
77 ) -> Observer {
78 (self.0.create_observer)(callback)
79 }
80
81 /// Generates the [`EventKey`] for this [`Event`].
82 ///
83 /// This is used by various dynamically typed observer APIs,
84 /// such as [`Observer::with_event_key`].
85 pub fn register_event_key(&self, world: &mut World) -> EventKey {
86 (self.0.register_event_key)(world)
87 }
88
89 /// Create a custom implementation of [`ReflectEvent`].
90 ///
91 /// This is an advanced feature,
92 /// useful for scripting implementations,
93 /// that should not be used by most users
94 /// unless you know what you are doing.
95 ///
96 /// Usually you should derive [`Reflect`] and add the `#[reflect(Event)]`
97 /// attribute to generate a [`ReflectEvent`] implementation automatically.
98 ///
99 /// See [`ReflectEventFns`] for more information.
100 pub fn new(fns: ReflectEventFns) -> Self {
101 ReflectEvent(fns)
102 }
103
104 /// The underlying function pointers implementing methods on [`ReflectEvent`].
105 ///
106 /// This is useful when you want to keep track locally of an individual
107 /// function pointer.
108 ///
109 /// Calling [`TypeRegistry::get`] followed by
110 /// [`TypeRegistration::data::<ReflectEvent>`] can be costly if done several
111 /// times per frame. Consider cloning [`ReflectEvent`] and keeping it
112 /// between frames, cloning a `ReflectEvent` is very cheap.
113 ///
114 /// If you only need a subset of the methods on `ReflectEvent`,
115 /// use `fn_pointers` to get the underlying [`ReflectEventFns`]
116 /// and copy the subset of function pointers you care about.
117 ///
118 /// [`TypeRegistration::data::<ReflectEvent>`]: bevy_reflect::TypeRegistration::data
119 /// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get
120 pub fn fn_pointers(&self) -> &ReflectEventFns {
121 &self.0
122 }
123}
124
125impl<'a, E: Event + Reflect + TypePath> FromType<E> for ReflectEvent
126where
127 <E as Event>::Trigger<'a>: Default,
128{
129 fn from_type() -> Self {
130 ReflectEvent(ReflectEventFns {
131 trigger: |world, reflected_event, registry| {
132 let event = from_reflect_with_fallback::<E>(reflected_event, world, registry);
133 world.trigger(event);
134 },
135 create_observer: |callback| {
136 Observer::new(move |event: On<E>, world: DeferredWorld| {
137 callback((*event).as_reflect(), world);
138 })
139 },
140 register_event_key: |world| world.register_event_key::<E>(),
141 })
142 }
143}