Fix Sparse Change Detection (#6896)
# Objective #6547 accidentally broke change detection for SparseSet components by using `Ticks::from_tick_cells` with the wrong argument order. ## Solution Use the right argument order. Add a regression test.
This commit is contained in:
parent
a5d70b8952
commit
6308041772
@ -960,6 +960,90 @@ mod tests {
|
|||||||
assert_eq!(get_filtered::<Changed<B>>(&mut world), vec![e4]);
|
assert_eq!(get_filtered::<Changed<B>>(&mut world), vec![e4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn changed_trackers_sparse() {
|
||||||
|
let mut world = World::default();
|
||||||
|
let e1 = world.spawn(SparseStored(0)).id();
|
||||||
|
let e2 = world.spawn(SparseStored(0)).id();
|
||||||
|
let e3 = world.spawn(SparseStored(0)).id();
|
||||||
|
world.spawn(SparseStored(0));
|
||||||
|
|
||||||
|
world.clear_trackers();
|
||||||
|
|
||||||
|
for (i, mut a) in world
|
||||||
|
.query::<&mut SparseStored>()
|
||||||
|
.iter_mut(&mut world)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if i % 2 == 0 {
|
||||||
|
a.0 += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_filtered<F: ReadOnlyWorldQuery>(world: &mut World) -> Vec<Entity> {
|
||||||
|
world
|
||||||
|
.query_filtered::<Entity, F>()
|
||||||
|
.iter(world)
|
||||||
|
.collect::<Vec<Entity>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_filtered::<Changed<SparseStored>>(&mut world),
|
||||||
|
vec![e1, e3]
|
||||||
|
);
|
||||||
|
|
||||||
|
// ensure changing an entity's archetypes also moves its changed state
|
||||||
|
world.entity_mut(e1).insert(C);
|
||||||
|
|
||||||
|
assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
|
||||||
|
|
||||||
|
// spawning a new SparseStored entity should not change existing changed state
|
||||||
|
world.entity_mut(e1).insert(SparseStored(0));
|
||||||
|
assert_eq!(
|
||||||
|
get_filtered::<Changed<SparseStored>>(&mut world),
|
||||||
|
vec![e3, e1],
|
||||||
|
"changed entities list should not change"
|
||||||
|
);
|
||||||
|
|
||||||
|
// removing an unchanged entity should not change changed state
|
||||||
|
assert!(world.despawn(e2));
|
||||||
|
assert_eq!(
|
||||||
|
get_filtered::<Changed<SparseStored>>(&mut world),
|
||||||
|
vec![e3, e1],
|
||||||
|
"changed entities list should not change"
|
||||||
|
);
|
||||||
|
|
||||||
|
// removing a changed entity should remove it from enumeration
|
||||||
|
assert!(world.despawn(e1));
|
||||||
|
assert_eq!(
|
||||||
|
get_filtered::<Changed<SparseStored>>(&mut world),
|
||||||
|
vec![e3],
|
||||||
|
"e1 should no longer be returned"
|
||||||
|
);
|
||||||
|
|
||||||
|
world.clear_trackers();
|
||||||
|
|
||||||
|
assert!(get_filtered::<Changed<SparseStored>>(&mut world).is_empty());
|
||||||
|
|
||||||
|
let e4 = world.spawn_empty().id();
|
||||||
|
|
||||||
|
world.entity_mut(e4).insert(SparseStored(0));
|
||||||
|
assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
|
||||||
|
assert_eq!(get_filtered::<Added<SparseStored>>(&mut world), vec![e4]);
|
||||||
|
|
||||||
|
world.entity_mut(e4).insert(A(1));
|
||||||
|
assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
|
||||||
|
|
||||||
|
world.clear_trackers();
|
||||||
|
|
||||||
|
// ensure inserting multiple components set changed state for all components and set added
|
||||||
|
// state for non existing components even when changing archetype.
|
||||||
|
world.entity_mut(e4).insert(SparseStored(0));
|
||||||
|
|
||||||
|
assert!(get_filtered::<Added<SparseStored>>(&mut world).is_empty());
|
||||||
|
assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_spawn() {
|
fn empty_spawn() {
|
||||||
let mut world = World::default();
|
let mut world = World::default();
|
||||||
|
|||||||
@ -771,7 +771,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
.debug_checked_unwrap();
|
.debug_checked_unwrap();
|
||||||
Mut {
|
Mut {
|
||||||
value: component.assert_unique().deref_mut(),
|
value: component.assert_unique().deref_mut(),
|
||||||
ticks: Ticks::from_tick_cells(ticks, fetch.change_tick, fetch.last_change_tick),
|
ticks: Ticks::from_tick_cells(ticks, fetch.last_change_tick, fetch.change_tick),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user