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