Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions crates/bevy_ecs/src/query/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub struct Access<T: SparseSetIndex> {
/// Is `true` if this has mutable access to all elements in the collection.
/// If this is true, then `reads_all` must also be true.
writes_all: bool,
// Elements that are not accessed, but whose presence in an archetype affect query results.
archetypal: FixedBitSet,
marker: PhantomData<T>,
}

Expand Down Expand Up @@ -90,6 +92,7 @@ impl<T: SparseSetIndex> Access<T> {
writes_all: false,
reads_and_writes: FixedBitSet::new(),
writes: FixedBitSet::new(),
archetypal: FixedBitSet::new(),
marker: PhantomData,
}
}
Expand All @@ -116,6 +119,12 @@ impl<T: SparseSetIndex> Access<T> {
self.writes.insert(index.sparse_set_index());
}

/// Adds an archetypal (inderect) access to the element given by `index`.
pub fn add_archetypal(&mut self, index: T) {
self.archetypal.grow(index.sparse_set_index() + 1);
self.archetypal.insert(index.sparse_set_index());
}

/// Returns `true` if this can access the element given by `index`.
pub fn has_read(&self, index: T) -> bool {
self.reads_all || self.reads_and_writes.contains(index.sparse_set_index())
Expand All @@ -136,6 +145,14 @@ impl<T: SparseSetIndex> Access<T> {
self.writes_all || !self.writes.is_clear()
}

/// Returns true if this has an archetypal (indirect) access to the element given by `index`.
///
/// This is an element that is not accessed (and thus will never lead to conflicts),
/// but whose presence in an archetype affects a query result.
pub fn has_archetypal(&self, index: T) -> bool {
self.archetypal.contains(index.sparse_set_index())
}

/// Sets this as having access to all indexed elements (i.e. `&World`).
pub fn read_all(&mut self) {
self.reads_all = true;
Expand Down Expand Up @@ -272,6 +289,14 @@ impl<T: SparseSetIndex> Access<T> {
pub fn writes(&self) -> impl Iterator<Item = T> + '_ {
self.writes.ones().map(T::get_sparse_set_index)
}

/// Returns the indices of the elements that this has an archetypal access to.
///
/// Archetypal accesses will never lead to conflicts, but the presence of the data
/// they refer to affects query results
pub fn archetypal(&self) -> impl Iterator<Item = T> + '_ {
self.archetypal.ones().map(T::get_sparse_set_index)
}
}

/// An [`Access`] that has been filtered to include and exclude certain combinations of elements.
Expand Down Expand Up @@ -469,6 +494,20 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
pub fn is_subset(&self, other: &FilteredAccess<T>) -> bool {
self.required.is_subset(&other.required) && self.access().is_subset(other.access())
}

/// Returns the components this access filters for.
pub fn get_with(&self) -> impl Iterator<Item = T> + '_ {
self.filter_sets
.iter()
.flat_map(|f| f.with.ones().map(T::get_sparse_set_index))
}

/// Returns the components this access filters out.
pub fn get_without(&self) -> impl Iterator<Item = T> + '_ {
self.filter_sets
.iter()
.flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
}
}

#[derive(Clone, Eq, PartialEq)]
Expand Down
20 changes: 20 additions & 0 deletions crates/bevy_ecs/src/query/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,26 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
) -> &QueryState<NewD, NewF> {
&*(self as *const QueryState<D, F> as *const QueryState<NewD, NewF>)
}

/// Returns the archetype components accessed by this query.
pub fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
&self.archetype_component_access
}

/// Returns the components accessed by this query.
pub fn component_access(&self) -> &FilteredAccess<ComponentId> {
&self.component_access
}

/// Returns the tables matched by this query.
pub fn matched_tables(&self) -> &[TableId] {
&self.matched_table_ids
}

/// Returns the archetypes matched by this query.
pub fn matched_archetypes(&self) -> &[ArchetypeId] {
&self.matched_archetype_ids
}
}

impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
Expand Down