Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Deprecate ChangeTrackers<T> in favor of Ref<T> #7306

Closed
wants to merge 12 commits into from
19 changes: 9 additions & 10 deletions crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -738,11 +737,11 @@ mod tests {

#[test]
fn change_expiration() {
fn change_detected(query: Query<ChangeTrackers<C>>) -> bool {
fn change_detected(query: Query<Ref<C>>) -> bool {
query.single().is_changed()
}

fn change_expired(query: Query<ChangeTrackers<C>>) -> bool {
fn change_expired(query: Query<Ref<C>>) -> bool {
query.single().is_changed()
}

Expand Down Expand Up @@ -773,7 +772,7 @@ mod tests {

#[test]
fn change_tick_wraparound() {
fn change_detected(query: Query<ChangeTrackers<C>>) -> bool {
fn change_detected(query: Query<Ref<C>>) -> bool {
query.single().is_changed()
}

Expand Down Expand Up @@ -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::<ChangeTrackers<C>>();
let mut query = world.query::<Ref<C>>();
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);
}
Expand All @@ -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);
}
Expand Down
14 changes: 9 additions & 5 deletions crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub use bevy_ptr as ptr;

/// Most commonly used re-exported types.
pub mod prelude {
#[allow(deprecated)]
pub use crate::query::ChangeTrackers;
#[doc(hidden)]
#[cfg(feature = "bevy_reflect")]
pub use crate::reflect::{ReflectComponent, ReflectResource};
Expand All @@ -33,7 +35,7 @@ pub mod prelude {
component::Component,
entity::Entity,
event::{EventReader, EventWriter, Events},
query::{Added, AnyOf, ChangeTrackers, Changed, Or, QueryState, With, Without},
query::{Added, AnyOf, Changed, Or, QueryState, With, Without},
schedule::{
IntoSystemDescriptor, RunCriteria, RunCriteriaDescriptorCoercion, RunCriteriaLabel,
Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage,
Expand All @@ -56,11 +58,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},
};
Expand Down Expand Up @@ -1290,7 +1291,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));
Expand Down Expand Up @@ -1534,7 +1538,7 @@ mod tests {
assert_eq!(1, query_min_size![&B, (With<A>, With<C>)],);
assert_eq!(1, query_min_size![(&A, &B), With<C>],);
assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal");
assert_eq!(4, query_min_size![ChangeTrackers<A>, ()],);
assert_eq!(4, query_min_size![Ref<A>, ()],);
// All the following should set minimum size to 0, as it's impossible to predict
// how many entites the filters will trim.
assert_eq!(0, query_min_size![(), Added<A>], "Simple Added");
Expand Down
15 changes: 9 additions & 6 deletions crates/bevy_ecs/src/query/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,25 +1115,25 @@ unsafe impl<T: ReadOnlyWorldQuery> ReadOnlyWorldQuery for Option<T> {}
/// }
/// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
/// ```
#[deprecated = "`ChangeTrackers<T>` will be removed in bevy 0.11. Use `bevy_ecs::prelude::Ref<T>` instead."]
pub struct ChangeTrackers<T: Component> {
pub(crate) component_ticks: ComponentTicks,
pub(crate) last_change_tick: u32,
pub(crate) change_tick: u32,
marker: PhantomData<T>,
}

#[allow(deprecated)]
impl<T: Component> Clone for ChangeTrackers<T> {
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<T: Component> Copy for ChangeTrackers<T> {}

#[allow(deprecated)]
impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChangeTrackers")
Expand All @@ -1144,6 +1144,7 @@ impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
}
}

#[allow(deprecated)]
impl<T: Component> ChangeTrackers<T> {
/// Returns true if this component has been added since the last execution of this system.
pub fn is_added(&self) -> bool {
Expand Down Expand Up @@ -1171,6 +1172,7 @@ pub struct ChangeTrackersFetch<'w, T> {
change_tick: u32,
}

#[allow(deprecated)]
// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
type Fetch<'w> = ChangeTrackersFetch<'w, T>;
Expand Down Expand Up @@ -1317,6 +1319,7 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
}
}

#[allow(deprecated)]
/// SAFETY: access is read only
unsafe impl<T: Component> ReadOnlyWorldQuery for ChangeTrackers<T> {}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/query/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>`](crate::query::ChangeTrackers).
/// system last ran, use [`Ref<T>`](crate::change_detection::Ref).
///
/// # Examples
///
Expand Down
22 changes: 11 additions & 11 deletions examples/ecs/component_change_detection.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -43,15 +43,15 @@ fn change_detection(query: Query<(Entity, &MyComponent), Changed<MyComponent>>)
}
}

// By looking at trackers, the query is not filtered but the information is available
fn tracker_monitoring(
query: Query<(
Entity,
Option<&MyComponent>,
Option<ChangeTrackers<MyComponent>>,
)>,
) {
for (entity, component, trackers) in &query {
info!("{:?}: {:?} -> {:?}", entity, component, trackers);
// By using `Ref`, the query is not filtered but the information is available
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems incorrect. I'm not sure that it was ever correct however.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the original intended meaning is that the query is not filtered based on change detection, but you can still access the change detection info. I tried to preserve that meaning when rewriting this section of code.

fn tracker_monitoring(query: Query<(Entity, Ref<MyComponent>)>) {
for (entity, component) in &query {
info!(
"{:?}: {:?} -> {{is_added: {}, is_changed: {}}}",
entity,
component,
component.is_added(),
component.is_changed()
);
}
}