Skip to main content

bevy_ecs/change_detection/
params.rs

1use crate::{
2    change_detection::{traits::*, ComponentTickCells, MaybeLocation, Tick},
3    component::Mutable,
4    ptr::PtrMut,
5    resource::Resource,
6};
7use bevy_ptr::{Ptr, ThinSlicePtr, UnsafeCellDeref};
8use core::{
9    cell::UnsafeCell,
10    ops::{Deref, DerefMut},
11    panic::Location,
12};
13
14/// Used by immutable query parameters (such as [`Ref`] and [`Res`])
15/// to store immutable access to the [`Tick`]s of a single component or resource.
16#[derive(Clone, Copy)]
17pub(crate) struct ComponentTicksRef<'w> {
18    pub(crate) added: &'w Tick,
19    pub(crate) changed: &'w Tick,
20    pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,
21    pub(crate) last_run: Tick,
22    pub(crate) this_run: Tick,
23}
24
25impl<'w> ComponentTicksRef<'w> {
26    /// # Safety
27    /// This should never alias the underlying ticks with a mutable one such as `ComponentTicksMut`.
28    #[inline]
29    pub(crate) unsafe fn from_tick_cells(
30        cells: ComponentTickCells<'w>,
31        last_run: Tick,
32        this_run: Tick,
33    ) -> Self {
34        Self {
35            // SAFETY: Caller ensures there is no mutable access to the cell.
36            added: unsafe { cells.added.deref() },
37            // SAFETY: Caller ensures there is no mutable access to the cell.
38            changed: unsafe { cells.changed.deref() },
39            // SAFETY: Caller ensures there is no mutable access to the cell.
40            changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref()) },
41            last_run,
42            this_run,
43        }
44    }
45}
46
47/// Data type storing contiguously lying ticks.
48///
49/// Retrievable via [`ContiguousRef::split`] and probably only useful if you want to use the following
50/// methods:
51/// - [`ContiguousComponentTicksRef::is_changed_iter`],
52/// - [`ContiguousComponentTicksRef::is_added_iter`]
53#[derive(Clone)]
54pub struct ContiguousComponentTicksRef<'w> {
55    pub(crate) added: &'w [Tick],
56    pub(crate) changed: &'w [Tick],
57    pub(crate) changed_by: MaybeLocation<&'w [&'static Location<'static>]>,
58    pub(crate) last_run: Tick,
59    pub(crate) this_run: Tick,
60}
61
62impl<'w> ContiguousComponentTicksRef<'w> {
63    /// # Safety
64    /// - The caller must have permission for all given ticks to be read.
65    /// - `len` must be the length of `added`, `changed` and `changed_by` (unless none) slices.
66    pub(crate) unsafe fn from_slice_ptrs(
67        added: ThinSlicePtr<'w, UnsafeCell<Tick>>,
68        changed: ThinSlicePtr<'w, UnsafeCell<Tick>>,
69        changed_by: MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
70        len: usize,
71        this_run: Tick,
72        last_run: Tick,
73    ) -> Self {
74        Self {
75            // SAFETY:
76            // - The caller ensures that `len` is the length of the slice.
77            // - The caller ensures we have permission to read the data.
78            added: unsafe { added.cast().as_slice_unchecked(len) },
79            // SAFETY: see above.
80            changed: unsafe { changed.cast().as_slice_unchecked(len) },
81            // SAFETY: see above.
82            changed_by: changed_by.map(|v| unsafe { v.cast().as_slice_unchecked(len) }),
83            last_run,
84            this_run,
85        }
86    }
87
88    /// Creates a new `ContiguousComponentTicksRef` using provided values or returns [`None`] if lengths of
89    /// `added`, `changed` and `changed_by` do not match    
90    ///
91    /// This is an advanced feature, `ContiguousComponentTicksRef`s are designed to be _created_ by
92    /// engine-internal code and _consumed_ by end-user code.
93    ///
94    /// - `added` - [`Tick`]s that store the tick when the wrapped value was created.
95    /// - `changed` - [`Tick`]s that store the last time the wrapped value was changed.
96    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
97    ///   as a reference to determine whether the wrapped value is newly added or changed.
98    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
99    /// - `caller` - [`Location`]s that store the location when the wrapper value was changed.
100    pub fn new(
101        added: &'w [Tick],
102        changed: &'w [Tick],
103        last_run: Tick,
104        this_run: Tick,
105        caller: MaybeLocation<&'w [&'static Location<'static>]>,
106    ) -> Option<Self> {
107        let eq = added.len() == changed.len()
108            && caller
109                .map(|v| v.len() == added.len())
110                .into_option()
111                .unwrap_or(true);
112        eq.then_some(Self {
113            added,
114            changed,
115            changed_by: caller,
116            last_run,
117            this_run,
118        })
119    }
120
121    /// Returns added ticks' slice.
122    pub fn added(&self) -> &'w [Tick] {
123        self.added
124    }
125
126    /// Returns changed ticks' slice.
127    pub fn changed(&self) -> &'w [Tick] {
128        self.changed
129    }
130
131    /// Returns changed by locations' slice.
132    pub fn changed_by(&self) -> MaybeLocation<&[&'static Location<'static>]> {
133        self.changed_by.as_deref()
134    }
135
136    /// Returns the tick the system last ran.
137    pub fn last_run(&self) -> Tick {
138        self.last_run
139    }
140
141    /// Returns the tick of the current system's run.
142    pub fn this_run(&self) -> Tick {
143        self.this_run
144    }
145
146    /// Returns an iterator where the i-th item corresponds to whether the i-th component was
147    /// marked as changed. If the value equals [`prim@true`], then the component was changed.
148    ///
149    /// # Example
150    /// ```
151    /// # use bevy_ecs::prelude::*;
152    /// #
153    /// # #[derive(Component)]
154    /// # struct A(pub i32);
155    ///
156    /// fn some_system(mut query: Query<Ref<A>>) {
157    ///     for a in query.contiguous_iter().unwrap() {
158    ///         let (a_values, a_ticks) = ContiguousRef::split(a);
159    ///         for (value, is_changed) in a_values.iter().zip(a_ticks.is_changed_iter()) {
160    ///             if is_changed {
161    ///                 // do something
162    ///             }
163    ///         }
164    ///     }
165    /// }
166    /// ```
167    pub fn is_changed_iter(&self) -> impl Iterator<Item = bool> {
168        self.changed
169            .iter()
170            .map(|v| v.is_newer_than(self.last_run, self.this_run))
171    }
172
173    /// Returns an iterator where the i-th item corresponds to whether the i-th component was
174    /// marked as added. If the value equals [`prim@true`], then the component was added.
175    ///
176    /// # Example
177    /// ```
178    /// # use bevy_ecs::prelude::*;
179    /// #
180    /// # #[derive(Component)]
181    /// # struct A(pub i32);
182    ///
183    /// fn some_system(mut query: Query<Ref<A>>) {
184    ///     for a in query.contiguous_iter().unwrap() {
185    ///         let (a_values, a_ticks) = ContiguousRef::split(a);
186    ///         for (value, is_added) in a_values.iter().zip(a_ticks.is_added_iter()) {
187    ///             if is_added {
188    ///                 // do something
189    ///             }
190    ///         }
191    ///     }
192    /// }
193    /// ```
194    pub fn is_added_iter(&self) -> impl Iterator<Item = bool> {
195        self.added
196            .iter()
197            .map(|v| v.is_newer_than(self.last_run, self.this_run))
198    }
199}
200
201/// Used by mutable query parameters (such as [`Mut`] and [`ResMut`])
202/// to store mutable access to the [`Tick`]s of a single component or resource.
203pub(crate) struct ComponentTicksMut<'w> {
204    pub(crate) added: &'w mut Tick,
205    pub(crate) changed: &'w mut Tick,
206    pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
207    pub(crate) last_run: Tick,
208    pub(crate) this_run: Tick,
209}
210
211impl<'w> ComponentTicksMut<'w> {
212    /// # Safety
213    /// This should never alias the underlying ticks. All access must be unique.
214    #[inline]
215    pub(crate) unsafe fn from_tick_cells(
216        cells: ComponentTickCells<'w>,
217        last_run: Tick,
218        this_run: Tick,
219    ) -> Self {
220        Self {
221            // SAFETY: Caller ensures there is no alias to the cell.
222            added: unsafe { cells.added.deref_mut() },
223            // SAFETY: Caller ensures there is no alias to the cell.
224            changed: unsafe { cells.changed.deref_mut() },
225            // SAFETY: Caller ensures there is no alias to the cell.
226            changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref_mut()) },
227            last_run,
228            this_run,
229        }
230    }
231}
232
233impl<'w> From<ComponentTicksMut<'w>> for ComponentTicksRef<'w> {
234    fn from(ticks: ComponentTicksMut<'w>) -> Self {
235        ComponentTicksRef {
236            added: ticks.added,
237            changed: ticks.changed,
238            changed_by: ticks.changed_by.map(|changed_by| &*changed_by),
239            last_run: ticks.last_run,
240            this_run: ticks.this_run,
241        }
242    }
243}
244
245/// Data type storing contiguously lying ticks, which may be accessed to mutate.
246///
247/// Retrievable via [`ContiguousMut::split`] and probably only useful if you want to use the following
248/// methods:
249/// - [`ContiguousComponentTicksMut::is_changed_iter`],
250/// - [`ContiguousComponentTicksMut::is_added_iter`]
251pub struct ContiguousComponentTicksMut<'w> {
252    pub(crate) added: &'w mut [Tick],
253    pub(crate) changed: &'w mut [Tick],
254    pub(crate) changed_by: MaybeLocation<&'w mut [&'static Location<'static>]>,
255    pub(crate) last_run: Tick,
256    pub(crate) this_run: Tick,
257}
258
259impl<'w> ContiguousComponentTicksMut<'w> {
260    /// # Safety
261    /// - The caller must have permission to use all given ticks to be mutated.
262    /// - `len` must be the length of `added`, `changed` and `changed_by` (unless none) slices.
263    pub(crate) unsafe fn from_slice_ptrs(
264        added: ThinSlicePtr<'w, UnsafeCell<Tick>>,
265        changed: ThinSlicePtr<'w, UnsafeCell<Tick>>,
266        changed_by: MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
267        len: usize,
268        this_run: Tick,
269        last_run: Tick,
270    ) -> Self {
271        Self {
272            // SAFETY:
273            // - The caller ensures that `len` is the length of the slice.
274            // - The caller ensures we have permission to mutate the data.
275            added: unsafe { added.as_mut_slice_unchecked(len) },
276            // SAFETY: see above.
277            changed: unsafe { changed.as_mut_slice_unchecked(len) },
278            // SAFETY: see above.
279            changed_by: changed_by.map(|v| unsafe { v.as_mut_slice_unchecked(len) }),
280            last_run,
281            this_run,
282        }
283    }
284
285    /// Creates a new `ContiguousComponentTicksMut` using provided values or returns [`None`] if lengths of
286    /// `added`, `changed` and `changed_by` do not match    
287    ///
288    /// This is an advanced feature, `ContiguousComponentTicksMut`s are designed to be _created_ by
289    /// engine-internal code and _consumed_ by end-user code.
290    ///
291    /// - `added` - [`Tick`]s that store the tick when the wrapped value was created.
292    /// - `changed` - [`Tick`]s that store the last time the wrapped value was changed.
293    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
294    ///   as a reference to determine whether the wrapped value is newly added or changed.
295    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
296    /// - `caller` - [`Location`]s that store the location when the wrapper value was changed.
297    pub fn new(
298        added: &'w mut [Tick],
299        changed: &'w mut [Tick],
300        last_run: Tick,
301        this_run: Tick,
302        caller: MaybeLocation<&'w mut [&'static Location<'static>]>,
303    ) -> Option<Self> {
304        let eq = added.len() == changed.len()
305            && caller
306                .as_ref()
307                .map(|v| v.len() == added.len())
308                .into_option()
309                .unwrap_or(true);
310        eq.then_some(Self {
311            added,
312            changed,
313            changed_by: caller,
314            last_run,
315            this_run,
316        })
317    }
318
319    /// Returns added ticks' slice.
320    pub fn added(&self) -> &[Tick] {
321        self.added
322    }
323
324    /// Returns changed ticks' slice.
325    pub fn changed(&self) -> &[Tick] {
326        self.changed
327    }
328
329    /// Returns changed by locations' slice.
330    pub fn changed_by(&self) -> MaybeLocation<&[&'static Location<'static>]> {
331        self.changed_by.as_deref()
332    }
333
334    /// Returns mutable added ticks' slice.
335    pub fn added_mut(&mut self) -> &mut [Tick] {
336        self.added
337    }
338
339    /// Returns mutable changed ticks' slice.
340    pub fn changed_mut(&mut self) -> &mut [Tick] {
341        self.changed
342    }
343
344    /// Returns mutable changed by locations' slice.
345    pub fn changed_by_mut(&mut self) -> MaybeLocation<&mut [&'static Location<'static>]> {
346        self.changed_by.as_deref_mut()
347    }
348
349    /// Returns the tick the system last ran.
350    pub fn last_run(&self) -> Tick {
351        self.last_run
352    }
353
354    /// Returns the tick of the current system's run.
355    pub fn this_run(&self) -> Tick {
356        self.this_run
357    }
358
359    /// Returns an iterator where the i-th item corresponds to whether the i-th component was
360    /// marked as changed. If the value equals [`prim@true`], then the component was changed.
361    ///
362    /// # Example
363    /// ```
364    /// # use bevy_ecs::prelude::*;
365    /// #
366    /// # #[derive(Component)]
367    /// # struct A(pub i32);
368    ///
369    /// fn some_system(mut query: Query<&mut A>) {
370    ///     for a in query.contiguous_iter_mut().unwrap() {
371    ///         let (a_values, a_ticks) = ContiguousMut::split(a);
372    ///         for (value, is_changed) in a_values.iter_mut().zip(a_ticks.is_changed_iter()) {
373    ///             if is_changed {
374    ///                 value.0 *= 10;
375    ///             }
376    ///         }
377    ///     }
378    /// }
379    /// ```
380    pub fn is_changed_iter(&self) -> impl Iterator<Item = bool> {
381        self.changed
382            .iter()
383            .map(|v| v.is_newer_than(self.last_run, self.this_run))
384    }
385
386    /// Returns an iterator where the i-th item corresponds to whether the i-th component was
387    /// marked as added. If the value equals [`prim@true`], then the component was added.
388    ///
389    /// # Example
390    /// ```
391    /// # use bevy_ecs::prelude::*;
392    /// #
393    /// # #[derive(Component)]
394    /// # struct A(pub i32);
395    ///
396    /// fn some_system(mut query: Query<&mut A>) {
397    ///     for a in query.contiguous_iter_mut().unwrap() {
398    ///         let (a_values, a_ticks) = ContiguousMut::split(a);
399    ///         for (value, is_added) in a_values.iter_mut().zip(a_ticks.is_added_iter()) {
400    ///             if is_added {
401    ///                 value.0 = 10;
402    ///             }
403    ///         }
404    ///     }
405    /// }
406    /// ```
407    pub fn is_added_iter(&self) -> impl Iterator<Item = bool> {
408        self.added
409            .iter()
410            .map(|v| v.is_newer_than(self.last_run, self.this_run))
411    }
412
413    /// Marks every tick as changed.
414    pub fn mark_all_as_changed(&mut self) {
415        let this_run = self.this_run;
416
417        self.changed_by.as_mut().map(|v| {
418            for v in v.iter_mut() {
419                *v = Location::caller();
420            }
421        });
422
423        for t in self.changed.iter_mut() {
424            *t = this_run;
425        }
426    }
427
428    /// Returns a `ContiguousComponentTicksMut` with a smaller lifetime.
429    pub fn reborrow(&mut self) -> ContiguousComponentTicksMut<'_> {
430        ContiguousComponentTicksMut {
431            added: self.added,
432            changed: self.changed,
433            changed_by: self.changed_by.as_deref_mut(),
434            last_run: self.last_run,
435            this_run: self.this_run,
436        }
437    }
438}
439
440impl<'w> From<ContiguousComponentTicksMut<'w>> for ContiguousComponentTicksRef<'w> {
441    fn from(value: ContiguousComponentTicksMut<'w>) -> Self {
442        Self {
443            added: value.added,
444            changed: value.changed,
445            changed_by: value.changed_by.map(|v| &*v),
446            last_run: value.last_run,
447            this_run: value.this_run,
448        }
449    }
450}
451
452/// Shared borrow of a [`Resource`].
453///
454/// See the [`Resource`] documentation for usage.
455///
456/// If you need a unique mutable borrow, use [`ResMut`] instead.
457///
458/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
459/// This will cause a panic, but can be configured to do nothing or warn once.
460///
461/// Use [`Option<Res<T>>`] instead if the resource might not always exist.
462pub struct Res<'w, T: ?Sized + Resource> {
463    pub(crate) value: &'w T,
464    pub(crate) ticks: ComponentTicksRef<'w>,
465}
466
467impl<'w, T: Resource> Res<'w, T> {
468    /// Copies a reference to a resource.
469    ///
470    /// Note that unless you actually need an instance of `Res<T>`, you should
471    /// prefer to just convert it to `&T` which can be freely copied.
472    #[expect(
473        clippy::should_implement_trait,
474        reason = "As this struct derefs to the inner resource, a `Clone` trait implementation would interfere with the common case of cloning the inner content."
475    )]
476    pub fn clone(this: &Self) -> Self {
477        Self {
478            value: this.value,
479            ticks: this.ticks,
480        }
481    }
482
483    /// Due to lifetime limitations of the `Deref` trait, this method can be used to obtain a
484    /// reference of the [`Resource`] with a lifetime bound to `'w` instead of the lifetime of the
485    /// struct itself.
486    pub fn into_inner(self) -> &'w T {
487        self.value
488    }
489}
490
491impl<'w, T: Resource<Mutability = Mutable>> From<ResMut<'w, T>> for Res<'w, T> {
492    fn from(res: ResMut<'w, T>) -> Self {
493        Self {
494            value: res.value,
495            ticks: res.ticks.into(),
496        }
497    }
498}
499
500impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
501    /// Convert a `Res` into a `Ref`. This allows keeping the change-detection feature of `Ref`
502    /// while losing the specificity of `Res` for resources.
503    fn from(res: Res<'w, T>) -> Self {
504        Self {
505            value: res.value,
506            ticks: res.ticks,
507        }
508    }
509}
510
511impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
512where
513    &'a T: IntoIterator,
514{
515    type Item = <&'a T as IntoIterator>::Item;
516    type IntoIter = <&'a T as IntoIterator>::IntoIter;
517
518    fn into_iter(self) -> Self::IntoIter {
519        self.value.into_iter()
520    }
521}
522change_detection_impl!(Res<'w, T>, T, Resource);
523impl_debug!(Res<'w, T>, Resource);
524
525/// Unique mutable borrow of a [`Resource`].
526///
527/// See the [`Resource`] documentation for usage.
528///
529/// If you need a shared borrow, use [`Res`] instead.
530///
531/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
532/// This will cause a panic, but can be configured to do nothing or warn once.
533///
534/// Use [`Option<ResMut<T>>`] instead if the resource might not always exist.
535pub struct ResMut<'w, T: ?Sized + Resource<Mutability = Mutable>> {
536    pub(crate) value: &'w mut T,
537    pub(crate) ticks: ComponentTicksMut<'w>,
538}
539
540impl<'w, 'a, T: Resource<Mutability = Mutable>> IntoIterator for &'a ResMut<'w, T>
541where
542    &'a T: IntoIterator,
543{
544    type Item = <&'a T as IntoIterator>::Item;
545    type IntoIter = <&'a T as IntoIterator>::IntoIter;
546
547    fn into_iter(self) -> Self::IntoIter {
548        self.value.into_iter()
549    }
550}
551
552impl<'w, 'a, T: Resource<Mutability = Mutable>> IntoIterator for &'a mut ResMut<'w, T>
553where
554    &'a mut T: IntoIterator,
555{
556    type Item = <&'a mut T as IntoIterator>::Item;
557    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
558
559    fn into_iter(self) -> Self::IntoIter {
560        self.set_changed();
561        self.value.into_iter()
562    }
563}
564
565change_detection_impl!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
566change_detection_mut_impl!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
567impl_methods!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
568impl_debug!(ResMut<'w, T>, Resource<Mutability = Mutable>);
569
570impl<'w, T: Resource<Mutability = Mutable>> From<ResMut<'w, T>> for Mut<'w, T> {
571    /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
572    /// while losing the specificity of `ResMut` for resources.
573    fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
574        Mut {
575            value: other.value,
576            ticks: other.ticks,
577        }
578    }
579}
580
581/// Shared borrow of a non-[`Send`] resource.
582///
583/// Only [`Send`] resources may be accessed with the [`Res`] [`SystemParam`](crate::system::SystemParam). In case that the
584/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
585/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
586/// over to another thread.
587///
588/// This [`SystemParam`](crate::system::SystemParam) fails validation if the non-send resource doesn't exist.
589/// This will cause a panic, but can be configured to do nothing or warn once.
590///
591/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.
592pub struct NonSend<'w, T: ?Sized + 'static> {
593    pub(crate) value: &'w T,
594    pub(crate) ticks: ComponentTicksRef<'w>,
595}
596
597change_detection_impl!(NonSend<'w, T>, T,);
598impl_debug!(NonSend<'w, T>,);
599
600impl<'w, T> From<NonSendMut<'w, T>> for NonSend<'w, T> {
601    fn from(other: NonSendMut<'w, T>) -> Self {
602        Self {
603            value: other.value,
604            ticks: other.ticks.into(),
605        }
606    }
607}
608
609/// Unique borrow of a non-[`Send`] resource.
610///
611/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
612/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
613/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
614/// over to another thread.
615///
616/// This [`SystemParam`](crate::system::SystemParam) fails validation if non-send resource doesn't exist.
617/// This will cause a panic, but can be configured to do nothing or warn once.
618///
619/// Use [`Option<NonSendMut<T>>`] instead if the resource might not always exist.
620pub struct NonSendMut<'w, T: ?Sized + 'static> {
621    pub(crate) value: &'w mut T,
622    pub(crate) ticks: ComponentTicksMut<'w>,
623}
624
625change_detection_impl!(NonSendMut<'w, T>, T,);
626change_detection_mut_impl!(NonSendMut<'w, T>, T,);
627impl_methods!(NonSendMut<'w, T>, T,);
628impl_debug!(NonSendMut<'w, T>,);
629
630impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
631    /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
632    /// while losing the specificity of `NonSendMut`.
633    fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
634        Mut {
635            value: other.value,
636            ticks: other.ticks,
637        }
638    }
639}
640
641/// Shared borrow of an entity's component with access to change detection.
642/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
643///
644/// # Examples
645///
646/// These two systems produce the same output.
647///
648/// ```
649/// # use bevy_ecs::change_detection::DetectChanges;
650/// # use bevy_ecs::query::{Changed, With};
651/// # use bevy_ecs::system::Query;
652/// # use bevy_ecs::world::Ref;
653/// # use bevy_ecs_macros::Component;
654/// # #[derive(Component)]
655/// # struct MyComponent;
656///
657/// fn how_many_changed_1(query: Query<(), Changed<MyComponent>>) {
658///     println!("{} changed", query.iter().count());
659/// }
660///
661/// fn how_many_changed_2(query: Query<Ref<MyComponent>>) {
662///     println!("{} changed", query.iter().filter(|c| c.is_changed()).count());
663/// }
664/// ```
665pub struct Ref<'w, T: ?Sized> {
666    pub(crate) value: &'w T,
667    pub(crate) ticks: ComponentTicksRef<'w>,
668}
669
670impl<'w, T: ?Sized> Ref<'w, T> {
671    /// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.
672    pub fn into_inner(self) -> &'w T {
673        self.value
674    }
675
676    /// Map `Ref` to a different type using `f`.
677    ///
678    /// This doesn't do anything else than call `f` on the wrapped value.
679    /// This is equivalent to [`Mut::map_unchanged`].
680    pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {
681        Ref {
682            value: f(self.value),
683            ticks: self.ticks,
684        }
685    }
686
687    /// Create a new `Ref` using provided values.
688    ///
689    /// This is an advanced feature, `Ref`s are designed to be _created_ by
690    /// engine-internal code and _consumed_ by end-user code.
691    ///
692    /// - `value` - The value wrapped by `Ref`.
693    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
694    /// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
695    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
696    ///   as a reference to determine whether the wrapped value is newly added or changed.
697    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
698    pub fn new(
699        value: &'w T,
700        added: &'w Tick,
701        changed: &'w Tick,
702        last_run: Tick,
703        this_run: Tick,
704        caller: MaybeLocation<&'w &'static Location<'static>>,
705    ) -> Ref<'w, T> {
706        Ref {
707            value,
708            ticks: ComponentTicksRef {
709                added,
710                changed,
711                changed_by: caller,
712                last_run,
713                this_run,
714            },
715        }
716    }
717
718    /// Overwrite the `last_run` and `this_run` tick that are used for change detection.
719    ///
720    /// This is an advanced feature. `Ref`s are usually _created_ by engine-internal code and
721    /// _consumed_ by end-user code.
722    pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
723        self.ticks.last_run = last_run;
724        self.ticks.this_run = this_run;
725    }
726}
727
728// `Ref` is `Copy` to facilitate creation of split borrows. Compared to `Res`
729// (which isn't `Copy`), `Ref` is not as widely used so can afford to require
730// `ref.as_ref().clone()` or `ref.deref().clone()` in order to clone the inner `T`.
731impl<'w, T: ?Sized> Copy for Ref<'w, T> {}
732
733impl<'w, T: ?Sized> Clone for Ref<'w, T> {
734    fn clone(&self) -> Self {
735        *self
736    }
737}
738
739/// Contiguous equivalent of [`Ref<T>`].
740///
741/// Data type returned by [`ContiguousQueryData::fetch_contiguous`](crate::query::ContiguousQueryData::fetch_contiguous) for [`Ref<T>`].
742#[derive(Clone)]
743pub struct ContiguousRef<'w, T> {
744    pub(crate) value: &'w [T],
745    pub(crate) ticks: ContiguousComponentTicksRef<'w>,
746}
747
748impl<'w, T> ContiguousRef<'w, T> {
749    /// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.
750    pub fn into_inner(self) -> &'w [T] {
751        self.value
752    }
753
754    /// Returns the added ticks.
755    #[inline]
756    pub fn added_ticks_slice(&self) -> &'w [Tick] {
757        self.ticks.added
758    }
759
760    /// Returns the changed ticks.
761    #[inline]
762    pub fn changed_ticks_slice(&self) -> &'w [Tick] {
763        self.ticks.changed
764    }
765
766    /// Returns the changed by ticks.
767    #[inline]
768    pub fn changed_by_ticks_slice(&self) -> MaybeLocation<&[&'static Location<'static>]> {
769        self.ticks.changed_by.as_deref()
770    }
771
772    /// Returns the tick when the system last ran.
773    #[inline]
774    pub fn last_run_tick(&self) -> Tick {
775        self.ticks.last_run
776    }
777
778    /// Returns the tick of the system's current run.
779    #[inline]
780    pub fn this_run_tick(&self) -> Tick {
781        self.ticks.this_run
782    }
783
784    /// Creates a new `ContiguousRef` using provided values or returns [`None`] if lengths of
785    /// `value`, `added`, `changed` and `changed_by` do not match    
786    ///
787    /// This is an advanced feature, `ContiguousRef`s are designed to be _created_ by
788    /// engine-internal code and _consumed_ by end-user code.
789    ///
790    /// - `value` - The values wrapped by `ContiguousRef`.
791    /// - `added` - [`Tick`]s that store the tick when the wrapped value was created.
792    /// - `changed` - [`Tick`]s that store the last time the wrapped value was changed.
793    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
794    ///   as a reference to determine whether the wrapped value is newly added or changed.
795    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
796    /// - `caller` - [`Location`]s that store the location when the wrapper value was changed.
797    pub fn new(
798        value: &'w [T],
799        added: &'w [Tick],
800        changed: &'w [Tick],
801        last_run: Tick,
802        this_run: Tick,
803        caller: MaybeLocation<&'w [&'static Location<'static>]>,
804    ) -> Option<Self> {
805        (value.len() == added.len())
806            .then(|| ContiguousComponentTicksRef::new(added, changed, last_run, this_run, caller))
807            .flatten()
808            .map(|ticks| Self { value, ticks })
809    }
810
811    /// Splits [`ContiguousRef`] into it's inner data types.
812    pub fn split(this: Self) -> (&'w [T], ContiguousComponentTicksRef<'w>) {
813        (this.value, this.ticks)
814    }
815
816    /// Reverse of [`ContiguousRef::split`], constructing a [`ContiguousRef`] using components'
817    /// values and ticks.
818    ///
819    /// Returns [`None`] if lengths of `value` and `ticks` do not match, which doesn't happen if
820    /// `ticks` and `value` come from the same [`Self::split`] call.
821    pub fn from_parts(value: &'w [T], ticks: ContiguousComponentTicksRef<'w>) -> Option<Self> {
822        (value.len() == ticks.changed.len()).then_some(Self { value, ticks })
823    }
824}
825
826impl<'w, T> Deref for ContiguousRef<'w, T> {
827    type Target = [T];
828
829    #[inline]
830    fn deref(&self) -> &Self::Target {
831        self.value
832    }
833}
834
835impl<'w, T> AsRef<[T]> for ContiguousRef<'w, T> {
836    #[inline]
837    fn as_ref(&self) -> &[T] {
838        self.deref()
839    }
840}
841
842impl<'w, T> IntoIterator for ContiguousRef<'w, T> {
843    type Item = &'w T;
844
845    type IntoIter = core::slice::Iter<'w, T>;
846
847    fn into_iter(self) -> Self::IntoIter {
848        self.value.iter()
849    }
850}
851
852impl<'w, T: core::fmt::Debug> core::fmt::Debug for ContiguousRef<'w, T> {
853    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
854        f.debug_tuple("ContiguousRef").field(&self.value).finish()
855    }
856}
857
858impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
859where
860    &'a T: IntoIterator,
861{
862    type Item = <&'a T as IntoIterator>::Item;
863    type IntoIter = <&'a T as IntoIterator>::IntoIter;
864
865    fn into_iter(self) -> Self::IntoIter {
866        self.value.into_iter()
867    }
868}
869change_detection_impl!(Ref<'w, T>, T,);
870impl_debug!(Ref<'w, T>,);
871
872/// Unique mutable borrow of an entity's component or of a resource.
873///
874/// This can be used in queries to access change detection from immutable query methods, as opposed
875/// to `&mut T` which only provides access to change detection from mutable query methods.
876///
877/// ```rust
878/// # use bevy_ecs::prelude::*;
879/// # use bevy_ecs::query::QueryData;
880/// #
881/// #[derive(Component, Clone, Debug)]
882/// struct Name(String);
883///
884/// #[derive(Component, Clone, Copy, Debug)]
885/// struct Health(f32);
886///
887/// fn my_system(mut query: Query<(Mut<Name>, &mut Health)>) {
888///     // Mutable access provides change detection information for both parameters:
889///     // - `name` has type `Mut<Name>`
890///     // - `health` has type `Mut<Health>`
891///     for (name, health) in query.iter_mut() {
892///         println!("Name: {:?} (last changed {:?})", name, name.last_changed());
893///         println!("Health: {:?} (last changed: {:?})", health, health.last_changed());
894/// #        println!("{}{}", name.0, health.0); // Silence dead_code warning
895///     }
896///
897///     // Immutable access only provides change detection for `Name`:
898///     // - `name` has type `Ref<Name>`
899///     // - `health` has type `&Health`
900///     for (name, health) in query.iter() {
901///         println!("Name: {:?} (last changed {:?})", name, name.last_changed());
902///         println!("Health: {:?}", health);
903///     }
904/// }
905///
906/// # bevy_ecs::system::assert_is_system(my_system);
907/// ```
908pub struct Mut<'w, T: ?Sized> {
909    pub(crate) value: &'w mut T,
910    pub(crate) ticks: ComponentTicksMut<'w>,
911}
912
913impl<'w, T: ?Sized> Mut<'w, T> {
914    /// Creates a new change-detection enabled smart pointer.
915    /// In almost all cases you do not need to call this method manually,
916    /// as instances of `Mut` will be created by engine-internal code.
917    ///
918    /// Many use-cases of this method would be better served by [`Mut::map_unchanged`]
919    /// or [`Mut::reborrow`].
920    ///
921    /// - `value` - The value wrapped by this smart pointer.
922    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
923    /// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.
924    ///   This will be updated to the value of `change_tick` if the returned smart pointer
925    ///   is modified.
926    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
927    ///   as a reference to determine whether the wrapped value is newly added or changed.
928    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
929    pub fn new(
930        value: &'w mut T,
931        added: &'w mut Tick,
932        last_changed: &'w mut Tick,
933        last_run: Tick,
934        this_run: Tick,
935        caller: MaybeLocation<&'w mut &'static Location<'static>>,
936    ) -> Self {
937        Self {
938            value,
939            ticks: ComponentTicksMut {
940                added,
941                changed: last_changed,
942                changed_by: caller,
943                last_run,
944                this_run,
945            },
946        }
947    }
948
949    /// Overwrite the `last_run` and `this_run` tick that are used for change detection.
950    ///
951    /// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and
952    /// _consumed_ by end-user code.
953    pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
954        self.ticks.last_run = last_run;
955        self.ticks.this_run = this_run;
956    }
957}
958
959/// Data type returned by [`ContiguousQueryData::fetch_contiguous`](crate::query::ContiguousQueryData::fetch_contiguous)
960/// for [`Mut<T>`] and `&mut T`
961///
962/// # Warning
963/// Implementations of [`DerefMut`], [`AsMut`] and [`IntoIterator`] update change ticks, which may effect performance.
964pub struct ContiguousMut<'w, T> {
965    pub(crate) value: &'w mut [T],
966    pub(crate) ticks: ContiguousComponentTicksMut<'w>,
967}
968
969impl<'w, T> ContiguousMut<'w, T> {
970    /// Manually bypasses change detection, allowing you to mutate the underlying values without updating the change tick,
971    /// which may be useful to reduce amount of work to be done.
972    ///
973    /// # Warning
974    /// This is a risky operation, that can have unexpected consequences on any system relying on this code.
975    /// However, it can be an essential escape hatch when, for example,
976    /// you are trying to synchronize representations using change detection and need to avoid infinite recursion.
977    #[inline]
978    pub fn bypass_change_detection(&mut self) -> &mut [T] {
979        self.value
980    }
981
982    /// Returns the immutable added ticks' slice.
983    #[inline]
984    pub fn added_ticks_slice(&self) -> &[Tick] {
985        self.ticks.added
986    }
987
988    /// Returns the immutable changed ticks' slice.
989    #[inline]
990    pub fn changed_ticks_slice(&self) -> &[Tick] {
991        self.ticks.changed
992    }
993
994    /// Returns the mutable changed by ticks' slice
995    #[inline]
996    pub fn changed_by_ticks_mut(&self) -> MaybeLocation<&[&'static Location<'static>]> {
997        self.ticks.changed_by.as_deref()
998    }
999
1000    /// Returns the tick when the system last ran.
1001    #[inline]
1002    pub fn last_run_tick(&self) -> Tick {
1003        self.ticks.last_run
1004    }
1005
1006    /// Returns the tick of the system's current run.
1007    #[inline]
1008    pub fn this_run_tick(&self) -> Tick {
1009        self.ticks.this_run
1010    }
1011
1012    /// Returns the mutable added ticks' slice.
1013    #[inline]
1014    pub fn added_ticks_slice_mut(&mut self) -> &mut [Tick] {
1015        self.ticks.added
1016    }
1017
1018    /// Returns the mutable changed ticks' slice.
1019    #[inline]
1020    pub fn changed_ticks_slice_mut(&mut self) -> &mut [Tick] {
1021        self.ticks.changed
1022    }
1023
1024    /// Returns the mutable changed by ticks' slice
1025    #[inline]
1026    pub fn changed_by_ticks_slice_mut(
1027        &mut self,
1028    ) -> MaybeLocation<&mut [&'static Location<'static>]> {
1029        self.ticks.changed_by.as_deref_mut()
1030    }
1031
1032    /// Marks all components as changed.
1033    ///
1034    /// **Runs in O(n), where n is the amount of rows**
1035    #[inline]
1036    pub fn mark_all_as_changed(&mut self) {
1037        self.ticks.mark_all_as_changed();
1038    }
1039
1040    /// Creates a new `ContiguousMut` using provided values or returns [`None`] if lengths of
1041    /// `value`, `added`, `changed` and `changed_by` do not match    
1042    ///
1043    /// This is an advanced feature, `ContiguousMut`s are designed to be _created_ by
1044    /// engine-internal code and _consumed_ by end-user code.
1045    ///
1046    /// - `value` - The values wrapped by `ContiguousMut`.
1047    /// - `added` - [`Tick`]s that store the tick when the wrapped value was created.
1048    /// - `changed` - [`Tick`]s that store the last time the wrapped value was changed.
1049    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
1050    ///   as a reference to determine whether the wrapped value is newly added or changed.
1051    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
1052    /// - `caller` - [`Location`]s that store the location when the wrapper value was changed.
1053    pub fn new(
1054        value: &'w mut [T],
1055        added: &'w mut [Tick],
1056        changed: &'w mut [Tick],
1057        last_run: Tick,
1058        this_run: Tick,
1059        caller: MaybeLocation<&'w mut [&'static Location<'static>]>,
1060    ) -> Option<Self> {
1061        (value.len() == added.len())
1062            .then(|| ContiguousComponentTicksMut::new(added, changed, last_run, this_run, caller))
1063            .flatten()
1064            .map(|ticks| Self { value, ticks })
1065    }
1066
1067    /// Returns a `ContiguousMut<T>` with a smaller lifetime.
1068    pub fn reborrow(&mut self) -> ContiguousMut<'_, T> {
1069        ContiguousMut {
1070            value: self.value,
1071            ticks: self.ticks.reborrow(),
1072        }
1073    }
1074
1075    /// Splits [`ContiguousMut`] into it's inner data types. It may be useful, when you want to
1076    /// have an iterator over component values and check ticks simultaneously (using
1077    /// [`ContiguousComponentTicksMut::is_changed_iter`] and
1078    /// [`ContiguousComponentTicksMut::is_added_iter`]).
1079    ///
1080    /// Variant of [`Self::split`] which bypasses change detection: [`Self::bypass_change_detection_split`].
1081    ///
1082    /// Reverse of [`Self::split`] is [`Self::from_parts`].
1083    ///
1084    /// # Warning
1085    /// This version updates changed ticks **before** returning, hence
1086    /// [`ContiguousComponentTicksMut::is_changed_iter`] will be useless (the iterator will be filled with
1087    /// [`prim@true`]s).
1088    // NOTE: `ticks_since_insert` will be 0 (because `this.mark_all_as_changed` makes all changed ticks `this_run`),
1089    // `ticks_since_system` won't be 0, `tick` is newer if
1090    // `ticks_since_system` > `ticks_since_insert`, hence it will always be true.
1091    pub fn split(mut this: Self) -> (&'w mut [T], ContiguousComponentTicksMut<'w>) {
1092        this.mark_all_as_changed();
1093        (this.value, this.ticks)
1094    }
1095
1096    /// Splits [`ContiguousMut`] into it's inner data types. It may be useful, when you want to
1097    /// have an iterator over component values and check ticks simultaneously (using
1098    /// [`ContiguousComponentTicksMut::is_changed_iter`] and
1099    /// [`ContiguousComponentTicksMut::is_added_iter`]).
1100    ///
1101    /// Variant of [`Self::bypass_change_detection_split`] which **does not** bypass change detection: [`Self::split`].
1102    ///
1103    /// Reverse of [`Self::bypass_change_detection_split`] is [`Self::from_parts`].
1104    ///
1105    /// # Warning
1106    /// **Bypasses change detection**, call [`Self::split`] if you don't want to bypass it.
1107    ///
1108    /// See [`Self::bypass_change_detection`] for further explanations.
1109    pub fn bypass_change_detection_split(
1110        this: Self,
1111    ) -> (&'w mut [T], ContiguousComponentTicksMut<'w>) {
1112        (this.value, this.ticks)
1113    }
1114
1115    /// Reverse of [`ContiguousMut::split`] and [`ContiguousMut::bypass_change_detection_split`],
1116    /// constructing a [`ContiguousMut`] using components' values and ticks.
1117    ///
1118    /// Returns [`None`] if lengths of `value` and `ticks` do not match, which doesn't happen if
1119    /// `ticks` and `value` come from the same [`Self::split`] or [`Self::bypass_change_detection_split`] call.
1120    pub fn from_parts(value: &'w mut [T], ticks: ContiguousComponentTicksMut<'w>) -> Option<Self> {
1121        (value.len() == ticks.changed.len()).then_some(Self { value, ticks })
1122    }
1123}
1124
1125impl<'w, T> Deref for ContiguousMut<'w, T> {
1126    type Target = [T];
1127
1128    #[inline]
1129    fn deref(&self) -> &Self::Target {
1130        self.value
1131    }
1132}
1133
1134impl<'w, T> DerefMut for ContiguousMut<'w, T> {
1135    #[inline]
1136    fn deref_mut(&mut self) -> &mut Self::Target {
1137        self.mark_all_as_changed();
1138        self.value
1139    }
1140}
1141
1142impl<'w, T> AsRef<[T]> for ContiguousMut<'w, T> {
1143    #[inline]
1144    fn as_ref(&self) -> &[T] {
1145        self.deref()
1146    }
1147}
1148
1149impl<'w, T> AsMut<[T]> for ContiguousMut<'w, T> {
1150    #[inline]
1151    fn as_mut(&mut self) -> &mut [T] {
1152        self.deref_mut()
1153    }
1154}
1155
1156impl<'w, T> IntoIterator for ContiguousMut<'w, T> {
1157    type Item = &'w mut T;
1158
1159    type IntoIter = core::slice::IterMut<'w, T>;
1160
1161    fn into_iter(mut self) -> Self::IntoIter {
1162        self.mark_all_as_changed();
1163        self.value.iter_mut()
1164    }
1165}
1166
1167impl<'w, T: core::fmt::Debug> core::fmt::Debug for ContiguousMut<'w, T> {
1168    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1169        f.debug_tuple("ContiguousMut").field(&self.value).finish()
1170    }
1171}
1172
1173impl<'w, T> From<ContiguousMut<'w, T>> for ContiguousRef<'w, T> {
1174    fn from(value: ContiguousMut<'w, T>) -> Self {
1175        Self {
1176            value: value.value,
1177            ticks: value.ticks.into(),
1178        }
1179    }
1180}
1181
1182impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
1183    fn from(mut_ref: Mut<'w, T>) -> Self {
1184        Self {
1185            value: mut_ref.value,
1186            ticks: mut_ref.ticks.into(),
1187        }
1188    }
1189}
1190
1191impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
1192where
1193    &'a T: IntoIterator,
1194{
1195    type Item = <&'a T as IntoIterator>::Item;
1196    type IntoIter = <&'a T as IntoIterator>::IntoIter;
1197
1198    fn into_iter(self) -> Self::IntoIter {
1199        self.value.into_iter()
1200    }
1201}
1202
1203impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
1204where
1205    &'a mut T: IntoIterator,
1206{
1207    type Item = <&'a mut T as IntoIterator>::Item;
1208    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1209
1210    fn into_iter(self) -> Self::IntoIter {
1211        self.set_changed();
1212        self.value.into_iter()
1213    }
1214}
1215
1216change_detection_impl!(Mut<'w, T>, T,);
1217change_detection_mut_impl!(Mut<'w, T>, T,);
1218impl_methods!(Mut<'w, T>, T,);
1219impl_debug!(Mut<'w, T>,);
1220
1221/// Unique mutable borrow of resources or an entity's component.
1222///
1223/// Similar to [`Mut`], but not generic over the component type, instead
1224/// exposing the raw pointer as a `*mut ()`.
1225///
1226/// Usually you don't need to use this and can instead use the APIs returning a
1227/// [`Mut`], but in situations where the types are not known at compile time
1228/// or are defined outside of rust this can be used.
1229pub struct MutUntyped<'w> {
1230    pub(crate) value: PtrMut<'w>,
1231    pub(crate) ticks: ComponentTicksMut<'w>,
1232}
1233
1234impl<'w> MutUntyped<'w> {
1235    /// Returns the pointer to the value, marking it as changed.
1236    ///
1237    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1238    #[inline]
1239    pub fn into_inner(mut self) -> PtrMut<'w> {
1240        self.set_changed();
1241        self.value
1242    }
1243
1244    /// Returns a [`MutUntyped`] with a smaller lifetime.
1245    /// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.
1246    #[inline]
1247    pub fn reborrow(&mut self) -> MutUntyped<'_> {
1248        MutUntyped {
1249            value: self.value.reborrow(),
1250            ticks: ComponentTicksMut {
1251                added: self.ticks.added,
1252                changed: self.ticks.changed,
1253                changed_by: self.ticks.changed_by.as_deref_mut(),
1254                last_run: self.ticks.last_run,
1255                this_run: self.ticks.this_run,
1256            },
1257        }
1258    }
1259
1260    /// Returns `true` if this value was changed or mutably dereferenced
1261    /// either since a specific change tick.
1262    pub fn has_changed_since(&self, tick: Tick) -> bool {
1263        self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
1264    }
1265
1266    /// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
1267    ///
1268    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1269    #[inline]
1270    pub fn as_mut(&mut self) -> PtrMut<'_> {
1271        self.set_changed();
1272        self.value.reborrow()
1273    }
1274
1275    /// Returns an immutable pointer to the value without taking ownership.
1276    #[inline]
1277    pub fn as_ref(&self) -> Ptr<'_> {
1278        self.value.as_ref()
1279    }
1280
1281    /// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,
1282    /// without flagging a change.
1283    /// This function is the untyped equivalent of [`Mut::map_unchanged`].
1284    ///
1285    /// 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.
1286    ///
1287    /// If you know the type of the value you can do
1288    /// ```no_run
1289    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1290    /// # let mut_untyped: MutUntyped = unimplemented!();
1291    /// // SAFETY: ptr is of type `u8`
1292    /// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
1293    /// ```
1294    /// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],
1295    /// you can do
1296    /// ```no_run
1297    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1298    /// # let mut_untyped: MutUntyped = unimplemented!();
1299    /// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();
1300    /// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
1301    /// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
1302    /// ```
1303    pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
1304        Mut {
1305            value: f(self.value),
1306            ticks: self.ticks,
1307        }
1308    }
1309
1310    /// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.
1311    ///
1312    /// # Safety
1313    /// - `T` must be the erased pointee type for this [`MutUntyped`].
1314    pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
1315        Mut {
1316            // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
1317            value: unsafe { self.value.deref_mut() },
1318            ticks: self.ticks,
1319        }
1320    }
1321}
1322
1323impl<'w> DetectChanges for MutUntyped<'w> {
1324    #[inline]
1325    fn is_added(&self) -> bool {
1326        self.is_added_after(self.ticks.last_run)
1327    }
1328
1329    #[inline]
1330    fn is_changed(&self) -> bool {
1331        self.is_changed_after(self.ticks.last_run)
1332    }
1333
1334    #[inline]
1335    fn is_added_after(&self, other: Tick) -> bool {
1336        self.ticks.added.is_newer_than(other, self.ticks.this_run)
1337    }
1338
1339    #[inline]
1340    fn is_changed_after(&self, other: Tick) -> bool {
1341        self.ticks.changed.is_newer_than(other, self.ticks.this_run)
1342    }
1343
1344    #[inline]
1345    fn last_changed(&self) -> Tick {
1346        *self.ticks.changed
1347    }
1348
1349    #[inline]
1350    fn changed_by(&self) -> MaybeLocation {
1351        self.ticks.changed_by.copied()
1352    }
1353
1354    #[inline]
1355    fn added(&self) -> Tick {
1356        *self.ticks.added
1357    }
1358}
1359
1360impl<'w> DetectChangesMut for MutUntyped<'w> {
1361    type Inner = PtrMut<'w>;
1362
1363    #[inline]
1364    #[track_caller]
1365    fn set_changed(&mut self) {
1366        *self.ticks.changed = self.ticks.this_run;
1367        self.ticks.changed_by.assign(MaybeLocation::caller());
1368    }
1369
1370    #[inline]
1371    #[track_caller]
1372    fn set_added(&mut self) {
1373        *self.ticks.changed = self.ticks.this_run;
1374        *self.ticks.added = self.ticks.this_run;
1375        self.ticks.changed_by.assign(MaybeLocation::caller());
1376    }
1377
1378    #[inline]
1379    #[track_caller]
1380    fn set_last_changed(&mut self, last_changed: Tick) {
1381        *self.ticks.changed = last_changed;
1382        self.ticks.changed_by.assign(MaybeLocation::caller());
1383    }
1384
1385    #[inline]
1386    #[track_caller]
1387    fn set_last_added(&mut self, last_added: Tick) {
1388        *self.ticks.added = last_added;
1389        *self.ticks.changed = last_added;
1390        self.ticks.changed_by.assign(MaybeLocation::caller());
1391    }
1392
1393    #[inline]
1394    #[track_caller]
1395    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
1396        &mut self.value
1397    }
1398}
1399
1400impl core::fmt::Debug for MutUntyped<'_> {
1401    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1402        f.debug_tuple("MutUntyped")
1403            .field(&self.value.as_ptr())
1404            .finish()
1405    }
1406}
1407
1408impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
1409    fn from(value: Mut<'w, T>) -> Self {
1410        MutUntyped {
1411            value: value.value.into(),
1412            ticks: value.ticks,
1413        }
1414    }
1415}