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