@@ -185,6 +185,17 @@ change_detection_impl!(ResMut<'a, T>, T, Resource);
185185impl_into_inner ! ( ResMut <' a, T >, T , Resource ) ;
186186impl_debug ! ( ResMut <' a, T >, Resource ) ;
187187
188+ impl < ' a , T : Resource > From < ResMut < ' a , T > > for Mut < ' a , T > {
189+ /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
190+ /// while losing the specificity of `ResMut` for resources.
191+ fn from ( other : ResMut < ' a , T > ) -> Mut < ' a , T > {
192+ Mut {
193+ value : other. value ,
194+ ticks : other. ticks ,
195+ }
196+ }
197+ }
198+
188199/// Unique borrow of a non-[`Send`] resource.
189200///
190201/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
@@ -206,6 +217,17 @@ change_detection_impl!(NonSendMut<'a, T>, T,);
206217impl_into_inner ! ( NonSendMut <' a, T >, T , ) ;
207218impl_debug ! ( NonSendMut <' a, T >, ) ;
208219
220+ impl < ' a , T : Resource > From < NonSendMut < ' a , T > > for Mut < ' a , T > {
221+ /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
222+ /// while losing the specificity of `NonSendMut`.
223+ fn from ( other : NonSendMut < ' a , T > ) -> Mut < ' a , T > {
224+ Mut {
225+ value : other. value ,
226+ ticks : other. ticks ,
227+ }
228+ }
229+ }
230+
209231/// Unique mutable borrow of an entity's component
210232pub struct Mut < ' a , T > {
211233 pub ( crate ) value : & ' a mut T ,
@@ -286,7 +308,9 @@ impl std::fmt::Debug for MutUntyped<'_> {
286308mod tests {
287309 use crate :: {
288310 self as bevy_ecs,
289- change_detection:: { CHECK_TICK_THRESHOLD , MAX_CHANGE_AGE } ,
311+ change_detection:: {
312+ ComponentTicks , Mut , NonSendMut , ResMut , Ticks , CHECK_TICK_THRESHOLD , MAX_CHANGE_AGE ,
313+ } ,
290314 component:: Component ,
291315 query:: ChangeTrackers ,
292316 system:: { IntoSystem , Query , System } ,
@@ -296,6 +320,8 @@ mod tests {
296320 #[ derive( Component ) ]
297321 struct C ;
298322
323+ struct R ; // Resource
324+
299325 #[ test]
300326 fn change_expiration ( ) {
301327 fn change_detected ( query : Query < ChangeTrackers < C > > ) -> bool {
@@ -382,4 +408,52 @@ mod tests {
382408 assert ! ( ticks_since_change == MAX_CHANGE_AGE ) ;
383409 }
384410 }
411+
412+ #[ test]
413+ fn mut_from_res_mut ( ) {
414+ let mut component_ticks = ComponentTicks {
415+ added : 1 ,
416+ changed : 2 ,
417+ } ;
418+ let ticks = Ticks {
419+ component_ticks : & mut component_ticks,
420+ last_change_tick : 3 ,
421+ change_tick : 4 ,
422+ } ;
423+ let mut res = R { } ;
424+ let res_mut = ResMut {
425+ value : & mut res,
426+ ticks,
427+ } ;
428+
429+ let into_mut: Mut < R > = res_mut. into ( ) ;
430+ assert_eq ! ( 1 , into_mut. ticks. component_ticks. added) ;
431+ assert_eq ! ( 2 , into_mut. ticks. component_ticks. changed) ;
432+ assert_eq ! ( 3 , into_mut. ticks. last_change_tick) ;
433+ assert_eq ! ( 4 , into_mut. ticks. change_tick) ;
434+ }
435+
436+ #[ test]
437+ fn mut_from_non_send_mut ( ) {
438+ let mut component_ticks = ComponentTicks {
439+ added : 1 ,
440+ changed : 2 ,
441+ } ;
442+ let ticks = Ticks {
443+ component_ticks : & mut component_ticks,
444+ last_change_tick : 3 ,
445+ change_tick : 4 ,
446+ } ;
447+ let mut res = R { } ;
448+ let non_send_mut = NonSendMut {
449+ value : & mut res,
450+ ticks,
451+ } ;
452+
453+ let into_mut: Mut < R > = non_send_mut. into ( ) ;
454+ assert_eq ! ( 1 , into_mut. ticks. component_ticks. added) ;
455+ assert_eq ! ( 2 , into_mut. ticks. component_ticks. changed) ;
456+ assert_eq ! ( 3 , into_mut. ticks. last_change_tick) ;
457+ assert_eq ! ( 4 , into_mut. ticks. change_tick) ;
458+ }
385459}
0 commit comments