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