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