@@ -10,11 +10,13 @@ use core::{
1010 mem,
1111 ops:: { Deref , DerefMut } ,
1212} ;
13+ use std:: cell:: RefCell ;
1314#[ cfg( feature = "track_change_detection" ) ]
1415use {
1516 bevy_ptr:: ThinSlicePtr ,
1617 core:: { cell:: UnsafeCell , panic:: Location } ,
1718} ;
19+ use crate :: storage:: { EntityChange , EntityChanges } ;
1820
1921/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
2022///
@@ -387,6 +389,7 @@ macro_rules! impl_methods {
387389 /// <T>`, but you need a `Mut<T>`.
388390 pub fn reborrow( & mut self ) -> Mut <' _, $target> {
389391 Mut {
392+ on_change: self . on_change,
390393 value: self . value,
391394 ticks: TicksMut {
392395 added: self . ticks. added,
@@ -423,6 +426,7 @@ macro_rules! impl_methods {
423426 /// ```
424427 pub fn map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> & mut U ) -> Mut <' w, U > {
425428 Mut {
429+ on_change: self . on_change,
426430 value: f( self . value) ,
427431 ticks: self . ticks,
428432 #[ cfg( feature = "track_change_detection" ) ]
@@ -437,6 +441,7 @@ macro_rules! impl_methods {
437441 pub fn filter_map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> Option <& mut U >) -> Option <Mut <' w, U >> {
438442 let value = f( self . value) ;
439443 value. map( |value| Mut {
444+ on_change: self . on_change,
440445 value,
441446 ticks: self . ticks,
442447 #[ cfg( feature = "track_change_detection" ) ]
@@ -659,22 +664,31 @@ where
659664
660665change_detection_impl ! ( ResMut <' w, T >, T , Resource ) ;
661666change_detection_mut_impl ! ( ResMut <' w, T >, T , Resource ) ;
662- impl_methods ! ( ResMut <' w, T >, T , Resource ) ;
667+ // impl_methods!(ResMut<'w, T>, T, Resource);
663668impl_debug ! ( ResMut <' w, T >, Resource ) ;
664669
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
675676 }
676677}
677678
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+
678692/// Unique borrow of a non-[`Send`] resource.
679693///
680694/// 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> {
695709
696710change_detection_impl ! ( NonSendMut <' w, T >, T , ) ;
697711change_detection_mut_impl ! ( NonSendMut <' w, T >, T , ) ;
698- impl_methods ! ( NonSendMut <' w, T >, T , ) ;
712+ // impl_methods!(NonSendMut<'w, T>, T,);
699713impl_debug ! ( NonSendMut <' w, T >, ) ;
700714
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+ // }
713727
714728/// Shared borrow of an entity's component with access to change detection.
715729/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
@@ -869,6 +883,7 @@ impl_debug!(Ref<'w, T>,);
869883/// # fn update_player_position(player: &Player, new_position: Position) {}
870884/// ```
871885pub struct Mut < ' w , T : ?Sized > {
886+ pub ( crate ) on_change : Option < ( EntityChange , & ' w RefCell < EntityChanges > ) > ,
872887 pub ( crate ) value : & ' w mut T ,
873888 pub ( crate ) ticks : TicksMut < ' w > ,
874889 #[ cfg( feature = "track_change_detection" ) ]
@@ -900,6 +915,7 @@ impl<'w, T: ?Sized> Mut<'w, T> {
900915 #[ cfg( feature = "track_change_detection" ) ] caller : & ' w mut & ' static Location < ' static > ,
901916 ) -> Self {
902917 Self {
918+ on_change : None ,
903919 value,
904920 ticks : TicksMut {
905921 added,
@@ -949,8 +965,58 @@ where
949965 }
950966}
951967
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+
9521018change_detection_impl ! ( Mut <' w, T >, T , ) ;
953- change_detection_mut_impl ! ( Mut <' w, T >, T , ) ;
1019+ // change_detection_mut_impl!(Mut<'w, T>, T,);
9541020impl_methods ! ( Mut <' w, T >, T , ) ;
9551021impl_debug ! ( Mut <' w, T >, ) ;
9561022
@@ -1041,6 +1107,7 @@ impl<'w> MutUntyped<'w> {
10411107 /// ```
10421108 pub fn map_unchanged < T : ?Sized > ( self , f : impl FnOnce ( PtrMut < ' w > ) -> & ' w mut T ) -> Mut < ' w , T > {
10431109 Mut {
1110+ on_change : None , // TODO
10441111 value : f ( self . value ) ,
10451112 ticks : self . ticks ,
10461113 #[ cfg( feature = "track_change_detection" ) ]
@@ -1054,6 +1121,7 @@ impl<'w> MutUntyped<'w> {
10541121 /// - `T` must be the erased pointee type for this [`MutUntyped`].
10551122 pub unsafe fn with_type < T > ( self ) -> Mut < ' w , T > {
10561123 Mut {
1124+ on_change : None ,
10571125 // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
10581126 value : unsafe { self . value . deref_mut ( ) } ,
10591127 ticks : self . ticks ,
@@ -1423,6 +1491,7 @@ mod tests {
14231491 let mut caller = Location :: caller ( ) ;
14241492
14251493 let ptr = Mut {
1494+ on_change : None ,
14261495 value : & mut outer,
14271496 ticks,
14281497 #[ cfg( feature = "track_change_detection" ) ]
@@ -1551,6 +1620,7 @@ mod tests {
15511620 let mut caller = Location :: caller ( ) ;
15521621
15531622 let mut_typed = Mut {
1623+ on_change : None ,
15541624 value : & mut c,
15551625 ticks,
15561626 #[ cfg( feature = "track_change_detection" ) ]
0 commit comments