Improve bevy_ecs query docs (#1935)

Mainly documents Query, WorldQuery and the various Query Filter types as well as some smaller doc changes.
This commit is contained in:
Lukas Wirth 2021-04-22 19:09:09 +00:00
parent 19f467ebd0
commit 7c274e5a44
11 changed files with 396 additions and 97 deletions

View file

@ -10,19 +10,19 @@ use std::{
};
use thiserror::Error;
/// A component is data associated with an `Entity`. Each entity can have multiple different types
/// of components, but only one of them per type.
/// A component is data associated with an [`Entity`](crate::entity::Entity). Each entity can have
/// multiple different types of components, but only one of them per type.
///
/// Any type that is `Send + Sync + 'static` automatically implements `Component`.
///
/// Components are added with new entities using [Commands::spawn](crate::system::Commands::spawn),
/// or to existing entities with [Commands::insert](crate::system::Commands::insert),
/// or their [World](crate::world::World) equivalents.
/// Components are added with new entities using [`Commands::spawn`](crate::system::Commands::spawn),
/// or to existing entities with [`EntityCommands::insert`](crate::system::EntityCommands::insert),
/// or their [`World`](crate::world::World) equivalents.
///
/// Components can be accessed in systems by using a [Query](crate::system::Query)
/// Components can be accessed in systems by using a [`Query`](crate::system::Query)
/// as one of the arguments.
///
/// Components can be grouped together into a [Bundle](crate::bundle::Bundle).
/// Components can be grouped together into a [`Bundle`](crate::bundle::Bundle).
pub trait Component: Send + Sync + 'static {}
impl<T: Send + Sync + 'static> Component for T {}
@ -241,6 +241,7 @@ impl Components {
}
/// # Safety
///
/// `id` must be a valid [ComponentId]
#[inline]
pub unsafe fn get_info_unchecked(&self, id: ComponentId) -> &ComponentInfo {

View file

@ -1,6 +1,6 @@
use std::{alloc::Layout, any::TypeId};
/// Metadata required to store a component
/// Metadata required to store a component.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeInfo {
type_id: TypeId,
@ -11,7 +11,7 @@ pub struct TypeInfo {
}
impl TypeInfo {
/// Metadata for `T`
/// Metadata for `T`.
pub fn of<T: Send + Sync + 'static>() -> Self {
Self {
type_id: TypeId::of::<T>(),

View file

@ -11,15 +11,15 @@ use std::{
sync::atomic::{AtomicI64, Ordering},
};
/// Lightweight unique ID of an entity
/// Lightweight unique ID of an entity.
///
/// Obtained from [World::spawn](crate::world::World::spawn), typically via
/// [Commands::spawn](crate::system::Commands::spawn). Can be stored to refer to an entity in the
/// Obtained from [`World::spawn`](crate::world::World::spawn), typically via
/// [`Commands::spawn`](crate::system::Commands::spawn). Can be stored to refer to an entity in the
/// future.
///
/// `Entity` can be a part of a query, e.g. `Query<(Entity, &MyComponent)>`.
/// Components of a specific entity can be accessed using
/// [Query::get](crate::system::Query::get) and related methods.
/// [`Query::get`](crate::system::Query::get) and related methods.
#[derive(Clone, Copy, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Entity {
pub(crate) generation: u32,
@ -27,12 +27,12 @@ pub struct Entity {
}
impl Entity {
/// Creates a new entity reference with a generation of 0
/// Creates a new entity reference with a generation of 0.
pub fn new(id: u32) -> Entity {
Entity { id, generation: 0 }
}
/// Convert to a form convenient for passing outside of rust
/// Convert to a form convenient for passing outside of rust.
///
/// Only useful for identifying entities within the same instance of an application. Do not use
/// for serialization between runs.
@ -42,7 +42,7 @@ impl Entity {
u64::from(self.generation) << 32 | u64::from(self.id)
}
/// Reconstruct an `Entity` previously destructured with `to_bits`
/// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
///
/// Only useful when applied to results from `to_bits` in the same instance of an application.
pub fn from_bits(bits: u64) -> Self {
@ -52,7 +52,7 @@ impl Entity {
}
}
/// Return a transiently unique identifier
/// Return a transiently unique identifier.
///
/// No two simultaneously-live entities share the same ID, but dead entities' IDs may collide
/// with both live and dead entities. Useful for compactly representing entities within a
@ -87,7 +87,8 @@ impl SparseSetIndex for Entity {
}
}
/// An iterator returning a sequence of Entity values from `Entities::reserve_entities`.
/// An [`Iterator`] returning a sequence of [`Entity`] values from
/// [`Entities::reserve_entities`](crate::entity::Entities::reserve_entities).
pub struct ReserveEntitiesIterator<'a> {
// Metas, so we can recover the current generation for anything in the freelist.
meta: &'a [EntityMeta],
@ -165,7 +166,7 @@ pub struct Entities {
}
impl Entities {
/// Reserve entity IDs concurrently
/// Reserve entity IDs concurrently.
///
/// Storage for entity generation and location is lazily allocated by calling `flush`.
pub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator {
@ -207,7 +208,7 @@ impl Entities {
}
}
/// Reserve one entity ID concurrently
/// Reserve one entity ID concurrently.
///
/// Equivalent to `self.reserve_entities(1).next().unwrap()`, but more efficient.
pub fn reserve_entity(&self) -> Entity {
@ -240,7 +241,7 @@ impl Entities {
);
}
/// Allocate an entity ID directly
/// Allocate an entity ID directly.
///
/// Location should be written immediately.
pub fn alloc(&mut self) -> Entity {
@ -261,7 +262,7 @@ impl Entities {
}
}
/// Allocate a specific entity ID, overwriting its generation
/// Allocate a specific entity ID, overwriting its generation.
///
/// Returns the location of the entity currently using the given ID, if any. Location should be
/// written immediately.
@ -293,7 +294,7 @@ impl Entities {
loc
}
/// Destroy an entity, allowing it to be reused
/// Destroy an entity, allowing it to be reused.
///
/// Must not be called while reserved entities are awaiting `flush()`.
pub fn free(&mut self, entity: Entity) -> Option<EntityLocation> {
@ -315,7 +316,7 @@ impl Entities {
Some(loc)
}
/// Ensure at least `n` allocations can succeed without reallocating
/// Ensure at least `n` allocations can succeed without reallocating.
pub fn reserve(&mut self, additional: u32) {
self.verify_flushed();
@ -340,7 +341,7 @@ impl Entities {
*self.free_cursor.get_mut() = 0;
}
/// Access the location storage of an entity
/// Access the location storage of an entity.
///
/// Must not be called on pending entities.
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut EntityLocation> {
@ -352,7 +353,7 @@ impl Entities {
}
}
/// Returns `Ok(Location { archetype: 0, index: undefined })` for pending entities
/// Returns `Ok(Location { archetype: 0, index: undefined })` for pending entities.
pub fn get(&self, entity: Entity) -> Option<EntityLocation> {
if (entity.id as usize) < self.meta.len() {
let meta = &self.meta[entity.id as usize];
@ -368,6 +369,7 @@ impl Entities {
/// Panics if the given id would represent an index outside of `meta`.
///
/// # Safety
///
/// Must only be called for currently allocated `id`s.
pub unsafe fn resolve_unknown_gen(&self, id: u32) -> Entity {
let meta_len = self.meta.len();
@ -463,7 +465,7 @@ impl EntityMeta {
};
}
/// A location of an entity in an archetype
/// A location of an entity in an archetype.
#[derive(Copy, Clone, Debug)]
pub struct EntityLocation {
/// The archetype index

View file

@ -69,7 +69,7 @@ enum State {
///
/// [`Events::update_system`] is a system that does this, typically intialized automatically using
/// [`AppBuilder::add_event`]. [EventReader]s are expected to read events from this collection at
/// least once per loop/frame.
/// least once per loop/frame.
/// Events will persist across a single frame boundary and so ordering of event producers and
/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).
/// If events are not handled by the end of the frame after they are updated, they will be
@ -116,6 +116,8 @@ enum State {
/// when events are cleared.
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
/// but can be done by adding your event as a resource instead of using [`AppBuilder::add_event`].
///
/// [`AppBuilder::add_event`]: https://docs.rs/bevy/*/bevy/app/struct.AppBuilder.html#method.add_event
#[derive(Debug)]
pub struct Events<T> {
events_a: Vec<EventInstance<T>>,

View file

@ -2,6 +2,9 @@ use crate::storage::SparseSetIndex;
use fixedbitset::FixedBitSet;
use std::marker::PhantomData;
/// `Access` keeps track of read and write accesses to values within a collection.
///
/// This is used for ensuring systems are executed soundly.
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Access<T: SparseSetIndex> {
reads_all: bool,
@ -28,11 +31,13 @@ impl<T: SparseSetIndex> Access<T> {
self.writes.grow(bits);
}
/// Adds a read access for the given index.
pub fn add_read(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.reads_and_writes.insert(index.sparse_set_index());
}
/// Adds a write access for the given index.
pub fn add_write(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.writes.grow(index.sparse_set_index() + 1);
@ -40,6 +45,7 @@ impl<T: SparseSetIndex> Access<T> {
self.writes.insert(index.sparse_set_index());
}
/// Returns true if this `Access` contains a read access for the given index.
pub fn has_read(&self, index: T) -> bool {
if self.reads_all {
true
@ -48,30 +54,39 @@ impl<T: SparseSetIndex> Access<T> {
}
}
/// Returns true if this `Access` contains a write access for the given index.
pub fn has_write(&self, index: T) -> bool {
self.writes.contains(index.sparse_set_index())
}
/// Sets this `Access` to having read access for all indices.
pub fn read_all(&mut self) {
self.reads_all = true;
}
/// Returns true if this `Access` has read access to all indices.
pub fn reads_all(&self) -> bool {
self.reads_all
}
/// Clears all recorded accesses.
pub fn clear(&mut self) {
self.reads_all = false;
self.reads_and_writes.clear();
self.writes.clear();
}
/// Extends this `Access` with another, copying all accesses of `other` into this.
pub fn extend(&mut self, other: &Access<T>) {
self.reads_all = self.reads_all || other.reads_all;
self.reads_and_writes.union_with(&other.reads_and_writes);
self.writes.union_with(&other.writes);
}
/// Returns true if this `Access` is compatible with `other`.
///
/// Two `Access` instances are incompatible with each other if one `Access` has a write for
/// which the other also has a write or a read.
pub fn is_compatible(&self, other: &Access<T>) -> bool {
if self.reads_all {
0 == other.writes.count_ones(..)
@ -83,6 +98,7 @@ impl<T: SparseSetIndex> Access<T> {
}
}
/// Calculates conflicting accesses between this `Access` and `other`.
pub fn get_conflicts(&self, other: &Access<T>) -> Vec<T> {
let mut conflicts = FixedBitSet::default();
if self.reads_all {

View file

@ -12,6 +12,32 @@ use std::{
ptr::{self, NonNull},
};
/// Types that can be queried from a [`World`].
///
/// Notable types that implement this trait are `&T` and `&mut T` where `T` implements [`Component`],
/// allowing you to query for components immutably and mutably accordingly.
///
/// See [`Query`](crate::system::Query) for a primer on queries.
///
/// # Basic WorldQueries
///
/// Here is a small list of the most important world queries to know about where `C` stands for a
/// [`Component`] and `WQ` stands for a [`WorldQuery`]:
/// - `&C`: Queries immutably for the component `C`
/// - `&mut C`: Queries mutably for the component `C`
/// - `Option<WQ>`: Queries the inner WorldQuery `WQ` but instead of discarding the entity if the world
/// query fails it returns [`None`]. See [`Query`](crate::system::Query).
/// - `(WQ1, WQ2, ...)`: Queries all contained world queries allowing to query for more than one thing.
/// This is the `And` operator for filters. See [`Or`].
/// - `ChangeTrackers<C>`: See the docs of [`ChangeTrackers`].
/// - [`Entity`]: Using the entity type as a world query will grant access to the entity that is
/// being queried for. See [`Entity`].
///
/// Bevy also offers a few filters like [`Added`](crate::query::Added), [`Changed`](crate::query::Changed),
/// [`With`](crate::query::With), [`Without`](crate::query::Without) and [`Or`].
/// For more information on these consult the item's corresponding documentation.
///
/// [`Or`]: crate::query::Or
pub trait WorldQuery {
type Fetch: for<'a> Fetch<'a, State = Self::State>;
type State: FetchState;
@ -24,6 +50,7 @@ pub trait Fetch<'w>: Sized {
/// Creates a new instance of this fetch.
///
/// # Safety
///
/// `state` must have been initialized (via [FetchState::init]) using the same `world` passed in
/// to this function.
unsafe fn init(
@ -35,52 +62,58 @@ pub trait Fetch<'w>: Sized {
/// Returns true if (and only if) every table of every archetype matched by this Fetch contains
/// all of the matched components. This is used to select a more efficient "table iterator"
/// for "dense" queries. If this returns true, [Fetch::set_table] and [Fetch::table_fetch]
/// will be called for iterators If this returns false, [Fetch::set_archetype] and
/// [Fetch::archetype_fetch] will be called for iterators
/// for "dense" queries. If this returns true, [`Fetch::set_table`] and [`Fetch::table_fetch`]
/// will be called for iterators. If this returns false, [`Fetch::set_archetype`] and
/// [`Fetch::archetype_fetch`] will be called for iterators.
fn is_dense(&self) -> bool;
/// Adjusts internal state to account for the next [Archetype]. This will always be called on
/// archetypes that match this [Fetch]
/// Adjusts internal state to account for the next [`Archetype`]. This will always be called on
/// archetypes that match this [`Fetch`].
///
/// # Safety
/// `archetype` and `tables` must be from the [World] [Fetch::init] was called on. `state` must
///
/// `archetype` and `tables` must be from the [`World`] [`Fetch::init`] was called on. `state` must
/// be the [Self::State] this was initialized with.
unsafe fn set_archetype(&mut self, state: &Self::State, archetype: &Archetype, tables: &Tables);
/// Adjusts internal state to account for the next [Table]. This will always be called on tables
/// that match this [Fetch]
/// Adjusts internal state to account for the next [`Table`]. This will always be called on tables
/// that match this [`Fetch`].
///
/// # Safety
/// `table` must be from the [World] [Fetch::init] was called on. `state` must be the
///
/// `table` must be from the [`World`] [`Fetch::init`] was called on. `state` must be the
/// [Self::State] this was initialized with.
unsafe fn set_table(&mut self, state: &Self::State, table: &Table);
/// Fetch [Self::Item] for the given `archetype_index` in the current [Archetype]. This must
/// always be called after [Fetch::set_archetype] with an `archetype_index` in the range of
/// the current [Archetype]
/// Fetch [`Self::Item`] for the given `archetype_index` in the current [`Archetype`]. This must
/// always be called after [`Fetch::set_archetype`] with an `archetype_index` in the range of
/// the current [`Archetype`]
///
/// # Safety
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range
/// Must always be called _after_ [`Fetch::set_archetype`]. `archetype_index` must be in the range
/// of the current archetype
unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item;
/// Fetch [Self::Item] for the given `table_row` in the current [Table]. This must always be
/// called after [Fetch::set_table] with a `table_row` in the range of the current [Table]
/// Fetch [`Self::Item`] for the given `table_row` in the current [`Table`]. This must always be
/// called after [`Fetch::set_table`] with a `table_row` in the range of the current [`Table`]
///
/// # Safety
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the
///
/// Must always be called _after_ [`Fetch::set_table`]. `table_row` must be in the range of the
/// current table
unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item;
}
/// State used to construct a Fetch. This will be cached inside QueryState, so it is best to move as
/// much data / computation here as possible to reduce the cost of constructing Fetch.
/// SAFETY:
/// Implementor must ensure that [FetchState::update_component_access] and
/// [FetchState::update_archetype_component_access] exactly reflects the results of
/// [FetchState::matches_archetype], [FetchState::matches_table], [Fetch::archetype_fetch], and
/// [Fetch::table_fetch]
/// State used to construct a Fetch. This will be cached inside [`QueryState`](crate::query::QueryState),
/// so it is best to move as much data / computation here as possible to reduce the cost of
/// constructing Fetch.
///
/// # Safety
///
/// Implementor must ensure that [`FetchState::update_component_access`] and
/// [`FetchState::update_archetype_component_access`] exactly reflects the results of
/// [`FetchState::matches_archetype`], [`FetchState::matches_table`], [`Fetch::archetype_fetch`], and
/// [`Fetch::table_fetch`].
pub unsafe trait FetchState: Send + Sync + Sized {
fn init(world: &mut World) -> Self;
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>);
@ -101,16 +134,18 @@ impl WorldQuery for Entity {
type State = EntityState;
}
/// The [`Fetch`] of [`Entity`].
pub struct EntityFetch {
entities: *const Entity,
}
/// SAFE: access is read only
/// SAFETY: access is read only
unsafe impl ReadOnlyFetch for EntityFetch {}
/// The [`FetchState`] of [`Entity`].
pub struct EntityState;
// SAFE: no component or archetype access
// SAFETY: no component or archetype access
unsafe impl FetchState for EntityState {
fn init(_world: &mut World) -> Self {
Self
@ -187,13 +222,14 @@ impl<T: Component> WorldQuery for &T {
type State = ReadState<T>;
}
/// The [`FetchState`] of `&T`.
pub struct ReadState<T> {
component_id: ComponentId,
storage_type: StorageType,
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is
// SAFETY: component access and archetype component access are properly updated to reflect that T is
// read
unsafe impl<T: Component> FetchState for ReadState<T> {
fn init(world: &mut World) -> Self {
@ -234,6 +270,7 @@ unsafe impl<T: Component> FetchState for ReadState<T> {
}
}
/// The [`Fetch`] of `&T`.
pub struct ReadFetch<T> {
storage_type: StorageType,
table_components: NonNull<T>,
@ -242,7 +279,7 @@ pub struct ReadFetch<T> {
sparse_set: *const ComponentSparseSet,
}
/// SAFE: access is read only
/// SAFETY: access is read only
unsafe impl<T> ReadOnlyFetch for ReadFetch<T> {}
impl<'w, T: Component> Fetch<'w> for ReadFetch<T> {
@ -333,6 +370,7 @@ impl<T: Component> WorldQuery for &mut T {
type State = WriteState<T>;
}
/// The [`Fetch`] of `&mut T`.
pub struct WriteFetch<T> {
storage_type: StorageType,
table_components: NonNull<T>,
@ -344,13 +382,14 @@ pub struct WriteFetch<T> {
change_tick: u32,
}
/// The [`FetchState`] of `&mut T`.
pub struct WriteState<T> {
component_id: ComponentId,
storage_type: StorageType,
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is
// SAFETY: component access and archetype component access are properly updated to reflect that T is
// written
unsafe impl<T: Component> FetchState for WriteState<T> {
fn init(world: &mut World) -> Self {
@ -498,19 +537,21 @@ impl<T: WorldQuery> WorldQuery for Option<T> {
type State = OptionState<T::State>;
}
/// The [`Fetch`] of `Option<T>`.
pub struct OptionFetch<T> {
fetch: T,
matches: bool,
}
/// SAFE: OptionFetch is read only because T is read only
/// SAFETY: OptionFetch is read only because T is read only
unsafe impl<T: ReadOnlyFetch> ReadOnlyFetch for OptionFetch<T> {}
/// The [`FetchState`] of `Option<T>`.
pub struct OptionState<T: FetchState> {
state: T,
}
// SAFE: component access and archetype component access are properly updated according to the
// SAFETY: component access and archetype component access are properly updated according to the
// internal Fetch
unsafe impl<T: FetchState> FetchState for OptionState<T> {
fn init(world: &mut World) -> Self {
@ -604,7 +645,36 @@ impl<'w, T: Fetch<'w>> Fetch<'w> for OptionFetch<T> {
}
}
/// Change trackers for component `T`
/// [`WorldQuery`] that tracks changes and additions for component `T`.
///
/// Wraps a [`Component`] to track whether the component changed for the corresponding entities in
/// a query since the last time the system that includes these queries ran.
///
/// If you only care about entities that changed or that got added use the
/// [`Changed`](crate::query::Changed) and [`Added`](crate::query::Added) filters instead.
///
/// # Examples
///
/// ```
/// # use bevy_ecs::system::Query;
/// # use bevy_ecs::query::ChangeTrackers;
/// # use bevy_ecs::system::IntoSystem;
/// #
/// # #[derive(Debug)]
/// # struct Name {};
/// # struct Transform {};
/// #
/// fn print_moving_objects_system(query: Query<(&Name, ChangeTrackers<Transform>)>) {
/// for (name, tracker) in query.iter() {
/// if tracker.is_changed() {
/// println!("Entity moved: {:?}", name);
/// } else {
/// println!("Entity stood still: {:?}", name);
/// }
/// }
/// }
/// # print_moving_objects_system.system();
/// ```
#[derive(Clone)]
pub struct ChangeTrackers<T: Component> {
pub(crate) component_ticks: ComponentTicks,
@ -612,6 +682,7 @@ pub struct ChangeTrackers<T: Component> {
pub(crate) change_tick: u32,
marker: PhantomData<T>,
}
impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChangeTrackers")
@ -623,13 +694,13 @@ impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
}
impl<T: Component> ChangeTrackers<T> {
/// Has this component been added since the last execution of this system.
/// Returns true if this component has been added since the last execution of this system.
pub fn is_added(&self) -> bool {
self.component_ticks
.is_added(self.last_change_tick, self.change_tick)
}
/// Has this component been changed since the last execution of this system.
/// Returns true if this component has been changed since the last execution of this system.
pub fn is_changed(&self) -> bool {
self.component_ticks
.is_changed(self.last_change_tick, self.change_tick)
@ -641,13 +712,14 @@ impl<T: Component> WorldQuery for ChangeTrackers<T> {
type State = ChangeTrackersState<T>;
}
/// The [`FetchState`] of [`ChangeTrackers`].
pub struct ChangeTrackersState<T> {
component_id: ComponentId,
storage_type: StorageType,
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is
// SAFETY: component access and archetype component access are properly updated to reflect that T is
// read
unsafe impl<T: Component> FetchState for ChangeTrackersState<T> {
fn init(world: &mut World) -> Self {
@ -688,6 +760,7 @@ unsafe impl<T: Component> FetchState for ChangeTrackersState<T> {
}
}
/// The [`Fetch`] of [`ChangeTrackers`].
pub struct ChangeTrackersFetch<T> {
storage_type: StorageType,
table_ticks: *const ComponentTicks,
@ -699,7 +772,7 @@ pub struct ChangeTrackersFetch<T> {
change_tick: u32,
}
/// SAFE: access is read only
/// SAFETY: access is read only
unsafe impl<T> ReadOnlyFetch for ChangeTrackersFetch<T> {}
impl<'w, T: Component> Fetch<'w> for ChangeTrackersFetch<T> {
@ -849,7 +922,7 @@ macro_rules! impl_tuple_fetch {
}
}
// SAFE: update_component_access and update_archetype_component_access are called for each item in the tuple
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
#[allow(non_snake_case)]
unsafe impl<$($name: FetchState),*> FetchState for ($($name,)*) {
fn init(_world: &mut World) -> Self {
@ -882,7 +955,7 @@ macro_rules! impl_tuple_fetch {
type State = ($($name::State,)*);
}
/// SAFE: each item in the tuple is read only
/// SAFETY: each item in the tuple is read only
unsafe impl<$($name: ReadOnlyFetch),*> ReadOnlyFetch for ($($name,)*) {}
};

View file

@ -21,17 +21,19 @@ use std::{marker::PhantomData, ptr};
// impl<T: WorldQuery> QueryFilter for T where T::Fetch: FilterFetch {
// }
/// Fetch methods used by query filters. This trait exists to allow "short circuit" behaviors for
/// relevant query filter fetches.
/// Extension trait for [`Fetch`] containing methods used by query filters.
/// This trait exists to allow "short circuit" behaviors for relevant query filter fetches.
pub trait FilterFetch: for<'a> Fetch<'a> {
/// # Safety
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range
/// of the current archetype
///
/// Must always be called _after_ [`Fetch::set_archetype`]. `archetype_index` must be in the range
/// of the current archetype.
unsafe fn archetype_filter_fetch(&mut self, archetype_index: usize) -> bool;
/// # Safety
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the
/// current table
///
/// Must always be called _after_ [`Fetch::set_table`]. `table_row` must be in the range of the
/// current table.
unsafe fn table_filter_fetch(&mut self, table_row: usize) -> bool;
}
@ -50,7 +52,31 @@ where
}
}
/// Filter that selects entities with a component `T`
/// Filter that selects entities with a component `T`.
///
/// This can be used in a [`Query`](crate::system::Query) if entities are required to have the
/// component `T` but you don't actually care about components value.
///
/// This is the negation of [`Without`].
///
/// # Examples
///
/// ```
/// # use bevy_ecs::system::Query;
/// # use bevy_ecs::query::With;
/// # use bevy_ecs::system::IntoSystem;
/// #
/// # #[derive(Debug)]
/// # struct IsBeautiful {};
/// # struct Name { name: &'static str };
/// #
/// fn compliment_entity_system(query: Query<&Name, With<IsBeautiful>>) {
/// for name in query.iter() {
/// println!("{} is looking lovely today!", name.name);
/// }
/// }
/// # compliment_entity_system.system();
/// ```
pub struct With<T>(PhantomData<T>);
impl<T: Component> WorldQuery for With<T> {
@ -58,17 +84,20 @@ impl<T: Component> WorldQuery for With<T> {
type State = WithState<T>;
}
/// The [`Fetch`] of [`With`].
pub struct WithFetch<T> {
storage_type: StorageType,
marker: PhantomData<T>,
}
/// The [`FetchState`] of [`With`].
pub struct WithState<T> {
component_id: ComponentId,
storage_type: StorageType,
marker: PhantomData<T>,
}
// SAFE: no component access or archetype component access
// SAFETY: no component access or archetype component access
unsafe impl<T: Component> FetchState for WithState<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();
@ -145,7 +174,28 @@ impl<'a, T: Component> Fetch<'a> for WithFetch<T> {
}
}
/// Filter that selects entities without a component `T`
/// Filter that selects entities without a component `T`.
///
/// This is the negation of [`With`].
///
/// # Examples
///
/// ```
/// # use bevy_ecs::system::Query;
/// # use bevy_ecs::query::Without;
/// # use bevy_ecs::system::IntoSystem;
/// #
/// # #[derive(Debug)]
/// # struct Permit;
/// # struct Name { name: &'static str };
/// #
/// fn no_permit_system(query: Query<&Name, Without<Permit>>) {
/// for name in query.iter() {
/// println!("{} has no permit!", name.name);
/// }
/// }
/// # no_permit_system.system();
/// ```
pub struct Without<T>(PhantomData<T>);
impl<T: Component> WorldQuery for Without<T> {
@ -153,18 +203,20 @@ impl<T: Component> WorldQuery for Without<T> {
type State = WithoutState<T>;
}
/// The [`Fetch`] of [`Without`].
pub struct WithoutFetch<T> {
storage_type: StorageType,
marker: PhantomData<T>,
}
/// The [`FetchState`] of [`Without`].
pub struct WithoutState<T> {
component_id: ComponentId,
storage_type: StorageType,
marker: PhantomData<T>,
}
// SAFE: no component access or archetype component access
// SAFETY: no component access or archetype component access
unsafe impl<T: Component> FetchState for WithoutState<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();
@ -254,7 +306,7 @@ pub struct WithBundleState<T: Bundle> {
marker: PhantomData<T>,
}
// SAFE: no component access or archetype component access
// SAFETY: no component access or archetype component access
unsafe impl<T: Bundle> FetchState for WithBundleState<T> {
fn init(world: &mut World) -> Self {
let bundle_info = world.bundles.init_info::<T>(&mut world.components);
@ -336,7 +388,37 @@ impl<'a, T: Bundle> Fetch<'a> for WithBundleFetch<T> {
}
}
/// A filter that tests if any of the given filters apply.
///
/// This is useful for example if a system with multiple components in a query only wants to run
/// when one or more of the components have changed.
///
/// The `And` equivalent to this filter is a [`prim@tuple`] testing that all the contained filters
/// apply instead.
///
/// # Examples
///
/// ```
/// # use bevy_ecs::entity::Entity;
/// # use bevy_ecs::system::Query;
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::query::Changed;
/// # use bevy_ecs::query::Or;
/// #
/// # #[derive(Debug)]
/// # struct Color {};
/// # struct Style {};
/// #
/// fn print_cool_entity_system(query: Query<Entity, Or<(Changed<Color>, Changed<Style>)>>) {
/// for entity in query.iter() {
/// println!("Entity {:?} got a new style or color", entity);
/// }
/// }
/// # print_cool_entity_system.system();
/// ```
pub struct Or<T>(pub T);
/// The [`Fetch`] of [`Or`].
pub struct OrFetch<T: FilterFetch> {
fetch: T,
matches: bool,
@ -425,7 +507,7 @@ macro_rules! impl_query_filter_tuple {
}
}
// SAFE: update_component_access and update_archetype_component_access are called for each item in the tuple
// SAFETY: update_component_access and update_archetype_component_access are called for each item in the tuple
#[allow(unused_variables)]
#[allow(non_snake_case)]
unsafe impl<$($filter: FetchState),*> FetchState for Or<($($filter,)*)> {
@ -461,10 +543,17 @@ all_tuples!(impl_query_filter_tuple, 0, 15, F, S);
macro_rules! impl_tick_filter {
(
$(#[$meta:meta])*
$name: ident, $state_name: ident, $fetch_name: ident, $is_detected: expr) => {
$name: ident,
$(#[$state_meta:meta])*
$state_name: ident,
$(#[$fetch_meta:meta])*
$fetch_name: ident,
$is_detected: expr
) => {
$(#[$meta])*
pub struct $name<T>(PhantomData<T>);
$(#[$fetch_meta])*
pub struct $fetch_name<T> {
storage_type: StorageType,
table_ticks: *mut ComponentTicks,
@ -476,6 +565,7 @@ macro_rules! impl_tick_filter {
change_tick: u32,
}
$(#[$state_meta])*
pub struct $state_name<T> {
component_id: ComponentId,
storage_type: StorageType,
@ -488,7 +578,7 @@ macro_rules! impl_tick_filter {
}
// SAFE: this reads the T component. archetype component access and component access are updated to reflect that
// SAFETY: this reads the T component. archetype component access and component access are updated to reflect that
unsafe impl<T: Component> FetchState for $state_name<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();
@ -599,7 +689,7 @@ macro_rules! impl_tick_filter {
impl_tick_filter!(
/// Filter that retrieves components of type `T` that have been added since the last execution
/// of this system
/// of this system.
///
/// This filter is useful to do one-time post-processing on components.
///
@ -607,8 +697,11 @@ impl_tick_filter!(
/// before the query executes you need to use explicit dependency ordering or ordered stages to
/// avoid frame delays.
///
/// If instead behavior is meant to change on whether the component changed or not
/// [`ChangeTrackers`](crate::query::ChangeTrackers) may be used.
///
/// # Examples
///
/// Example:
/// ```
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::system::Query;
@ -627,14 +720,16 @@ impl_tick_filter!(
/// # print_add_name_component.system();
/// ```
Added,
/// The [`FetchState`] of [`Added`].
AddedState,
/// The [`Fetch`] of [`Added`].
AddedFetch,
ComponentTicks::is_added
);
impl_tick_filter!(
/// Filter that retrieves components of type `T` that have been changed since the last
/// execution of this system
/// execution of this system.
///
/// This filter is useful for synchronizing components, and as a performance optimization as it
/// means that the query contains fewer items for a system to iterate over.
@ -643,7 +738,11 @@ impl_tick_filter!(
/// before the query executes you need to use explicit dependency ordering or ordered
/// stages to avoid frame delays.
///
/// Example:
/// If instead behavior is meant to change on whether the component changed or not
/// [`ChangeTrackers`](crate::query::ChangeTrackers) may be used.
///
/// # Examples
///
/// ```
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::system::Query;
@ -662,7 +761,9 @@ impl_tick_filter!(
/// # print_moving_objects_system.system();
/// ```
Changed,
/// The [`FetchState`] of [`Changed`].
ChangedState,
/// The [`Fetch`] of [`Changed`].
ChangedFetch,
ComponentTicks::is_changed
);

View file

@ -5,6 +5,10 @@ use crate::{
world::World,
};
/// An [`Iterator`] over query results of a [`Query`](crate::system::Query).
///
/// This struct is created by the [`Query::iter`](crate::system::Query::iter) and
/// [`Query::iter_mut`](crate::system::Query::iter_mut) methods.
pub struct QueryIter<'w, 's, Q: WorldQuery, F: WorldQuery>
where
F::Fetch: FilterFetch,

View file

@ -122,7 +122,7 @@ where
where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: query is read only
// SAFETY: query is read only
unsafe { self.get_unchecked(world, entity) }
}
@ -132,11 +132,12 @@ where
world: &'w mut World,
entity: Entity,
) -> Result<<Q::Fetch as Fetch<'w>>::Item, QueryEntityError> {
// SAFE: query has unique world access
// SAFETY: query has unique world access
unsafe { self.get_unchecked(world, entity) }
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
#[inline]
@ -194,17 +195,18 @@ where
where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: query is read only
// SAFETY: query is read only
unsafe { self.iter_unchecked(world) }
}
#[inline]
pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, Q, F> {
// SAFE: query has unique world access
// SAFETY: query has unique world access
unsafe { self.iter_unchecked(world) }
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
#[inline]
@ -217,10 +219,11 @@ where
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
/// with a mismatched WorldId is unsound.
#[inline]
pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
&'s self,
@ -239,7 +242,7 @@ where
) where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: query is read only
// SAFETY: query is read only
unsafe {
self.for_each_unchecked(world, func);
}
@ -251,13 +254,14 @@ where
world: &'w mut World,
func: impl FnMut(<Q::Fetch as Fetch<'w>>::Item),
) {
// SAFE: query has unique world access
// SAFETY: query has unique world access
unsafe {
self.for_each_unchecked(world, func);
}
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
#[inline]
@ -285,7 +289,7 @@ where
) where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: query is read only
// SAFETY: query is read only
unsafe {
self.par_for_each_unchecked(world, task_pool, batch_size, func);
}
@ -299,13 +303,14 @@ where
batch_size: usize,
func: impl Fn(<Q::Fetch as Fetch<'w>>::Item) + Send + Sync + Clone,
) {
// SAFE: query has unique world access
// SAFETY: query has unique world access
unsafe {
self.par_for_each_unchecked(world, task_pool, batch_size, func);
}
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
#[inline]
@ -328,10 +333,11 @@ where
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
/// with a mismatched WorldId is unsound.
pub(crate) unsafe fn for_each_unchecked_manual<'w, 's>(
&'s self,
world: &'w World,
@ -377,10 +383,11 @@ where
}
/// # Safety
///
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
/// with a mismatched WorldId is unsound.
pub unsafe fn par_for_each_unchecked_manual<'w, 's>(
&'s self,
world: &'w World,
@ -473,7 +480,7 @@ where
}
}
/// An error that occurs when retrieving a specific [Entity]'s query result.
/// An error that occurs when retrieving a specific [`Entity`]'s query result.
#[derive(Error, Debug)]
pub enum QueryEntityError {
#[error("The given entity does not have the requested component.")]

View file

@ -11,6 +11,101 @@ use std::{any::TypeId, fmt::Debug};
use thiserror::Error;
/// Provides scoped access to a [`World`] according to a given [`WorldQuery`] and query filter.
///
/// Queries are a powerful tool enabling the programmer to iterate over entities and their components
/// as well as filtering them on certain conditions.
///
/// # Query Building Primer
///
/// ### Basic Component Access
///
/// A basic query looks like `Query<&UnitHealth>` and all it does is grant immutable access to all
/// `UnitHealth` components. Similarly using `&mut UnitHealth` instead grants mutable access instead.
///
/// The main way to access the components of a query is through the [`Query::iter`] and [`Query::iter_mut`]
/// functions which return a [`QueryIter`] to iterate over:
///
/// ```
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::system::Query;
/// struct UnitHealth(pub u32);
/// fn system(query: Query<&UnitHealth>) {
/// for UnitHealth(health) in query.iter() {
/// println!("We got {} health points left!", health);
/// }
/// }
/// # system.system();
/// ```
///
/// ### Multiple Component Access
///
/// Instead of asking for just one component like before we can build a query that queries for multiple
/// components with the help of tuples,`Query<(&Shape, &Color, &mut Size)>`. This query retrieves
/// immutable references to the `Shape` and `Color` component and a mutable reference to the `Size`
/// component.
///
/// ```
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::system::Query;
/// #[derive(Debug)]
/// enum Shape {
/// Circle,
/// Box,
/// };
/// struct Color(pub String);
/// struct Size(pub u32);
/// fn system(mut query: Query<(&Shape, &Color, &mut Size)>) {
/// for (shape, color, mut size) in query.iter_mut() {
/// *size = Size(1);
/// println!("We got a {} colored {:?} and made it one unit big!", color.0, shape);
/// }
/// }
/// # system.system();
/// ```
///
/// Note the use of [`Query::iter_mut`] here, as our query is not read-only anymore due to the use
/// of the `&mut` [`WorldQuery`] we aren't able to use the `iter` method any longer.
///
/// ### Filtering Query Results
///
/// Queries also support filters. A filter is a [`WorldQuery`] that can be used as a predicate to
/// filter out entities that do not meet the requirement set by the predicate. [`With`](crate::query::With)
/// is one such filter and all it does is filter out all entities that do not contain the component
/// it requests. Let's look at an example on how to use this filter.
///
/// ```
/// # use bevy_ecs::system::IntoSystem;
/// # use bevy_ecs::system::Query;
/// # use bevy_ecs::query::With;
/// struct Person(String);
/// struct IsTallEnough;
/// fn system(query: Query<&Person, With<IsTallEnough>>) {
/// for person in query.iter() {
/// println!("{} is tall enough!", person.0);
/// }
/// }
/// # system.system();
/// ```
///
/// As shown above, the filter is a second type parameter of the query. It is optional (defaults to
/// ()). Filters do not give access to the component data, only limit the entities that the query will match.
///
/// ### Optional Components
///
/// Now we've seen how to narrow down results of a query, but what if we want to act on entities that
/// may have a component but not always. This is where [`Option`] comes into play, with `Option` we
/// can specify just that. The result of the following query, `Query<&Color, Option<&mut Size>>`, is
/// the tuple `(&Color, Option<&mut Size>)` containing all entities that have the `Color` component,
/// some of which also have a `Size` component. Note that we didn't put a [`Component`] inside the
/// `Option` but a [`WorldQuery`], `&mut T` in this case. This means we can also do the following
/// just fine, `Query<Option<(&Size, &Color)>>`.
///
/// Do take care when handling optional components though, as iterating a query that solely consists
/// of optional components will go over all the entities of the [`World`]. Therefore it's best to
/// design your queries in such a way that they at least contain one non-optional [`WorldQuery`].
///
/// This touches all the basics of queries, make sure to check out all the [`WorldQueries`](WorldQuery)
/// bevy has to offer.
pub struct Query<'w, Q: WorldQuery, F: WorldQuery = ()>
where
F::Fetch: FilterFetch,

View file

@ -884,8 +884,6 @@ impl<'a, T: 'static> SystemParamFetch<'a> for NonSendMutState<T> {
}
}
pub struct OrState<T>(T);
impl<'a> SystemParam for &'a Archetypes {
type Fetch = ArchetypesState;
}