bevy_reflect/type_data.rs
1use ::alloc::boxed::Box;
2use bevy_reflect::TypeRegistration;
3use downcast_rs::{impl_downcast, Downcast};
4
5/// A trait for representing type metadata.
6///
7/// Type data can be registered to the [`TypeRegistry`] and stored on a type's [`TypeRegistration`].
8///
9/// While type data is often generated using the [`#[reflect_trait]`](crate::reflect_trait) macro,
10/// almost any type that implements [`Clone`] can be considered "type data".
11/// This is because it has a blanket implementation over all `T` where `T: Clone + Send + Sync + 'static`.
12///
13/// For creating your own type data, see the [`CreateTypeData`] trait.
14///
15/// See the [crate-level documentation] for more information on type data and type registration.
16///
17/// [`TypeRegistry`]: crate::TypeRegistry
18/// [`TypeRegistration`]: crate::TypeRegistration
19/// [crate-level documentation]: crate
20pub trait TypeData: Downcast + Send + Sync {
21 /// Creates a type-erased clone of `self`.
22 fn clone_type_data(&self) -> Box<dyn TypeData>;
23}
24impl_downcast!(TypeData);
25
26impl<T: 'static + Send + Sync> TypeData for T
27where
28 T: Clone,
29{
30 fn clone_type_data(&self) -> Box<dyn TypeData> {
31 Box::new(self.clone())
32 }
33}
34
35/// A trait for creating [`TypeData`].
36///
37/// Normally any type that is `Clone + Send + Sync + 'static` can be used as type data
38/// and inserted into a [`TypeRegistration`] using [`TypeRegistration::insert`]
39/// However, only types that implement this trait may be registered using [`TypeRegistry::register_type_data`],
40/// [`TypeRegistry::register_type_data_with`], or via the `#[reflect(MyTrait)]` attribute with the [`Reflect` derive macro].
41///
42/// Note that in order to work with the `#[reflect(MyTrait)]` attribute,
43/// implementors must be named with the `Reflect` prefix (e.g. `ReflectMyTrait`).
44///
45/// # Input
46///
47/// By default, this trait expects no input for creating the type data
48/// (the `Input` type parameter defaults to `()`).
49///
50/// However, implementors may choose to implement this trait with other input types.
51/// As long as the implementations don't conflict, multiple different input types can be specified.
52///
53/// # Example
54///
55/// ```
56/// # use bevy_reflect::{CreateTypeData, Reflect};
57/// trait Combine {
58/// fn combine(a: f32, b: f32) -> f32;
59/// }
60///
61/// #[derive(Clone)]
62/// struct ReflectCombine {
63/// multiplier: f32,
64/// additional: f32,
65/// combine: fn(f32, f32) -> f32,
66/// }
67///
68/// impl ReflectCombine {
69/// pub fn combine(&self, a: f32, b: f32) -> f32 {
70/// let combined = (self.combine)(a, b);
71/// let multiplied = self.multiplier * combined;
72/// multiplied + self.additional
73/// }
74/// }
75///
76/// // A default implementation for when no input is given
77/// impl<T: Combine + Reflect> CreateTypeData<T> for ReflectCombine {
78/// fn create_type_data(_: ()) -> Self {
79/// Self {
80/// multiplier: 1.0,
81/// additional: 0.0,
82/// combine: T::combine,
83/// }
84/// }
85/// }
86///
87/// // A custom implementation for when a multiplier is given
88/// impl<T: Combine + Reflect> CreateTypeData<T, (f32, f32)> for ReflectCombine {
89/// fn create_type_data(input: (f32, f32)) -> Self {
90/// Self {
91/// multiplier: input.0,
92/// additional: input.1,
93/// combine: T::combine,
94/// }
95/// }
96/// }
97///
98/// #[derive(Reflect)]
99/// // We can have the `Reflect` derive automatically register `ReflectCombine`:
100/// #[reflect(Combine)]
101/// struct WithoutMultiplier;
102///
103/// impl Combine for WithoutMultiplier {
104/// fn combine(a: f32, b: f32) -> f32 {
105/// a + b
106/// }
107/// }
108///
109/// #[derive(Reflect)]
110/// // We can also given it some input:
111/// #[reflect(Combine(2.0, 4.0))]
112/// struct WithMultiplier;
113///
114/// impl Combine for WithMultiplier {
115/// fn combine(a: f32, b: f32) -> f32 {
116/// a + b
117/// }
118/// }
119///
120/// // Or we can simply create the data manually:
121/// let without_multiplier = <ReflectCombine as CreateTypeData<WithoutMultiplier>>::create_type_data(());
122/// let with_multiplier = <ReflectCombine as CreateTypeData<WithMultiplier, _>>::create_type_data((2.0, 4.0));
123///
124/// assert_eq!(without_multiplier.combine(1.0, 2.0), 3.0);
125/// assert_eq!(with_multiplier.combine(1.0, 2.0), 10.0);
126/// ```
127///
128/// [`TypeRegistration`]: crate::TypeRegistration
129/// [`TypeRegistry::register_type_data`]: crate::TypeRegistry::register_type_data
130/// [`TypeRegistry::register_type_data_with`]: crate::TypeRegistry::register_type_data_with
131/// [`Reflect` derive macro]: derive@crate::Reflect
132pub trait CreateTypeData<T, Input = ()>: TypeData {
133 /// Create this type data using the given input.
134 fn create_type_data(input: Input) -> Self;
135
136 /// Inserts [`TypeData`] dependencies of this [`TypeData`].
137 /// This is especially useful for trait [`TypeData`] that has a supertrait (ex: `A: B`).
138 /// When the [`TypeData`] for `A` is inserted, the `B` [`TypeData`] will also be inserted.
139 #[expect(
140 unused_variables,
141 reason = "default implementation does not have any dependencies"
142 )]
143 fn insert_dependencies(type_registration: &mut TypeRegistration) {}
144}