bevy_ecs/query/
builder.rs1use core::marker::PhantomData;
2
3use crate::{
4 component::{ComponentId, StorageType},
5 prelude::*,
6};
7
8use super::{FilteredAccess, QueryData, QueryFilter};
9
10pub 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 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 let mut filter_access = FilteredAccess::default();
59 F::update_component_access(&filter_state, &mut filter_access);
60
61 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 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 pub fn world(&self) -> &World {
100 self.world
101 }
102
103 pub fn world_mut(&mut self) -> &mut World {
105 self.world
106 }
107
108 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 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 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 pub fn with<T: Component>(&mut self) -> &mut Self {
143 self.filter::<With<T>>();
144 self
145 }
146
147 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 pub fn without<T: Component>(&mut self) -> &mut Self {
157 self.filter::<Without<T>>();
158 self
159 }
160
161 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 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 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 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 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 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 pub fn access(&self) -> &FilteredAccess<ComponentId> {
236 &self.access
237 }
238
239 pub fn transmute<NewD: QueryData>(&mut self) -> &mut QueryBuilder<'w, NewD> {
244 self.transmute_filtered::<NewD, ()>()
245 }
246
247 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 unsafe { core::mem::transmute(self) }
266 }
267
268 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 unsafe {
421 assert_eq!(0, a.deref::<A>().0);
422 assert_eq!(1, b.deref::<B>().0);
423 }
424 }
425
426 #[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}