@@ -185,6 +185,17 @@ change_detection_impl!(ResMut<'a, T>, T, Resource);
185
185
impl_into_inner ! ( ResMut <' a, T >, T , Resource ) ;
186
186
impl_debug ! ( ResMut <' a, T >, Resource ) ;
187
187
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
+
188
199
/// Unique borrow of a non-[`Send`] resource.
189
200
///
190
201
/// 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,);
206
217
impl_into_inner ! ( NonSendMut <' a, T >, T , ) ;
207
218
impl_debug ! ( NonSendMut <' a, T >, ) ;
208
219
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
+
209
231
/// Unique mutable borrow of an entity's component
210
232
pub struct Mut < ' a , T > {
211
233
pub ( crate ) value : & ' a mut T ,
@@ -286,7 +308,9 @@ impl std::fmt::Debug for MutUntyped<'_> {
286
308
mod tests {
287
309
use crate :: {
288
310
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
+ } ,
290
314
component:: Component ,
291
315
query:: ChangeTrackers ,
292
316
system:: { IntoSystem , Query , System } ,
@@ -296,6 +320,8 @@ mod tests {
296
320
#[ derive( Component ) ]
297
321
struct C ;
298
322
323
+ struct R ; // Resource
324
+
299
325
#[ test]
300
326
fn change_expiration ( ) {
301
327
fn change_detected ( query : Query < ChangeTrackers < C > > ) -> bool {
@@ -382,4 +408,52 @@ mod tests {
382
408
assert ! ( ticks_since_change == MAX_CHANGE_AGE ) ;
383
409
}
384
410
}
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
+ }
385
459
}
0 commit comments