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
@ -10,19 +10,19 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// A component is data associated with an `Entity`. Each entity can have multiple different types
|
/// A component is data associated with an [`Entity`](crate::entity::Entity). Each entity can have
|
||||||
/// of components, but only one of them per type.
|
/// multiple different types of components, but only one of them per type.
|
||||||
///
|
///
|
||||||
/// Any type that is `Send + Sync + 'static` automatically implements `Component`.
|
/// Any type that is `Send + Sync + 'static` automatically implements `Component`.
|
||||||
///
|
///
|
||||||
/// Components are added with new entities using [Commands::spawn](crate::system::Commands::spawn),
|
/// 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 to existing entities with [`EntityCommands::insert`](crate::system::EntityCommands::insert),
|
||||||
/// or their [World](crate::world::World) equivalents.
|
/// 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.
|
/// 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 {}
|
pub trait Component: Send + Sync + 'static {}
|
||||||
impl<T: Send + Sync + 'static> Component for T {}
|
impl<T: Send + Sync + 'static> Component for T {}
|
||||||
|
|
||||||
@ -241,6 +241,7 @@ impl Components {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// `id` must be a valid [ComponentId]
|
/// `id` must be a valid [ComponentId]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn get_info_unchecked(&self, id: ComponentId) -> &ComponentInfo {
|
pub unsafe fn get_info_unchecked(&self, id: ComponentId) -> &ComponentInfo {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{alloc::Layout, any::TypeId};
|
use std::{alloc::Layout, any::TypeId};
|
||||||
|
|
||||||
/// Metadata required to store a component
|
/// Metadata required to store a component.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct TypeInfo {
|
pub struct TypeInfo {
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
@ -11,7 +11,7 @@ pub struct TypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeInfo {
|
impl TypeInfo {
|
||||||
/// Metadata for `T`
|
/// Metadata for `T`.
|
||||||
pub fn of<T: Send + Sync + 'static>() -> Self {
|
pub fn of<T: Send + Sync + 'static>() -> Self {
|
||||||
Self {
|
Self {
|
||||||
type_id: TypeId::of::<T>(),
|
type_id: TypeId::of::<T>(),
|
||||||
|
@ -11,15 +11,15 @@ use std::{
|
|||||||
sync::atomic::{AtomicI64, Ordering},
|
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
|
/// 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
|
/// [`Commands::spawn`](crate::system::Commands::spawn). Can be stored to refer to an entity in the
|
||||||
/// future.
|
/// future.
|
||||||
///
|
///
|
||||||
/// `Entity` can be a part of a query, e.g. `Query<(Entity, &MyComponent)>`.
|
/// `Entity` can be a part of a query, e.g. `Query<(Entity, &MyComponent)>`.
|
||||||
/// Components of a specific entity can be accessed using
|
/// 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)]
|
#[derive(Clone, Copy, Hash, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
pub(crate) generation: u32,
|
pub(crate) generation: u32,
|
||||||
@ -27,12 +27,12 @@ pub struct Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn new(id: u32) -> Entity {
|
||||||
Entity { id, generation: 0 }
|
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
|
/// Only useful for identifying entities within the same instance of an application. Do not use
|
||||||
/// for serialization between runs.
|
/// for serialization between runs.
|
||||||
@ -42,7 +42,7 @@ impl Entity {
|
|||||||
u64::from(self.generation) << 32 | u64::from(self.id)
|
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.
|
/// Only useful when applied to results from `to_bits` in the same instance of an application.
|
||||||
pub fn from_bits(bits: u64) -> Self {
|
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
|
/// 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
|
/// 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> {
|
pub struct ReserveEntitiesIterator<'a> {
|
||||||
// Metas, so we can recover the current generation for anything in the freelist.
|
// Metas, so we can recover the current generation for anything in the freelist.
|
||||||
meta: &'a [EntityMeta],
|
meta: &'a [EntityMeta],
|
||||||
@ -165,7 +166,7 @@ pub struct Entities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Entities {
|
impl Entities {
|
||||||
/// Reserve entity IDs concurrently
|
/// Reserve entity IDs concurrently.
|
||||||
///
|
///
|
||||||
/// Storage for entity generation and location is lazily allocated by calling `flush`.
|
/// Storage for entity generation and location is lazily allocated by calling `flush`.
|
||||||
pub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator {
|
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.
|
/// Equivalent to `self.reserve_entities(1).next().unwrap()`, but more efficient.
|
||||||
pub fn reserve_entity(&self) -> Entity {
|
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.
|
/// Location should be written immediately.
|
||||||
pub fn alloc(&mut self) -> Entity {
|
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
|
/// Returns the location of the entity currently using the given ID, if any. Location should be
|
||||||
/// written immediately.
|
/// written immediately.
|
||||||
@ -293,7 +294,7 @@ impl Entities {
|
|||||||
loc
|
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()`.
|
/// Must not be called while reserved entities are awaiting `flush()`.
|
||||||
pub fn free(&mut self, entity: Entity) -> Option<EntityLocation> {
|
pub fn free(&mut self, entity: Entity) -> Option<EntityLocation> {
|
||||||
@ -315,7 +316,7 @@ impl Entities {
|
|||||||
Some(loc)
|
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) {
|
pub fn reserve(&mut self, additional: u32) {
|
||||||
self.verify_flushed();
|
self.verify_flushed();
|
||||||
|
|
||||||
@ -340,7 +341,7 @@ impl Entities {
|
|||||||
*self.free_cursor.get_mut() = 0;
|
*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.
|
/// Must not be called on pending entities.
|
||||||
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut EntityLocation> {
|
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> {
|
pub fn get(&self, entity: Entity) -> Option<EntityLocation> {
|
||||||
if (entity.id as usize) < self.meta.len() {
|
if (entity.id as usize) < self.meta.len() {
|
||||||
let meta = &self.meta[entity.id as usize];
|
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`.
|
/// Panics if the given id would represent an index outside of `meta`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// Must only be called for currently allocated `id`s.
|
/// Must only be called for currently allocated `id`s.
|
||||||
pub unsafe fn resolve_unknown_gen(&self, id: u32) -> Entity {
|
pub unsafe fn resolve_unknown_gen(&self, id: u32) -> Entity {
|
||||||
let meta_len = self.meta.len();
|
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)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct EntityLocation {
|
pub struct EntityLocation {
|
||||||
/// The archetype index
|
/// The archetype index
|
||||||
|
@ -116,6 +116,8 @@ enum State {
|
|||||||
/// when events are cleared.
|
/// when events are cleared.
|
||||||
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
|
/// 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`].
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub struct Events<T> {
|
pub struct Events<T> {
|
||||||
events_a: Vec<EventInstance<T>>,
|
events_a: Vec<EventInstance<T>>,
|
||||||
|
@ -2,6 +2,9 @@ use crate::storage::SparseSetIndex;
|
|||||||
use fixedbitset::FixedBitSet;
|
use fixedbitset::FixedBitSet;
|
||||||
use std::marker::PhantomData;
|
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)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub struct Access<T: SparseSetIndex> {
|
pub struct Access<T: SparseSetIndex> {
|
||||||
reads_all: bool,
|
reads_all: bool,
|
||||||
@ -28,11 +31,13 @@ impl<T: SparseSetIndex> Access<T> {
|
|||||||
self.writes.grow(bits);
|
self.writes.grow(bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a read access for the given index.
|
||||||
pub fn add_read(&mut self, index: T) {
|
pub fn add_read(&mut self, index: T) {
|
||||||
self.reads_and_writes.grow(index.sparse_set_index() + 1);
|
self.reads_and_writes.grow(index.sparse_set_index() + 1);
|
||||||
self.reads_and_writes.insert(index.sparse_set_index());
|
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) {
|
pub fn add_write(&mut self, index: T) {
|
||||||
self.reads_and_writes.grow(index.sparse_set_index() + 1);
|
self.reads_and_writes.grow(index.sparse_set_index() + 1);
|
||||||
self.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());
|
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 {
|
pub fn has_read(&self, index: T) -> bool {
|
||||||
if self.reads_all {
|
if self.reads_all {
|
||||||
true
|
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 {
|
pub fn has_write(&self, index: T) -> bool {
|
||||||
self.writes.contains(index.sparse_set_index())
|
self.writes.contains(index.sparse_set_index())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets this `Access` to having read access for all indices.
|
||||||
pub fn read_all(&mut self) {
|
pub fn read_all(&mut self) {
|
||||||
self.reads_all = true;
|
self.reads_all = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this `Access` has read access to all indices.
|
||||||
pub fn reads_all(&self) -> bool {
|
pub fn reads_all(&self) -> bool {
|
||||||
self.reads_all
|
self.reads_all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clears all recorded accesses.
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.reads_all = false;
|
self.reads_all = false;
|
||||||
self.reads_and_writes.clear();
|
self.reads_and_writes.clear();
|
||||||
self.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>) {
|
pub fn extend(&mut self, other: &Access<T>) {
|
||||||
self.reads_all = self.reads_all || other.reads_all;
|
self.reads_all = self.reads_all || other.reads_all;
|
||||||
self.reads_and_writes.union_with(&other.reads_and_writes);
|
self.reads_and_writes.union_with(&other.reads_and_writes);
|
||||||
self.writes.union_with(&other.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 {
|
pub fn is_compatible(&self, other: &Access<T>) -> bool {
|
||||||
if self.reads_all {
|
if self.reads_all {
|
||||||
0 == other.writes.count_ones(..)
|
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> {
|
pub fn get_conflicts(&self, other: &Access<T>) -> Vec<T> {
|
||||||
let mut conflicts = FixedBitSet::default();
|
let mut conflicts = FixedBitSet::default();
|
||||||
if self.reads_all {
|
if self.reads_all {
|
||||||
|
@ -12,6 +12,32 @@ use std::{
|
|||||||
ptr::{self, NonNull},
|
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 {
|
pub trait WorldQuery {
|
||||||
type Fetch: for<'a> Fetch<'a, State = Self::State>;
|
type Fetch: for<'a> Fetch<'a, State = Self::State>;
|
||||||
type State: FetchState;
|
type State: FetchState;
|
||||||
@ -24,6 +50,7 @@ pub trait Fetch<'w>: Sized {
|
|||||||
/// Creates a new instance of this fetch.
|
/// Creates a new instance of this fetch.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// `state` must have been initialized (via [FetchState::init]) using the same `world` passed in
|
/// `state` must have been initialized (via [FetchState::init]) using the same `world` passed in
|
||||||
/// to this function.
|
/// to this function.
|
||||||
unsafe fn init(
|
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
|
/// 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"
|
/// 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]
|
/// 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
|
/// will be called for iterators. If this returns false, [`Fetch::set_archetype`] and
|
||||||
/// [Fetch::archetype_fetch] will be called for iterators
|
/// [`Fetch::archetype_fetch`] will be called for iterators.
|
||||||
fn is_dense(&self) -> bool;
|
fn is_dense(&self) -> bool;
|
||||||
|
|
||||||
/// Adjusts internal state to account for the next [Archetype]. This will always be called on
|
/// Adjusts internal state to account for the next [`Archetype`]. This will always be called on
|
||||||
/// archetypes that match this [Fetch]
|
/// archetypes that match this [`Fetch`].
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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.
|
/// be the [Self::State] this was initialized with.
|
||||||
unsafe fn set_archetype(&mut self, state: &Self::State, archetype: &Archetype, tables: &Tables);
|
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
|
/// Adjusts internal state to account for the next [`Table`]. This will always be called on tables
|
||||||
/// that match this [Fetch]
|
/// that match this [`Fetch`].
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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.
|
/// [Self::State] this was initialized with.
|
||||||
unsafe fn set_table(&mut self, state: &Self::State, table: &Table);
|
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
|
/// 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
|
/// always be called after [`Fetch::set_archetype`] with an `archetype_index` in the range of
|
||||||
/// the current [Archetype]
|
/// the current [`Archetype`]
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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
|
/// of the current archetype
|
||||||
unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item;
|
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
|
/// 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]
|
/// called after [`Fetch::set_table`] with a `table_row` in the range of the current [`Table`]
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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
|
/// current table
|
||||||
unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item;
|
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
|
/// State used to construct a Fetch. This will be cached inside [`QueryState`](crate::query::QueryState),
|
||||||
/// much data / computation here as possible to reduce the cost of constructing Fetch.
|
/// so it is best to move as much data / computation here as possible to reduce the cost of
|
||||||
/// SAFETY:
|
/// constructing Fetch.
|
||||||
/// Implementor must ensure that [FetchState::update_component_access] and
|
///
|
||||||
/// [FetchState::update_archetype_component_access] exactly reflects the results of
|
/// # Safety
|
||||||
/// [FetchState::matches_archetype], [FetchState::matches_table], [Fetch::archetype_fetch], and
|
///
|
||||||
/// [Fetch::table_fetch]
|
/// 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 {
|
pub unsafe trait FetchState: Send + Sync + Sized {
|
||||||
fn init(world: &mut World) -> Self;
|
fn init(world: &mut World) -> Self;
|
||||||
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>);
|
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>);
|
||||||
@ -101,16 +134,18 @@ impl WorldQuery for Entity {
|
|||||||
type State = EntityState;
|
type State = EntityState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`Fetch`] of [`Entity`].
|
||||||
pub struct EntityFetch {
|
pub struct EntityFetch {
|
||||||
entities: *const Entity,
|
entities: *const Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SAFE: access is read only
|
/// SAFETY: access is read only
|
||||||
unsafe impl ReadOnlyFetch for EntityFetch {}
|
unsafe impl ReadOnlyFetch for EntityFetch {}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of [`Entity`].
|
||||||
pub struct EntityState;
|
pub struct EntityState;
|
||||||
|
|
||||||
// SAFE: no component or archetype access
|
// SAFETY: no component or archetype access
|
||||||
unsafe impl FetchState for EntityState {
|
unsafe impl FetchState for EntityState {
|
||||||
fn init(_world: &mut World) -> Self {
|
fn init(_world: &mut World) -> Self {
|
||||||
Self
|
Self
|
||||||
@ -187,13 +222,14 @@ impl<T: Component> WorldQuery for &T {
|
|||||||
type State = ReadState<T>;
|
type State = ReadState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of `&T`.
|
||||||
pub struct ReadState<T> {
|
pub struct ReadState<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
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
|
// read
|
||||||
unsafe impl<T: Component> FetchState for ReadState<T> {
|
unsafe impl<T: Component> FetchState for ReadState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
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> {
|
pub struct ReadFetch<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
table_components: NonNull<T>,
|
table_components: NonNull<T>,
|
||||||
@ -242,7 +279,7 @@ pub struct ReadFetch<T> {
|
|||||||
sparse_set: *const ComponentSparseSet,
|
sparse_set: *const ComponentSparseSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SAFE: access is read only
|
/// SAFETY: access is read only
|
||||||
unsafe impl<T> ReadOnlyFetch for ReadFetch<T> {}
|
unsafe impl<T> ReadOnlyFetch for ReadFetch<T> {}
|
||||||
|
|
||||||
impl<'w, T: Component> Fetch<'w> 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>;
|
type State = WriteState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`Fetch`] of `&mut T`.
|
||||||
pub struct WriteFetch<T> {
|
pub struct WriteFetch<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
table_components: NonNull<T>,
|
table_components: NonNull<T>,
|
||||||
@ -344,13 +382,14 @@ pub struct WriteFetch<T> {
|
|||||||
change_tick: u32,
|
change_tick: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of `&mut T`.
|
||||||
pub struct WriteState<T> {
|
pub struct WriteState<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
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
|
// written
|
||||||
unsafe impl<T: Component> FetchState for WriteState<T> {
|
unsafe impl<T: Component> FetchState for WriteState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
fn init(world: &mut World) -> Self {
|
||||||
@ -498,19 +537,21 @@ impl<T: WorldQuery> WorldQuery for Option<T> {
|
|||||||
type State = OptionState<T::State>;
|
type State = OptionState<T::State>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`Fetch`] of `Option<T>`.
|
||||||
pub struct OptionFetch<T> {
|
pub struct OptionFetch<T> {
|
||||||
fetch: T,
|
fetch: T,
|
||||||
matches: bool,
|
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> {}
|
unsafe impl<T: ReadOnlyFetch> ReadOnlyFetch for OptionFetch<T> {}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of `Option<T>`.
|
||||||
pub struct OptionState<T: FetchState> {
|
pub struct OptionState<T: FetchState> {
|
||||||
state: T,
|
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
|
// internal Fetch
|
||||||
unsafe impl<T: FetchState> FetchState for OptionState<T> {
|
unsafe impl<T: FetchState> FetchState for OptionState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct ChangeTrackers<T: Component> {
|
pub struct ChangeTrackers<T: Component> {
|
||||||
pub(crate) component_ticks: ComponentTicks,
|
pub(crate) component_ticks: ComponentTicks,
|
||||||
@ -612,6 +682,7 @@ pub struct ChangeTrackers<T: Component> {
|
|||||||
pub(crate) change_tick: u32,
|
pub(crate) change_tick: u32,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
|
impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("ChangeTrackers")
|
f.debug_struct("ChangeTrackers")
|
||||||
@ -623,13 +694,13 @@ impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Component> 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 {
|
pub fn is_added(&self) -> bool {
|
||||||
self.component_ticks
|
self.component_ticks
|
||||||
.is_added(self.last_change_tick, self.change_tick)
|
.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 {
|
pub fn is_changed(&self) -> bool {
|
||||||
self.component_ticks
|
self.component_ticks
|
||||||
.is_changed(self.last_change_tick, self.change_tick)
|
.is_changed(self.last_change_tick, self.change_tick)
|
||||||
@ -641,13 +712,14 @@ impl<T: Component> WorldQuery for ChangeTrackers<T> {
|
|||||||
type State = ChangeTrackersState<T>;
|
type State = ChangeTrackersState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of [`ChangeTrackers`].
|
||||||
pub struct ChangeTrackersState<T> {
|
pub struct ChangeTrackersState<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
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
|
// read
|
||||||
unsafe impl<T: Component> FetchState for ChangeTrackersState<T> {
|
unsafe impl<T: Component> FetchState for ChangeTrackersState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
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> {
|
pub struct ChangeTrackersFetch<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
table_ticks: *const ComponentTicks,
|
table_ticks: *const ComponentTicks,
|
||||||
@ -699,7 +772,7 @@ pub struct ChangeTrackersFetch<T> {
|
|||||||
change_tick: u32,
|
change_tick: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SAFE: access is read only
|
/// SAFETY: access is read only
|
||||||
unsafe impl<T> ReadOnlyFetch for ChangeTrackersFetch<T> {}
|
unsafe impl<T> ReadOnlyFetch for ChangeTrackersFetch<T> {}
|
||||||
|
|
||||||
impl<'w, T: Component> Fetch<'w> 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)]
|
#[allow(non_snake_case)]
|
||||||
unsafe impl<$($name: FetchState),*> FetchState for ($($name,)*) {
|
unsafe impl<$($name: FetchState),*> FetchState for ($($name,)*) {
|
||||||
fn init(_world: &mut World) -> Self {
|
fn init(_world: &mut World) -> Self {
|
||||||
@ -882,7 +955,7 @@ macro_rules! impl_tuple_fetch {
|
|||||||
type State = ($($name::State,)*);
|
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,)*) {}
|
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 {
|
// 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
|
/// Extension trait for [`Fetch`] containing methods used by query filters.
|
||||||
/// relevant query filter fetches.
|
/// This trait exists to allow "short circuit" behaviors for relevant query filter fetches.
|
||||||
pub trait FilterFetch: for<'a> Fetch<'a> {
|
pub trait FilterFetch: for<'a> Fetch<'a> {
|
||||||
/// # Safety
|
/// # 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;
|
unsafe fn archetype_filter_fetch(&mut self, archetype_index: usize) -> bool;
|
||||||
|
|
||||||
/// # Safety
|
/// # 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;
|
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>);
|
pub struct With<T>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T: Component> WorldQuery for With<T> {
|
impl<T: Component> WorldQuery for With<T> {
|
||||||
@ -58,17 +84,20 @@ impl<T: Component> WorldQuery for With<T> {
|
|||||||
type State = WithState<T>;
|
type State = WithState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`Fetch`] of [`With`].
|
||||||
pub struct WithFetch<T> {
|
pub struct WithFetch<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of [`With`].
|
||||||
pub struct WithState<T> {
|
pub struct WithState<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
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> {
|
unsafe impl<T: Component> FetchState for WithState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
fn init(world: &mut World) -> Self {
|
||||||
let component_info = world.components.get_or_insert_info::<T>();
|
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>);
|
pub struct Without<T>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T: Component> WorldQuery for Without<T> {
|
impl<T: Component> WorldQuery for Without<T> {
|
||||||
@ -153,18 +203,20 @@ impl<T: Component> WorldQuery for Without<T> {
|
|||||||
type State = WithoutState<T>;
|
type State = WithoutState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`Fetch`] of [`Without`].
|
||||||
pub struct WithoutFetch<T> {
|
pub struct WithoutFetch<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [`FetchState`] of [`Without`].
|
||||||
pub struct WithoutState<T> {
|
pub struct WithoutState<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
marker: PhantomData<T>,
|
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> {
|
unsafe impl<T: Component> FetchState for WithoutState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
fn init(world: &mut World) -> Self {
|
||||||
let component_info = world.components.get_or_insert_info::<T>();
|
let component_info = world.components.get_or_insert_info::<T>();
|
||||||
@ -254,7 +306,7 @@ pub struct WithBundleState<T: Bundle> {
|
|||||||
marker: PhantomData<T>,
|
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> {
|
unsafe impl<T: Bundle> FetchState for WithBundleState<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
fn init(world: &mut World) -> Self {
|
||||||
let bundle_info = world.bundles.init_info::<T>(&mut world.components);
|
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);
|
pub struct Or<T>(pub T);
|
||||||
|
|
||||||
|
/// The [`Fetch`] of [`Or`].
|
||||||
pub struct OrFetch<T: FilterFetch> {
|
pub struct OrFetch<T: FilterFetch> {
|
||||||
fetch: T,
|
fetch: T,
|
||||||
matches: bool,
|
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(unused_variables)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe impl<$($filter: FetchState),*> FetchState for Or<($($filter,)*)> {
|
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 {
|
macro_rules! impl_tick_filter {
|
||||||
(
|
(
|
||||||
$(#[$meta:meta])*
|
$(#[$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])*
|
$(#[$meta])*
|
||||||
pub struct $name<T>(PhantomData<T>);
|
pub struct $name<T>(PhantomData<T>);
|
||||||
|
|
||||||
|
$(#[$fetch_meta])*
|
||||||
pub struct $fetch_name<T> {
|
pub struct $fetch_name<T> {
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
table_ticks: *mut ComponentTicks,
|
table_ticks: *mut ComponentTicks,
|
||||||
@ -476,6 +565,7 @@ macro_rules! impl_tick_filter {
|
|||||||
change_tick: u32,
|
change_tick: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(#[$state_meta])*
|
||||||
pub struct $state_name<T> {
|
pub struct $state_name<T> {
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
storage_type: StorageType,
|
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> {
|
unsafe impl<T: Component> FetchState for $state_name<T> {
|
||||||
fn init(world: &mut World) -> Self {
|
fn init(world: &mut World) -> Self {
|
||||||
let component_info = world.components.get_or_insert_info::<T>();
|
let component_info = world.components.get_or_insert_info::<T>();
|
||||||
@ -599,7 +689,7 @@ macro_rules! impl_tick_filter {
|
|||||||
|
|
||||||
impl_tick_filter!(
|
impl_tick_filter!(
|
||||||
/// Filter that retrieves components of type `T` that have been added since the last execution
|
/// 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.
|
/// 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
|
/// before the query executes you need to use explicit dependency ordering or ordered stages to
|
||||||
/// avoid frame delays.
|
/// 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::IntoSystem;
|
||||||
/// # use bevy_ecs::system::Query;
|
/// # use bevy_ecs::system::Query;
|
||||||
@ -627,14 +720,16 @@ impl_tick_filter!(
|
|||||||
/// # print_add_name_component.system();
|
/// # print_add_name_component.system();
|
||||||
/// ```
|
/// ```
|
||||||
Added,
|
Added,
|
||||||
|
/// The [`FetchState`] of [`Added`].
|
||||||
AddedState,
|
AddedState,
|
||||||
|
/// The [`Fetch`] of [`Added`].
|
||||||
AddedFetch,
|
AddedFetch,
|
||||||
ComponentTicks::is_added
|
ComponentTicks::is_added
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_tick_filter!(
|
impl_tick_filter!(
|
||||||
/// Filter that retrieves components of type `T` that have been changed since the last
|
/// 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
|
/// 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.
|
/// 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
|
/// before the query executes you need to use explicit dependency ordering or ordered
|
||||||
/// stages to avoid frame delays.
|
/// 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::IntoSystem;
|
||||||
/// # use bevy_ecs::system::Query;
|
/// # use bevy_ecs::system::Query;
|
||||||
@ -662,7 +761,9 @@ impl_tick_filter!(
|
|||||||
/// # print_moving_objects_system.system();
|
/// # print_moving_objects_system.system();
|
||||||
/// ```
|
/// ```
|
||||||
Changed,
|
Changed,
|
||||||
|
/// The [`FetchState`] of [`Changed`].
|
||||||
ChangedState,
|
ChangedState,
|
||||||
|
/// The [`Fetch`] of [`Changed`].
|
||||||
ChangedFetch,
|
ChangedFetch,
|
||||||
ComponentTicks::is_changed
|
ComponentTicks::is_changed
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,10 @@ use crate::{
|
|||||||
world::World,
|
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>
|
pub struct QueryIter<'w, 's, Q: WorldQuery, F: WorldQuery>
|
||||||
where
|
where
|
||||||
F::Fetch: FilterFetch,
|
F::Fetch: FilterFetch,
|
||||||
|
@ -122,7 +122,7 @@ where
|
|||||||
where
|
where
|
||||||
Q::Fetch: ReadOnlyFetch,
|
Q::Fetch: ReadOnlyFetch,
|
||||||
{
|
{
|
||||||
// SAFE: query is read only
|
// SAFETY: query is read only
|
||||||
unsafe { self.get_unchecked(world, entity) }
|
unsafe { self.get_unchecked(world, entity) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,11 +132,12 @@ where
|
|||||||
world: &'w mut World,
|
world: &'w mut World,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
) -> Result<<Q::Fetch as Fetch<'w>>::Item, QueryEntityError> {
|
) -> 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) }
|
unsafe { self.get_unchecked(world, entity) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -194,17 +195,18 @@ where
|
|||||||
where
|
where
|
||||||
Q::Fetch: ReadOnlyFetch,
|
Q::Fetch: ReadOnlyFetch,
|
||||||
{
|
{
|
||||||
// SAFE: query is read only
|
// SAFETY: query is read only
|
||||||
unsafe { self.iter_unchecked(world) }
|
unsafe { self.iter_unchecked(world) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, Q, F> {
|
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) }
|
unsafe { self.iter_unchecked(world) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -217,10 +219,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
|
/// 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]
|
#[inline]
|
||||||
pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
|
pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
|
||||||
&'s self,
|
&'s self,
|
||||||
@ -239,7 +242,7 @@ where
|
|||||||
) where
|
) where
|
||||||
Q::Fetch: ReadOnlyFetch,
|
Q::Fetch: ReadOnlyFetch,
|
||||||
{
|
{
|
||||||
// SAFE: query is read only
|
// SAFETY: query is read only
|
||||||
unsafe {
|
unsafe {
|
||||||
self.for_each_unchecked(world, func);
|
self.for_each_unchecked(world, func);
|
||||||
}
|
}
|
||||||
@ -251,13 +254,14 @@ where
|
|||||||
world: &'w mut World,
|
world: &'w mut World,
|
||||||
func: impl FnMut(<Q::Fetch as Fetch<'w>>::Item),
|
func: impl FnMut(<Q::Fetch as Fetch<'w>>::Item),
|
||||||
) {
|
) {
|
||||||
// SAFE: query has unique world access
|
// SAFETY: query has unique world access
|
||||||
unsafe {
|
unsafe {
|
||||||
self.for_each_unchecked(world, func);
|
self.for_each_unchecked(world, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -285,7 +289,7 @@ where
|
|||||||
) where
|
) where
|
||||||
Q::Fetch: ReadOnlyFetch,
|
Q::Fetch: ReadOnlyFetch,
|
||||||
{
|
{
|
||||||
// SAFE: query is read only
|
// SAFETY: query is read only
|
||||||
unsafe {
|
unsafe {
|
||||||
self.par_for_each_unchecked(world, task_pool, batch_size, func);
|
self.par_for_each_unchecked(world, task_pool, batch_size, func);
|
||||||
}
|
}
|
||||||
@ -299,13 +303,14 @@ where
|
|||||||
batch_size: usize,
|
batch_size: usize,
|
||||||
func: impl Fn(<Q::Fetch as Fetch<'w>>::Item) + Send + Sync + Clone,
|
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 {
|
unsafe {
|
||||||
self.par_for_each_unchecked(world, task_pool, batch_size, func);
|
self.par_for_each_unchecked(world, task_pool, batch_size, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -328,10 +333,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
|
/// 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>(
|
pub(crate) unsafe fn for_each_unchecked_manual<'w, 's>(
|
||||||
&'s self,
|
&'s self,
|
||||||
world: &'w World,
|
world: &'w World,
|
||||||
@ -377,10 +383,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
///
|
||||||
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
|
||||||
/// have unique access to the components they query.
|
/// have unique access to the components they query.
|
||||||
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
|
/// 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>(
|
pub unsafe fn par_for_each_unchecked_manual<'w, 's>(
|
||||||
&'s self,
|
&'s self,
|
||||||
world: &'w World,
|
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)]
|
#[derive(Error, Debug)]
|
||||||
pub enum QueryEntityError {
|
pub enum QueryEntityError {
|
||||||
#[error("The given entity does not have the requested component.")]
|
#[error("The given entity does not have the requested component.")]
|
||||||
|
@ -11,6 +11,101 @@ use std::{any::TypeId, fmt::Debug};
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Provides scoped access to a [`World`] according to a given [`WorldQuery`] and query filter.
|
/// 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 = ()>
|
pub struct Query<'w, Q: WorldQuery, F: WorldQuery = ()>
|
||||||
where
|
where
|
||||||
F::Fetch: FilterFetch,
|
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 {
|
impl<'a> SystemParam for &'a Archetypes {
|
||||||
type Fetch = ArchetypesState;
|
type Fetch = ArchetypesState;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user