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