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