Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/change_detection/params.rs
7219 views
1
use crate::{
2
change_detection::{traits::*, ComponentTickCells, MaybeLocation, Tick},
3
ptr::PtrMut,
4
resource::Resource,
5
};
6
use bevy_ptr::{Ptr, UnsafeCellDeref};
7
use core::{
8
ops::{Deref, DerefMut},
9
panic::Location,
10
};
11
12
/// Used by immutable query parameters (such as [`Ref`] and [`Res`])
13
/// to store immutable access to the [`Tick`]s of a single component or resource.
14
#[derive(Clone)]
15
pub(crate) struct ComponentTicksRef<'w> {
16
pub(crate) added: &'w Tick,
17
pub(crate) changed: &'w Tick,
18
pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,
19
pub(crate) last_run: Tick,
20
pub(crate) this_run: Tick,
21
}
22
23
impl<'w> ComponentTicksRef<'w> {
24
/// # Safety
25
/// This should never alias the underlying ticks with a mutable one such as `ComponentTicksMut`.
26
#[inline]
27
pub(crate) unsafe fn from_tick_cells(
28
cells: ComponentTickCells<'w>,
29
last_run: Tick,
30
this_run: Tick,
31
) -> Self {
32
Self {
33
// SAFETY: Caller ensures there is no mutable access to the cell.
34
added: unsafe { cells.added.deref() },
35
// SAFETY: Caller ensures there is no mutable access to the cell.
36
changed: unsafe { cells.changed.deref() },
37
// SAFETY: Caller ensures there is no mutable access to the cell.
38
changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref()) },
39
last_run,
40
this_run,
41
}
42
}
43
}
44
45
/// Used by mutable query parameters (such as [`Mut`] and [`ResMut`])
46
/// to store mutable access to the [`Tick`]s of a single component or resource.
47
pub(crate) struct ComponentTicksMut<'w> {
48
pub(crate) added: &'w mut Tick,
49
pub(crate) changed: &'w mut Tick,
50
pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
51
pub(crate) last_run: Tick,
52
pub(crate) this_run: Tick,
53
}
54
55
impl<'w> ComponentTicksMut<'w> {
56
/// # Safety
57
/// This should never alias the underlying ticks. All access must be unique.
58
#[inline]
59
pub(crate) unsafe fn from_tick_cells(
60
cells: ComponentTickCells<'w>,
61
last_run: Tick,
62
this_run: Tick,
63
) -> Self {
64
Self {
65
// SAFETY: Caller ensures there is no alias to the cell.
66
added: unsafe { cells.added.deref_mut() },
67
// SAFETY: Caller ensures there is no alias to the cell.
68
changed: unsafe { cells.changed.deref_mut() },
69
// SAFETY: Caller ensures there is no alias to the cell.
70
changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref_mut()) },
71
last_run,
72
this_run,
73
}
74
}
75
}
76
77
impl<'w> From<ComponentTicksMut<'w>> for ComponentTicksRef<'w> {
78
fn from(ticks: ComponentTicksMut<'w>) -> Self {
79
ComponentTicksRef {
80
added: ticks.added,
81
changed: ticks.changed,
82
changed_by: ticks.changed_by.map(|changed_by| &*changed_by),
83
last_run: ticks.last_run,
84
this_run: ticks.this_run,
85
}
86
}
87
}
88
89
/// Shared borrow of a [`Resource`].
90
///
91
/// See the [`Resource`] documentation for usage.
92
///
93
/// If you need a unique mutable borrow, use [`ResMut`] instead.
94
///
95
/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
96
/// This will cause a panic, but can be configured to do nothing or warn once.
97
///
98
/// Use [`Option<Res<T>>`] instead if the resource might not always exist.
99
pub struct Res<'w, T: ?Sized + Resource> {
100
pub(crate) value: &'w T,
101
pub(crate) ticks: ComponentTicksRef<'w>,
102
}
103
104
impl<'w, T: Resource> Res<'w, T> {
105
/// Copies a reference to a resource.
106
///
107
/// Note that unless you actually need an instance of `Res<T>`, you should
108
/// prefer to just convert it to `&T` which can be freely copied.
109
#[expect(
110
clippy::should_implement_trait,
111
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()`.)"
112
)]
113
pub fn clone(this: &Self) -> Self {
114
Self {
115
value: this.value,
116
ticks: this.ticks.clone(),
117
}
118
}
119
120
/// Due to lifetime limitations of the `Deref` trait, this method can be used to obtain a
121
/// reference of the [`Resource`] with a lifetime bound to `'w` instead of the lifetime of the
122
/// struct itself.
123
pub fn into_inner(self) -> &'w T {
124
self.value
125
}
126
}
127
128
impl<'w, T: Resource> From<ResMut<'w, T>> for Res<'w, T> {
129
fn from(res: ResMut<'w, T>) -> Self {
130
Self {
131
value: res.value,
132
ticks: res.ticks.into(),
133
}
134
}
135
}
136
137
impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
138
/// Convert a `Res` into a `Ref`. This allows keeping the change-detection feature of `Ref`
139
/// while losing the specificity of `Res` for resources.
140
fn from(res: Res<'w, T>) -> Self {
141
Self {
142
value: res.value,
143
ticks: res.ticks,
144
}
145
}
146
}
147
148
impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
149
where
150
&'a T: IntoIterator,
151
{
152
type Item = <&'a T as IntoIterator>::Item;
153
type IntoIter = <&'a T as IntoIterator>::IntoIter;
154
155
fn into_iter(self) -> Self::IntoIter {
156
self.value.into_iter()
157
}
158
}
159
change_detection_impl!(Res<'w, T>, T, Resource);
160
impl_debug!(Res<'w, T>, Resource);
161
162
/// Unique mutable borrow of a [`Resource`].
163
///
164
/// See the [`Resource`] documentation for usage.
165
///
166
/// If you need a shared borrow, use [`Res`] instead.
167
///
168
/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
169
/// This will cause a panic, but can be configured to do nothing or warn once.
170
///
171
/// Use [`Option<ResMut<T>>`] instead if the resource might not always exist.
172
pub struct ResMut<'w, T: ?Sized + Resource> {
173
pub(crate) value: &'w mut T,
174
pub(crate) ticks: ComponentTicksMut<'w>,
175
}
176
177
impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T>
178
where
179
&'a T: IntoIterator,
180
{
181
type Item = <&'a T as IntoIterator>::Item;
182
type IntoIter = <&'a T as IntoIterator>::IntoIter;
183
184
fn into_iter(self) -> Self::IntoIter {
185
self.value.into_iter()
186
}
187
}
188
189
impl<'w, 'a, T: Resource> IntoIterator for &'a mut ResMut<'w, T>
190
where
191
&'a mut T: IntoIterator,
192
{
193
type Item = <&'a mut T as IntoIterator>::Item;
194
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
195
196
fn into_iter(self) -> Self::IntoIter {
197
self.set_changed();
198
self.value.into_iter()
199
}
200
}
201
202
change_detection_impl!(ResMut<'w, T>, T, Resource);
203
change_detection_mut_impl!(ResMut<'w, T>, T, Resource);
204
impl_methods!(ResMut<'w, T>, T, Resource);
205
impl_debug!(ResMut<'w, T>, Resource);
206
207
impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
208
/// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
209
/// while losing the specificity of `ResMut` for resources.
210
fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
211
Mut {
212
value: other.value,
213
ticks: other.ticks,
214
}
215
}
216
}
217
218
/// Shared borrow of a non-[`Send`] resource.
219
///
220
/// Only [`Send`] resources may be accessed with the [`Res`] [`SystemParam`](crate::system::SystemParam). In case that the
221
/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
222
/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
223
/// over to another thread.
224
///
225
/// This [`SystemParam`](crate::system::SystemParam) fails validation if the non-send resource doesn't exist.
226
/// This will cause a panic, but can be configured to do nothing or warn once.
227
///
228
/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.
229
pub struct NonSend<'w, T: ?Sized + 'static> {
230
pub(crate) value: &'w T,
231
pub(crate) ticks: ComponentTicksRef<'w>,
232
}
233
234
change_detection_impl!(NonSend<'w, T>, T,);
235
impl_debug!(NonSend<'w, T>,);
236
237
impl<'w, T> From<NonSendMut<'w, T>> for NonSend<'w, T> {
238
fn from(other: NonSendMut<'w, T>) -> Self {
239
Self {
240
value: other.value,
241
ticks: other.ticks.into(),
242
}
243
}
244
}
245
246
/// Unique borrow of a non-[`Send`] resource.
247
///
248
/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
249
/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
250
/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
251
/// over to another thread.
252
///
253
/// This [`SystemParam`](crate::system::SystemParam) fails validation if non-send resource doesn't exist.
254
/// This will cause a panic, but can be configured to do nothing or warn once.
255
///
256
/// Use [`Option<NonSendMut<T>>`] instead if the resource might not always exist.
257
pub struct NonSendMut<'w, T: ?Sized + 'static> {
258
pub(crate) value: &'w mut T,
259
pub(crate) ticks: ComponentTicksMut<'w>,
260
}
261
262
change_detection_impl!(NonSendMut<'w, T>, T,);
263
change_detection_mut_impl!(NonSendMut<'w, T>, T,);
264
impl_methods!(NonSendMut<'w, T>, T,);
265
impl_debug!(NonSendMut<'w, T>,);
266
267
impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
268
/// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
269
/// while losing the specificity of `NonSendMut`.
270
fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
271
Mut {
272
value: other.value,
273
ticks: other.ticks,
274
}
275
}
276
}
277
278
/// Shared borrow of an entity's component with access to change detection.
279
/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
280
///
281
/// # Examples
282
///
283
/// These two systems produce the same output.
284
///
285
/// ```
286
/// # use bevy_ecs::change_detection::DetectChanges;
287
/// # use bevy_ecs::query::{Changed, With};
288
/// # use bevy_ecs::system::Query;
289
/// # use bevy_ecs::world::Ref;
290
/// # use bevy_ecs_macros::Component;
291
/// # #[derive(Component)]
292
/// # struct MyComponent;
293
///
294
/// fn how_many_changed_1(query: Query<(), Changed<MyComponent>>) {
295
/// println!("{} changed", query.iter().count());
296
/// }
297
///
298
/// fn how_many_changed_2(query: Query<Ref<MyComponent>>) {
299
/// println!("{} changed", query.iter().filter(|c| c.is_changed()).count());
300
/// }
301
/// ```
302
pub struct Ref<'w, T: ?Sized> {
303
pub(crate) value: &'w T,
304
pub(crate) ticks: ComponentTicksRef<'w>,
305
}
306
307
impl<'w, T: ?Sized> Ref<'w, T> {
308
/// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.
309
pub fn into_inner(self) -> &'w T {
310
self.value
311
}
312
313
/// Map `Ref` to a different type using `f`.
314
///
315
/// This doesn't do anything else than call `f` on the wrapped value.
316
/// This is equivalent to [`Mut::map_unchanged`].
317
pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {
318
Ref {
319
value: f(self.value),
320
ticks: self.ticks,
321
}
322
}
323
324
/// Create a new `Ref` using provided values.
325
///
326
/// This is an advanced feature, `Ref`s are designed to be _created_ by
327
/// engine-internal code and _consumed_ by end-user code.
328
///
329
/// - `value` - The value wrapped by `Ref`.
330
/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
331
/// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
332
/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
333
/// as a reference to determine whether the wrapped value is newly added or changed.
334
/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
335
pub fn new(
336
value: &'w T,
337
added: &'w Tick,
338
changed: &'w Tick,
339
last_run: Tick,
340
this_run: Tick,
341
caller: MaybeLocation<&'w &'static Location<'static>>,
342
) -> Ref<'w, T> {
343
Ref {
344
value,
345
ticks: ComponentTicksRef {
346
added,
347
changed,
348
changed_by: caller,
349
last_run,
350
this_run,
351
},
352
}
353
}
354
355
/// Overwrite the `last_run` and `this_run` tick that are used for change detection.
356
///
357
/// This is an advanced feature. `Ref`s are usually _created_ by engine-internal code and
358
/// _consumed_ by end-user code.
359
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
360
self.ticks.last_run = last_run;
361
self.ticks.this_run = this_run;
362
}
363
}
364
365
impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
366
where
367
&'a T: IntoIterator,
368
{
369
type Item = <&'a T as IntoIterator>::Item;
370
type IntoIter = <&'a T as IntoIterator>::IntoIter;
371
372
fn into_iter(self) -> Self::IntoIter {
373
self.value.into_iter()
374
}
375
}
376
change_detection_impl!(Ref<'w, T>, T,);
377
impl_debug!(Ref<'w, T>,);
378
379
/// Unique mutable borrow of an entity's component or of a resource.
380
///
381
/// This can be used in queries to access change detection from immutable query methods, as opposed
382
/// to `&mut T` which only provides access to change detection from mutable query methods.
383
///
384
/// ```rust
385
/// # use bevy_ecs::prelude::*;
386
/// # use bevy_ecs::query::QueryData;
387
/// #
388
/// #[derive(Component, Clone, Debug)]
389
/// struct Name(String);
390
///
391
/// #[derive(Component, Clone, Copy, Debug)]
392
/// struct Health(f32);
393
///
394
/// fn my_system(mut query: Query<(Mut<Name>, &mut Health)>) {
395
/// // Mutable access provides change detection information for both parameters:
396
/// // - `name` has type `Mut<Name>`
397
/// // - `health` has type `Mut<Health>`
398
/// for (name, health) in query.iter_mut() {
399
/// println!("Name: {:?} (last changed {:?})", name, name.last_changed());
400
/// println!("Health: {:?} (last changed: {:?})", health, health.last_changed());
401
/// # println!("{}{}", name.0, health.0); // Silence dead_code warning
402
/// }
403
///
404
/// // Immutable access only provides change detection for `Name`:
405
/// // - `name` has type `Ref<Name>`
406
/// // - `health` has type `&Health`
407
/// for (name, health) in query.iter() {
408
/// println!("Name: {:?} (last changed {:?})", name, name.last_changed());
409
/// println!("Health: {:?}", health);
410
/// }
411
/// }
412
///
413
/// # bevy_ecs::system::assert_is_system(my_system);
414
/// ```
415
pub struct Mut<'w, T: ?Sized> {
416
pub(crate) value: &'w mut T,
417
pub(crate) ticks: ComponentTicksMut<'w>,
418
}
419
420
impl<'w, T: ?Sized> Mut<'w, T> {
421
/// Creates a new change-detection enabled smart pointer.
422
/// In almost all cases you do not need to call this method manually,
423
/// as instances of `Mut` will be created by engine-internal code.
424
///
425
/// Many use-cases of this method would be better served by [`Mut::map_unchanged`]
426
/// or [`Mut::reborrow`].
427
///
428
/// - `value` - The value wrapped by this smart pointer.
429
/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
430
/// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.
431
/// This will be updated to the value of `change_tick` if the returned smart pointer
432
/// is modified.
433
/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
434
/// as a reference to determine whether the wrapped value is newly added or changed.
435
/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
436
pub fn new(
437
value: &'w mut T,
438
added: &'w mut Tick,
439
last_changed: &'w mut Tick,
440
last_run: Tick,
441
this_run: Tick,
442
caller: MaybeLocation<&'w mut &'static Location<'static>>,
443
) -> Self {
444
Self {
445
value,
446
ticks: ComponentTicksMut {
447
added,
448
changed: last_changed,
449
changed_by: caller,
450
last_run,
451
this_run,
452
},
453
}
454
}
455
456
/// Overwrite the `last_run` and `this_run` tick that are used for change detection.
457
///
458
/// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and
459
/// _consumed_ by end-user code.
460
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
461
self.ticks.last_run = last_run;
462
self.ticks.this_run = this_run;
463
}
464
}
465
466
impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
467
fn from(mut_ref: Mut<'w, T>) -> Self {
468
Self {
469
value: mut_ref.value,
470
ticks: mut_ref.ticks.into(),
471
}
472
}
473
}
474
475
impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
476
where
477
&'a T: IntoIterator,
478
{
479
type Item = <&'a T as IntoIterator>::Item;
480
type IntoIter = <&'a T as IntoIterator>::IntoIter;
481
482
fn into_iter(self) -> Self::IntoIter {
483
self.value.into_iter()
484
}
485
}
486
487
impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
488
where
489
&'a mut T: IntoIterator,
490
{
491
type Item = <&'a mut T as IntoIterator>::Item;
492
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
493
494
fn into_iter(self) -> Self::IntoIter {
495
self.set_changed();
496
self.value.into_iter()
497
}
498
}
499
500
change_detection_impl!(Mut<'w, T>, T,);
501
change_detection_mut_impl!(Mut<'w, T>, T,);
502
impl_methods!(Mut<'w, T>, T,);
503
impl_debug!(Mut<'w, T>,);
504
505
/// Unique mutable borrow of resources or an entity's component.
506
///
507
/// Similar to [`Mut`], but not generic over the component type, instead
508
/// exposing the raw pointer as a `*mut ()`.
509
///
510
/// Usually you don't need to use this and can instead use the APIs returning a
511
/// [`Mut`], but in situations where the types are not known at compile time
512
/// or are defined outside of rust this can be used.
513
pub struct MutUntyped<'w> {
514
pub(crate) value: PtrMut<'w>,
515
pub(crate) ticks: ComponentTicksMut<'w>,
516
}
517
518
impl<'w> MutUntyped<'w> {
519
/// Returns the pointer to the value, marking it as changed.
520
///
521
/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
522
#[inline]
523
pub fn into_inner(mut self) -> PtrMut<'w> {
524
self.set_changed();
525
self.value
526
}
527
528
/// Returns a [`MutUntyped`] with a smaller lifetime.
529
/// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.
530
#[inline]
531
pub fn reborrow(&mut self) -> MutUntyped<'_> {
532
MutUntyped {
533
value: self.value.reborrow(),
534
ticks: ComponentTicksMut {
535
added: self.ticks.added,
536
changed: self.ticks.changed,
537
changed_by: self.ticks.changed_by.as_deref_mut(),
538
last_run: self.ticks.last_run,
539
this_run: self.ticks.this_run,
540
},
541
}
542
}
543
544
/// Returns `true` if this value was changed or mutably dereferenced
545
/// either since a specific change tick.
546
pub fn has_changed_since(&self, tick: Tick) -> bool {
547
self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
548
}
549
550
/// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
551
///
552
/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
553
#[inline]
554
pub fn as_mut(&mut self) -> PtrMut<'_> {
555
self.set_changed();
556
self.value.reborrow()
557
}
558
559
/// Returns an immutable pointer to the value without taking ownership.
560
#[inline]
561
pub fn as_ref(&self) -> Ptr<'_> {
562
self.value.as_ref()
563
}
564
565
/// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,
566
/// without flagging a change.
567
/// This function is the untyped equivalent of [`Mut::map_unchanged`].
568
///
569
/// 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.
570
///
571
/// If you know the type of the value you can do
572
/// ```no_run
573
/// # use bevy_ecs::change_detection::{Mut, MutUntyped};
574
/// # let mut_untyped: MutUntyped = unimplemented!();
575
/// // SAFETY: ptr is of type `u8`
576
/// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
577
/// ```
578
/// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],
579
/// you can do
580
/// ```no_run
581
/// # use bevy_ecs::change_detection::{Mut, MutUntyped};
582
/// # let mut_untyped: MutUntyped = unimplemented!();
583
/// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();
584
/// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
585
/// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
586
/// ```
587
pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
588
Mut {
589
value: f(self.value),
590
ticks: self.ticks,
591
}
592
}
593
594
/// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.
595
///
596
/// # Safety
597
/// - `T` must be the erased pointee type for this [`MutUntyped`].
598
pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
599
Mut {
600
// SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
601
value: unsafe { self.value.deref_mut() },
602
ticks: self.ticks,
603
}
604
}
605
}
606
607
impl<'w> DetectChanges for MutUntyped<'w> {
608
#[inline]
609
fn is_added(&self) -> bool {
610
self.ticks
611
.added
612
.is_newer_than(self.ticks.last_run, self.ticks.this_run)
613
}
614
615
#[inline]
616
fn is_changed(&self) -> bool {
617
self.ticks
618
.changed
619
.is_newer_than(self.ticks.last_run, self.ticks.this_run)
620
}
621
622
#[inline]
623
fn last_changed(&self) -> Tick {
624
*self.ticks.changed
625
}
626
627
#[inline]
628
fn changed_by(&self) -> MaybeLocation {
629
self.ticks.changed_by.copied()
630
}
631
632
#[inline]
633
fn added(&self) -> Tick {
634
*self.ticks.added
635
}
636
}
637
638
impl<'w> DetectChangesMut for MutUntyped<'w> {
639
type Inner = PtrMut<'w>;
640
641
#[inline]
642
#[track_caller]
643
fn set_changed(&mut self) {
644
*self.ticks.changed = self.ticks.this_run;
645
self.ticks.changed_by.assign(MaybeLocation::caller());
646
}
647
648
#[inline]
649
#[track_caller]
650
fn set_added(&mut self) {
651
*self.ticks.changed = self.ticks.this_run;
652
*self.ticks.added = self.ticks.this_run;
653
self.ticks.changed_by.assign(MaybeLocation::caller());
654
}
655
656
#[inline]
657
#[track_caller]
658
fn set_last_changed(&mut self, last_changed: Tick) {
659
*self.ticks.changed = last_changed;
660
self.ticks.changed_by.assign(MaybeLocation::caller());
661
}
662
663
#[inline]
664
#[track_caller]
665
fn set_last_added(&mut self, last_added: Tick) {
666
*self.ticks.added = last_added;
667
*self.ticks.changed = last_added;
668
self.ticks.changed_by.assign(MaybeLocation::caller());
669
}
670
671
#[inline]
672
#[track_caller]
673
fn bypass_change_detection(&mut self) -> &mut Self::Inner {
674
&mut self.value
675
}
676
}
677
678
impl core::fmt::Debug for MutUntyped<'_> {
679
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
680
f.debug_tuple("MutUntyped")
681
.field(&self.value.as_ptr())
682
.finish()
683
}
684
}
685
686
impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
687
fn from(value: Mut<'w, T>) -> Self {
688
MutUntyped {
689
value: value.value.into(),
690
ticks: value.ticks,
691
}
692
}
693
}
694
695