bevy_ecs/query/filter.rs
1use crate::{
2 archetype::Archetype,
3 change_detection::Tick,
4 component::{Component, ComponentId, Components, StorageType},
5 entity::{Entities, Entity},
6 query::{DebugCheckedUnwrap, FilteredAccess, FilteredAccessSet, StorageSwitch, WorldQuery},
7 storage::{ComponentSparseSet, Table, TableRow},
8 world::{unsafe_world_cell::UnsafeWorldCell, World},
9};
10use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
11use bevy_utils::prelude::DebugName;
12use core::{cell::UnsafeCell, marker::PhantomData};
13use variadics_please::all_tuples;
14
15/// Types that filter the results of a [`Query`].
16///
17/// There are many types that natively implement this trait:
18/// - **Component filters.**
19/// [`With`] and [`Without`] filters can be applied to check if the queried entity does or does not contain a particular component.
20/// - **Change detection filters.**
21/// [`Added`] and [`Changed`] filters can be applied to detect component changes to an entity.
22/// - **Spawned filter.**
23/// [`Spawned`] filter can be applied to check if the queried entity was spawned recently.
24/// - **`QueryFilter` tuples.**
25/// If every element of a tuple implements `QueryFilter`, then the tuple itself also implements the same trait.
26/// This enables a single `Query` to filter over multiple conditions.
27/// Due to the current lack of variadic generics in Rust, the trait has been implemented for tuples from 0 to 15 elements,
28/// but nesting of tuples allows infinite `QueryFilter`s.
29/// - **Filter disjunction operator.**
30/// By default, tuples compose query filters in such a way that all conditions must be satisfied to generate a query item for a given entity.
31/// Wrapping a tuple inside an [`Or`] operator will relax the requirement to just one condition.
32///
33/// Implementing the trait manually can allow for a fundamentally new type of behavior.
34///
35/// Query design can be easily structured by deriving `QueryFilter` for custom types.
36/// Despite the added complexity, this approach has several advantages over using `QueryFilter` tuples.
37/// The most relevant improvements are:
38///
39/// - Reusability across multiple systems.
40/// - Filters can be composed together to create a more complex filter.
41///
42/// This trait can only be derived for structs if each field also implements `QueryFilter`.
43///
44/// ```
45/// # use bevy_ecs::prelude::*;
46/// # use bevy_ecs::{query::QueryFilter, component::Component};
47/// #
48/// # #[derive(Component)]
49/// # struct ComponentA;
50/// # #[derive(Component)]
51/// # struct ComponentB;
52/// # #[derive(Component)]
53/// # struct ComponentC;
54/// # #[derive(Component)]
55/// # struct ComponentD;
56/// # #[derive(Component)]
57/// # struct ComponentE;
58/// #
59/// #[derive(QueryFilter)]
60/// struct MyFilter<T: Component, P: Component> {
61/// // Field names are not relevant, since they are never manually accessed.
62/// with_a: With<ComponentA>,
63/// or_filter: Or<(With<ComponentC>, Added<ComponentB>)>,
64/// generic_tuple: (With<T>, Without<P>),
65/// }
66///
67/// fn my_system(query: Query<Entity, MyFilter<ComponentD, ComponentE>>) {
68/// // ...
69/// }
70/// # bevy_ecs::system::assert_is_system(my_system);
71/// ```
72///
73/// [`Query`]: crate::system::Query
74///
75/// # Safety
76///
77/// The [`WorldQuery`] implementation must not take any mutable access.
78/// This is the same safety requirement as [`ReadOnlyQueryData`](crate::query::ReadOnlyQueryData).
79#[diagnostic::on_unimplemented(
80 message = "`{Self}` is not a valid `Query` filter",
81 label = "invalid `Query` filter",
82 note = "a `QueryFilter` typically uses a combination of `With<T>` and `Without<T>` statements"
83)]
84pub unsafe trait QueryFilter: WorldQuery {
85 /// Returns true if (and only if) this Filter relies strictly on archetypes to limit which
86 /// components are accessed by the Query.
87 ///
88 /// This enables optimizations for [`QueryIter`](`crate::query::QueryIter`) that rely on knowing exactly how
89 /// many elements are being iterated (such as `Iterator::collect()`).
90 ///
91 /// If this is `true`, then [`QueryFilter::filter_fetch`] must always return true.
92 const IS_ARCHETYPAL: bool;
93
94 /// Returns true if the provided [`Entity`] and [`TableRow`] should be included in the query results.
95 /// If false, the entity will be skipped.
96 ///
97 /// Note that this is called after already restricting the matched [`Table`]s and [`Archetype`]s to the
98 /// ones that are compatible with the Filter's access.
99 ///
100 /// Implementors of this method will generally either have a trivial `true` body (required for archetypal filters),
101 /// or access the necessary data within this function to make the final decision on filter inclusion.
102 ///
103 /// # Safety
104 ///
105 /// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
106 /// `table_row` must be in the range of the current table and archetype.
107 unsafe fn filter_fetch(
108 state: &Self::State,
109 fetch: &mut Self::Fetch<'_>,
110 entity: Entity,
111 table_row: TableRow,
112 ) -> bool;
113}
114
115/// Filter that selects entities with a component `T`.
116///
117/// This can be used in a [`Query`](crate::system::Query) if entities are required to have the
118/// component `T` but you don't actually care about components value.
119///
120/// This is the negation of [`Without`].
121///
122/// # Examples
123///
124/// ```
125/// # use bevy_ecs::component::Component;
126/// # use bevy_ecs::query::With;
127/// # use bevy_ecs::system::IntoSystem;
128/// # use bevy_ecs::system::Query;
129/// #
130/// # #[derive(Component)]
131/// # struct IsBeautiful;
132/// # #[derive(Component)]
133/// # struct Name { name: &'static str };
134/// #
135/// fn compliment_entity_system(query: Query<&Name, With<IsBeautiful>>) {
136/// for name in &query {
137/// println!("{} is looking lovely today!", name.name);
138/// }
139/// }
140/// # bevy_ecs::system::assert_is_system(compliment_entity_system);
141/// ```
142pub struct With<T>(PhantomData<T>);
143
144// SAFETY:
145// `update_component_access` does not add any accesses.
146// This is sound because [`QueryFilter::filter_fetch`] does not access any components.
147// `update_component_access` adds a `With` filter for `T`.
148// This is sound because `matches_component_set` returns whether the set contains the component.
149unsafe impl<T: Component> WorldQuery for With<T> {
150 type Fetch<'w> = ();
151 type State = ComponentId;
152
153 fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
154
155 #[inline]
156 unsafe fn init_fetch(
157 _world: UnsafeWorldCell,
158 _state: &ComponentId,
159 _last_run: Tick,
160 _this_run: Tick,
161 ) {
162 }
163
164 const IS_DENSE: bool = {
165 match T::STORAGE_TYPE {
166 StorageType::Table => true,
167 StorageType::SparseSet => false,
168 }
169 };
170
171 #[inline]
172 unsafe fn set_archetype(
173 _fetch: &mut (),
174 _state: &ComponentId,
175 _archetype: &Archetype,
176 _table: &Table,
177 ) {
178 }
179
180 #[inline]
181 unsafe fn set_table(_fetch: &mut (), _state: &ComponentId, _table: &Table) {}
182
183 #[inline]
184 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
185 access.and_with(id);
186 }
187
188 fn init_nested_access(
189 _state: &Self::State,
190 _system_name: Option<&str>,
191 _component_access_set: &mut FilteredAccessSet,
192 _world: UnsafeWorldCell,
193 ) {
194 }
195
196 fn init_state(world: &mut World) -> ComponentId {
197 world.register_component::<T>()
198 }
199
200 fn get_state(components: &Components) -> Option<Self::State> {
201 components.component_id::<T>()
202 }
203
204 fn matches_component_set(
205 &id: &ComponentId,
206 set_contains_id: &impl Fn(ComponentId) -> bool,
207 ) -> bool {
208 set_contains_id(id)
209 }
210
211 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
212}
213
214// SAFETY: WorldQuery impl performs no access at all
215unsafe impl<T: Component> QueryFilter for With<T> {
216 const IS_ARCHETYPAL: bool = true;
217
218 #[inline(always)]
219 unsafe fn filter_fetch(
220 _state: &Self::State,
221 _fetch: &mut Self::Fetch<'_>,
222 _entity: Entity,
223 _table_row: TableRow,
224 ) -> bool {
225 true
226 }
227}
228
229/// Filter that selects entities without a component `T`.
230///
231/// This is the negation of [`With`].
232///
233/// # Examples
234///
235/// ```
236/// # use bevy_ecs::component::Component;
237/// # use bevy_ecs::query::Without;
238/// # use bevy_ecs::system::IntoSystem;
239/// # use bevy_ecs::system::Query;
240/// #
241/// # #[derive(Component)]
242/// # struct Permit;
243/// # #[derive(Component)]
244/// # struct Name { name: &'static str };
245/// #
246/// fn no_permit_system(query: Query<&Name, Without<Permit>>) {
247/// for name in &query{
248/// println!("{} has no permit!", name.name);
249/// }
250/// }
251/// # bevy_ecs::system::assert_is_system(no_permit_system);
252/// ```
253pub struct Without<T>(PhantomData<T>);
254
255// SAFETY:
256// `update_component_access` does not add any accesses.
257// This is sound because [`QueryFilter::filter_fetch`] does not access any components.
258// `update_component_access` adds a `Without` filter for `T`.
259// This is sound because `matches_component_set` returns whether the set does not contain the component.
260unsafe impl<T: Component> WorldQuery for Without<T> {
261 type Fetch<'w> = ();
262 type State = ComponentId;
263
264 fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
265
266 #[inline]
267 unsafe fn init_fetch(
268 _world: UnsafeWorldCell,
269 _state: &ComponentId,
270 _last_run: Tick,
271 _this_run: Tick,
272 ) {
273 }
274
275 const IS_DENSE: bool = {
276 match T::STORAGE_TYPE {
277 StorageType::Table => true,
278 StorageType::SparseSet => false,
279 }
280 };
281
282 #[inline]
283 unsafe fn set_archetype(
284 _fetch: &mut (),
285 _state: &ComponentId,
286 _archetype: &Archetype,
287 _table: &Table,
288 ) {
289 }
290
291 #[inline]
292 unsafe fn set_table(_fetch: &mut (), _state: &Self::State, _table: &Table) {}
293
294 #[inline]
295 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
296 access.and_without(id);
297 }
298
299 fn init_nested_access(
300 _state: &Self::State,
301 _system_name: Option<&str>,
302 _component_access_set: &mut FilteredAccessSet,
303 _world: UnsafeWorldCell,
304 ) {
305 }
306
307 fn init_state(world: &mut World) -> ComponentId {
308 world.register_component::<T>()
309 }
310
311 fn get_state(components: &Components) -> Option<Self::State> {
312 components.component_id::<T>()
313 }
314
315 fn matches_component_set(
316 &id: &ComponentId,
317 set_contains_id: &impl Fn(ComponentId) -> bool,
318 ) -> bool {
319 !set_contains_id(id)
320 }
321
322 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
323}
324
325// SAFETY: WorldQuery impl performs no access at all
326unsafe impl<T: Component> QueryFilter for Without<T> {
327 const IS_ARCHETYPAL: bool = true;
328
329 #[inline(always)]
330 unsafe fn filter_fetch(
331 _state: &Self::State,
332 _fetch: &mut Self::Fetch<'_>,
333 _entity: Entity,
334 _table_row: TableRow,
335 ) -> bool {
336 true
337 }
338}
339
340/// A filter that tests if any of the given filters apply.
341///
342/// This is useful for example if a system with multiple components in a query only wants to run
343/// when one or more of the components have changed.
344///
345/// The `And` equivalent to this filter is a [`prim@tuple`] testing that all the contained filters
346/// apply instead.
347///
348/// # Examples
349///
350/// ```
351/// # use bevy_ecs::component::Component;
352/// # use bevy_ecs::entity::Entity;
353/// # use bevy_ecs::query::Changed;
354/// # use bevy_ecs::query::Or;
355/// # use bevy_ecs::system::IntoSystem;
356/// # use bevy_ecs::system::Query;
357/// #
358/// # #[derive(Component, Debug)]
359/// # struct Color {};
360/// # #[derive(Component)]
361/// # struct Node {};
362/// #
363/// fn print_cool_entity_system(query: Query<Entity, Or<(Changed<Color>, Changed<Node>)>>) {
364/// for entity in &query {
365/// println!("Entity {} got a new style or color", entity);
366/// }
367/// }
368/// # bevy_ecs::system::assert_is_system(print_cool_entity_system);
369/// ```
370pub struct Or<T>(PhantomData<T>);
371
372#[doc(hidden)]
373pub struct OrFetch<'w, T: WorldQuery> {
374 fetch: T::Fetch<'w>,
375 matches: bool,
376}
377
378impl<T: WorldQuery> Clone for OrFetch<'_, T> {
379 fn clone(&self) -> Self {
380 Self {
381 fetch: self.fetch.clone(),
382 matches: self.matches,
383 }
384 }
385}
386
387macro_rules! impl_or_query_filter {
388 ($(#[$meta:meta])* $(($filter: ident, $state: ident)),*) => {
389 $(#[$meta])*
390 #[expect(
391 clippy::allow_attributes,
392 reason = "This is a tuple-related macro; as such the lints below may not always apply."
393 )]
394 #[allow(
395 non_snake_case,
396 reason = "The names of some variables are provided by the macro's caller, not by us."
397 )]
398 #[allow(
399 unused_variables,
400 reason = "Zero-length tuples won't use any of the parameters."
401 )]
402 #[allow(
403 clippy::unused_unit,
404 reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
405 )]
406 // SAFETY:
407 // [`QueryFilter::filter_fetch`] accesses are a subset of the subqueries' accesses
408 // This is sound because `update_component_access` adds accesses according to the implementations of all the subqueries.
409 // `update_component_access` replace the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries.
410 // This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations.
411 unsafe impl<$($filter: QueryFilter),*> WorldQuery for Or<($($filter,)*)> {
412 type Fetch<'w> = ($(OrFetch<'w, $filter>,)*);
413 type State = ($($filter::State,)*);
414
415 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
416 let ($($filter,)*) = fetch;
417 ($(
418 OrFetch {
419 fetch: $filter::shrink_fetch($filter.fetch),
420 matches: $filter.matches
421 },
422 )*)
423 }
424
425 const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*;
426
427 #[inline]
428 unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> {
429 let ($($filter,)*) = state;
430 ($(OrFetch {
431 // SAFETY: The invariants are upheld by the caller.
432 fetch: unsafe { $filter::init_fetch(world, $filter, last_run, this_run) },
433 matches: false,
434 },)*)
435 }
436
437 #[inline]
438 unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, table: &'w Table) {
439 // If this is an archetypal query, then it is guaranteed to match all entities,
440 // so `filter_fetch` will ignore `$filter.matches` and we don't need to initialize it.
441 if Self::IS_ARCHETYPAL {
442 return;
443 }
444 let ($($filter,)*) = fetch;
445 let ($($state,)*) = state;
446 $(
447 $filter.matches = $filter::matches_component_set($state, &|id| table.has_column(id));
448 if $filter.matches {
449 // SAFETY: The invariants are upheld by the caller.
450 unsafe { $filter::set_table(&mut $filter.fetch, $state, table); }
451 }
452 )*
453 }
454
455 #[inline]
456 unsafe fn set_archetype<'w, 's>(
457 fetch: &mut Self::Fetch<'w>,
458 state: &'s Self::State,
459 archetype: &'w Archetype,
460 table: &'w Table
461 ) {
462 // If this is an archetypal query, then it is guaranteed to match all entities,
463 // so `filter_fetch` will ignore `$filter.matches` and we don't need to initialize it.
464 if Self::IS_ARCHETYPAL {
465 return;
466 }
467 let ($($filter,)*) = fetch;
468 let ($($state,)*) = &state;
469 $(
470 $filter.matches = $filter::matches_component_set($state, &|id| archetype.contains(id));
471 if $filter.matches {
472 // SAFETY: The invariants are upheld by the caller.
473 unsafe { $filter::set_archetype(&mut $filter.fetch, $state, archetype, table); }
474 }
475 )*
476 }
477
478 fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
479 let ($($filter,)*) = state;
480
481 let mut new_access = FilteredAccess::matches_nothing();
482
483 $(
484 // Create an intermediate because `access`'s value needs to be preserved
485 // for the next filter, and `_new_access` has to be modified only by `append_or` to it.
486 let mut intermediate = access.clone();
487 $filter::update_component_access($filter, &mut intermediate);
488 new_access.append_or(&intermediate);
489 // Also extend the accesses required to compute the filter. This is required because
490 // otherwise a `Query<(), Or<(Changed<Foo>,)>` won't conflict with `Query<&mut Foo>`.
491 new_access.extend_access(&intermediate);
492 )*
493
494 // The required components remain the same as the original `access`.
495 new_access.required = core::mem::take(&mut access.required);
496
497 *access = new_access;
498 }
499
500 fn init_nested_access(
501 state: &Self::State,
502 _system_name: Option<&str>,
503 _component_access_set: &mut FilteredAccessSet,
504 _world: UnsafeWorldCell,
505 ) {
506 let ($($state,)*) = state;
507 $($filter::init_nested_access($state, _system_name, _component_access_set, _world);)*
508 }
509
510 fn init_state(world: &mut World) -> Self::State {
511 ($($filter::init_state(world),)*)
512 }
513
514 fn get_state(components: &Components) -> Option<Self::State> {
515 Some(($($filter::get_state(components)?,)*))
516 }
517
518 fn matches_component_set(state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
519 let ($($filter,)*) = state;
520 false $(|| $filter::matches_component_set($filter, set_contains_id))*
521 }
522
523 fn update_archetypes(state: &mut Self::State, _world: UnsafeWorldCell) {
524 let ($($filter,)*) = state;
525 $($filter::update_archetypes($filter, _world);)*
526 }
527 }
528
529 #[expect(
530 clippy::allow_attributes,
531 reason = "This is a tuple-related macro; as such the lints below may not always apply."
532 )]
533 #[allow(
534 non_snake_case,
535 reason = "The names of some variables are provided by the macro's caller, not by us."
536 )]
537 #[allow(
538 unused_variables,
539 reason = "Zero-length tuples won't use any of the parameters."
540 )]
541 $(#[$meta])*
542 // SAFETY: This only performs access that subqueries perform, and they impl `QueryFilter` and so perform no mutable access.
543 unsafe impl<$($filter: QueryFilter),*> QueryFilter for Or<($($filter,)*)> {
544 const IS_ARCHETYPAL: bool = true $(&& $filter::IS_ARCHETYPAL)*;
545
546 #[inline(always)]
547 unsafe fn filter_fetch(
548 state: &Self::State,
549 fetch: &mut Self::Fetch<'_>,
550 entity: Entity,
551 table_row: TableRow
552 ) -> bool {
553 let ($($state,)*) = state;
554 let ($($filter,)*) = fetch;
555 // If this is an archetypal query, then it is guaranteed to return true,
556 // and we can help the compiler remove branches by checking the const `IS_ARCHETYPAL` first.
557 (Self::IS_ARCHETYPAL
558 // SAFETY: The invariants are upheld by the caller.
559 $(|| ($filter.matches && unsafe { $filter::filter_fetch($state, &mut $filter.fetch, entity, table_row) }))*
560 // If *none* of the subqueries matched the archetype, then this archetype was added in a transmute.
561 // We must treat those as matching in order to be consistent with `size_hint` for archetypal queries,
562 // so we treat them as matching for non-archetypal queries, as well.
563 || !(false $(|| $filter.matches)*))
564 }
565 }
566 };
567}
568
569macro_rules! impl_tuple_query_filter {
570 ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => {
571 #[expect(
572 clippy::allow_attributes,
573 reason = "This is a tuple-related macro; as such the lints below may not always apply."
574 )]
575 #[allow(
576 non_snake_case,
577 reason = "The names of some variables are provided by the macro's caller, not by us."
578 )]
579 #[allow(
580 unused_variables,
581 reason = "Zero-length tuples won't use any of the parameters."
582 )]
583 $(#[$meta])*
584 // SAFETY: This only performs access that subqueries perform, and they impl `QueryFilter` and so perform no mutable access.
585 unsafe impl<$($name: QueryFilter),*> QueryFilter for ($($name,)*) {
586 const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
587
588 #[inline(always)]
589 unsafe fn filter_fetch(
590 state: &Self::State,
591 fetch: &mut Self::Fetch<'_>,
592 entity: Entity,
593 table_row: TableRow
594 ) -> bool {
595 let ($($state,)*) = state;
596 let ($($name,)*) = fetch;
597 // SAFETY: The invariants are upheld by the caller.
598 true $(&& unsafe { $name::filter_fetch($state, $name, entity, table_row) })*
599 }
600 }
601 };
602}
603
604all_tuples!(
605 #[doc(fake_variadic)]
606 impl_tuple_query_filter,
607 0,
608 15,
609 F,
610 S
611);
612all_tuples!(
613 #[doc(fake_variadic)]
614 impl_or_query_filter,
615 0,
616 15,
617 F,
618 S
619);
620
621/// Allows a query to contain entities with the component `T`, bypassing [`DefaultQueryFilters`].
622///
623/// [`DefaultQueryFilters`]: crate::entity_disabling::DefaultQueryFilters
624pub struct Allow<T>(PhantomData<T>);
625
626// SAFETY:
627// `update_component_access` does not add any accesses.
628// This is sound because [`QueryFilter::filter_fetch`] does not access any components.
629// `update_component_access` adds an archetypal filter for `T`.
630// This is sound because it doesn't affect the query
631unsafe impl<T: Component> WorldQuery for Allow<T> {
632 type Fetch<'w> = ();
633 type State = ComponentId;
634
635 fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
636
637 #[inline]
638 unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {}
639
640 // Even if the component is sparse, this implementation doesn't do anything with it
641 const IS_DENSE: bool = true;
642
643 #[inline]
644 unsafe fn set_archetype(_: &mut (), _: &ComponentId, _: &Archetype, _: &Table) {}
645
646 #[inline]
647 unsafe fn set_table(_: &mut (), _: &ComponentId, _: &Table) {}
648
649 #[inline]
650 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
651 access.access_mut().add_archetypal(id);
652 }
653
654 fn init_nested_access(
655 _state: &Self::State,
656 _system_name: Option<&str>,
657 _component_access_set: &mut FilteredAccessSet,
658 _world: UnsafeWorldCell,
659 ) {
660 }
661
662 fn init_state(world: &mut World) -> ComponentId {
663 world.register_component::<T>()
664 }
665
666 fn get_state(components: &Components) -> Option<Self::State> {
667 components.component_id::<T>()
668 }
669
670 fn matches_component_set(_: &ComponentId, _: &impl Fn(ComponentId) -> bool) -> bool {
671 // Allow<T> always matches
672 true
673 }
674
675 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
676}
677
678// SAFETY: WorldQuery impl performs no access at all
679unsafe impl<T: Component> QueryFilter for Allow<T> {
680 const IS_ARCHETYPAL: bool = true;
681
682 #[inline(always)]
683 unsafe fn filter_fetch(
684 _: &Self::State,
685 _: &mut Self::Fetch<'_>,
686 _: Entity,
687 _: TableRow,
688 ) -> bool {
689 true
690 }
691}
692
693/// A filter on a component that only retains results the first time after they have been added.
694///
695/// A common use for this filter is one-time initialization.
696///
697/// To retain all results without filtering but still check whether they were added after the
698/// system last ran, use [`Ref<T>`](crate::change_detection::Ref).
699///
700/// **Note** that this includes changes that happened before the first time this `Query` was run.
701///
702/// # Deferred
703///
704/// Note, that entity modifications issued with [`Commands`](crate::system::Commands)
705/// are visible only after deferred operations are applied, typically after the system
706/// that queued them.
707///
708/// # Time complexity
709///
710/// `Added` is not [`ArchetypeFilter`], which practically means that
711/// if the query (with `T` component filter) matches a million entities,
712/// `Added<T>` filter will iterate over all of them even if none of them were just added.
713///
714/// For example, these two systems are roughly equivalent in terms of performance:
715///
716/// ```
717/// # use bevy_ecs::change_detection::{DetectChanges, Ref};
718/// # use bevy_ecs::entity::Entity;
719/// # use bevy_ecs::query::Added;
720/// # use bevy_ecs::system::Query;
721/// # use bevy_ecs_macros::Component;
722/// # #[derive(Component)]
723/// # struct MyComponent;
724/// # #[derive(Component)]
725/// # struct Transform;
726///
727/// fn system1(q: Query<&MyComponent, Added<Transform>>) {
728/// for item in &q { /* component added */ }
729/// }
730///
731/// fn system2(q: Query<(&MyComponent, Ref<Transform>)>) {
732/// for item in &q {
733/// if item.1.is_added() { /* component added */ }
734/// }
735/// }
736/// ```
737///
738/// # Examples
739///
740/// ```
741/// # use bevy_ecs::component::Component;
742/// # use bevy_ecs::query::Added;
743/// # use bevy_ecs::system::IntoSystem;
744/// # use bevy_ecs::system::Query;
745/// #
746/// # #[derive(Component, Debug)]
747/// # struct Name {};
748///
749/// fn print_add_name_component(query: Query<&Name, Added<Name>>) {
750/// for name in &query {
751/// println!("Named entity created: {:?}", name)
752/// }
753/// }
754///
755/// # bevy_ecs::system::assert_is_system(print_add_name_component);
756/// ```
757pub struct Added<T>(PhantomData<T>);
758
759#[doc(hidden)]
760pub struct AddedFetch<'w, T: Component> {
761 ticks: StorageSwitch<
762 T,
763 // T::STORAGE_TYPE = StorageType::Table
764 Option<ThinSlicePtr<'w, UnsafeCell<Tick>>>,
765 // T::STORAGE_TYPE = StorageType::SparseSet
766 // Can be `None` when the component has never been inserted
767 Option<&'w ComponentSparseSet>,
768 >,
769 last_run: Tick,
770 this_run: Tick,
771}
772
773impl<T: Component> Clone for AddedFetch<'_, T> {
774 fn clone(&self) -> Self {
775 Self {
776 ticks: self.ticks,
777 last_run: self.last_run,
778 this_run: self.this_run,
779 }
780 }
781}
782
783// SAFETY:
784// [`QueryFilter::filter_fetch`] accesses a single component in a readonly way.
785// This is sound because `update_component_access` adds read access for that component and panics when appropriate.
786// `update_component_access` adds a `With` filter for a component.
787// This is sound because `matches_component_set` returns whether the set contains that component.
788unsafe impl<T: Component> WorldQuery for Added<T> {
789 type Fetch<'w> = AddedFetch<'w, T>;
790 type State = ComponentId;
791
792 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
793 fetch
794 }
795
796 #[inline]
797 unsafe fn init_fetch<'w, 's>(
798 world: UnsafeWorldCell<'w>,
799 &id: &'s ComponentId,
800 last_run: Tick,
801 this_run: Tick,
802 ) -> Self::Fetch<'w> {
803 Self::Fetch::<'w> {
804 ticks: StorageSwitch::new(
805 || None,
806 || {
807 // SAFETY: The underlying type associated with `component_id` is `T`,
808 // which we are allowed to access since we registered it in `update_component_access`.
809 // Note that we do not actually access any components' ticks in this function, we just get a shared
810 // reference to the sparse set, which is used to access the components' ticks in `Self::fetch`.
811 unsafe { world.storages().sparse_sets.get(id) }
812 },
813 ),
814 last_run,
815 this_run,
816 }
817 }
818
819 const IS_DENSE: bool = {
820 match T::STORAGE_TYPE {
821 StorageType::Table => true,
822 StorageType::SparseSet => false,
823 }
824 };
825
826 #[inline]
827 unsafe fn set_archetype<'w, 's>(
828 fetch: &mut Self::Fetch<'w>,
829 component_id: &'s ComponentId,
830 _archetype: &'w Archetype,
831 table: &'w Table,
832 ) {
833 if Self::IS_DENSE {
834 // SAFETY: `set_archetype`'s safety rules are a super set of the `set_table`'s ones.
835 unsafe {
836 Self::set_table(fetch, component_id, table);
837 }
838 }
839 }
840
841 #[inline]
842 unsafe fn set_table<'w, 's>(
843 fetch: &mut Self::Fetch<'w>,
844 &component_id: &'s ComponentId,
845 table: &'w Table,
846 ) {
847 let table_ticks = Some(
848 table
849 .get_added_ticks_slice_for(component_id)
850 .debug_checked_unwrap()
851 .into(),
852 );
853 // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
854 unsafe { fetch.ticks.set_table(table_ticks) };
855 }
856
857 #[inline]
858 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
859 if access.access().has_write(id) {
860 panic!("$state_name<{}> conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.", DebugName::type_name::<T>());
861 }
862 access.add_read(id);
863 }
864
865 fn init_nested_access(
866 _state: &Self::State,
867 _system_name: Option<&str>,
868 _component_access_set: &mut FilteredAccessSet,
869 _world: UnsafeWorldCell,
870 ) {
871 }
872
873 fn init_state(world: &mut World) -> ComponentId {
874 world.register_component::<T>()
875 }
876
877 fn get_state(components: &Components) -> Option<ComponentId> {
878 components.component_id::<T>()
879 }
880
881 fn matches_component_set(
882 &id: &ComponentId,
883 set_contains_id: &impl Fn(ComponentId) -> bool,
884 ) -> bool {
885 set_contains_id(id)
886 }
887
888 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
889}
890
891// SAFETY: WorldQuery impl performs only read access on ticks
892unsafe impl<T: Component> QueryFilter for Added<T> {
893 const IS_ARCHETYPAL: bool = false;
894 #[inline(always)]
895 unsafe fn filter_fetch(
896 _state: &Self::State,
897 fetch: &mut Self::Fetch<'_>,
898 entity: Entity,
899 table_row: TableRow,
900 ) -> bool {
901 // SAFETY: The invariants are upheld by the caller.
902 fetch.ticks.extract(
903 |table| {
904 // SAFETY: set_table was previously called
905 let table = unsafe { table.debug_checked_unwrap() };
906 // SAFETY: The caller ensures `table_row` is in range.
907 let tick = unsafe { table.get_unchecked(table_row.index()) };
908
909 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
910 },
911 |sparse_set| {
912 // SAFETY: The caller ensures `entity` is in range.
913 let tick = unsafe {
914 sparse_set
915 .debug_checked_unwrap()
916 .get_added_tick(entity)
917 .debug_checked_unwrap()
918 };
919
920 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
921 },
922 )
923 }
924}
925
926/// A filter on a component that only retains results the first time after they have been added or mutably dereferenced.
927///
928/// A common use for this filter is avoiding redundant work when values have not changed.
929///
930/// **Note** that simply *mutably dereferencing* a component is considered a change ([`DerefMut`](std::ops::DerefMut)).
931/// Bevy does not compare components to their previous values.
932///
933/// To retain all results without filtering but still check whether they were changed after the
934/// system last ran, use [`Ref<T>`](crate::change_detection::Ref).
935///
936/// **Note** that this includes changes that happened before the first time this `Query` was run.
937///
938/// # Deferred
939///
940/// Note, that entity modifications issued with [`Commands`](crate::system::Commands)
941/// (like entity creation or entity component addition or removal) are visible only
942/// after deferred operations are applied, typically after the system that queued them.
943///
944/// # Time complexity
945///
946/// `Changed` is not [`ArchetypeFilter`], which practically means that
947/// if query (with `T` component filter) matches million entities,
948/// `Changed<T>` filter will iterate over all of them even if none of them were changed.
949///
950/// For example, these two systems are roughly equivalent in terms of performance:
951///
952/// ```
953/// # use bevy_ecs::change_detection::DetectChanges;
954/// # use bevy_ecs::entity::Entity;
955/// # use bevy_ecs::query::Changed;
956/// # use bevy_ecs::system::Query;
957/// # use bevy_ecs::world::Ref;
958/// # use bevy_ecs_macros::Component;
959/// # #[derive(Component)]
960/// # struct MyComponent;
961/// # #[derive(Component)]
962/// # struct Transform;
963///
964/// fn system1(q: Query<&MyComponent, Changed<Transform>>) {
965/// for item in &q { /* component changed */ }
966/// }
967///
968/// fn system2(q: Query<(&MyComponent, Ref<Transform>)>) {
969/// for item in &q {
970/// if item.1.is_changed() { /* component changed */ }
971/// }
972/// }
973/// ```
974///
975/// # Examples
976///
977/// ```
978/// # use bevy_ecs::component::Component;
979/// # use bevy_ecs::query::Changed;
980/// # use bevy_ecs::system::IntoSystem;
981/// # use bevy_ecs::system::Query;
982/// #
983/// # #[derive(Component, Debug)]
984/// # struct Name {};
985/// # #[derive(Component)]
986/// # struct Transform {};
987///
988/// fn print_moving_objects_system(query: Query<&Name, Changed<Transform>>) {
989/// for name in &query {
990/// println!("Entity Moved: {:?}", name);
991/// }
992/// }
993///
994/// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
995/// ```
996pub struct Changed<T>(PhantomData<T>);
997
998#[doc(hidden)]
999pub struct ChangedFetch<'w, T: Component> {
1000 ticks: StorageSwitch<
1001 T,
1002 Option<ThinSlicePtr<'w, UnsafeCell<Tick>>>,
1003 // Can be `None` when the component has never been inserted
1004 Option<&'w ComponentSparseSet>,
1005 >,
1006 last_run: Tick,
1007 this_run: Tick,
1008}
1009
1010impl<T: Component> Clone for ChangedFetch<'_, T> {
1011 fn clone(&self) -> Self {
1012 Self {
1013 ticks: self.ticks,
1014 last_run: self.last_run,
1015 this_run: self.this_run,
1016 }
1017 }
1018}
1019
1020// SAFETY:
1021// `fetch` accesses a single component in a readonly way.
1022// This is sound because `update_component_access` add read access for that component and panics when appropriate.
1023// `update_component_access` adds a `With` filter for a component.
1024// This is sound because `matches_component_set` returns whether the set contains that component.
1025unsafe impl<T: Component> WorldQuery for Changed<T> {
1026 type Fetch<'w> = ChangedFetch<'w, T>;
1027 type State = ComponentId;
1028
1029 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
1030 fetch
1031 }
1032
1033 #[inline]
1034 unsafe fn init_fetch<'w, 's>(
1035 world: UnsafeWorldCell<'w>,
1036 &id: &'s ComponentId,
1037 last_run: Tick,
1038 this_run: Tick,
1039 ) -> Self::Fetch<'w> {
1040 Self::Fetch::<'w> {
1041 ticks: StorageSwitch::new(
1042 || None,
1043 || {
1044 // SAFETY: The underlying type associated with `component_id` is `T`,
1045 // which we are allowed to access since we registered it in `update_component_access`.
1046 // Note that we do not actually access any components' ticks in this function, we just get a shared
1047 // reference to the sparse set, which is used to access the components' ticks in `Self::fetch`.
1048 unsafe { world.storages().sparse_sets.get(id) }
1049 },
1050 ),
1051 last_run,
1052 this_run,
1053 }
1054 }
1055
1056 const IS_DENSE: bool = {
1057 match T::STORAGE_TYPE {
1058 StorageType::Table => true,
1059 StorageType::SparseSet => false,
1060 }
1061 };
1062
1063 #[inline]
1064 unsafe fn set_archetype<'w, 's>(
1065 fetch: &mut Self::Fetch<'w>,
1066 component_id: &'s ComponentId,
1067 _archetype: &'w Archetype,
1068 table: &'w Table,
1069 ) {
1070 if Self::IS_DENSE {
1071 // SAFETY: `set_archetype`'s safety rules are a super set of the `set_table`'s ones.
1072 unsafe {
1073 Self::set_table(fetch, component_id, table);
1074 }
1075 }
1076 }
1077
1078 #[inline]
1079 unsafe fn set_table<'w, 's>(
1080 fetch: &mut Self::Fetch<'w>,
1081 &component_id: &'s ComponentId,
1082 table: &'w Table,
1083 ) {
1084 let table_ticks = Some(
1085 table
1086 .get_changed_ticks_slice_for(component_id)
1087 .debug_checked_unwrap()
1088 .into(),
1089 );
1090 // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
1091 unsafe { fetch.ticks.set_table(table_ticks) };
1092 }
1093
1094 #[inline]
1095 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
1096 if access.access().has_write(id) {
1097 panic!("$state_name<{}> conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.", DebugName::type_name::<T>());
1098 }
1099 access.add_read(id);
1100 }
1101
1102 fn init_nested_access(
1103 _state: &Self::State,
1104 _system_name: Option<&str>,
1105 _component_access_set: &mut FilteredAccessSet,
1106 _world: UnsafeWorldCell,
1107 ) {
1108 }
1109
1110 fn init_state(world: &mut World) -> ComponentId {
1111 world.register_component::<T>()
1112 }
1113
1114 fn get_state(components: &Components) -> Option<ComponentId> {
1115 components.component_id::<T>()
1116 }
1117
1118 fn matches_component_set(
1119 &id: &ComponentId,
1120 set_contains_id: &impl Fn(ComponentId) -> bool,
1121 ) -> bool {
1122 set_contains_id(id)
1123 }
1124
1125 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
1126}
1127
1128// SAFETY: WorldQuery impl performs only read access on ticks
1129unsafe impl<T: Component> QueryFilter for Changed<T> {
1130 const IS_ARCHETYPAL: bool = false;
1131
1132 #[inline(always)]
1133 unsafe fn filter_fetch(
1134 _state: &Self::State,
1135 fetch: &mut Self::Fetch<'_>,
1136 entity: Entity,
1137 table_row: TableRow,
1138 ) -> bool {
1139 // SAFETY: The invariants are upheld by the caller.
1140 fetch.ticks.extract(
1141 |table| {
1142 // SAFETY: set_table was previously called
1143 let table = unsafe { table.debug_checked_unwrap() };
1144 // SAFETY: The caller ensures `table_row` is in range.
1145 let tick = unsafe { table.get_unchecked(table_row.index()) };
1146
1147 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
1148 },
1149 |sparse_set| {
1150 // SAFETY: The caller ensures `entity` is in range.
1151 let tick = unsafe {
1152 sparse_set
1153 .debug_checked_unwrap()
1154 .get_changed_tick(entity)
1155 .debug_checked_unwrap()
1156 };
1157
1158 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
1159 },
1160 )
1161 }
1162}
1163
1164/// A filter that only retains results the first time after the entity has been spawned.
1165///
1166/// A common use for this filter is one-time initialization.
1167///
1168/// To retain all results without filtering but still check whether they were spawned after the
1169/// system last ran, use [`SpawnDetails`](crate::query::SpawnDetails) instead.
1170///
1171/// **Note** that this includes entities that spawned before the first time this Query was run.
1172///
1173/// # Deferred
1174///
1175/// Note, that entity spawns issued with [`Commands`](crate::system::Commands)
1176/// are visible only after deferred operations are applied, typically after the
1177/// system that queued them.
1178///
1179/// # Time complexity
1180///
1181/// `Spawned` is not [`ArchetypeFilter`], which practically means that if query matches million
1182/// entities, `Spawned` filter will iterate over all of them even if none of them were spawned.
1183///
1184/// For example, these two systems are roughly equivalent in terms of performance:
1185///
1186/// ```
1187/// # use bevy_ecs::entity::Entity;
1188/// # use bevy_ecs::system::Query;
1189/// # use bevy_ecs::query::Spawned;
1190/// # use bevy_ecs::query::SpawnDetails;
1191///
1192/// fn system1(query: Query<Entity, Spawned>) {
1193/// for entity in &query { /* entity spawned */ }
1194/// }
1195///
1196/// fn system2(query: Query<(Entity, SpawnDetails)>) {
1197/// for (entity, spawned) in &query {
1198/// if spawned.is_spawned() { /* entity spawned */ }
1199/// }
1200/// }
1201/// ```
1202///
1203/// # Examples
1204///
1205/// ```
1206/// # use bevy_ecs::component::Component;
1207/// # use bevy_ecs::query::Spawned;
1208/// # use bevy_ecs::system::IntoSystem;
1209/// # use bevy_ecs::system::Query;
1210/// #
1211/// # #[derive(Component, Debug)]
1212/// # struct Name {};
1213///
1214/// fn print_spawning_entities(query: Query<&Name, Spawned>) {
1215/// for name in &query {
1216/// println!("Entity spawned: {:?}", name);
1217/// }
1218/// }
1219///
1220/// # bevy_ecs::system::assert_is_system(print_spawning_entities);
1221/// ```
1222pub struct Spawned;
1223
1224#[doc(hidden)]
1225#[derive(Clone)]
1226pub struct SpawnedFetch<'w> {
1227 entities: &'w Entities,
1228 last_run: Tick,
1229 this_run: Tick,
1230}
1231
1232// SAFETY: WorldQuery impl accesses no components or component ticks
1233unsafe impl WorldQuery for Spawned {
1234 type Fetch<'w> = SpawnedFetch<'w>;
1235 type State = ();
1236
1237 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
1238 fetch
1239 }
1240
1241 #[inline]
1242 unsafe fn init_fetch<'w, 's>(
1243 world: UnsafeWorldCell<'w>,
1244 _state: &'s (),
1245 last_run: Tick,
1246 this_run: Tick,
1247 ) -> Self::Fetch<'w> {
1248 SpawnedFetch {
1249 entities: world.entities(),
1250 last_run,
1251 this_run,
1252 }
1253 }
1254
1255 const IS_DENSE: bool = true;
1256
1257 #[inline]
1258 unsafe fn set_archetype<'w, 's>(
1259 _fetch: &mut Self::Fetch<'w>,
1260 _state: &'s (),
1261 _archetype: &'w Archetype,
1262 _table: &'w Table,
1263 ) {
1264 }
1265
1266 #[inline]
1267 unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w>, _state: &'s (), _table: &'w Table) {}
1268
1269 #[inline]
1270 fn update_component_access(_state: &(), _access: &mut FilteredAccess) {}
1271
1272 fn init_nested_access(
1273 _state: &Self::State,
1274 _system_name: Option<&str>,
1275 _component_access_set: &mut FilteredAccessSet,
1276 _world: UnsafeWorldCell,
1277 ) {
1278 }
1279
1280 fn init_state(_world: &mut World) {}
1281
1282 fn get_state(_components: &Components) -> Option<()> {
1283 Some(())
1284 }
1285
1286 fn matches_component_set(_state: &(), _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
1287 true
1288 }
1289
1290 fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
1291}
1292
1293// SAFETY: WorldQuery impl accesses no components or component ticks
1294unsafe impl QueryFilter for Spawned {
1295 const IS_ARCHETYPAL: bool = false;
1296
1297 #[inline(always)]
1298 unsafe fn filter_fetch(
1299 _state: &Self::State,
1300 fetch: &mut Self::Fetch<'_>,
1301 entity: Entity,
1302 _table_row: TableRow,
1303 ) -> bool {
1304 // SAFETY: only living entities are queried
1305 let spawned = unsafe {
1306 fetch
1307 .entities
1308 .entity_get_spawned_or_despawned_unchecked(entity)
1309 .1
1310 };
1311 spawned.is_newer_than(fetch.last_run, fetch.this_run)
1312 }
1313}
1314
1315/// A marker trait to indicate that the filter works at an archetype level.
1316///
1317/// This is needed to:
1318/// - implement [`ExactSizeIterator`] for [`QueryIter`](crate::query::QueryIter) that contains archetype-level filters.
1319/// - ensure table filtering for [`QueryContiguousIter`](crate::query::QueryContiguousIter).
1320///
1321/// The trait must only be implemented for filters where its corresponding [`QueryFilter::IS_ARCHETYPAL`]
1322/// is [`prim@true`]. As such, only the [`With`] and [`Without`] filters can implement the trait.
1323/// [Tuples](prim@tuple) and [`Or`] filters are automatically implemented with the trait only if its containing types
1324/// also implement the same trait.
1325///
1326/// [`Added`], [`Changed`] and [`Spawned`] work with entities, and therefore are not archetypal. As such
1327/// they do not implement [`ArchetypeFilter`].
1328#[diagnostic::on_unimplemented(
1329 message = "`{Self}` is not a valid `Query` filter based on archetype information",
1330 label = "invalid `Query` filter",
1331 note = "an `ArchetypeFilter` typically uses a combination of `With<T>` and `Without<T>` statements"
1332)]
1333pub trait ArchetypeFilter: QueryFilter {}
1334
1335impl<T: Component> ArchetypeFilter for With<T> {}
1336
1337impl<T: Component> ArchetypeFilter for Without<T> {}
1338
1339macro_rules! impl_archetype_filter_tuple {
1340 ($(#[$meta:meta])* $($filter: ident),*) => {
1341 $(#[$meta])*
1342 impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for ($($filter,)*) {}
1343 };
1344}
1345
1346macro_rules! impl_archetype_or_filter_tuple {
1347 ($(#[$meta:meta])* $($filter: ident),*) => {
1348 $(#[$meta])*
1349 impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for Or<($($filter,)*)> {}
1350 };
1351}
1352
1353all_tuples!(
1354 #[doc(fake_variadic)]
1355 impl_archetype_filter_tuple,
1356 0,
1357 15,
1358 F
1359);
1360
1361all_tuples!(
1362 #[doc(fake_variadic)]
1363 impl_archetype_or_filter_tuple,
1364 0,
1365 15,
1366 F
1367);