Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/query/access.rs
6600 views
1
use crate::component::ComponentId;
2
use crate::world::World;
3
use alloc::{format, string::String, vec, vec::Vec};
4
use core::{fmt, fmt::Debug};
5
use derive_more::From;
6
use fixedbitset::FixedBitSet;
7
use thiserror::Error;
8
9
/// A wrapper struct to make Debug representations of [`FixedBitSet`] easier
10
/// to read.
11
///
12
/// Instead of the raw integer representation of the `FixedBitSet`, the list of
13
/// indexes are shown.
14
///
15
/// Normal `FixedBitSet` `Debug` output:
16
/// ```text
17
/// read_and_writes: FixedBitSet { data: [ 160 ], length: 8 }
18
/// ```
19
///
20
/// Which, unless you are a computer, doesn't help much understand what's in
21
/// the set. With `FormattedBitSet`, we convert the present set entries into
22
/// what they stand for, it is much clearer what is going on:
23
/// ```text
24
/// read_and_writes: [ 5, 7 ]
25
/// ```
26
struct FormattedBitSet<'a> {
27
bit_set: &'a FixedBitSet,
28
}
29
30
impl<'a> FormattedBitSet<'a> {
31
fn new(bit_set: &'a FixedBitSet) -> Self {
32
Self { bit_set }
33
}
34
}
35
36
impl<'a> Debug for FormattedBitSet<'a> {
37
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38
f.debug_list().entries(self.bit_set.ones()).finish()
39
}
40
}
41
42
/// Tracks read and write access to specific elements in a collection.
43
///
44
/// Used internally to ensure soundness during system initialization and execution.
45
/// See the [`is_compatible`](Access::is_compatible) and [`get_conflicts`](Access::get_conflicts) functions.
46
#[derive(Eq, PartialEq, Default)]
47
pub struct Access {
48
/// All accessed components, or forbidden components if
49
/// `Self::component_read_and_writes_inverted` is set.
50
component_read_and_writes: FixedBitSet,
51
/// All exclusively-accessed components, or components that may not be
52
/// exclusively accessed if `Self::component_writes_inverted` is set.
53
component_writes: FixedBitSet,
54
/// All accessed resources.
55
resource_read_and_writes: FixedBitSet,
56
/// The exclusively-accessed resources.
57
resource_writes: FixedBitSet,
58
/// Is `true` if this component can read all components *except* those
59
/// present in `Self::component_read_and_writes`.
60
component_read_and_writes_inverted: bool,
61
/// Is `true` if this component can write to all components *except* those
62
/// present in `Self::component_writes`.
63
component_writes_inverted: bool,
64
/// Is `true` if this has access to all resources.
65
/// This field is a performance optimization for `&World` (also harder to mess up for soundness).
66
reads_all_resources: bool,
67
/// Is `true` if this has mutable access to all resources.
68
/// If this is true, then `reads_all` must also be true.
69
writes_all_resources: bool,
70
// Components that are not accessed, but whose presence in an archetype affect query results.
71
archetypal: FixedBitSet,
72
}
73
74
// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
75
impl Clone for Access {
76
fn clone(&self) -> Self {
77
Self {
78
component_read_and_writes: self.component_read_and_writes.clone(),
79
component_writes: self.component_writes.clone(),
80
resource_read_and_writes: self.resource_read_and_writes.clone(),
81
resource_writes: self.resource_writes.clone(),
82
component_read_and_writes_inverted: self.component_read_and_writes_inverted,
83
component_writes_inverted: self.component_writes_inverted,
84
reads_all_resources: self.reads_all_resources,
85
writes_all_resources: self.writes_all_resources,
86
archetypal: self.archetypal.clone(),
87
}
88
}
89
90
fn clone_from(&mut self, source: &Self) {
91
self.component_read_and_writes
92
.clone_from(&source.component_read_and_writes);
93
self.component_writes.clone_from(&source.component_writes);
94
self.resource_read_and_writes
95
.clone_from(&source.resource_read_and_writes);
96
self.resource_writes.clone_from(&source.resource_writes);
97
self.component_read_and_writes_inverted = source.component_read_and_writes_inverted;
98
self.component_writes_inverted = source.component_writes_inverted;
99
self.reads_all_resources = source.reads_all_resources;
100
self.writes_all_resources = source.writes_all_resources;
101
self.archetypal.clone_from(&source.archetypal);
102
}
103
}
104
105
impl Debug for Access {
106
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107
f.debug_struct("Access")
108
.field(
109
"component_read_and_writes",
110
&FormattedBitSet::new(&self.component_read_and_writes),
111
)
112
.field(
113
"component_writes",
114
&FormattedBitSet::new(&self.component_writes),
115
)
116
.field(
117
"resource_read_and_writes",
118
&FormattedBitSet::new(&self.resource_read_and_writes),
119
)
120
.field(
121
"resource_writes",
122
&FormattedBitSet::new(&self.resource_writes),
123
)
124
.field(
125
"component_read_and_writes_inverted",
126
&self.component_read_and_writes_inverted,
127
)
128
.field("component_writes_inverted", &self.component_writes_inverted)
129
.field("reads_all_resources", &self.reads_all_resources)
130
.field("writes_all_resources", &self.writes_all_resources)
131
.field("archetypal", &FormattedBitSet::new(&self.archetypal))
132
.finish()
133
}
134
}
135
136
impl Access {
137
/// Creates an empty [`Access`] collection.
138
pub const fn new() -> Self {
139
Self {
140
reads_all_resources: false,
141
writes_all_resources: false,
142
component_read_and_writes_inverted: false,
143
component_writes_inverted: false,
144
component_read_and_writes: FixedBitSet::new(),
145
component_writes: FixedBitSet::new(),
146
resource_read_and_writes: FixedBitSet::new(),
147
resource_writes: FixedBitSet::new(),
148
archetypal: FixedBitSet::new(),
149
}
150
}
151
152
/// Creates an [`Access`] with read access to all components.
153
/// This is equivalent to calling `read_all()` on `Access::new()`,
154
/// but is available in a `const` context.
155
pub(crate) const fn new_read_all() -> Self {
156
let mut access = Self::new();
157
access.reads_all_resources = true;
158
// Note that we cannot use `read_all_components()`
159
// because `FixedBitSet::clear()` is not `const`.
160
access.component_read_and_writes_inverted = true;
161
access
162
}
163
164
/// Creates an [`Access`] with read access to all components.
165
/// This is equivalent to calling `read_all()` on `Access::new()`,
166
/// but is available in a `const` context.
167
pub(crate) const fn new_write_all() -> Self {
168
let mut access = Self::new();
169
access.reads_all_resources = true;
170
access.writes_all_resources = true;
171
// Note that we cannot use `write_all_components()`
172
// because `FixedBitSet::clear()` is not `const`.
173
access.component_read_and_writes_inverted = true;
174
access.component_writes_inverted = true;
175
access
176
}
177
178
fn add_component_sparse_set_index_read(&mut self, index: usize) {
179
if !self.component_read_and_writes_inverted {
180
self.component_read_and_writes.grow_and_insert(index);
181
} else if index < self.component_read_and_writes.len() {
182
self.component_read_and_writes.remove(index);
183
}
184
}
185
186
fn add_component_sparse_set_index_write(&mut self, index: usize) {
187
if !self.component_writes_inverted {
188
self.component_writes.grow_and_insert(index);
189
} else if index < self.component_writes.len() {
190
self.component_writes.remove(index);
191
}
192
}
193
194
/// Adds access to the component given by `index`.
195
pub fn add_component_read(&mut self, index: ComponentId) {
196
let sparse_set_index = index.index();
197
self.add_component_sparse_set_index_read(sparse_set_index);
198
}
199
200
/// Adds exclusive access to the component given by `index`.
201
pub fn add_component_write(&mut self, index: ComponentId) {
202
let sparse_set_index = index.index();
203
self.add_component_sparse_set_index_read(sparse_set_index);
204
self.add_component_sparse_set_index_write(sparse_set_index);
205
}
206
207
/// Adds access to the resource given by `index`.
208
pub fn add_resource_read(&mut self, index: ComponentId) {
209
self.resource_read_and_writes.grow_and_insert(index.index());
210
}
211
212
/// Adds exclusive access to the resource given by `index`.
213
pub fn add_resource_write(&mut self, index: ComponentId) {
214
self.resource_read_and_writes.grow_and_insert(index.index());
215
self.resource_writes.grow_and_insert(index.index());
216
}
217
218
fn remove_component_sparse_set_index_read(&mut self, index: usize) {
219
if self.component_read_and_writes_inverted {
220
self.component_read_and_writes.grow_and_insert(index);
221
} else if index < self.component_read_and_writes.len() {
222
self.component_read_and_writes.remove(index);
223
}
224
}
225
226
fn remove_component_sparse_set_index_write(&mut self, index: usize) {
227
if self.component_writes_inverted {
228
self.component_writes.grow_and_insert(index);
229
} else if index < self.component_writes.len() {
230
self.component_writes.remove(index);
231
}
232
}
233
234
/// Removes both read and write access to the component given by `index`.
235
///
236
/// Because this method corresponds to the set difference operator ∖, it can
237
/// create complicated logical formulas that you should verify correctness
238
/// of. For example, A ∪ (B ∖ A) isn't equivalent to (A ∪ B) ∖ A, so you
239
/// can't replace a call to `remove_component_read` followed by a call to
240
/// `extend` with a call to `extend` followed by a call to
241
/// `remove_component_read`.
242
pub fn remove_component_read(&mut self, index: ComponentId) {
243
let sparse_set_index = index.index();
244
self.remove_component_sparse_set_index_write(sparse_set_index);
245
self.remove_component_sparse_set_index_read(sparse_set_index);
246
}
247
248
/// Removes write access to the component given by `index`.
249
///
250
/// Because this method corresponds to the set difference operator ∖, it can
251
/// create complicated logical formulas that you should verify correctness
252
/// of. For example, A ∪ (B ∖ A) isn't equivalent to (A ∪ B) ∖ A, so you
253
/// can't replace a call to `remove_component_write` followed by a call to
254
/// `extend` with a call to `extend` followed by a call to
255
/// `remove_component_write`.
256
pub fn remove_component_write(&mut self, index: ComponentId) {
257
let sparse_set_index = index.index();
258
self.remove_component_sparse_set_index_write(sparse_set_index);
259
}
260
261
/// Adds an archetypal (indirect) access to the component given by `index`.
262
///
263
/// This is for components whose values are not accessed (and thus will never cause conflicts),
264
/// but whose presence in an archetype may affect query results.
265
///
266
/// Currently, this is only used for [`Has<T>`] and [`Allow<T>`].
267
///
268
/// [`Has<T>`]: crate::query::Has
269
/// [`Allow<T>`]: crate::query::filter::Allow
270
pub fn add_archetypal(&mut self, index: ComponentId) {
271
self.archetypal.grow_and_insert(index.index());
272
}
273
274
/// Returns `true` if this can access the component given by `index`.
275
pub fn has_component_read(&self, index: ComponentId) -> bool {
276
self.component_read_and_writes_inverted
277
^ self.component_read_and_writes.contains(index.index())
278
}
279
280
/// Returns `true` if this can access any component.
281
pub fn has_any_component_read(&self) -> bool {
282
self.component_read_and_writes_inverted || !self.component_read_and_writes.is_clear()
283
}
284
285
/// Returns `true` if this can exclusively access the component given by `index`.
286
pub fn has_component_write(&self, index: ComponentId) -> bool {
287
self.component_writes_inverted ^ self.component_writes.contains(index.index())
288
}
289
290
/// Returns `true` if this accesses any component mutably.
291
pub fn has_any_component_write(&self) -> bool {
292
self.component_writes_inverted || !self.component_writes.is_clear()
293
}
294
295
/// Returns `true` if this can access the resource given by `index`.
296
pub fn has_resource_read(&self, index: ComponentId) -> bool {
297
self.reads_all_resources || self.resource_read_and_writes.contains(index.index())
298
}
299
300
/// Returns `true` if this can access any resource.
301
pub fn has_any_resource_read(&self) -> bool {
302
self.reads_all_resources || !self.resource_read_and_writes.is_clear()
303
}
304
305
/// Returns `true` if this can exclusively access the resource given by `index`.
306
pub fn has_resource_write(&self, index: ComponentId) -> bool {
307
self.writes_all_resources || self.resource_writes.contains(index.index())
308
}
309
310
/// Returns `true` if this accesses any resource mutably.
311
pub fn has_any_resource_write(&self) -> bool {
312
self.writes_all_resources || !self.resource_writes.is_clear()
313
}
314
315
/// Returns `true` if this accesses any resources or components.
316
pub fn has_any_read(&self) -> bool {
317
self.has_any_component_read() || self.has_any_resource_read()
318
}
319
320
/// Returns `true` if this accesses any resources or components mutably.
321
pub fn has_any_write(&self) -> bool {
322
self.has_any_component_write() || self.has_any_resource_write()
323
}
324
325
/// Returns true if this has an archetypal (indirect) access to the component given by `index`.
326
///
327
/// This is a component whose value is not accessed (and thus will never cause conflicts),
328
/// but whose presence in an archetype may affect query results.
329
///
330
/// Currently, this is only used for [`Has<T>`].
331
///
332
/// [`Has<T>`]: crate::query::Has
333
pub fn has_archetypal(&self, index: ComponentId) -> bool {
334
self.archetypal.contains(index.index())
335
}
336
337
/// Sets this as having access to all components (i.e. `EntityRef`).
338
#[inline]
339
pub fn read_all_components(&mut self) {
340
self.component_read_and_writes_inverted = true;
341
self.component_read_and_writes.clear();
342
}
343
344
/// Sets this as having mutable access to all components (i.e. `EntityMut`).
345
#[inline]
346
pub fn write_all_components(&mut self) {
347
self.read_all_components();
348
self.component_writes_inverted = true;
349
self.component_writes.clear();
350
}
351
352
/// Sets this as having access to all resources (i.e. `&World`).
353
#[inline]
354
pub const fn read_all_resources(&mut self) {
355
self.reads_all_resources = true;
356
}
357
358
/// Sets this as having mutable access to all resources (i.e. `&mut World`).
359
#[inline]
360
pub const fn write_all_resources(&mut self) {
361
self.reads_all_resources = true;
362
self.writes_all_resources = true;
363
}
364
365
/// Sets this as having access to all indexed elements (i.e. `&World`).
366
#[inline]
367
pub fn read_all(&mut self) {
368
self.read_all_components();
369
self.read_all_resources();
370
}
371
372
/// Sets this as having mutable access to all indexed elements (i.e. `&mut World`).
373
#[inline]
374
pub fn write_all(&mut self) {
375
self.write_all_components();
376
self.write_all_resources();
377
}
378
379
/// Returns `true` if this has access to all components (i.e. `EntityRef`).
380
#[inline]
381
pub fn has_read_all_components(&self) -> bool {
382
self.component_read_and_writes_inverted && self.component_read_and_writes.is_clear()
383
}
384
385
/// Returns `true` if this has write access to all components (i.e. `EntityMut`).
386
#[inline]
387
pub fn has_write_all_components(&self) -> bool {
388
self.component_writes_inverted && self.component_writes.is_clear()
389
}
390
391
/// Returns `true` if this has access to all resources (i.e. `EntityRef`).
392
#[inline]
393
pub fn has_read_all_resources(&self) -> bool {
394
self.reads_all_resources
395
}
396
397
/// Returns `true` if this has write access to all resources (i.e. `EntityMut`).
398
#[inline]
399
pub fn has_write_all_resources(&self) -> bool {
400
self.writes_all_resources
401
}
402
403
/// Returns `true` if this has access to all indexed elements (i.e. `&World`).
404
pub fn has_read_all(&self) -> bool {
405
self.has_read_all_components() && self.has_read_all_resources()
406
}
407
408
/// Returns `true` if this has write access to all indexed elements (i.e. `&mut World`).
409
pub fn has_write_all(&self) -> bool {
410
self.has_write_all_components() && self.has_write_all_resources()
411
}
412
413
/// Removes all writes.
414
pub fn clear_writes(&mut self) {
415
self.writes_all_resources = false;
416
self.component_writes_inverted = false;
417
self.component_writes.clear();
418
self.resource_writes.clear();
419
}
420
421
/// Removes all accesses.
422
pub fn clear(&mut self) {
423
self.reads_all_resources = false;
424
self.writes_all_resources = false;
425
self.component_read_and_writes_inverted = false;
426
self.component_writes_inverted = false;
427
self.component_read_and_writes.clear();
428
self.component_writes.clear();
429
self.resource_read_and_writes.clear();
430
self.resource_writes.clear();
431
}
432
433
/// Adds all access from `other`.
434
pub fn extend(&mut self, other: &Access) {
435
invertible_union_with(
436
&mut self.component_read_and_writes,
437
&mut self.component_read_and_writes_inverted,
438
&other.component_read_and_writes,
439
other.component_read_and_writes_inverted,
440
);
441
invertible_union_with(
442
&mut self.component_writes,
443
&mut self.component_writes_inverted,
444
&other.component_writes,
445
other.component_writes_inverted,
446
);
447
448
self.reads_all_resources = self.reads_all_resources || other.reads_all_resources;
449
self.writes_all_resources = self.writes_all_resources || other.writes_all_resources;
450
self.resource_read_and_writes
451
.union_with(&other.resource_read_and_writes);
452
self.resource_writes.union_with(&other.resource_writes);
453
self.archetypal.union_with(&other.archetypal);
454
}
455
456
/// Removes any access from `self` that would conflict with `other`.
457
/// This removes any reads and writes for any component written by `other`,
458
/// and removes any writes for any component read by `other`.
459
pub fn remove_conflicting_access(&mut self, other: &Access) {
460
invertible_difference_with(
461
&mut self.component_read_and_writes,
462
&mut self.component_read_and_writes_inverted,
463
&other.component_writes,
464
other.component_writes_inverted,
465
);
466
invertible_difference_with(
467
&mut self.component_writes,
468
&mut self.component_writes_inverted,
469
&other.component_read_and_writes,
470
other.component_read_and_writes_inverted,
471
);
472
473
if other.reads_all_resources {
474
self.writes_all_resources = false;
475
self.resource_writes.clear();
476
}
477
if other.writes_all_resources {
478
self.reads_all_resources = false;
479
self.resource_read_and_writes.clear();
480
}
481
self.resource_read_and_writes
482
.difference_with(&other.resource_writes);
483
self.resource_writes
484
.difference_with(&other.resource_read_and_writes);
485
}
486
487
/// Returns `true` if the access and `other` can be active at the same time,
488
/// only looking at their component access.
489
///
490
/// [`Access`] instances are incompatible if one can write
491
/// an element that the other can read or write.
492
pub fn is_components_compatible(&self, other: &Access) -> bool {
493
// We have a conflict if we write and they read or write, or if they
494
// write and we read or write.
495
for (
496
lhs_writes,
497
rhs_reads_and_writes,
498
lhs_writes_inverted,
499
rhs_reads_and_writes_inverted,
500
) in [
501
(
502
&self.component_writes,
503
&other.component_read_and_writes,
504
self.component_writes_inverted,
505
other.component_read_and_writes_inverted,
506
),
507
(
508
&other.component_writes,
509
&self.component_read_and_writes,
510
other.component_writes_inverted,
511
self.component_read_and_writes_inverted,
512
),
513
] {
514
match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
515
(true, true) => return false,
516
(false, true) => {
517
if !lhs_writes.is_subset(rhs_reads_and_writes) {
518
return false;
519
}
520
}
521
(true, false) => {
522
if !rhs_reads_and_writes.is_subset(lhs_writes) {
523
return false;
524
}
525
}
526
(false, false) => {
527
if !lhs_writes.is_disjoint(rhs_reads_and_writes) {
528
return false;
529
}
530
}
531
}
532
}
533
534
true
535
}
536
537
/// Returns `true` if the access and `other` can be active at the same time,
538
/// only looking at their resource access.
539
///
540
/// [`Access`] instances are incompatible if one can write
541
/// an element that the other can read or write.
542
pub fn is_resources_compatible(&self, other: &Access) -> bool {
543
if self.writes_all_resources {
544
return !other.has_any_resource_read();
545
}
546
547
if other.writes_all_resources {
548
return !self.has_any_resource_read();
549
}
550
551
if self.reads_all_resources {
552
return !other.has_any_resource_write();
553
}
554
555
if other.reads_all_resources {
556
return !self.has_any_resource_write();
557
}
558
559
self.resource_writes
560
.is_disjoint(&other.resource_read_and_writes)
561
&& other
562
.resource_writes
563
.is_disjoint(&self.resource_read_and_writes)
564
}
565
566
/// Returns `true` if the access and `other` can be active at the same time.
567
///
568
/// [`Access`] instances are incompatible if one can write
569
/// an element that the other can read or write.
570
pub fn is_compatible(&self, other: &Access) -> bool {
571
self.is_components_compatible(other) && self.is_resources_compatible(other)
572
}
573
574
/// Returns `true` if the set's component access is a subset of another, i.e. `other`'s component access
575
/// contains at least all the values in `self`.
576
pub fn is_subset_components(&self, other: &Access) -> bool {
577
for (
578
our_components,
579
their_components,
580
our_components_inverted,
581
their_components_inverted,
582
) in [
583
(
584
&self.component_read_and_writes,
585
&other.component_read_and_writes,
586
self.component_read_and_writes_inverted,
587
other.component_read_and_writes_inverted,
588
),
589
(
590
&self.component_writes,
591
&other.component_writes,
592
self.component_writes_inverted,
593
other.component_writes_inverted,
594
),
595
] {
596
match (our_components_inverted, their_components_inverted) {
597
(true, true) => {
598
if !their_components.is_subset(our_components) {
599
return false;
600
}
601
}
602
(true, false) => {
603
return false;
604
}
605
(false, true) => {
606
if !our_components.is_disjoint(their_components) {
607
return false;
608
}
609
}
610
(false, false) => {
611
if !our_components.is_subset(their_components) {
612
return false;
613
}
614
}
615
}
616
}
617
618
true
619
}
620
621
/// Returns `true` if the set's resource access is a subset of another, i.e. `other`'s resource access
622
/// contains at least all the values in `self`.
623
pub fn is_subset_resources(&self, other: &Access) -> bool {
624
if self.writes_all_resources {
625
return other.writes_all_resources;
626
}
627
628
if other.writes_all_resources {
629
return true;
630
}
631
632
if self.reads_all_resources {
633
return other.reads_all_resources;
634
}
635
636
if other.reads_all_resources {
637
return self.resource_writes.is_subset(&other.resource_writes);
638
}
639
640
self.resource_read_and_writes
641
.is_subset(&other.resource_read_and_writes)
642
&& self.resource_writes.is_subset(&other.resource_writes)
643
}
644
645
/// Returns `true` if the set is a subset of another, i.e. `other` contains
646
/// at least all the values in `self`.
647
pub fn is_subset(&self, other: &Access) -> bool {
648
self.is_subset_components(other) && self.is_subset_resources(other)
649
}
650
651
fn get_component_conflicts(&self, other: &Access) -> AccessConflicts {
652
let mut conflicts = FixedBitSet::new();
653
654
// We have a conflict if we write and they read or write, or if they
655
// write and we read or write.
656
for (
657
lhs_writes,
658
rhs_reads_and_writes,
659
lhs_writes_inverted,
660
rhs_reads_and_writes_inverted,
661
) in [
662
(
663
&self.component_writes,
664
&other.component_read_and_writes,
665
self.component_writes_inverted,
666
other.component_read_and_writes_inverted,
667
),
668
(
669
&other.component_writes,
670
&self.component_read_and_writes,
671
other.component_writes_inverted,
672
self.component_read_and_writes_inverted,
673
),
674
] {
675
// There's no way that I can see to do this without a temporary.
676
// Neither CNF nor DNF allows us to avoid one.
677
let temp_conflicts: FixedBitSet =
678
match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
679
(true, true) => return AccessConflicts::All,
680
(false, true) => lhs_writes.difference(rhs_reads_and_writes).collect(),
681
(true, false) => rhs_reads_and_writes.difference(lhs_writes).collect(),
682
(false, false) => lhs_writes.intersection(rhs_reads_and_writes).collect(),
683
};
684
conflicts.union_with(&temp_conflicts);
685
}
686
687
AccessConflicts::Individual(conflicts)
688
}
689
690
/// Returns a vector of elements that the access and `other` cannot access at the same time.
691
pub fn get_conflicts(&self, other: &Access) -> AccessConflicts {
692
let mut conflicts = match self.get_component_conflicts(other) {
693
AccessConflicts::All => return AccessConflicts::All,
694
AccessConflicts::Individual(conflicts) => conflicts,
695
};
696
697
if self.reads_all_resources {
698
if other.writes_all_resources {
699
return AccessConflicts::All;
700
}
701
conflicts.extend(other.resource_writes.ones());
702
}
703
704
if other.reads_all_resources {
705
if self.writes_all_resources {
706
return AccessConflicts::All;
707
}
708
conflicts.extend(self.resource_writes.ones());
709
}
710
if self.writes_all_resources {
711
conflicts.extend(other.resource_read_and_writes.ones());
712
}
713
714
if other.writes_all_resources {
715
conflicts.extend(self.resource_read_and_writes.ones());
716
}
717
718
conflicts.extend(
719
self.resource_writes
720
.intersection(&other.resource_read_and_writes),
721
);
722
conflicts.extend(
723
self.resource_read_and_writes
724
.intersection(&other.resource_writes),
725
);
726
AccessConflicts::Individual(conflicts)
727
}
728
729
/// Returns the indices of the resources this has access to.
730
pub fn resource_reads_and_writes(&self) -> impl Iterator<Item = ComponentId> + '_ {
731
self.resource_read_and_writes.ones().map(ComponentId::new)
732
}
733
734
/// Returns the indices of the resources this has non-exclusive access to.
735
pub fn resource_reads(&self) -> impl Iterator<Item = ComponentId> + '_ {
736
self.resource_read_and_writes
737
.difference(&self.resource_writes)
738
.map(ComponentId::new)
739
}
740
741
/// Returns the indices of the resources this has exclusive access to.
742
pub fn resource_writes(&self) -> impl Iterator<Item = ComponentId> + '_ {
743
self.resource_writes.ones().map(ComponentId::new)
744
}
745
746
/// Returns the indices of the components that this has an archetypal access to.
747
///
748
/// These are components whose values are not accessed (and thus will never cause conflicts),
749
/// but whose presence in an archetype may affect query results.
750
///
751
/// Currently, this is only used for [`Has<T>`].
752
///
753
/// [`Has<T>`]: crate::query::Has
754
pub fn archetypal(&self) -> impl Iterator<Item = ComponentId> + '_ {
755
self.archetypal.ones().map(ComponentId::new)
756
}
757
758
/// Returns an iterator over the component IDs and their [`ComponentAccessKind`].
759
///
760
/// Returns `Err(UnboundedAccess)` if the access is unbounded.
761
/// This typically occurs when an [`Access`] is marked as accessing all
762
/// components, and then adding exceptions.
763
///
764
/// # Examples
765
///
766
/// ```rust
767
/// # use bevy_ecs::query::{Access, ComponentAccessKind};
768
/// # use bevy_ecs::component::ComponentId;
769
/// let mut access = Access::default();
770
///
771
/// access.add_component_read(ComponentId::new(1));
772
/// access.add_component_write(ComponentId::new(2));
773
/// access.add_archetypal(ComponentId::new(3));
774
///
775
/// let result = access
776
/// .try_iter_component_access()
777
/// .map(Iterator::collect::<Vec<_>>);
778
///
779
/// assert_eq!(
780
/// result,
781
/// Ok(vec![
782
/// ComponentAccessKind::Shared(ComponentId::new(1)),
783
/// ComponentAccessKind::Exclusive(ComponentId::new(2)),
784
/// ComponentAccessKind::Archetypal(ComponentId::new(3)),
785
/// ]),
786
/// );
787
/// ```
788
pub fn try_iter_component_access(
789
&self,
790
) -> Result<impl Iterator<Item = ComponentAccessKind> + '_, UnboundedAccessError> {
791
// component_writes_inverted is only ever true when component_read_and_writes_inverted is
792
// also true. Therefore it is sufficient to check just component_read_and_writes_inverted.
793
if self.component_read_and_writes_inverted {
794
return Err(UnboundedAccessError {
795
writes_inverted: self.component_writes_inverted,
796
read_and_writes_inverted: self.component_read_and_writes_inverted,
797
});
798
}
799
800
let reads_and_writes = self.component_read_and_writes.ones().map(|index| {
801
let sparse_index = ComponentId::new(index);
802
803
if self.component_writes.contains(index) {
804
ComponentAccessKind::Exclusive(sparse_index)
805
} else {
806
ComponentAccessKind::Shared(sparse_index)
807
}
808
});
809
810
let archetypal = self
811
.archetypal
812
.ones()
813
.filter(|&index| {
814
!self.component_writes.contains(index)
815
&& !self.component_read_and_writes.contains(index)
816
})
817
.map(|index| ComponentAccessKind::Archetypal(ComponentId::new(index)));
818
819
Ok(reads_and_writes.chain(archetypal))
820
}
821
}
822
823
/// Performs an in-place union of `other` into `self`, where either set may be inverted.
824
///
825
/// Each set corresponds to a `FixedBitSet` if `inverted` is `false`,
826
/// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`.
827
///
828
/// This updates the `self` set to include any elements in the `other` set.
829
/// Note that this may change `self_inverted` to `true` if we add an infinite
830
/// set to a finite one, resulting in a new infinite set.
831
fn invertible_union_with(
832
self_set: &mut FixedBitSet,
833
self_inverted: &mut bool,
834
other_set: &FixedBitSet,
835
other_inverted: bool,
836
) {
837
match (*self_inverted, other_inverted) {
838
(true, true) => self_set.intersect_with(other_set),
839
(true, false) => self_set.difference_with(other_set),
840
(false, true) => {
841
*self_inverted = true;
842
// We have to grow here because the new bits are going to get flipped to 1.
843
self_set.grow(other_set.len());
844
self_set.toggle_range(..);
845
self_set.intersect_with(other_set);
846
}
847
(false, false) => self_set.union_with(other_set),
848
}
849
}
850
851
/// Performs an in-place set difference of `other` from `self`, where either set may be inverted.
852
///
853
/// Each set corresponds to a `FixedBitSet` if `inverted` is `false`,
854
/// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`.
855
///
856
/// This updates the `self` set to remove any elements in the `other` set.
857
/// Note that this may change `self_inverted` to `false` if we remove an
858
/// infinite set from another infinite one, resulting in a finite difference.
859
fn invertible_difference_with(
860
self_set: &mut FixedBitSet,
861
self_inverted: &mut bool,
862
other_set: &FixedBitSet,
863
other_inverted: bool,
864
) {
865
// We can share the implementation of `invertible_union_with` with some algebra:
866
// A - B = A & !B = !(!A | B)
867
*self_inverted = !*self_inverted;
868
invertible_union_with(self_set, self_inverted, other_set, other_inverted);
869
*self_inverted = !*self_inverted;
870
}
871
872
/// Error returned when attempting to iterate over items included in an [`Access`]
873
/// if the access excludes items rather than including them.
874
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
875
#[error("Access is unbounded")]
876
pub struct UnboundedAccessError {
877
/// [`Access`] is defined in terms of _excluding_ [exclusive](ComponentAccessKind::Exclusive)
878
/// access.
879
pub writes_inverted: bool,
880
/// [`Access`] is defined in terms of _excluding_ [shared](ComponentAccessKind::Shared) and
881
/// [exclusive](ComponentAccessKind::Exclusive) access.
882
pub read_and_writes_inverted: bool,
883
}
884
885
/// Describes the level of access for a particular component as defined in an [`Access`].
886
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
887
pub enum ComponentAccessKind {
888
/// Archetypical access, such as `Has<Foo>`.
889
Archetypal(ComponentId),
890
/// Shared access, such as `&Foo`.
891
Shared(ComponentId),
892
/// Exclusive access, such as `&mut Foo`.
893
Exclusive(ComponentId),
894
}
895
896
impl ComponentAccessKind {
897
/// Gets the index of this `ComponentAccessKind`.
898
pub fn index(&self) -> &ComponentId {
899
let (Self::Archetypal(value) | Self::Shared(value) | Self::Exclusive(value)) = self;
900
value
901
}
902
}
903
904
/// An [`Access`] that has been filtered to include and exclude certain combinations of elements.
905
///
906
/// Used internally to statically check if queries are disjoint.
907
///
908
/// Subtle: a `read` or `write` in `access` should not be considered to imply a
909
/// `with` access.
910
///
911
/// For example consider `Query<Option<&T>>` this only has a `read` of `T` as doing
912
/// otherwise would allow for queries to be considered disjoint when they shouldn't:
913
/// - `Query<(&mut T, Option<&U>)>` read/write `T`, read `U`, with `U`
914
/// - `Query<&mut T, Without<U>>` read/write `T`, without `U`
915
/// from this we could reasonably conclude that the queries are disjoint but they aren't.
916
///
917
/// In order to solve this the actual access that `Query<(&mut T, Option<&U>)>` has
918
/// is read/write `T`, read `U`. It must still have a read `U` access otherwise the following
919
/// queries would be incorrectly considered disjoint:
920
/// - `Query<&mut T>` read/write `T`
921
/// - `Query<Option<&T>>` accesses nothing
922
///
923
/// See comments the [`WorldQuery`](super::WorldQuery) impls of [`AnyOf`](super::AnyOf)/`Option`/[`Or`](super::Or) for more information.
924
#[derive(Debug, Eq, PartialEq)]
925
pub struct FilteredAccess {
926
pub(crate) access: Access,
927
pub(crate) required: FixedBitSet,
928
// An array of filter sets to express `With` or `Without` clauses in disjunctive normal form, for example: `Or<(With<A>, With<B>)>`.
929
// Filters like `(With<A>, Or<(With<B>, Without<C>)>` are expanded into `Or<((With<A>, With<B>), (With<A>, Without<C>))>`.
930
pub(crate) filter_sets: Vec<AccessFilters>,
931
}
932
933
// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
934
impl Clone for FilteredAccess {
935
fn clone(&self) -> Self {
936
Self {
937
access: self.access.clone(),
938
required: self.required.clone(),
939
filter_sets: self.filter_sets.clone(),
940
}
941
}
942
943
fn clone_from(&mut self, source: &Self) {
944
self.access.clone_from(&source.access);
945
self.required.clone_from(&source.required);
946
self.filter_sets.clone_from(&source.filter_sets);
947
}
948
}
949
950
impl Default for FilteredAccess {
951
fn default() -> Self {
952
Self::matches_everything()
953
}
954
}
955
956
impl From<FilteredAccess> for FilteredAccessSet {
957
fn from(filtered_access: FilteredAccess) -> Self {
958
let mut base = FilteredAccessSet::default();
959
base.add(filtered_access);
960
base
961
}
962
}
963
964
/// Records how two accesses conflict with each other
965
#[derive(Debug, PartialEq, From)]
966
pub enum AccessConflicts {
967
/// Conflict is for all indices
968
All,
969
/// There is a conflict for a subset of indices
970
Individual(FixedBitSet),
971
}
972
973
impl AccessConflicts {
974
fn add(&mut self, other: &Self) {
975
match (self, other) {
976
(s, AccessConflicts::All) => {
977
*s = AccessConflicts::All;
978
}
979
(AccessConflicts::Individual(this), AccessConflicts::Individual(other)) => {
980
this.extend(other.ones());
981
}
982
_ => {}
983
}
984
}
985
986
/// Returns true if there are no conflicts present
987
pub fn is_empty(&self) -> bool {
988
match self {
989
Self::All => false,
990
Self::Individual(set) => set.is_empty(),
991
}
992
}
993
994
pub(crate) fn format_conflict_list(&self, world: &World) -> String {
995
match self {
996
AccessConflicts::All => String::new(),
997
AccessConflicts::Individual(indices) => indices
998
.ones()
999
.map(|index| {
1000
format!(
1001
"{}",
1002
world
1003
.components
1004
.get_name(ComponentId::new(index))
1005
.unwrap()
1006
.shortname()
1007
)
1008
})
1009
.collect::<Vec<_>>()
1010
.join(", "),
1011
}
1012
}
1013
1014
/// An [`AccessConflicts`] which represents the absence of any conflict
1015
pub(crate) fn empty() -> Self {
1016
Self::Individual(FixedBitSet::new())
1017
}
1018
}
1019
1020
impl From<Vec<ComponentId>> for AccessConflicts {
1021
fn from(value: Vec<ComponentId>) -> Self {
1022
Self::Individual(value.iter().map(|c| c.index()).collect())
1023
}
1024
}
1025
1026
impl FilteredAccess {
1027
/// Returns a `FilteredAccess` which has no access and matches everything.
1028
/// This is the equivalent of a `TRUE` logic atom.
1029
pub fn matches_everything() -> Self {
1030
Self {
1031
access: Access::default(),
1032
required: FixedBitSet::default(),
1033
filter_sets: vec![AccessFilters::default()],
1034
}
1035
}
1036
1037
/// Returns a `FilteredAccess` which has no access and matches nothing.
1038
/// This is the equivalent of a `FALSE` logic atom.
1039
pub fn matches_nothing() -> Self {
1040
Self {
1041
access: Access::default(),
1042
required: FixedBitSet::default(),
1043
filter_sets: Vec::new(),
1044
}
1045
}
1046
1047
/// Returns a reference to the underlying unfiltered access.
1048
#[inline]
1049
pub fn access(&self) -> &Access {
1050
&self.access
1051
}
1052
1053
/// Returns a mutable reference to the underlying unfiltered access.
1054
#[inline]
1055
pub fn access_mut(&mut self) -> &mut Access {
1056
&mut self.access
1057
}
1058
1059
/// Adds access to the component given by `index`.
1060
pub fn add_component_read(&mut self, index: ComponentId) {
1061
self.access.add_component_read(index);
1062
self.add_required(index);
1063
self.and_with(index);
1064
}
1065
1066
/// Adds exclusive access to the component given by `index`.
1067
pub fn add_component_write(&mut self, index: ComponentId) {
1068
self.access.add_component_write(index);
1069
self.add_required(index);
1070
self.and_with(index);
1071
}
1072
1073
/// Adds access to the resource given by `index`.
1074
pub fn add_resource_read(&mut self, index: ComponentId) {
1075
self.access.add_resource_read(index);
1076
}
1077
1078
/// Adds exclusive access to the resource given by `index`.
1079
pub fn add_resource_write(&mut self, index: ComponentId) {
1080
self.access.add_resource_write(index);
1081
}
1082
1083
fn add_required(&mut self, index: ComponentId) {
1084
self.required.grow_and_insert(index.index());
1085
}
1086
1087
/// Adds a `With` filter: corresponds to a conjunction (AND) operation.
1088
///
1089
/// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
1090
/// Adding `AND With<C>` via this method transforms it into the equivalent of `Or<((With<A>, With<C>), (With<B>, With<C>))>`.
1091
pub fn and_with(&mut self, index: ComponentId) {
1092
for filter in &mut self.filter_sets {
1093
filter.with.grow_and_insert(index.index());
1094
}
1095
}
1096
1097
/// Adds a `Without` filter: corresponds to a conjunction (AND) operation.
1098
///
1099
/// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
1100
/// Adding `AND Without<C>` via this method transforms it into the equivalent of `Or<((With<A>, Without<C>), (With<B>, Without<C>))>`.
1101
pub fn and_without(&mut self, index: ComponentId) {
1102
for filter in &mut self.filter_sets {
1103
filter.without.grow_and_insert(index.index());
1104
}
1105
}
1106
1107
/// Appends an array of filters: corresponds to a disjunction (OR) operation.
1108
///
1109
/// As the underlying array of filters represents a disjunction,
1110
/// where each element (`AccessFilters`) represents a conjunction,
1111
/// we can simply append to the array.
1112
pub fn append_or(&mut self, other: &FilteredAccess) {
1113
self.filter_sets.append(&mut other.filter_sets.clone());
1114
}
1115
1116
/// Adds all of the accesses from `other` to `self`.
1117
pub fn extend_access(&mut self, other: &FilteredAccess) {
1118
self.access.extend(&other.access);
1119
}
1120
1121
/// Returns `true` if this and `other` can be active at the same time.
1122
pub fn is_compatible(&self, other: &FilteredAccess) -> bool {
1123
// Resources are read from the world rather than the filtered archetypes,
1124
// so they must be compatible even if the filters are disjoint.
1125
if !self.access.is_resources_compatible(&other.access) {
1126
return false;
1127
}
1128
1129
if self.access.is_components_compatible(&other.access) {
1130
return true;
1131
}
1132
1133
// If the access instances are incompatible, we want to check that whether filters can
1134
// guarantee that queries are disjoint.
1135
// Since the `filter_sets` array represents a Disjunctive Normal Form formula ("ORs of ANDs"),
1136
// we need to make sure that each filter set (ANDs) rule out every filter set from the `other` instance.
1137
//
1138
// For example, `Query<&mut C, Or<(With<A>, Without<B>)>>` is compatible `Query<&mut C, (With<B>, Without<A>)>`,
1139
// but `Query<&mut C, Or<(Without<A>, Without<B>)>>` isn't compatible with `Query<&mut C, Or<(With<A>, With<B>)>>`.
1140
self.filter_sets.iter().all(|filter| {
1141
other
1142
.filter_sets
1143
.iter()
1144
.all(|other_filter| filter.is_ruled_out_by(other_filter))
1145
})
1146
}
1147
1148
/// Returns a vector of elements that this and `other` cannot access at the same time.
1149
pub fn get_conflicts(&self, other: &FilteredAccess) -> AccessConflicts {
1150
if !self.is_compatible(other) {
1151
// filters are disjoint, so we can just look at the unfiltered intersection
1152
return self.access.get_conflicts(&other.access);
1153
}
1154
AccessConflicts::empty()
1155
}
1156
1157
/// Adds all access and filters from `other`.
1158
///
1159
/// Corresponds to a conjunction operation (AND) for filters.
1160
///
1161
/// Extending `Or<(With<A>, Without<B>)>` with `Or<(With<C>, Without<D>)>` will result in
1162
/// `Or<((With<A>, With<C>), (With<A>, Without<D>), (Without<B>, With<C>), (Without<B>, Without<D>))>`.
1163
pub fn extend(&mut self, other: &FilteredAccess) {
1164
self.access.extend(&other.access);
1165
self.required.union_with(&other.required);
1166
1167
// We can avoid allocating a new array of bitsets if `other` contains just a single set of filters:
1168
// in this case we can short-circuit by performing an in-place union for each bitset.
1169
if other.filter_sets.len() == 1 {
1170
for filter in &mut self.filter_sets {
1171
filter.with.union_with(&other.filter_sets[0].with);
1172
filter.without.union_with(&other.filter_sets[0].without);
1173
}
1174
return;
1175
}
1176
1177
let mut new_filters = Vec::with_capacity(self.filter_sets.len() * other.filter_sets.len());
1178
for filter in &self.filter_sets {
1179
for other_filter in &other.filter_sets {
1180
let mut new_filter = filter.clone();
1181
new_filter.with.union_with(&other_filter.with);
1182
new_filter.without.union_with(&other_filter.without);
1183
new_filters.push(new_filter);
1184
}
1185
}
1186
self.filter_sets = new_filters;
1187
}
1188
1189
/// Sets the underlying unfiltered access as having access to all indexed elements.
1190
pub fn read_all(&mut self) {
1191
self.access.read_all();
1192
}
1193
1194
/// Sets the underlying unfiltered access as having mutable access to all indexed elements.
1195
pub fn write_all(&mut self) {
1196
self.access.write_all();
1197
}
1198
1199
/// Sets the underlying unfiltered access as having access to all components.
1200
pub fn read_all_components(&mut self) {
1201
self.access.read_all_components();
1202
}
1203
1204
/// Sets the underlying unfiltered access as having mutable access to all components.
1205
pub fn write_all_components(&mut self) {
1206
self.access.write_all_components();
1207
}
1208
1209
/// Returns `true` if the set is a subset of another, i.e. `other` contains
1210
/// at least all the values in `self`.
1211
pub fn is_subset(&self, other: &FilteredAccess) -> bool {
1212
self.required.is_subset(&other.required) && self.access().is_subset(other.access())
1213
}
1214
1215
/// Returns the indices of the elements that this access filters for.
1216
pub fn with_filters(&self) -> impl Iterator<Item = ComponentId> + '_ {
1217
self.filter_sets
1218
.iter()
1219
.flat_map(|f| f.with.ones().map(ComponentId::new))
1220
}
1221
1222
/// Returns the indices of the elements that this access filters out.
1223
pub fn without_filters(&self) -> impl Iterator<Item = ComponentId> + '_ {
1224
self.filter_sets
1225
.iter()
1226
.flat_map(|f| f.without.ones().map(ComponentId::new))
1227
}
1228
1229
/// Returns true if the index is used by this `FilteredAccess` in filters or archetypal access.
1230
/// This includes most ways to access a component, but notably excludes `EntityRef` and `EntityMut`
1231
/// along with anything inside `Option<T>`.
1232
pub fn contains(&self, index: ComponentId) -> bool {
1233
self.access().has_archetypal(index)
1234
|| self
1235
.filter_sets
1236
.iter()
1237
.any(|f| f.with.contains(index.index()) || f.without.contains(index.index()))
1238
}
1239
}
1240
1241
#[derive(Eq, PartialEq, Default)]
1242
pub(crate) struct AccessFilters {
1243
pub(crate) with: FixedBitSet,
1244
pub(crate) without: FixedBitSet,
1245
}
1246
1247
// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
1248
impl Clone for AccessFilters {
1249
fn clone(&self) -> Self {
1250
Self {
1251
with: self.with.clone(),
1252
without: self.without.clone(),
1253
}
1254
}
1255
1256
fn clone_from(&mut self, source: &Self) {
1257
self.with.clone_from(&source.with);
1258
self.without.clone_from(&source.without);
1259
}
1260
}
1261
1262
impl Debug for AccessFilters {
1263
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1264
f.debug_struct("AccessFilters")
1265
.field("with", &FormattedBitSet::new(&self.with))
1266
.field("without", &FormattedBitSet::new(&self.without))
1267
.finish()
1268
}
1269
}
1270
1271
impl AccessFilters {
1272
fn is_ruled_out_by(&self, other: &Self) -> bool {
1273
// Although not technically complete, we don't consider the case when `AccessFilters`'s
1274
// `without` bitset contradicts its own `with` bitset (e.g. `(With<A>, Without<A>)`).
1275
// Such query would be considered compatible with any other query, but as it's almost
1276
// always an error, we ignore this case instead of treating such query as compatible
1277
// with others.
1278
!self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
1279
}
1280
}
1281
1282
/// A collection of [`FilteredAccess`] instances.
1283
///
1284
/// Used internally to statically check if systems have conflicting access.
1285
///
1286
/// It stores multiple sets of accesses.
1287
/// - A "combined" set, which is the access of all filters in this set combined.
1288
/// - The set of access of each individual filters in this set.
1289
#[derive(Debug, PartialEq, Eq, Default)]
1290
pub struct FilteredAccessSet {
1291
combined_access: Access,
1292
filtered_accesses: Vec<FilteredAccess>,
1293
}
1294
1295
// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
1296
impl Clone for FilteredAccessSet {
1297
fn clone(&self) -> Self {
1298
Self {
1299
combined_access: self.combined_access.clone(),
1300
filtered_accesses: self.filtered_accesses.clone(),
1301
}
1302
}
1303
1304
fn clone_from(&mut self, source: &Self) {
1305
self.combined_access.clone_from(&source.combined_access);
1306
self.filtered_accesses.clone_from(&source.filtered_accesses);
1307
}
1308
}
1309
1310
impl FilteredAccessSet {
1311
/// Creates an empty [`FilteredAccessSet`].
1312
pub const fn new() -> Self {
1313
Self {
1314
combined_access: Access::new(),
1315
filtered_accesses: Vec::new(),
1316
}
1317
}
1318
1319
/// Returns a reference to the unfiltered access of the entire set.
1320
#[inline]
1321
pub fn combined_access(&self) -> &Access {
1322
&self.combined_access
1323
}
1324
1325
/// Returns `true` if this and `other` can be active at the same time.
1326
///
1327
/// Access conflict resolution happen in two steps:
1328
/// 1. A "coarse" check, if there is no mutual unfiltered conflict between
1329
/// `self` and `other`, we already know that the two access sets are
1330
/// compatible.
1331
/// 2. A "fine grained" check, it kicks in when the "coarse" check fails.
1332
/// the two access sets might still be compatible if some of the accesses
1333
/// are restricted with the [`With`](super::With) or [`Without`](super::Without) filters so that access is
1334
/// mutually exclusive. The fine grained phase iterates over all filters in
1335
/// the `self` set and compares it to all the filters in the `other` set,
1336
/// making sure they are all mutually compatible.
1337
pub fn is_compatible(&self, other: &FilteredAccessSet) -> bool {
1338
if self.combined_access.is_compatible(other.combined_access()) {
1339
return true;
1340
}
1341
for filtered in &self.filtered_accesses {
1342
for other_filtered in &other.filtered_accesses {
1343
if !filtered.is_compatible(other_filtered) {
1344
return false;
1345
}
1346
}
1347
}
1348
true
1349
}
1350
1351
/// Returns a vector of elements that this set and `other` cannot access at the same time.
1352
pub fn get_conflicts(&self, other: &FilteredAccessSet) -> AccessConflicts {
1353
// if the unfiltered access is incompatible, must check each pair
1354
let mut conflicts = AccessConflicts::empty();
1355
if !self.combined_access.is_compatible(other.combined_access()) {
1356
for filtered in &self.filtered_accesses {
1357
for other_filtered in &other.filtered_accesses {
1358
conflicts.add(&filtered.get_conflicts(other_filtered));
1359
}
1360
}
1361
}
1362
conflicts
1363
}
1364
1365
/// Returns a vector of elements that this set and `other` cannot access at the same time.
1366
pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess) -> AccessConflicts {
1367
// if the unfiltered access is incompatible, must check each pair
1368
let mut conflicts = AccessConflicts::empty();
1369
if !self.combined_access.is_compatible(filtered_access.access()) {
1370
for filtered in &self.filtered_accesses {
1371
conflicts.add(&filtered.get_conflicts(filtered_access));
1372
}
1373
}
1374
conflicts
1375
}
1376
1377
/// Adds the filtered access to the set.
1378
pub fn add(&mut self, filtered_access: FilteredAccess) {
1379
self.combined_access.extend(&filtered_access.access);
1380
self.filtered_accesses.push(filtered_access);
1381
}
1382
1383
/// Adds a read access to a resource to the set.
1384
pub fn add_unfiltered_resource_read(&mut self, index: ComponentId) {
1385
let mut filter = FilteredAccess::default();
1386
filter.add_resource_read(index);
1387
self.add(filter);
1388
}
1389
1390
/// Adds a write access to a resource to the set.
1391
pub fn add_unfiltered_resource_write(&mut self, index: ComponentId) {
1392
let mut filter = FilteredAccess::default();
1393
filter.add_resource_write(index);
1394
self.add(filter);
1395
}
1396
1397
/// Adds read access to all resources to the set.
1398
pub fn add_unfiltered_read_all_resources(&mut self) {
1399
let mut filter = FilteredAccess::default();
1400
filter.access.read_all_resources();
1401
self.add(filter);
1402
}
1403
1404
/// Adds write access to all resources to the set.
1405
pub fn add_unfiltered_write_all_resources(&mut self) {
1406
let mut filter = FilteredAccess::default();
1407
filter.access.write_all_resources();
1408
self.add(filter);
1409
}
1410
1411
/// Adds all of the accesses from the passed set to `self`.
1412
pub fn extend(&mut self, filtered_access_set: FilteredAccessSet) {
1413
self.combined_access
1414
.extend(&filtered_access_set.combined_access);
1415
self.filtered_accesses
1416
.extend(filtered_access_set.filtered_accesses);
1417
}
1418
1419
/// Marks the set as reading all possible indices of type T.
1420
pub fn read_all(&mut self) {
1421
let mut filter = FilteredAccess::matches_everything();
1422
filter.read_all();
1423
self.add(filter);
1424
}
1425
1426
/// Marks the set as writing all T.
1427
pub fn write_all(&mut self) {
1428
let mut filter = FilteredAccess::matches_everything();
1429
filter.write_all();
1430
self.add(filter);
1431
}
1432
1433
/// Removes all accesses stored in this set.
1434
pub fn clear(&mut self) {
1435
self.combined_access.clear();
1436
self.filtered_accesses.clear();
1437
}
1438
}
1439
1440
#[cfg(test)]
1441
mod tests {
1442
use super::{invertible_difference_with, invertible_union_with};
1443
use crate::{
1444
component::ComponentId,
1445
query::{
1446
access::AccessFilters, Access, AccessConflicts, ComponentAccessKind, FilteredAccess,
1447
FilteredAccessSet, UnboundedAccessError,
1448
},
1449
};
1450
use alloc::{vec, vec::Vec};
1451
use fixedbitset::FixedBitSet;
1452
1453
fn create_sample_access() -> Access {
1454
let mut access = Access::default();
1455
1456
access.add_component_read(ComponentId::new(1));
1457
access.add_component_read(ComponentId::new(2));
1458
access.add_component_write(ComponentId::new(3));
1459
access.add_archetypal(ComponentId::new(5));
1460
access.read_all();
1461
1462
access
1463
}
1464
1465
fn create_sample_filtered_access() -> FilteredAccess {
1466
let mut filtered_access = FilteredAccess::default();
1467
1468
filtered_access.add_component_write(ComponentId::new(1));
1469
filtered_access.add_component_read(ComponentId::new(2));
1470
filtered_access.add_required(ComponentId::new(3));
1471
filtered_access.and_with(ComponentId::new(4));
1472
1473
filtered_access
1474
}
1475
1476
fn create_sample_access_filters() -> AccessFilters {
1477
let mut access_filters = AccessFilters::default();
1478
1479
access_filters.with.grow_and_insert(3);
1480
access_filters.without.grow_and_insert(5);
1481
1482
access_filters
1483
}
1484
1485
fn create_sample_filtered_access_set() -> FilteredAccessSet {
1486
let mut filtered_access_set = FilteredAccessSet::default();
1487
1488
filtered_access_set.add_unfiltered_resource_read(ComponentId::new(2));
1489
filtered_access_set.add_unfiltered_resource_write(ComponentId::new(4));
1490
filtered_access_set.read_all();
1491
1492
filtered_access_set
1493
}
1494
1495
#[test]
1496
fn test_access_clone() {
1497
let original = create_sample_access();
1498
let cloned = original.clone();
1499
1500
assert_eq!(original, cloned);
1501
}
1502
1503
#[test]
1504
fn test_access_clone_from() {
1505
let original = create_sample_access();
1506
let mut cloned = Access::default();
1507
1508
cloned.add_component_write(ComponentId::new(7));
1509
cloned.add_component_read(ComponentId::new(4));
1510
cloned.add_archetypal(ComponentId::new(8));
1511
cloned.write_all();
1512
1513
cloned.clone_from(&original);
1514
1515
assert_eq!(original, cloned);
1516
}
1517
1518
#[test]
1519
fn test_filtered_access_clone() {
1520
let original = create_sample_filtered_access();
1521
let cloned = original.clone();
1522
1523
assert_eq!(original, cloned);
1524
}
1525
1526
#[test]
1527
fn test_filtered_access_clone_from() {
1528
let original = create_sample_filtered_access();
1529
let mut cloned = FilteredAccess::default();
1530
1531
cloned.add_component_write(ComponentId::new(7));
1532
cloned.add_component_read(ComponentId::new(4));
1533
cloned.append_or(&FilteredAccess::default());
1534
1535
cloned.clone_from(&original);
1536
1537
assert_eq!(original, cloned);
1538
}
1539
1540
#[test]
1541
fn test_access_filters_clone() {
1542
let original = create_sample_access_filters();
1543
let cloned = original.clone();
1544
1545
assert_eq!(original, cloned);
1546
}
1547
1548
#[test]
1549
fn test_access_filters_clone_from() {
1550
let original = create_sample_access_filters();
1551
let mut cloned = AccessFilters::default();
1552
1553
cloned.with.grow_and_insert(1);
1554
cloned.without.grow_and_insert(2);
1555
1556
cloned.clone_from(&original);
1557
1558
assert_eq!(original, cloned);
1559
}
1560
1561
#[test]
1562
fn test_filtered_access_set_clone() {
1563
let original = create_sample_filtered_access_set();
1564
let cloned = original.clone();
1565
1566
assert_eq!(original, cloned);
1567
}
1568
1569
#[test]
1570
fn test_filtered_access_set_from() {
1571
let original = create_sample_filtered_access_set();
1572
let mut cloned = FilteredAccessSet::default();
1573
1574
cloned.add_unfiltered_resource_read(ComponentId::new(7));
1575
cloned.add_unfiltered_resource_write(ComponentId::new(9));
1576
cloned.write_all();
1577
1578
cloned.clone_from(&original);
1579
1580
assert_eq!(original, cloned);
1581
}
1582
1583
#[test]
1584
fn read_all_access_conflicts() {
1585
// read_all / single write
1586
let mut access_a = Access::default();
1587
access_a.add_component_write(ComponentId::new(0));
1588
1589
let mut access_b = Access::default();
1590
access_b.read_all();
1591
1592
assert!(!access_b.is_compatible(&access_a));
1593
1594
// read_all / read_all
1595
let mut access_a = Access::default();
1596
access_a.read_all();
1597
1598
let mut access_b = Access::default();
1599
access_b.read_all();
1600
1601
assert!(access_b.is_compatible(&access_a));
1602
}
1603
1604
#[test]
1605
fn access_get_conflicts() {
1606
let mut access_a = Access::default();
1607
access_a.add_component_read(ComponentId::new(0));
1608
access_a.add_component_read(ComponentId::new(1));
1609
1610
let mut access_b = Access::default();
1611
access_b.add_component_read(ComponentId::new(0));
1612
access_b.add_component_write(ComponentId::new(1));
1613
1614
assert_eq!(
1615
access_a.get_conflicts(&access_b),
1616
vec![ComponentId::new(1)].into()
1617
);
1618
1619
let mut access_c = Access::default();
1620
access_c.add_component_write(ComponentId::new(0));
1621
access_c.add_component_write(ComponentId::new(1));
1622
1623
assert_eq!(
1624
access_a.get_conflicts(&access_c),
1625
vec![ComponentId::new(0), ComponentId::new(1)].into()
1626
);
1627
assert_eq!(
1628
access_b.get_conflicts(&access_c),
1629
vec![ComponentId::new(0), ComponentId::new(1)].into()
1630
);
1631
1632
let mut access_d = Access::default();
1633
access_d.add_component_read(ComponentId::new(0));
1634
1635
assert_eq!(access_d.get_conflicts(&access_a), AccessConflicts::empty());
1636
assert_eq!(access_d.get_conflicts(&access_b), AccessConflicts::empty());
1637
assert_eq!(
1638
access_d.get_conflicts(&access_c),
1639
vec![ComponentId::new(0)].into()
1640
);
1641
}
1642
1643
#[test]
1644
fn filtered_combined_access() {
1645
let mut access_a = FilteredAccessSet::default();
1646
access_a.add_unfiltered_resource_read(ComponentId::new(1));
1647
1648
let mut filter_b = FilteredAccess::default();
1649
filter_b.add_resource_write(ComponentId::new(1));
1650
1651
let conflicts = access_a.get_conflicts_single(&filter_b);
1652
assert_eq!(
1653
&conflicts,
1654
&AccessConflicts::from(vec![ComponentId::new(1)]),
1655
"access_a: {access_a:?}, filter_b: {filter_b:?}"
1656
);
1657
}
1658
1659
#[test]
1660
fn filtered_access_extend() {
1661
let mut access_a = FilteredAccess::default();
1662
access_a.add_component_read(ComponentId::new(0));
1663
access_a.add_component_read(ComponentId::new(1));
1664
access_a.and_with(ComponentId::new(2));
1665
1666
let mut access_b = FilteredAccess::default();
1667
access_b.add_component_read(ComponentId::new(0));
1668
access_b.add_component_write(ComponentId::new(3));
1669
access_b.and_without(ComponentId::new(4));
1670
1671
access_a.extend(&access_b);
1672
1673
let mut expected = FilteredAccess::default();
1674
expected.add_component_read(ComponentId::new(0));
1675
expected.add_component_read(ComponentId::new(1));
1676
expected.and_with(ComponentId::new(2));
1677
expected.add_component_write(ComponentId::new(3));
1678
expected.and_without(ComponentId::new(4));
1679
1680
assert!(access_a.eq(&expected));
1681
}
1682
1683
#[test]
1684
fn filtered_access_extend_or() {
1685
let mut access_a = FilteredAccess::default();
1686
// Exclusive access to `(&mut A, &mut B)`.
1687
access_a.add_component_write(ComponentId::new(0));
1688
access_a.add_component_write(ComponentId::new(1));
1689
1690
// Filter by `With<C>`.
1691
let mut access_b = FilteredAccess::default();
1692
access_b.and_with(ComponentId::new(2));
1693
1694
// Filter by `(With<D>, Without<E>)`.
1695
let mut access_c = FilteredAccess::default();
1696
access_c.and_with(ComponentId::new(3));
1697
access_c.and_without(ComponentId::new(4));
1698
1699
// Turns `access_b` into `Or<(With<C>, (With<D>, Without<D>))>`.
1700
access_b.append_or(&access_c);
1701
// Applies the filters to the initial query, which corresponds to the FilteredAccess'
1702
// representation of `Query<(&mut A, &mut B), Or<(With<C>, (With<D>, Without<E>))>>`.
1703
access_a.extend(&access_b);
1704
1705
// Construct the expected `FilteredAccess` struct.
1706
// The intention here is to test that exclusive access implied by `add_write`
1707
// forms correct normalized access structs when extended with `Or` filters.
1708
let mut expected = FilteredAccess::default();
1709
expected.add_component_write(ComponentId::new(0));
1710
expected.add_component_write(ComponentId::new(1));
1711
// The resulted access is expected to represent `Or<((With<A>, With<B>, With<C>), (With<A>, With<B>, With<D>, Without<E>))>`.
1712
expected.filter_sets = vec![
1713
AccessFilters {
1714
with: FixedBitSet::with_capacity_and_blocks(3, [0b111]),
1715
without: FixedBitSet::default(),
1716
},
1717
AccessFilters {
1718
with: FixedBitSet::with_capacity_and_blocks(4, [0b1011]),
1719
without: FixedBitSet::with_capacity_and_blocks(5, [0b10000]),
1720
},
1721
];
1722
1723
assert_eq!(access_a, expected);
1724
}
1725
1726
#[test]
1727
fn try_iter_component_access_simple() {
1728
let mut access = Access::default();
1729
1730
access.add_component_read(ComponentId::new(1));
1731
access.add_component_read(ComponentId::new(2));
1732
access.add_component_write(ComponentId::new(3));
1733
access.add_archetypal(ComponentId::new(5));
1734
1735
let result = access
1736
.try_iter_component_access()
1737
.map(Iterator::collect::<Vec<_>>);
1738
1739
assert_eq!(
1740
result,
1741
Ok(vec![
1742
ComponentAccessKind::Shared(ComponentId::new(1)),
1743
ComponentAccessKind::Shared(ComponentId::new(2)),
1744
ComponentAccessKind::Exclusive(ComponentId::new(3)),
1745
ComponentAccessKind::Archetypal(ComponentId::new(5)),
1746
]),
1747
);
1748
}
1749
1750
#[test]
1751
fn try_iter_component_access_unbounded_write_all() {
1752
let mut access = Access::default();
1753
1754
access.add_component_read(ComponentId::new(1));
1755
access.add_component_read(ComponentId::new(2));
1756
access.write_all();
1757
1758
let result = access
1759
.try_iter_component_access()
1760
.map(Iterator::collect::<Vec<_>>);
1761
1762
assert_eq!(
1763
result,
1764
Err(UnboundedAccessError {
1765
writes_inverted: true,
1766
read_and_writes_inverted: true
1767
}),
1768
);
1769
}
1770
1771
#[test]
1772
fn try_iter_component_access_unbounded_read_all() {
1773
let mut access = Access::default();
1774
1775
access.add_component_read(ComponentId::new(1));
1776
access.add_component_read(ComponentId::new(2));
1777
access.read_all();
1778
1779
let result = access
1780
.try_iter_component_access()
1781
.map(Iterator::collect::<Vec<_>>);
1782
1783
assert_eq!(
1784
result,
1785
Err(UnboundedAccessError {
1786
writes_inverted: false,
1787
read_and_writes_inverted: true
1788
}),
1789
);
1790
}
1791
1792
/// Create a `FixedBitSet` with a given number of total bits and a given list of bits to set.
1793
/// Setting the number of bits is important in tests since the `PartialEq` impl checks that the length matches.
1794
fn bit_set(bits: usize, iter: impl IntoIterator<Item = usize>) -> FixedBitSet {
1795
let mut result = FixedBitSet::with_capacity(bits);
1796
result.extend(iter);
1797
result
1798
}
1799
1800
#[test]
1801
fn invertible_union_with_tests() {
1802
let invertible_union = |mut self_inverted: bool, other_inverted: bool| {
1803
// Check all four possible bit states: In both sets, the first, the second, or neither
1804
let mut self_set = bit_set(4, [0, 1]);
1805
let other_set = bit_set(4, [0, 2]);
1806
invertible_union_with(
1807
&mut self_set,
1808
&mut self_inverted,
1809
&other_set,
1810
other_inverted,
1811
);
1812
(self_set, self_inverted)
1813
};
1814
1815
// Check each combination of `inverted` flags
1816
let (s, i) = invertible_union(false, false);
1817
// [0, 1] | [0, 2] = [0, 1, 2]
1818
assert_eq!((s, i), (bit_set(4, [0, 1, 2]), false));
1819
1820
let (s, i) = invertible_union(false, true);
1821
// [0, 1] | [1, 3, ...] = [0, 1, 3, ...]
1822
assert_eq!((s, i), (bit_set(4, [2]), true));
1823
1824
let (s, i) = invertible_union(true, false);
1825
// [2, 3, ...] | [0, 2] = [0, 2, 3, ...]
1826
assert_eq!((s, i), (bit_set(4, [1]), true));
1827
1828
let (s, i) = invertible_union(true, true);
1829
// [2, 3, ...] | [1, 3, ...] = [1, 2, 3, ...]
1830
assert_eq!((s, i), (bit_set(4, [0]), true));
1831
}
1832
1833
#[test]
1834
fn invertible_union_with_different_lengths() {
1835
// When adding a large inverted set to a small normal set,
1836
// make sure we invert the bits beyond the original length.
1837
// Failing to call `grow` before `toggle_range` would cause bit 1 to be zero,
1838
// which would incorrectly treat it as included in the output set.
1839
let mut self_set = bit_set(1, [0]);
1840
let mut self_inverted = false;
1841
let other_set = bit_set(3, [0, 1]);
1842
let other_inverted = true;
1843
invertible_union_with(
1844
&mut self_set,
1845
&mut self_inverted,
1846
&other_set,
1847
other_inverted,
1848
);
1849
1850
// [0] | [2, ...] = [0, 2, ...]
1851
assert_eq!((self_set, self_inverted), (bit_set(3, [1]), true));
1852
}
1853
1854
#[test]
1855
fn invertible_difference_with_tests() {
1856
let invertible_difference = |mut self_inverted: bool, other_inverted: bool| {
1857
// Check all four possible bit states: In both sets, the first, the second, or neither
1858
let mut self_set = bit_set(4, [0, 1]);
1859
let other_set = bit_set(4, [0, 2]);
1860
invertible_difference_with(
1861
&mut self_set,
1862
&mut self_inverted,
1863
&other_set,
1864
other_inverted,
1865
);
1866
(self_set, self_inverted)
1867
};
1868
1869
// Check each combination of `inverted` flags
1870
let (s, i) = invertible_difference(false, false);
1871
// [0, 1] - [0, 2] = [1]
1872
assert_eq!((s, i), (bit_set(4, [1]), false));
1873
1874
let (s, i) = invertible_difference(false, true);
1875
// [0, 1] - [1, 3, ...] = [0]
1876
assert_eq!((s, i), (bit_set(4, [0]), false));
1877
1878
let (s, i) = invertible_difference(true, false);
1879
// [2, 3, ...] - [0, 2] = [3, ...]
1880
assert_eq!((s, i), (bit_set(4, [0, 1, 2]), true));
1881
1882
let (s, i) = invertible_difference(true, true);
1883
// [2, 3, ...] - [1, 3, ...] = [2]
1884
assert_eq!((s, i), (bit_set(4, [2]), false));
1885
}
1886
}
1887
1888