reflection/
reflection.rs

1//! Illustrates how "reflection" works in Bevy.
2//!
3//! Reflection provides a way to dynamically interact with Rust types, such as accessing fields
4//! by their string name. Reflection is a core part of Bevy and enables a number of interesting
5//! features (like scenes).
6
7use bevy::{
8    prelude::*,
9    reflect::{
10        serde::{ReflectDeserializer, ReflectSerializer},
11        DynamicStruct, PartialReflect,
12    },
13};
14use serde::de::DeserializeSeed;
15
16fn main() {
17    App::new()
18        .add_plugins(DefaultPlugins)
19        // Bar will be automatically registered as it's a dependency of Foo
20        .register_type::<Foo>()
21        .add_systems(Startup, setup)
22        .run();
23}
24
25/// Deriving `Reflect` implements the relevant reflection traits. In this case, it implements the
26/// `Reflect` trait and the `Struct` trait `derive(Reflect)` assumes that all fields also implement
27/// Reflect.
28///
29/// All fields in a reflected item will need to be `Reflect` as well. You can opt a field out of
30/// reflection by using the `#[reflect(ignore)]` attribute.
31/// If you choose to ignore a field, you need to let the automatically-derived `FromReflect` implementation
32/// how to handle the field.
33/// To do this, you can either define a `#[reflect(default = "...")]` attribute on the ignored field, or
34/// opt-out of `FromReflect`'s auto-derive using the `#[reflect(from_reflect = false)]` attribute.
35#[derive(Reflect)]
36#[reflect(from_reflect = false)]
37pub struct Foo {
38    a: usize,
39    nested: Bar,
40    #[reflect(ignore)]
41    _ignored: NonReflectedValue,
42}
43
44/// This `Bar` type is used in the `nested` field of the `Foo` type. We must derive `Reflect` here
45/// too (or ignore it)
46#[derive(Reflect)]
47pub struct Bar {
48    b: usize,
49}
50
51#[derive(Default)]
52struct NonReflectedValue {
53    _a: usize,
54}
55
56fn setup(type_registry: Res<AppTypeRegistry>) {
57    let mut value = Foo {
58        a: 1,
59        _ignored: NonReflectedValue { _a: 10 },
60        nested: Bar { b: 8 },
61    };
62
63    // You can set field values like this. The type must match exactly or this will fail.
64    *value.get_field_mut("a").unwrap() = 2usize;
65    assert_eq!(value.a, 2);
66    assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
67
68    // You can also get the `&dyn PartialReflect` value of a field like this
69    let field = value.field("a").unwrap();
70
71    // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
72    // (even if the containing type does implement `Reflect`), so we need to convert them:
73    let fully_reflected_field = field.try_as_reflect().unwrap();
74
75    // Now, you can downcast your `Reflect` value like this:
76    assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
77
78    // For this specific case, we also support the shortcut `try_downcast_ref`:
79    assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
80
81    // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
82    let mut patch = DynamicStruct::default();
83    patch.insert("a", 4usize);
84
85    // You can "apply" Reflect implementations on top of other Reflect implementations.
86    // This will only set fields with the same name, and it will fail if the types don't match.
87    // You can use this to "patch" your types with new values.
88    value.apply(&patch);
89    assert_eq!(value.a, 4);
90
91    let type_registry = type_registry.read();
92    // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
93    // Serialize!
94    let serializer = ReflectSerializer::new(&value, &type_registry);
95    let ron_string =
96        ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
97    info!("{}\n", ron_string);
98
99    // Dynamic properties can be deserialized
100    let reflect_deserializer = ReflectDeserializer::new(&type_registry);
101    let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
102    let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
103
104    // Deserializing returns a `Box<dyn PartialReflect>` value.
105    // Generally, deserializing a value will return the "dynamic" variant of a type.
106    // For example, deserializing a struct will return the DynamicStruct type.
107    // "Opaque types" will be deserialized as themselves.
108    assert_eq!(
109        reflect_value.reflect_type_path(),
110        DynamicStruct::type_path(),
111    );
112
113    // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
114    // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
115    // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
116    assert!(reflect_value.reflect_partial_eq(&value).unwrap());
117
118    // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
119    // This means we can serialize and deserialize with a single `Reflect` derive!
120    value.apply(&*reflect_value);
121}