diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index 3802af55dd349..4bdd9a3ef7e98 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -716,10 +716,9 @@ mod tests { use crate::{ self as bevy_ecs, change_detection::{ - Mut, NonSendMut, ResMut, TicksMut, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE, + Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE, }, component::{Component, ComponentTicks, Tick}, - query::ChangeTrackers, system::{IntoSystem, Query, System}, world::World, }; @@ -738,11 +737,11 @@ mod tests { #[test] fn change_expiration() { - fn change_detected(query: Query>) -> bool { + fn change_detected(query: Query>) -> bool { query.single().is_changed() } - fn change_expired(query: Query>) -> bool { + fn change_expired(query: Query>) -> bool { query.single().is_changed() } @@ -773,7 +772,7 @@ mod tests { #[test] fn change_tick_wraparound() { - fn change_detected(query: Query>) -> bool { + fn change_detected(query: Query>) -> bool { query.single().is_changed() } @@ -804,10 +803,10 @@ mod tests { *world.change_tick.get_mut() += MAX_CHANGE_AGE + CHECK_TICK_THRESHOLD; let change_tick = world.change_tick(); - let mut query = world.query::>(); + let mut query = world.query::>(); for tracker in query.iter(&world) { - let ticks_since_insert = change_tick.wrapping_sub(tracker.component_ticks.added.tick); - let ticks_since_change = change_tick.wrapping_sub(tracker.component_ticks.changed.tick); + let ticks_since_insert = change_tick.wrapping_sub(tracker.ticks.added.tick); + let ticks_since_change = change_tick.wrapping_sub(tracker.ticks.changed.tick); assert!(ticks_since_insert > MAX_CHANGE_AGE); assert!(ticks_since_change > MAX_CHANGE_AGE); } @@ -816,8 +815,8 @@ mod tests { world.check_change_ticks(); for tracker in query.iter(&world) { - let ticks_since_insert = change_tick.wrapping_sub(tracker.component_ticks.added.tick); - let ticks_since_change = change_tick.wrapping_sub(tracker.component_ticks.changed.tick); + let ticks_since_insert = change_tick.wrapping_sub(tracker.ticks.added.tick); + let ticks_since_change = change_tick.wrapping_sub(tracker.ticks.changed.tick); assert!(ticks_since_insert == MAX_CHANGE_AGE); assert!(ticks_since_change == MAX_CHANGE_AGE); } diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 77d6befc5d68d..e05e34896c9f6 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -23,6 +23,9 @@ pub use bevy_ptr as ptr; /// Most commonly used re-exported types. pub mod prelude { + #[doc(hidden)] + #[allow(deprecated)] + pub use crate::query::ChangeTrackers; #[doc(hidden)] #[cfg(feature = "bevy_reflect")] pub use crate::reflect::{ReflectComponent, ReflectResource}; @@ -33,7 +36,7 @@ pub mod prelude { component::Component, entity::Entity, event::{Event, EventReader, EventWriter, Events}, - query::{Added, AnyOf, ChangeTrackers, Changed, Or, QueryState, With, Without}, + query::{Added, AnyOf, Changed, Or, QueryState, With, Without}, removal_detection::RemovedComponents, schedule::{ apply_state_transition, apply_system_buffers, common_conditions::*, IntoSystemConfig, @@ -58,11 +61,10 @@ mod tests { use crate::prelude::Or; use crate::{ bundle::Bundle, + change_detection::Ref, component::{Component, ComponentId}, entity::Entity, - query::{ - Added, ChangeTrackers, Changed, FilteredAccess, ReadOnlyWorldQuery, With, Without, - }, + query::{Added, Changed, FilteredAccess, ReadOnlyWorldQuery, With, Without}, system::Resource, world::{Mut, World}, }; @@ -1292,7 +1294,10 @@ mod tests { } #[test] + #[allow(deprecated)] fn trackers_query() { + use crate::prelude::ChangeTrackers; + let mut world = World::default(); let e1 = world.spawn((A(0), B(0))).id(); world.spawn(B(0)); @@ -1536,7 +1541,7 @@ mod tests { assert_eq!(1, query_min_size![&B, (With, With)],); assert_eq!(1, query_min_size![(&A, &B), With],); assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal"); - assert_eq!(4, query_min_size![ChangeTrackers, ()],); + assert_eq!(4, query_min_size![Ref, ()],); // All the following should set minimum size to 0, as it's impossible to predict // how many entities the filters will trim. assert_eq!(0, query_min_size![(), Added], "Simple Added"); diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 5733ffd262829..dc6f42c90bd1d 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -1115,6 +1115,7 @@ unsafe impl ReadOnlyWorldQuery for Option {} /// } /// # bevy_ecs::system::assert_is_system(print_moving_objects_system); /// ``` +#[deprecated = "`ChangeTrackers` will be removed in bevy 0.11. Use `bevy_ecs::prelude::Ref` instead."] pub struct ChangeTrackers { pub(crate) component_ticks: ComponentTicks, pub(crate) last_change_tick: u32, @@ -1122,18 +1123,17 @@ pub struct ChangeTrackers { marker: PhantomData, } +#[allow(deprecated)] impl Clone for ChangeTrackers { fn clone(&self) -> Self { - Self { - component_ticks: self.component_ticks, - last_change_tick: self.last_change_tick, - change_tick: self.change_tick, - marker: PhantomData, - } + *self } } + +#[allow(deprecated)] impl Copy for ChangeTrackers {} +#[allow(deprecated)] impl std::fmt::Debug for ChangeTrackers { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("ChangeTrackers") @@ -1144,6 +1144,7 @@ impl std::fmt::Debug for ChangeTrackers { } } +#[allow(deprecated)] impl ChangeTrackers { /// Returns true if this component has been added since the last execution of this system. pub fn is_added(&self) -> bool { @@ -1171,6 +1172,7 @@ pub struct ChangeTrackersFetch<'w, T> { change_tick: u32, } +#[allow(deprecated)] // SAFETY: `ROQueryFetch` is the same as `QueryFetch` unsafe impl WorldQuery for ChangeTrackers { type Fetch<'w> = ChangeTrackersFetch<'w, T>; @@ -1317,6 +1319,7 @@ unsafe impl WorldQuery for ChangeTrackers { } } +#[allow(deprecated)] /// SAFETY: access is read only unsafe impl ReadOnlyWorldQuery for ChangeTrackers {} diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index a067acbd89932..9b6a72ad2f6dc 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -572,7 +572,7 @@ impl_tick_filter!( /// A common use for this filter is one-time initialization. /// /// To retain all results without filtering but still check whether they were added after the - /// system last ran, use [`ChangeTrackers`](crate::query::ChangeTrackers). + /// system last ran, use [`Ref`](crate::change_detection::Ref). /// /// # Examples /// diff --git a/examples/ecs/component_change_detection.rs b/examples/ecs/component_change_detection.rs index 67d05f6fd04ca..8758e03c25792 100644 --- a/examples/ecs/component_change_detection.rs +++ b/examples/ecs/component_change_detection.rs @@ -1,6 +1,6 @@ //! This example illustrates how to react to component change. -use bevy::prelude::*; +use bevy::{ecs::world::Ref, prelude::*}; use rand::Rng; fn main() { @@ -43,15 +43,15 @@ fn change_detection(query: Query<(Entity, &MyComponent), Changed>) } } -// By looking at trackers, the query is not filtered but the information is available -fn tracker_monitoring( - query: Query<( - Entity, - Option<&MyComponent>, - Option>, - )>, -) { - for (entity, component, trackers) in &query { - info!("{:?}: {:?} -> {:?}", entity, component, trackers); +// By using `Ref`, the query is not filtered but the information is available +fn tracker_monitoring(query: Query<(Entity, Ref)>) { + for (entity, component) in &query { + info!( + "{:?}: {:?} -> {{is_added: {}, is_changed: {}}}", + entity, + component, + component.is_added(), + component.is_changed() + ); } }