Skip to main content

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