diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index c4abfdc77a..767134fdc6 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -71,6 +71,9 @@ pub trait DetectChanges { /// [`SystemParam`](crate::system::SystemParam). fn last_changed(&self) -> Tick; + /// Returns the change tick recording the time this data was added. + fn added(&self) -> Tick; + /// The location that last caused this to change. fn changed_by(&self) -> MaybeLocation; } @@ -118,6 +121,15 @@ pub trait DetectChangesMut: DetectChanges { /// **Note**: This operation cannot be undone. fn set_changed(&mut self); + /// Flags this value as having been added. + /// + /// It is not normally necessary to call this method. + /// The 'added' tick is set when the value is first added, + /// and is not normally changed afterwards. + /// + /// **Note**: This operation cannot be undone. + fn set_added(&mut self); + /// Manually sets the change tick recording the time when this data was last mutated. /// /// # Warning @@ -126,6 +138,12 @@ pub trait DetectChangesMut: DetectChanges { /// If you want to avoid triggering change detection, use [`bypass_change_detection`](DetectChangesMut::bypass_change_detection) instead. fn set_last_changed(&mut self, last_changed: Tick); + /// Manually sets the added tick recording the time when this data was last added. + /// + /// # Warning + /// The caveats of [`set_last_changed`](DetectChangesMut::set_last_changed) apply. This modifies both the added and changed ticks together. + fn set_last_added(&mut self, last_added: Tick); + /// Manually bypasses change detection, allowing you to mutate the underlying value without updating the change tick. /// /// # Warning @@ -340,6 +358,11 @@ macro_rules! change_detection_impl { *self.ticks.changed } + #[inline] + fn added(&self) -> Tick { + *self.ticks.added + } + #[inline] fn changed_by(&self) -> MaybeLocation { self.changed_by.copied() @@ -376,6 +399,14 @@ macro_rules! change_detection_mut_impl { self.changed_by.assign(MaybeLocation::caller()); } + #[inline] + #[track_caller] + fn set_added(&mut self) { + *self.ticks.changed = self.ticks.this_run; + *self.ticks.added = self.ticks.this_run; + self.changed_by.assign(MaybeLocation::caller()); + } + #[inline] #[track_caller] fn set_last_changed(&mut self, last_changed: Tick) { @@ -383,6 +414,14 @@ macro_rules! change_detection_mut_impl { self.changed_by.assign(MaybeLocation::caller()); } + #[inline] + #[track_caller] + fn set_last_added(&mut self, last_added: Tick) { + *self.ticks.added = last_added; + *self.ticks.changed = last_added; + self.changed_by.assign(MaybeLocation::caller()); + } + #[inline] fn bypass_change_detection(&mut self) -> &mut Self::Inner { self.value @@ -1139,6 +1178,11 @@ impl<'w> DetectChanges for MutUntyped<'w> { fn changed_by(&self) -> MaybeLocation { self.changed_by.copied() } + + #[inline] + fn added(&self) -> Tick { + *self.ticks.added + } } impl<'w> DetectChangesMut for MutUntyped<'w> { @@ -1151,6 +1195,14 @@ impl<'w> DetectChangesMut for MutUntyped<'w> { self.changed_by.assign(MaybeLocation::caller()); } + #[inline] + #[track_caller] + fn set_added(&mut self) { + *self.ticks.changed = self.ticks.this_run; + *self.ticks.added = self.ticks.this_run; + self.changed_by.assign(MaybeLocation::caller()); + } + #[inline] #[track_caller] fn set_last_changed(&mut self, last_changed: Tick) { @@ -1158,6 +1210,14 @@ impl<'w> DetectChangesMut for MutUntyped<'w> { self.changed_by.assign(MaybeLocation::caller()); } + #[inline] + #[track_caller] + fn set_last_added(&mut self, last_added: Tick) { + *self.ticks.added = last_added; + *self.ticks.changed = last_added; + self.changed_by.assign(MaybeLocation::caller()); + } + #[inline] #[track_caller] fn bypass_change_detection(&mut self) -> &mut Self::Inner {