bevy_ecs/query/
builder.rs

1use core::marker::PhantomData;
2
3use crate::{
4    component::{ComponentId, StorageType},
5    prelude::*,
6};
7
8use super::{FilteredAccess, QueryData, QueryFilter};
9
10/// Builder struct to create [`QueryState`] instances at runtime.
11///
12/// ```
13/// # use bevy_ecs::prelude::*;
14/// #
15/// # #[derive(Component)]
16/// # struct A;
17/// #
18/// # #[derive(Component)]
19/// # struct B;
20/// #
21/// # #[derive(Component)]
22/// # struct C;
23/// #
24/// let mut world = World::new();
25/// let entity_a = world.spawn((A, B)).id();
26/// let entity_b = world.spawn((A, C)).id();
27///
28/// // Instantiate the builder using the type signature of the iterator you will consume
29/// let mut query = QueryBuilder::<(Entity, &B)>::new(&mut world)
30/// // Add additional terms through builder methods
31///     .with::<A>()
32///     .without::<C>()
33///     .build();
34///
35/// // Consume the QueryState
36/// let (entity, b) = query.single(&world);
37/// ```
38pub struct QueryBuilder<'w, D: QueryData = (), F: QueryFilter = ()> {
39    access: FilteredAccess<ComponentId>,
40    world: &'w mut World,
41    or: bool,
42    first: bool,
43    _marker: PhantomData<(D, F)>,
44}
45
46impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> {
47    /// Creates a new builder with the accesses required for `Q` and `F`
48    pub fn new(world: &'w mut World) -> Self {
49        let fetch_state = D::init_state(world);
50        let filter_state = F::init_state(world);
51
52        let mut access = FilteredAccess::default();
53        D::update_component_access(&fetch_state, &mut access);
54
55        // Use a temporary empty FilteredAccess for filters. This prevents them from conflicting with the
56        // main Query's `fetch_state` access. Filters are allowed to conflict with the main query fetch
57        // because they are evaluated *before* a specific reference is constructed.
58        let mut filter_access = FilteredAccess::default();
59        F::update_component_access(&filter_state, &mut filter_access);
60
61        // Merge the temporary filter access with the main access. This ensures that filter access is
62        // properly considered in a global "cross-query" context (both within systems and across systems).
63        access.extend(&filter_access);
64
65        Self {
66            access,
67            world,
68            or: false,
69            first: false,
70            _marker: PhantomData,
71        }
72    }
73
74    pub(super) fn is_dense(&self) -> bool {
75        // Note: `component_id` comes from the user in safe code, so we cannot trust it to
76        // exist. If it doesn't exist we pessimistically assume it's sparse.
77        let is_dense = |component_id| {
78            self.world()
79                .components()
80                .get_info(component_id)
81                .map_or(false, |info| info.storage_type() == StorageType::Table)
82        };
83
84        #[allow(deprecated)]
85        let (mut component_reads_and_writes, component_reads_and_writes_inverted) =
86            self.access.access().component_reads_and_writes();
87        if component_reads_and_writes_inverted {
88            return false;
89        }
90
91        component_reads_and_writes.all(is_dense)
92            && self.access.access().archetypal().all(is_dense)
93            && !self.access.access().has_read_all_components()
94            && self.access.with_filters().all(is_dense)
95            && self.access.without_filters().all(is_dense)
96    }
97
98    /// Returns a reference to the world passed to [`Self::new`].
99    pub fn world(&self) -> &World {
100        self.world
101    }
102
103    /// Returns a mutable reference to the world passed to [`Self::new`].
104    pub fn world_mut(&mut self) -> &mut World {
105        self.world
106    }
107
108    /// Adds access to self's underlying [`FilteredAccess`] respecting [`Self::or`] and [`Self::and`]
109    pub fn extend_access(&mut self, mut access: FilteredAccess<ComponentId>) {
110        if self.or {
111            if self.first {
112                access.required.clear();
113                self.access.extend(&access);
114                self.first = false;
115            } else {
116                self.access.append_or(&access);
117            }
118        } else {
119            self.access.extend(&access);
120        }
121    }
122
123    /// Adds accesses required for `T` to self.
124    pub fn data<T: QueryData>(&mut self) -> &mut Self {
125        let state = T::init_state(self.world);
126        let mut access = FilteredAccess::default();
127        T::update_component_access(&state, &mut access);
128        self.extend_access(access);
129        self
130    }
131
132    /// Adds filter from `T` to self.
133    pub fn filter<T: QueryFilter>(&mut self) -> &mut Self {
134        let state = T::init_state(self.world);
135        let mut access = FilteredAccess::default();
136        T::update_component_access(&state, &mut access);
137        self.extend_access(access);
138        self
139    }
140
141    /// Adds [`With<T>`] to the [`FilteredAccess`] of self.
142    pub fn with<T: Component>(&mut self) -> &mut Self {
143        self.filter::<With<T>>();
144        self
145    }
146
147    /// Adds [`With<T>`] to the [`FilteredAccess`] of self from a runtime [`ComponentId`].
148    pub fn with_id(&mut self, id: ComponentId) -> &mut Self {
149        let mut access = FilteredAccess::default();
150        access.and_with(id);
151        self.extend_access(access);
152        self
153    }
154
155    /// Adds [`Without<T>`] to the [`FilteredAccess`] of self.
156    pub fn without<T: Component>(&mut self) -> &mut Self {
157        self.filter::<Without<T>>();
158        self
159    }
160
161    /// Adds [`Without<T>`] to the [`FilteredAccess`] of self from a runtime [`ComponentId`].
162    pub fn without_id(&mut self, id: ComponentId) -> &mut Self {
163        let mut access = FilteredAccess::default();
164        access.and_without(id);
165        self.extend_access(access);
166        self
167    }
168
169    /// Adds `&T` to the [`FilteredAccess`] of self.
170    pub fn ref_id(&mut self, id: ComponentId) -> &mut Self {
171        self.with_id(id);
172        self.access.add_component_read(id);
173        self
174    }
175
176    /// Adds `&mut T` to the [`FilteredAccess`] of self.
177    pub fn mut_id(&mut self, id: ComponentId) -> &mut Self {
178        self.with_id(id);
179        self.access.add_component_write(id);
180        self
181    }
182
183    /// Takes a function over mutable access to a [`QueryBuilder`], calls that function
184    /// on an empty builder and then adds all accesses from that builder to self as optional.
185    pub fn optional(&mut self, f: impl Fn(&mut QueryBuilder)) -> &mut Self {
186        let mut builder = QueryBuilder::new(self.world);
187        f(&mut builder);
188        self.access.extend_access(builder.access());
189        self
190    }
191
192    /// Takes a function over mutable access to a [`QueryBuilder`], calls that function
193    /// on an empty builder and then adds all accesses from that builder to self.
194    ///
195    /// Primarily used when inside a [`Self::or`] closure to group several terms.
196    pub fn and(&mut self, f: impl Fn(&mut QueryBuilder)) -> &mut Self {
197        let mut builder = QueryBuilder::new(self.world);
198        f(&mut builder);
199        let access = builder.access().clone();
200        self.extend_access(access);
201        self
202    }
203
204    /// Takes a function over mutable access to a [`QueryBuilder`], calls that function
205    /// on an empty builder, all accesses added to that builder will become terms in an or expression.
206    ///
207    /// ```
208    /// # use bevy_ecs::prelude::*;
209    /// #
210    /// # #[derive(Component)]
211    /// # struct A;
212    /// #
213    /// # #[derive(Component)]
214    /// # struct B;
215    /// #
216    /// # let mut world = World::new();
217    /// #
218    /// QueryBuilder::<Entity>::new(&mut world).or(|builder| {
219    ///     builder.with::<A>();
220    ///     builder.with::<B>();
221    /// });
222    /// // is equivalent to
223    /// QueryBuilder::<Entity>::new(&mut world).filter::<Or<(With<A>, With<B>)>>();
224    /// ```
225    pub fn or(&mut self, f: impl Fn(&mut QueryBuilder)) -> &mut Self {
226        let mut builder = QueryBuilder::new(self.world);
227        builder.or = true;
228        builder.first = true;
229        f(&mut builder);
230        self.access.extend(builder.access());
231        self
232    }
233
234    /// Returns a reference to the [`FilteredAccess`] that will be provided to the built [`Query`].
235    pub fn access(&self) -> &FilteredAccess<ComponentId> {
236        &self.access
237    }
238
239    /// Transmute the existing builder adding required accesses.
240    /// This will maintain all existing accesses.
241    ///
242    /// If including a filter type see [`Self::transmute_filtered`]
243    pub fn transmute<NewD: QueryData>(&mut self) -> &mut QueryBuilder<'w, NewD> {
244        self.transmute_filtered::<NewD, ()>()
245    }
246
247    /// Transmute the existing builder adding required accesses.
248    /// This will maintain all existing accesses.
249    pub fn transmute_filtered<NewD: QueryData, NewF: QueryFilter>(
250        &mut self,
251    ) -> &mut QueryBuilder<'w, NewD, NewF> {
252        let mut fetch_state = NewD::init_state(self.world);
253        let filter_state = NewF::init_state(self.world);
254
255        NewD::set_access(&mut fetch_state, &self.access);
256
257        let mut access = FilteredAccess::default();
258        NewD::update_component_access(&fetch_state, &mut access);
259        NewF::update_component_access(&filter_state, &mut access);
260
261        self.extend_access(access);
262        // SAFETY:
263        // - We have included all required accesses for NewQ and NewF
264        // - The layout of all QueryBuilder instances is the same
265        unsafe { core::mem::transmute(self) }
266    }
267
268    /// Create a [`QueryState`] with the accesses of the builder.
269    ///
270    /// Takes `&mut self` to access the inner world reference while initializing
271    /// state for the new [`QueryState`]
272    pub fn build(&mut self) -> QueryState<D, F> {
273        QueryState::<D, F>::from_builder(self)
274    }
275}
276
277#[cfg(test)]
278mod tests {
279    use crate as bevy_ecs;
280    use crate::{prelude::*, world::FilteredEntityRef};
281
282    #[derive(Component, PartialEq, Debug)]
283    struct A(usize);
284
285    #[derive(Component, PartialEq, Debug)]
286    struct B(usize);
287
288    #[derive(Component, PartialEq, Debug)]
289    struct C(usize);
290
291    #[test]
292    fn builder_with_without_static() {
293        let mut world = World::new();
294        let entity_a = world.spawn((A(0), B(0))).id();
295        let entity_b = world.spawn((A(0), C(0))).id();
296
297        let mut query_a = QueryBuilder::<Entity>::new(&mut world)
298            .with::<A>()
299            .without::<C>()
300            .build();
301        assert_eq!(entity_a, query_a.single(&world));
302
303        let mut query_b = QueryBuilder::<Entity>::new(&mut world)
304            .with::<A>()
305            .without::<B>()
306            .build();
307        assert_eq!(entity_b, query_b.single(&world));
308    }
309
310    #[test]
311    fn builder_with_without_dynamic() {
312        let mut world = World::new();
313        let entity_a = world.spawn((A(0), B(0))).id();
314        let entity_b = world.spawn((A(0), C(0))).id();
315        let component_id_a = world.register_component::<A>();
316        let component_id_b = world.register_component::<B>();
317        let component_id_c = world.register_component::<C>();
318
319        let mut query_a = QueryBuilder::<Entity>::new(&mut world)
320            .with_id(component_id_a)
321            .without_id(component_id_c)
322            .build();
323        assert_eq!(entity_a, query_a.single(&world));
324
325        let mut query_b = QueryBuilder::<Entity>::new(&mut world)
326            .with_id(component_id_a)
327            .without_id(component_id_b)
328            .build();
329        assert_eq!(entity_b, query_b.single(&world));
330    }
331
332    #[test]
333    fn builder_or() {
334        let mut world = World::new();
335        world.spawn((A(0), B(0)));
336        world.spawn(B(0));
337        world.spawn(C(0));
338
339        let mut query_a = QueryBuilder::<Entity>::new(&mut world)
340            .or(|builder| {
341                builder.with::<A>();
342                builder.with::<B>();
343            })
344            .build();
345        assert_eq!(2, query_a.iter(&world).count());
346
347        let mut query_b = QueryBuilder::<Entity>::new(&mut world)
348            .or(|builder| {
349                builder.with::<A>();
350                builder.without::<B>();
351            })
352            .build();
353        dbg!(&query_b.component_access);
354        assert_eq!(2, query_b.iter(&world).count());
355
356        let mut query_c = QueryBuilder::<Entity>::new(&mut world)
357            .or(|builder| {
358                builder.with::<A>();
359                builder.with::<B>();
360                builder.with::<C>();
361            })
362            .build();
363        assert_eq!(3, query_c.iter(&world).count());
364    }
365
366    #[test]
367    fn builder_transmute() {
368        let mut world = World::new();
369        world.spawn(A(0));
370        world.spawn((A(1), B(0)));
371        let mut query = QueryBuilder::<()>::new(&mut world)
372            .with::<B>()
373            .transmute::<&A>()
374            .build();
375
376        query.iter(&world).for_each(|a| assert_eq!(a.0, 1));
377    }
378
379    #[test]
380    fn builder_static_components() {
381        let mut world = World::new();
382        let entity = world.spawn((A(0), B(1))).id();
383
384        let mut query = QueryBuilder::<FilteredEntityRef>::new(&mut world)
385            .data::<&A>()
386            .data::<&B>()
387            .build();
388
389        let entity_ref = query.single(&world);
390
391        assert_eq!(entity, entity_ref.id());
392
393        let a = entity_ref.get::<A>().unwrap();
394        let b = entity_ref.get::<B>().unwrap();
395
396        assert_eq!(0, a.0);
397        assert_eq!(1, b.0);
398    }
399
400    #[test]
401    fn builder_dynamic_components() {
402        let mut world = World::new();
403        let entity = world.spawn((A(0), B(1))).id();
404        let component_id_a = world.register_component::<A>();
405        let component_id_b = world.register_component::<B>();
406
407        let mut query = QueryBuilder::<FilteredEntityRef>::new(&mut world)
408            .ref_id(component_id_a)
409            .ref_id(component_id_b)
410            .build();
411
412        let entity_ref = query.single(&world);
413
414        assert_eq!(entity, entity_ref.id());
415
416        let a = entity_ref.get_by_id(component_id_a).unwrap();
417        let b = entity_ref.get_by_id(component_id_b).unwrap();
418
419        // SAFETY: We set these pointers to point to these components
420        unsafe {
421            assert_eq!(0, a.deref::<A>().0);
422            assert_eq!(1, b.deref::<B>().0);
423        }
424    }
425
426    /// Regression test for issue #14348
427    #[test]
428    fn builder_static_dense_dynamic_sparse() {
429        #[derive(Component)]
430        struct Dense;
431
432        #[derive(Component)]
433        #[component(storage = "SparseSet")]
434        struct Sparse;
435
436        let mut world = World::new();
437
438        world.spawn(Dense);
439        world.spawn((Dense, Sparse));
440
441        let mut query = QueryBuilder::<&Dense>::new(&mut world)
442            .with::<Sparse>()
443            .build();
444
445        let matched = query.iter(&world).count();
446        assert_eq!(matched, 1);
447    }
448}