Skip to main content

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