@@ -17,11 +17,66 @@ Since our last release a few months ago we've added a _ton_ of new features, bug
17
17
18
18
* ** Feature** : description
19
19
20
- ## Feature
20
+ ## ` FromReflect ` Ergonomics
21
21
22
- <div class =" release-feature-authors " >authors: @todo </div >
22
+ <div class =" release-feature-authors " >authors: @MrGVSV </div >
23
23
24
- Description
24
+ Bevy's [ reflection API] commonly passes around data using type-erased ` dyn Reflect ` trait objects.
25
+ This can usually be downcast back to its concrete type using ` <dyn Reflect>::downcast_ref::<T> ` ;
26
+ however, this doesn't work if the underlying data has been converted to a "dynamic" representation
27
+ (e.g. ` DynamicStruct ` for struct types, ` DynamicList ` for list types, etc.).
28
+
29
+ ``` rust
30
+ let data : Vec <i32 > = vec! [1 , 2 , 3 ];
31
+
32
+ let reflect : & dyn Reflect = & data ;
33
+ let cloned : Box <dyn Reflect > = reflect . clone_value ();
34
+
35
+ // `reflect` really is a `Vec<i32>`
36
+ assert! (reflect . is :: <Vec <i32 >>());
37
+ assert! (reflect . represents :: <Vec <i32 >>());
38
+
39
+ // `cloned` is a `DynamicList`, but represents a `Vec<i32>`
40
+ assert! (cloned . is :: <DynamicList >());
41
+ assert! (cloned . represents :: <Vec <i32 >>());
42
+
43
+ // `cloned` is equivalent to the original `reflect`, despite not being a `Vec<i32>`
44
+ assert! (cloned . reflect_partial_eq (reflect ). unwrap_or_default ());
45
+ ```
46
+
47
+ To account for this, the [ ` FromReflect ` ] trait can be used to convert any ` dyn Reflect ` trait object
48
+ back into its concrete type— whether it is actually that type or a dynamic representation of it.
49
+ And it can even be called dynamically using the [ ` ReflectFromReflect ` ] type data.
50
+
51
+ Before 0.11, users had to be manually derive ` FromReflect ` for every type that needed it,
52
+ as well as manually register the ` ReflectFromReflect ` type data.
53
+ This made it cumbersome to use and also meant that it was often forgotten about,
54
+ resulting in reflection conversions difficulties for users downstream.
55
+
56
+ Now in 0.11, ` FromReflect ` is automatically derived and ` ReflectFromReflect ` is automatically registered for all types that derive ` Reflect ` .
57
+ This means most types will be ` FromReflect ` -capable by default,
58
+ thus reducing boilerplate and empowering logic centered around ` FromReflect ` .
59
+
60
+ Users can still opt out of this behavior by adding the [ ` #[reflect(from_reflect = false)] ` ] [ from_reflect = false ] attribute to their type.
61
+
62
+ ``` rust
63
+ #[derive(Reflect )]
64
+ struct Foo ;
65
+
66
+ #[derive(Reflect )]
67
+ #[reflect(from_reflect = false)]
68
+ struct Bar ;
69
+
70
+ fn test <T : FromReflect >(value : T ) {}
71
+
72
+ test (Foo ); // <-- OK!
73
+ test (Bar ); // <-- ERROR! `Bar` does not implement trait `FromReflect`
74
+ ```
75
+
76
+ [ reflection API ] : https://docs.rs/bevy_reflect/latest/bevy_reflect/index.html
77
+ [ `FromReflect` ] : https://docs.rs/bevy_reflect/latest/bevy_reflect/trait.FromReflect.html
78
+ [ `ReflectFromReflect` ] : https://docs.rs/bevy_reflect/latest/bevy_reflect/struct.ReflectFromReflect.html
79
+ [ from_reflect = false ] : https://docs.rs/bevy_reflect/latest/bevy_reflect/derive.Reflect.html#reflectfrom_reflect--false
25
80
26
81
## <a name =" what-s-next " ></a >What's Next?
27
82
0 commit comments