Thanks to visit codestin.com
Credit goes to docs.rs

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).unwrap());
192    /// # // second time `reset_score` runs, the score is not changed.
193    /// # schedule.run(&mut world);
194    /// # assert!(!score_changed.run((), &mut world).unwrap());
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(Message, 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: MessageWriter<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).unwrap());
267    /// # assert!(score_changed_event.run((), &mut world).unwrap());
268    /// # // second time `reset_score` runs, the score is not changed.
269    /// # schedule.run(&mut world);
270    /// # assert!(!score_changed.run((), &mut world).unwrap());
271    /// # assert!(!score_changed_event.run((), &mut world).unwrap());
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).unwrap());
319    /// # // second time `reset_score` runs, the score is not changed.
320    /// # schedule.run(&mut world);
321    /// # assert!(!message_changed.run((), &mut world).unwrap());
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 access change detection from immutable query methods, as opposed
902/// to `&mut T` which only provides access to change detection from mutable query methods.
903///
904/// ```rust
905/// # use bevy_ecs::prelude::*;
906/// # use bevy_ecs::query::QueryData;
907/// #
908/// #[derive(Component, Clone, Debug)]
909/// struct Name(String);
910///
911/// #[derive(Component, Clone, Copy, Debug)]
912/// struct Health(f32);
913///
914/// fn my_system(mut query: Query<(Mut<Name>, &mut Health)>) {
915///     // Mutable access provides change detection information for both parameters:
916///     // - `name` has type `Mut<Name>`
917///     // - `health` has type `Mut<Health>`
918///     for (name, health) in query.iter_mut() {
919///         println!("Name: {:?} (last changed {:?})", name, name.last_changed());
920///         println!("Health: {:?} (last changed: {:?})", health, health.last_changed());
921/// #        println!("{}{}", name.0, health.0); // Silence dead_code warning
922///     }
923///
924///     // Immutable access only provides change detection for `Name`:
925///     // - `name` has type `Ref<Name>`
926///     // - `health` has type `&Health`
927///     for (name, health) in query.iter() {
928///         println!("Name: {:?} (last changed {:?})", name, name.last_changed());
929///         println!("Health: {:?}", health);
930///     }
931/// }
932///
933/// # bevy_ecs::system::assert_is_system(my_system);
934/// ```
935pub struct Mut<'w, T: ?Sized> {
936    pub(crate) value: &'w mut T,
937    pub(crate) ticks: TicksMut<'w>,
938    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
939}
940
941impl<'w, T: ?Sized> Mut<'w, T> {
942    /// Creates a new change-detection enabled smart pointer.
943    /// In almost all cases you do not need to call this method manually,
944    /// as instances of `Mut` will be created by engine-internal code.
945    ///
946    /// Many use-cases of this method would be better served by [`Mut::map_unchanged`]
947    /// or [`Mut::reborrow`].
948    ///
949    /// - `value` - The value wrapped by this smart pointer.
950    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
951    /// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.
952    ///   This will be updated to the value of `change_tick` if the returned smart pointer
953    ///   is modified.
954    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
955    ///   as a reference to determine whether the wrapped value is newly added or changed.
956    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
957    pub fn new(
958        value: &'w mut T,
959        added: &'w mut Tick,
960        last_changed: &'w mut Tick,
961        last_run: Tick,
962        this_run: Tick,
963        caller: MaybeLocation<&'w mut &'static Location<'static>>,
964    ) -> Self {
965        Self {
966            value,
967            ticks: TicksMut {
968                added,
969                changed: last_changed,
970                last_run,
971                this_run,
972            },
973            changed_by: caller,
974        }
975    }
976
977    /// Overwrite the `last_run` and `this_run` tick that are used for change detection.
978    ///
979    /// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and
980    /// _consumed_ by end-user code.
981    pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
982        self.ticks.last_run = last_run;
983        self.ticks.this_run = this_run;
984    }
985}
986
987impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
988    fn from(mut_ref: Mut<'w, T>) -> Self {
989        Self {
990            value: mut_ref.value,
991            ticks: mut_ref.ticks.into(),
992            changed_by: mut_ref.changed_by.map(|changed_by| &*changed_by),
993        }
994    }
995}
996
997impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
998where
999    &'a T: IntoIterator,
1000{
1001    type Item = <&'a T as IntoIterator>::Item;
1002    type IntoIter = <&'a T as IntoIterator>::IntoIter;
1003
1004    fn into_iter(self) -> Self::IntoIter {
1005        self.value.into_iter()
1006    }
1007}
1008
1009impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
1010where
1011    &'a mut T: IntoIterator,
1012{
1013    type Item = <&'a mut T as IntoIterator>::Item;
1014    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1015
1016    fn into_iter(self) -> Self::IntoIter {
1017        self.set_changed();
1018        self.value.into_iter()
1019    }
1020}
1021
1022change_detection_impl!(Mut<'w, T>, T,);
1023change_detection_mut_impl!(Mut<'w, T>, T,);
1024impl_methods!(Mut<'w, T>, T,);
1025impl_debug!(Mut<'w, T>,);
1026
1027/// Unique mutable borrow of resources or an entity's component.
1028///
1029/// Similar to [`Mut`], but not generic over the component type, instead
1030/// exposing the raw pointer as a `*mut ()`.
1031///
1032/// Usually you don't need to use this and can instead use the APIs returning a
1033/// [`Mut`], but in situations where the types are not known at compile time
1034/// or are defined outside of rust this can be used.
1035pub struct MutUntyped<'w> {
1036    pub(crate) value: PtrMut<'w>,
1037    pub(crate) ticks: TicksMut<'w>,
1038    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
1039}
1040
1041impl<'w> MutUntyped<'w> {
1042    /// Returns the pointer to the value, marking it as changed.
1043    ///
1044    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1045    #[inline]
1046    pub fn into_inner(mut self) -> PtrMut<'w> {
1047        self.set_changed();
1048        self.value
1049    }
1050
1051    /// Returns a [`MutUntyped`] with a smaller lifetime.
1052    /// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.
1053    #[inline]
1054    pub fn reborrow(&mut self) -> MutUntyped<'_> {
1055        MutUntyped {
1056            value: self.value.reborrow(),
1057            ticks: TicksMut {
1058                added: self.ticks.added,
1059                changed: self.ticks.changed,
1060                last_run: self.ticks.last_run,
1061                this_run: self.ticks.this_run,
1062            },
1063            changed_by: self.changed_by.as_deref_mut(),
1064        }
1065    }
1066
1067    /// Returns `true` if this value was changed or mutably dereferenced
1068    /// either since a specific change tick.
1069    pub fn has_changed_since(&self, tick: Tick) -> bool {
1070        self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
1071    }
1072
1073    /// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
1074    ///
1075    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1076    #[inline]
1077    pub fn as_mut(&mut self) -> PtrMut<'_> {
1078        self.set_changed();
1079        self.value.reborrow()
1080    }
1081
1082    /// Returns an immutable pointer to the value without taking ownership.
1083    #[inline]
1084    pub fn as_ref(&self) -> Ptr<'_> {
1085        self.value.as_ref()
1086    }
1087
1088    /// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,
1089    /// without flagging a change.
1090    /// This function is the untyped equivalent of [`Mut::map_unchanged`].
1091    ///
1092    /// 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.
1093    ///
1094    /// If you know the type of the value you can do
1095    /// ```no_run
1096    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1097    /// # let mut_untyped: MutUntyped = unimplemented!();
1098    /// // SAFETY: ptr is of type `u8`
1099    /// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
1100    /// ```
1101    /// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],
1102    /// you can do
1103    /// ```no_run
1104    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1105    /// # let mut_untyped: MutUntyped = unimplemented!();
1106    /// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();
1107    /// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
1108    /// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
1109    /// ```
1110    pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
1111        Mut {
1112            value: f(self.value),
1113            ticks: self.ticks,
1114            changed_by: self.changed_by,
1115        }
1116    }
1117
1118    /// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.
1119    ///
1120    /// # Safety
1121    /// - `T` must be the erased pointee type for this [`MutUntyped`].
1122    pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
1123        Mut {
1124            // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
1125            value: unsafe { self.value.deref_mut() },
1126            ticks: self.ticks,
1127            // SAFETY: `caller` is `Aligned`.
1128            changed_by: self.changed_by,
1129        }
1130    }
1131}
1132
1133impl<'w> DetectChanges for MutUntyped<'w> {
1134    #[inline]
1135    fn is_added(&self) -> bool {
1136        self.ticks
1137            .added
1138            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1139    }
1140
1141    #[inline]
1142    fn is_changed(&self) -> bool {
1143        self.ticks
1144            .changed
1145            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1146    }
1147
1148    #[inline]
1149    fn last_changed(&self) -> Tick {
1150        *self.ticks.changed
1151    }
1152
1153    #[inline]
1154    fn changed_by(&self) -> MaybeLocation {
1155        self.changed_by.copied()
1156    }
1157
1158    #[inline]
1159    fn added(&self) -> Tick {
1160        *self.ticks.added
1161    }
1162}
1163
1164impl<'w> DetectChangesMut for MutUntyped<'w> {
1165    type Inner = PtrMut<'w>;
1166
1167    #[inline]
1168    #[track_caller]
1169    fn set_changed(&mut self) {
1170        *self.ticks.changed = self.ticks.this_run;
1171        self.changed_by.assign(MaybeLocation::caller());
1172    }
1173
1174    #[inline]
1175    #[track_caller]
1176    fn set_added(&mut self) {
1177        *self.ticks.changed = self.ticks.this_run;
1178        *self.ticks.added = self.ticks.this_run;
1179        self.changed_by.assign(MaybeLocation::caller());
1180    }
1181
1182    #[inline]
1183    #[track_caller]
1184    fn set_last_changed(&mut self, last_changed: Tick) {
1185        *self.ticks.changed = last_changed;
1186        self.changed_by.assign(MaybeLocation::caller());
1187    }
1188
1189    #[inline]
1190    #[track_caller]
1191    fn set_last_added(&mut self, last_added: Tick) {
1192        *self.ticks.added = last_added;
1193        *self.ticks.changed = last_added;
1194        self.changed_by.assign(MaybeLocation::caller());
1195    }
1196
1197    #[inline]
1198    #[track_caller]
1199    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
1200        &mut self.value
1201    }
1202}
1203
1204impl core::fmt::Debug for MutUntyped<'_> {
1205    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1206        f.debug_tuple("MutUntyped")
1207            .field(&self.value.as_ptr())
1208            .finish()
1209    }
1210}
1211
1212impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
1213    fn from(value: Mut<'w, T>) -> Self {
1214        MutUntyped {
1215            value: value.value.into(),
1216            ticks: value.ticks,
1217            changed_by: value.changed_by,
1218        }
1219    }
1220}
1221
1222/// A value that contains a `T` if the `track_location` feature is enabled,
1223/// and is a ZST if it is not.
1224///
1225/// The overall API is similar to [`Option`], but whether the value is `Some` or `None` is set at compile
1226/// time and is the same for all values.
1227///
1228/// If the `track_location` feature is disabled, then all functions on this type that return
1229/// an `MaybeLocation` will have an empty body and should be removed by the optimizer.
1230///
1231/// This allows code to be written that will be checked by the compiler even when the feature is disabled,
1232/// but that will be entirely removed during compilation.
1233#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
1234#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1235pub struct MaybeLocation<T: ?Sized = &'static Location<'static>> {
1236    #[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
1237    marker: PhantomData<T>,
1238    #[cfg(feature = "track_location")]
1239    value: T,
1240}
1241
1242impl<T: core::fmt::Display> core::fmt::Display for MaybeLocation<T> {
1243    fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1244        #[cfg(feature = "track_location")]
1245        {
1246            self.value.fmt(_f)?;
1247        }
1248        Ok(())
1249    }
1250}
1251
1252impl<T> MaybeLocation<T> {
1253    /// Constructs a new `MaybeLocation` that wraps the given value.
1254    ///
1255    /// This may only accept `Copy` types,
1256    /// since it needs to drop the value if the `track_location` feature is disabled,
1257    /// and non-`Copy` types cannot be dropped in `const` context.
1258    /// Use [`new_with`][Self::new_with] if you need to construct a non-`Copy` value.
1259    ///
1260    /// # See also
1261    /// - [`new_with`][Self::new_with] to initialize using a closure.
1262    /// - [`new_with_flattened`][Self::new_with_flattened] to initialize using a closure that returns an `Option<MaybeLocation<T>>`.
1263    #[inline]
1264    pub const fn new(_value: T) -> Self
1265    where
1266        T: Copy,
1267    {
1268        Self {
1269            #[cfg(feature = "track_location")]
1270            value: _value,
1271            marker: PhantomData,
1272        }
1273    }
1274
1275    /// Constructs a new `MaybeLocation` that wraps the result of the given closure.
1276    ///
1277    /// # See also
1278    /// - [`new`][Self::new] to initialize using a value.
1279    /// - [`new_with_flattened`][Self::new_with_flattened] to initialize using a closure that returns an `Option<MaybeLocation<T>>`.
1280    #[inline]
1281    pub fn new_with(_f: impl FnOnce() -> T) -> Self {
1282        Self {
1283            #[cfg(feature = "track_location")]
1284            value: _f(),
1285            marker: PhantomData,
1286        }
1287    }
1288
1289    /// Maps an `MaybeLocation<T> `to `MaybeLocation<U>` by applying a function to a contained value.
1290    #[inline]
1291    pub fn map<U>(self, _f: impl FnOnce(T) -> U) -> MaybeLocation<U> {
1292        MaybeLocation {
1293            #[cfg(feature = "track_location")]
1294            value: _f(self.value),
1295            marker: PhantomData,
1296        }
1297    }
1298
1299    /// Converts a pair of `MaybeLocation` values to an `MaybeLocation` of a tuple.
1300    #[inline]
1301    pub fn zip<U>(self, _other: MaybeLocation<U>) -> MaybeLocation<(T, U)> {
1302        MaybeLocation {
1303            #[cfg(feature = "track_location")]
1304            value: (self.value, _other.value),
1305            marker: PhantomData,
1306        }
1307    }
1308
1309    /// Returns the contained value or a default.
1310    /// If the `track_location` feature is enabled, this always returns the contained value.
1311    /// If it is disabled, this always returns `T::Default()`.
1312    #[inline]
1313    pub fn unwrap_or_default(self) -> T
1314    where
1315        T: Default,
1316    {
1317        self.into_option().unwrap_or_default()
1318    }
1319
1320    /// Converts an `MaybeLocation` to an [`Option`] to allow run-time branching.
1321    /// If the `track_location` feature is enabled, this always returns `Some`.
1322    /// If it is disabled, this always returns `None`.
1323    #[inline]
1324    pub fn into_option(self) -> Option<T> {
1325        #[cfg(feature = "track_location")]
1326        {
1327            Some(self.value)
1328        }
1329        #[cfg(not(feature = "track_location"))]
1330        {
1331            None
1332        }
1333    }
1334}
1335
1336impl<T> MaybeLocation<Option<T>> {
1337    /// Constructs a new `MaybeLocation` that wraps the result of the given closure.
1338    /// If the closure returns `Some`, it unwraps the inner value.
1339    ///
1340    /// # See also
1341    /// - [`new`][Self::new] to initialize using a value.
1342    /// - [`new_with`][Self::new_with] to initialize using a closure.
1343    #[inline]
1344    pub fn new_with_flattened(_f: impl FnOnce() -> Option<MaybeLocation<T>>) -> Self {
1345        Self {
1346            #[cfg(feature = "track_location")]
1347            value: _f().map(|value| value.value),
1348            marker: PhantomData,
1349        }
1350    }
1351
1352    /// Transposes a `MaybeLocation` of an [`Option`] into an [`Option`] of a `MaybeLocation`.
1353    ///
1354    /// This can be useful if you want to use the `?` operator to exit early
1355    /// if the `track_location` feature is enabled but the value is not found.
1356    ///
1357    /// If the `track_location` feature is enabled,
1358    /// this returns `Some` if the inner value is `Some`
1359    /// and `None` if the inner value is `None`.
1360    ///
1361    /// If it is disabled, this always returns `Some`.
1362    ///
1363    /// # Example
1364    ///
1365    /// ```
1366    /// # use bevy_ecs::{change_detection::MaybeLocation, world::World};
1367    /// # use core::panic::Location;
1368    /// #
1369    /// # fn test() -> Option<()> {
1370    /// let mut world = World::new();
1371    /// let entity = world.spawn(()).id();
1372    /// let location: MaybeLocation<Option<&'static Location<'static>>> =
1373    ///     world.entities().entity_get_spawned_or_despawned_by(entity);
1374    /// let location: MaybeLocation<&'static Location<'static>> = location.transpose()?;
1375    /// # Some(())
1376    /// # }
1377    /// # test();
1378    /// ```
1379    ///
1380    /// # See also
1381    ///
1382    /// - [`into_option`][Self::into_option] to convert to an `Option<Option<T>>`.
1383    ///   When used with [`Option::flatten`], this will have a similar effect,
1384    ///   but will return `None` when the `track_location` feature is disabled.
1385    #[inline]
1386    pub fn transpose(self) -> Option<MaybeLocation<T>> {
1387        #[cfg(feature = "track_location")]
1388        {
1389            self.value.map(|value| MaybeLocation {
1390                value,
1391                marker: PhantomData,
1392            })
1393        }
1394        #[cfg(not(feature = "track_location"))]
1395        {
1396            Some(MaybeLocation {
1397                marker: PhantomData,
1398            })
1399        }
1400    }
1401}
1402
1403impl<T> MaybeLocation<&T> {
1404    /// Maps an `MaybeLocation<&T>` to an `MaybeLocation<T>` by copying the contents.
1405    #[inline]
1406    pub const fn copied(&self) -> MaybeLocation<T>
1407    where
1408        T: Copy,
1409    {
1410        MaybeLocation {
1411            #[cfg(feature = "track_location")]
1412            value: *self.value,
1413            marker: PhantomData,
1414        }
1415    }
1416}
1417
1418impl<T> MaybeLocation<&mut T> {
1419    /// Maps an `MaybeLocation<&mut T>` to an `MaybeLocation<T>` by copying the contents.
1420    #[inline]
1421    pub const fn copied(&self) -> MaybeLocation<T>
1422    where
1423        T: Copy,
1424    {
1425        MaybeLocation {
1426            #[cfg(feature = "track_location")]
1427            value: *self.value,
1428            marker: PhantomData,
1429        }
1430    }
1431
1432    /// Assigns the contents of an `MaybeLocation<T>` to an `MaybeLocation<&mut T>`.
1433    #[inline]
1434    pub fn assign(&mut self, _value: MaybeLocation<T>) {
1435        #[cfg(feature = "track_location")]
1436        {
1437            *self.value = _value.value;
1438        }
1439    }
1440}
1441
1442impl<T: ?Sized> MaybeLocation<T> {
1443    /// Converts from `&MaybeLocation<T>` to `MaybeLocation<&T>`.
1444    #[inline]
1445    pub const fn as_ref(&self) -> MaybeLocation<&T> {
1446        MaybeLocation {
1447            #[cfg(feature = "track_location")]
1448            value: &self.value,
1449            marker: PhantomData,
1450        }
1451    }
1452
1453    /// Converts from `&mut MaybeLocation<T>` to `MaybeLocation<&mut T>`.
1454    #[inline]
1455    pub const fn as_mut(&mut self) -> MaybeLocation<&mut T> {
1456        MaybeLocation {
1457            #[cfg(feature = "track_location")]
1458            value: &mut self.value,
1459            marker: PhantomData,
1460        }
1461    }
1462
1463    /// Converts from `&MaybeLocation<T>` to `MaybeLocation<&T::Target>`.
1464    #[inline]
1465    pub fn as_deref(&self) -> MaybeLocation<&T::Target>
1466    where
1467        T: Deref,
1468    {
1469        MaybeLocation {
1470            #[cfg(feature = "track_location")]
1471            value: &*self.value,
1472            marker: PhantomData,
1473        }
1474    }
1475
1476    /// Converts from `&mut MaybeLocation<T>` to `MaybeLocation<&mut T::Target>`.
1477    #[inline]
1478    pub fn as_deref_mut(&mut self) -> MaybeLocation<&mut T::Target>
1479    where
1480        T: DerefMut,
1481    {
1482        MaybeLocation {
1483            #[cfg(feature = "track_location")]
1484            value: &mut *self.value,
1485            marker: PhantomData,
1486        }
1487    }
1488}
1489
1490impl MaybeLocation {
1491    /// Returns the source location of the caller of this function. If that function's caller is
1492    /// annotated then its call location will be returned, and so on up the stack to the first call
1493    /// within a non-tracked function body.
1494    #[inline]
1495    #[track_caller]
1496    pub const fn caller() -> Self {
1497        // Note that this cannot use `new_with`, since `FnOnce` invocations cannot be annotated with `#[track_caller]`.
1498        MaybeLocation {
1499            #[cfg(feature = "track_location")]
1500            value: Location::caller(),
1501            marker: PhantomData,
1502        }
1503    }
1504}
1505
1506#[cfg(test)]
1507mod tests {
1508    use bevy_ecs_macros::Resource;
1509    use bevy_ptr::PtrMut;
1510    use bevy_reflect::{FromType, ReflectFromPtr};
1511    use core::ops::{Deref, DerefMut};
1512
1513    use crate::{
1514        change_detection::{
1515            MaybeLocation, Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD,
1516            MAX_CHANGE_AGE,
1517        },
1518        component::{Component, ComponentTicks, Tick},
1519        system::{IntoSystem, Single, System},
1520        world::World,
1521    };
1522
1523    use super::{DetectChanges, DetectChangesMut, MutUntyped};
1524
1525    #[derive(Component, PartialEq)]
1526    struct C;
1527
1528    #[derive(Resource)]
1529    struct R;
1530
1531    #[derive(Resource, PartialEq)]
1532    struct R2(u8);
1533
1534    impl Deref for R2 {
1535        type Target = u8;
1536        fn deref(&self) -> &u8 {
1537            &self.0
1538        }
1539    }
1540
1541    impl DerefMut for R2 {
1542        fn deref_mut(&mut self) -> &mut u8 {
1543            &mut self.0
1544        }
1545    }
1546
1547    #[test]
1548    fn change_expiration() {
1549        fn change_detected(query: Option<Single<Ref<C>>>) -> bool {
1550            query.unwrap().is_changed()
1551        }
1552
1553        fn change_expired(query: Option<Single<Ref<C>>>) -> bool {
1554            query.unwrap().is_changed()
1555        }
1556
1557        let mut world = World::new();
1558
1559        // component added: 1, changed: 1
1560        world.spawn(C);
1561
1562        let mut change_detected_system = IntoSystem::into_system(change_detected);
1563        let mut change_expired_system = IntoSystem::into_system(change_expired);
1564        change_detected_system.initialize(&mut world);
1565        change_expired_system.initialize(&mut world);
1566
1567        // world: 1, system last ran: 0, component changed: 1
1568        // The spawn will be detected since it happened after the system "last ran".
1569        assert!(change_detected_system.run((), &mut world).unwrap());
1570
1571        // world: 1 + MAX_CHANGE_AGE
1572        let change_tick = world.change_tick.get_mut();
1573        *change_tick = change_tick.wrapping_add(MAX_CHANGE_AGE);
1574
1575        // Both the system and component appeared `MAX_CHANGE_AGE` ticks ago.
1576        // Since we clamp things to `MAX_CHANGE_AGE` for determinism,
1577        // `ComponentTicks::is_changed` will now see `MAX_CHANGE_AGE > MAX_CHANGE_AGE`
1578        // and return `false`.
1579        assert!(!change_expired_system.run((), &mut world).unwrap());
1580    }
1581
1582    #[test]
1583    fn change_tick_wraparound() {
1584        let mut world = World::new();
1585        world.last_change_tick = Tick::new(u32::MAX);
1586        *world.change_tick.get_mut() = 0;
1587
1588        // component added: 0, changed: 0
1589        world.spawn(C);
1590
1591        world.increment_change_tick();
1592
1593        // Since the world is always ahead, as long as changes can't get older than `u32::MAX` (which we ensure),
1594        // the wrapping difference will always be positive, so wraparound doesn't matter.
1595        let mut query = world.query::<Ref<C>>();
1596        assert!(query.single(&world).unwrap().is_changed());
1597    }
1598
1599    #[test]
1600    fn change_tick_scan() {
1601        let mut world = World::new();
1602
1603        // component added: 1, changed: 1
1604        world.spawn(C);
1605
1606        // a bunch of stuff happens, the component is now older than `MAX_CHANGE_AGE`
1607        *world.change_tick.get_mut() += MAX_CHANGE_AGE + CHECK_TICK_THRESHOLD;
1608        let change_tick = world.change_tick();
1609
1610        let mut query = world.query::<Ref<C>>();
1611        for tracker in query.iter(&world) {
1612            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1613            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1614            assert!(ticks_since_insert > MAX_CHANGE_AGE);
1615            assert!(ticks_since_change > MAX_CHANGE_AGE);
1616        }
1617
1618        // scan change ticks and clamp those at risk of overflow
1619        world.check_change_ticks();
1620
1621        for tracker in query.iter(&world) {
1622            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1623            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1624            assert_eq!(ticks_since_insert, MAX_CHANGE_AGE);
1625            assert_eq!(ticks_since_change, MAX_CHANGE_AGE);
1626        }
1627    }
1628
1629    #[test]
1630    fn mut_from_res_mut() {
1631        let mut component_ticks = ComponentTicks {
1632            added: Tick::new(1),
1633            changed: Tick::new(2),
1634        };
1635        let ticks = TicksMut {
1636            added: &mut component_ticks.added,
1637            changed: &mut component_ticks.changed,
1638            last_run: Tick::new(3),
1639            this_run: Tick::new(4),
1640        };
1641        let mut res = R {};
1642        let mut caller = MaybeLocation::caller();
1643
1644        let res_mut = ResMut {
1645            value: &mut res,
1646            ticks,
1647            changed_by: caller.as_mut(),
1648        };
1649
1650        let into_mut: Mut<R> = res_mut.into();
1651        assert_eq!(1, into_mut.ticks.added.get());
1652        assert_eq!(2, into_mut.ticks.changed.get());
1653        assert_eq!(3, into_mut.ticks.last_run.get());
1654        assert_eq!(4, into_mut.ticks.this_run.get());
1655    }
1656
1657    #[test]
1658    fn mut_new() {
1659        let mut component_ticks = ComponentTicks {
1660            added: Tick::new(1),
1661            changed: Tick::new(3),
1662        };
1663        let mut res = R {};
1664        let mut caller = MaybeLocation::caller();
1665
1666        let val = Mut::new(
1667            &mut res,
1668            &mut component_ticks.added,
1669            &mut component_ticks.changed,
1670            Tick::new(2), // last_run
1671            Tick::new(4), // this_run
1672            caller.as_mut(),
1673        );
1674
1675        assert!(!val.is_added());
1676        assert!(val.is_changed());
1677    }
1678
1679    #[test]
1680    fn mut_from_non_send_mut() {
1681        let mut component_ticks = ComponentTicks {
1682            added: Tick::new(1),
1683            changed: Tick::new(2),
1684        };
1685        let ticks = TicksMut {
1686            added: &mut component_ticks.added,
1687            changed: &mut component_ticks.changed,
1688            last_run: Tick::new(3),
1689            this_run: Tick::new(4),
1690        };
1691        let mut res = R {};
1692        let mut caller = MaybeLocation::caller();
1693
1694        let non_send_mut = NonSendMut {
1695            value: &mut res,
1696            ticks,
1697            changed_by: caller.as_mut(),
1698        };
1699
1700        let into_mut: Mut<R> = non_send_mut.into();
1701        assert_eq!(1, into_mut.ticks.added.get());
1702        assert_eq!(2, into_mut.ticks.changed.get());
1703        assert_eq!(3, into_mut.ticks.last_run.get());
1704        assert_eq!(4, into_mut.ticks.this_run.get());
1705    }
1706
1707    #[test]
1708    fn map_mut() {
1709        use super::*;
1710        struct Outer(i64);
1711
1712        let last_run = Tick::new(2);
1713        let this_run = Tick::new(3);
1714        let mut component_ticks = ComponentTicks {
1715            added: Tick::new(1),
1716            changed: Tick::new(2),
1717        };
1718        let ticks = TicksMut {
1719            added: &mut component_ticks.added,
1720            changed: &mut component_ticks.changed,
1721            last_run,
1722            this_run,
1723        };
1724
1725        let mut outer = Outer(0);
1726        let mut caller = MaybeLocation::caller();
1727
1728        let ptr = Mut {
1729            value: &mut outer,
1730            ticks,
1731            changed_by: caller.as_mut(),
1732        };
1733        assert!(!ptr.is_changed());
1734
1735        // Perform a mapping operation.
1736        let mut inner = ptr.map_unchanged(|x| &mut x.0);
1737        assert!(!inner.is_changed());
1738
1739        // Mutate the inner value.
1740        *inner = 64;
1741        assert!(inner.is_changed());
1742        // Modifying one field of a component should flag a change for the entire component.
1743        assert!(component_ticks.is_changed(last_run, this_run));
1744    }
1745
1746    #[test]
1747    fn set_if_neq() {
1748        let mut world = World::new();
1749
1750        world.insert_resource(R2(0));
1751        // Resources are Changed when first added
1752        world.increment_change_tick();
1753        // This is required to update world::last_change_tick
1754        world.clear_trackers();
1755
1756        let mut r = world.resource_mut::<R2>();
1757        assert!(!r.is_changed(), "Resource must begin unchanged.");
1758
1759        r.set_if_neq(R2(0));
1760        assert!(
1761            !r.is_changed(),
1762            "Resource must not be changed after setting to the same value."
1763        );
1764
1765        r.set_if_neq(R2(3));
1766        assert!(
1767            r.is_changed(),
1768            "Resource must be changed after setting to a different value."
1769        );
1770    }
1771
1772    #[test]
1773    fn as_deref_mut() {
1774        let mut world = World::new();
1775
1776        world.insert_resource(R2(0));
1777        // Resources are Changed when first added
1778        world.increment_change_tick();
1779        // This is required to update world::last_change_tick
1780        world.clear_trackers();
1781
1782        let mut r = world.resource_mut::<R2>();
1783        assert!(!r.is_changed(), "Resource must begin unchanged.");
1784
1785        let mut r = r.as_deref_mut();
1786        assert!(
1787            !r.is_changed(),
1788            "Dereferencing should not mark the item as changed yet"
1789        );
1790
1791        r.set_if_neq(3);
1792        assert!(
1793            r.is_changed(),
1794            "Resource must be changed after setting to a different value."
1795        );
1796    }
1797
1798    #[test]
1799    fn mut_untyped_to_reflect() {
1800        let last_run = Tick::new(2);
1801        let this_run = Tick::new(3);
1802        let mut component_ticks = ComponentTicks {
1803            added: Tick::new(1),
1804            changed: Tick::new(2),
1805        };
1806        let ticks = TicksMut {
1807            added: &mut component_ticks.added,
1808            changed: &mut component_ticks.changed,
1809            last_run,
1810            this_run,
1811        };
1812
1813        let mut value: i32 = 5;
1814        let mut caller = MaybeLocation::caller();
1815
1816        let value = MutUntyped {
1817            value: PtrMut::from(&mut value),
1818            ticks,
1819            changed_by: caller.as_mut(),
1820        };
1821
1822        let reflect_from_ptr = <ReflectFromPtr as FromType<i32>>::from_type();
1823
1824        let mut new = value.map_unchanged(|ptr| {
1825            // SAFETY: The underlying type of `ptr` matches `reflect_from_ptr`.
1826            unsafe { reflect_from_ptr.as_reflect_mut(ptr) }
1827        });
1828
1829        assert!(!new.is_changed());
1830
1831        new.reflect_mut();
1832
1833        assert!(new.is_changed());
1834    }
1835
1836    #[test]
1837    fn mut_untyped_from_mut() {
1838        let mut component_ticks = ComponentTicks {
1839            added: Tick::new(1),
1840            changed: Tick::new(2),
1841        };
1842        let ticks = TicksMut {
1843            added: &mut component_ticks.added,
1844            changed: &mut component_ticks.changed,
1845            last_run: Tick::new(3),
1846            this_run: Tick::new(4),
1847        };
1848        let mut c = C {};
1849        let mut caller = MaybeLocation::caller();
1850
1851        let mut_typed = Mut {
1852            value: &mut c,
1853            ticks,
1854            changed_by: caller.as_mut(),
1855        };
1856
1857        let into_mut: MutUntyped = mut_typed.into();
1858        assert_eq!(1, into_mut.ticks.added.get());
1859        assert_eq!(2, into_mut.ticks.changed.get());
1860        assert_eq!(3, into_mut.ticks.last_run.get());
1861        assert_eq!(4, into_mut.ticks.this_run.get());
1862    }
1863}