Skip to main content

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}