bevy_ecs/query/
filter.rs

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