@@ -3,6 +3,7 @@ use crate::{
3
3
batching:: BatchingStrategy ,
4
4
component:: { ComponentId , Tick } ,
5
5
entity:: { Entity , EntityBorrow , EntitySet } ,
6
+ entity_disabling:: DefaultQueryFilters ,
6
7
prelude:: FromWorld ,
7
8
query:: {
8
9
Access , DebugCheckedUnwrap , FilteredAccess , QueryCombinationIter , QueryIter , QueryParIter ,
@@ -214,7 +215,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
214
215
fn new_uninitialized ( world : & mut World ) -> Self {
215
216
let fetch_state = D :: init_state ( world) ;
216
217
let filter_state = F :: init_state ( world) ;
217
- Self :: from_states_uninitialized ( world. id ( ) , fetch_state, filter_state)
218
+ Self :: from_states_uninitialized ( world, fetch_state, filter_state)
218
219
}
219
220
220
221
/// Creates a new [`QueryState`] but does not populate it with the matched results from the World yet
@@ -225,7 +226,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
225
226
let fetch_state = D :: get_state ( world. components ( ) ) ?;
226
227
let filter_state = F :: get_state ( world. components ( ) ) ?;
227
228
Some ( Self :: from_states_uninitialized (
228
- world. id ( ) ,
229
+ world,
229
230
fetch_state,
230
231
filter_state,
231
232
) )
@@ -236,7 +237,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
236
237
/// `new_archetype` and its variants must be called on all of the World's archetypes before the
237
238
/// state can return valid query results.
238
239
fn from_states_uninitialized (
239
- world_id : WorldId ,
240
+ world : & World ,
240
241
fetch_state : <D as WorldQuery >:: State ,
241
242
filter_state : <F as WorldQuery >:: State ,
242
243
) -> Self {
@@ -255,10 +256,15 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
255
256
256
257
// For queries without dynamic filters the dense-ness of the query is equal to the dense-ness
257
258
// of its static type parameters.
258
- let is_dense = D :: IS_DENSE && F :: IS_DENSE ;
259
+ let mut is_dense = D :: IS_DENSE && F :: IS_DENSE ;
260
+
261
+ if let Some ( default_filters) = world. get_resource :: < DefaultQueryFilters > ( ) {
262
+ default_filters. apply ( & mut component_access) ;
263
+ is_dense &= default_filters. is_dense ( world. components ( ) ) ;
264
+ }
259
265
260
266
Self {
261
- world_id,
267
+ world_id : world . id ( ) ,
262
268
archetype_generation : ArchetypeGeneration :: initial ( ) ,
263
269
matched_storage_ids : Vec :: new ( ) ,
264
270
is_dense,
@@ -282,15 +288,24 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
282
288
let filter_state = F :: init_state ( builder. world_mut ( ) ) ;
283
289
D :: set_access ( & mut fetch_state, builder. access ( ) ) ;
284
290
291
+ let mut component_access = builder. access ( ) . clone ( ) ;
292
+
293
+ // For dynamic queries the dense-ness is given by the query builder.
294
+ let mut is_dense = builder. is_dense ( ) ;
295
+
296
+ if let Some ( default_filters) = builder. world ( ) . get_resource :: < DefaultQueryFilters > ( ) {
297
+ default_filters. apply ( & mut component_access) ;
298
+ is_dense &= default_filters. is_dense ( builder. world ( ) . components ( ) ) ;
299
+ }
300
+
285
301
let mut state = Self {
286
302
world_id : builder. world ( ) . id ( ) ,
287
303
archetype_generation : ArchetypeGeneration :: initial ( ) ,
288
304
matched_storage_ids : Vec :: new ( ) ,
289
- // For dynamic queries the dense-ness is given by the query builder.
290
- is_dense : builder. is_dense ( ) ,
305
+ is_dense,
291
306
fetch_state,
292
307
filter_state,
293
- component_access : builder . access ( ) . clone ( ) ,
308
+ component_access,
294
309
matched_tables : Default :: default ( ) ,
295
310
matched_archetypes : Default :: default ( ) ,
296
311
#[ cfg( feature = "trace" ) ]
@@ -1880,7 +1895,8 @@ impl<D: QueryData, F: QueryFilter> From<QueryBuilder<'_, D, F>> for QueryState<D
1880
1895
mod tests {
1881
1896
use crate as bevy_ecs;
1882
1897
use crate :: {
1883
- component:: Component , prelude:: * , query:: QueryEntityError , world:: FilteredEntityRef ,
1898
+ component:: Component , entity_disabling:: DefaultQueryFilters , prelude:: * ,
1899
+ query:: QueryEntityError , world:: FilteredEntityRef ,
1884
1900
} ;
1885
1901
use alloc:: vec:: Vec ;
1886
1902
@@ -2314,4 +2330,76 @@ mod tests {
2314
2330
let query_2 = QueryState :: < & B , Without < C > > :: new ( & mut world) ;
2315
2331
let _: QueryState < Entity , Changed < C > > = query_1. join_filtered ( & world, & query_2) ;
2316
2332
}
2333
+
2334
+ #[ test]
2335
+ fn query_respects_default_filters ( ) {
2336
+ let mut world = World :: new ( ) ;
2337
+ world. spawn ( ( A ( 0 ) , B ( 0 ) ) ) ;
2338
+ world. spawn ( ( B ( 0 ) , C ( 0 ) ) ) ;
2339
+ world. spawn ( C ( 0 ) ) ;
2340
+
2341
+ let mut df = DefaultQueryFilters :: default ( ) ;
2342
+ df. set_disabled ( world. register_component :: < C > ( ) ) ;
2343
+ world. insert_resource ( df) ;
2344
+
2345
+ // Without<C> only matches the first entity
2346
+ let mut query = QueryState :: < ( ) > :: new ( & mut world) ;
2347
+ assert_eq ! ( 1 , query. iter( & world) . count( ) ) ;
2348
+
2349
+ // With<C> matches the last two entities
2350
+ let mut query = QueryState :: < ( ) , With < C > > :: new ( & mut world) ;
2351
+ assert_eq ! ( 2 , query. iter( & world) . count( ) ) ;
2352
+
2353
+ // Has should bypass the filter entirely
2354
+ let mut query = QueryState :: < Has < C > > :: new ( & mut world) ;
2355
+ assert_eq ! ( 3 , query. iter( & world) . count( ) ) ;
2356
+
2357
+ // Other filters should still be respected
2358
+ let mut query = QueryState :: < Has < C > , Without < B > > :: new ( & mut world) ;
2359
+ assert_eq ! ( 1 , query. iter( & world) . count( ) ) ;
2360
+ }
2361
+
2362
+ #[ derive( Component ) ]
2363
+ struct Table ;
2364
+
2365
+ #[ derive( Component ) ]
2366
+ #[ component( storage = "SparseSet" ) ]
2367
+ struct Sparse ;
2368
+
2369
+ #[ test]
2370
+ fn query_default_filters_updates_is_dense ( ) {
2371
+ let mut world = World :: new ( ) ;
2372
+ world. spawn ( ( Table , Sparse ) ) ;
2373
+ world. spawn ( Table ) ;
2374
+ world. spawn ( Sparse ) ;
2375
+
2376
+ let mut query = QueryState :: < ( ) > :: new ( & mut world) ;
2377
+ // There are no sparse components involved thus the query is dense
2378
+ assert ! ( query. is_dense) ;
2379
+ assert_eq ! ( 3 , query. iter( & world) . count( ) ) ;
2380
+
2381
+ let mut df = DefaultQueryFilters :: default ( ) ;
2382
+ df. set_disabled ( world. register_component :: < Sparse > ( ) ) ;
2383
+ world. insert_resource ( df) ;
2384
+
2385
+ let mut query = QueryState :: < ( ) > :: new ( & mut world) ;
2386
+ // The query doesn't ask for sparse components, but the default filters adds
2387
+ // a sparse components thus it is NOT dense
2388
+ assert ! ( !query. is_dense) ;
2389
+ assert_eq ! ( 1 , query. iter( & world) . count( ) ) ;
2390
+
2391
+ let mut df = DefaultQueryFilters :: default ( ) ;
2392
+ df. set_disabled ( world. register_component :: < Table > ( ) ) ;
2393
+ world. insert_resource ( df) ;
2394
+
2395
+ let mut query = QueryState :: < ( ) > :: new ( & mut world) ;
2396
+ // If the filter is instead a table components, the query can still be dense
2397
+ assert ! ( query. is_dense) ;
2398
+ assert_eq ! ( 1 , query. iter( & world) . count( ) ) ;
2399
+
2400
+ let mut query = QueryState :: < & Sparse > :: new ( & mut world) ;
2401
+ // But only if the original query was dense
2402
+ assert ! ( !query. is_dense) ;
2403
+ assert_eq ! ( 1 , query. iter( & world) . count( ) ) ;
2404
+ }
2317
2405
}
0 commit comments