Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose query accesses #11700

Merged
merged 10 commits into from
Feb 10, 2024
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,
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
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`.
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
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
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
/// 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.
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
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.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
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
Loading