Skip to content

Commit dcef362

Browse files
committed
Add example
1 parent 350b316 commit dcef362

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,17 @@ description = "Demonstrates how functions can be called dynamically using reflec
21952195
category = "Reflection"
21962196
wasm = false
21972197

2198+
[[example]]
2199+
name = "nested_reflection"
2200+
path = "examples/reflection/nested_reflection.rs"
2201+
doc-scrape-examples = true
2202+
2203+
[package.metadata.example.nested_reflection]
2204+
name = "Nested Reflection"
2205+
description = "Demonstrates how reflection trait objects can be nested in other reflected types"
2206+
category = "Reflection"
2207+
wasm = false
2208+
21982209
[[example]]
21992210
name = "generic_reflection"
22002211
path = "examples/reflection/generic_reflection.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ Example | Description
365365
[Custom Attributes](../examples/reflection/custom_attributes.rs) | Registering and accessing custom attributes on reflected types
366366
[Dynamic Types](../examples/reflection/dynamic_types.rs) | How dynamic types are used with reflection
367367
[Function Reflection](../examples/reflection/function_reflection.rs) | Demonstrates how functions can be called dynamically using reflection
368+
[Nested Reflection](../examples/reflection/nested_reflection.rs) | Demonstrates how reflection trait objects can be nested in other reflected types
368369
[Generic Reflection](../examples/reflection/generic_reflection.rs) | Registers concrete instances of generic types that may be used with reflection
369370
[Reflection](../examples/reflection/reflection.rs) | Demonstrates how reflection in Bevy provides a way to dynamically interact with Rust types
370371
[Reflection Types](../examples/reflection/reflection_types.rs) | Illustrates the various reflection types available
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! This example demonstrates how reflection trait objects can be nested in other reflected types
2+
//! using remote reflection.
3+
4+
use bevy::prelude::*;
5+
6+
fn main() {
7+
// Bevy's reflection crate relies heavily on the `dyn Reflect` trait object.
8+
// This allows the compile-time name of a type to be "erased" and passed around at runtime,
9+
// most often as a `Box<dyn Reflect>`.
10+
let _: Box<dyn Reflect> = Box::new(String::from("Hello, World!"));
11+
12+
// However, you'll notice that `Box<dyn Reflect>` itself doesn't implement `Reflect`.
13+
// This makes it impossible to use `Box<dyn Reflect>` as a field in a struct that derives `Reflect`.
14+
// ```
15+
// #[derive(Reflect)]
16+
// struct MyType {
17+
// field: Box<dyn Reflect>, // <- Compile Error
18+
// }
19+
// ```
20+
// This is because it would be too easy to accidentally box a `Reflect` type,
21+
// then accidentally box it again, and again, and so on.
22+
// So instead, `bevy_reflect` exposes a `ReflectBox` type which can be used
23+
// as a remote wrapper around a `Box<dyn Reflect>` (or `Box<dyn PartialReflect>`).
24+
//
25+
// For example, let's say we want to define some equipment for a player.
26+
// We don't know what kind of equipment the player will have at compile time,
27+
// so we want to store it as a `Box<dyn Reflect>`.
28+
// To do this, we first need to derive `Reflect` for our `Player`.
29+
#[derive(Reflect)]
30+
// Next, we need to opt out of deriving `FromReflect` since `Box<dyn Reflect>`
31+
// has no knowledge of `FromReflect`.
32+
#[reflect(from_reflect = false)]
33+
struct Player {
34+
// Now we can use remote reflection to tell `Reflect` how to reflect our `Box<dyn Reflect>`.
35+
#[reflect(remote = bevy::reflect::boxed::ReflectBox<dyn Reflect>)]
36+
equipment: Box<dyn Reflect>,
37+
}
38+
39+
// Now we can use any type that implements `Reflect` as equipment for our player.
40+
let equipment: Box<dyn Reflect> = Box::new(String::from("Sword"));
41+
let mut player: Box<dyn Struct> = Box::new(Player { equipment });
42+
43+
// We can also use reflection to modify our player's equipment.
44+
let equipment = player.field_mut("equipment").unwrap();
45+
equipment.try_apply(&String::from("Shield")).unwrap();
46+
assert!(player
47+
.reflect_partial_eq(&Player {
48+
equipment: Box::new(String::from("Shield")),
49+
})
50+
.unwrap_or_default());
51+
}

0 commit comments

Comments
 (0)