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}