Path: blob/main/crates/bevy_ecs/src/change_detection/params.rs
7219 views
use crate::{1change_detection::{traits::*, ComponentTickCells, MaybeLocation, Tick},2ptr::PtrMut,3resource::Resource,4};5use bevy_ptr::{Ptr, UnsafeCellDeref};6use core::{7ops::{Deref, DerefMut},8panic::Location,9};1011/// Used by immutable query parameters (such as [`Ref`] and [`Res`])12/// to store immutable access to the [`Tick`]s of a single component or resource.13#[derive(Clone)]14pub(crate) struct ComponentTicksRef<'w> {15pub(crate) added: &'w Tick,16pub(crate) changed: &'w Tick,17pub(crate) changed_by: MaybeLocation<&'w &'static Location<'static>>,18pub(crate) last_run: Tick,19pub(crate) this_run: Tick,20}2122impl<'w> ComponentTicksRef<'w> {23/// # Safety24/// This should never alias the underlying ticks with a mutable one such as `ComponentTicksMut`.25#[inline]26pub(crate) unsafe fn from_tick_cells(27cells: ComponentTickCells<'w>,28last_run: Tick,29this_run: Tick,30) -> Self {31Self {32// SAFETY: Caller ensures there is no mutable access to the cell.33added: unsafe { cells.added.deref() },34// SAFETY: Caller ensures there is no mutable access to the cell.35changed: unsafe { cells.changed.deref() },36// SAFETY: Caller ensures there is no mutable access to the cell.37changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref()) },38last_run,39this_run,40}41}42}4344/// Used by mutable query parameters (such as [`Mut`] and [`ResMut`])45/// to store mutable access to the [`Tick`]s of a single component or resource.46pub(crate) struct ComponentTicksMut<'w> {47pub(crate) added: &'w mut Tick,48pub(crate) changed: &'w mut Tick,49pub(crate) changed_by: MaybeLocation<&'w mut &'static Location<'static>>,50pub(crate) last_run: Tick,51pub(crate) this_run: Tick,52}5354impl<'w> ComponentTicksMut<'w> {55/// # Safety56/// This should never alias the underlying ticks. All access must be unique.57#[inline]58pub(crate) unsafe fn from_tick_cells(59cells: ComponentTickCells<'w>,60last_run: Tick,61this_run: Tick,62) -> Self {63Self {64// SAFETY: Caller ensures there is no alias to the cell.65added: unsafe { cells.added.deref_mut() },66// SAFETY: Caller ensures there is no alias to the cell.67changed: unsafe { cells.changed.deref_mut() },68// SAFETY: Caller ensures there is no alias to the cell.69changed_by: unsafe { cells.changed_by.map(|changed_by| changed_by.deref_mut()) },70last_run,71this_run,72}73}74}7576impl<'w> From<ComponentTicksMut<'w>> for ComponentTicksRef<'w> {77fn from(ticks: ComponentTicksMut<'w>) -> Self {78ComponentTicksRef {79added: ticks.added,80changed: ticks.changed,81changed_by: ticks.changed_by.map(|changed_by| &*changed_by),82last_run: ticks.last_run,83this_run: ticks.this_run,84}85}86}8788/// Shared borrow of a [`Resource`].89///90/// See the [`Resource`] documentation for usage.91///92/// If you need a unique mutable borrow, use [`ResMut`] instead.93///94/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.95/// This will cause a panic, but can be configured to do nothing or warn once.96///97/// Use [`Option<Res<T>>`] instead if the resource might not always exist.98pub struct Res<'w, T: ?Sized + Resource> {99pub(crate) value: &'w T,100pub(crate) ticks: ComponentTicksRef<'w>,101}102103impl<'w, T: Resource> Res<'w, T> {104/// Copies a reference to a resource.105///106/// Note that unless you actually need an instance of `Res<T>`, you should107/// prefer to just convert it to `&T` which can be freely copied.108#[expect(109clippy::should_implement_trait,110reason = "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()`.)"111)]112pub fn clone(this: &Self) -> Self {113Self {114value: this.value,115ticks: this.ticks.clone(),116}117}118119/// Due to lifetime limitations of the `Deref` trait, this method can be used to obtain a120/// reference of the [`Resource`] with a lifetime bound to `'w` instead of the lifetime of the121/// struct itself.122pub fn into_inner(self) -> &'w T {123self.value124}125}126127impl<'w, T: Resource> From<ResMut<'w, T>> for Res<'w, T> {128fn from(res: ResMut<'w, T>) -> Self {129Self {130value: res.value,131ticks: res.ticks.into(),132}133}134}135136impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {137/// Convert a `Res` into a `Ref`. This allows keeping the change-detection feature of `Ref`138/// while losing the specificity of `Res` for resources.139fn from(res: Res<'w, T>) -> Self {140Self {141value: res.value,142ticks: res.ticks,143}144}145}146147impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>148where149&'a T: IntoIterator,150{151type Item = <&'a T as IntoIterator>::Item;152type IntoIter = <&'a T as IntoIterator>::IntoIter;153154fn into_iter(self) -> Self::IntoIter {155self.value.into_iter()156}157}158change_detection_impl!(Res<'w, T>, T, Resource);159impl_debug!(Res<'w, T>, Resource);160161/// Unique mutable borrow of a [`Resource`].162///163/// See the [`Resource`] documentation for usage.164///165/// If you need a shared borrow, use [`Res`] instead.166///167/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.168/// This will cause a panic, but can be configured to do nothing or warn once.169///170/// Use [`Option<ResMut<T>>`] instead if the resource might not always exist.171pub struct ResMut<'w, T: ?Sized + Resource> {172pub(crate) value: &'w mut T,173pub(crate) ticks: ComponentTicksMut<'w>,174}175176impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T>177where178&'a T: IntoIterator,179{180type Item = <&'a T as IntoIterator>::Item;181type IntoIter = <&'a T as IntoIterator>::IntoIter;182183fn into_iter(self) -> Self::IntoIter {184self.value.into_iter()185}186}187188impl<'w, 'a, T: Resource> IntoIterator for &'a mut ResMut<'w, T>189where190&'a mut T: IntoIterator,191{192type Item = <&'a mut T as IntoIterator>::Item;193type IntoIter = <&'a mut T as IntoIterator>::IntoIter;194195fn into_iter(self) -> Self::IntoIter {196self.set_changed();197self.value.into_iter()198}199}200201change_detection_impl!(ResMut<'w, T>, T, Resource);202change_detection_mut_impl!(ResMut<'w, T>, T, Resource);203impl_methods!(ResMut<'w, T>, T, Resource);204impl_debug!(ResMut<'w, T>, Resource);205206impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {207/// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`208/// while losing the specificity of `ResMut` for resources.209fn from(other: ResMut<'w, T>) -> Mut<'w, T> {210Mut {211value: other.value,212ticks: other.ticks,213}214}215}216217/// Shared borrow of a non-[`Send`] resource.218///219/// Only [`Send`] resources may be accessed with the [`Res`] [`SystemParam`](crate::system::SystemParam). In case that the220/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct221/// the scheduler to instead run the system on the main thread so that it doesn't send the resource222/// over to another thread.223///224/// This [`SystemParam`](crate::system::SystemParam) fails validation if the non-send resource doesn't exist.225/// This will cause a panic, but can be configured to do nothing or warn once.226///227/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.228pub struct NonSend<'w, T: ?Sized + 'static> {229pub(crate) value: &'w T,230pub(crate) ticks: ComponentTicksRef<'w>,231}232233change_detection_impl!(NonSend<'w, T>, T,);234impl_debug!(NonSend<'w, T>,);235236impl<'w, T> From<NonSendMut<'w, T>> for NonSend<'w, T> {237fn from(other: NonSendMut<'w, T>) -> Self {238Self {239value: other.value,240ticks: other.ticks.into(),241}242}243}244245/// Unique borrow of a non-[`Send`] resource.246///247/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the248/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct249/// the scheduler to instead run the system on the main thread so that it doesn't send the resource250/// over to another thread.251///252/// This [`SystemParam`](crate::system::SystemParam) fails validation if non-send resource doesn't exist.253/// This will cause a panic, but can be configured to do nothing or warn once.254///255/// Use [`Option<NonSendMut<T>>`] instead if the resource might not always exist.256pub struct NonSendMut<'w, T: ?Sized + 'static> {257pub(crate) value: &'w mut T,258pub(crate) ticks: ComponentTicksMut<'w>,259}260261change_detection_impl!(NonSendMut<'w, T>, T,);262change_detection_mut_impl!(NonSendMut<'w, T>, T,);263impl_methods!(NonSendMut<'w, T>, T,);264impl_debug!(NonSendMut<'w, T>,);265266impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {267/// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`268/// while losing the specificity of `NonSendMut`.269fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {270Mut {271value: other.value,272ticks: other.ticks,273}274}275}276277/// Shared borrow of an entity's component with access to change detection.278/// Similar to [`Mut`] but is immutable and so doesn't require unique access.279///280/// # Examples281///282/// These two systems produce the same output.283///284/// ```285/// # use bevy_ecs::change_detection::DetectChanges;286/// # use bevy_ecs::query::{Changed, With};287/// # use bevy_ecs::system::Query;288/// # use bevy_ecs::world::Ref;289/// # use bevy_ecs_macros::Component;290/// # #[derive(Component)]291/// # struct MyComponent;292///293/// fn how_many_changed_1(query: Query<(), Changed<MyComponent>>) {294/// println!("{} changed", query.iter().count());295/// }296///297/// fn how_many_changed_2(query: Query<Ref<MyComponent>>) {298/// println!("{} changed", query.iter().filter(|c| c.is_changed()).count());299/// }300/// ```301pub struct Ref<'w, T: ?Sized> {302pub(crate) value: &'w T,303pub(crate) ticks: ComponentTicksRef<'w>,304}305306impl<'w, T: ?Sized> Ref<'w, T> {307/// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.308pub fn into_inner(self) -> &'w T {309self.value310}311312/// Map `Ref` to a different type using `f`.313///314/// This doesn't do anything else than call `f` on the wrapped value.315/// This is equivalent to [`Mut::map_unchanged`].316pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {317Ref {318value: f(self.value),319ticks: self.ticks,320}321}322323/// Create a new `Ref` using provided values.324///325/// This is an advanced feature, `Ref`s are designed to be _created_ by326/// engine-internal code and _consumed_ by end-user code.327///328/// - `value` - The value wrapped by `Ref`.329/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.330/// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.331/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used332/// as a reference to determine whether the wrapped value is newly added or changed.333/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".334pub fn new(335value: &'w T,336added: &'w Tick,337changed: &'w Tick,338last_run: Tick,339this_run: Tick,340caller: MaybeLocation<&'w &'static Location<'static>>,341) -> Ref<'w, T> {342Ref {343value,344ticks: ComponentTicksRef {345added,346changed,347changed_by: caller,348last_run,349this_run,350},351}352}353354/// Overwrite the `last_run` and `this_run` tick that are used for change detection.355///356/// This is an advanced feature. `Ref`s are usually _created_ by engine-internal code and357/// _consumed_ by end-user code.358pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {359self.ticks.last_run = last_run;360self.ticks.this_run = this_run;361}362}363364impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>365where366&'a T: IntoIterator,367{368type Item = <&'a T as IntoIterator>::Item;369type IntoIter = <&'a T as IntoIterator>::IntoIter;370371fn into_iter(self) -> Self::IntoIter {372self.value.into_iter()373}374}375change_detection_impl!(Ref<'w, T>, T,);376impl_debug!(Ref<'w, T>,);377378/// Unique mutable borrow of an entity's component or of a resource.379///380/// This can be used in queries to access change detection from immutable query methods, as opposed381/// to `&mut T` which only provides access to change detection from mutable query methods.382///383/// ```rust384/// # use bevy_ecs::prelude::*;385/// # use bevy_ecs::query::QueryData;386/// #387/// #[derive(Component, Clone, Debug)]388/// struct Name(String);389///390/// #[derive(Component, Clone, Copy, Debug)]391/// struct Health(f32);392///393/// fn my_system(mut query: Query<(Mut<Name>, &mut Health)>) {394/// // Mutable access provides change detection information for both parameters:395/// // - `name` has type `Mut<Name>`396/// // - `health` has type `Mut<Health>`397/// for (name, health) in query.iter_mut() {398/// println!("Name: {:?} (last changed {:?})", name, name.last_changed());399/// println!("Health: {:?} (last changed: {:?})", health, health.last_changed());400/// # println!("{}{}", name.0, health.0); // Silence dead_code warning401/// }402///403/// // Immutable access only provides change detection for `Name`:404/// // - `name` has type `Ref<Name>`405/// // - `health` has type `&Health`406/// for (name, health) in query.iter() {407/// println!("Name: {:?} (last changed {:?})", name, name.last_changed());408/// println!("Health: {:?}", health);409/// }410/// }411///412/// # bevy_ecs::system::assert_is_system(my_system);413/// ```414pub struct Mut<'w, T: ?Sized> {415pub(crate) value: &'w mut T,416pub(crate) ticks: ComponentTicksMut<'w>,417}418419impl<'w, T: ?Sized> Mut<'w, T> {420/// Creates a new change-detection enabled smart pointer.421/// In almost all cases you do not need to call this method manually,422/// as instances of `Mut` will be created by engine-internal code.423///424/// Many use-cases of this method would be better served by [`Mut::map_unchanged`]425/// or [`Mut::reborrow`].426///427/// - `value` - The value wrapped by this smart pointer.428/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.429/// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.430/// This will be updated to the value of `change_tick` if the returned smart pointer431/// is modified.432/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used433/// as a reference to determine whether the wrapped value is newly added or changed.434/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".435pub fn new(436value: &'w mut T,437added: &'w mut Tick,438last_changed: &'w mut Tick,439last_run: Tick,440this_run: Tick,441caller: MaybeLocation<&'w mut &'static Location<'static>>,442) -> Self {443Self {444value,445ticks: ComponentTicksMut {446added,447changed: last_changed,448changed_by: caller,449last_run,450this_run,451},452}453}454455/// Overwrite the `last_run` and `this_run` tick that are used for change detection.456///457/// This is an advanced feature. `Mut`s are usually _created_ by engine-internal code and458/// _consumed_ by end-user code.459pub fn set_ticks(&mut self, last_run: Tick, this_run: Tick) {460self.ticks.last_run = last_run;461self.ticks.this_run = this_run;462}463}464465impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {466fn from(mut_ref: Mut<'w, T>) -> Self {467Self {468value: mut_ref.value,469ticks: mut_ref.ticks.into(),470}471}472}473474impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>475where476&'a T: IntoIterator,477{478type Item = <&'a T as IntoIterator>::Item;479type IntoIter = <&'a T as IntoIterator>::IntoIter;480481fn into_iter(self) -> Self::IntoIter {482self.value.into_iter()483}484}485486impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>487where488&'a mut T: IntoIterator,489{490type Item = <&'a mut T as IntoIterator>::Item;491type IntoIter = <&'a mut T as IntoIterator>::IntoIter;492493fn into_iter(self) -> Self::IntoIter {494self.set_changed();495self.value.into_iter()496}497}498499change_detection_impl!(Mut<'w, T>, T,);500change_detection_mut_impl!(Mut<'w, T>, T,);501impl_methods!(Mut<'w, T>, T,);502impl_debug!(Mut<'w, T>,);503504/// Unique mutable borrow of resources or an entity's component.505///506/// Similar to [`Mut`], but not generic over the component type, instead507/// exposing the raw pointer as a `*mut ()`.508///509/// Usually you don't need to use this and can instead use the APIs returning a510/// [`Mut`], but in situations where the types are not known at compile time511/// or are defined outside of rust this can be used.512pub struct MutUntyped<'w> {513pub(crate) value: PtrMut<'w>,514pub(crate) ticks: ComponentTicksMut<'w>,515}516517impl<'w> MutUntyped<'w> {518/// Returns the pointer to the value, marking it as changed.519///520/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).521#[inline]522pub fn into_inner(mut self) -> PtrMut<'w> {523self.set_changed();524self.value525}526527/// Returns a [`MutUntyped`] with a smaller lifetime.528/// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.529#[inline]530pub fn reborrow(&mut self) -> MutUntyped<'_> {531MutUntyped {532value: self.value.reborrow(),533ticks: ComponentTicksMut {534added: self.ticks.added,535changed: self.ticks.changed,536changed_by: self.ticks.changed_by.as_deref_mut(),537last_run: self.ticks.last_run,538this_run: self.ticks.this_run,539},540}541}542543/// Returns `true` if this value was changed or mutably dereferenced544/// either since a specific change tick.545pub fn has_changed_since(&self, tick: Tick) -> bool {546self.ticks.changed.is_newer_than(tick, self.ticks.this_run)547}548549/// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.550///551/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).552#[inline]553pub fn as_mut(&mut self) -> PtrMut<'_> {554self.set_changed();555self.value.reborrow()556}557558/// Returns an immutable pointer to the value without taking ownership.559#[inline]560pub fn as_ref(&self) -> Ptr<'_> {561self.value.as_ref()562}563564/// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,565/// without flagging a change.566/// This function is the untyped equivalent of [`Mut::map_unchanged`].567///568/// 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.569///570/// If you know the type of the value you can do571/// ```no_run572/// # use bevy_ecs::change_detection::{Mut, MutUntyped};573/// # let mut_untyped: MutUntyped = unimplemented!();574/// // SAFETY: ptr is of type `u8`575/// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });576/// ```577/// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],578/// you can do579/// ```no_run580/// # use bevy_ecs::change_detection::{Mut, MutUntyped};581/// # let mut_untyped: MutUntyped = unimplemented!();582/// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();583/// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`584/// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });585/// ```586pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {587Mut {588value: f(self.value),589ticks: self.ticks,590}591}592593/// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.594///595/// # Safety596/// - `T` must be the erased pointee type for this [`MutUntyped`].597pub unsafe fn with_type<T>(self) -> Mut<'w, T> {598Mut {599// SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.600value: unsafe { self.value.deref_mut() },601ticks: self.ticks,602}603}604}605606impl<'w> DetectChanges for MutUntyped<'w> {607#[inline]608fn is_added(&self) -> bool {609self.ticks610.added611.is_newer_than(self.ticks.last_run, self.ticks.this_run)612}613614#[inline]615fn is_changed(&self) -> bool {616self.ticks617.changed618.is_newer_than(self.ticks.last_run, self.ticks.this_run)619}620621#[inline]622fn last_changed(&self) -> Tick {623*self.ticks.changed624}625626#[inline]627fn changed_by(&self) -> MaybeLocation {628self.ticks.changed_by.copied()629}630631#[inline]632fn added(&self) -> Tick {633*self.ticks.added634}635}636637impl<'w> DetectChangesMut for MutUntyped<'w> {638type Inner = PtrMut<'w>;639640#[inline]641#[track_caller]642fn set_changed(&mut self) {643*self.ticks.changed = self.ticks.this_run;644self.ticks.changed_by.assign(MaybeLocation::caller());645}646647#[inline]648#[track_caller]649fn set_added(&mut self) {650*self.ticks.changed = self.ticks.this_run;651*self.ticks.added = self.ticks.this_run;652self.ticks.changed_by.assign(MaybeLocation::caller());653}654655#[inline]656#[track_caller]657fn set_last_changed(&mut self, last_changed: Tick) {658*self.ticks.changed = last_changed;659self.ticks.changed_by.assign(MaybeLocation::caller());660}661662#[inline]663#[track_caller]664fn set_last_added(&mut self, last_added: Tick) {665*self.ticks.added = last_added;666*self.ticks.changed = last_added;667self.ticks.changed_by.assign(MaybeLocation::caller());668}669670#[inline]671#[track_caller]672fn bypass_change_detection(&mut self) -> &mut Self::Inner {673&mut self.value674}675}676677impl core::fmt::Debug for MutUntyped<'_> {678fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {679f.debug_tuple("MutUntyped")680.field(&self.value.as_ptr())681.finish()682}683}684685impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {686fn from(value: Mut<'w, T>) -> Self {687MutUntyped {688value: value.value.into(),689ticks: value.ticks,690}691}692}693694695