Skip to content

Commit d74fd65

Browse files
MrGVSVcart
andauthored
0.11 Section: FromReflect Ergonomics (#669)
Co-authored-by: Carter Anderson <[email protected]>
1 parent 257b2e5 commit d74fd65

File tree

1 file changed

+61
-0
lines changed
  • content/news/2023-07-07-bevy-0.11

1 file changed

+61
-0
lines changed

content/news/2023-07-07-bevy-0.11/index.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,67 @@ Since our last release a few months ago we've added a _ton_ of new features, bug
2020
flat surfaces a feel of depth through parallaxing the material's textures.
2121
* **Gamepad Rumble API**: an ECS-friendly way of making controllers rumble
2222

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

2586
<div class="release-feature-authors">authors: @johanhelsing, @nicopap</div>

0 commit comments

Comments
 (0)