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);