Don't ignore default query filters for EntityRef
or EntityMut
(#20163)
# Objective Don't ignore default query filters for `EntityRef` or `EntityMut`. Currently, `Query<EntityRef>` will include entities with a `Disabled` component, even though queries like `Query<()>` or `Query<Entity>` would not. This was noticed in https://github.com/bevyengine/bevy/pull/19711#discussion_r2205981065. ## Solution Change `Access::contains` to completely ignore read access and just look at filters and archetypal access. Filters covers `With`, `Without`, `&`, and `&mut`, while archetypal covers `Has` and `Allows`. Note that `Option<&Disabled>` will no longer count as a use of `Disabled`, though.
This commit is contained in:
parent
9e1e8bc1bc
commit
25cb339a12
@ -205,7 +205,7 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::World,
|
prelude::{EntityMut, EntityRef, World},
|
||||||
query::{Has, With},
|
query::{Has, With},
|
||||||
};
|
};
|
||||||
use alloc::{vec, vec::Vec};
|
use alloc::{vec, vec::Vec};
|
||||||
@ -278,30 +278,42 @@ mod tests {
|
|||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.register_disabling_component::<CustomDisabled>();
|
world.register_disabling_component::<CustomDisabled>();
|
||||||
|
|
||||||
|
// Use powers of two so we can uniquely identify the set of matching archetypes from the count.
|
||||||
world.spawn_empty();
|
world.spawn_empty();
|
||||||
world.spawn(Disabled);
|
world.spawn_batch((0..2).map(|_| Disabled));
|
||||||
world.spawn(CustomDisabled);
|
world.spawn_batch((0..4).map(|_| CustomDisabled));
|
||||||
world.spawn((Disabled, CustomDisabled));
|
world.spawn_batch((0..8).map(|_| (Disabled, CustomDisabled)));
|
||||||
|
|
||||||
let mut query = world.query::<()>();
|
let mut query = world.query::<()>();
|
||||||
assert_eq!(1, query.iter(&world).count());
|
assert_eq!(1, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query_filtered::<(), With<Disabled>>();
|
let mut query = world.query::<EntityRef>();
|
||||||
assert_eq!(1, query.iter(&world).count());
|
assert_eq!(1, query.iter(&world).count());
|
||||||
|
|
||||||
|
let mut query = world.query::<EntityMut>();
|
||||||
|
assert_eq!(1, query.iter(&world).count());
|
||||||
|
|
||||||
|
let mut query = world.query_filtered::<(), With<Disabled>>();
|
||||||
|
assert_eq!(2, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query::<Has<Disabled>>();
|
let mut query = world.query::<Has<Disabled>>();
|
||||||
assert_eq!(2, query.iter(&world).count());
|
assert_eq!(3, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query_filtered::<(), With<CustomDisabled>>();
|
let mut query = world.query_filtered::<(), With<CustomDisabled>>();
|
||||||
assert_eq!(1, query.iter(&world).count());
|
assert_eq!(4, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query::<Has<CustomDisabled>>();
|
let mut query = world.query::<Has<CustomDisabled>>();
|
||||||
assert_eq!(2, query.iter(&world).count());
|
assert_eq!(5, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query_filtered::<(), (With<Disabled>, With<CustomDisabled>)>();
|
let mut query = world.query_filtered::<(), (With<Disabled>, With<CustomDisabled>)>();
|
||||||
assert_eq!(1, query.iter(&world).count());
|
assert_eq!(8, query.iter(&world).count());
|
||||||
|
|
||||||
let mut query = world.query::<(Has<Disabled>, Has<CustomDisabled>)>();
|
let mut query = world.query::<(Has<Disabled>, Has<CustomDisabled>)>();
|
||||||
assert_eq!(4, query.iter(&world).count());
|
assert_eq!(15, query.iter(&world).count());
|
||||||
|
|
||||||
|
// This seems like it ought to count as a mention of `Disabled`, but it does not.
|
||||||
|
// We don't consider read access, since that would count `EntityRef` as a mention of *all* components.
|
||||||
|
let mut query = world.query::<Option<&Disabled>>();
|
||||||
|
assert_eq!(1, query.iter(&world).count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1225,10 +1225,11 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
|
|||||||
.flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
|
.flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the index is used by this `FilteredAccess` in any way
|
/// Returns true if the index is used by this `FilteredAccess` in filters or archetypal access.
|
||||||
|
/// This includes most ways to access a component, but notably excludes `EntityRef` and `EntityMut`
|
||||||
|
/// along with anything inside `Option<T>`.
|
||||||
pub fn contains(&self, index: T) -> bool {
|
pub fn contains(&self, index: T) -> bool {
|
||||||
self.access().has_component_read(index.clone())
|
self.access().has_archetypal(index.clone())
|
||||||
|| self.access().has_archetypal(index.clone())
|
|
||||||
|| self.filter_sets.iter().any(|f| {
|
|| self.filter_sets.iter().any(|f| {
|
||||||
f.with.contains(index.sparse_set_index())
|
f.with.contains(index.sparse_set_index())
|
||||||
|| f.without.contains(index.sparse_set_index())
|
|| f.without.contains(index.sparse_set_index())
|
||||||
|
Loading…
Reference in New Issue
Block a user