bevy_ecs/reflect/
mod.rs

1//! Types that enable reflection support.
2
3use core::{
4    any::TypeId,
5    ops::{Deref, DerefMut},
6};
7
8use crate::{resource::Resource, world::World};
9use bevy_reflect::{
10    std_traits::ReflectDefault, PartialReflect, Reflect, ReflectFromReflect, TypePath,
11    TypeRegistry, TypeRegistryArc,
12};
13
14mod bundle;
15mod component;
16mod entity_commands;
17mod from_world;
18mod map_entities;
19mod resource;
20
21use bevy_utils::prelude::DebugName;
22pub use bundle::{ReflectBundle, ReflectBundleFns};
23pub use component::{ReflectComponent, ReflectComponentFns};
24pub use entity_commands::ReflectCommandExt;
25pub use from_world::{ReflectFromWorld, ReflectFromWorldFns};
26pub use map_entities::ReflectMapEntities;
27pub use resource::{ReflectResource, ReflectResourceFns};
28
29/// A [`Resource`] storing [`TypeRegistry`] for
30/// type registrations relevant to a whole app.
31#[derive(Resource, Clone, Default)]
32pub struct AppTypeRegistry(pub TypeRegistryArc);
33
34impl Deref for AppTypeRegistry {
35    type Target = TypeRegistryArc;
36
37    #[inline]
38    fn deref(&self) -> &Self::Target {
39        &self.0
40    }
41}
42
43impl DerefMut for AppTypeRegistry {
44    #[inline]
45    fn deref_mut(&mut self) -> &mut Self::Target {
46        &mut self.0
47    }
48}
49
50impl 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)]
68pub struct AppFunctionRegistry(pub bevy_reflect::func::FunctionRegistryArc);
69
70#[cfg(feature = "reflect_functions")]
71impl 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")]
81impl 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.
104pub 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}