bevy_ecs/query/
filter.rs

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