Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/reflect/event.rs
9366 views
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
8
use crate::{event::Event, reflect::from_reflect_with_fallback, world::World};
9
use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry};
10
11
/// A struct used to operate on reflected [`Event`] trait of a type.
12
///
13
/// A [`ReflectEvent`] for type `T` can be obtained via
14
/// [`bevy_reflect::TypeRegistration::data`].
15
#[derive(Clone)]
16
pub struct ReflectEvent(ReflectEventFns);
17
18
/// The raw function pointers needed to make up a [`ReflectEvent`].
19
///
20
/// This is used when creating custom implementations of [`ReflectEvent`] with
21
/// [`ReflectEvent::new()`].
22
///
23
/// > **Note:**
24
/// > Creating custom implementations of [`ReflectEvent`] is an advanced feature
25
/// > that most users will not need. Usually a [`ReflectEvent`] is created for a
26
/// > type by deriving [`Reflect`] and adding the `#[reflect(Event)]` attribute.
27
/// > After adding the event to the [`TypeRegistry`], its [`ReflectEvent`] can
28
/// > then be retrieved when needed.
29
///
30
/// Creating a custom [`ReflectEvent`] may be useful if you need to create new
31
/// event types at runtime, for example, for scripting implementations.
32
///
33
/// By creating a custom [`ReflectEvent`] and inserting it into a type's
34
/// [`TypeRegistration`][bevy_reflect::TypeRegistration], you can modify the way
35
/// that reflected event of that type will be triggered in the Bevy world.
36
#[derive(Clone)]
37
pub struct ReflectEventFns {
38
/// Function pointer implementing [`ReflectEvent::trigger`].
39
pub trigger: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
40
}
41
42
impl ReflectEventFns {
43
/// Get the default set of [`ReflectEventFns`] for a specific event type
44
/// using its [`FromType`] implementation.
45
///
46
/// This is useful if you want to start with the default implementation
47
/// before overriding some of the functions to create a custom implementation.
48
pub fn new<'a, T: Event + FromReflect + TypePath>() -> Self
49
where
50
T::Trigger<'a>: Default,
51
{
52
<ReflectEvent as FromType<T>>::from_type().0
53
}
54
}
55
56
impl ReflectEvent {
57
/// Triggers a reflected [`Event`] like [`trigger()`](World::trigger).
58
pub fn trigger(&self, world: &mut World, event: &dyn PartialReflect, registry: &TypeRegistry) {
59
(self.0.trigger)(world, event, registry);
60
}
61
62
/// Create a custom implementation of [`ReflectEvent`].
63
///
64
/// This is an advanced feature,
65
/// useful for scripting implementations,
66
/// that should not be used by most users
67
/// unless you know what you are doing.
68
///
69
/// Usually you should derive [`Reflect`] and add the `#[reflect(Event)]`
70
/// attribute to generate a [`ReflectEvent`] implementation automatically.
71
///
72
/// See [`ReflectEventFns`] for more information.
73
pub fn new(fns: ReflectEventFns) -> Self {
74
ReflectEvent(fns)
75
}
76
77
/// The underlying function pointers implementing methods on [`ReflectEvent`].
78
///
79
/// This is useful when you want to keep track locally of an individual
80
/// function pointer.
81
///
82
/// Calling [`TypeRegistry::get`] followed by
83
/// [`TypeRegistration::data::<ReflectEvent>`] can be costly if done several
84
/// times per frame. Consider cloning [`ReflectEvent`] and keeping it
85
/// between frames, cloning a `ReflectEvent` is very cheap.
86
///
87
/// If you only need a subset of the methods on `ReflectEvent`,
88
/// use `fn_pointers` to get the underlying [`ReflectEventFns`]
89
/// and copy the subset of function pointers you care about.
90
///
91
/// [`TypeRegistration::data::<ReflectEvent>`]: bevy_reflect::TypeRegistration::data
92
/// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get
93
pub fn fn_pointers(&self) -> &ReflectEventFns {
94
&self.0
95
}
96
}
97
98
impl<'a, E: Event + Reflect + TypePath> FromType<E> for ReflectEvent
99
where
100
<E as Event>::Trigger<'a>: Default,
101
{
102
fn from_type() -> Self {
103
ReflectEvent(ReflectEventFns {
104
trigger: |world, reflected_event, registry| {
105
let event = from_reflect_with_fallback::<E>(reflected_event, world, registry);
106
world.trigger(event);
107
},
108
})
109
}
110
}
111
112