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 event;
18mod from_world;
19mod map_entities;
20mod resource;
21
22use bevy_utils::prelude::DebugName;
23pub use bundle::{ReflectBundle, ReflectBundleFns};
24pub use component::{ReflectComponent, ReflectComponentFns};
25pub use entity_commands::ReflectCommandExt;
26pub use event::{ReflectEvent, ReflectEventFns};
27pub use from_world::{ReflectFromWorld, ReflectFromWorldFns};
28pub use map_entities::ReflectMapEntities;
29pub use resource::{ReflectResource, ReflectResourceFns};
30
31/// A [`Resource`] storing [`TypeRegistry`] for
32/// type registrations relevant to a whole app.
33#[derive(Resource, Clone, Default)]
34pub struct AppTypeRegistry(pub TypeRegistryArc);
35
36impl Deref for AppTypeRegistry {
37    type Target = TypeRegistryArc;
38
39    #[inline]
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl DerefMut for AppTypeRegistry {
46    #[inline]
47    fn deref_mut(&mut self) -> &mut Self::Target {
48        &mut self.0
49    }
50}
51
52impl 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)]
70pub struct AppFunctionRegistry(pub bevy_reflect::func::FunctionRegistryArc);
71
72#[cfg(feature = "reflect_functions")]
73impl 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")]
83impl 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.
106pub 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}