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