forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreflection_types.rs
99 lines (89 loc) · 4.08 KB
/
reflection_types.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use bevy::{
prelude::*,
reflect::{DynamicList, ReflectRef},
utils::HashMap,
};
use serde::{Deserialize, Serialize};
/// This example illustrates the various reflection types available
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.run();
}
/// Deriving reflect on a struct will implement the `Reflect` and `Struct` traits
#[derive(Reflect)]
pub struct A {
x: usize,
y: Vec<u32>,
z: HashMap<String, f32>,
}
/// Deriving reflect on a unit struct will implement `Reflect` and `Struct` traits
#[derive(Reflect)]
pub struct B;
/// Deriving reflect on a tuple struct will implement `Reflect` and `TupleStruct` traits
#[derive(Reflect)]
pub struct C(usize);
/// Reflect has "built in" support for some common traits like `PartialEq`, `Hash`, and `Serialize`.
/// These are exposed via methods like `Reflect::hash()`, `Reflect::partial_eq()`, and `Reflect::serialize()`.
/// You can force these implementations to use the actual trait implementations (instead of their defaults) like this:
#[derive(Reflect, Hash, Serialize, PartialEq)]
#[reflect(Hash, Serialize, PartialEq)]
pub struct D {
x: usize,
}
/// By default, deriving with Reflect assumes the type is a "struct". You can tell reflect to treat your type as a
/// "value type" by using the `reflect_value` attribute instead of `reflect`. It is generally a good idea to implement
/// (and reflect) the PartialEq, Serialize, and Deserialize traits on `reflect_value` types to ensure that these values
/// behave as expected when nested underneath Reflect-ed structs.
#[derive(Reflect, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[reflect_value(PartialEq, Serialize, Deserialize)]
pub enum E {
X,
Y,
}
fn setup() {
let mut z = HashMap::default();
z.insert("Hello".to_string(), 1.0);
let value: Box<dyn Reflect> = Box::new(A {
x: 1,
y: vec![1, 2],
z,
});
// There are a number of different "reflect traits", which each expose different operations on the underlying type
match value.reflect_ref() {
// `Struct` is a trait automatically implemented for structs that derive Reflect. This trait allows you to interact
// with fields via their string names or indices
ReflectRef::Struct(value) => {
println!(
"This is a 'struct' type with an 'x' value of {}",
value.get_field::<usize>("x").unwrap()
)
}
// `TupleStruct` is a trait automatically implemented for tuple structs that derive Reflect. This trait allows you
// to interact with fields via their indices
ReflectRef::TupleStruct(_) => {}
// `Tuple` is a special trait that can be manually implemented (instead of deriving Reflect). This exposes "tuple"
// operations on your type, allowing you to interact with fields via their indices. Tuple is automatically
// implemented for tuples of arity 12 or less.
ReflectRef::Tuple(_) => {}
// `List` is a special trait that can be manually implemented (instead of deriving Reflect). This exposes "list"
// operations on your type, such as indexing and insertion. List is automatically implemented for relevant core
// types like Vec<T>
ReflectRef::List(_) => {}
// `Map` is a special trait that can be manually implemented (instead of deriving Reflect). This exposes "map"
// operations on your type, such as getting / inserting by key. Map is automatically implemented for relevant core
// types like HashMap<K, V>
ReflectRef::Map(_) => {}
// `Value` types do not implement any of the other traits above. They are simply a Reflect implementation. Value
// is implemented for core types like i32, usize, f32, and String.
ReflectRef::Value(_) => {}
}
let mut dynamic_list = DynamicList::default();
dynamic_list.push(3u32);
dynamic_list.push(4u32);
dynamic_list.push(5u32);
let mut value: A = value.take::<A>().unwrap();
value.y.apply(&dynamic_list);
assert_eq!(value.y, vec![3u32, 4u32, 5u32]);
}