2021-09-17 18:00:29 +00:00
|
|
|
//! Types that detect when their internal data mutate.
|
|
|
|
|
2021-10-03 19:23:44 +00:00
|
|
|
use crate::{component::ComponentTicks, system::Resource};
|
2021-11-13 21:15:22 +00:00
|
|
|
#[cfg(feature = "bevy_reflect")]
|
2021-05-30 19:29:31 +00:00
|
|
|
use bevy_reflect::Reflect;
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
|
|
|
|
/// Types that implement reliable change detection.
|
|
|
|
///
|
|
|
|
/// ## Example
|
|
|
|
/// Using types that implement [`DetectChanges`], such as [`ResMut`], provide
|
|
|
|
/// a way to query if a value has been mutated in another system.
|
|
|
|
/// Normally change detecting is triggered by either [`DerefMut`] or [`AsMut`], however
|
|
|
|
/// it can be manually triggered via [`DetectChanges::set_changed`].
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use bevy_ecs::prelude::*;
|
|
|
|
///
|
|
|
|
/// struct MyResource(u32);
|
|
|
|
///
|
|
|
|
/// fn my_system(mut resource: ResMut<MyResource>) {
|
|
|
|
/// if resource.is_changed() {
|
|
|
|
/// println!("My resource was mutated!");
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// resource.0 = 42; // triggers change detection via [`DerefMut`]
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
pub trait DetectChanges {
|
|
|
|
/// Returns true if (and only if) this value been added since the last execution of this
|
|
|
|
/// system.
|
|
|
|
fn is_added(&self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if (and only if) this value been changed since the last execution of this
|
|
|
|
/// system.
|
|
|
|
fn is_changed(&self) -> bool;
|
|
|
|
|
|
|
|
/// Manually flags this value as having been changed. This normally isn't
|
|
|
|
/// required because accessing this pointer mutably automatically flags this
|
|
|
|
/// value as "changed".
|
|
|
|
///
|
|
|
|
/// **Note**: This operation is irreversible.
|
|
|
|
fn set_changed(&mut self);
|
2022-05-02 18:26:52 +00:00
|
|
|
|
|
|
|
/// Returns the change tick recording the previous time this component (or resource) was changed.
|
|
|
|
///
|
|
|
|
/// Note that components and resources are also marked as changed upon insertion.
|
|
|
|
///
|
|
|
|
/// For comparison, the previous change tick of a system can be read using the
|
|
|
|
/// [`SystemChangeTick`](crate::system::SystemChangeTick)
|
|
|
|
/// [`SystemParam`](crate::system::SystemParam).
|
|
|
|
fn last_changed(&self) -> u32;
|
2021-05-30 19:29:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! change_detection_impl {
|
|
|
|
($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
|
|
|
|
impl<$($generics),* $(: $traits)?> DetectChanges for $name<$($generics),*> {
|
|
|
|
#[inline]
|
|
|
|
fn is_added(&self) -> bool {
|
|
|
|
self.ticks
|
|
|
|
.component_ticks
|
|
|
|
.is_added(self.ticks.last_change_tick, self.ticks.change_tick)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn is_changed(&self) -> bool {
|
|
|
|
self.ticks
|
|
|
|
.component_ticks
|
|
|
|
.is_changed(self.ticks.last_change_tick, self.ticks.change_tick)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn set_changed(&mut self) {
|
|
|
|
self.ticks
|
|
|
|
.component_ticks
|
|
|
|
.set_changed(self.ticks.change_tick);
|
|
|
|
}
|
2022-05-02 18:26:52 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn last_changed(&self) -> u32 {
|
|
|
|
self.ticks.last_change_tick
|
|
|
|
}
|
2021-05-30 19:29:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<$($generics),* $(: $traits)?> Deref for $name<$($generics),*> {
|
|
|
|
type Target = $target;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$($generics),* $(: $traits)?> DerefMut for $name<$($generics),*> {
|
|
|
|
#[inline]
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
self.set_changed();
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$($generics),* $(: $traits)?> AsRef<$target> for $name<$($generics),*> {
|
|
|
|
#[inline]
|
|
|
|
fn as_ref(&self) -> &$target {
|
|
|
|
self.deref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$($generics),* $(: $traits)?> AsMut<$target> for $name<$($generics),*> {
|
|
|
|
#[inline]
|
|
|
|
fn as_mut(&mut self) -> &mut $target {
|
|
|
|
self.deref_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_into_inner {
|
|
|
|
($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
|
|
|
|
impl<$($generics),* $(: $traits)?> $name<$($generics),*> {
|
|
|
|
/// Consume `self` and return a mutable reference to the
|
|
|
|
/// contained value while marking `self` as "changed".
|
|
|
|
#[inline]
|
|
|
|
pub fn into_inner(mut self) -> &'a mut $target {
|
|
|
|
self.set_changed();
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_debug {
|
|
|
|
($name:ident < $( $generics:tt ),+ >, $($traits:ident)?) => {
|
|
|
|
impl<$($generics),* $(: $traits)?> std::fmt::Debug for $name<$($generics),*>
|
|
|
|
where T: std::fmt::Debug
|
|
|
|
{
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
f.debug_tuple(stringify!($name))
|
|
|
|
.field(self.value)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct Ticks<'a> {
|
|
|
|
pub(crate) component_ticks: &'a mut ComponentTicks,
|
|
|
|
pub(crate) last_change_tick: u32,
|
|
|
|
pub(crate) change_tick: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Unique mutable borrow of a resource.
|
|
|
|
///
|
2021-09-17 18:00:29 +00:00
|
|
|
/// See the [`World`](crate::world::World) documentation to see the usage of a resource.
|
|
|
|
///
|
|
|
|
/// If you need a shared borrow, use [`Res`](crate::system::Res) instead.
|
|
|
|
///
|
2021-05-30 19:29:31 +00:00
|
|
|
/// # Panics
|
|
|
|
///
|
2021-09-17 18:00:29 +00:00
|
|
|
/// Panics when used as a [`SystemParam`](crate::system::SystemParam) if the resource does not exist.
|
2021-05-30 19:29:31 +00:00
|
|
|
///
|
|
|
|
/// Use `Option<ResMut<T>>` instead if the resource might not always exist.
|
2021-10-03 19:23:44 +00:00
|
|
|
pub struct ResMut<'a, T: Resource> {
|
2021-05-30 19:29:31 +00:00
|
|
|
pub(crate) value: &'a mut T,
|
|
|
|
pub(crate) ticks: Ticks<'a>,
|
|
|
|
}
|
|
|
|
|
2021-10-03 19:23:44 +00:00
|
|
|
change_detection_impl!(ResMut<'a, T>, T, Resource);
|
|
|
|
impl_into_inner!(ResMut<'a, T>, T, Resource);
|
|
|
|
impl_debug!(ResMut<'a, T>, Resource);
|
2021-05-30 19:29:31 +00:00
|
|
|
|
2021-06-09 19:02:00 +00:00
|
|
|
/// Unique borrow of a non-[`Send`] resource.
|
|
|
|
///
|
2021-09-17 18:00:29 +00:00
|
|
|
/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
|
2021-06-09 19:02:00 +00:00
|
|
|
/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
|
|
|
|
/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
|
|
|
|
/// over to another thread.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics when used as a `SystemParameter` if the resource does not exist.
|
2021-06-26 19:29:38 +00:00
|
|
|
///
|
|
|
|
/// Use `Option<NonSendMut<T>>` instead if the resource might not always exist.
|
2021-06-09 19:02:00 +00:00
|
|
|
pub struct NonSendMut<'a, T: 'static> {
|
|
|
|
pub(crate) value: &'a mut T,
|
|
|
|
pub(crate) ticks: Ticks<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
change_detection_impl!(NonSendMut<'a, T>, T,);
|
|
|
|
impl_into_inner!(NonSendMut<'a, T>, T,);
|
|
|
|
impl_debug!(NonSendMut<'a, T>,);
|
|
|
|
|
2021-05-30 19:29:31 +00:00
|
|
|
/// Unique mutable borrow of an entity's component
|
|
|
|
pub struct Mut<'a, T> {
|
|
|
|
pub(crate) value: &'a mut T,
|
|
|
|
pub(crate) ticks: Ticks<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
change_detection_impl!(Mut<'a, T>, T,);
|
|
|
|
impl_into_inner!(Mut<'a, T>, T,);
|
|
|
|
impl_debug!(Mut<'a, T>,);
|
|
|
|
|
|
|
|
/// Unique mutable borrow of a Reflected component
|
2021-11-13 21:15:22 +00:00
|
|
|
#[cfg(feature = "bevy_reflect")]
|
2021-05-30 19:29:31 +00:00
|
|
|
pub struct ReflectMut<'a> {
|
|
|
|
pub(crate) value: &'a mut dyn Reflect,
|
|
|
|
pub(crate) ticks: Ticks<'a>,
|
|
|
|
}
|
|
|
|
|
2021-11-13 21:15:22 +00:00
|
|
|
#[cfg(feature = "bevy_reflect")]
|
2021-05-30 19:29:31 +00:00
|
|
|
change_detection_impl!(ReflectMut<'a>, dyn Reflect,);
|
2022-02-04 03:37:45 +00:00
|
|
|
#[cfg(feature = "bevy_reflect")]
|
|
|
|
impl_into_inner!(ReflectMut<'a>, dyn Reflect,);
|