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