mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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:
parent
19f467ebd0
commit
7c274e5a44
11 changed files with 396 additions and 97 deletions
|
@ -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 {
|
||||
|
|
|
@ -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>(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>>,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,)*) {}
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.")]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue