@@ -28,15 +28,14 @@ use bevy::{
28
28
} ,
29
29
ptr:: Ptr ,
30
30
reflect:: {
31
- Access , ParsedPath , PartialReflect , Reflect , ReflectFromPtr , ReflectPath , ReflectPathError ,
32
- TypeInfo , TypeRegistry ,
31
+ Access , DynamicEnum , DynamicTuple , ParsedPath , PartialReflect , Reflect , ReflectFromPtr , ReflectPath , ReflectPathError , TypeInfo , TypeRegistry
33
32
} ,
34
33
} ;
35
34
use smallvec:: SmallVec ;
36
35
37
36
use crate :: {
38
37
bindings:: { ReflectAllocation , ReflectAllocationId } ,
39
- prelude:: { ReflectAllocator , ScriptError , ScriptResult } , reflection_extensions:: TypeIdExtensions ,
38
+ prelude:: { ReflectAllocator , ScriptError , ScriptResult } , reflection_extensions:: { PartialReflectExt , TypeIdExtensions } ,
40
39
} ;
41
40
42
41
use super :: {
@@ -64,6 +63,16 @@ impl ReflectReference {
64
63
ReflectRefIter :: new_indexed ( self )
65
64
}
66
65
66
+ /// Attempts to insert into the reflected value, if the underlying supports inserting at usize indices
67
+ pub fn insert_at ( & mut self , world : & WorldAccessGuard , index : usize , elem : ReflectReference ) -> ScriptResult < ( ) > {
68
+ self . with_reflect_mut ( world, |target, type_registry, allocator| {
69
+ elem. with_reflect_only ( world, type_registry, allocator, |other, _, _| {
70
+ target. insert_at ( index, other. clone_value ( ) )
71
+ } ) ?
72
+ } ) ??;
73
+ Ok ( ( ) )
74
+ }
75
+
67
76
/// Prints the reference using the world to resolve type names.
68
77
pub fn print_with_world ( & self , world : & WorldAccessGuard ) -> String {
69
78
world. with_resource ( |_, type_registry : Mut < AppTypeRegistry > | {
@@ -119,10 +128,23 @@ impl ReflectReference {
119
128
120
129
/// A form of [`Self::reflect`] which does the access checks for you.
121
130
#[ track_caller]
122
- pub fn with_reflect < O , F : FnOnce ( & dyn PartialReflect , & TypeRegistry , & ReflectAllocator ) -> O > (
131
+ pub fn with_reflect < O , F : FnOnce ( & dyn PartialReflect , & TypeRegistry , & mut ReflectAllocator ) -> O > (
123
132
& self ,
124
133
world : & WorldAccessGuard ,
125
134
f : F ,
135
+ ) -> ScriptResult < O > {
136
+ world. with_allocator_and_type_registry ( |world, type_registry, mut allocator| {
137
+ let type_registry = type_registry. write ( ) ;
138
+ self . with_reflect_only ( world, & type_registry, & mut allocator, f)
139
+ } )
140
+ }
141
+
142
+ pub fn with_reflect_only < O , F : FnOnce ( & dyn PartialReflect , & TypeRegistry , & mut ReflectAllocator ) -> O > (
143
+ & self ,
144
+ world : & WorldAccessGuard ,
145
+ type_registry : & TypeRegistry ,
146
+ allocator : & mut ReflectAllocator ,
147
+ f : F ,
126
148
) -> ScriptResult < O > {
127
149
let access = world
128
150
. get_access_timeout (
@@ -131,51 +153,54 @@ impl ReflectReference {
131
153
DEFAULT_INTERVAL ,
132
154
) ;
133
155
134
- let out = world. with_allocator_and_type_registry ( |_, type_registry, allocator| {
135
- let type_registry = type_registry. read ( ) ;
136
- let reflect = self
137
- . reflect (
138
- world. as_unsafe_world_cell ( ) ,
139
- & access,
140
- & type_registry,
141
- Some ( & allocator) ,
142
- ) ?;
143
- let o = f ( reflect, & type_registry, & allocator) ;
144
-
145
- Ok ( o)
146
- } ) ;
156
+ let reflect = self
157
+ . reflect (
158
+ world. as_unsafe_world_cell ( ) ,
159
+ & access,
160
+ type_registry,
161
+ Some ( allocator) ,
162
+ ) . map ( |r| f ( r, type_registry, allocator) ) ;
147
163
148
164
world. release_access ( access) ;
149
- out
165
+ reflect
150
166
}
151
167
152
168
#[ track_caller]
153
169
pub fn with_reflect_mut < O , F : FnOnce ( & mut dyn PartialReflect , & TypeRegistry , & mut ReflectAllocator ) -> O > (
154
170
& self ,
155
171
world : & WorldAccessGuard ,
156
172
f : F ,
173
+ ) -> ScriptResult < O > {
174
+ world. with_allocator_and_type_registry ( |_, type_registry, mut allocator| {
175
+ let type_registry = type_registry. read ( ) ;
176
+ self . with_reflect_mut_only ( world, & type_registry, & mut allocator, f)
177
+ } )
178
+ }
179
+
180
+ pub fn with_reflect_mut_only < O , F : FnOnce ( & mut dyn PartialReflect , & TypeRegistry , & mut ReflectAllocator ) -> O > (
181
+ & self ,
182
+ world : & WorldAccessGuard ,
183
+ type_registry : & TypeRegistry ,
184
+ allocator : & mut ReflectAllocator ,
185
+ f : F ,
157
186
) -> ScriptResult < O > {
158
187
let mut access = world
159
188
. get_access_timeout (
160
189
self . base . base_id . get_reflect_access_id ( ) ,
161
190
DEFAULT_TIMEOUT ,
162
191
DEFAULT_INTERVAL ,
163
192
) ;
164
- let out = world. with_allocator_and_type_registry ( |_, type_registry, mut allocator| {
165
- let type_registry = type_registry. read ( ) ;
166
- let reflect = self
167
- . reflect_mut (
168
- world. as_unsafe_world_cell ( ) ,
169
- & mut access,
170
- & type_registry,
171
- Some ( & allocator) ,
172
- ) ?;
173
- let o = f ( reflect, & type_registry, & mut allocator) ;
174
- Ok ( o)
175
- } ) ;
176
193
194
+ let reflect = self
195
+ . reflect_mut (
196
+ world. as_unsafe_world_cell ( ) ,
197
+ & mut access,
198
+ type_registry,
199
+ Some ( allocator) ,
200
+ ) . map ( |r| f ( r, type_registry, allocator) ) ;
201
+
177
202
world. release_access ( access) ;
178
- out
203
+ reflect
179
204
}
180
205
181
206
/// Returns `Ok(())` if the given access is sufficient to read the value or an appropriate error otherwise
@@ -456,12 +481,14 @@ impl ReflectBase {
456
481
}
457
482
458
483
/// An element in the reflection path, the base reference included
459
- #[ derive( Clone , PartialEq , Eq , Debug ) ]
484
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
460
485
pub enum ReflectionPathElem {
461
486
/// A standard reflection path, i.e. `.field_name[vec_index]`, pre-parsed since we construct once potentially use many times
462
487
Reflection ( ParsedPath ) ,
463
488
/// a deferred reflection
464
489
DeferredReflection ( DeferredReflection ) ,
490
+ /// a no-op reflection, i.e. a reference to the base object, useful identity to have
491
+ Identity
465
492
}
466
493
467
494
impl ReflectionPathElem {
@@ -511,6 +538,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
511
538
match self {
512
539
ReflectionPathElem :: Reflection ( path) => path. reflect_element ( root) ,
513
540
ReflectionPathElem :: DeferredReflection ( f) => ( f. get ) ( root) ,
541
+ ReflectionPathElem :: Identity => Ok ( root) ,
514
542
}
515
543
}
516
544
@@ -521,6 +549,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
521
549
match self {
522
550
ReflectionPathElem :: Reflection ( path) => path. reflect_element_mut ( root) ,
523
551
ReflectionPathElem :: DeferredReflection ( defref) => ( defref. get_mut ) ( root) ,
552
+ ReflectionPathElem :: Identity => Ok ( root)
524
553
}
525
554
}
526
555
}
@@ -542,6 +571,22 @@ pub struct DeferredReflection {
542
571
> ,
543
572
}
544
573
574
+ /// Given a function, repeats it with a mutable reference for the get_mut deferred variant
575
+ #[ macro_export]
576
+ macro_rules! new_deferred_reflection {
577
+ ( |$root: ident| { $( $get: tt) * } ) => {
578
+ DeferredReflection :: from( (
579
+ |$root: & dyn PartialReflect | -> Result <& dyn PartialReflect , ReflectPathError <' static >> {
580
+ $( $get) *
581
+ } ,
582
+ |$root: & mut dyn PartialReflect | -> Result <& mut dyn PartialReflect , ReflectPathError <' static >> {
583
+ $( $get) *
584
+ } ,
585
+ ) )
586
+ } ;
587
+ }
588
+
589
+
545
590
impl Debug for DeferredReflection {
546
591
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
547
592
f. write_str ( "DeferredReflection" )
@@ -614,6 +659,6 @@ impl Iterator for ReflectRefIter {
614
659
}
615
660
} ;
616
661
617
- return Some ( result) ;
662
+ Some ( result)
618
663
}
619
664
}
0 commit comments