@@ -10,11 +10,13 @@ use core::{
10
10
mem,
11
11
ops:: { Deref , DerefMut } ,
12
12
} ;
13
+ use std:: cell:: RefCell ;
13
14
#[ cfg( feature = "track_change_detection" ) ]
14
15
use {
15
16
bevy_ptr:: ThinSlicePtr ,
16
17
core:: { cell:: UnsafeCell , panic:: Location } ,
17
18
} ;
19
+ use crate :: storage:: { EntityChange , EntityChanges , ParallelEntityChanges } ;
18
20
19
21
/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
20
22
///
@@ -387,6 +389,7 @@ macro_rules! impl_methods {
387
389
/// <T>`, but you need a `Mut<T>`.
388
390
pub fn reborrow( & mut self ) -> Mut <' _, $target> {
389
391
Mut {
392
+ on_change: self . on_change,
390
393
value: self . value,
391
394
ticks: TicksMut {
392
395
added: self . ticks. added,
@@ -423,6 +426,7 @@ macro_rules! impl_methods {
423
426
/// ```
424
427
pub fn map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> & mut U ) -> Mut <' w, U > {
425
428
Mut {
429
+ on_change: self . on_change,
426
430
value: f( self . value) ,
427
431
ticks: self . ticks,
428
432
#[ cfg( feature = "track_change_detection" ) ]
@@ -437,6 +441,7 @@ macro_rules! impl_methods {
437
441
pub fn filter_map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> Option <& mut U >) -> Option <Mut <' w, U >> {
438
442
let value = f( self . value) ;
439
443
value. map( |value| Mut {
444
+ on_change: self . on_change,
440
445
value,
441
446
ticks: self . ticks,
442
447
#[ cfg( feature = "track_change_detection" ) ]
@@ -659,22 +664,31 @@ where
659
664
660
665
change_detection_impl ! ( ResMut <' w, T >, T , Resource ) ;
661
666
change_detection_mut_impl ! ( ResMut <' w, T >, T , Resource ) ;
662
- impl_methods ! ( ResMut <' w, T >, T , Resource ) ;
667
+ // impl_methods!(ResMut<'w, T>, T, Resource);
663
668
impl_debug ! ( ResMut <' w, T >, Resource ) ;
664
669
665
- impl < ' w , T : Resource > From < ResMut < ' w , T > > for Mut < ' w , T > {
666
- /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
667
- /// while losing the specificity of `ResMut` for resources.
668
- fn from ( other : ResMut < ' w , T > ) -> Mut < ' w , T > {
669
- Mut {
670
- value : other. value ,
671
- ticks : other. ticks ,
672
- #[ cfg( feature = "track_change_detection" ) ]
673
- changed_by : other. changed_by ,
674
- }
670
+ impl < ' w , T : ?Sized + Resource > ResMut < ' w , T > {
671
+
672
+ /// TODO
673
+ pub fn into_inner ( mut self ) -> & ' w mut T {
674
+ self . set_changed ( ) ;
675
+ self . value
675
676
}
676
677
}
677
678
679
+ // impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
680
+ // /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
681
+ // /// while losing the specificity of `ResMut` for resources.
682
+ // fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
683
+ // Mut {
684
+ // value: other.value,
685
+ // ticks: other.ticks,
686
+ // #[cfg(feature = "track_change_detection")]
687
+ // changed_by: other.changed_by,
688
+ // }
689
+ // }
690
+ // }
691
+
678
692
/// Unique borrow of a non-[`Send`] resource.
679
693
///
680
694
/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
@@ -695,21 +709,21 @@ pub struct NonSendMut<'w, T: ?Sized + 'static> {
695
709
696
710
change_detection_impl ! ( NonSendMut <' w, T >, T , ) ;
697
711
change_detection_mut_impl ! ( NonSendMut <' w, T >, T , ) ;
698
- impl_methods ! ( NonSendMut <' w, T >, T , ) ;
712
+ // impl_methods!(NonSendMut<'w, T>, T,);
699
713
impl_debug ! ( NonSendMut <' w, T >, ) ;
700
714
701
- impl < ' w , T : ' static > From < NonSendMut < ' w , T > > for Mut < ' w , T > {
702
- /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
703
- /// while losing the specificity of `NonSendMut`.
704
- fn from ( other : NonSendMut < ' w , T > ) -> Mut < ' w , T > {
705
- Mut {
706
- value : other. value ,
707
- ticks : other. ticks ,
708
- #[ cfg( feature = "track_change_detection" ) ]
709
- changed_by : other. changed_by ,
710
- }
711
- }
712
- }
715
+ // impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
716
+ // /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
717
+ // /// while losing the specificity of `NonSendMut`.
718
+ // fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
719
+ // Mut {
720
+ // value: other.value,
721
+ // ticks: other.ticks,
722
+ // #[cfg(feature = "track_change_detection")]
723
+ // changed_by: other.changed_by,
724
+ // }
725
+ // }
726
+ // }
713
727
714
728
/// Shared borrow of an entity's component with access to change detection.
715
729
/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
@@ -869,6 +883,7 @@ impl_debug!(Ref<'w, T>,);
869
883
/// # fn update_player_position(player: &Player, new_position: Position) {}
870
884
/// ```
871
885
pub struct Mut < ' w , T : ?Sized > {
886
+ pub ( crate ) on_change : Option < ( EntityChange , & ' w RefCell < EntityChanges > ) > ,
872
887
pub ( crate ) value : & ' w mut T ,
873
888
pub ( crate ) ticks : TicksMut < ' w > ,
874
889
#[ cfg( feature = "track_change_detection" ) ]
@@ -900,6 +915,7 @@ impl<'w, T: ?Sized> Mut<'w, T> {
900
915
#[ cfg( feature = "track_change_detection" ) ] caller : & ' w mut & ' static Location < ' static > ,
901
916
) -> Self {
902
917
Self {
918
+ on_change : None ,
903
919
value,
904
920
ticks : TicksMut {
905
921
added,
@@ -949,8 +965,58 @@ where
949
965
}
950
966
}
951
967
968
+ impl < ' w , T : ?Sized > DetectChangesMut for Mut < ' w , T > {
969
+ type Inner = T ;
970
+ #[ inline]
971
+ #[ track_caller]
972
+ fn set_changed ( & mut self ) {
973
+ * self . ticks . changed = self . ticks . this_run ;
974
+ if let Some ( ( change, changes) ) = self . on_change {
975
+ changes. borrow_mut ( ) . push ( change) ;
976
+ }
977
+ #[ cfg( feature = "track_change_detection" ) ]
978
+ {
979
+ * self . changed_by = Location :: caller ( ) ;
980
+ }
981
+ }
982
+ #[ inline]
983
+ #[ track_caller]
984
+ fn set_last_changed ( & mut self , last_changed : Tick ) {
985
+ * self . ticks . changed = last_changed;
986
+ #[ cfg( feature = "track_change_detection" ) ]
987
+ {
988
+ * self . changed_by = Location :: caller ( ) ;
989
+ }
990
+ }
991
+
992
+ #[ inline]
993
+ fn bypass_change_detection ( & mut self ) -> & mut Self :: Inner {
994
+ self . value
995
+ }
996
+ }
997
+
998
+ impl < ' w , T : ?Sized > DerefMut for Mut < ' w , T > {
999
+ #[ inline]
1000
+ #[ track_caller]
1001
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
1002
+ self . set_changed ( ) ;
1003
+ #[ cfg( feature = "track_change_detection" ) ]
1004
+ {
1005
+ * self . changed_by = Location :: caller ( ) ;
1006
+ }
1007
+ self . value
1008
+ }
1009
+ }
1010
+
1011
+ impl < ' w , T : ?Sized > AsMut < T > for Mut < ' w , T > {
1012
+ #[ inline]
1013
+ fn as_mut ( & mut self ) -> & mut T {
1014
+ self . deref_mut ( )
1015
+ }
1016
+ }
1017
+
952
1018
change_detection_impl ! ( Mut <' w, T >, T , ) ;
953
- change_detection_mut_impl ! ( Mut <' w, T >, T , ) ;
1019
+ // change_detection_mut_impl!(Mut<'w, T>, T,);
954
1020
impl_methods ! ( Mut <' w, T >, T , ) ;
955
1021
impl_debug ! ( Mut <' w, T >, ) ;
956
1022
@@ -1041,6 +1107,7 @@ impl<'w> MutUntyped<'w> {
1041
1107
/// ```
1042
1108
pub fn map_unchanged < T : ?Sized > ( self , f : impl FnOnce ( PtrMut < ' w > ) -> & ' w mut T ) -> Mut < ' w , T > {
1043
1109
Mut {
1110
+ on_change : None , // TODO
1044
1111
value : f ( self . value ) ,
1045
1112
ticks : self . ticks ,
1046
1113
#[ cfg( feature = "track_change_detection" ) ]
@@ -1054,6 +1121,7 @@ impl<'w> MutUntyped<'w> {
1054
1121
/// - `T` must be the erased pointee type for this [`MutUntyped`].
1055
1122
pub unsafe fn with_type < T > ( self ) -> Mut < ' w , T > {
1056
1123
Mut {
1124
+ on_change : None ,
1057
1125
// SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
1058
1126
value : unsafe { self . value . deref_mut ( ) } ,
1059
1127
ticks : self . ticks ,
@@ -1423,6 +1491,7 @@ mod tests {
1423
1491
let mut caller = Location :: caller ( ) ;
1424
1492
1425
1493
let ptr = Mut {
1494
+ on_change : None ,
1426
1495
value : & mut outer,
1427
1496
ticks,
1428
1497
#[ cfg( feature = "track_change_detection" ) ]
@@ -1551,6 +1620,7 @@ mod tests {
1551
1620
let mut caller = Location :: caller ( ) ;
1552
1621
1553
1622
let mut_typed = Mut {
1623
+ on_change : None ,
1554
1624
value : & mut c,
1555
1625
ticks,
1556
1626
#[ cfg( feature = "track_change_detection" ) ]
0 commit comments