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, 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_state(world: &mut World) -> Self::State {
481 ($($filter::init_state(world),)*)
482 }
483
484 fn get_state(components: &Components) -> Option<Self::State> {
485 Some(($($filter::get_state(components)?,)*))
486 }
487
488 fn matches_component_set(state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
489 let ($($filter,)*) = state;
490 false $(|| $filter::matches_component_set($filter, set_contains_id))*
491 }
492 }
493
494 #[expect(
495 clippy::allow_attributes,
496 reason = "This is a tuple-related macro; as such the lints below may not always apply."
497 )]
498 #[allow(
499 non_snake_case,
500 reason = "The names of some variables are provided by the macro's caller, not by us."
501 )]
502 #[allow(
503 unused_variables,
504 reason = "Zero-length tuples won't use any of the parameters."
505 )]
506 $(#[$meta])*
507 // SAFETY: This only performs access that subqueries perform, and they impl `QueryFilter` and so perform no mutable access.
508 unsafe impl<$($filter: QueryFilter),*> QueryFilter for Or<($($filter,)*)> {
509 const IS_ARCHETYPAL: bool = true $(&& $filter::IS_ARCHETYPAL)*;
510
511 #[inline(always)]
512 unsafe fn filter_fetch(
513 state: &Self::State,
514 fetch: &mut Self::Fetch<'_>,
515 entity: Entity,
516 table_row: TableRow
517 ) -> bool {
518 let ($($state,)*) = state;
519 let ($($filter,)*) = fetch;
520 // If this is an archetypal query, then it is guaranteed to return true,
521 // and we can help the compiler remove branches by checking the const `IS_ARCHETYPAL` first.
522 (Self::IS_ARCHETYPAL
523 // SAFETY: The invariants are upheld by the caller.
524 $(|| ($filter.matches && unsafe { $filter::filter_fetch($state, &mut $filter.fetch, entity, table_row) }))*
525 // If *none* of the subqueries matched the archetype, then this archetype was added in a transmute.
526 // We must treat those as matching in order to be consistent with `size_hint` for archetypal queries,
527 // so we treat them as matching for non-archetypal queries, as well.
528 || !(false $(|| $filter.matches)*))
529 }
530 }
531 };
532}
533
534macro_rules! impl_tuple_query_filter {
535 ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => {
536 #[expect(
537 clippy::allow_attributes,
538 reason = "This is a tuple-related macro; as such the lints below may not always apply."
539 )]
540 #[allow(
541 non_snake_case,
542 reason = "The names of some variables are provided by the macro's caller, not by us."
543 )]
544 #[allow(
545 unused_variables,
546 reason = "Zero-length tuples won't use any of the parameters."
547 )]
548 $(#[$meta])*
549 // SAFETY: This only performs access that subqueries perform, and they impl `QueryFilter` and so perform no mutable access.
550 unsafe impl<$($name: QueryFilter),*> QueryFilter for ($($name,)*) {
551 const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
552
553 #[inline(always)]
554 unsafe fn filter_fetch(
555 state: &Self::State,
556 fetch: &mut Self::Fetch<'_>,
557 entity: Entity,
558 table_row: TableRow
559 ) -> bool {
560 let ($($state,)*) = state;
561 let ($($name,)*) = fetch;
562 // SAFETY: The invariants are upheld by the caller.
563 true $(&& unsafe { $name::filter_fetch($state, $name, entity, table_row) })*
564 }
565 }
566
567 };
568}
569
570all_tuples!(
571 #[doc(fake_variadic)]
572 impl_tuple_query_filter,
573 0,
574 15,
575 F,
576 S
577);
578all_tuples!(
579 #[doc(fake_variadic)]
580 impl_or_query_filter,
581 0,
582 15,
583 F,
584 S
585);
586
587/// Allows a query to contain entities with the component `T`, bypassing [`DefaultQueryFilters`].
588///
589/// [`DefaultQueryFilters`]: crate::entity_disabling::DefaultQueryFilters
590pub struct Allow<T>(PhantomData<T>);
591
592/// SAFETY:
593/// `update_component_access` does not add any accesses.
594/// This is sound because [`QueryFilter::filter_fetch`] does not access any components.
595/// `update_component_access` adds an archetypal filter for `T`.
596/// This is sound because it doesn't affect the query
597unsafe impl<T: Component> WorldQuery for Allow<T> {
598 type Fetch<'w> = ();
599 type State = ComponentId;
600
601 fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
602
603 #[inline]
604 unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {}
605
606 // Even if the component is sparse, this implementation doesn't do anything with it
607 const IS_DENSE: bool = true;
608
609 #[inline]
610 unsafe fn set_archetype(_: &mut (), _: &ComponentId, _: &Archetype, _: &Table) {}
611
612 #[inline]
613 unsafe fn set_table(_: &mut (), _: &ComponentId, _: &Table) {}
614
615 #[inline]
616 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
617 access.access_mut().add_archetypal(id);
618 }
619
620 fn init_state(world: &mut World) -> ComponentId {
621 world.register_component::<T>()
622 }
623
624 fn get_state(components: &Components) -> Option<Self::State> {
625 components.component_id::<T>()
626 }
627
628 fn matches_component_set(_: &ComponentId, _: &impl Fn(ComponentId) -> bool) -> bool {
629 // Allow<T> always matches
630 true
631 }
632}
633
634// SAFETY: WorldQuery impl performs no access at all
635unsafe impl<T: Component> QueryFilter for Allow<T> {
636 const IS_ARCHETYPAL: bool = true;
637
638 #[inline(always)]
639 unsafe fn filter_fetch(
640 _: &Self::State,
641 _: &mut Self::Fetch<'_>,
642 _: Entity,
643 _: TableRow,
644 ) -> bool {
645 true
646 }
647}
648
649/// A filter on a component that only retains results the first time after they have been added.
650///
651/// A common use for this filter is one-time initialization.
652///
653/// To retain all results without filtering but still check whether they were added after the
654/// system last ran, use [`Ref<T>`](crate::change_detection::Ref).
655///
656/// **Note** that this includes changes that happened before the first time this `Query` was run.
657///
658/// # Deferred
659///
660/// Note, that entity modifications issued with [`Commands`](crate::system::Commands)
661/// are visible only after deferred operations are applied, typically after the system
662/// that queued them.
663///
664/// # Time complexity
665///
666/// `Added` is not [`ArchetypeFilter`], which practically means that
667/// if the query (with `T` component filter) matches a million entities,
668/// `Added<T>` filter will iterate over all of them even if none of them were just added.
669///
670/// For example, these two systems are roughly equivalent in terms of performance:
671///
672/// ```
673/// # use bevy_ecs::change_detection::{DetectChanges, Ref};
674/// # use bevy_ecs::entity::Entity;
675/// # use bevy_ecs::query::Added;
676/// # use bevy_ecs::system::Query;
677/// # use bevy_ecs_macros::Component;
678/// # #[derive(Component)]
679/// # struct MyComponent;
680/// # #[derive(Component)]
681/// # struct Transform;
682///
683/// fn system1(q: Query<&MyComponent, Added<Transform>>) {
684/// for item in &q { /* component added */ }
685/// }
686///
687/// fn system2(q: Query<(&MyComponent, Ref<Transform>)>) {
688/// for item in &q {
689/// if item.1.is_added() { /* component added */ }
690/// }
691/// }
692/// ```
693///
694/// # Examples
695///
696/// ```
697/// # use bevy_ecs::component::Component;
698/// # use bevy_ecs::query::Added;
699/// # use bevy_ecs::system::IntoSystem;
700/// # use bevy_ecs::system::Query;
701/// #
702/// # #[derive(Component, Debug)]
703/// # struct Name {};
704///
705/// fn print_add_name_component(query: Query<&Name, Added<Name>>) {
706/// for name in &query {
707/// println!("Named entity created: {:?}", name)
708/// }
709/// }
710///
711/// # bevy_ecs::system::assert_is_system(print_add_name_component);
712/// ```
713pub struct Added<T>(PhantomData<T>);
714
715#[doc(hidden)]
716pub struct AddedFetch<'w, T: Component> {
717 ticks: StorageSwitch<
718 T,
719 // T::STORAGE_TYPE = StorageType::Table
720 Option<ThinSlicePtr<'w, UnsafeCell<Tick>>>,
721 // T::STORAGE_TYPE = StorageType::SparseSet
722 // Can be `None` when the component has never been inserted
723 Option<&'w ComponentSparseSet>,
724 >,
725 last_run: Tick,
726 this_run: Tick,
727}
728
729impl<T: Component> Clone for AddedFetch<'_, T> {
730 fn clone(&self) -> Self {
731 Self {
732 ticks: self.ticks,
733 last_run: self.last_run,
734 this_run: self.this_run,
735 }
736 }
737}
738
739/// SAFETY:
740/// [`QueryFilter::filter_fetch`] accesses a single component in a readonly way.
741/// This is sound because `update_component_access` adds read access for that component and panics when appropriate.
742/// `update_component_access` adds a `With` filter for a component.
743/// This is sound because `matches_component_set` returns whether the set contains that component.
744unsafe impl<T: Component> WorldQuery for Added<T> {
745 type Fetch<'w> = AddedFetch<'w, T>;
746 type State = ComponentId;
747
748 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
749 fetch
750 }
751
752 #[inline]
753 unsafe fn init_fetch<'w, 's>(
754 world: UnsafeWorldCell<'w>,
755 &id: &'s ComponentId,
756 last_run: Tick,
757 this_run: Tick,
758 ) -> Self::Fetch<'w> {
759 Self::Fetch::<'w> {
760 ticks: StorageSwitch::new(
761 || None,
762 || {
763 // SAFETY: The underlying type associated with `component_id` is `T`,
764 // which we are allowed to access since we registered it in `update_component_access`.
765 // Note that we do not actually access any components' ticks in this function, we just get a shared
766 // reference to the sparse set, which is used to access the components' ticks in `Self::fetch`.
767 unsafe { world.storages().sparse_sets.get(id) }
768 },
769 ),
770 last_run,
771 this_run,
772 }
773 }
774
775 const IS_DENSE: bool = {
776 match T::STORAGE_TYPE {
777 StorageType::Table => true,
778 StorageType::SparseSet => false,
779 }
780 };
781
782 #[inline]
783 unsafe fn set_archetype<'w, 's>(
784 fetch: &mut Self::Fetch<'w>,
785 component_id: &'s ComponentId,
786 _archetype: &'w Archetype,
787 table: &'w Table,
788 ) {
789 if Self::IS_DENSE {
790 // SAFETY: `set_archetype`'s safety rules are a super set of the `set_table`'s ones.
791 unsafe {
792 Self::set_table(fetch, component_id, table);
793 }
794 }
795 }
796
797 #[inline]
798 unsafe fn set_table<'w, 's>(
799 fetch: &mut Self::Fetch<'w>,
800 &component_id: &'s ComponentId,
801 table: &'w Table,
802 ) {
803 let table_ticks = Some(
804 table
805 .get_added_ticks_slice_for(component_id)
806 .debug_checked_unwrap()
807 .into(),
808 );
809 // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
810 unsafe { fetch.ticks.set_table(table_ticks) };
811 }
812
813 #[inline]
814 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
815 if access.access().has_component_write(id) {
816 panic!("$state_name<{}> conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.", DebugName::type_name::<T>());
817 }
818 access.add_component_read(id);
819 }
820
821 fn init_state(world: &mut World) -> ComponentId {
822 world.register_component::<T>()
823 }
824
825 fn get_state(components: &Components) -> Option<ComponentId> {
826 components.component_id::<T>()
827 }
828
829 fn matches_component_set(
830 &id: &ComponentId,
831 set_contains_id: &impl Fn(ComponentId) -> bool,
832 ) -> bool {
833 set_contains_id(id)
834 }
835}
836
837// SAFETY: WorldQuery impl performs only read access on ticks
838unsafe impl<T: Component> QueryFilter for Added<T> {
839 const IS_ARCHETYPAL: bool = false;
840 #[inline(always)]
841 unsafe fn filter_fetch(
842 _state: &Self::State,
843 fetch: &mut Self::Fetch<'_>,
844 entity: Entity,
845 table_row: TableRow,
846 ) -> bool {
847 // SAFETY: The invariants are upheld by the caller.
848 fetch.ticks.extract(
849 |table| {
850 // SAFETY: set_table was previously called
851 let table = unsafe { table.debug_checked_unwrap() };
852 // SAFETY: The caller ensures `table_row` is in range.
853 let tick = unsafe { table.get_unchecked(table_row.index()) };
854
855 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
856 },
857 |sparse_set| {
858 // SAFETY: The caller ensures `entity` is in range.
859 let tick = unsafe {
860 sparse_set
861 .debug_checked_unwrap()
862 .get_added_tick(entity)
863 .debug_checked_unwrap()
864 };
865
866 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
867 },
868 )
869 }
870}
871
872/// A filter on a component that only retains results the first time after they have been added or mutably dereferenced.
873///
874/// A common use for this filter is avoiding redundant work when values have not changed.
875///
876/// **Note** that simply *mutably dereferencing* a component is considered a change ([`DerefMut`](std::ops::DerefMut)).
877/// Bevy does not compare components to their previous values.
878///
879/// To retain all results without filtering but still check whether they were changed after the
880/// system last ran, use [`Ref<T>`](crate::change_detection::Ref).
881///
882/// **Note** that this includes changes that happened before the first time this `Query` was run.
883///
884/// # Deferred
885///
886/// Note, that entity modifications issued with [`Commands`](crate::system::Commands)
887/// (like entity creation or entity component addition or removal) are visible only
888/// after deferred operations are applied, typically after the system that queued them.
889///
890/// # Time complexity
891///
892/// `Changed` is not [`ArchetypeFilter`], which practically means that
893/// if query (with `T` component filter) matches million entities,
894/// `Changed<T>` filter will iterate over all of them even if none of them were changed.
895///
896/// For example, these two systems are roughly equivalent in terms of performance:
897///
898/// ```
899/// # use bevy_ecs::change_detection::DetectChanges;
900/// # use bevy_ecs::entity::Entity;
901/// # use bevy_ecs::query::Changed;
902/// # use bevy_ecs::system::Query;
903/// # use bevy_ecs::world::Ref;
904/// # use bevy_ecs_macros::Component;
905/// # #[derive(Component)]
906/// # struct MyComponent;
907/// # #[derive(Component)]
908/// # struct Transform;
909///
910/// fn system1(q: Query<&MyComponent, Changed<Transform>>) {
911/// for item in &q { /* component changed */ }
912/// }
913///
914/// fn system2(q: Query<(&MyComponent, Ref<Transform>)>) {
915/// for item in &q {
916/// if item.1.is_changed() { /* component changed */ }
917/// }
918/// }
919/// ```
920///
921/// # Examples
922///
923/// ```
924/// # use bevy_ecs::component::Component;
925/// # use bevy_ecs::query::Changed;
926/// # use bevy_ecs::system::IntoSystem;
927/// # use bevy_ecs::system::Query;
928/// #
929/// # #[derive(Component, Debug)]
930/// # struct Name {};
931/// # #[derive(Component)]
932/// # struct Transform {};
933///
934/// fn print_moving_objects_system(query: Query<&Name, Changed<Transform>>) {
935/// for name in &query {
936/// println!("Entity Moved: {:?}", name);
937/// }
938/// }
939///
940/// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
941/// ```
942pub struct Changed<T>(PhantomData<T>);
943
944#[doc(hidden)]
945pub struct ChangedFetch<'w, T: Component> {
946 ticks: StorageSwitch<
947 T,
948 Option<ThinSlicePtr<'w, UnsafeCell<Tick>>>,
949 // Can be `None` when the component has never been inserted
950 Option<&'w ComponentSparseSet>,
951 >,
952 last_run: Tick,
953 this_run: Tick,
954}
955
956impl<T: Component> Clone for ChangedFetch<'_, T> {
957 fn clone(&self) -> Self {
958 Self {
959 ticks: self.ticks,
960 last_run: self.last_run,
961 this_run: self.this_run,
962 }
963 }
964}
965
966/// SAFETY:
967/// `fetch` accesses a single component in a readonly way.
968/// This is sound because `update_component_access` add read access for that component and panics when appropriate.
969/// `update_component_access` adds a `With` filter for a component.
970/// This is sound because `matches_component_set` returns whether the set contains that component.
971unsafe impl<T: Component> WorldQuery for Changed<T> {
972 type Fetch<'w> = ChangedFetch<'w, T>;
973 type State = ComponentId;
974
975 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
976 fetch
977 }
978
979 #[inline]
980 unsafe fn init_fetch<'w, 's>(
981 world: UnsafeWorldCell<'w>,
982 &id: &'s ComponentId,
983 last_run: Tick,
984 this_run: Tick,
985 ) -> Self::Fetch<'w> {
986 Self::Fetch::<'w> {
987 ticks: StorageSwitch::new(
988 || None,
989 || {
990 // SAFETY: The underlying type associated with `component_id` is `T`,
991 // which we are allowed to access since we registered it in `update_component_access`.
992 // Note that we do not actually access any components' ticks in this function, we just get a shared
993 // reference to the sparse set, which is used to access the components' ticks in `Self::fetch`.
994 unsafe { world.storages().sparse_sets.get(id) }
995 },
996 ),
997 last_run,
998 this_run,
999 }
1000 }
1001
1002 const IS_DENSE: bool = {
1003 match T::STORAGE_TYPE {
1004 StorageType::Table => true,
1005 StorageType::SparseSet => false,
1006 }
1007 };
1008
1009 #[inline]
1010 unsafe fn set_archetype<'w, 's>(
1011 fetch: &mut Self::Fetch<'w>,
1012 component_id: &'s ComponentId,
1013 _archetype: &'w Archetype,
1014 table: &'w Table,
1015 ) {
1016 if Self::IS_DENSE {
1017 // SAFETY: `set_archetype`'s safety rules are a super set of the `set_table`'s ones.
1018 unsafe {
1019 Self::set_table(fetch, component_id, table);
1020 }
1021 }
1022 }
1023
1024 #[inline]
1025 unsafe fn set_table<'w, 's>(
1026 fetch: &mut Self::Fetch<'w>,
1027 &component_id: &'s ComponentId,
1028 table: &'w Table,
1029 ) {
1030 let table_ticks = Some(
1031 table
1032 .get_changed_ticks_slice_for(component_id)
1033 .debug_checked_unwrap()
1034 .into(),
1035 );
1036 // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
1037 unsafe { fetch.ticks.set_table(table_ticks) };
1038 }
1039
1040 #[inline]
1041 fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess) {
1042 if access.access().has_component_write(id) {
1043 panic!("$state_name<{}> conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.", DebugName::type_name::<T>());
1044 }
1045 access.add_component_read(id);
1046 }
1047
1048 fn init_state(world: &mut World) -> ComponentId {
1049 world.register_component::<T>()
1050 }
1051
1052 fn get_state(components: &Components) -> Option<ComponentId> {
1053 components.component_id::<T>()
1054 }
1055
1056 fn matches_component_set(
1057 &id: &ComponentId,
1058 set_contains_id: &impl Fn(ComponentId) -> bool,
1059 ) -> bool {
1060 set_contains_id(id)
1061 }
1062}
1063
1064// SAFETY: WorldQuery impl performs only read access on ticks
1065unsafe impl<T: Component> QueryFilter for Changed<T> {
1066 const IS_ARCHETYPAL: bool = false;
1067
1068 #[inline(always)]
1069 unsafe fn filter_fetch(
1070 _state: &Self::State,
1071 fetch: &mut Self::Fetch<'_>,
1072 entity: Entity,
1073 table_row: TableRow,
1074 ) -> bool {
1075 // SAFETY: The invariants are upheld by the caller.
1076 fetch.ticks.extract(
1077 |table| {
1078 // SAFETY: set_table was previously called
1079 let table = unsafe { table.debug_checked_unwrap() };
1080 // SAFETY: The caller ensures `table_row` is in range.
1081 let tick = unsafe { table.get_unchecked(table_row.index()) };
1082
1083 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
1084 },
1085 |sparse_set| {
1086 // SAFETY: The caller ensures `entity` is in range.
1087 let tick = unsafe {
1088 sparse_set
1089 .debug_checked_unwrap()
1090 .get_changed_tick(entity)
1091 .debug_checked_unwrap()
1092 };
1093
1094 tick.deref().is_newer_than(fetch.last_run, fetch.this_run)
1095 },
1096 )
1097 }
1098}
1099
1100/// A filter that only retains results the first time after the entity has been spawned.
1101///
1102/// A common use for this filter is one-time initialization.
1103///
1104/// To retain all results without filtering but still check whether they were spawned after the
1105/// system last ran, use [`SpawnDetails`](crate::query::SpawnDetails) instead.
1106///
1107/// **Note** that this includes entities that spawned before the first time this Query was run.
1108///
1109/// # Deferred
1110///
1111/// Note, that entity spawns issued with [`Commands`](crate::system::Commands)
1112/// are visible only after deferred operations are applied, typically after the
1113/// system that queued them.
1114///
1115/// # Time complexity
1116///
1117/// `Spawned` is not [`ArchetypeFilter`], which practically means that if query matches million
1118/// entities, `Spawned` filter will iterate over all of them even if none of them were spawned.
1119///
1120/// For example, these two systems are roughly equivalent in terms of performance:
1121///
1122/// ```
1123/// # use bevy_ecs::entity::Entity;
1124/// # use bevy_ecs::system::Query;
1125/// # use bevy_ecs::query::Spawned;
1126/// # use bevy_ecs::query::SpawnDetails;
1127///
1128/// fn system1(query: Query<Entity, Spawned>) {
1129/// for entity in &query { /* entity spawned */ }
1130/// }
1131///
1132/// fn system2(query: Query<(Entity, SpawnDetails)>) {
1133/// for (entity, spawned) in &query {
1134/// if spawned.is_spawned() { /* entity spawned */ }
1135/// }
1136/// }
1137/// ```
1138///
1139/// # Examples
1140///
1141/// ```
1142/// # use bevy_ecs::component::Component;
1143/// # use bevy_ecs::query::Spawned;
1144/// # use bevy_ecs::system::IntoSystem;
1145/// # use bevy_ecs::system::Query;
1146/// #
1147/// # #[derive(Component, Debug)]
1148/// # struct Name {};
1149///
1150/// fn print_spawning_entities(query: Query<&Name, Spawned>) {
1151/// for name in &query {
1152/// println!("Entity spawned: {:?}", name);
1153/// }
1154/// }
1155///
1156/// # bevy_ecs::system::assert_is_system(print_spawning_entities);
1157/// ```
1158pub struct Spawned;
1159
1160#[doc(hidden)]
1161#[derive(Clone)]
1162pub struct SpawnedFetch<'w> {
1163 entities: &'w Entities,
1164 last_run: Tick,
1165 this_run: Tick,
1166}
1167
1168// SAFETY: WorldQuery impl accesses no components or component ticks
1169unsafe impl WorldQuery for Spawned {
1170 type Fetch<'w> = SpawnedFetch<'w>;
1171 type State = ();
1172
1173 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
1174 fetch
1175 }
1176
1177 #[inline]
1178 unsafe fn init_fetch<'w, 's>(
1179 world: UnsafeWorldCell<'w>,
1180 _state: &'s (),
1181 last_run: Tick,
1182 this_run: Tick,
1183 ) -> Self::Fetch<'w> {
1184 SpawnedFetch {
1185 entities: world.entities(),
1186 last_run,
1187 this_run,
1188 }
1189 }
1190
1191 const IS_DENSE: bool = true;
1192
1193 #[inline]
1194 unsafe fn set_archetype<'w, 's>(
1195 _fetch: &mut Self::Fetch<'w>,
1196 _state: &'s (),
1197 _archetype: &'w Archetype,
1198 _table: &'w Table,
1199 ) {
1200 }
1201
1202 #[inline]
1203 unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w>, _state: &'s (), _table: &'w Table) {}
1204
1205 #[inline]
1206 fn update_component_access(_state: &(), _access: &mut FilteredAccess) {}
1207
1208 fn init_state(_world: &mut World) {}
1209
1210 fn get_state(_components: &Components) -> Option<()> {
1211 Some(())
1212 }
1213
1214 fn matches_component_set(_state: &(), _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
1215 true
1216 }
1217}
1218
1219// SAFETY: WorldQuery impl accesses no components or component ticks
1220unsafe impl QueryFilter for Spawned {
1221 const IS_ARCHETYPAL: bool = false;
1222
1223 #[inline(always)]
1224 unsafe fn filter_fetch(
1225 _state: &Self::State,
1226 fetch: &mut Self::Fetch<'_>,
1227 entity: Entity,
1228 _table_row: TableRow,
1229 ) -> bool {
1230 // SAFETY: only living entities are queried
1231 let spawned = unsafe {
1232 fetch
1233 .entities
1234 .entity_get_spawned_or_despawned_unchecked(entity)
1235 .1
1236 };
1237 spawned.is_newer_than(fetch.last_run, fetch.this_run)
1238 }
1239}
1240
1241/// A marker trait to indicate that the filter works at an archetype level.
1242///
1243/// This is needed to implement [`ExactSizeIterator`] for
1244/// [`QueryIter`](crate::query::QueryIter) that contains archetype-level filters.
1245///
1246/// The trait must only be implemented for filters where its corresponding [`QueryFilter::IS_ARCHETYPAL`]
1247/// is [`prim@true`]. As such, only the [`With`] and [`Without`] filters can implement the trait.
1248/// [Tuples](prim@tuple) and [`Or`] filters are automatically implemented with the trait only if its containing types
1249/// also implement the same trait.
1250///
1251/// [`Added`], [`Changed`] and [`Spawned`] work with entities, and therefore are not archetypal. As such
1252/// they do not implement [`ArchetypeFilter`].
1253#[diagnostic::on_unimplemented(
1254 message = "`{Self}` is not a valid `Query` filter based on archetype information",
1255 label = "invalid `Query` filter",
1256 note = "an `ArchetypeFilter` typically uses a combination of `With<T>` and `Without<T>` statements"
1257)]
1258pub trait ArchetypeFilter: QueryFilter {}
1259
1260impl<T: Component> ArchetypeFilter for With<T> {}
1261
1262impl<T: Component> ArchetypeFilter for Without<T> {}
1263
1264macro_rules! impl_archetype_filter_tuple {
1265 ($(#[$meta:meta])* $($filter: ident),*) => {
1266 $(#[$meta])*
1267 impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for ($($filter,)*) {}
1268 };
1269}
1270
1271macro_rules! impl_archetype_or_filter_tuple {
1272 ($(#[$meta:meta])* $($filter: ident),*) => {
1273 $(#[$meta])*
1274 impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for Or<($($filter,)*)> {}
1275 };
1276}
1277
1278all_tuples!(
1279 #[doc(fake_variadic)]
1280 impl_archetype_filter_tuple,
1281 0,
1282 15,
1283 F
1284);
1285
1286all_tuples!(
1287 #[doc(fake_variadic)]
1288 impl_archetype_or_filter_tuple,
1289 0,
1290 15,
1291 F
1292);