bevy_ecs/
change_detection.rs

1//! Types that detect when their internal data mutate.
2
3use crate::{
4    component::{Tick, TickCells},
5    ptr::PtrMut,
6    resource::Resource,
7};
8use alloc::borrow::ToOwned;
9use bevy_ptr::{Ptr, UnsafeCellDeref};
10#[cfg(feature = "bevy_reflect")]
11use bevy_reflect::Reflect;
12use core::{
13    marker::PhantomData,
14    mem,
15    ops::{Deref, DerefMut},
16    panic::Location,
17};
18
19/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
20///
21/// Change ticks can only be scanned when systems aren't running. Thus, if the threshold is `N`,
22/// the maximum is `2 * N - 1` (i.e. the world ticks `N - 1` times, then `N` times).
23///
24/// If no change is older than `u32::MAX - (2 * N - 1)` following a scan, none of their ages can
25/// overflow and cause false positives.
26// (518,400,000 = 1000 ticks per frame * 144 frames per second * 3600 seconds per hour)
27pub const CHECK_TICK_THRESHOLD: u32 = 518_400_000;
28
29/// The maximum change tick difference that won't overflow before the next `check_tick` scan.
30///
31/// Changes stop being detected once they become this old.
32pub const MAX_CHANGE_AGE: u32 = u32::MAX - (2 * CHECK_TICK_THRESHOLD - 1);
33
34/// Types that can read change detection information.
35/// This change detection is controlled by [`DetectChangesMut`] types such as [`ResMut`].
36///
37/// ## Example
38/// Using types that implement [`DetectChanges`], such as [`Res`], provide
39/// a way to query if a value has been mutated in another system.
40///
41/// ```
42/// use bevy_ecs::prelude::*;
43///
44/// #[derive(Resource)]
45/// struct MyResource(u32);
46///
47/// fn my_system(mut resource: Res<MyResource>) {
48///     if resource.is_changed() {
49///         println!("My component was mutated!");
50///     }
51/// }
52/// ```
53pub trait DetectChanges {
54    /// Returns `true` if this value was added after the system last ran.
55    fn is_added(&self) -> bool;
56
57    /// Returns `true` if this value was added or mutably dereferenced
58    /// either since the last time the system ran or, if the system never ran,
59    /// since the beginning of the program.
60    ///
61    /// To check if the value was mutably dereferenced only,
62    /// use `this.is_changed() && !this.is_added()`.
63    fn is_changed(&self) -> bool;
64
65    /// Returns the change tick recording the time this data was most recently changed.
66    ///
67    /// Note that components and resources are also marked as changed upon insertion.
68    ///
69    /// For comparison, the previous change tick of a system can be read using the
70    /// [`SystemChangeTick`](crate::system::SystemChangeTick)
71    /// [`SystemParam`](crate::system::SystemParam).
72    fn last_changed(&self) -> Tick;
73
74    /// Returns the change tick recording the time this data was added.
75    fn added(&self) -> Tick;
76
77    /// The location that last caused this to change.
78    fn changed_by(&self) -> MaybeLocation;
79}
80
81/// Types that implement reliable change detection.
82///
83/// ## Example
84/// Using types that implement [`DetectChangesMut`], such as [`ResMut`], provide
85/// a way to query if a value has been mutated in another system.
86/// Normally change detection is triggered by either [`DerefMut`] or [`AsMut`], however
87/// it can be manually triggered via [`set_changed`](DetectChangesMut::set_changed).
88///
89/// To ensure that changes are only triggered when the value actually differs,
90/// check if the value would change before assignment, such as by checking that `new != old`.
91/// You must be *sure* that you are not mutably dereferencing in this process.
92///
93/// [`set_if_neq`](DetectChangesMut::set_if_neq) is a helper
94/// method for this common functionality.
95///
96/// ```
97/// use bevy_ecs::prelude::*;
98///
99/// #[derive(Resource)]
100/// struct MyResource(u32);
101///
102/// fn my_system(mut resource: ResMut<MyResource>) {
103///     if resource.is_changed() {
104///         println!("My resource was mutated!");
105///     }
106///
107///    resource.0 = 42; // triggers change detection via [`DerefMut`]
108/// }
109/// ```
110pub trait DetectChangesMut: DetectChanges {
111    /// The type contained within this smart pointer
112    ///
113    /// For example, for `ResMut<T>` this would be `T`.
114    type Inner: ?Sized;
115
116    /// Flags this value as having been changed.
117    ///
118    /// Mutably accessing this smart pointer will automatically flag this value as having been changed.
119    /// However, mutation through interior mutability requires manual reporting.
120    ///
121    /// **Note**: This operation cannot be undone.
122    fn set_changed(&mut self);
123
124    /// Flags this value as having been added.
125    ///
126    /// It is not normally necessary to call this method.
127    /// The 'added' tick is set when the value is first added,
128    /// and is not normally changed afterwards.
129    ///
130    /// **Note**: This operation cannot be undone.
131    fn set_added(&mut self);
132
133    /// Manually sets the change tick recording the time when this data was last mutated.
134    ///
135    /// # Warning
136    /// This is a complex and error-prone operation, primarily intended for use with rollback networking strategies.
137    /// If you merely want to flag this data as changed, use [`set_changed`](DetectChangesMut::set_changed) instead.
138    /// If you want to avoid triggering change detection, use [`bypass_change_detection`](DetectChangesMut::bypass_change_detection) instead.
139    fn set_last_changed(&mut self, last_changed: Tick);
140
141    /// Manually sets the added tick recording the time when this data was last added.
142    ///
143    /// # Warning
144    /// The caveats of [`set_last_changed`](DetectChangesMut::set_last_changed) apply. This modifies both the added and changed ticks together.
145    fn set_last_added(&mut self, last_added: Tick);
146
147    /// Manually bypasses change detection, allowing you to mutate the underlying value without updating the change tick.
148    ///
149    /// # Warning
150    /// This is a risky operation, that can have unexpected consequences on any system relying on this code.
151    /// However, it can be an essential escape hatch when, for example,
152    /// you are trying to synchronize representations using change detection and need to avoid infinite recursion.
153    fn bypass_change_detection(&mut self) -> &mut Self::Inner;
154
155    /// Overwrites this smart pointer with the given value, if and only if `*self != value`.
156    /// Returns `true` if the value was overwritten, and returns `false` if it was not.
157    ///
158    /// This is useful to ensure change detection is only triggered when the underlying value
159    /// changes, instead of every time it is mutably accessed.
160    ///
161    /// If you're dealing with non-trivial structs which have multiple fields of non-trivial size,
162    /// then consider applying a `map_unchanged` beforehand to allow changing only the relevant
163    /// field and prevent unnecessary copying and cloning.
164    /// See the docs of [`Mut::map_unchanged`], [`MutUntyped::map_unchanged`],
165    /// [`ResMut::map_unchanged`] or [`NonSendMut::map_unchanged`] for an example
166    ///
167    /// If you need the previous value, use [`replace_if_neq`](DetectChangesMut::replace_if_neq).
168    ///
169    /// # Examples
170    ///
171    /// ```
172    /// # use bevy_ecs::{prelude::*, schedule::common_conditions::resource_changed};
173    /// #[derive(Resource, PartialEq, Eq)]
174    /// pub struct Score(u32);
175    ///
176    /// fn reset_score(mut score: ResMut<Score>) {
177    ///     // Set the score to zero, unless it is already zero.
178    ///     score.set_if_neq(Score(0));
179    /// }
180    /// # let mut world = World::new();
181    /// # world.insert_resource(Score(1));
182    /// # let mut score_changed = IntoSystem::into_system(resource_changed::<Score>);
183    /// # score_changed.initialize(&mut world);
184    /// # score_changed.run((), &mut world);
185    /// #
186    /// # let mut schedule = Schedule::default();
187    /// # schedule.add_systems(reset_score);
188    /// #
189    /// # // first time `reset_score` runs, the score is changed.
190    /// # schedule.run(&mut world);
191    /// # assert!(score_changed.run((), &mut world));
192    /// # // second time `reset_score` runs, the score is not changed.
193    /// # schedule.run(&mut world);
194    /// # assert!(!score_changed.run((), &mut world));
195    /// ```
196    #[inline]
197    #[track_caller]
198    fn set_if_neq(&mut self, value: Self::Inner) -> bool
199    where
200        Self::Inner: Sized + PartialEq,
201    {
202        let old = self.bypass_change_detection();
203        if *old != value {
204            *old = value;
205            self.set_changed();
206            true
207        } else {
208            false
209        }
210    }
211
212    /// Overwrites this smart pointer with the given value, if and only if `*self != value`,
213    /// returning the previous value if this occurs.
214    ///
215    /// This is useful to ensure change detection is only triggered when the underlying value
216    /// changes, instead of every time it is mutably accessed.
217    ///
218    /// If you're dealing with non-trivial structs which have multiple fields of non-trivial size,
219    /// then consider applying a [`map_unchanged`](Mut::map_unchanged) beforehand to allow
220    /// changing only the relevant field and prevent unnecessary copying and cloning.
221    /// See the docs of [`Mut::map_unchanged`], [`MutUntyped::map_unchanged`],
222    /// [`ResMut::map_unchanged`] or [`NonSendMut::map_unchanged`] for an example
223    ///
224    /// If you don't need the previous value, use [`set_if_neq`](DetectChangesMut::set_if_neq).
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// # use bevy_ecs::{prelude::*, schedule::common_conditions::{resource_changed, on_event}};
230    /// #[derive(Resource, PartialEq, Eq)]
231    /// pub struct Score(u32);
232    ///
233    /// #[derive(Event, PartialEq, Eq)]
234    /// pub struct ScoreChanged {
235    ///     current: u32,
236    ///     previous: u32,
237    /// }
238    ///
239    /// fn reset_score(mut score: ResMut<Score>, mut score_changed: EventWriter<ScoreChanged>) {
240    ///     // Set the score to zero, unless it is already zero.
241    ///     let new_score = 0;
242    ///     if let Some(Score(previous_score)) = score.replace_if_neq(Score(new_score)) {
243    ///         // If `score` change, emit a `ScoreChanged` event.
244    ///         score_changed.write(ScoreChanged {
245    ///             current: new_score,
246    ///             previous: previous_score,
247    ///         });
248    ///     }
249    /// }
250    /// # let mut world = World::new();
251    /// # world.insert_resource(Events::<ScoreChanged>::default());
252    /// # world.insert_resource(Score(1));
253    /// # let mut score_changed = IntoSystem::into_system(resource_changed::<Score>);
254    /// # score_changed.initialize(&mut world);
255    /// # score_changed.run((), &mut world);
256    /// #
257    /// # let mut score_changed_event = IntoSystem::into_system(on_event::<ScoreChanged>);
258    /// # score_changed_event.initialize(&mut world);
259    /// # score_changed_event.run((), &mut world);
260    /// #
261    /// # let mut schedule = Schedule::default();
262    /// # schedule.add_systems(reset_score);
263    /// #
264    /// # // first time `reset_score` runs, the score is changed.
265    /// # schedule.run(&mut world);
266    /// # assert!(score_changed.run((), &mut world));
267    /// # assert!(score_changed_event.run((), &mut world));
268    /// # // second time `reset_score` runs, the score is not changed.
269    /// # schedule.run(&mut world);
270    /// # assert!(!score_changed.run((), &mut world));
271    /// # assert!(!score_changed_event.run((), &mut world));
272    /// ```
273    #[inline]
274    #[must_use = "If you don't need to handle the previous value, use `set_if_neq` instead."]
275    fn replace_if_neq(&mut self, value: Self::Inner) -> Option<Self::Inner>
276    where
277        Self::Inner: Sized + PartialEq,
278    {
279        let old = self.bypass_change_detection();
280        if *old != value {
281            let previous = mem::replace(old, value);
282            self.set_changed();
283            Some(previous)
284        } else {
285            None
286        }
287    }
288
289    /// Overwrites this smart pointer with a clone of the given value, if and only if `*self != value`.
290    /// Returns `true` if the value was overwritten, and returns `false` if it was not.
291    ///
292    /// This method is useful when the caller only has a borrowed form of `Inner`,
293    /// e.g. when writing a `&str` into a `Mut<String>`.
294    ///
295    /// # Examples
296    /// ```
297    /// # extern crate alloc;
298    /// # use alloc::borrow::ToOwned;
299    /// # use bevy_ecs::{prelude::*, schedule::common_conditions::resource_changed};
300    /// #[derive(Resource)]
301    /// pub struct Message(String);
302    ///
303    /// fn update_message(mut message: ResMut<Message>) {
304    ///     // Set the score to zero, unless it is already zero.
305    ///     ResMut::map_unchanged(message, |Message(msg)| msg).clone_from_if_neq("another string");
306    /// }
307    /// # let mut world = World::new();
308    /// # world.insert_resource(Message("initial string".into()));
309    /// # let mut message_changed = IntoSystem::into_system(resource_changed::<Message>);
310    /// # message_changed.initialize(&mut world);
311    /// # message_changed.run((), &mut world);
312    /// #
313    /// # let mut schedule = Schedule::default();
314    /// # schedule.add_systems(update_message);
315    /// #
316    /// # // first time `reset_score` runs, the score is changed.
317    /// # schedule.run(&mut world);
318    /// # assert!(message_changed.run((), &mut world));
319    /// # // second time `reset_score` runs, the score is not changed.
320    /// # schedule.run(&mut world);
321    /// # assert!(!message_changed.run((), &mut world));
322    /// ```
323    fn clone_from_if_neq<T>(&mut self, value: &T) -> bool
324    where
325        T: ToOwned<Owned = Self::Inner> + ?Sized,
326        Self::Inner: PartialEq<T>,
327    {
328        let old = self.bypass_change_detection();
329        if old != value {
330            value.clone_into(old);
331            self.set_changed();
332            true
333        } else {
334            false
335        }
336    }
337}
338
339macro_rules! change_detection_impl {
340    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
341        impl<$($generics),* : ?Sized $(+ $traits)?> DetectChanges for $name<$($generics),*> {
342            #[inline]
343            fn is_added(&self) -> bool {
344                self.ticks
345                    .added
346                    .is_newer_than(self.ticks.last_run, self.ticks.this_run)
347            }
348
349            #[inline]
350            fn is_changed(&self) -> bool {
351                self.ticks
352                    .changed
353                    .is_newer_than(self.ticks.last_run, self.ticks.this_run)
354            }
355
356            #[inline]
357            fn last_changed(&self) -> Tick {
358                *self.ticks.changed
359            }
360
361            #[inline]
362            fn added(&self) -> Tick {
363                *self.ticks.added
364            }
365
366            #[inline]
367            fn changed_by(&self) -> MaybeLocation {
368                self.changed_by.copied()
369            }
370        }
371
372        impl<$($generics),*: ?Sized $(+ $traits)?> Deref for $name<$($generics),*> {
373            type Target = $target;
374
375            #[inline]
376            fn deref(&self) -> &Self::Target {
377                self.value
378            }
379        }
380
381        impl<$($generics),* $(: $traits)?> AsRef<$target> for $name<$($generics),*> {
382            #[inline]
383            fn as_ref(&self) -> &$target {
384                self.deref()
385            }
386        }
387    }
388}
389
390macro_rules! change_detection_mut_impl {
391    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
392        impl<$($generics),* : ?Sized $(+ $traits)?> DetectChangesMut for $name<$($generics),*> {
393            type Inner = $target;
394
395            #[inline]
396            #[track_caller]
397            fn set_changed(&mut self) {
398                *self.ticks.changed = self.ticks.this_run;
399                self.changed_by.assign(MaybeLocation::caller());
400            }
401
402            #[inline]
403            #[track_caller]
404            fn set_added(&mut self) {
405                *self.ticks.changed = self.ticks.this_run;
406                *self.ticks.added = self.ticks.this_run;
407                self.changed_by.assign(MaybeLocation::caller());
408            }
409
410            #[inline]
411            #[track_caller]
412            fn set_last_changed(&mut self, last_changed: Tick) {
413                *self.ticks.changed = last_changed;
414                self.changed_by.assign(MaybeLocation::caller());
415            }
416
417            #[inline]
418            #[track_caller]
419            fn set_last_added(&mut self, last_added: Tick) {
420                *self.ticks.added = last_added;
421                *self.ticks.changed = last_added;
422                self.changed_by.assign(MaybeLocation::caller());
423            }
424
425            #[inline]
426            fn bypass_change_detection(&mut self) -> &mut Self::Inner {
427                self.value
428            }
429        }
430
431        impl<$($generics),* : ?Sized $(+ $traits)?> DerefMut for $name<$($generics),*> {
432            #[inline]
433            #[track_caller]
434            fn deref_mut(&mut self) -> &mut Self::Target {
435                self.set_changed();
436                self.changed_by.assign(MaybeLocation::caller());
437                self.value
438            }
439        }
440
441        impl<$($generics),* $(: $traits)?> AsMut<$target> for $name<$($generics),*> {
442            #[inline]
443            fn as_mut(&mut self) -> &mut $target {
444                self.deref_mut()
445            }
446        }
447    };
448}
449
450macro_rules! impl_methods {
451    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
452        impl<$($generics),* : ?Sized $(+ $traits)?> $name<$($generics),*> {
453            /// Consume `self` and return a mutable reference to the
454            /// contained value while marking `self` as "changed".
455            #[inline]
456            pub fn into_inner(mut self) -> &'w mut $target {
457                self.set_changed();
458                self.value
459            }
460
461            /// Returns a `Mut<>` with a smaller lifetime.
462            /// This is useful if you have `&mut
463            #[doc = stringify!($name)]
464            /// <T>`, but you need a `Mut<T>`.
465            pub fn reborrow(&mut self) -> Mut<'_, $target> {
466                Mut {
467                    value: self.value,
468                    ticks: TicksMut {
469                        added: self.ticks.added,
470                        changed: self.ticks.changed,
471                        last_run: self.ticks.last_run,
472                        this_run: self.ticks.this_run,
473                    },
474                    changed_by: self.changed_by.as_deref_mut(),
475                }
476            }
477
478            /// Maps to an inner value by applying a function to the contained reference, without flagging a change.
479            ///
480            /// You should never modify the argument passed to the closure -- if you want to modify the data
481            /// without flagging a change, consider using [`DetectChangesMut::bypass_change_detection`] to make your intent explicit.
482            ///
483            /// ```
484            /// # use bevy_ecs::prelude::*;
485            /// # #[derive(PartialEq)] pub struct Vec2;
486            /// # impl Vec2 { pub const ZERO: Self = Self; }
487            /// # #[derive(Component)] pub struct Transform { translation: Vec2 }
488            /// // When run, zeroes the translation of every entity.
489            /// fn reset_positions(mut transforms: Query<&mut Transform>) {
490            ///     for transform in &mut transforms {
491            ///         // We pinky promise not to modify `t` within the closure.
492            ///         // Breaking this promise will result in logic errors, but will never cause undefined behavior.
493            ///         let mut translation = transform.map_unchanged(|t| &mut t.translation);
494            ///         // Only reset the translation if it isn't already zero;
495            ///         translation.set_if_neq(Vec2::ZERO);
496            ///     }
497            /// }
498            /// # bevy_ecs::system::assert_is_system(reset_positions);
499            /// ```
500            pub fn map_unchanged<U: ?Sized>(self, f: impl FnOnce(&mut $target) -> &mut U) -> Mut<'w, U> {
501                Mut {
502                    value: f(self.value),
503                    ticks: self.ticks,
504                    changed_by: self.changed_by,
505                }
506            }
507
508            /// Optionally maps to an inner value by applying a function to the contained reference.
509            /// This is useful in a situation where you need to convert a `Mut<T>` to a `Mut<U>`, but only if `T` contains `U`.
510            ///
511            /// As with `map_unchanged`, you should never modify the argument passed to the closure.
512            pub fn filter_map_unchanged<U: ?Sized>(self, f: impl FnOnce(&mut $target) -> Option<&mut U>) -> Option<Mut<'w, U>> {
513                let value = f(self.value);
514                value.map(|value| Mut {
515                    value,
516                    ticks: self.ticks,
517                    changed_by: self.changed_by,
518                })
519            }
520
521            /// Optionally maps to an inner value by applying a function to the contained reference, returns an error on failure.
522            /// This is useful in a situation where you need to convert a `Mut<T>` to a `Mut<U>`, but only if `T` contains `U`.
523            ///
524            /// As with `map_unchanged`, you should never modify the argument passed to the closure.
525            pub fn try_map_unchanged<U: ?Sized, E>(self, f: impl FnOnce(&mut $target) -> Result<&mut U, E>) -> Result<Mut<'w, U>, E> {
526                let value = f(self.value);
527                value.map(|value| Mut {
528                    value,
529                    ticks: self.ticks,
530                    changed_by: self.changed_by,
531                })
532            }
533
534            /// Allows you access to the dereferenced value of this pointer without immediately
535            /// triggering change detection.
536            pub fn as_deref_mut(&mut self) -> Mut<'_, <$target as Deref>::Target>
537                where $target: DerefMut
538            {
539                self.reborrow().map_unchanged(|v| v.deref_mut())
540            }
541
542        }
543    };
544}
545
546macro_rules! impl_debug {
547    ($name:ident < $( $generics:tt ),+ >, $($traits:ident)?) => {
548        impl<$($generics),* : ?Sized $(+ $traits)?> core::fmt::Debug for $name<$($generics),*>
549            where T: core::fmt::Debug
550        {
551            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
552                f.debug_tuple(stringify!($name))
553                    .field(&self.value)
554                    .finish()
555            }
556        }
557
558    };
559}
560
561#[derive(Clone)]
562pub(crate) struct Ticks<'w> {
563    pub(crate) added: &'w Tick,
564    pub(crate) changed: &'w Tick,
565    pub(crate) last_run: Tick,
566    pub(crate) this_run: Tick,
567}
568
569impl<'w> Ticks<'w> {
570    /// # Safety
571    /// This should never alias the underlying ticks with a mutable one such as `TicksMut`.
572    #[inline]
573    pub(crate) unsafe fn from_tick_cells(
574        cells: TickCells<'w>,
575        last_run: Tick,
576        this_run: Tick,
577    ) -> Self {
578        Self {
579            // SAFETY: Caller ensures there is no mutable access to the cell.
580            added: unsafe { cells.added.deref() },
581            // SAFETY: Caller ensures there is no mutable access to the cell.
582            changed: unsafe { cells.changed.deref() },
583            last_run,
584            this_run,
585        }
586    }
587}
588
589pub(crate) struct TicksMut<'w> {
590    pub(crate) added: &'w mut Tick,
591    pub(crate) changed: &'w mut Tick,
592    pub(crate) last_run: Tick,
593    pub(crate) this_run: Tick,
594}
595
596impl<'w> TicksMut<'w> {
597    /// # Safety
598    /// This should never alias the underlying ticks. All access must be unique.
599    #[inline]
600    pub(crate) unsafe fn from_tick_cells(
601        cells: TickCells<'w>,
602        last_run: Tick,
603        this_run: Tick,
604    ) -> Self {
605        Self {
606            // SAFETY: Caller ensures there is no alias to the cell.
607            added: unsafe { cells.added.deref_mut() },
608            // SAFETY: Caller ensures there is no alias to the cell.
609            changed: unsafe { cells.changed.deref_mut() },
610            last_run,
611            this_run,
612        }
613    }
614}
615
616impl<'w> From<TicksMut<'w>> for Ticks<'w> {
617    fn from(ticks: TicksMut<'w>) -> Self {
618        Ticks {
619            added: ticks.added,
620            changed: ticks.changed,
621            last_run: ticks.last_run,
622            this_run: ticks.this_run,
623        }
624    }
625}
626
627/// Shared borrow of a [`Resource`].
628///
629/// See the [`Resource`] documentation for usage.
630///
631/// If you need a unique mutable borrow, use [`ResMut`] instead.
632///
633/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
634/// This will cause a panic, but can be configured to do nothing or warn once.
635///
636/// Use [`Option<Res<T>>`] instead if the resource might not always exist.
637pub struct Res<'w, T: ?Sized + Resource> {
638    pub(crate) value: &'w T,
639    pub(crate) ticks: Ticks<'w>,
640    pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,
641}
642
643impl<'w, T: Resource> Res<'w, T> {
644    /// Copies a reference to a resource.
645    ///
646    /// Note that unless you actually need an instance of `Res<T>`, you should
647    /// prefer to just convert it to `&T` which can be freely copied.
648    #[expect(
649        clippy::should_implement_trait,
650        reason = "As this struct derefs to the inner resource, a `Clone` trait implementation would interfere with the common case of cloning the inner content. (A similar case of this happening can be found with `std::cell::Ref::clone()`.)"
651    )]
652    pub fn clone(this: &Self) -> Self {
653        Self {
654            value: this.value,
655            ticks: this.ticks.clone(),
656            changed_by: this.changed_by,
657        }
658    }
659
660    /// Due to lifetime limitations of the `Deref` trait, this method can be used to obtain a
661    /// reference of the [`Resource`] with a lifetime bound to `'w` instead of the lifetime of the
662    /// struct itself.
663    pub fn into_inner(self) -> &'w T {
664        self.value
665    }
666}
667
668impl<'w, T: Resource> From<ResMut<'w, T>> for Res<'w, T> {
669    fn from(res: ResMut<'w, T>) -> Self {
670        Self {
671            value: res.value,
672            ticks: res.ticks.into(),
673            changed_by: res.changed_by.map(|changed_by| &*changed_by),
674        }
675    }
676}
677
678impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
679    /// Convert a `Res` into a `Ref`. This allows keeping the change-detection feature of `Ref`
680    /// while losing the specificity of `Res` for resources.
681    fn from(res: Res<'w, T>) -> Self {
682        Self {
683            value: res.value,
684            ticks: res.ticks,
685            changed_by: res.changed_by,
686        }
687    }
688}
689
690impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
691where
692    &'a T: IntoIterator,
693{
694    type Item = <&'a T as IntoIterator>::Item;
695    type IntoIter = <&'a T as IntoIterator>::IntoIter;
696
697    fn into_iter(self) -> Self::IntoIter {
698        self.value.into_iter()
699    }
700}
701change_detection_impl!(Res<'w, T>, T, Resource);
702impl_debug!(Res<'w, T>, Resource);
703
704/// Unique mutable borrow of a [`Resource`].
705///
706/// See the [`Resource`] documentation for usage.
707///
708/// If you need a shared borrow, use [`Res`] instead.
709///
710/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
711/// This will cause a panic, but can be configured to do nothing or warn once.
712///
713/// Use [`Option<ResMut<T>>`] instead if the resource might not always exist.
714pub struct ResMut<'w, T: ?Sized + Resource> {
715    pub(crate) value: &'w mut T,
716    pub(crate) ticks: TicksMut<'w>,
717    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
718}
719
720impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T>
721where
722    &'a T: IntoIterator,
723{
724    type Item = <&'a T as IntoIterator>::Item;
725    type IntoIter = <&'a T as IntoIterator>::IntoIter;
726
727    fn into_iter(self) -> Self::IntoIter {
728        self.value.into_iter()
729    }
730}
731
732impl<'w, 'a, T: Resource> IntoIterator for &'a mut ResMut<'w, T>
733where
734    &'a mut T: IntoIterator,
735{
736    type Item = <&'a mut T as IntoIterator>::Item;
737    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
738
739    fn into_iter(self) -> Self::IntoIter {
740        self.set_changed();
741        self.value.into_iter()
742    }
743}
744
745change_detection_impl!(ResMut<'w, T>, T, Resource);
746change_detection_mut_impl!(ResMut<'w, T>, T, Resource);
747impl_methods!(ResMut<'w, T>, T, Resource);
748impl_debug!(ResMut<'w, T>, Resource);
749
750impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
751    /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
752    /// while losing the specificity of `ResMut` for resources.
753    fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
754        Mut {
755            value: other.value,
756            ticks: other.ticks,
757            changed_by: other.changed_by,
758        }
759    }
760}
761
762/// Unique borrow of a non-[`Send`] resource.
763///
764/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
765/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
766/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
767/// over to another thread.
768///
769/// This [`SystemParam`](crate::system::SystemParam) fails validation if non-send resource doesn't exist.
770/// This will cause a panic, but can be configured to do nothing or warn once.
771///
772/// Use [`Option<NonSendMut<T>>`] instead if the resource might not always exist.
773pub struct NonSendMut<'w, T: ?Sized + 'static> {
774    pub(crate) value: &'w mut T,
775    pub(crate) ticks: TicksMut<'w>,
776    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
777}
778
779change_detection_impl!(NonSendMut<'w, T>, T,);
780change_detection_mut_impl!(NonSendMut<'w, T>, T,);
781impl_methods!(NonSendMut<'w, T>, T,);
782impl_debug!(NonSendMut<'w, T>,);
783
784impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
785    /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
786    /// while losing the specificity of `NonSendMut`.
787    fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
788        Mut {
789            value: other.value,
790            ticks: other.ticks,
791            changed_by: other.changed_by,
792        }
793    }
794}
795
796/// Shared borrow of an entity's component with access to change detection.
797/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
798///
799/// # Examples
800///
801/// These two systems produce the same output.
802///
803/// ```
804/// # use bevy_ecs::change_detection::DetectChanges;
805/// # use bevy_ecs::query::{Changed, With};
806/// # use bevy_ecs::system::Query;
807/// # use bevy_ecs::world::Ref;
808/// # use bevy_ecs_macros::Component;
809/// # #[derive(Component)]
810/// # struct MyComponent;
811///
812/// fn how_many_changed_1(query: Query<(), Changed<MyComponent>>) {
813///     println!("{} changed", query.iter().count());
814/// }
815///
816/// fn how_many_changed_2(query: Query<Ref<MyComponent>>) {
817///     println!("{} changed", query.iter().filter(|c| c.is_changed()).count());
818/// }
819/// ```
820pub struct Ref<'w, T: ?Sized> {
821    pub(crate) value: &'w T,
822    pub(crate) ticks: Ticks<'w>,
823    pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,
824}
825
826impl<'w, T: ?Sized> Ref<'w, T> {
827    /// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.
828    pub fn into_inner(self) -> &'w T {
829        self.value
830    }
831
832    /// Map `Ref` to a different type using `f`.
833    ///
834    /// This doesn't do anything else than call `f` on the wrapped value.
835    /// This is equivalent to [`Mut::map_unchanged`].
836    pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {
837        Ref {
838            value: f(self.value),
839            ticks: self.ticks,
840            changed_by: self.changed_by,
841        }
842    }
843
844    /// Create a new `Ref` using provided values.
845    ///
846    /// This is an advanced feature, `Ref`s are designed to be _created_ by
847    /// engine-internal code and _consumed_ by end-user code.
848    ///
849    /// - `value` - The value wrapped by `Ref`.
850    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
851    /// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
852    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
853    ///   as a reference to determine whether the wrapped value is newly added or changed.
854    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
855    pub fn new(
856        value: &'w T,
857        added: &'w Tick,
858        changed: &'w Tick,
859        last_run: Tick,
860        this_run: Tick,
861        caller: MaybeLocation<&'w &'static Location<'static>>,
862    ) -> Ref<'w, T> {
863        Ref {
864            value,
865            ticks: Ticks {
866                added,
867                changed,
868                last_run,
869                this_run,
870            },
871            changed_by: caller,
872        }
873    }
874
875    /// Overwrite the `last_run` and `this_run` tick that are used for change detection.
876    ///
877    /// This is an advanced feature. `Ref`s are usually _created_ by engine-internal code and
878    /// _consumed_ by end-user code.
879    pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
880        self.ticks.last_run = last_run;
881        self.ticks.this_run = this_run;
882    }
883}
884
885impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
886where
887    &'a T: IntoIterator,
888{
889    type Item = <&'a T as IntoIterator>::Item;
890    type IntoIter = <&'a T as IntoIterator>::IntoIter;
891
892    fn into_iter(self) -> Self::IntoIter {
893        self.value.into_iter()
894    }
895}
896change_detection_impl!(Ref<'w, T>, T,);
897impl_debug!(Ref<'w, T>,);
898
899/// Unique mutable borrow of an entity's component or of a resource.
900///
901/// This can be used in queries to opt into change detection on both their mutable and immutable forms, as opposed to
902/// `&mut T`, which only provides access to change detection while in its mutable form:
903///
904/// ```rust
905/// # use bevy_ecs::prelude::*;
906/// # use bevy_ecs::query::QueryData;
907/// #
908/// #[derive(Component, Clone)]
909/// struct Name(String);
910///
911/// #[derive(Component, Clone, Copy)]
912/// struct Health(f32);
913///
914/// #[derive(Component, Clone, Copy)]
915/// struct Position {
916///     x: f32,
917///     y: f32,
918/// };
919///
920/// #[derive(Component, Clone, Copy)]
921/// struct Player {
922///     id: usize,
923/// };
924///
925/// #[derive(QueryData)]
926/// #[query_data(mutable)]
927/// struct PlayerQuery {
928///     id: &'static Player,
929///
930///     // Reacting to `PlayerName` changes is expensive, so we need to enable change detection when reading it.
931///     name: Mut<'static, Name>,
932///
933///     health: &'static mut Health,
934///     position: &'static mut Position,
935/// }
936///
937/// fn update_player_avatars(players_query: Query<PlayerQuery>) {
938///     // The item returned by the iterator is of type `PlayerQueryReadOnlyItem`.
939///     for player in players_query.iter() {
940///         if player.name.is_changed() {
941///             // Update the player's name. This clones a String, and so is more expensive.
942///             update_player_name(player.id, player.name.clone());
943///         }
944///
945///         // Update the health bar.
946///         update_player_health(player.id, *player.health);
947///
948///         // Update the player's position.
949///         update_player_position(player.id, *player.position);
950///     }
951/// }
952///
953/// # bevy_ecs::system::assert_is_system(update_player_avatars);
954///
955/// # fn update_player_name(player: &Player, new_name: Name) {}
956/// # fn update_player_health(player: &Player, new_health: Health) {}
957/// # fn update_player_position(player: &Player, new_position: Position) {}
958/// ```
959pub struct Mut<'w, T: ?Sized> {
960    pub(crate) value: &'w mut T,
961    pub(crate) ticks: TicksMut<'w>,
962    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
963}
964
965impl<'w, T: ?Sized> Mut<'w, T> {
966    /// Creates a new change-detection enabled smart pointer.
967    /// In almost all cases you do not need to call this method manually,
968    /// as instances of `Mut` will be created by engine-internal code.
969    ///
970    /// Many use-cases of this method would be better served by [`Mut::map_unchanged`]
971    /// or [`Mut::reborrow`].
972    ///
973    /// - `value` - The value wrapped by this smart pointer.
974    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
975    /// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.
976    ///   This will be updated to the value of `change_tick` if the returned smart pointer
977    ///   is modified.
978    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
979    ///   as a reference to determine whether the wrapped value is newly added or changed.
980    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
981    pub fn new(
982        value: &'w mut T,
983        added: &'w mut Tick,
984        last_changed: &'w mut Tick,
985        last_run: Tick,
986        this_run: Tick,
987        caller: MaybeLocation<&'w mut &'static Location<'static>>,
988    ) -> Self {
989        Self {
990            value,
991            ticks: TicksMut {
992                added,
993                changed: last_changed,
994                last_run,
995                this_run,
996            },
997            changed_by: caller,
998        }
999    }
1000
1001    /// Overwrite the `last_run` and `this_run` tick that are used for change detection.
1002    ///
1003    /// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and
1004    /// _consumed_ by end-user code.
1005    pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
1006        self.ticks.last_run = last_run;
1007        self.ticks.this_run = this_run;
1008    }
1009}
1010
1011impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
1012    fn from(mut_ref: Mut<'w, T>) -> Self {
1013        Self {
1014            value: mut_ref.value,
1015            ticks: mut_ref.ticks.into(),
1016            changed_by: mut_ref.changed_by.map(|changed_by| &*changed_by),
1017        }
1018    }
1019}
1020
1021impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
1022where
1023    &'a T: IntoIterator,
1024{
1025    type Item = <&'a T as IntoIterator>::Item;
1026    type IntoIter = <&'a T as IntoIterator>::IntoIter;
1027
1028    fn into_iter(self) -> Self::IntoIter {
1029        self.value.into_iter()
1030    }
1031}
1032
1033impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
1034where
1035    &'a mut T: IntoIterator,
1036{
1037    type Item = <&'a mut T as IntoIterator>::Item;
1038    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1039
1040    fn into_iter(self) -> Self::IntoIter {
1041        self.set_changed();
1042        self.value.into_iter()
1043    }
1044}
1045
1046change_detection_impl!(Mut<'w, T>, T,);
1047change_detection_mut_impl!(Mut<'w, T>, T,);
1048impl_methods!(Mut<'w, T>, T,);
1049impl_debug!(Mut<'w, T>,);
1050
1051/// Unique mutable borrow of resources or an entity's component.
1052///
1053/// Similar to [`Mut`], but not generic over the component type, instead
1054/// exposing the raw pointer as a `*mut ()`.
1055///
1056/// Usually you don't need to use this and can instead use the APIs returning a
1057/// [`Mut`], but in situations where the types are not known at compile time
1058/// or are defined outside of rust this can be used.
1059pub struct MutUntyped<'w> {
1060    pub(crate) value: PtrMut<'w>,
1061    pub(crate) ticks: TicksMut<'w>,
1062    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
1063}
1064
1065impl<'w> MutUntyped<'w> {
1066    /// Returns the pointer to the value, marking it as changed.
1067    ///
1068    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1069    #[inline]
1070    pub fn into_inner(mut self) -> PtrMut<'w> {
1071        self.set_changed();
1072        self.value
1073    }
1074
1075    /// Returns a [`MutUntyped`] with a smaller lifetime.
1076    /// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.
1077    #[inline]
1078    pub fn reborrow(&mut self) -> MutUntyped {
1079        MutUntyped {
1080            value: self.value.reborrow(),
1081            ticks: TicksMut {
1082                added: self.ticks.added,
1083                changed: self.ticks.changed,
1084                last_run: self.ticks.last_run,
1085                this_run: self.ticks.this_run,
1086            },
1087            changed_by: self.changed_by.as_deref_mut(),
1088        }
1089    }
1090
1091    /// Returns `true` if this value was changed or mutably dereferenced
1092    /// either since a specific change tick.
1093    pub fn has_changed_since(&self, tick: Tick) -> bool {
1094        self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
1095    }
1096
1097    /// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
1098    ///
1099    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1100    #[inline]
1101    pub fn as_mut(&mut self) -> PtrMut<'_> {
1102        self.set_changed();
1103        self.value.reborrow()
1104    }
1105
1106    /// Returns an immutable pointer to the value without taking ownership.
1107    #[inline]
1108    pub fn as_ref(&self) -> Ptr<'_> {
1109        self.value.as_ref()
1110    }
1111
1112    /// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,
1113    /// without flagging a change.
1114    /// This function is the untyped equivalent of [`Mut::map_unchanged`].
1115    ///
1116    /// You should never modify the argument passed to the closure – if you want to modify the data without flagging a change, consider using [`bypass_change_detection`](DetectChangesMut::bypass_change_detection) to make your intent explicit.
1117    ///
1118    /// If you know the type of the value you can do
1119    /// ```no_run
1120    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1121    /// # let mut_untyped: MutUntyped = unimplemented!();
1122    /// // SAFETY: ptr is of type `u8`
1123    /// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
1124    /// ```
1125    /// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],
1126    /// you can do
1127    /// ```no_run
1128    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1129    /// # let mut_untyped: MutUntyped = unimplemented!();
1130    /// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();
1131    /// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
1132    /// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
1133    /// ```
1134    pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
1135        Mut {
1136            value: f(self.value),
1137            ticks: self.ticks,
1138            changed_by: self.changed_by,
1139        }
1140    }
1141
1142    /// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.
1143    ///
1144    /// # Safety
1145    /// - `T` must be the erased pointee type for this [`MutUntyped`].
1146    pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
1147        Mut {
1148            // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
1149            value: unsafe { self.value.deref_mut() },
1150            ticks: self.ticks,
1151            // SAFETY: `caller` is `Aligned`.
1152            changed_by: self.changed_by,
1153        }
1154    }
1155}
1156
1157impl<'w> DetectChanges for MutUntyped<'w> {
1158    #[inline]
1159    fn is_added(&self) -> bool {
1160        self.ticks
1161            .added
1162            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1163    }
1164
1165    #[inline]
1166    fn is_changed(&self) -> bool {
1167        self.ticks
1168            .changed
1169            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1170    }
1171
1172    #[inline]
1173    fn last_changed(&self) -> Tick {
1174        *self.ticks.changed
1175    }
1176
1177    #[inline]
1178    fn changed_by(&self) -> MaybeLocation {
1179        self.changed_by.copied()
1180    }
1181
1182    #[inline]
1183    fn added(&self) -> Tick {
1184        *self.ticks.added
1185    }
1186}
1187
1188impl<'w> DetectChangesMut for MutUntyped<'w> {
1189    type Inner = PtrMut<'w>;
1190
1191    #[inline]
1192    #[track_caller]
1193    fn set_changed(&mut self) {
1194        *self.ticks.changed = self.ticks.this_run;
1195        self.changed_by.assign(MaybeLocation::caller());
1196    }
1197
1198    #[inline]
1199    #[track_caller]
1200    fn set_added(&mut self) {
1201        *self.ticks.changed = self.ticks.this_run;
1202        *self.ticks.added = self.ticks.this_run;
1203        self.changed_by.assign(MaybeLocation::caller());
1204    }
1205
1206    #[inline]
1207    #[track_caller]
1208    fn set_last_changed(&mut self, last_changed: Tick) {
1209        *self.ticks.changed = last_changed;
1210        self.changed_by.assign(MaybeLocation::caller());
1211    }
1212
1213    #[inline]
1214    #[track_caller]
1215    fn set_last_added(&mut self, last_added: Tick) {
1216        *self.ticks.added = last_added;
1217        *self.ticks.changed = last_added;
1218        self.changed_by.assign(MaybeLocation::caller());
1219    }
1220
1221    #[inline]
1222    #[track_caller]
1223    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
1224        &mut self.value
1225    }
1226}
1227
1228impl core::fmt::Debug for MutUntyped<'_> {
1229    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1230        f.debug_tuple("MutUntyped")
1231            .field(&self.value.as_ptr())
1232            .finish()
1233    }
1234}
1235
1236impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
1237    fn from(value: Mut<'w, T>) -> Self {
1238        MutUntyped {
1239            value: value.value.into(),
1240            ticks: value.ticks,
1241            changed_by: value.changed_by,
1242        }
1243    }
1244}
1245
1246/// A value that contains a `T` if the `track_location` feature is enabled,
1247/// and is a ZST if it is not.
1248///
1249/// The overall API is similar to [`Option`], but whether the value is `Some` or `None` is set at compile
1250/// time and is the same for all values.
1251///
1252/// If the `track_location` feature is disabled, then all functions on this type that return
1253/// an `MaybeLocation` will have an empty body and should be removed by the optimizer.
1254///
1255/// This allows code to be written that will be checked by the compiler even when the feature is disabled,
1256/// but that will be entirely removed during compilation.
1257#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
1258#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1259pub struct MaybeLocation<T: ?Sized = &'static Location<'static>> {
1260    #[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
1261    marker: PhantomData<T>,
1262    #[cfg(feature = "track_location")]
1263    value: T,
1264}
1265
1266impl<T: core::fmt::Display> core::fmt::Display for MaybeLocation<T> {
1267    fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1268        #[cfg(feature = "track_location")]
1269        {
1270            self.value.fmt(_f)?;
1271        }
1272        Ok(())
1273    }
1274}
1275
1276impl<T> MaybeLocation<T> {
1277    /// Constructs a new `MaybeLocation` that wraps the given value.
1278    ///
1279    /// This may only accept `Copy` types,
1280    /// since it needs to drop the value if the `track_location` feature is disabled,
1281    /// and non-`Copy` types cannot be dropped in `const` context.
1282    /// Use [`new_with`][Self::new_with] if you need to construct a non-`Copy` value.
1283    ///
1284    /// # See also
1285    /// - [`new_with`][Self::new_with] to initialize using a closure.
1286    /// - [`new_with_flattened`][Self::new_with_flattened] to initialize using a closure that returns an `Option<MaybeLocation<T>>`.
1287    #[inline]
1288    pub const fn new(_value: T) -> Self
1289    where
1290        T: Copy,
1291    {
1292        Self {
1293            #[cfg(feature = "track_location")]
1294            value: _value,
1295            marker: PhantomData,
1296        }
1297    }
1298
1299    /// Constructs a new `MaybeLocation` that wraps the result of the given closure.
1300    ///
1301    /// # See also
1302    /// - [`new`][Self::new] to initialize using a value.
1303    /// - [`new_with_flattened`][Self::new_with_flattened] to initialize using a closure that returns an `Option<MaybeLocation<T>>`.
1304    #[inline]
1305    pub fn new_with(_f: impl FnOnce() -> T) -> Self {
1306        Self {
1307            #[cfg(feature = "track_location")]
1308            value: _f(),
1309            marker: PhantomData,
1310        }
1311    }
1312
1313    /// Maps an `MaybeLocation<T> `to `MaybeLocation<U>` by applying a function to a contained value.
1314    #[inline]
1315    pub fn map<U>(self, _f: impl FnOnce(T) -> U) -> MaybeLocation<U> {
1316        MaybeLocation {
1317            #[cfg(feature = "track_location")]
1318            value: _f(self.value),
1319            marker: PhantomData,
1320        }
1321    }
1322
1323    /// Converts a pair of `MaybeLocation` values to an `MaybeLocation` of a tuple.
1324    #[inline]
1325    pub fn zip<U>(self, _other: MaybeLocation<U>) -> MaybeLocation<(T, U)> {
1326        MaybeLocation {
1327            #[cfg(feature = "track_location")]
1328            value: (self.value, _other.value),
1329            marker: PhantomData,
1330        }
1331    }
1332
1333    /// Returns the contained value or a default.
1334    /// If the `track_location` feature is enabled, this always returns the contained value.
1335    /// If it is disabled, this always returns `T::Default()`.
1336    #[inline]
1337    pub fn unwrap_or_default(self) -> T
1338    where
1339        T: Default,
1340    {
1341        self.into_option().unwrap_or_default()
1342    }
1343
1344    /// Converts an `MaybeLocation` to an [`Option`] to allow run-time branching.
1345    /// If the `track_location` feature is enabled, this always returns `Some`.
1346    /// If it is disabled, this always returns `None`.
1347    #[inline]
1348    pub fn into_option(self) -> Option<T> {
1349        #[cfg(feature = "track_location")]
1350        {
1351            Some(self.value)
1352        }
1353        #[cfg(not(feature = "track_location"))]
1354        {
1355            None
1356        }
1357    }
1358}
1359
1360impl<T> MaybeLocation<Option<T>> {
1361    /// Constructs a new `MaybeLocation` that wraps the result of the given closure.
1362    /// If the closure returns `Some`, it unwraps the inner value.
1363    ///
1364    /// # See also
1365    /// - [`new`][Self::new] to initialize using a value.
1366    /// - [`new_with`][Self::new_with] to initialize using a closure.
1367    #[inline]
1368    pub fn new_with_flattened(_f: impl FnOnce() -> Option<MaybeLocation<T>>) -> Self {
1369        Self {
1370            #[cfg(feature = "track_location")]
1371            value: _f().map(|value| value.value),
1372            marker: PhantomData,
1373        }
1374    }
1375
1376    /// Transposes a `MaybeLocation` of an [`Option`] into an [`Option`] of a `MaybeLocation`.
1377    ///
1378    /// This can be useful if you want to use the `?` operator to exit early
1379    /// if the `track_location` feature is enabled but the value is not found.
1380    ///
1381    /// If the `track_location` feature is enabled,
1382    /// this returns `Some` if the inner value is `Some`
1383    /// and `None` if the inner value is `None`.
1384    ///
1385    /// If it is disabled, this always returns `Some`.
1386    ///
1387    /// # Example
1388    ///
1389    /// ```
1390    /// # use bevy_ecs::{change_detection::MaybeLocation, world::World};
1391    /// # use core::panic::Location;
1392    /// #
1393    /// # fn test() -> Option<()> {
1394    /// let mut world = World::new();
1395    /// let entity = world.spawn(()).id();
1396    /// let location: MaybeLocation<Option<&'static Location<'static>>> =
1397    ///     world.entities().entity_get_spawned_or_despawned_by(entity);
1398    /// let location: MaybeLocation<&'static Location<'static>> = location.transpose()?;
1399    /// # Some(())
1400    /// # }
1401    /// # test();
1402    /// ```
1403    ///
1404    /// # See also
1405    ///
1406    /// - [`into_option`][Self::into_option] to convert to an `Option<Option<T>>`.
1407    ///   When used with [`Option::flatten`], this will have a similar effect,
1408    ///   but will return `None` when the `track_location` feature is disabled.
1409    #[inline]
1410    pub fn transpose(self) -> Option<MaybeLocation<T>> {
1411        #[cfg(feature = "track_location")]
1412        {
1413            self.value.map(|value| MaybeLocation {
1414                value,
1415                marker: PhantomData,
1416            })
1417        }
1418        #[cfg(not(feature = "track_location"))]
1419        {
1420            Some(MaybeLocation {
1421                marker: PhantomData,
1422            })
1423        }
1424    }
1425}
1426
1427impl<T> MaybeLocation<&T> {
1428    /// Maps an `MaybeLocation<&T>` to an `MaybeLocation<T>` by copying the contents.
1429    #[inline]
1430    pub const fn copied(&self) -> MaybeLocation<T>
1431    where
1432        T: Copy,
1433    {
1434        MaybeLocation {
1435            #[cfg(feature = "track_location")]
1436            value: *self.value,
1437            marker: PhantomData,
1438        }
1439    }
1440}
1441
1442impl<T> MaybeLocation<&mut T> {
1443    /// Maps an `MaybeLocation<&mut T>` to an `MaybeLocation<T>` by copying the contents.
1444    #[inline]
1445    pub const fn copied(&self) -> MaybeLocation<T>
1446    where
1447        T: Copy,
1448    {
1449        MaybeLocation {
1450            #[cfg(feature = "track_location")]
1451            value: *self.value,
1452            marker: PhantomData,
1453        }
1454    }
1455
1456    /// Assigns the contents of an `MaybeLocation<T>` to an `MaybeLocation<&mut T>`.
1457    #[inline]
1458    pub fn assign(&mut self, _value: MaybeLocation<T>) {
1459        #[cfg(feature = "track_location")]
1460        {
1461            *self.value = _value.value;
1462        }
1463    }
1464}
1465
1466impl<T: ?Sized> MaybeLocation<T> {
1467    /// Converts from `&MaybeLocation<T>` to `MaybeLocation<&T>`.
1468    #[inline]
1469    pub const fn as_ref(&self) -> MaybeLocation<&T> {
1470        MaybeLocation {
1471            #[cfg(feature = "track_location")]
1472            value: &self.value,
1473            marker: PhantomData,
1474        }
1475    }
1476
1477    /// Converts from `&mut MaybeLocation<T>` to `MaybeLocation<&mut T>`.
1478    #[inline]
1479    pub const fn as_mut(&mut self) -> MaybeLocation<&mut T> {
1480        MaybeLocation {
1481            #[cfg(feature = "track_location")]
1482            value: &mut self.value,
1483            marker: PhantomData,
1484        }
1485    }
1486
1487    /// Converts from `&MaybeLocation<T>` to `MaybeLocation<&T::Target>`.
1488    #[inline]
1489    pub fn as_deref(&self) -> MaybeLocation<&T::Target>
1490    where
1491        T: Deref,
1492    {
1493        MaybeLocation {
1494            #[cfg(feature = "track_location")]
1495            value: &*self.value,
1496            marker: PhantomData,
1497        }
1498    }
1499
1500    /// Converts from `&mut MaybeLocation<T>` to `MaybeLocation<&mut T::Target>`.
1501    #[inline]
1502    pub fn as_deref_mut(&mut self) -> MaybeLocation<&mut T::Target>
1503    where
1504        T: DerefMut,
1505    {
1506        MaybeLocation {
1507            #[cfg(feature = "track_location")]
1508            value: &mut *self.value,
1509            marker: PhantomData,
1510        }
1511    }
1512}
1513
1514impl MaybeLocation {
1515    /// Returns the source location of the caller of this function. If that function's caller is
1516    /// annotated then its call location will be returned, and so on up the stack to the first call
1517    /// within a non-tracked function body.
1518    #[inline]
1519    #[track_caller]
1520    pub fn caller() -> Self {
1521        // Note that this cannot use `new_with`, since `FnOnce` invocations cannot be annotated with `#[track_caller]`.
1522        MaybeLocation {
1523            #[cfg(feature = "track_location")]
1524            value: Location::caller(),
1525            marker: PhantomData,
1526        }
1527    }
1528}
1529
1530#[cfg(test)]
1531mod tests {
1532    use bevy_ecs_macros::Resource;
1533    use bevy_ptr::PtrMut;
1534    use bevy_reflect::{FromType, ReflectFromPtr};
1535    use core::ops::{Deref, DerefMut};
1536
1537    use crate::{
1538        change_detection::{
1539            MaybeLocation, Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD,
1540            MAX_CHANGE_AGE,
1541        },
1542        component::{Component, ComponentTicks, Tick},
1543        system::{IntoSystem, Single, System},
1544        world::World,
1545    };
1546
1547    use super::{DetectChanges, DetectChangesMut, MutUntyped};
1548
1549    #[derive(Component, PartialEq)]
1550    struct C;
1551
1552    #[derive(Resource)]
1553    struct R;
1554
1555    #[derive(Resource, PartialEq)]
1556    struct R2(u8);
1557
1558    impl Deref for R2 {
1559        type Target = u8;
1560        fn deref(&self) -> &u8 {
1561            &self.0
1562        }
1563    }
1564
1565    impl DerefMut for R2 {
1566        fn deref_mut(&mut self) -> &mut u8 {
1567            &mut self.0
1568        }
1569    }
1570
1571    #[test]
1572    fn change_expiration() {
1573        fn change_detected(query: Option<Single<Ref<C>>>) -> bool {
1574            query.unwrap().is_changed()
1575        }
1576
1577        fn change_expired(query: Option<Single<Ref<C>>>) -> bool {
1578            query.unwrap().is_changed()
1579        }
1580
1581        let mut world = World::new();
1582
1583        // component added: 1, changed: 1
1584        world.spawn(C);
1585
1586        let mut change_detected_system = IntoSystem::into_system(change_detected);
1587        let mut change_expired_system = IntoSystem::into_system(change_expired);
1588        change_detected_system.initialize(&mut world);
1589        change_expired_system.initialize(&mut world);
1590
1591        // world: 1, system last ran: 0, component changed: 1
1592        // The spawn will be detected since it happened after the system "last ran".
1593        assert!(change_detected_system.run((), &mut world));
1594
1595        // world: 1 + MAX_CHANGE_AGE
1596        let change_tick = world.change_tick.get_mut();
1597        *change_tick = change_tick.wrapping_add(MAX_CHANGE_AGE);
1598
1599        // Both the system and component appeared `MAX_CHANGE_AGE` ticks ago.
1600        // Since we clamp things to `MAX_CHANGE_AGE` for determinism,
1601        // `ComponentTicks::is_changed` will now see `MAX_CHANGE_AGE > MAX_CHANGE_AGE`
1602        // and return `false`.
1603        assert!(!change_expired_system.run((), &mut world));
1604    }
1605
1606    #[test]
1607    fn change_tick_wraparound() {
1608        let mut world = World::new();
1609        world.last_change_tick = Tick::new(u32::MAX);
1610        *world.change_tick.get_mut() = 0;
1611
1612        // component added: 0, changed: 0
1613        world.spawn(C);
1614
1615        world.increment_change_tick();
1616
1617        // Since the world is always ahead, as long as changes can't get older than `u32::MAX` (which we ensure),
1618        // the wrapping difference will always be positive, so wraparound doesn't matter.
1619        let mut query = world.query::<Ref<C>>();
1620        assert!(query.single(&world).unwrap().is_changed());
1621    }
1622
1623    #[test]
1624    fn change_tick_scan() {
1625        let mut world = World::new();
1626
1627        // component added: 1, changed: 1
1628        world.spawn(C);
1629
1630        // a bunch of stuff happens, the component is now older than `MAX_CHANGE_AGE`
1631        *world.change_tick.get_mut() += MAX_CHANGE_AGE + CHECK_TICK_THRESHOLD;
1632        let change_tick = world.change_tick();
1633
1634        let mut query = world.query::<Ref<C>>();
1635        for tracker in query.iter(&world) {
1636            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1637            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1638            assert!(ticks_since_insert > MAX_CHANGE_AGE);
1639            assert!(ticks_since_change > MAX_CHANGE_AGE);
1640        }
1641
1642        // scan change ticks and clamp those at risk of overflow
1643        world.check_change_ticks();
1644
1645        for tracker in query.iter(&world) {
1646            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1647            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1648            assert_eq!(ticks_since_insert, MAX_CHANGE_AGE);
1649            assert_eq!(ticks_since_change, MAX_CHANGE_AGE);
1650        }
1651    }
1652
1653    #[test]
1654    fn mut_from_res_mut() {
1655        let mut component_ticks = ComponentTicks {
1656            added: Tick::new(1),
1657            changed: Tick::new(2),
1658        };
1659        let ticks = TicksMut {
1660            added: &mut component_ticks.added,
1661            changed: &mut component_ticks.changed,
1662            last_run: Tick::new(3),
1663            this_run: Tick::new(4),
1664        };
1665        let mut res = R {};
1666        let mut caller = MaybeLocation::caller();
1667
1668        let res_mut = ResMut {
1669            value: &mut res,
1670            ticks,
1671            changed_by: caller.as_mut(),
1672        };
1673
1674        let into_mut: Mut<R> = res_mut.into();
1675        assert_eq!(1, into_mut.ticks.added.get());
1676        assert_eq!(2, into_mut.ticks.changed.get());
1677        assert_eq!(3, into_mut.ticks.last_run.get());
1678        assert_eq!(4, into_mut.ticks.this_run.get());
1679    }
1680
1681    #[test]
1682    fn mut_new() {
1683        let mut component_ticks = ComponentTicks {
1684            added: Tick::new(1),
1685            changed: Tick::new(3),
1686        };
1687        let mut res = R {};
1688        let mut caller = MaybeLocation::caller();
1689
1690        let val = Mut::new(
1691            &mut res,
1692            &mut component_ticks.added,
1693            &mut component_ticks.changed,
1694            Tick::new(2), // last_run
1695            Tick::new(4), // this_run
1696            caller.as_mut(),
1697        );
1698
1699        assert!(!val.is_added());
1700        assert!(val.is_changed());
1701    }
1702
1703    #[test]
1704    fn mut_from_non_send_mut() {
1705        let mut component_ticks = ComponentTicks {
1706            added: Tick::new(1),
1707            changed: Tick::new(2),
1708        };
1709        let ticks = TicksMut {
1710            added: &mut component_ticks.added,
1711            changed: &mut component_ticks.changed,
1712            last_run: Tick::new(3),
1713            this_run: Tick::new(4),
1714        };
1715        let mut res = R {};
1716        let mut caller = MaybeLocation::caller();
1717
1718        let non_send_mut = NonSendMut {
1719            value: &mut res,
1720            ticks,
1721            changed_by: caller.as_mut(),
1722        };
1723
1724        let into_mut: Mut<R> = non_send_mut.into();
1725        assert_eq!(1, into_mut.ticks.added.get());
1726        assert_eq!(2, into_mut.ticks.changed.get());
1727        assert_eq!(3, into_mut.ticks.last_run.get());
1728        assert_eq!(4, into_mut.ticks.this_run.get());
1729    }
1730
1731    #[test]
1732    fn map_mut() {
1733        use super::*;
1734        struct Outer(i64);
1735
1736        let last_run = Tick::new(2);
1737        let this_run = Tick::new(3);
1738        let mut component_ticks = ComponentTicks {
1739            added: Tick::new(1),
1740            changed: Tick::new(2),
1741        };
1742        let ticks = TicksMut {
1743            added: &mut component_ticks.added,
1744            changed: &mut component_ticks.changed,
1745            last_run,
1746            this_run,
1747        };
1748
1749        let mut outer = Outer(0);
1750        let mut caller = MaybeLocation::caller();
1751
1752        let ptr = Mut {
1753            value: &mut outer,
1754            ticks,
1755            changed_by: caller.as_mut(),
1756        };
1757        assert!(!ptr.is_changed());
1758
1759        // Perform a mapping operation.
1760        let mut inner = ptr.map_unchanged(|x| &mut x.0);
1761        assert!(!inner.is_changed());
1762
1763        // Mutate the inner value.
1764        *inner = 64;
1765        assert!(inner.is_changed());
1766        // Modifying one field of a component should flag a change for the entire component.
1767        assert!(component_ticks.is_changed(last_run, this_run));
1768    }
1769
1770    #[test]
1771    fn set_if_neq() {
1772        let mut world = World::new();
1773
1774        world.insert_resource(R2(0));
1775        // Resources are Changed when first added
1776        world.increment_change_tick();
1777        // This is required to update world::last_change_tick
1778        world.clear_trackers();
1779
1780        let mut r = world.resource_mut::<R2>();
1781        assert!(!r.is_changed(), "Resource must begin unchanged.");
1782
1783        r.set_if_neq(R2(0));
1784        assert!(
1785            !r.is_changed(),
1786            "Resource must not be changed after setting to the same value."
1787        );
1788
1789        r.set_if_neq(R2(3));
1790        assert!(
1791            r.is_changed(),
1792            "Resource must be changed after setting to a different value."
1793        );
1794    }
1795
1796    #[test]
1797    fn as_deref_mut() {
1798        let mut world = World::new();
1799
1800        world.insert_resource(R2(0));
1801        // Resources are Changed when first added
1802        world.increment_change_tick();
1803        // This is required to update world::last_change_tick
1804        world.clear_trackers();
1805
1806        let mut r = world.resource_mut::<R2>();
1807        assert!(!r.is_changed(), "Resource must begin unchanged.");
1808
1809        let mut r = r.as_deref_mut();
1810        assert!(
1811            !r.is_changed(),
1812            "Dereferencing should not mark the item as changed yet"
1813        );
1814
1815        r.set_if_neq(3);
1816        assert!(
1817            r.is_changed(),
1818            "Resource must be changed after setting to a different value."
1819        );
1820    }
1821
1822    #[test]
1823    fn mut_untyped_to_reflect() {
1824        let last_run = Tick::new(2);
1825        let this_run = Tick::new(3);
1826        let mut component_ticks = ComponentTicks {
1827            added: Tick::new(1),
1828            changed: Tick::new(2),
1829        };
1830        let ticks = TicksMut {
1831            added: &mut component_ticks.added,
1832            changed: &mut component_ticks.changed,
1833            last_run,
1834            this_run,
1835        };
1836
1837        let mut value: i32 = 5;
1838        let mut caller = MaybeLocation::caller();
1839
1840        let value = MutUntyped {
1841            value: PtrMut::from(&mut value),
1842            ticks,
1843            changed_by: caller.as_mut(),
1844        };
1845
1846        let reflect_from_ptr = <ReflectFromPtr as FromType<i32>>::from_type();
1847
1848        let mut new = value.map_unchanged(|ptr| {
1849            // SAFETY: The underlying type of `ptr` matches `reflect_from_ptr`.
1850            let value = unsafe { reflect_from_ptr.as_reflect_mut(ptr) };
1851            value
1852        });
1853
1854        assert!(!new.is_changed());
1855
1856        new.reflect_mut();
1857
1858        assert!(new.is_changed());
1859    }
1860
1861    #[test]
1862    fn mut_untyped_from_mut() {
1863        let mut component_ticks = ComponentTicks {
1864            added: Tick::new(1),
1865            changed: Tick::new(2),
1866        };
1867        let ticks = TicksMut {
1868            added: &mut component_ticks.added,
1869            changed: &mut component_ticks.changed,
1870            last_run: Tick::new(3),
1871            this_run: Tick::new(4),
1872        };
1873        let mut c = C {};
1874        let mut caller = MaybeLocation::caller();
1875
1876        let mut_typed = Mut {
1877            value: &mut c,
1878            ticks,
1879            changed_by: caller.as_mut(),
1880        };
1881
1882        let into_mut: MutUntyped = mut_typed.into();
1883        assert_eq!(1, into_mut.ticks.added.get());
1884        assert_eq!(2, into_mut.ticks.changed.get());
1885        assert_eq!(3, into_mut.ticks.last_run.get());
1886        assert_eq!(4, into_mut.ticks.this_run.get());
1887    }
1888}