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