use crate::{
change_detection::{traits::*, ComponentTickCells, MaybeLocation, Tick},
component::Mutable,
ptr::PtrMut,
resource::Resource,
};
use bevy_ptr::{Ptr, ThinSlicePtr, UnsafeCellDeref};
use core::{
cell::UnsafeCell,
ops::{Deref, DerefMut},
panic::Location,
};
#[derive(Clone, Copy)]
pub(crate) struct ComponentTicksRef<'w> {
pub(crate) added: &'w Tick,
pub(crate) changed: &'w Tick,
pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,
pub(crate) last_run: Tick,
pub(crate) this_run: Tick,
}
impl<'w> ComponentTicksRef<'w> {
#[inline]
pub(crate) unsafe fn from_tick_cells(
cells: ComponentTickCells<'w>,
last_run: Tick,
this_run: Tick,
) -> Self {
Self {
added: unsafe { cells.added.deref() },
changed: unsafe { cells.changed.deref() },
changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref()) },
last_run,
this_run,
}
}
}
#[derive(Clone)]
pub struct ContiguousComponentTicksRef<'w> {
pub(crate) added: &'w [Tick],
pub(crate) changed: &'w [Tick],
pub(crate) changed_by: MaybeLocation<&'w [&'static Location<'static>]>,
pub(crate) last_run: Tick,
pub(crate) this_run: Tick,
}
impl<'w> ContiguousComponentTicksRef<'w> {
pub(crate) unsafe fn from_slice_ptrs(
added: ThinSlicePtr<'w, UnsafeCell<Tick>>,
changed: ThinSlicePtr<'w, UnsafeCell<Tick>>,
changed_by: MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
len: usize,
this_run: Tick,
last_run: Tick,
) -> Self {
Self {
added: unsafe { added.cast().as_slice_unchecked(len) },
changed: unsafe { changed.cast().as_slice_unchecked(len) },
changed_by: changed_by.map(|v| unsafe { v.cast().as_slice_unchecked(len) }),
last_run,
this_run,
}
}
pub fn new(
added: &'w [Tick],
changed: &'w [Tick],
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w [&'static Location<'static>]>,
) -> Option<Self> {
let eq = added.len() == changed.len()
&& caller
.map(|v| v.len() == added.len())
.into_option()
.unwrap_or(true);
eq.then_some(Self {
added,
changed,
changed_by: caller,
last_run,
this_run,
})
}
pub fn added(&self) -> &'w [Tick] {
self.added
}
pub fn changed(&self) -> &'w [Tick] {
self.changed
}
pub fn changed_by(&self) -> MaybeLocation<&[&'static Location<'static>]> {
self.changed_by.as_deref()
}
pub fn last_run(&self) -> Tick {
self.last_run
}
pub fn this_run(&self) -> Tick {
self.this_run
}
pub fn is_changed_iter(&self) -> impl Iterator<Item = bool> {
self.changed
.iter()
.map(|v| v.is_newer_than(self.last_run, self.this_run))
}
pub fn is_added_iter(&self) -> impl Iterator<Item = bool> {
self.added
.iter()
.map(|v| v.is_newer_than(self.last_run, self.this_run))
}
}
pub(crate) struct ComponentTicksMut<'w> {
pub(crate) added: &'w mut Tick,
pub(crate) changed: &'w mut Tick,
pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,
pub(crate) last_run: Tick,
pub(crate) this_run: Tick,
}
impl<'w> ComponentTicksMut<'w> {
#[inline]
pub(crate) unsafe fn from_tick_cells(
cells: ComponentTickCells<'w>,
last_run: Tick,
this_run: Tick,
) -> Self {
Self {
added: unsafe { cells.added.deref_mut() },
changed: unsafe { cells.changed.deref_mut() },
changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref_mut()) },
last_run,
this_run,
}
}
}
impl<'w> From<ComponentTicksMut<'w>> for ComponentTicksRef<'w> {
fn from(ticks: ComponentTicksMut<'w>) -> Self {
ComponentTicksRef {
added: ticks.added,
changed: ticks.changed,
changed_by: ticks.changed_by.map(|changed_by| &*changed_by),
last_run: ticks.last_run,
this_run: ticks.this_run,
}
}
}
pub struct ContiguousComponentTicksMut<'w> {
pub(crate) added: &'w mut [Tick],
pub(crate) changed: &'w mut [Tick],
pub(crate) changed_by: MaybeLocation<&'w mut [&'static Location<'static>]>,
pub(crate) last_run: Tick,
pub(crate) this_run: Tick,
}
impl<'w> ContiguousComponentTicksMut<'w> {
pub(crate) unsafe fn from_slice_ptrs(
added: ThinSlicePtr<'w, UnsafeCell<Tick>>,
changed: ThinSlicePtr<'w, UnsafeCell<Tick>>,
changed_by: MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
len: usize,
this_run: Tick,
last_run: Tick,
) -> Self {
Self {
added: unsafe { added.as_mut_slice_unchecked(len) },
changed: unsafe { changed.as_mut_slice_unchecked(len) },
changed_by: changed_by.map(|v| unsafe { v.as_mut_slice_unchecked(len) }),
last_run,
this_run,
}
}
pub fn new(
added: &'w mut [Tick],
changed: &'w mut [Tick],
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w mut [&'static Location<'static>]>,
) -> Option<Self> {
let eq = added.len() == changed.len()
&& caller
.as_ref()
.map(|v| v.len() == added.len())
.into_option()
.unwrap_or(true);
eq.then_some(Self {
added,
changed,
changed_by: caller,
last_run,
this_run,
})
}
pub fn added(&self) -> &[Tick] {
self.added
}
pub fn changed(&self) -> &[Tick] {
self.changed
}
pub fn changed_by(&self) -> MaybeLocation<&[&'static Location<'static>]> {
self.changed_by.as_deref()
}
pub fn added_mut(&mut self) -> &mut [Tick] {
self.added
}
pub fn changed_mut(&mut self) -> &mut [Tick] {
self.changed
}
pub fn changed_by_mut(&mut self) -> MaybeLocation<&mut [&'static Location<'static>]> {
self.changed_by.as_deref_mut()
}
pub fn last_run(&self) -> Tick {
self.last_run
}
pub fn this_run(&self) -> Tick {
self.this_run
}
pub fn is_changed_iter(&self) -> impl Iterator<Item = bool> {
self.changed
.iter()
.map(|v| v.is_newer_than(self.last_run, self.this_run))
}
pub fn is_added_iter(&self) -> impl Iterator<Item = bool> {
self.added
.iter()
.map(|v| v.is_newer_than(self.last_run, self.this_run))
}
pub fn mark_all_as_changed(&mut self) {
let this_run = self.this_run;
self.changed_by.as_mut().map(|v| {
for v in v.iter_mut() {
*v = Location::caller();
}
});
for t in self.changed.iter_mut() {
*t = this_run;
}
}
pub fn reborrow(&mut self) -> ContiguousComponentTicksMut<'_> {
ContiguousComponentTicksMut {
added: self.added,
changed: self.changed,
changed_by: self.changed_by.as_deref_mut(),
last_run: self.last_run,
this_run: self.this_run,
}
}
}
impl<'w> From<ContiguousComponentTicksMut<'w>> for ContiguousComponentTicksRef<'w> {
fn from(value: ContiguousComponentTicksMut<'w>) -> Self {
Self {
added: value.added,
changed: value.changed,
changed_by: value.changed_by.map(|v| &*v),
last_run: value.last_run,
this_run: value.this_run,
}
}
}
pub struct Res<'w, T: ?Sized + Resource> {
pub(crate) value: &'w T,
pub(crate) ticks: ComponentTicksRef<'w>,
}
impl<'w, T: Resource> Res<'w, T> {
#[expect(
clippy::should_implement_trait,
reason = "As this struct derefs to the inner resource, a `Clone` trait implementation would interfere with the common case of cloning the inner content."
)]
pub fn clone(this: &Self) -> Self {
Self {
value: this.value,
ticks: this.ticks,
}
}
pub fn into_inner(self) -> &'w T {
self.value
}
}
impl<'w, T: Resource<Mutability = Mutable>> From<ResMut<'w, T>> for Res<'w, T> {
fn from(res: ResMut<'w, T>) -> Self {
Self {
value: res.value,
ticks: res.ticks.into(),
}
}
}
impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
fn from(res: Res<'w, T>) -> Self {
Self {
value: res.value,
ticks: res.ticks,
}
}
}
impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.value.into_iter()
}
}
change_detection_impl!(Res<'w, T>, T, Resource);
impl_debug!(Res<'w, T>, Resource);
pub struct ResMut<'w, T: ?Sized + Resource<Mutability = Mutable>> {
pub(crate) value: &'w mut T,
pub(crate) ticks: ComponentTicksMut<'w>,
}
impl<'w, 'a, T: Resource<Mutability = Mutable>> IntoIterator for &'a ResMut<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.value.into_iter()
}
}
impl<'w, 'a, T: Resource<Mutability = Mutable>> IntoIterator for &'a mut ResMut<'w, T>
where
&'a mut T: IntoIterator,
{
type Item = <&'a mut T as IntoIterator>::Item;
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.set_changed();
self.value.into_iter()
}
}
change_detection_impl!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
change_detection_mut_impl!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
impl_methods!(ResMut<'w, T>, T, Resource<Mutability = Mutable>);
impl_debug!(ResMut<'w, T>, Resource<Mutability = Mutable>);
impl<'w, T: Resource<Mutability = Mutable>> From<ResMut<'w, T>> for Mut<'w, T> {
fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
Mut {
value: other.value,
ticks: other.ticks,
}
}
}
pub struct NonSend<'w, T: ?Sized + 'static> {
pub(crate) value: &'w T,
pub(crate) ticks: ComponentTicksRef<'w>,
}
change_detection_impl!(NonSend<'w, T>, T,);
impl_debug!(NonSend<'w, T>,);
impl<'w, T> From<NonSendMut<'w, T>> for NonSend<'w, T> {
fn from(other: NonSendMut<'w, T>) -> Self {
Self {
value: other.value,
ticks: other.ticks.into(),
}
}
}
pub struct NonSendMut<'w, T: ?Sized + 'static> {
pub(crate) value: &'w mut T,
pub(crate) ticks: ComponentTicksMut<'w>,
}
change_detection_impl!(NonSendMut<'w, T>, T,);
change_detection_mut_impl!(NonSendMut<'w, T>, T,);
impl_methods!(NonSendMut<'w, T>, T,);
impl_debug!(NonSendMut<'w, T>,);
impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
Mut {
value: other.value,
ticks: other.ticks,
}
}
}
pub struct Ref<'w, T: ?Sized> {
pub(crate) value: &'w T,
pub(crate) ticks: ComponentTicksRef<'w>,
}
impl<'w, T: ?Sized> Ref<'w, T> {
pub fn into_inner(self) -> &'w T {
self.value
}
pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {
Ref {
value: f(self.value),
ticks: self.ticks,
}
}
pub fn new(
value: &'w T,
added: &'w Tick,
changed: &'w Tick,
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w &'static Location<'static>>,
) -> Ref<'w, T> {
Ref {
value,
ticks: ComponentTicksRef {
added,
changed,
changed_by: caller,
last_run,
this_run,
},
}
}
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
self.ticks.last_run = last_run;
self.ticks.this_run = this_run;
}
}
impl<'w, T: ?Sized> Copy for Ref<'w, T> {}
impl<'w, T: ?Sized> Clone for Ref<'w, T> {
fn clone(&self) -> Self {
*self
}
}
#[derive(Clone)]
pub struct ContiguousRef<'w, T> {
pub(crate) value: &'w [T],
pub(crate) ticks: ContiguousComponentTicksRef<'w>,
}
impl<'w, T> ContiguousRef<'w, T> {
pub fn into_inner(self) -> &'w [T] {
self.value
}
#[inline]
pub fn added_ticks_slice(&self) -> &'w [Tick] {
self.ticks.added
}
#[inline]
pub fn changed_ticks_slice(&self) -> &'w [Tick] {
self.ticks.changed
}
#[inline]
pub fn changed_by_ticks_slice(&self) -> MaybeLocation<&[&'static Location<'static>]> {
self.ticks.changed_by.as_deref()
}
#[inline]
pub fn last_run_tick(&self) -> Tick {
self.ticks.last_run
}
#[inline]
pub fn this_run_tick(&self) -> Tick {
self.ticks.this_run
}
pub fn new(
value: &'w [T],
added: &'w [Tick],
changed: &'w [Tick],
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w [&'static Location<'static>]>,
) -> Option<Self> {
(value.len() == added.len())
.then(|| ContiguousComponentTicksRef::new(added, changed, last_run, this_run, caller))
.flatten()
.map(|ticks| Self { value, ticks })
}
pub fn split(this: Self) -> (&'w [T], ContiguousComponentTicksRef<'w>) {
(this.value, this.ticks)
}
pub fn from_parts(value: &'w [T], ticks: ContiguousComponentTicksRef<'w>) -> Option<Self> {
(value.len() == ticks.changed.len()).then_some(Self { value, ticks })
}
}
impl<'w, T> Deref for ContiguousRef<'w, T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'w, T> AsRef<[T]> for ContiguousRef<'w, T> {
#[inline]
fn as_ref(&self) -> &[T] {
self.deref()
}
}
impl<'w, T> IntoIterator for ContiguousRef<'w, T> {
type Item = &'w T;
type IntoIter = core::slice::Iter<'w, T>;
fn into_iter(self) -> Self::IntoIter {
self.value.iter()
}
}
impl<'w, T: core::fmt::Debug> core::fmt::Debug for ContiguousRef<'w, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ContiguousRef").field(&self.value).finish()
}
}
impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.value.into_iter()
}
}
change_detection_impl!(Ref<'w, T>, T,);
impl_debug!(Ref<'w, T>,);
pub struct Mut<'w, T: ?Sized> {
pub(crate) value: &'w mut T,
pub(crate) ticks: ComponentTicksMut<'w>,
}
impl<'w, T: ?Sized> Mut<'w, T> {
pub fn new(
value: &'w mut T,
added: &'w mut Tick,
last_changed: &'w mut Tick,
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w mut &'static Location<'static>>,
) -> Self {
Self {
value,
ticks: ComponentTicksMut {
added,
changed: last_changed,
changed_by: caller,
last_run,
this_run,
},
}
}
pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {
self.ticks.last_run = last_run;
self.ticks.this_run = this_run;
}
}
pub struct ContiguousMut<'w, T> {
pub(crate) value: &'w mut [T],
pub(crate) ticks: ContiguousComponentTicksMut<'w>,
}
impl<'w, T> ContiguousMut<'w, T> {
#[inline]
pub fn bypass_change_detection(&mut self) -> &mut [T] {
self.value
}
#[inline]
pub fn added_ticks_slice(&self) -> &[Tick] {
self.ticks.added
}
#[inline]
pub fn changed_ticks_slice(&self) -> &[Tick] {
self.ticks.changed
}
#[inline]
pub fn changed_by_ticks_mut(&self) -> MaybeLocation<&[&'static Location<'static>]> {
self.ticks.changed_by.as_deref()
}
#[inline]
pub fn last_run_tick(&self) -> Tick {
self.ticks.last_run
}
#[inline]
pub fn this_run_tick(&self) -> Tick {
self.ticks.this_run
}
#[inline]
pub fn added_ticks_slice_mut(&mut self) -> &mut [Tick] {
self.ticks.added
}
#[inline]
pub fn changed_ticks_slice_mut(&mut self) -> &mut [Tick] {
self.ticks.changed
}
#[inline]
pub fn changed_by_ticks_slice_mut(
&mut self,
) -> MaybeLocation<&mut [&'static Location<'static>]> {
self.ticks.changed_by.as_deref_mut()
}
#[inline]
pub fn mark_all_as_changed(&mut self) {
self.ticks.mark_all_as_changed();
}
pub fn new(
value: &'w mut [T],
added: &'w mut [Tick],
changed: &'w mut [Tick],
last_run: Tick,
this_run: Tick,
caller: MaybeLocation<&'w mut [&'static Location<'static>]>,
) -> Option<Self> {
(value.len() == added.len())
.then(|| ContiguousComponentTicksMut::new(added, changed, last_run, this_run, caller))
.flatten()
.map(|ticks| Self { value, ticks })
}
pub fn reborrow(&mut self) -> ContiguousMut<'_, T> {
ContiguousMut {
value: self.value,
ticks: self.ticks.reborrow(),
}
}
pub fn split(mut this: Self) -> (&'w mut [T], ContiguousComponentTicksMut<'w>) {
this.mark_all_as_changed();
(this.value, this.ticks)
}
pub fn bypass_change_detection_split(
this: Self,
) -> (&'w mut [T], ContiguousComponentTicksMut<'w>) {
(this.value, this.ticks)
}
pub fn from_parts(value: &'w mut [T], ticks: ContiguousComponentTicksMut<'w>) -> Option<Self> {
(value.len() == ticks.changed.len()).then_some(Self { value, ticks })
}
}
impl<'w, T> Deref for ContiguousMut<'w, T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'w, T> DerefMut for ContiguousMut<'w, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.mark_all_as_changed();
self.value
}
}
impl<'w, T> AsRef<[T]> for ContiguousMut<'w, T> {
#[inline]
fn as_ref(&self) -> &[T] {
self.deref()
}
}
impl<'w, T> AsMut<[T]> for ContiguousMut<'w, T> {
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self.deref_mut()
}
}
impl<'w, T> IntoIterator for ContiguousMut<'w, T> {
type Item = &'w mut T;
type IntoIter = core::slice::IterMut<'w, T>;
fn into_iter(mut self) -> Self::IntoIter {
self.mark_all_as_changed();
self.value.iter_mut()
}
}
impl<'w, T: core::fmt::Debug> core::fmt::Debug for ContiguousMut<'w, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ContiguousMut").field(&self.value).finish()
}
}
impl<'w, T> From<ContiguousMut<'w, T>> for ContiguousRef<'w, T> {
fn from(value: ContiguousMut<'w, T>) -> Self {
Self {
value: value.value,
ticks: value.ticks.into(),
}
}
}
impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
fn from(mut_ref: Mut<'w, T>) -> Self {
Self {
value: mut_ref.value,
ticks: mut_ref.ticks.into(),
}
}
}
impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.value.into_iter()
}
}
impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
where
&'a mut T: IntoIterator,
{
type Item = <&'a mut T as IntoIterator>::Item;
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.set_changed();
self.value.into_iter()
}
}
change_detection_impl!(Mut<'w, T>, T,);
change_detection_mut_impl!(Mut<'w, T>, T,);
impl_methods!(Mut<'w, T>, T,);
impl_debug!(Mut<'w, T>,);
pub struct MutUntyped<'w> {
pub(crate) value: PtrMut<'w>,
pub(crate) ticks: ComponentTicksMut<'w>,
}
impl<'w> MutUntyped<'w> {
#[inline]
pub fn into_inner(mut self) -> PtrMut<'w> {
self.set_changed();
self.value
}
#[inline]
pub fn reborrow(&mut self) -> MutUntyped<'_> {
MutUntyped {
value: self.value.reborrow(),
ticks: ComponentTicksMut {
added: self.ticks.added,
changed: self.ticks.changed,
changed_by: self.ticks.changed_by.as_deref_mut(),
last_run: self.ticks.last_run,
this_run: self.ticks.this_run,
},
}
}
pub fn has_changed_since(&self, tick: Tick) -> bool {
self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
}
#[inline]
pub fn as_mut(&mut self) -> PtrMut<'_> {
self.set_changed();
self.value.reborrow()
}
#[inline]
pub fn as_ref(&self) -> Ptr<'_> {
self.value.as_ref()
}
pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
Mut {
value: f(self.value),
ticks: self.ticks,
}
}
pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
Mut {
value: unsafe { self.value.deref_mut() },
ticks: self.ticks,
}
}
}
impl<'w> DetectChanges for MutUntyped<'w> {
#[inline]
fn is_added(&self) -> bool {
self.is_added_after(self.ticks.last_run)
}
#[inline]
fn is_changed(&self) -> bool {
self.is_changed_after(self.ticks.last_run)
}
#[inline]
fn is_added_after(&self, other: Tick) -> bool {
self.ticks.added.is_newer_than(other, self.ticks.this_run)
}
#[inline]
fn is_changed_after(&self, other: Tick) -> bool {
self.ticks.changed.is_newer_than(other, self.ticks.this_run)
}
#[inline]
fn last_changed(&self) -> Tick {
*self.ticks.changed
}
#[inline]
fn changed_by(&self) -> MaybeLocation {
self.ticks.changed_by.copied()
}
#[inline]
fn added(&self) -> Tick {
*self.ticks.added
}
}
impl<'w> DetectChangesMut for MutUntyped<'w> {
type Inner = PtrMut<'w>;
#[inline]
#[track_caller]
fn set_changed(&mut self) {
*self.ticks.changed = self.ticks.this_run;
self.ticks.changed_by.assign(MaybeLocation::caller());
}
#[inline]
#[track_caller]
fn set_added(&mut self) {
*self.ticks.changed = self.ticks.this_run;
*self.ticks.added = self.ticks.this_run;
self.ticks.changed_by.assign(MaybeLocation::caller());
}
#[inline]
#[track_caller]
fn set_last_changed(&mut self, last_changed: Tick) {
*self.ticks.changed = last_changed;
self.ticks.changed_by.assign(MaybeLocation::caller());
}
#[inline]
#[track_caller]
fn set_last_added(&mut self, last_added: Tick) {
*self.ticks.added = last_added;
*self.ticks.changed = last_added;
self.ticks.changed_by.assign(MaybeLocation::caller());
}
#[inline]
#[track_caller]
fn bypass_change_detection(&mut self) -> &mut Self::Inner {
&mut self.value
}
}
impl core::fmt::Debug for MutUntyped<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("MutUntyped")
.field(&self.value.as_ptr())
.finish()
}
}
impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
fn from(value: Mut<'w, T>) -> Self {
MutUntyped {
value: value.value.into(),
ticks: value.ticks,
}
}
}