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