1
1
use std:: any:: TypeId ;
2
2
3
- use anyhow:: { format_err, Context } ;
3
+ use anyhow:: { bail , format_err, Context } ;
4
4
use bevy:: prelude:: { default, ReflectDefault , World } ;
5
5
use bevy_ecs_dynamic:: reflect_value_ref:: ReflectValueRef ;
6
- use bevy_reflect:: { ReflectRef , TypeRegistryArc } ;
6
+ use bevy_reflect:: { Reflect , ReflectRef , TypeRegistryArc } ;
7
7
use bevy_reflect_fns:: { PassMode , ReflectArg , ReflectMethods } ;
8
8
9
9
use crate :: runtime:: OpContext ;
@@ -17,22 +17,141 @@ use super::{
17
17
18
18
macro_rules! try_downcast_leaf_get {
19
19
( $value: ident for $( $ty: ty $( , ) ?) ,* ) => {
20
- $( if let Some ( value) = $value. downcast_ref:: <$ty>( ) {
21
- let value = serde_json:: to_value( value) ?;
22
- return Ok ( value) ;
23
- } ) *
20
+ ( || {
21
+ $( if let Some ( value) = $value. downcast_ref:: <$ty>( ) {
22
+ let value = serde_json:: to_value( value) ?;
23
+ return Ok ( Some ( value) ) ;
24
+ } ) *
25
+
26
+ Ok :: <_, anyhow:: Error >( None )
27
+ } ) ( )
24
28
} ;
25
29
}
26
30
27
31
macro_rules! try_downcast_leaf_set {
28
32
( $value: ident <- $new_value: ident for $( $ty: ty $( , ) ?) ,* ) => {
29
- $( if let Some ( value) = $value. downcast_mut:: <$ty>( ) {
30
- * value = serde_json:: from_value( $new_value) ?;
31
- return Ok ( serde_json:: Value :: Null ) ;
32
- } ) *
33
+ ( || {
34
+ $( if let Some ( value) = $value. downcast_mut:: <$ty>( ) {
35
+ * value = serde_json:: from_value( $new_value) ?;
36
+ return Ok ( ( ) ) ;
37
+ } ) *
38
+
39
+ Ok :: <( ) , anyhow:: Error >( ( ) )
40
+ } ) ( )
33
41
} ;
34
42
}
35
43
44
+ /// Converts a JSON value to a dynamic reflect struct or list
45
+ pub fn patch_reflect_with_json (
46
+ value : & mut dyn Reflect ,
47
+ patch : serde_json:: Value ,
48
+ ) -> anyhow:: Result < ( ) > {
49
+ match patch {
50
+ serde_json:: Value :: Null => {
51
+ bail ! ( "Can't patch values with null" ) ;
52
+ }
53
+ patch @ ( serde_json:: Value :: Bool ( _)
54
+ | serde_json:: Value :: Number ( _)
55
+ | serde_json:: Value :: String ( _) ) => {
56
+ try_downcast_leaf_set ! ( value <- patch for
57
+ u8 , u16 , u32 , u64 , u128 , usize ,
58
+ i8 , i16 , i32 , i64 , i128 , isize ,
59
+ String , char , bool , f32 , f64
60
+ ) ?;
61
+ }
62
+ serde_json:: Value :: Array ( array) => match value. reflect_mut ( ) {
63
+ bevy_reflect:: ReflectMut :: Struct ( _) => todo ! ( ) ,
64
+ bevy_reflect:: ReflectMut :: List ( target) => {
65
+ let target_len = target. len ( ) ;
66
+ let patch_len = array. len ( ) ;
67
+ if target_len < patch_len {
68
+ bail ! ( "Cannot patch list with {target_len} elements with patch with {patch_len} elements" ) ;
69
+ }
70
+
71
+ for ( i, patch) in array. into_iter ( ) . enumerate ( ) {
72
+ let target = target. get_mut ( i) . unwrap ( ) ;
73
+ patch_reflect_with_json ( target, patch) ?;
74
+ }
75
+ }
76
+ bevy_reflect:: ReflectMut :: Tuple ( target) => {
77
+ let target_len = target. field_len ( ) ;
78
+ let patch_len = array. len ( ) ;
79
+ if target_len != patch_len {
80
+ bail ! ( "Cannot patch tuple with {target_len} elements with patch with {patch_len} elements" ) ;
81
+ }
82
+
83
+ for ( i, patch) in array. into_iter ( ) . enumerate ( ) {
84
+ let target = target. field_mut ( i) . unwrap ( ) ;
85
+ patch_reflect_with_json ( target, patch) ?;
86
+ }
87
+ }
88
+ bevy_reflect:: ReflectMut :: TupleStruct ( target) => {
89
+ let target_len = target. field_len ( ) ;
90
+ let patch_len = array. len ( ) ;
91
+ if target_len != patch_len {
92
+ bail ! ( "Cannot patch tuple with {target_len} elements with patch with {patch_len} elements" ) ;
93
+ }
94
+
95
+ for ( i, patch) in array. into_iter ( ) . enumerate ( ) {
96
+ let target = target. field_mut ( i) . unwrap ( ) ;
97
+ patch_reflect_with_json ( target, patch) ?;
98
+ }
99
+ }
100
+ bevy_reflect:: ReflectMut :: Array ( target) => {
101
+ let target_len = target. len ( ) ;
102
+ let patch_len = array. len ( ) ;
103
+ if target_len != patch_len {
104
+ bail ! ( "Cannot patch array with {target_len} elements with patch with {patch_len} elements" ) ;
105
+ }
106
+
107
+ for ( i, patch) in array. into_iter ( ) . enumerate ( ) {
108
+ let target = target. get_mut ( i) . unwrap ( ) ;
109
+ patch_reflect_with_json ( target, patch) ?;
110
+ }
111
+ }
112
+ bevy_reflect:: ReflectMut :: Map ( _) => bail ! ( "Cannot patch map with array" ) ,
113
+ bevy_reflect:: ReflectMut :: Value ( _) => bail ! ( "Cannot patch primitive value with array" ) ,
114
+ } ,
115
+ serde_json:: Value :: Object ( map) => match value. reflect_mut ( ) {
116
+ bevy_reflect:: ReflectMut :: Struct ( target) => {
117
+ for ( key, value) in map {
118
+ let field = target. field_mut ( & key) . ok_or_else ( || {
119
+ format_err ! ( "Field `{key}` in patch does not exist on target struct" )
120
+ } ) ?;
121
+
122
+ patch_reflect_with_json ( field, value) ?;
123
+ }
124
+ }
125
+ bevy_reflect:: ReflectMut :: Map ( _) => {
126
+ bail ! ( "Patching maps are not yet supported" ) ;
127
+ // TODO: The code would be something like below, but we have to figure out how to
128
+ // insert new values of the right type, or find out that it isn't actually a concern.
129
+
130
+ // for (key, value) in map {
131
+ // let key = Box::new(key) as Box<dyn Reflect>;
132
+ // if let Some(field) = target.get_mut(key.as_reflect()) {
133
+ // patch_reflect_with_json(field, value)?;
134
+ // } else {
135
+ // target.insert_boxed(
136
+ // key,
137
+ // /* How do we know what the expected value type for the map is? */
138
+ // );
139
+ // }
140
+ // }
141
+ }
142
+ bevy_reflect:: ReflectMut :: Tuple ( _) | bevy_reflect:: ReflectMut :: TupleStruct ( _) => {
143
+ bail ! ( "Cannot patch tuple struct with object" )
144
+ }
145
+ bevy_reflect:: ReflectMut :: List ( _) | bevy_reflect:: ReflectMut :: Array ( _) => {
146
+ bail ! ( "Cannot patch list or array with object" )
147
+ }
148
+ bevy_reflect:: ReflectMut :: Value ( _) => bail ! ( "Cannot patch primitive value with object" ) ,
149
+ } ,
150
+ }
151
+
152
+ Ok ( ( ) )
153
+ }
154
+
36
155
pub fn ecs_value_ref_get (
37
156
context : OpContext ,
38
157
world : & mut bevy:: prelude:: World ,
@@ -81,11 +200,15 @@ pub fn ecs_value_ref_get(
81
200
{
82
201
let value = value_ref. get ( world) ?;
83
202
84
- try_downcast_leaf_get ! ( value for
203
+ let value = try_downcast_leaf_get ! ( value for
85
204
u8 , u16 , u32 , u64 , u128 , usize ,
86
205
i8 , i16 , i32 , i64 , i128 , isize ,
87
206
String , char , bool , f32 , f64
88
207
) ;
208
+
209
+ if let Some ( value) = value? {
210
+ return Ok ( value) ;
211
+ }
89
212
}
90
213
91
214
// If not a primitive, just return a new value ref
@@ -129,12 +252,14 @@ pub fn ecs_value_ref_set(
129
252
u8 , u16 , u32 , u64 , u128 , usize ,
130
253
i8 , i16 , i32 , i64 , i128 , isize ,
131
254
String , char , bool , f32 , f64
132
- ) ;
133
-
134
- anyhow:: bail!(
135
- "could not set value reference: type `{}` is not a primitive type" ,
136
- reflect. type_name( ) ,
137
- ) ;
255
+ )
256
+ . map ( |_| serde_json:: Value :: Null )
257
+ . map_err ( |e| {
258
+ format_err ! (
259
+ "could not set value reference: type `{typename}` is not a primitive type: {e}" ,
260
+ typename = reflect. type_name( ) ,
261
+ )
262
+ } )
138
263
}
139
264
140
265
pub fn ecs_value_ref_keys (
@@ -206,7 +331,8 @@ pub fn ecs_value_ref_default(
206
331
args : serde_json:: Value ,
207
332
) -> anyhow:: Result < serde_json:: Value > {
208
333
// Parse args
209
- let ( type_name, ) : ( String , ) = serde_json:: from_value ( args) . context ( "parse args" ) ?;
334
+ let ( type_name, patch) : ( String , Option < serde_json:: Value > ) =
335
+ serde_json:: from_value ( args) . context ( "parse args" ) ?;
210
336
211
337
let value_refs = context
212
338
. op_state
@@ -226,7 +352,12 @@ pub fn ecs_value_ref_default(
226
352
let reflect_default = type_registration
227
353
. data :: < ReflectDefault > ( )
228
354
. ok_or_else ( || format_err ! ( "Type does not have ReflectDefault: {type_name}" ) ) ?;
229
- let value = reflect_default. default ( ) ;
355
+ let mut value = reflect_default. default ( ) ;
356
+
357
+ // Patch the default value if a patch is provided
358
+ if let Some ( patch) = patch {
359
+ patch_reflect_with_json ( value. as_reflect_mut ( ) , patch) ?;
360
+ }
230
361
231
362
// Return the value ref to the new object
232
363
let value_ref = JsValueRef :: new_free ( value, value_refs) ;
0 commit comments