Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/reflect/mod.rs
9371 views
1
//! Types that enable reflection support.
2
3
use core::{
4
any::TypeId,
5
ops::{Deref, DerefMut},
6
};
7
8
use crate::{resource::Resource, world::World};
9
use bevy_reflect::{
10
std_traits::ReflectDefault, PartialReflect, Reflect, ReflectFromReflect, TypePath,
11
TypeRegistry, TypeRegistryArc,
12
};
13
14
mod bundle;
15
mod component;
16
mod entity_commands;
17
mod event;
18
mod from_world;
19
mod map_entities;
20
mod resource;
21
22
use bevy_utils::prelude::DebugName;
23
pub use bundle::{ReflectBundle, ReflectBundleFns};
24
pub use component::{ReflectComponent, ReflectComponentFns};
25
pub use entity_commands::ReflectCommandExt;
26
pub use event::{ReflectEvent, ReflectEventFns};
27
pub use from_world::{ReflectFromWorld, ReflectFromWorldFns};
28
pub use map_entities::ReflectMapEntities;
29
pub use resource::ReflectResource;
30
31
/// A [`Resource`] storing [`TypeRegistry`] for
32
/// type registrations relevant to a whole app.
33
#[derive(Resource, Clone, Default)]
34
pub struct AppTypeRegistry(pub TypeRegistryArc);
35
36
impl Deref for AppTypeRegistry {
37
type Target = TypeRegistryArc;
38
39
#[inline]
40
fn deref(&self) -> &Self::Target {
41
&self.0
42
}
43
}
44
45
impl DerefMut for AppTypeRegistry {
46
#[inline]
47
fn deref_mut(&mut self) -> &mut Self::Target {
48
&mut self.0
49
}
50
}
51
52
impl AppTypeRegistry {
53
/// Creates [`AppTypeRegistry`] and automatically registers all types deriving [`Reflect`].
54
///
55
/// See [`TypeRegistry::register_derived_types`] for more details.
56
#[cfg(feature = "reflect_auto_register")]
57
pub fn new_with_derived_types() -> Self {
58
let app_registry = AppTypeRegistry::default();
59
app_registry.write().register_derived_types();
60
app_registry
61
}
62
}
63
64
/// A [`Resource`] storing [`FunctionRegistry`] for
65
/// function registrations relevant to a whole app.
66
///
67
/// [`FunctionRegistry`]: bevy_reflect::func::FunctionRegistry
68
#[cfg(feature = "reflect_functions")]
69
#[derive(Resource, Clone, Default)]
70
pub struct AppFunctionRegistry(pub bevy_reflect::func::FunctionRegistryArc);
71
72
#[cfg(feature = "reflect_functions")]
73
impl Deref for AppFunctionRegistry {
74
type Target = bevy_reflect::func::FunctionRegistryArc;
75
76
#[inline]
77
fn deref(&self) -> &Self::Target {
78
&self.0
79
}
80
}
81
82
#[cfg(feature = "reflect_functions")]
83
impl DerefMut for AppFunctionRegistry {
84
#[inline]
85
fn deref_mut(&mut self) -> &mut Self::Target {
86
&mut self.0
87
}
88
}
89
90
/// Creates a `T` from a `&dyn PartialReflect`.
91
///
92
/// This will try the following strategies, in this order:
93
///
94
/// - use the reflected `FromReflect`, if it's present and doesn't fail;
95
/// - use the reflected `Default`, if it's present, and then call `apply` on the result;
96
/// - use the reflected `FromWorld`, just like the `Default`.
97
///
98
/// The first one that is present and doesn't fail will be used.
99
///
100
/// # Panics
101
///
102
/// If any strategy produces a `Box<dyn Reflect>` that doesn't store a value of type `T`
103
/// this method will panic.
104
///
105
/// If none of the strategies succeed, this method will panic.
106
pub fn from_reflect_with_fallback<T: Reflect + TypePath>(
107
reflected: &dyn PartialReflect,
108
world: &mut World,
109
registry: &TypeRegistry,
110
) -> T {
111
#[inline(never)]
112
fn type_erased(
113
reflected: &dyn PartialReflect,
114
world: &mut World,
115
registry: &TypeRegistry,
116
id: TypeId,
117
name: DebugName,
118
) -> alloc::boxed::Box<dyn core::any::Any> {
119
// First, try `FromReflect`. This is handled differently from the others because
120
// it doesn't need a subsequent `apply` and may fail.
121
// If it fails it's ok, we can continue checking `Default` and `FromWorld`.
122
let (value, source) = if let Some(value) = registry
123
.get_type_data::<ReflectFromReflect>(id)
124
.and_then(|reflect_from_reflect| reflect_from_reflect.from_reflect(reflected))
125
{
126
(value, "FromReflect")
127
}
128
// Create an instance of `T` using either the reflected `Default` or `FromWorld`.
129
else if let Some(reflect_default) = registry.get_type_data::<ReflectDefault>(id) {
130
let mut value = reflect_default.default();
131
value.apply(reflected);
132
(value, "Default")
133
} else if let Some(reflect_from_world) = registry.get_type_data::<ReflectFromWorld>(id) {
134
let mut value = reflect_from_world.from_world(world);
135
value.apply(reflected);
136
(value, "FromWorld")
137
} else {
138
panic!(
139
"Couldn't create an instance of `{name}` using the reflected `FromReflect`, \
140
`Default` or `FromWorld` traits. Are you perhaps missing a `#[reflect(Default)]` \
141
or `#[reflect(FromWorld)]`?",
142
);
143
};
144
assert_eq!(
145
value.as_any().type_id(),
146
id,
147
"The registration for the reflected `{source}` trait for the type `{name}` produced \
148
a value of a different type",
149
);
150
value
151
}
152
*type_erased(
153
reflected,
154
world,
155
registry,
156
TypeId::of::<T>(),
157
// FIXME: once we have unique reflect, use `TypePath`.
158
DebugName::type_name::<T>(),
159
)
160
.downcast::<T>()
161
.unwrap()
162
}
163
164