1515 bevy_ptr:: ThinSlicePtr ,
1616 core:: { cell:: UnsafeCell , panic:: Location } ,
1717} ;
18+ use crate :: storage:: { ParallelChanges , EntityChange } ;
1819
1920/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
2021///
@@ -387,6 +388,7 @@ macro_rules! impl_methods {
387388 /// <T>`, but you need a `Mut<T>`.
388389 pub fn reborrow( & mut self ) -> Mut <' _, $target> {
389390 Mut {
391+ on_change: self . on_change,
390392 value: self . value,
391393 ticks: TicksMut {
392394 added: self . ticks. added,
@@ -423,6 +425,7 @@ macro_rules! impl_methods {
423425 /// ```
424426 pub fn map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> & mut U ) -> Mut <' w, U > {
425427 Mut {
428+ on_change: self . on_change,
426429 value: f( self . value) ,
427430 ticks: self . ticks,
428431 #[ cfg( feature = "track_change_detection" ) ]
@@ -437,6 +440,7 @@ macro_rules! impl_methods {
437440 pub fn filter_map_unchanged<U : ?Sized >( self , f: impl FnOnce ( & mut $target) -> Option <& mut U >) -> Option <Mut <' w, U >> {
438441 let value = f( self . value) ;
439442 value. map( |value| Mut {
443+ on_change: self . on_change,
440444 value,
441445 ticks: self . ticks,
442446 #[ cfg( feature = "track_change_detection" ) ]
@@ -659,22 +663,31 @@ where
659663
660664change_detection_impl ! ( ResMut <' w, T >, T , Resource ) ;
661665change_detection_mut_impl ! ( ResMut <' w, T >, T , Resource ) ;
662- impl_methods ! ( ResMut <' w, T >, T , Resource ) ;
666+ // impl_methods!(ResMut<'w, T>, T, Resource);
663667impl_debug ! ( ResMut <' w, T >, Resource ) ;
664668
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- }
669+ impl < ' w , T : ?Sized + Resource > ResMut < ' w , T > {
670+
671+ /// TODO
672+ pub fn into_inner ( mut self ) -> & ' w mut T {
673+ self . set_changed ( ) ;
674+ self . value
675675 }
676676}
677677
678+ // impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
679+ // /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
680+ // /// while losing the specificity of `ResMut` for resources.
681+ // fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
682+ // Mut {
683+ // value: other.value,
684+ // ticks: other.ticks,
685+ // #[cfg(feature = "track_change_detection")]
686+ // changed_by: other.changed_by,
687+ // }
688+ // }
689+ // }
690+
678691/// Unique borrow of a non-[`Send`] resource.
679692///
680693/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
@@ -695,21 +708,21 @@ pub struct NonSendMut<'w, T: ?Sized + 'static> {
695708
696709change_detection_impl ! ( NonSendMut <' w, T >, T , ) ;
697710change_detection_mut_impl ! ( NonSendMut <' w, T >, T , ) ;
698- impl_methods ! ( NonSendMut <' w, T >, T , ) ;
711+ // impl_methods!(NonSendMut<'w, T>, T,);
699712impl_debug ! ( NonSendMut <' w, T >, ) ;
700713
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- }
714+ // impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
715+ // /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
716+ // /// while losing the specificity of `NonSendMut`.
717+ // fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
718+ // Mut {
719+ // value: other.value,
720+ // ticks: other.ticks,
721+ // #[cfg(feature = "track_change_detection")]
722+ // changed_by: other.changed_by,
723+ // }
724+ // }
725+ // }
713726
714727/// Shared borrow of an entity's component with access to change detection.
715728/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
@@ -869,6 +882,7 @@ impl_debug!(Ref<'w, T>,);
869882/// # fn update_player_position(player: &Player, new_position: Position) {}
870883/// ```
871884pub struct Mut < ' w , T : ?Sized > {
885+ pub ( crate ) on_change : Option < ( EntityChange , & ' w ParallelChanges ) > ,
872886 pub ( crate ) value : & ' w mut T ,
873887 pub ( crate ) ticks : TicksMut < ' w > ,
874888 #[ cfg( feature = "track_change_detection" ) ]
@@ -900,6 +914,7 @@ impl<'w, T: ?Sized> Mut<'w, T> {
900914 #[ cfg( feature = "track_change_detection" ) ] caller : & ' w mut & ' static Location < ' static > ,
901915 ) -> Self {
902916 Self {
917+ on_change : None ,
903918 value,
904919 ticks : TicksMut {
905920 added,
@@ -949,8 +964,58 @@ where
949964 }
950965}
951966
967+ impl < ' w , T : ?Sized > DetectChangesMut for Mut < ' w , T > {
968+ type Inner = T ;
969+ #[ inline]
970+ #[ track_caller]
971+ fn set_changed ( & mut self ) {
972+ * self . ticks . changed = self . ticks . this_run ;
973+ if let Some ( ( change, changes) ) = self . on_change {
974+ changes. push ( change) ;
975+ }
976+ #[ cfg( feature = "track_change_detection" ) ]
977+ {
978+ * self . changed_by = Location :: caller ( ) ;
979+ }
980+ }
981+ #[ inline]
982+ #[ track_caller]
983+ fn set_last_changed ( & mut self , last_changed : Tick ) {
984+ * self . ticks . changed = last_changed;
985+ #[ cfg( feature = "track_change_detection" ) ]
986+ {
987+ * self . changed_by = Location :: caller ( ) ;
988+ }
989+ }
990+
991+ #[ inline]
992+ fn bypass_change_detection ( & mut self ) -> & mut Self :: Inner {
993+ self . value
994+ }
995+ }
996+
997+ impl < ' w , T : ?Sized > DerefMut for Mut < ' w , T > {
998+ #[ inline]
999+ #[ track_caller]
1000+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
1001+ self . set_changed ( ) ;
1002+ #[ cfg( feature = "track_change_detection" ) ]
1003+ {
1004+ * self . changed_by = Location :: caller ( ) ;
1005+ }
1006+ self . value
1007+ }
1008+ }
1009+
1010+ impl < ' w , T : ?Sized > AsMut < T > for Mut < ' w , T > {
1011+ #[ inline]
1012+ fn as_mut ( & mut self ) -> & mut T {
1013+ self . deref_mut ( )
1014+ }
1015+ }
1016+
9521017change_detection_impl ! ( Mut <' w, T >, T , ) ;
953- change_detection_mut_impl ! ( Mut <' w, T >, T , ) ;
1018+ // change_detection_mut_impl!(Mut<'w, T>, T,);
9541019impl_methods ! ( Mut <' w, T >, T , ) ;
9551020impl_debug ! ( Mut <' w, T >, ) ;
9561021
@@ -1041,6 +1106,7 @@ impl<'w> MutUntyped<'w> {
10411106 /// ```
10421107 pub fn map_unchanged < T : ?Sized > ( self , f : impl FnOnce ( PtrMut < ' w > ) -> & ' w mut T ) -> Mut < ' w , T > {
10431108 Mut {
1109+ on_change : None , // TODO
10441110 value : f ( self . value ) ,
10451111 ticks : self . ticks ,
10461112 #[ cfg( feature = "track_change_detection" ) ]
@@ -1054,6 +1120,7 @@ impl<'w> MutUntyped<'w> {
10541120 /// - `T` must be the erased pointee type for this [`MutUntyped`].
10551121 pub unsafe fn with_type < T > ( self ) -> Mut < ' w , T > {
10561122 Mut {
1123+ on_change : None ,
10571124 // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
10581125 value : unsafe { self . value . deref_mut ( ) } ,
10591126 ticks : self . ticks ,
@@ -1423,6 +1490,7 @@ mod tests {
14231490 let mut caller = Location :: caller ( ) ;
14241491
14251492 let ptr = Mut {
1493+ on_change : None ,
14261494 value : & mut outer,
14271495 ticks,
14281496 #[ cfg( feature = "track_change_detection" ) ]
@@ -1551,6 +1619,7 @@ mod tests {
15511619 let mut caller = Location :: caller ( ) ;
15521620
15531621 let mut_typed = Mut {
1622+ on_change : None ,
15541623 value : & mut c,
15551624 ticks,
15561625 #[ cfg( feature = "track_change_detection" ) ]
0 commit comments