@@ -28,15 +28,14 @@ use bevy::{
2828 } ,
2929 ptr:: Ptr ,
3030 reflect:: {
31- Access , ParsedPath , PartialReflect , Reflect , ReflectFromPtr , ReflectPath , ReflectPathError ,
32- TypeInfo , TypeRegistry ,
31+ Access , DynamicEnum , DynamicTuple , ParsedPath , PartialReflect , Reflect , ReflectFromPtr , ReflectPath , ReflectPathError , TypeInfo , TypeRegistry
3332 } ,
3433} ;
3534use smallvec:: SmallVec ;
3635
3736use crate :: {
3837 bindings:: { ReflectAllocation , ReflectAllocationId } ,
39- prelude:: { ReflectAllocator , ScriptError , ScriptResult } , reflection_extensions:: TypeIdExtensions ,
38+ prelude:: { ReflectAllocator , ScriptError , ScriptResult } , reflection_extensions:: { PartialReflectExt , TypeIdExtensions } ,
4039} ;
4140
4241use super :: {
@@ -64,6 +63,16 @@ impl ReflectReference {
6463 ReflectRefIter :: new_indexed ( self )
6564 }
6665
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+
6776 /// Prints the reference using the world to resolve type names.
6877 pub fn print_with_world ( & self , world : & WorldAccessGuard ) -> String {
6978 world. with_resource ( |_, type_registry : Mut < AppTypeRegistry > | {
@@ -119,10 +128,23 @@ impl ReflectReference {
119128
120129 /// A form of [`Self::reflect`] which does the access checks for you.
121130 #[ 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 > (
123132 & self ,
124133 world : & WorldAccessGuard ,
125134 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 ,
126148 ) -> ScriptResult < O > {
127149 let access = world
128150 . get_access_timeout (
@@ -131,51 +153,54 @@ impl ReflectReference {
131153 DEFAULT_INTERVAL ,
132154 ) ;
133155
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) ) ;
147163
148164 world. release_access ( access) ;
149- out
165+ reflect
150166 }
151167
152168 #[ track_caller]
153169 pub fn with_reflect_mut < O , F : FnOnce ( & mut dyn PartialReflect , & TypeRegistry , & mut ReflectAllocator ) -> O > (
154170 & self ,
155171 world : & WorldAccessGuard ,
156172 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 ,
157186 ) -> ScriptResult < O > {
158187 let mut access = world
159188 . get_access_timeout (
160189 self . base . base_id . get_reflect_access_id ( ) ,
161190 DEFAULT_TIMEOUT ,
162191 DEFAULT_INTERVAL ,
163192 ) ;
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- } ) ;
176193
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+
177202 world. release_access ( access) ;
178- out
203+ reflect
179204 }
180205
181206 /// Returns `Ok(())` if the given access is sufficient to read the value or an appropriate error otherwise
@@ -456,12 +481,14 @@ impl ReflectBase {
456481}
457482
458483/// An element in the reflection path, the base reference included
459- #[ derive( Clone , PartialEq , Eq , Debug ) ]
484+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
460485pub enum ReflectionPathElem {
461486 /// A standard reflection path, i.e. `.field_name[vec_index]`, pre-parsed since we construct once potentially use many times
462487 Reflection ( ParsedPath ) ,
463488 /// a deferred reflection
464489 DeferredReflection ( DeferredReflection ) ,
490+ /// a no-op reflection, i.e. a reference to the base object, useful identity to have
491+ Identity
465492}
466493
467494impl ReflectionPathElem {
@@ -511,6 +538,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
511538 match self {
512539 ReflectionPathElem :: Reflection ( path) => path. reflect_element ( root) ,
513540 ReflectionPathElem :: DeferredReflection ( f) => ( f. get ) ( root) ,
541+ ReflectionPathElem :: Identity => Ok ( root) ,
514542 }
515543 }
516544
@@ -521,6 +549,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
521549 match self {
522550 ReflectionPathElem :: Reflection ( path) => path. reflect_element_mut ( root) ,
523551 ReflectionPathElem :: DeferredReflection ( defref) => ( defref. get_mut ) ( root) ,
552+ ReflectionPathElem :: Identity => Ok ( root)
524553 }
525554 }
526555}
@@ -542,6 +571,22 @@ pub struct DeferredReflection {
542571 > ,
543572}
544573
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+
545590impl Debug for DeferredReflection {
546591 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
547592 f. write_str ( "DeferredReflection" )
@@ -614,6 +659,6 @@ impl Iterator for ReflectRefIter {
614659 }
615660 } ;
616661
617- return Some ( result) ;
662+ Some ( result)
618663 }
619664}
0 commit comments