From 1f81535f58f2f2487a44e029280081e753d0cf97 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Thu, 16 Jun 2022 09:58:34 +0200 Subject: [PATCH 01/26] Squash and rebase Co-authored-by: Alice Cecile Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com> --- crates/bevy_ecs/src/query/fetch.rs | 370 +++++++-------- crates/bevy_ecs/src/query/iter.rs | 57 ++- crates/bevy_ecs/src/system/query.rs | 689 ++++++++++++++++------------ 3 files changed, 610 insertions(+), 506 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 21fab0db52367..0b831fb1cad5a 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -12,94 +12,145 @@ pub use bevy_ecs_macros::WorldQuery; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use std::{cell::UnsafeCell, marker::PhantomData}; -/// Types that can be queried from a [`World`]. +/// Types that can be used to query a [`World`]. +/// +/// There are many types that natively implement `WorldQuery`: +/// +/// - **Component references.** +/// Fetches a component by reference (immutably or mutably). +/// - **`WorldQuery` tuples.** +/// If every element of a tuple implements `WorldQuery`, then the tuple itself also implements the same trait. +/// This enables a single `Query` to access multiple components and filter over multiple conditions. +/// Due to the current lack of variadic generics in Rust, the trait has been implemented for tuples from 0 to 15 elements, +/// but nesting of tuples allows infinite `WorldQuery`s. +/// - **Component filters.** +/// [`With`] and [`Without`] filters can be applied to check if the queried entity contains or not a particular component. +/// - **Change detection filters.** +/// [`Added`] and [`Changed`] filters can be applied to detect component changes to an entity. +/// - **Filter disjunction operator.** +/// By default, tuples compose query filters in such a way that all conditions must be satisfied to generate a query item for a given entity. +/// Wrapping a tuple inside an [`Or`] operator will relax the requirement to just one condition. +/// - **[`Entity`].** +/// Gets the identifier of the queried entity. +/// - **[`Option`].** +/// By default, a world query only tests entities that are compatible with its type. +/// Wrapping it into an `Option` will increase the query search space, and it will return `None` if an entity doesn't satisfy the `WorldQuery`. +/// - **[`AnyOf`].** +/// Equivalent to wrapping each world query inside it into an `Option`. +/// - **[`ChangeTrackers`].** +/// Similar to change detection filters but it is used as a query fetch parameter. +/// It exposes methods to check for changes to the wrapped component. /// -/// 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 [`WorldQuery`]'s -/// -/// 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`: 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`: 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. +/// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// +/// [queries]: crate::system::Query +/// [`With`]: crate::query::With +/// [`Without`]: crate::query::Without /// [`Or`]: crate::query::Or +/// [`Added`]: crate::query::Added +/// [`Changed`]: crate::query::Changed /// -/// # Derive -/// -/// This trait can be derived with the [`derive@super::WorldQuery`] macro. -/// -/// You may want to implement a custom query with the derive macro for the following reasons: -/// - Named structs can be clearer and easier to use than complex query tuples. Access via struct -/// fields is more convenient than destructuring tuples or accessing them via `q.0, q.1, ...` -/// pattern and saves a lot of maintenance burden when adding or removing components. -/// - Nested queries enable the composition pattern and makes query types easier to re-use. -/// - You can bypass the limit of 15 components that exists for query tuples. -/// -/// Implementing the trait manually can allow for a fundamentally new type of behaviour. +/// # Trait derivation /// -/// The derive macro implements [`WorldQuery`] for your type and declares an additional struct -/// which will be used as an item for query iterators. The implementation also generates two other -/// structs that are used as [`WorldQuery::Fetch`](WorldQueryGats::Fetch) and -/// [`WorldQuery::State`] associated types. +/// Query design can be easily structured by deriving `WorldQuery` for custom types. +/// Despite the added complexity, this approach has several advantages over using `WorldQuery` tuples. +/// The most relevant improvements are: /// -/// The derive macro requires every struct field to implement the `WorldQuery` trait. +/// - Reusability across multiple systems. +/// - There is no need to destructure a tuple since all fields are named. +/// - Subqueries can be composed together to create a more complex query. +/// - Methods can be implemented for the query items. +/// - There is no hardcoded limit on the number of elements. /// -/// **Note:** currently, the macro only supports named structs. +/// This trait can only be derived if each field of the struct also implements `WorldQuery`. +/// The derive macro only supports regular structs (structs with named fields). /// /// ``` /// # use bevy_ecs::prelude::*; /// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(Component)] -/// struct Foo; -/// #[derive(Component)] -/// struct Bar; +/// # +/// # #[derive(Component)] +/// # struct ComponentA; +/// # #[derive(Component)] +/// # struct ComponentB; /// /// #[derive(WorldQuery)] /// struct MyQuery { /// entity: Entity, -/// // We must explicitly list out all lifetimes, as we are defining a struct -/// foo: &'static Foo, -/// bar: Option<&'static Bar>, +/// // It is required that all reference lifetimes are explicitly annotated, just like in any +/// // struct. Each lifetime should be 'static. +/// component_a: &'static ComponentA, +/// component_b: &'static ComponentB, /// } /// /// fn my_system(query: Query) { -/// for q in &query { -/// // Note the type of the returned item. -/// let q: MyQueryItem<'_> = q; -/// q.foo; +/// for q in query.iter() { +/// q.component_a; /// } /// } -/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// -/// ## Mutable queries +/// ## Macro expansion /// -/// All queries that are derived with the `WorldQuery` macro provide only an immutable access by default. -/// If you need a mutable access to components, you can mark a struct with the `mutable` attribute. +/// Expanding the macro will declare three or five additional structs, depending on whether or not the struct is marked as mutable. +/// For a struct named `X`, the additional structs will be: +/// +/// |Struct name|`mutable` only|Description| +/// |:---:|:---:|---| +/// |`XItem`|---|The type of the query item| +/// |`XFetch`|---|Implements [`Fetch`] for `XItem`| +/// |`XState`|---|Implements [`FetchState`]| +/// |`XReadOnlyItem`|✓|The type of the read-only query item| +/// |`XReadOnlyFetch`|✓|Implements [`Fetch`] for `XReadOnlyItem`| +/// +/// ## Adding mutable references +/// +/// Simply adding mutable references to a derived `WorldQuery` will result in a compilation error: +/// +/// ```compile_fail +/// # use bevy_ecs::prelude::*; +/// # use bevy_ecs::query::WorldQuery; +/// # +/// # #[derive(Component)] +/// # struct ComponentA; +/// # +/// #[derive(WorldQuery)] +/// struct CustomQuery { +/// component_a: &'static mut ComponentA, +/// } +/// ``` +/// +/// To grant mutable access to components, the struct must be marked with the `#[world_query(mutable)]` attribute. +/// This will also create two more structs that will be used for accessing the query immutably (see table above). /// /// ``` /// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; +/// # use bevy_ecs::query::WorldQuery; +/// # +/// # #[derive(Component)] +/// # struct ComponentA; +/// # +/// #[derive(WorldQuery)] +/// #[world_query(mutable)] +/// struct CustomQuery { +/// component_a: &'static mut ComponentA, +/// } +/// ``` +/// +/// ## Adding methods to query items /// +/// It is possible to add methods to query items in order to write reusable logic about related components. +/// This will often make systems more readable because low level logic is moved out from them. +/// It is done by adding `impl` blocks with methods for the `-Item` or `-ReadOnlyItem` generated structs. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # use bevy_ecs::query::WorldQuery; +/// # /// #[derive(Component)] /// struct Health(f32); +/// /// #[derive(Component)] /// struct Buff(f32); /// @@ -110,7 +161,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// buff: Option<&'static mut Buff>, /// } /// -/// // This implementation is only available when iterating with `iter_mut`. +/// // `HealthQueryItem` is only available when accessing the query with mutable methods. /// impl<'w> HealthQueryItem<'w> { /// fn damage(&mut self, value: f32) { /// self.health.0 -= value; @@ -121,7 +172,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// } /// -/// // If you want to use it with `iter`, you'll need to write an additional implementation. +/// // `HealthQueryReadOnlyItem` is only available when accessing the query with immutable methods. /// impl<'w> HealthQueryReadOnlyItem<'w> { /// fn total(&self) -> f32 { /// self.health.0 + self.buff.map_or(0.0, |Buff(buff)| *buff) @@ -129,191 +180,104 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// /// fn my_system(mut health_query: Query) { -/// // Iterator's item is `HealthQueryReadOnlyItem`. -/// for health in &health_query { +/// // The item returned by the iterator is of type `HealthQueryReadOnlyItem`. +/// for health in health_query.iter() { /// println!("Total: {}", health.total()); /// } -/// // Iterator's item is `HealthQueryItem`. -/// for mut health in &mut health_query { +/// // The item returned by the iterator is of type `HealthQueryItem`. +/// for mut health in health_query.iter_mut() { /// health.damage(1.0); /// println!("Total (mut): {}", health.total()); /// } /// } -/// -/// # bevy_ecs::system::assert_is_system(my_system); -/// ``` -/// -/// Mutable queries will also have a read only version derived: -/// ```rust -/// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(Component)] -/// pub struct MyComponent; -/// -/// #[derive(WorldQuery)] -/// #[world_query(mutable)] -/// pub struct Foo { -/// my_component_yay: &'static mut MyComponent, -/// } -/// -/// fn my_system(mut my_query: Query<(FooReadOnly, FooReadOnly)>) { -/// for (i1, i2) in &mut my_query { -/// let _: FooReadOnlyItem<'_> = i1; -/// let _: FooReadOnlyItem<'_> = i2; -/// } -/// } -/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// -/// **Note:** if you omit the `mutable` attribute for a query that doesn't implement -/// [`ReadOnlyWorldQuery`], compilation will fail. We insert static checks as in the example above for -/// every query component and a nested query. -/// (The checks neither affect the runtime, nor pollute your local namespace.) -/// -/// ```compile_fail -/// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(Component)] -/// struct Foo; -/// #[derive(Component)] -/// struct Bar; -/// -/// #[derive(WorldQuery)] -/// struct FooQuery { -/// foo: &'static Foo, -/// bar_query: BarQuery, -/// } -/// -/// #[derive(WorldQuery)] -/// #[world_query(mutable)] -/// struct BarQuery { -/// bar: &'static mut Bar, -/// } -/// ``` -/// -/// ## Derives for items +/// ## Deriving traits for query items /// -/// If you want query items to have derivable traits, you can pass them with using -/// the `world_query(derive)` attribute. When the `WorldQuery` macro generates the structs -/// for query items, it doesn't automatically inherit derives of a query itself. Since derive macros -/// can't access information about other derives, they need to be passed manually with the -/// `world_query(derive)` attribute. +/// The `WorldQuery` derive macro does not automatically implement the traits of the struct to the query item types. +/// Something similar can be done by using the `#[world_query(derive(...))]` attribute. +/// This will apply the listed derivable traits to the query item structs. /// /// ``` /// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(Component, Debug)] -/// struct Foo; -/// +/// # use bevy_ecs::query::WorldQuery; +/// # +/// # #[derive(Component, Debug)] +/// # struct ComponentA; +/// # /// #[derive(WorldQuery)] /// #[world_query(mutable, derive(Debug))] -/// struct FooQuery { -/// foo: &'static Foo, +/// struct CustomQuery { +/// component_a: &'static ComponentA, /// } /// +/// // This function statically checks that `T` implements `Debug`. /// fn assert_debug() {} /// -/// assert_debug::(); -/// assert_debug::(); +/// assert_debug::(); +/// assert_debug::(); /// ``` /// -/// ## Nested queries +/// ## Query composition /// -/// Using nested queries enable the composition pattern, which makes it possible to re-use other -/// query types. All types that implement [`WorldQuery`] (including the ones that use this derive -/// macro) are supported. +/// It is possible to use any `WorldQuery` as a field of another one. +/// This means that a `WorldQuery` can also be used as a subquery, potentially in multiple places. /// /// ``` /// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(Component)] -/// struct Foo; -/// #[derive(Component)] -/// struct Bar; -/// #[derive(Component)] -/// struct OptionalFoo; -/// #[derive(Component)] -/// struct OptionalBar; -/// +/// # use bevy_ecs::query::WorldQuery; +/// # +/// # #[derive(Component)] +/// # struct ComponentA; +/// # #[derive(Component)] +/// # struct ComponentB; +/// # #[derive(Component)] +/// # struct ComponentC; +/// # /// #[derive(WorldQuery)] -/// struct MyQuery { -/// foo: FooQuery, -/// bar: (&'static Bar, Option<&'static OptionalBar>) +/// struct SubQuery { +/// component_a: &'static ComponentA, +/// component_b: &'static ComponentB, /// } /// /// #[derive(WorldQuery)] -/// struct FooQuery { -/// foo: &'static Foo, -/// optional_foo: Option<&'static OptionalFoo>, -/// } -/// -/// // You can also compose derived queries with regular ones in tuples. -/// fn my_system(query: Query<(&Foo, MyQuery, FooQuery)>) { -/// for (foo, my_query, foo_query) in &query { -/// foo; my_query; foo_query; -/// } -/// } -/// -/// # bevy_ecs::system::assert_is_system(my_system); -/// ``` -/// -/// ## Ignored fields -/// -/// The macro also supports `ignore` attribute for struct members. Fields marked with this attribute -/// must implement the `Default` trait. -/// -/// This example demonstrates a query that would iterate over every entity. -/// -/// ``` -/// # use bevy_ecs::prelude::*; -/// use bevy_ecs::query::WorldQuery; -/// -/// #[derive(WorldQuery, Debug)] -/// struct EmptyQuery { -/// empty: (), -/// } -/// -/// fn my_system(query: Query) { -/// for _ in &query {} +/// struct MyQuery { +/// subquery: SubQuery, +/// component_c: &'static ComponentC, /// } -/// -/// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// /// ## Filters /// -/// Using [`derive@super::WorldQuery`] macro we can create our own query filters. +/// Since the query filter type parameter is `WorldQuery`, it is also possible to use this macro to create filters. /// /// ``` /// # use bevy_ecs::prelude::*; -/// use bevy_ecs::{query::WorldQuery, component::Component}; -/// -/// #[derive(Component)] -/// struct Foo; -/// #[derive(Component)] -/// struct Bar; -/// #[derive(Component)] -/// struct Baz; -/// #[derive(Component)] -/// struct Qux; -/// +/// # use bevy_ecs::{query::WorldQuery, component::Component}; +/// # +/// # #[derive(Component)] +/// # struct ComponentA; +/// # #[derive(Component)] +/// # struct ComponentB; +/// # #[derive(Component)] +/// # struct ComponentC; +/// # #[derive(Component)] +/// # struct ComponentD; +/// # #[derive(Component)] +/// # struct ComponentE; +/// # /// #[derive(WorldQuery)] /// struct MyFilter { -/// _foo: With, -/// _bar: With, -/// _or: Or<(With, Changed, Added)>, -/// _generic_tuple: (With, Without

), +/// // Field names are not relevant, since they are never manually accessed. +/// with_a: With, +/// or_filter: Or<(With, Added)>, +/// generic_tuple: (With, Without

), /// } /// -/// fn my_system(query: Query>) { -/// for _ in &query {} +/// fn my_system(query: Query>) { +/// // ... /// } -/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// # Safety diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 1c8f7e92562d0..cd3427c1be80c 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -214,6 +214,58 @@ where { } +/// An iterator over `K`-sized combinations of query items without repetition. +/// +/// In this context, a combination is an unordered subset of `K` elements. +/// The number of combinations depend on how `K` relates to the number of entities matching the [`Query`] (called `N`): +/// - if `K = N`, only one combination exists, +/// - if `K < N`, there are NCK combinations (see the [performance section] of `Query`), +/// - if `K > N`, there are no combinations. +/// +/// # Usage +/// +/// This type is returned by calling [`Query::iter_combinations`] or [`Query::iter_combinations_mut`]. +/// +/// It implements [`Iterator`] only if it iterates over read-only query items ([learn more]). +/// +/// In the case of mutable query items, it can be iterated by calling [`fetch_next`](Self::fetch_next) in a `while let` loop. +/// +/// [`Query`]: crate::system::Query +/// [performance section]: crate::system::Query#performance +/// [`Query::iter_combinations`]: crate::system::Query::iter_combinations +/// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut +/// [learn more]: Self#impl-Iterator +/// +/// # Examples +/// +/// The following example shows how to traverse the iterator when the query items are read-only. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # #[derive(Component)] +/// # struct ComponentA; +/// # +/// fn some_system(query: Query<&ComponentA>) { +/// for [a1, a2] in query.iter_combinations() { +/// // ... +/// } +/// } +/// ``` +/// +/// The following example shows how `fetch_next` should be called with a `while let` loop to traverse the iterator when the query items are mutable. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # #[derive(Component)] +/// # struct ComponentA; +/// # +/// fn some_system(mut query: Query<&mut ComponentA>) { +/// let mut combinations = query.iter_combinations_mut(); +/// while let Some([a1, a2]) = combinations.fetch_next() { +/// // ... +/// } +/// } +/// ``` pub struct QueryCombinationIter<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, @@ -327,9 +379,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> QueryCombinationIter< } } -// Iterator type is intentionally implemented only for read-only access. -// Doing so for mutable references would be unsound, because calling `next` -// multiple times would allow multiple owned references to the same data to exist. +/// Iterator type is intentionally implemented only for read-only access. +/// Doing so for mutable references would be unsound, because calling `next` multiple times would allow multiple owned references to the same data to exist. impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> Iterator for QueryCombinationIter<'w, 's, Q, F, K> where diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index d1bf9b2b747c6..565802c545fa6 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -9,95 +9,74 @@ use crate::{ }; use std::{any::TypeId, borrow::Borrow, fmt::Debug}; -/// Provides scoped access to components in a [`World`]. +/// [System parameter] that provides selective access to the [`Component`] data stored in a [`World`]. /// -/// Queries enable iteration over entities and their components as well as filtering them -/// on certain conditions. A query matches its parameters against the world to produce a series -/// of results. Each *query result* is a tuple of components (the same components defined -/// in the query) that belong to the same entity. +/// Enables access to [entity identifiers] and [components] from a system, without the need to directly access the world. +/// Its iterators and getter methods return *query items*. +/// Each query item is a type containing data relative to an entity. /// -/// Computational cost of queries is reduced by the fact that they have an internal archetype -/// cache to avoid re-computing archetype matches on each query access. +/// `Query` is a generic data structure that accepts two type parameters, both of which must implement the [`WorldQuery`] trait: /// -/// Query functionality is based on the [`WorldQuery`] trait. Both tuples of components -/// (up to 16 elements) and query filters implement this trait. +/// - **`Q` (query fetch).** +/// The type of data contained in the query item. +/// Only entities that match the requested data will generate an item. +/// - **`F` (query filter).** +/// A set of conditions that determines wheter query items should be kept or discarded. +/// This type parameter is optional. /// -/// `Query` accepts two type parameters: +/// [System parameter]: crate::system::SystemParam +/// [entity identifiers]: crate::entity::Entity +/// [components]: crate::component::Component /// -/// 1. **Component access:** the components that an entity must have at the same time to yield -/// a query result. -/// 2. **Query filters (optional):** a predicate that ignores query results that don't match -/// its conditions. +/// # System parameter declaration /// -/// # Usage as system parameter +/// A query should always be declared as a system parameter. +/// This section shows the most common idioms involving the declaration of `Query`, emerging by combining [`WorldQuery`] implementors. /// -/// A query is defined by declaring it as a system parameter. This section shows the various -/// use cases of `Query` as a system parameter. +/// ## Component access /// -/// ## Immutable component access -/// -/// The following example defines a query that gives an iterator over `(&ComponentA, &ComponentB)` -/// tuples, where `ComponentA` and `ComponentB` belong to the same entity. Accessing components -/// immutably helps system parallelization. +/// A query defined with a reference to a component as the query fetch type parameter can be used to generate items that refer to the data of said component. /// /// ``` -/// # use bevy_ecs::component::Component; -/// # use bevy_ecs::system::IntoSystem; -/// # use bevy_ecs::system::Query; +/// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; -/// # fn system( -/// query: Query<(&ComponentA, &ComponentB)> +/// # fn immutable_ref( +/// // A component can be accessed by shared reference... +/// query: Query<&ComponentA> /// # ) {} -/// # bevy_ecs::system::assert_is_system(system); -/// ``` +/// # bevy_ecs::system::assert_is_system(immutable_ref); /// -/// You can use the [`ReadOnlyWorldQuery`] trait to abstract over read only query generics: -/// ``` -/// # use bevy_ecs::system::Query; -/// # use bevy_ecs::query::{QueryItem, ReadOnlyWorldQuery}; -/// fn system( -/// query: Query, -/// ) { -/// let _: Option> = query.iter().next(); -/// } +/// # fn mutable_ref( +/// // ... or by mutable reference. +/// query: Query<&mut ComponentA> +/// # ) {} +/// # bevy_ecs::system::assert_is_system(mutable_ref); /// ``` /// -/// ## Mutable component access +/// ## Query filtering /// -/// The following example is similar to the previous one, with the exception of `ComponentA` -/// being accessed mutably here. Note that both mutable and immutable accesses are allowed -/// in the same query. +/// Setting the query filter type parameter will ensure that each query item satisfies the given condition. /// /// ``` -/// # use bevy_ecs::component::Component; -/// # use bevy_ecs::system::IntoSystem; -/// # use bevy_ecs::system::Query; +/// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct ComponentA; /// # #[derive(Component)] /// # struct ComponentB; /// # fn system( -/// // `ComponentA` is accessed mutably, while `ComponentB` is accessed immutably. -/// mut query: Query<(&mut ComponentA, &ComponentB)> +/// // Just `ComponentA` data will be accessed, but only for entities that also contain +/// // `ComponentB`. +/// query: Query<&ComponentA, With> /// # ) {} /// # bevy_ecs::system::assert_is_system(system); /// ``` /// -/// Two systems cannot be executed in parallel if both access a certain component and -/// at least one of the accesses is mutable, unless the schedule can verify that no entity -/// could be found in both queries, as otherwise Rusts mutability Rules would be broken. +/// ## `WorldQuery` tuples /// -/// Similarly, a system cannot contain two queries that would break Rust's mutability Rules. -/// If you need such Queries, you can use Filters to make the Queries disjoint or use a -/// [`ParamSet`](super::ParamSet). +/// Using tuples, each `Query` type parameter can contain multiple elements. /// -/// ## Entity ID access -/// -/// Inserting [`Entity`](crate::entity::Entity) at any position in the type parameter tuple -/// will give access to the entity ID. +/// In the following example, two components are accessed simultaneously, and the query items are filtered on two conditions. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -105,33 +84,35 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// # struct ComponentA; /// # #[derive(Component)] /// # struct ComponentB; -/// # fn system( -/// query: Query<(Entity, &ComponentA, &ComponentB)> +/// # #[derive(Component)] +/// # struct ComponentC; +/// # #[derive(Component)] +/// # struct ComponentD; +/// # fn immutable_ref( +/// query: Query<(&ComponentA, &ComponentB), (With, Without)> /// # ) {} -/// # bevy_ecs::system::assert_is_system(system); +/// # bevy_ecs::system::assert_is_system(immutable_ref); /// ``` /// -/// ## Query filtering +/// ## Entity identifier access /// -/// The second, optional type parameter of query, is used for filters can be added to filter -/// out the query results that don't satisfy the given condition. +/// The identifier of an entity can be made available inside the query item by including [`Entity`] in the query fetch type parameter. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; -/// # #[derive(Component)] -/// # struct ComponentC; /// # fn system( -/// // `ComponentC` data won't be accessed, but only entities that contain it will be queried. -/// query: Query<(&ComponentA, &ComponentB), With> +/// query: Query<(Entity, &ComponentA)> /// # ) {} /// # bevy_ecs::system::assert_is_system(system); /// ``` /// -/// If you need to apply more filters in a single query, group them into a tuple: +/// ## Optional component access +/// +/// A component can be made optional in a query by wrapping it into an [`Option`]. +/// In this way, a query item can still be generated even if the queried entity does not contain the wrapped component. +/// In this case, its corresponding value will be `None`. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -139,116 +120,154 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// # struct ComponentA; /// # #[derive(Component)] /// # struct ComponentB; -/// # #[derive(Component)] -/// # struct ComponentC; /// # fn system( -/// // Similar to the previous query, but with the addition of a `Changed` filter. -/// query: Query<(&ComponentA, &ComponentB), (With, Changed)> +/// // Generates items for entities that contain `ComponentA`, and optionally `ComponentB`. +/// query: Query<(&ComponentA, Option<&ComponentB>)> /// # ) {} /// # bevy_ecs::system::assert_is_system(system); /// ``` /// -/// The following list contains all the available query filters: +/// See the documentation for [`AnyOf`] to idiomatically declare many optional components. /// -/// - [`Added`](crate::query::Added) -/// - [`Changed`](crate::query::Changed) -/// - [`With`](crate::query::With) -/// - [`Without`](crate::query::Without) -/// - [`Or`](crate::query::Or) +/// See the [performance] section to learn more about the impact of optional components. /// -/// ## Optional component access +/// [`AnyOf`]: crate::query::AnyOf +/// [performance]: #performance /// -/// A component can be made optional in a query by wrapping it into an [`Option`]. In the -/// following example, the query will iterate over components of both entities that contain -/// `ComponentA` and `ComponentB`, and entities that contain `ComponentA` but not `ComponentB`. +/// ## Disjoint queries /// -/// ``` +/// A system cannot contain two queries that break Rust's mutability rules. +/// In this case, the [`Without`] filter can be used to disjoint them. +/// +/// In the following example, two queries mutably access the same component. +/// Executing this system will panic, since an entity could potentially match the two queries at the same time by having both `Player` and `Enemy` components. +/// This would violate mutability rules. +/// +/// ```should_panic /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] -/// # struct ComponentA; +/// # struct Health; /// # #[derive(Component)] -/// # struct ComponentB; -/// # fn system( -/// query: Query<(&ComponentA, Option<&ComponentB>)> -/// # ) {} -/// # bevy_ecs::system::assert_is_system(system); +/// # struct Player; +/// # #[derive(Component)] +/// # struct Enemy; +/// # +/// fn randomize_health( +/// player_query: Query<&mut Health, With>, +/// enemy_query: Query<&mut Health, With>, +/// ) +/// # {} +/// # let mut randomize_health_system = bevy_ecs::system::IntoSystem::into_system(randomize_health); +/// # let mut world = World::new(); +/// # randomize_health_system.initialize(&mut world); +/// # randomize_health_system.run((), &mut world); /// ``` /// -/// If an entity does not contain a component, its corresponding query result value will be -/// `None`. Optional components increase the number of entities a query has to match against, -/// therefore they can hurt iteration performance, especially in the worst case scenario where -/// the query solely consists of only optional components, since all entities will be iterated -/// over. -/// -/// ## Single component access -/// -/// If just a single component needs to be accessed, using a tuple as the first type parameter -/// of `Query` can be omitted. +/// Adding a `Without` filter will disjoint the queries. +/// In this way, any entity that has both `Player` and `Enemy` components is excluded from both queries. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] -/// # struct MyComponent; -/// # fn tuple_system( -/// // This is correct, but can be avoided. -/// query: Query<(&MyComponent,)> -/// # ) {} -/// # bevy_ecs::system::assert_is_system(tuple_system); -/// -/// # fn non_tuple_system( -/// // This is the preferred method. -/// query: Query<&MyComponent> -/// # ) {} -/// # bevy_ecs::system::assert_is_system(non_tuple_system); +/// # struct Health; +/// # #[derive(Component)] +/// # struct Player; +/// # #[derive(Component)] +/// # struct Enemy; +/// # +/// fn randomize_health( +/// player_query: Query<&mut Health, (With, Without)>, +/// enemy_query: Query<&mut Health, (With, Without)>, +/// ) +/// # {} +/// # let mut randomize_health_system = bevy_ecs::system::IntoSystem::into_system(randomize_health); +/// # let mut world = World::new(); +/// # randomize_health_system.initialize(&mut world); +/// # randomize_health_system.run((), &mut world); /// ``` /// -/// # Usage of query results +/// An alternative to this idiom is to wrap the conflicting queries into a [`ParamSet`](super::ParamSet). /// -/// Inside the body of the system function, the `Query` is available as a function parameter. -/// This section shows various methods to access query results. +/// # Accessing query items /// -/// ## Iteration over every query result +/// The following table summarizes the behavior of the safe methods that can be used to get query items. /// -/// The [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) methods are used to iterate -/// over every query result. Refer to the -/// [`Iterator` API docs](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) -/// for advanced iterator usage. +/// |Query methods|Effect| +/// |:---:|---| +/// |[`iter`]\([`_mut`][iter_mut])|Returns an iterator over all query items.| +/// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|Runs a specified function for each query item.| +/// |[`iter_many`],
[`many_for_each_mut`]|Iterates or runs a specified function over query items generated by a list of entities.| +/// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|Returns an iterator over all combinations of a specified number of query items.| +/// |[`get`]\([`_mut`][get_mut])|Returns the query item for the specified entity.| +/// |[`many`]\([`_mut`][many_mut]),
[`get_many`]\([`_mut`][get_many_mut])|Returns the query items for the specified entities.| +/// |[`single`]\([`_mut`][single_mut]),
[`get_single`]\([`_mut`][get_single_mut])|Returns the query item while veryfing that there aren't others.| /// -/// ``` -/// # use bevy_ecs::prelude::*; -/// # #[derive(Component)] -/// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; -/// fn immutable_query_system(query: Query<(&ComponentA, &ComponentB)>) { -/// for (a, b) in &query { -/// // Here, `a` and `b` are normal references to components, relatively of -/// // `&ComponentA` and `&ComponentB` types. -/// } -/// } -/// # bevy_ecs::system::assert_is_system(immutable_query_system); +/// There are two methods for each type of query operation: immutable and mutable (ending with `_mut`). +/// When using immutable methods, the query items returned are of type [`ROQueryItem`], a read-only version of the query item. +/// In this circumstance, every mutable reference in the query fetch type parameter is substituted by a shared reference. /// -/// fn mutable_query_system(mut query: Query<(&mut ComponentA, &ComponentB)>) { -/// for (mut a, b) in &mut query { -/// // Similar to the above system, but this time `ComponentA` can be accessed mutably. -/// // Note the usage of `mut` in the tuple and the call to `iter_mut` instead of `iter`. -/// } -/// } -/// # bevy_ecs::system::assert_is_system(mutable_query_system); -/// ``` +/// # Performance +/// +/// Creating a `Query` is a low-cost operation. +/// Iterating it, on the other hand, fetches data from the world and generates items, which can have a significant computational cost. +/// However, iteration cost of queries is reduced by the fact that they have an internal archetype cache to avoid re-computing archetype matches on each query access. +/// +/// Two systems cannot be executed in parallel if both access the same component type where at least one of the accesses is mutable. +/// This happens unless the schedule can verify that no entity could be found in both queries. +/// +/// Optional components increase the number of entities a query has to match against. +/// This can hurt iteration performance, especially if the query solely consists of only optional components, since the query would iterate over each entity in the world. /// -/// ## Getting the query result for a particular entity +/// The following table compares the computational complexity of the various methods and operations, where: /// -/// If you have an [`Entity`] ID, you can use the [`get`](Self::get) or -/// [`get_mut`](Self::get_mut) methods to access the query result for that particular entity. +/// - **n** is the number of entities that match the query, +/// - **r** is the number of elements in a combination, +/// - **k** is the number of involved entities in the operation, +/// - **a** is the number of archetypes in the world, +/// - **C** is the [binomial coefficient], used to count combinations. +/// nCr is read as "*n* choose *r*" and is equivalent to the number of distinct unordered subsets of *r* elements that can be taken from a set of *n* elements. /// -/// ## Getting a single query result +/// |Query operation|Computational complexity| +/// |:---:|:---:| +/// |[`iter`]\([`_mut`][iter_mut])|O(n)| +/// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|O(n)| +/// |[`iter_many`],
[`many_for_each_mut`]|O(k)| +/// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|O(nCr)| +/// |[`get`]\([`_mut`][get_mut])|O(1)| +/// |([`get_`][get_many])[`many`]|O(k)| +/// |([`get_`][get_many_mut])[`many_mut`]|O(k2)| +/// |[`single`]\([`_mut`][single_mut]),
[`get_single`]\([`_mut`][get_single_mut])|O(a)| +/// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)| +/// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// -/// While it's possible to get a single result from a query by using `iter.next()`, a more -/// idiomatic approach would use the [`single`](Self::single) or [`single_mut`](Self::single_mut) -/// methods instead. Keep in mind though that they will return a [`QuerySingleError`] if the -/// number of query results differ from being exactly one. If that's the case, use `iter.next()` -/// (or `iter_mut.next()`) to only get the first query result. +/// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient +/// [`iter`]: Self::iter +/// [`for_each`]: Self::for_each +/// [`par_for_each`]: Self::par_for_each +/// [`iter_combinations`]: Self::iter_combinations +/// [`get`]: Self::get +/// [`many`]: Self::many +/// [`many_mut`]: Self::many_mut +/// [`single`]: Self::single +/// [`get_single`]: Self::get_single +/// [iter_mut]: Self::iter_mut +/// [for_each_mut]: Self::for_each_mut +/// [par_for_each_mut]: Self::par_for_each_mut +/// [iter_combinations_mut]: Self::iter_combinations_mut +/// [get_mut]: Self::get_mut +/// [get_many]: Self::get_many +/// [get_many_mut]: Self::get_many_mut +/// [single_mut]: Self::single_mut +/// [get_single_mut]: Self::get_single_mut +/// [`With`]: crate::query::With +/// [`Without`]: crate::query::Without +/// [`Or`]: crate::query::Or +/// [`Added`]: crate::query::Added +/// [`Changed`]: crate::query::Changed +/// [many_mut]: Self::many_mut +/// [`get_many`]: Self::get_many +/// [`iter_many`]: Self::iter_many +/// [`many_for_each_mut`]: Self::many_for_each_mut pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> { pub(crate) world: &'world World, pub(crate) state: &'state QueryState, @@ -296,15 +315,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query results. - /// - /// This can only return immutable data (mutable data will be cast to an immutable form). - /// See [`Self::iter_mut`] for queries that contain at least one mutable component. + /// Returns an [`Iterator`] over the read-only query items. /// /// # Example /// - /// Here, the `report_names_system` iterates over the `Player` component of every entity - /// that contains it: + /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -319,6 +334,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` + /// + /// # See also + /// + /// - [`iter_mut`](Self::iter_mut) for mutable query items. + /// - [`for_each`](Self::for_each) for the closure based alternative. #[inline] pub fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly> { // SAFETY: system runs without conflicts with other systems. @@ -332,12 +352,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query results. + /// Returns an [`Iterator`] over the query items. /// /// # Example /// - /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in - /// the world that contains it in order to update it: + /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -352,6 +371,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` + /// + /// # See also + /// + /// - [`iter`](Self::iter) for read-only query items. #[inline] pub fn iter_mut(&mut self) -> QueryIter<'_, 's, Q, F> { // SAFETY: system runs without conflicts with other systems. @@ -362,13 +385,25 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition. - /// This can only return immutable data + /// Returns a [`QueryCombinationIter`] over all combinations of `K` read-only query items without repetition. + /// + /// # Example /// - /// For permutations of size `K` of query returning `N` results, you will get: - /// - if `K == N`: one permutation of all query results - /// - if `K < N`: all possible `K`-sized combinations of query results, without repetition - /// - if `K > N`: empty set (no `K`-sized combinations exist) + /// ``` + /// # use bevy_ecs::prelude::*; + /// # #[derive(Component)] + /// # struct ComponentA; + /// # + /// fn some_system(query: Query<&ComponentA>) { + /// for [a1, a2] in query.iter_combinations() { + /// // ... + /// } + /// } + /// ``` + /// + /// # See also + /// + /// - [`iter_combinations_mut`](Self::iter_combinations_mut) for mutable query item combinations. #[inline] pub fn iter_combinations( &self, @@ -384,28 +419,25 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Iterates over all possible combinations of `K` query results without repetition. + /// Returns a [`QueryCombinationIter`] over all combinations of `K` query items without repetition. /// - /// The returned value is not an `Iterator`, because that would lead to aliasing of mutable references. - /// In order to iterate it, use `fetch_next` method with `while let Some(..)` loop pattern. + /// # Example /// /// ``` /// # use bevy_ecs::prelude::*; - /// #[derive(Component)] - /// # struct A; - /// # fn some_system(mut query: Query<&mut A>) { - /// // iterate using `fetch_next` in while loop - /// let mut combinations = query.iter_combinations_mut(); - /// while let Some([mut a, mut b]) = combinations.fetch_next() { - /// // mutably access components data + /// # #[derive(Component)] + /// # struct ComponentA; + /// fn some_system(mut query: Query<&mut ComponentA>) { + /// let mut combinations = query.iter_combinations_mut(); + /// while let Some([mut a1, mut a2]) = combinations.fetch_next() { + /// // mutably access components data + /// } /// } - /// # } /// ``` /// - /// There is no `for_each` method, because it cannot be safely implemented - /// due to a [compiler bug](https://github.com/rust-lang/rust/issues/62529). + /// # See also /// - /// For immutable access see [`Query::iter_combinations`]. + /// - [`iter_combinations`](Self::iter_combinations) for read-only query item combinations. #[inline] pub fn iter_combinations_mut( &mut self, @@ -421,19 +453,18 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query results of a list of [`Entity`]'s. + /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list. /// - /// This can only return immutable data (mutable data will be cast to an immutable form). - /// See [`Self::iter_many_mut`] for queries that contain at least one mutable component. + /// # Example /// - /// # Examples /// ``` /// # use bevy_ecs::prelude::*; - /// #[derive(Component)] - /// struct Counter { - /// value: i32 - /// } - /// + /// # #[derive(Component)] + /// # struct Counter { + /// # value: i32 + /// # } + /// # + /// // A component containing an entity list. /// #[derive(Component)] /// struct Friends { /// list: Vec, @@ -451,6 +482,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(system); /// ``` + /// + /// # See also + /// + /// - [`many_for_each_mut`](Self::many_for_each_mut) to get mutable query items. #[inline] pub fn iter_many( &self, @@ -520,12 +555,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query results. + /// Returns an [`Iterator`] over the query items. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure - /// this call does not result in multiple mutable references to the same component + /// This function makes it possible to violate Rust's aliasing guarantees. + /// You must make sure this call does not result in multiple mutable references to the same component. + /// + /// # See also + /// + /// - [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) for the safe versions. #[inline] pub unsafe fn iter_unsafe(&'s self) -> QueryIter<'w, 's, Q, F> { // SEMI-SAFETY: system runs without conflicts with other systems. @@ -534,12 +573,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { .iter_unchecked_manual(self.world, self.last_change_tick, self.change_tick) } - /// Iterates over all possible combinations of `K` query results without repetition. - /// See [`Query::iter_combinations`]. + /// Iterates over all possible combinations of `K` query items without repetition. /// /// # Safety - /// This allows aliased mutability. You must make sure this call does not result in multiple - /// mutable references to the same component + /// + /// This allows aliased mutability. + /// You must make sure this call does not result in multiple mutable references to the same component. + /// + /// # See also + /// + /// - [`iter_combinations`](Self::iter_combinations) and [`iter_combinations_mut`](Self::iter_combinations_mut) for the safe versions. #[inline] pub unsafe fn iter_combinations_unsafe( &self, @@ -553,14 +596,17 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ) } - /// Returns an [`Iterator`] over the query results of a list of [`Entity`]'s. - /// - /// If you want safe mutable access to query results of a list of [`Entity`]'s. See [`Self::iter_many_mut`]. + /// Returns an [`Iterator`] over the query items generated from an [`Entity`] list. /// /// # Safety + /// /// This allows aliased mutability and does not check for entity uniqueness. /// You must make sure this call does not result in multiple mutable references to the same component. - /// Particular care must be taken when collecting the data (rather than iterating over it one item at a time) such as via `[Iterator::collect()]`. + /// Particular care must be taken when collecting the data (rather than iterating over it one item at a time) such as via [`Iterator::collect`]. + /// + /// # See also + /// + /// - [`many_for_each_mut`](Self::many_for_each_mut) to safely access the query items. pub unsafe fn iter_many_unsafe( &self, entities: EntityList, @@ -576,15 +622,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ) } - /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot - /// be chained like a normal [`Iterator`]. + /// Runs `f` on each read-only query item. /// - /// This can only pass in immutable data, see [`Self::for_each_mut`] for mutable access. + /// It is faster than the equivalent [`iter`](Self::iter) method, but cannot be chained like a normal [`Iterator`]. /// /// # Example /// - /// Here, the `report_names_system` iterates over the `Player` component of every entity - /// that contains it: + /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -599,6 +643,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` + /// + /// # See also + /// + /// - [`for_each_mut`](Self::for_each_mut) to operate on mutable query items. #[inline] pub fn for_each<'this>(&'this self, f: impl FnMut(ROQueryItem<'this, Q>)) { // SAFETY: system runs without conflicts with other systems. @@ -613,13 +661,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot - /// be chained like a normal [`Iterator`]. + /// Runs `f` on each query item. + /// + /// This is faster than the equivalent [`iter`](Self::iter) method, but cannot be chained like a normal [`Iterator`]. /// /// # Example /// - /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in - /// the world that contains it in order to update it: + /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -634,6 +682,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` + /// + /// # See also + /// + /// - [`for_each`](Self::for_each) to operate on read-only query items. #[inline] pub fn for_each_mut<'a, FN: FnMut(QueryItem<'a, Q>)>(&'a mut self, f: FN) { // SAFETY: system runs without conflicts with other systems. same-system queries have runtime @@ -648,10 +700,9 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. + /// Runs `f` on each read-only query item in parallel. /// - /// This can only be called for immutable data, see [`Self::par_for_each_mut`] for - /// mutable access. + /// Parallelization is achieved by using the [`World`]'s [`ComputeTaskPool`]. /// /// # Tasks and batch size /// @@ -663,16 +714,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// Rule of thumb: If the function body is (mostly) computationally expensive but there are not many items, a small batch size (=more batches) may help to even out the load. /// If the body is computationally cheap and you have many items, a large batch size (=fewer batches) avoids spawning additional futures that don't help to even out the load. /// - /// # Arguments - /// - ///* `batch_size` - The number of batches to spawn - ///* `f` - The function to run on each item in the query + /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool /// /// # Panics - /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being - /// initialized and run from the ECS scheduler, this should never panic. /// - /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool + /// This method panics if the [`ComputeTaskPool`] resource is added to the `World` before using this method. + /// If using this from a query that is being initialized and run from the [`Schedule`](crate::schedule::Schedule), this should never panic. + /// + /// # See also + /// + /// - [`par_for_each_mut`](Self::par_for_each_mut) for operating on mutable query items. #[inline] pub fn par_for_each<'this>( &'this self, @@ -692,14 +743,20 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. - /// See [`Self::par_for_each`] for more details. + /// Runs `f` on each read-only query item in parallel. + /// + /// Parallelization is achieved by using the [`World`]'s [`ComputeTaskPool`]. /// /// # Panics - /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being - /// initialized and run from the ECS scheduler, this should never panic. + /// + /// This method panics if the [`ComputeTaskPool`] resource is added to the `World` before using this method. + /// If using this from a query that is being initialized and run from the [`Schedule`](crate::schedule::Schedule), this should never panic. /// /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool + /// + /// # See also + /// + /// - [`par_for_each`](Self::par_for_each) for more usage details. #[inline] pub fn par_for_each_mut<'a, FN: Fn(QueryItem<'a, Q>) + Send + Sync + Clone>( &'a mut self, @@ -719,18 +776,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Returns the query result for the given [`Entity`]. + /// Returns the read-only query item for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. - /// - /// This can only return immutable data (mutable data will be cast to an immutable form). - /// See [`get_mut`](Self::get_mut) for queries that contain at least one mutable component. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Example /// - /// Here, `get` is used to retrieve the exact query result of the entity specified by the - /// `SelectedCharacter` resource. + /// Here, `get` is used to retrieve the exact query item of the entity specified by the `SelectedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -751,6 +803,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` + /// + /// # See also + /// + /// - [`get_mut`](Self::get_mut) to get a mutable query item. #[inline] pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. @@ -765,14 +821,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the read-only query results for the given array of [`Entity`]. + /// Returns the read-only query items for the given array of [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// The elements of the array do not need to be unique, unlike `get_many_mut`. /// - /// Note that the unlike [`Query::get_many_mut`], the entities passed in do not need to be unique. + /// # See also /// - /// See [`Query::many`] for the infallible equivalent. + /// - [`get_many_mut`](Self::get_many_mut) to get mutable query items. + /// - [`many`](Self::many) for the panicking version. #[inline] pub fn get_many( &self, @@ -789,9 +846,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the read-only query items for the provided array of [`Entity`] + /// Returns the read-only query items for the given array of [`Entity`]. /// - /// See [`Query::get_many`] for the [`Result`]-returning equivalent. + /// # Panics + /// + /// This method panics if there is a query mismatch or a non-existing entity. /// /// # Examples /// ```rust, no_run @@ -824,20 +883,22 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// } /// ``` + /// + /// # See also + /// + /// - [`get_many`](Self::get_many) for the non-panicking version. #[inline] pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, Q>; N] { self.get_many(entities).unwrap() } - /// Returns the query result for the given [`Entity`]. + /// Returns the query item for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Example /// - /// Here, `get_mut` is used to retrieve the exact query result of the entity specified by the - /// `PoisonedCharacter` resource. + /// Here, `get_mut` is used to retrieve the exact query item of the entity specified by the `PoisonedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -854,6 +915,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(poison_system); /// ``` + /// + /// # See also + /// + /// - [`get`](Self::get) to get a read-only query item. #[inline] pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. @@ -868,12 +933,14 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the query results for the given array of [`Entity`]. + /// Returns the query items for the given array of [`Entity`]. /// - /// In case of a nonexisting entity, duplicate entities or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity, duplicate entities or mismatched component, a [`QueryEntityError`] is returned instead. + /// + /// # See also /// - /// See [`Query::many_mut`] for the infallible equivalent. + /// - [`get_many`](Self::get_many) to get read-only query items. + /// - [`many_mut`](Self::many_mut) for the panicking version. #[inline] pub fn get_many_mut( &mut self, @@ -890,9 +957,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the query items for the provided array of [`Entity`] + /// Returns the query items for the given array of [`Entity`]. + /// + /// # Panics /// - /// See [`Query::get_many_mut`] for the [`Result`]-returning equivalent. + /// This method panics if there is a query mismatch, a non-existing entity, or the same `Entity` is included more than once in the array. /// /// # Examples /// @@ -931,20 +1000,28 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// } /// ``` + /// + /// # See also + /// + /// - [`get_many_mut`](Self::get_many_mut) for the non panicking version. + /// - [`many`](Self::many) to get read-only query items. #[inline] pub fn many_mut(&mut self, entities: [Entity; N]) -> [QueryItem<'_, Q>; N] { self.get_many_mut(entities).unwrap() } - /// Returns the query result for the given [`Entity`]. + /// Returns the query item for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure - /// this call does not result in multiple mutable references to the same component + /// This function makes it possible to violate Rust's aliasing guarantees. + /// You must make sure this call does not result in multiple mutable references to the same component. + /// + /// # See also + /// + /// - [`get_mut`](Self::get_mut) for the safe version. #[inline] pub unsafe fn get_unchecked( &'s self, @@ -956,15 +1033,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { .get_unchecked_manual(self.world, entity, self.last_change_tick, self.change_tick) } - /// Returns a reference to the [`Entity`]'s [`Component`] of the given type. + /// Returns a shared reference to the component `T` of the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Example /// - /// Here, `get_component` is used to retrieve the `Character` component of the entity - /// specified by the `SelectedCharacter` resource. + /// Here, `get_component` is used to retrieve the `Character` component of the entity specified by the `SelectedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -985,6 +1060,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` + /// + /// # See also + /// + /// - [`get_component_mut`](Self::get_component_mut) to get a mutable reference of a component. #[inline] pub fn get_component(&self, entity: Entity) -> Result<&T, QueryComponentError> { let world = self.world; @@ -1012,15 +1091,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. + /// Returns a mutable reference to the component `T` of the given entity. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Example /// - /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity - /// specified by the `PoisonedCharacter` resource. + /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity specified by the `PoisonedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -1037,6 +1114,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(poison_system); /// ``` + /// + /// # See also + /// + /// - [`get_component`](Self::get_component) to get a shared reference of a component. #[inline] pub fn get_component_mut( &mut self, @@ -1046,15 +1127,18 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { unsafe { self.get_component_unchecked_mut(entity) } } - /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. + /// Returns a mutable reference to the component `T` of the given entity. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is - /// returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure - /// this call does not result in multiple mutable references to the same component + /// This function makes it possible to violate Rust's aliasing guarantees. + /// You must make sure this call does not result in multiple mutable references to the same component. + /// + /// # See also + /// + /// - [`get_component_mut`](Self::get_component_mut) for the safe version. #[inline] pub unsafe fn get_component_unchecked_mut( &self, @@ -1085,11 +1169,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a single immutable query result when there is exactly one entity matching - /// the query. + /// Returns a single read-only query item when there is exactly one entity matching the query. + /// + /// # Panics /// - /// This can only return immutable data. Use [`single_mut`](Self::single_mut) for - /// queries that contain at least one mutable component. + /// This method panics if the number of query items is not exactly one. /// /// # Example /// @@ -1106,23 +1190,18 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(player_system); /// ``` /// - /// # Panics + /// # See also /// - /// Panics if the number of query results is not exactly one. Use - /// [`get_single`](Self::get_single) to return a `Result` instead of panicking. + /// - [`get_single`](Self::get_single) for the non-panicking version. + /// - [`single_mut`](Self::single_mut) to get the mutable query item. #[track_caller] pub fn single(&self) -> ROQueryItem<'_, Q> { self.get_single().unwrap() } - /// Returns a single immutable query result when there is exactly one entity matching - /// the query. - /// - /// This can only return immutable data. Use [`get_single_mut`](Self::get_single_mut) - /// for queries that contain at least one mutable component. + /// Returns a single read-only query item when there is exactly one entity matching the query. /// - /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned - /// instead. + /// If the number of query items is not exactly one, a [`QuerySingleError`] is returned instead. /// /// # Example /// @@ -1146,6 +1225,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(player_scoring_system); /// ``` + /// + /// # See also + /// + /// - [`get_single_mut`](Self::get_single_mut) to get the mutable query item. + /// - [`single`](Self::single) for the panicking version. #[inline] pub fn get_single(&self) -> Result, QuerySingleError> { // SAFETY: @@ -1160,8 +1244,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a single mutable query result when there is exactly one entity matching - /// the query. + /// Returns a single query item when there is exactly one entity matching the query. + /// + /// # Panics + /// + /// This method panics if the number of query item is not exactly one. /// /// # Example /// @@ -1180,20 +1267,18 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system); /// ``` /// - /// # Panics + /// # See also /// - /// Panics if the number of query results is not exactly one. Use - /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking. + /// - [`get_single_mut`](Self::get_single_mut) for the non-panicking version. + /// - [`single`](Self::single) to get the read-only query item. #[track_caller] pub fn single_mut(&mut self) -> QueryItem<'_, Q> { self.get_single_mut().unwrap() } - /// Returns a single mutable query result when there is exactly one entity matching - /// the query. + /// Returns a single query item when there is exactly one entity matching the query. /// - /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned - /// instead. + /// If the number of query items is not exactly one, a [`QuerySingleError`] is returned instead. /// /// # Example /// @@ -1211,6 +1296,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system); /// ``` + /// + /// # See also + /// + /// - [`get_single`](Self::get_single) to get the read-only query item. + /// - [`single_mut`](Self::single_mut) for the panicking version. #[inline] pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { // SAFETY: @@ -1225,12 +1315,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns `true` if there are no query results. + /// Returns `true` if there are no query items. /// /// # Example /// - /// Here, the score is increased only if an entity with a `Player` component is present - /// in the world: + /// Here, the score is increased only if an entity with a `Player` component is present in the world: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -1341,7 +1430,7 @@ impl std::fmt::Display for QueryComponentError { } impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { - /// Returns the query result for the given [`Entity`], with the actual "inner" world lifetime. + /// Returns the query item for the given [`Entity`], with the actual "inner" world lifetime. /// /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is /// returned instead. @@ -1351,7 +1440,7 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// # Example /// - /// Here, `get` is used to retrieve the exact query result of the entity specified by the + /// Here, `get` is used to retrieve the exact query item of the entity specified by the /// `SelectedCharacter` resource. /// /// ``` @@ -1387,7 +1476,7 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query results, with the actual "inner" world lifetime. + /// Returns an [`Iterator`] over the query items, with the actual "inner" world lifetime. /// /// This can only return immutable data (mutable data will be cast to an immutable form). /// See [`Self::iter_mut`] for queries that contain at least one mutable component. From a04c319943c86150212ea95102565d9df2faf85d Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 20 Jun 2022 08:36:20 +0200 Subject: [PATCH 02/26] State that query creation has a time-constant cost --- crates/bevy_ecs/src/system/query.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 565802c545fa6..2f37e0f2132ec 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -208,7 +208,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// /// # Performance /// -/// Creating a `Query` is a low-cost operation. +/// Creating a `Query` is a low-cost constant operation. /// Iterating it, on the other hand, fetches data from the world and generates items, which can have a significant computational cost. /// However, iteration cost of queries is reduced by the fact that they have an internal archetype cache to avoid re-computing archetype matches on each query access. /// From e403f9ec31db083802a04c6041c93bddac8c3f6c Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 20 Jun 2022 08:53:41 +0200 Subject: [PATCH 03/26] Table vs sparse set query iteratino performance --- crates/bevy_ecs/src/system/query.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 2f37e0f2132ec..5fceb6c2355f5 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -212,6 +212,8 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// Iterating it, on the other hand, fetches data from the world and generates items, which can have a significant computational cost. /// However, iteration cost of queries is reduced by the fact that they have an internal archetype cache to avoid re-computing archetype matches on each query access. /// +/// [`Table`] component storage type is much more optimized for query iteration than [`SparseSet`]. +/// /// Two systems cannot be executed in parallel if both access the same component type where at least one of the accesses is mutable. /// This happens unless the schedule can verify that no entity could be found in both queries. /// @@ -268,6 +270,8 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// [`get_many`]: Self::get_many /// [`iter_many`]: Self::iter_many /// [`many_for_each_mut`]: Self::many_for_each_mut +/// [`Table`]: crate::storage::Table +/// [`SparseSet`]: crate::storage::SparseSet pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> { pub(crate) world: &'world World, pub(crate) state: &'state QueryState, From b0304e4920358148135354db6b9e8d99af70e3ea Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 20 Jun 2022 09:06:23 +0200 Subject: [PATCH 04/26] Reference `Query` from `WorldQuery` --- crates/bevy_ecs/src/query/fetch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 0b831fb1cad5a..28de6977030c9 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -12,7 +12,7 @@ pub use bevy_ecs_macros::WorldQuery; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use std::{cell::UnsafeCell, marker::PhantomData}; -/// Types that can be used to query a [`World`]. +/// Types that can be fetched from a [`World`] using a [`Query`]. /// /// There are many types that natively implement `WorldQuery`: /// @@ -43,7 +43,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// -/// [queries]: crate::system::Query +/// [`Query`]: crate::system::Query /// [`With`]: crate::query::With /// [`Without`]: crate::query::Without /// [`Or`]: crate::query::Or From 7be57c95439496f25b10a974087e3c6078db2f5d Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 20 Jun 2022 09:07:04 +0200 Subject: [PATCH 05/26] Remove `WorldQuery` repetition in second paragraph --- crates/bevy_ecs/src/query/fetch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 28de6977030c9..a13a4e56dd52c 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -14,7 +14,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// Types that can be fetched from a [`World`] using a [`Query`]. /// -/// There are many types that natively implement `WorldQuery`: +/// There are many types that natively implement this trait: /// /// - **Component references.** /// Fetches a component by reference (immutably or mutably). From 8195f8361114ba92dbb4a65e2c8e67baab3cdd27 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Tue, 21 Jun 2022 10:22:07 +0200 Subject: [PATCH 06/26] Add note about `for_each` vs `iter` performance --- crates/bevy_ecs/src/system/query.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 5fceb6c2355f5..04601ca1d9c9a 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -242,6 +242,9 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)| /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// +/// `for_each` methods are generally faster than their `iter` version on worlds with a high archetype fragmentation. +/// On the other hand, `iter` methods are more ergonomic and flexible. +/// /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient /// [`iter`]: Self::iter /// [`for_each`]: Self::for_each From c7b234377a63091b3335782e32bb74907d070a21 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 1 Jul 2022 10:32:31 +0200 Subject: [PATCH 07/26] Remove implementation detail from performance section --- crates/bevy_ecs/src/system/query.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 04601ca1d9c9a..65c05bf7075d1 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -210,7 +210,6 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// /// Creating a `Query` is a low-cost constant operation. /// Iterating it, on the other hand, fetches data from the world and generates items, which can have a significant computational cost. -/// However, iteration cost of queries is reduced by the fact that they have an internal archetype cache to avoid re-computing archetype matches on each query access. /// /// [`Table`] component storage type is much more optimized for query iteration than [`SparseSet`]. /// From 2a37c0eb584aa349f52555c390d940c6b448346c Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 1 Jul 2022 10:44:28 +0200 Subject: [PATCH 08/26] Reword `for_each` performance --- crates/bevy_ecs/src/system/query.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 65c05bf7075d1..5750a5a1f8c57 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -241,8 +241,9 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)| /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// -/// `for_each` methods are generally faster than their `iter` version on worlds with a high archetype fragmentation. -/// On the other hand, `iter` methods are more ergonomic and flexible. +/// `for_each` methods are seen to be generally faster than their `iter` version on worlds with high archetype fragmentation. +/// Only benchmarks can guarantee what variant is faster in each use case. +/// So, if performance analysis is not done, it's better to use the more ergonomic `iter` methods. /// /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient /// [`iter`]: Self::iter From 91c0b9d14bed92565e48fc2ca2829da42e8fdf8f Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 1 Jul 2022 10:45:20 +0200 Subject: [PATCH 09/26] Remove `for_each` performance remarks from method descriptions --- crates/bevy_ecs/src/system/query.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 5750a5a1f8c57..c084fa8d39365 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -631,8 +631,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// Runs `f` on each read-only query item. /// - /// It is faster than the equivalent [`iter`](Self::iter) method, but cannot be chained like a normal [`Iterator`]. - /// /// # Example /// /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: @@ -670,8 +668,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// Runs `f` on each query item. /// - /// This is faster than the equivalent [`iter`](Self::iter) method, but cannot be chained like a normal [`Iterator`]. - /// /// # Example /// /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: From 8ffe098fe86cdf9eb3d41e0aba999e7b76d231bc Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 1 Jul 2022 10:51:50 +0200 Subject: [PATCH 10/26] Add cross-links between `iter` and `for_each` methods --- crates/bevy_ecs/src/system/query.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index c084fa8d39365..8ad90a7d9c606 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -382,6 +382,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # See also /// /// - [`iter`](Self::iter) for read-only query items. + /// - [`for_each_mut`](Self::for_each_mut) for the closure based alternative. #[inline] pub fn iter_mut(&mut self) -> QueryIter<'_, 's, Q, F> { // SAFETY: system runs without conflicts with other systems. @@ -652,6 +653,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # See also /// /// - [`for_each_mut`](Self::for_each_mut) to operate on mutable query items. + /// - [`iter`](Self::iter) for the iterator based alternative. #[inline] pub fn for_each<'this>(&'this self, f: impl FnMut(ROQueryItem<'this, Q>)) { // SAFETY: system runs without conflicts with other systems. @@ -689,6 +691,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # See also /// /// - [`for_each`](Self::for_each) to operate on read-only query items. + /// - [`iter_mut`](Self::iter_mut) for the iterator based alternative. #[inline] pub fn for_each_mut<'a, FN: FnMut(QueryItem<'a, Q>)>(&'a mut self, f: FN) { // SAFETY: system runs without conflicts with other systems. same-system queries have runtime From 9166cd16bfc78f08aac48b22ae99476167098793 Mon Sep 17 00:00:00 2001 From: Federico Rinaldi Date: Sat, 2 Jul 2022 12:49:37 +0200 Subject: [PATCH 11/26] Apply @james7132 suggestion on `for_each` performance Co-authored-by: James Liu --- crates/bevy_ecs/src/system/query.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 8ad90a7d9c606..f25910b4e3e5a 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -242,8 +242,10 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// /// `for_each` methods are seen to be generally faster than their `iter` version on worlds with high archetype fragmentation. -/// Only benchmarks can guarantee what variant is faster in each use case. -/// So, if performance analysis is not done, it's better to use the more ergonomic `iter` methods. +/// As iterators are in general more flexible and better integrated with the rest of the +/// Rust ecosystem, it's advised to use `iter` methods over `for_each`. +/// It is strongly advised to only use `for_each` if it tangibly improves performance: be sure profile +/// or benchmark both before and after the change. /// /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient /// [`iter`]: Self::iter From ea313b89269e1b006d5a1ac8aeee3629db8f51b9 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sat, 2 Jul 2022 12:53:38 +0200 Subject: [PATCH 12/26] Break doc comments at clause or sentence boundaries --- crates/bevy_ecs/src/system/query.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index f25910b4e3e5a..8eccc2e3beb73 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -242,10 +242,10 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// /// `for_each` methods are seen to be generally faster than their `iter` version on worlds with high archetype fragmentation. -/// As iterators are in general more flexible and better integrated with the rest of the -/// Rust ecosystem, it's advised to use `iter` methods over `for_each`. -/// It is strongly advised to only use `for_each` if it tangibly improves performance: be sure profile -/// or benchmark both before and after the change. +/// As iterators are in general more flexible and better integrated with the rest of the Rust ecosystem, +/// it is advised to use `iter` methods over `for_each`. +/// It is strongly advised to only use `for_each` if it tangibly improves performance: +/// be sure profile or benchmark both before and after the change. /// /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient /// [`iter`]: Self::iter From bbf8a1e5e63f037c9a2c949a444385af4725fabd Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 16:27:22 +0200 Subject: [PATCH 13/26] Split long line --- crates/bevy_ecs/src/query/iter.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index cd3427c1be80c..23c48aea62d5f 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -380,7 +380,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> QueryCombinationIter< } /// Iterator type is intentionally implemented only for read-only access. -/// Doing so for mutable references would be unsound, because calling `next` multiple times would allow multiple owned references to the same data to exist. +/// Doing so for mutable references would be unsound, +/// because calling `next` multiple times would allow multiple owned references to the same data to exist. impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> Iterator for QueryCombinationIter<'w, 's, Q, F, K> where From 890624c3956a1d71396d49bb06d1f1b9e857d15a Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 17:03:07 +0200 Subject: [PATCH 14/26] =?UTF-8?q?Migrate=20`many=5Ffor=5Feach=5Fmut`=20?= =?UTF-8?q?=E2=86=92=20`iter=5Fmany=5Fmut`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bevy_ecs/src/system/query.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 8eccc2e3beb73..d7bf5e9ee78db 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -196,7 +196,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |:---:|---| /// |[`iter`]\([`_mut`][iter_mut])|Returns an iterator over all query items.| /// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|Runs a specified function for each query item.| -/// |[`iter_many`],
[`many_for_each_mut`]|Iterates or runs a specified function over query items generated by a list of entities.| +/// |[`iter_many`]\([`_mut`][iter_many_mut])|Iterates or runs a specified function over query items generated by a list of entities.| /// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|Returns an iterator over all combinations of a specified number of query items.| /// |[`get`]\([`_mut`][get_mut])|Returns the query item for the specified entity.| /// |[`many`]\([`_mut`][many_mut]),
[`get_many`]\([`_mut`][get_many_mut])|Returns the query items for the specified entities.| @@ -232,7 +232,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |:---:|:---:| /// |[`iter`]\([`_mut`][iter_mut])|O(n)| /// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|O(n)| -/// |[`iter_many`],
[`many_for_each_mut`]|O(k)| +/// |[`iter_many`]\([`_mut`][iter_many_mut])|O(k)| /// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|O(nCr)| /// |[`get`]\([`_mut`][get_mut])|O(1)| /// |([`get_`][get_many])[`many`]|O(k)| @@ -274,7 +274,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// [many_mut]: Self::many_mut /// [`get_many`]: Self::get_many /// [`iter_many`]: Self::iter_many -/// [`many_for_each_mut`]: Self::many_for_each_mut +/// [iter_many_mut]: Self::iter_many_mut /// [`Table`]: crate::storage::Table /// [`SparseSet`]: crate::storage::SparseSet pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> { @@ -495,7 +495,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// # See also /// - /// - [`many_for_each_mut`](Self::many_for_each_mut) to get mutable query items. + /// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items. #[inline] pub fn iter_many( &self, @@ -616,7 +616,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// # See also /// - /// - [`many_for_each_mut`](Self::many_for_each_mut) to safely access the query items. + /// - [`iter_many_mut`](Self::iter_many_mut) to safely access the query items. pub unsafe fn iter_many_unsafe( &self, entities: EntityList, From 68df415eeb99786f0ba01bb9f156ee183efb5642 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 17:06:19 +0200 Subject: [PATCH 15/26] Fix `iter_many_mut` description --- crates/bevy_ecs/src/system/query.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index d7bf5e9ee78db..cc622050a59b1 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -516,7 +516,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Calls a closure on each result of [`Query`] where the entities match. + /// Returns an [`Iterator`] over the query items generated from an [`Entity`] list. + /// /// # Examples /// /// ``` From 4aa7e20e7de3d34b37dfa181137a345f17619952 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 17:13:33 +0200 Subject: [PATCH 16/26] Update `to_readonly` description This will reflect the added context in this PR that is aware of what query items are and that they can be read-only or not. --- crates/bevy_ecs/src/system/query.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index cc622050a59b1..a5b86f79feaa9 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -306,7 +306,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Downgrades all data accessed in this query to a read-only form. + /// Returns another `Query` from this that fetches the read-only version of the query items. /// /// For example, `Query<(&mut A, &B, &mut C), With>` will become `Query<(&A, &B, &C), With>`. /// This can be useful when working around the borrow checker, From d5372e9b982e828e1a1df09bf1b2662dc4f90081 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 17:37:59 +0200 Subject: [PATCH 17/26] Ref-style link revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved all links to the bottom of the doc comment. Links have been alphabetically ordered. Rebase notes: - After #5205 got merged, the “Safety” section of `WorldQuery` has changed. I listed the mentioned methods for a better layout. I also removed the `WorldQuery::` prefix for readability. - I don't have enough knowledge of the previous and current state of `WorldQuery` types, so the documentation may be outdated somewhere. `WorldQuery` needs another review round. --- crates/bevy_ecs/src/query/fetch.rs | 34 +++++++----- crates/bevy_ecs/src/query/iter.rs | 15 +++--- crates/bevy_ecs/src/system/query.rs | 84 ++++++++++++++--------------- 3 files changed, 70 insertions(+), 63 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index a13a4e56dd52c..f0a4350c543c8 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -43,13 +43,6 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// -/// [`Query`]: crate::system::Query -/// [`With`]: crate::query::With -/// [`Without`]: crate::query::Without -/// [`Or`]: crate::query::Or -/// [`Added`]: crate::query::Added -/// [`Changed`]: crate::query::Changed -/// /// # Trait derivation /// /// Query design can be easily structured by deriving `WorldQuery` for custom types. @@ -280,15 +273,32 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// # bevy_ecs::system::assert_is_system(my_system); /// ``` +/// /// # Safety /// -/// component access of `ROQueryFetch` must be a subset of `QueryFetch` +/// Component access of `ROQueryFetch` must be a subset of `QueryFetch` /// and `ROQueryFetch` must match exactly the same archetypes/tables as `QueryFetch` /// -/// Implementor must ensure that [`WorldQuery::update_component_access`] and -/// [`WorldQuery::update_archetype_component_access`] exactly reflects the results of -/// [`WorldQuery::matches_component_set`], [`WorldQuery::archetype_fetch`], and -/// [`WorldQuery::table_fetch`]. +/// Implementor must ensure that +/// [`update_component_access`] and [`update_archetype_component_access`] +/// exactly reflects the results of the following methods: +/// +/// - [`matches_component_set`] +/// - [`archetype_fetch`] +/// - [`table_fetch`] +/// +/// [`archetype_fetch`]: Self::archetype_fetch +/// [`Added`]: crate::query::Added +/// [`Changed`]: crate::query::Changed +/// [`Fetch`]: crate::query::WorldQueryGats::Fetch +/// [`matches_component_set`]: Self::matches_component_set +/// [`Or`]: crate::query::Or +/// [`Query`]: crate::system::Query +/// [`table_fetch`]: Self::table_fetch +/// [`update_archetype_component_access`]: Self::update_archetype_component_access +/// [`update_component_access`]: Self::update_component_access +/// [`With`]: crate::query::With +/// [`Without`]: crate::query::Without pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> { /// The read-only variant of this [`WorldQuery`], which satisfies the [`ReadOnlyWorldQuery`] trait. type ReadOnly: ReadOnlyWorldQuery; diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 23c48aea62d5f..fd4ac9b7e7baf 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -228,13 +228,7 @@ where /// /// It implements [`Iterator`] only if it iterates over read-only query items ([learn more]). /// -/// In the case of mutable query items, it can be iterated by calling [`fetch_next`](Self::fetch_next) in a `while let` loop. -/// -/// [`Query`]: crate::system::Query -/// [performance section]: crate::system::Query#performance -/// [`Query::iter_combinations`]: crate::system::Query::iter_combinations -/// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut -/// [learn more]: Self#impl-Iterator +/// In the case of mutable query items, it can be iterated by calling [`fetch_next`] in a `while let` loop. /// /// # Examples /// @@ -266,6 +260,13 @@ where /// } /// } /// ``` +/// +/// [`fetch_next`]: Self::fetch_next +/// [learn more]: Self#impl-Iterator +/// [performance section]: crate::system::Query#performance +/// [`Query`]: crate::system::Query +/// [`Query::iter_combinations`]: crate::system::Query::iter_combinations +/// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut pub struct QueryCombinationIter<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index a5b86f79feaa9..a6cbc6c1e9c55 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -24,10 +24,6 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// A set of conditions that determines wheter query items should be kept or discarded. /// This type parameter is optional. /// -/// [System parameter]: crate::system::SystemParam -/// [entity identifiers]: crate::entity::Entity -/// [components]: crate::component::Component -/// /// # System parameter declaration /// /// A query should always be declared as a system parameter. @@ -131,9 +127,6 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// /// See the [performance] section to learn more about the impact of optional components. /// -/// [`AnyOf`]: crate::query::AnyOf -/// [performance]: #performance -/// /// ## Disjoint queries /// /// A system cannot contain two queries that break Rust's mutability rules. @@ -194,13 +187,13 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// /// |Query methods|Effect| /// |:---:|---| -/// |[`iter`]\([`_mut`][iter_mut])|Returns an iterator over all query items.| -/// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|Runs a specified function for each query item.| -/// |[`iter_many`]\([`_mut`][iter_many_mut])|Iterates or runs a specified function over query items generated by a list of entities.| -/// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|Returns an iterator over all combinations of a specified number of query items.| -/// |[`get`]\([`_mut`][get_mut])|Returns the query item for the specified entity.| -/// |[`many`]\([`_mut`][many_mut]),
[`get_many`]\([`_mut`][get_many_mut])|Returns the query items for the specified entities.| -/// |[`single`]\([`_mut`][single_mut]),
[`get_single`]\([`_mut`][get_single_mut])|Returns the query item while veryfing that there aren't others.| +/// |[`iter`]\([`_mut`][`iter_mut`])|Returns an iterator over all query items.| +/// |[`for_each`]\([`_mut`][`for_each_mut`]),
[`par_for_each`]\([`_mut`][`par_for_each_mut`])|Runs a specified function for each query item.| +/// |[`iter_many`]\([`_mut`][`iter_many_mut`])|Iterates or runs a specified function over query items generated by a list of entities.| +/// |[`iter_combinations`]\([`_mut`][`iter_combinations_mut`])|Returns an iterator over all combinations of a specified number of query items.| +/// |[`get`]\([`_mut`][`get_mut`])|Returns the query item for the specified entity.| +/// |[`many`]\([`_mut`][`many_mut`]),
[`get_many`]\([`_mut`][`get_many_mut`])|Returns the query items for the specified entities.| +/// |[`single`]\([`_mut`][`single_mut`]),
[`get_single`]\([`_mut`][`get_single_mut`])|Returns the query item while veryfing that there aren't others.| /// /// There are two methods for each type of query operation: immutable and mutable (ending with `_mut`). /// When using immutable methods, the query items returned are of type [`ROQueryItem`], a read-only version of the query item. @@ -230,14 +223,14 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// /// |Query operation|Computational complexity| /// |:---:|:---:| -/// |[`iter`]\([`_mut`][iter_mut])|O(n)| -/// |[`for_each`]\([`_mut`][for_each_mut]),
[`par_for_each`]\([`_mut`][par_for_each_mut])|O(n)| -/// |[`iter_many`]\([`_mut`][iter_many_mut])|O(k)| -/// |[`iter_combinations`]\([`_mut`][iter_combinations_mut])|O(nCr)| -/// |[`get`]\([`_mut`][get_mut])|O(1)| -/// |([`get_`][get_many])[`many`]|O(k)| -/// |([`get_`][get_many_mut])[`many_mut`]|O(k2)| -/// |[`single`]\([`_mut`][single_mut]),
[`get_single`]\([`_mut`][get_single_mut])|O(a)| +/// |[`iter`]\([`_mut`][`iter_mut`])|O(n)| +/// |[`for_each`]\([`_mut`][`for_each_mut`]),
[`par_for_each`]\([`_mut`][`par_for_each_mut`])|O(n)| +/// |[`iter_many`]\([`_mut`][`iter_many_mut`])|O(k)| +/// |[`iter_combinations`]\([`_mut`][`iter_combinations_mut`])|O(nCr)| +/// |[`get`]\([`_mut`][`get_mut`])|O(1)| +/// |([`get_`][`get_many`])[`many`]|O(k)| +/// |([`get_`][`get_many_mut`])[`many_mut`]|O(k2)| +/// |[`single`]\([`_mut`][`single_mut`]),
[`get_single`]\([`_mut`][`get_single_mut`])|O(a)| /// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)| /// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)| /// @@ -247,36 +240,39 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// It is strongly advised to only use `for_each` if it tangibly improves performance: /// be sure profile or benchmark both before and after the change. /// +/// [`Added`]: crate::query::Added +/// [`AnyOf`]: crate::query::AnyOf /// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient -/// [`iter`]: Self::iter +/// [`Changed`]: crate::query::Changed +/// [components]: crate::component::Component +/// [entity identifiers]: crate::entity::Entity /// [`for_each`]: Self::for_each -/// [`par_for_each`]: Self::par_for_each -/// [`iter_combinations`]: Self::iter_combinations +/// [`for_each_mut`]: Self::for_each_mut /// [`get`]: Self::get +/// [`get_many`]: Self::get_many +/// [`get_many_mut`]: Self::get_many_mut +/// [`get_mut`]: Self::get_mut +/// [`get_single`]: Self::get_single +/// [`get_single_mut`]: Self::get_single_mut +/// [`iter`]: Self::iter +/// [`iter_combinations`]: Self::iter_combinations +/// [`iter_combinations_mut`]: Self::iter_combinations_mut +/// [`iter_many`]: Self::iter_many +/// [`iter_many_mut`]: Self::iter_many_mut +/// [`iter_mut`]: Self::iter_mut /// [`many`]: Self::many /// [`many_mut`]: Self::many_mut +/// [`Or`]: crate::query::Or +/// [`par_for_each`]: Self::par_for_each +/// [`par_for_each_mut`]: Self::par_for_each_mut +/// [performance]: #performance /// [`single`]: Self::single -/// [`get_single`]: Self::get_single -/// [iter_mut]: Self::iter_mut -/// [for_each_mut]: Self::for_each_mut -/// [par_for_each_mut]: Self::par_for_each_mut -/// [iter_combinations_mut]: Self::iter_combinations_mut -/// [get_mut]: Self::get_mut -/// [get_many]: Self::get_many -/// [get_many_mut]: Self::get_many_mut -/// [single_mut]: Self::single_mut -/// [get_single_mut]: Self::get_single_mut +/// [`single_mut`]: Self::single_mut +/// [`SparseSet`]: crate::storage::SparseSet +/// [System parameter]: crate::system::SystemParam +/// [`Table`]: crate::storage::Table /// [`With`]: crate::query::With /// [`Without`]: crate::query::Without -/// [`Or`]: crate::query::Or -/// [`Added`]: crate::query::Added -/// [`Changed`]: crate::query::Changed -/// [many_mut]: Self::many_mut -/// [`get_many`]: Self::get_many -/// [`iter_many`]: Self::iter_many -/// [iter_many_mut]: Self::iter_many_mut -/// [`Table`]: crate::storage::Table -/// [`SparseSet`]: crate::storage::SparseSet pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> { pub(crate) world: &'world World, pub(crate) state: &'state QueryState, From 74cf66c11f671e4134b3c1a86858f22978935336 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Sun, 31 Jul 2022 17:39:11 +0200 Subject: [PATCH 18/26] Move `WorldQuery safety section up --- crates/bevy_ecs/src/query/fetch.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index f0a4350c543c8..e2ffa2f5c3307 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -43,6 +43,11 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// +/// # Safety +/// +/// component access of `ROQueryFetch` must be a subset of `QueryFetch` +/// and `ROQueryFetch` must match exactly the same archetypes/tables as `QueryFetch` +/// /// # Trait derivation /// /// Query design can be easily structured by deriving `WorldQuery` for custom types. @@ -287,8 +292,8 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// - [`archetype_fetch`] /// - [`table_fetch`] /// -/// [`archetype_fetch`]: Self::archetype_fetch /// [`Added`]: crate::query::Added +/// [`archetype_fetch`]: Self::archetype_fetch /// [`Changed`]: crate::query::Changed /// [`Fetch`]: crate::query::WorldQueryGats::Fetch /// [`matches_component_set`]: Self::matches_component_set From 01ff48677ce72004bd894340c59652e7824e8b5a Mon Sep 17 00:00:00 2001 From: Federico Rinaldi Date: Thu, 4 Aug 2022 21:40:35 +0200 Subject: [PATCH 19/26] Apply suggestions from code review Co-authored-by: Rob Parrett --- crates/bevy_ecs/src/system/query.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index a6cbc6c1e9c55..130fbda045e1d 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -21,7 +21,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// The type of data contained in the query item. /// Only entities that match the requested data will generate an item. /// - **`F` (query filter).** -/// A set of conditions that determines wheter query items should be kept or discarded. +/// A set of conditions that determines whether query items should be kept or discarded. /// This type parameter is optional. /// /// # System parameter declaration @@ -193,7 +193,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// |[`iter_combinations`]\([`_mut`][`iter_combinations_mut`])|Returns an iterator over all combinations of a specified number of query items.| /// |[`get`]\([`_mut`][`get_mut`])|Returns the query item for the specified entity.| /// |[`many`]\([`_mut`][`many_mut`]),
[`get_many`]\([`_mut`][`get_many_mut`])|Returns the query items for the specified entities.| -/// |[`single`]\([`_mut`][`single_mut`]),
[`get_single`]\([`_mut`][`get_single_mut`])|Returns the query item while veryfing that there aren't others.| +/// |[`single`]\([`_mut`][`single_mut`]),
[`get_single`]\([`_mut`][`get_single_mut`])|Returns the query item while verifying that there aren't others.| /// /// There are two methods for each type of query operation: immutable and mutable (ending with `_mut`). /// When using immutable methods, the query items returned are of type [`ROQueryItem`], a read-only version of the query item. From fa78f7c6271f6f5ce1d4e3c43f2e6095839c2808 Mon Sep 17 00:00:00 2001 From: Federico Rinaldi Date: Mon, 8 Aug 2022 21:16:05 +0200 Subject: [PATCH 20/26] Apply diff-based suggestions Co-authored-by: Boxy --- crates/bevy_ecs/src/query/fetch.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index e2ffa2f5c3307..984bc4e98f93e 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -91,16 +91,17 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// ## Macro expansion /// -/// Expanding the macro will declare three or five additional structs, depending on whether or not the struct is marked as mutable. +/// Expanding the macro will declare three or six additional structs, depending on whether or not the struct is marked as mutable. /// For a struct named `X`, the additional structs will be: /// /// |Struct name|`mutable` only|Description| /// |:---:|:---:|---| -/// |`XItem`|---|The type of the query item| -/// |`XFetch`|---|Implements [`Fetch`] for `XItem`| -/// |`XState`|---|Implements [`FetchState`]| -/// |`XReadOnlyItem`|✓|The type of the read-only query item| -/// |`XReadOnlyFetch`|✓|Implements [`Fetch`] for `XReadOnlyItem`| +/// |`XState`|---|Used as the [`State`] type for `X` and `XReadOnly`| +/// |`XItem`|---|The type of the query item for `X`| +/// |`XFetch`|---|Used as the [`Fetch`] type for `X`| +/// |`XReadOnlyItem`|✓|The type of the query item for `XReadOnly`| +/// |`XReadOnlyFetch`|✓|Used as the [`Fetch`] type for `XReadOnly`| +/// |`XReadOnly`|✓|ReadOnly variant of `X`| /// /// ## Adding mutable references /// @@ -120,7 +121,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// ``` /// /// To grant mutable access to components, the struct must be marked with the `#[world_query(mutable)]` attribute. -/// This will also create two more structs that will be used for accessing the query immutably (see table above). +/// This will also create three more structs that will be used for accessing the query immutably (see table above). /// /// ``` /// # use bevy_ecs::prelude::*; From 1ad2328b2d8db7a825799f6b1c52ae676648a9f5 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 8 Aug 2022 21:18:27 +0200 Subject: [PATCH 21/26] =?UTF-8?q?Remove=20duplicated=20and=20outdated=20?= =?UTF-8?q?=E2=80=9CSafety=E2=80=9D=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bevy_ecs/src/query/fetch.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 984bc4e98f93e..962fe73f223a0 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -43,11 +43,6 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// -/// # Safety -/// -/// component access of `ROQueryFetch` must be a subset of `QueryFetch` -/// and `ROQueryFetch` must match exactly the same archetypes/tables as `QueryFetch` -/// /// # Trait derivation /// /// Query design can be easily structured by deriving `WorldQuery` for custom types. From 6a9c56018cde76d76e287f2553e2e1395505a191 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 8 Aug 2022 21:27:11 +0200 Subject: [PATCH 22/26] Add link to `State` associated type --- crates/bevy_ecs/src/query/fetch.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 962fe73f223a0..eb6c6158bf13d 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -295,6 +295,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// [`matches_component_set`]: Self::matches_component_set /// [`Or`]: crate::query::Or /// [`Query`]: crate::system::Query +/// [`State`]: Self::State /// [`table_fetch`]: Self::table_fetch /// [`update_archetype_component_access`]: Self::update_archetype_component_access /// [`update_component_access`]: Self::update_component_access From 684dff63d6939aee7e28bdc404ec0bb861370a15 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Mon, 8 Aug 2022 21:33:32 +0200 Subject: [PATCH 23/26] Make clippy happy --- crates/bevy_ecs/src/query/fetch.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index eb6c6158bf13d..b4f2d95b087ab 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -96,7 +96,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// |`XFetch`|---|Used as the [`Fetch`] type for `X`| /// |`XReadOnlyItem`|✓|The type of the query item for `XReadOnly`| /// |`XReadOnlyFetch`|✓|Used as the [`Fetch`] type for `XReadOnly`| -/// |`XReadOnly`|✓|ReadOnly variant of `X`| +/// |`XReadOnly`|✓|[`ReadOnly`] variant of `X`| /// /// ## Adding mutable references /// @@ -295,6 +295,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// [`matches_component_set`]: Self::matches_component_set /// [`Or`]: crate::query::Or /// [`Query`]: crate::system::Query +/// [`ReadOnly`]: Self::ReadOnly /// [`State`]: Self::State /// [`table_fetch`]: Self::table_fetch /// [`update_archetype_component_access`]: Self::update_archetype_component_access From d18ea9bffa511bc15165d485a885bb1876f680b7 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 19 Aug 2022 12:56:02 +0200 Subject: [PATCH 24/26] Checkout other files from `main` --- crates/bevy_ecs/src/query/fetch.rs | 397 +++++++++++++++-------------- crates/bevy_ecs/src/query/iter.rs | 59 +---- 2 files changed, 213 insertions(+), 243 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index b4f2d95b087ab..21fab0db52367 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -12,139 +12,94 @@ pub use bevy_ecs_macros::WorldQuery; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use std::{cell::UnsafeCell, marker::PhantomData}; -/// Types that can be fetched from a [`World`] using a [`Query`]. -/// -/// There are many types that natively implement this trait: -/// -/// - **Component references.** -/// Fetches a component by reference (immutably or mutably). -/// - **`WorldQuery` tuples.** -/// If every element of a tuple implements `WorldQuery`, then the tuple itself also implements the same trait. -/// This enables a single `Query` to access multiple components and filter over multiple conditions. -/// Due to the current lack of variadic generics in Rust, the trait has been implemented for tuples from 0 to 15 elements, -/// but nesting of tuples allows infinite `WorldQuery`s. -/// - **Component filters.** -/// [`With`] and [`Without`] filters can be applied to check if the queried entity contains or not a particular component. -/// - **Change detection filters.** -/// [`Added`] and [`Changed`] filters can be applied to detect component changes to an entity. -/// - **Filter disjunction operator.** -/// By default, tuples compose query filters in such a way that all conditions must be satisfied to generate a query item for a given entity. -/// Wrapping a tuple inside an [`Or`] operator will relax the requirement to just one condition. -/// - **[`Entity`].** -/// Gets the identifier of the queried entity. -/// - **[`Option`].** -/// By default, a world query only tests entities that are compatible with its type. -/// Wrapping it into an `Option` will increase the query search space, and it will return `None` if an entity doesn't satisfy the `WorldQuery`. -/// - **[`AnyOf`].** -/// Equivalent to wrapping each world query inside it into an `Option`. -/// - **[`ChangeTrackers`].** -/// Similar to change detection filters but it is used as a query fetch parameter. -/// It exposes methods to check for changes to the wrapped component. +/// Types that can be queried from a [`World`]. /// -/// Implementing the trait manually can allow for a fundamentally new type of behaviour. +/// 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 [`WorldQuery`]'s /// -/// # Trait derivation +/// 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`: 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`: 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`]. /// -/// Query design can be easily structured by deriving `WorldQuery` for custom types. -/// Despite the added complexity, this approach has several advantages over using `WorldQuery` tuples. -/// The most relevant improvements are: +/// 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 /// -/// - Reusability across multiple systems. -/// - There is no need to destructure a tuple since all fields are named. -/// - Subqueries can be composed together to create a more complex query. -/// - Methods can be implemented for the query items. -/// - There is no hardcoded limit on the number of elements. +/// # Derive +/// +/// This trait can be derived with the [`derive@super::WorldQuery`] macro. +/// +/// You may want to implement a custom query with the derive macro for the following reasons: +/// - Named structs can be clearer and easier to use than complex query tuples. Access via struct +/// fields is more convenient than destructuring tuples or accessing them via `q.0, q.1, ...` +/// pattern and saves a lot of maintenance burden when adding or removing components. +/// - Nested queries enable the composition pattern and makes query types easier to re-use. +/// - You can bypass the limit of 15 components that exists for query tuples. +/// +/// Implementing the trait manually can allow for a fundamentally new type of behaviour. /// -/// This trait can only be derived if each field of the struct also implements `WorldQuery`. -/// The derive macro only supports regular structs (structs with named fields). +/// The derive macro implements [`WorldQuery`] for your type and declares an additional struct +/// which will be used as an item for query iterators. The implementation also generates two other +/// structs that are used as [`WorldQuery::Fetch`](WorldQueryGats::Fetch) and +/// [`WorldQuery::State`] associated types. +/// +/// The derive macro requires every struct field to implement the `WorldQuery` trait. +/// +/// **Note:** currently, the macro only supports named structs. /// /// ``` /// # use bevy_ecs::prelude::*; /// use bevy_ecs::query::WorldQuery; -/// # -/// # #[derive(Component)] -/// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; +/// +/// #[derive(Component)] +/// struct Foo; +/// #[derive(Component)] +/// struct Bar; /// /// #[derive(WorldQuery)] /// struct MyQuery { /// entity: Entity, -/// // It is required that all reference lifetimes are explicitly annotated, just like in any -/// // struct. Each lifetime should be 'static. -/// component_a: &'static ComponentA, -/// component_b: &'static ComponentB, +/// // We must explicitly list out all lifetimes, as we are defining a struct +/// foo: &'static Foo, +/// bar: Option<&'static Bar>, /// } /// /// fn my_system(query: Query) { -/// for q in query.iter() { -/// q.component_a; +/// for q in &query { +/// // Note the type of the returned item. +/// let q: MyQueryItem<'_> = q; +/// q.foo; /// } /// } +/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// -/// ## Macro expansion -/// -/// Expanding the macro will declare three or six additional structs, depending on whether or not the struct is marked as mutable. -/// For a struct named `X`, the additional structs will be: -/// -/// |Struct name|`mutable` only|Description| -/// |:---:|:---:|---| -/// |`XState`|---|Used as the [`State`] type for `X` and `XReadOnly`| -/// |`XItem`|---|The type of the query item for `X`| -/// |`XFetch`|---|Used as the [`Fetch`] type for `X`| -/// |`XReadOnlyItem`|✓|The type of the query item for `XReadOnly`| -/// |`XReadOnlyFetch`|✓|Used as the [`Fetch`] type for `XReadOnly`| -/// |`XReadOnly`|✓|[`ReadOnly`] variant of `X`| +/// ## Mutable queries /// -/// ## Adding mutable references -/// -/// Simply adding mutable references to a derived `WorldQuery` will result in a compilation error: -/// -/// ```compile_fail -/// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::query::WorldQuery; -/// # -/// # #[derive(Component)] -/// # struct ComponentA; -/// # -/// #[derive(WorldQuery)] -/// struct CustomQuery { -/// component_a: &'static mut ComponentA, -/// } -/// ``` -/// -/// To grant mutable access to components, the struct must be marked with the `#[world_query(mutable)]` attribute. -/// This will also create three more structs that will be used for accessing the query immutably (see table above). +/// All queries that are derived with the `WorldQuery` macro provide only an immutable access by default. +/// If you need a mutable access to components, you can mark a struct with the `mutable` attribute. /// /// ``` /// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::query::WorldQuery; -/// # -/// # #[derive(Component)] -/// # struct ComponentA; -/// # -/// #[derive(WorldQuery)] -/// #[world_query(mutable)] -/// struct CustomQuery { -/// component_a: &'static mut ComponentA, -/// } -/// ``` -/// -/// ## Adding methods to query items -/// -/// It is possible to add methods to query items in order to write reusable logic about related components. -/// This will often make systems more readable because low level logic is moved out from them. -/// It is done by adding `impl` blocks with methods for the `-Item` or `-ReadOnlyItem` generated structs. +/// use bevy_ecs::query::WorldQuery; /// -/// ``` -/// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::query::WorldQuery; -/// # /// #[derive(Component)] /// struct Health(f32); -/// /// #[derive(Component)] /// struct Buff(f32); /// @@ -155,7 +110,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// buff: Option<&'static mut Buff>, /// } /// -/// // `HealthQueryItem` is only available when accessing the query with mutable methods. +/// // This implementation is only available when iterating with `iter_mut`. /// impl<'w> HealthQueryItem<'w> { /// fn damage(&mut self, value: f32) { /// self.health.0 -= value; @@ -166,7 +121,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// } /// -/// // `HealthQueryReadOnlyItem` is only available when accessing the query with immutable methods. +/// // If you want to use it with `iter`, you'll need to write an additional implementation. /// impl<'w> HealthQueryReadOnlyItem<'w> { /// fn total(&self) -> f32 { /// self.health.0 + self.buff.map_or(0.0, |Buff(buff)| *buff) @@ -174,134 +129,202 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// /// fn my_system(mut health_query: Query) { -/// // The item returned by the iterator is of type `HealthQueryReadOnlyItem`. -/// for health in health_query.iter() { +/// // Iterator's item is `HealthQueryReadOnlyItem`. +/// for health in &health_query { /// println!("Total: {}", health.total()); /// } -/// // The item returned by the iterator is of type `HealthQueryItem`. -/// for mut health in health_query.iter_mut() { +/// // Iterator's item is `HealthQueryItem`. +/// for mut health in &mut health_query { /// health.damage(1.0); /// println!("Total (mut): {}", health.total()); /// } /// } +/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// -/// ## Deriving traits for query items +/// Mutable queries will also have a read only version derived: +/// ```rust +/// # use bevy_ecs::prelude::*; +/// use bevy_ecs::query::WorldQuery; /// -/// The `WorldQuery` derive macro does not automatically implement the traits of the struct to the query item types. -/// Something similar can be done by using the `#[world_query(derive(...))]` attribute. -/// This will apply the listed derivable traits to the query item structs. +/// #[derive(Component)] +/// pub struct MyComponent; /// +/// #[derive(WorldQuery)] +/// #[world_query(mutable)] +/// pub struct Foo { +/// my_component_yay: &'static mut MyComponent, +/// } +/// +/// fn my_system(mut my_query: Query<(FooReadOnly, FooReadOnly)>) { +/// for (i1, i2) in &mut my_query { +/// let _: FooReadOnlyItem<'_> = i1; +/// let _: FooReadOnlyItem<'_> = i2; +/// } +/// } +/// +/// # bevy_ecs::system::assert_is_system(my_system); /// ``` +/// +/// **Note:** if you omit the `mutable` attribute for a query that doesn't implement +/// [`ReadOnlyWorldQuery`], compilation will fail. We insert static checks as in the example above for +/// every query component and a nested query. +/// (The checks neither affect the runtime, nor pollute your local namespace.) +/// +/// ```compile_fail /// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::query::WorldQuery; -/// # -/// # #[derive(Component, Debug)] -/// # struct ComponentA; -/// # +/// use bevy_ecs::query::WorldQuery; +/// +/// #[derive(Component)] +/// struct Foo; +/// #[derive(Component)] +/// struct Bar; +/// +/// #[derive(WorldQuery)] +/// struct FooQuery { +/// foo: &'static Foo, +/// bar_query: BarQuery, +/// } +/// +/// #[derive(WorldQuery)] +/// #[world_query(mutable)] +/// struct BarQuery { +/// bar: &'static mut Bar, +/// } +/// ``` +/// +/// ## Derives for items +/// +/// If you want query items to have derivable traits, you can pass them with using +/// the `world_query(derive)` attribute. When the `WorldQuery` macro generates the structs +/// for query items, it doesn't automatically inherit derives of a query itself. Since derive macros +/// can't access information about other derives, they need to be passed manually with the +/// `world_query(derive)` attribute. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// use bevy_ecs::query::WorldQuery; +/// +/// #[derive(Component, Debug)] +/// struct Foo; +/// /// #[derive(WorldQuery)] /// #[world_query(mutable, derive(Debug))] -/// struct CustomQuery { -/// component_a: &'static ComponentA, +/// struct FooQuery { +/// foo: &'static Foo, /// } /// -/// // This function statically checks that `T` implements `Debug`. /// fn assert_debug() {} /// -/// assert_debug::(); -/// assert_debug::(); +/// assert_debug::(); +/// assert_debug::(); /// ``` /// -/// ## Query composition +/// ## Nested queries /// -/// It is possible to use any `WorldQuery` as a field of another one. -/// This means that a `WorldQuery` can also be used as a subquery, potentially in multiple places. +/// Using nested queries enable the composition pattern, which makes it possible to re-use other +/// query types. All types that implement [`WorldQuery`] (including the ones that use this derive +/// macro) are supported. /// /// ``` /// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::query::WorldQuery; -/// # -/// # #[derive(Component)] -/// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; -/// # #[derive(Component)] -/// # struct ComponentC; -/// # +/// use bevy_ecs::query::WorldQuery; +/// +/// #[derive(Component)] +/// struct Foo; +/// #[derive(Component)] +/// struct Bar; +/// #[derive(Component)] +/// struct OptionalFoo; +/// #[derive(Component)] +/// struct OptionalBar; +/// /// #[derive(WorldQuery)] -/// struct SubQuery { -/// component_a: &'static ComponentA, -/// component_b: &'static ComponentB, +/// struct MyQuery { +/// foo: FooQuery, +/// bar: (&'static Bar, Option<&'static OptionalBar>) /// } /// /// #[derive(WorldQuery)] -/// struct MyQuery { -/// subquery: SubQuery, -/// component_c: &'static ComponentC, +/// struct FooQuery { +/// foo: &'static Foo, +/// optional_foo: Option<&'static OptionalFoo>, /// } +/// +/// // You can also compose derived queries with regular ones in tuples. +/// fn my_system(query: Query<(&Foo, MyQuery, FooQuery)>) { +/// for (foo, my_query, foo_query) in &query { +/// foo; my_query; foo_query; +/// } +/// } +/// +/// # bevy_ecs::system::assert_is_system(my_system); +/// ``` +/// +/// ## Ignored fields +/// +/// The macro also supports `ignore` attribute for struct members. Fields marked with this attribute +/// must implement the `Default` trait. +/// +/// This example demonstrates a query that would iterate over every entity. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// use bevy_ecs::query::WorldQuery; +/// +/// #[derive(WorldQuery, Debug)] +/// struct EmptyQuery { +/// empty: (), +/// } +/// +/// fn my_system(query: Query) { +/// for _ in &query {} +/// } +/// +/// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// /// ## Filters /// -/// Since the query filter type parameter is `WorldQuery`, it is also possible to use this macro to create filters. +/// Using [`derive@super::WorldQuery`] macro we can create our own query filters. /// /// ``` /// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::{query::WorldQuery, component::Component}; -/// # -/// # #[derive(Component)] -/// # struct ComponentA; -/// # #[derive(Component)] -/// # struct ComponentB; -/// # #[derive(Component)] -/// # struct ComponentC; -/// # #[derive(Component)] -/// # struct ComponentD; -/// # #[derive(Component)] -/// # struct ComponentE; -/// # +/// use bevy_ecs::{query::WorldQuery, component::Component}; +/// +/// #[derive(Component)] +/// struct Foo; +/// #[derive(Component)] +/// struct Bar; +/// #[derive(Component)] +/// struct Baz; +/// #[derive(Component)] +/// struct Qux; +/// /// #[derive(WorldQuery)] /// struct MyFilter { -/// // Field names are not relevant, since they are never manually accessed. -/// with_a: With, -/// or_filter: Or<(With, Added)>, -/// generic_tuple: (With, Without

), +/// _foo: With, +/// _bar: With, +/// _or: Or<(With, Changed, Added)>, +/// _generic_tuple: (With, Without

), /// } /// -/// fn my_system(query: Query>) { -/// // ... +/// fn my_system(query: Query>) { +/// for _ in &query {} /// } +/// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` -/// /// # Safety /// -/// Component access of `ROQueryFetch` must be a subset of `QueryFetch` +/// component access of `ROQueryFetch` must be a subset of `QueryFetch` /// and `ROQueryFetch` must match exactly the same archetypes/tables as `QueryFetch` /// -/// Implementor must ensure that -/// [`update_component_access`] and [`update_archetype_component_access`] -/// exactly reflects the results of the following methods: -/// -/// - [`matches_component_set`] -/// - [`archetype_fetch`] -/// - [`table_fetch`] -/// -/// [`Added`]: crate::query::Added -/// [`archetype_fetch`]: Self::archetype_fetch -/// [`Changed`]: crate::query::Changed -/// [`Fetch`]: crate::query::WorldQueryGats::Fetch -/// [`matches_component_set`]: Self::matches_component_set -/// [`Or`]: crate::query::Or -/// [`Query`]: crate::system::Query -/// [`ReadOnly`]: Self::ReadOnly -/// [`State`]: Self::State -/// [`table_fetch`]: Self::table_fetch -/// [`update_archetype_component_access`]: Self::update_archetype_component_access -/// [`update_component_access`]: Self::update_component_access -/// [`With`]: crate::query::With -/// [`Without`]: crate::query::Without +/// Implementor must ensure that [`WorldQuery::update_component_access`] and +/// [`WorldQuery::update_archetype_component_access`] exactly reflects the results of +/// [`WorldQuery::matches_component_set`], [`WorldQuery::archetype_fetch`], and +/// [`WorldQuery::table_fetch`]. pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> { /// The read-only variant of this [`WorldQuery`], which satisfies the [`ReadOnlyWorldQuery`] trait. type ReadOnly: ReadOnlyWorldQuery; diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index fd4ac9b7e7baf..1c8f7e92562d0 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -214,59 +214,6 @@ where { } -/// An iterator over `K`-sized combinations of query items without repetition. -/// -/// In this context, a combination is an unordered subset of `K` elements. -/// The number of combinations depend on how `K` relates to the number of entities matching the [`Query`] (called `N`): -/// - if `K = N`, only one combination exists, -/// - if `K < N`, there are NCK combinations (see the [performance section] of `Query`), -/// - if `K > N`, there are no combinations. -/// -/// # Usage -/// -/// This type is returned by calling [`Query::iter_combinations`] or [`Query::iter_combinations_mut`]. -/// -/// It implements [`Iterator`] only if it iterates over read-only query items ([learn more]). -/// -/// In the case of mutable query items, it can be iterated by calling [`fetch_next`] in a `while let` loop. -/// -/// # Examples -/// -/// The following example shows how to traverse the iterator when the query items are read-only. -/// -/// ``` -/// # use bevy_ecs::prelude::*; -/// # #[derive(Component)] -/// # struct ComponentA; -/// # -/// fn some_system(query: Query<&ComponentA>) { -/// for [a1, a2] in query.iter_combinations() { -/// // ... -/// } -/// } -/// ``` -/// -/// The following example shows how `fetch_next` should be called with a `while let` loop to traverse the iterator when the query items are mutable. -/// -/// ``` -/// # use bevy_ecs::prelude::*; -/// # #[derive(Component)] -/// # struct ComponentA; -/// # -/// fn some_system(mut query: Query<&mut ComponentA>) { -/// let mut combinations = query.iter_combinations_mut(); -/// while let Some([a1, a2]) = combinations.fetch_next() { -/// // ... -/// } -/// } -/// ``` -/// -/// [`fetch_next`]: Self::fetch_next -/// [learn more]: Self#impl-Iterator -/// [performance section]: crate::system::Query#performance -/// [`Query`]: crate::system::Query -/// [`Query::iter_combinations`]: crate::system::Query::iter_combinations -/// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut pub struct QueryCombinationIter<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, @@ -380,9 +327,9 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> QueryCombinationIter< } } -/// Iterator type is intentionally implemented only for read-only access. -/// Doing so for mutable references would be unsound, -/// because calling `next` multiple times would allow multiple owned references to the same data to exist. +// Iterator type is intentionally implemented only for read-only access. +// Doing so for mutable references would be unsound, because calling `next` +// multiple times would allow multiple owned references to the same data to exist. impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> Iterator for QueryCombinationIter<'w, 's, Q, F, K> where From f0874e47e30750cac4586caeb57aef94cdde2d68 Mon Sep 17 00:00:00 2001 From: Nilirad Date: Fri, 19 Aug 2022 13:10:31 +0200 Subject: [PATCH 25/26] Remove changes to methods --- crates/bevy_ecs/src/system/query.rs | 370 +++++++++++----------------- 1 file changed, 150 insertions(+), 220 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 130fbda045e1d..8375ef5109e77 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -302,7 +302,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns another `Query` from this that fetches the read-only version of the query items. + /// Downgrades all data accessed in this query to a read-only form. /// /// For example, `Query<(&mut A, &B, &mut C), With>` will become `Query<(&A, &B, &C), With>`. /// This can be useful when working around the borrow checker, @@ -320,11 +320,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the read-only query items. + /// Returns an [`Iterator`] over the query results. + /// + /// This can only return immutable data (mutable data will be cast to an immutable form). + /// See [`Self::iter_mut`] for queries that contain at least one mutable component. /// /// # Example /// - /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: + /// Here, the `report_names_system` iterates over the `Player` component of every entity + /// that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -339,11 +343,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` - /// - /// # See also - /// - /// - [`iter_mut`](Self::iter_mut) for mutable query items. - /// - [`for_each`](Self::for_each) for the closure based alternative. #[inline] pub fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly> { // SAFETY: system runs without conflicts with other systems. @@ -357,11 +356,12 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query items. + /// Returns an [`Iterator`] over the query results. /// /// # Example /// - /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: + /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in + /// the world that contains it in order to update it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -376,11 +376,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` - /// - /// # See also - /// - /// - [`iter`](Self::iter) for read-only query items. - /// - [`for_each_mut`](Self::for_each_mut) for the closure based alternative. #[inline] pub fn iter_mut(&mut self) -> QueryIter<'_, 's, Q, F> { // SAFETY: system runs without conflicts with other systems. @@ -391,25 +386,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a [`QueryCombinationIter`] over all combinations of `K` read-only query items without repetition. - /// - /// # Example - /// - /// ``` - /// # use bevy_ecs::prelude::*; - /// # #[derive(Component)] - /// # struct ComponentA; - /// # - /// fn some_system(query: Query<&ComponentA>) { - /// for [a1, a2] in query.iter_combinations() { - /// // ... - /// } - /// } - /// ``` + /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition. + /// This can only return immutable data /// - /// # See also - /// - /// - [`iter_combinations_mut`](Self::iter_combinations_mut) for mutable query item combinations. + /// For permutations of size `K` of query returning `N` results, you will get: + /// - if `K == N`: one permutation of all query results + /// - if `K < N`: all possible `K`-sized combinations of query results, without repetition + /// - if `K > N`: empty set (no `K`-sized combinations exist) #[inline] pub fn iter_combinations( &self, @@ -425,25 +408,28 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a [`QueryCombinationIter`] over all combinations of `K` query items without repetition. + /// Iterates over all possible combinations of `K` query results without repetition. /// - /// # Example + /// The returned value is not an `Iterator`, because that would lead to aliasing of mutable references. + /// In order to iterate it, use `fetch_next` method with `while let Some(..)` loop pattern. /// /// ``` /// # use bevy_ecs::prelude::*; - /// # #[derive(Component)] - /// # struct ComponentA; - /// fn some_system(mut query: Query<&mut ComponentA>) { - /// let mut combinations = query.iter_combinations_mut(); - /// while let Some([mut a1, mut a2]) = combinations.fetch_next() { - /// // mutably access components data - /// } + /// #[derive(Component)] + /// # struct A; + /// # fn some_system(mut query: Query<&mut A>) { + /// // iterate using `fetch_next` in while loop + /// let mut combinations = query.iter_combinations_mut(); + /// while let Some([mut a, mut b]) = combinations.fetch_next() { + /// // mutably access components data /// } + /// # } /// ``` /// - /// # See also + /// There is no `for_each` method, because it cannot be safely implemented + /// due to a [compiler bug](https://github.com/rust-lang/rust/issues/62529). /// - /// - [`iter_combinations`](Self::iter_combinations) for read-only query item combinations. + /// For immutable access see [`Query::iter_combinations`]. #[inline] pub fn iter_combinations_mut( &mut self, @@ -459,18 +445,19 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list. + /// Returns an [`Iterator`] over the query results of a list of [`Entity`]'s. /// - /// # Example + /// This can only return immutable data (mutable data will be cast to an immutable form). + /// See [`Self::iter_many_mut`] for queries that contain at least one mutable component. /// + /// # Examples /// ``` /// # use bevy_ecs::prelude::*; - /// # #[derive(Component)] - /// # struct Counter { - /// # value: i32 - /// # } - /// # - /// // A component containing an entity list. + /// #[derive(Component)] + /// struct Counter { + /// value: i32 + /// } + /// /// #[derive(Component)] /// struct Friends { /// list: Vec, @@ -488,10 +475,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(system); /// ``` - /// - /// # See also - /// - /// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items. #[inline] pub fn iter_many( &self, @@ -512,8 +495,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query items generated from an [`Entity`] list. - /// + /// Calls a closure on each result of [`Query`] where the entities match. /// # Examples /// /// ``` @@ -562,16 +544,12 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query items. + /// Returns an [`Iterator`] over the query results. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. - /// You must make sure this call does not result in multiple mutable references to the same component. - /// - /// # See also - /// - /// - [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) for the safe versions. + /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure + /// this call does not result in multiple mutable references to the same component #[inline] pub unsafe fn iter_unsafe(&'s self) -> QueryIter<'w, 's, Q, F> { // SEMI-SAFETY: system runs without conflicts with other systems. @@ -580,16 +558,12 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { .iter_unchecked_manual(self.world, self.last_change_tick, self.change_tick) } - /// Iterates over all possible combinations of `K` query items without repetition. + /// Iterates over all possible combinations of `K` query results without repetition. + /// See [`Query::iter_combinations`]. /// /// # Safety - /// - /// This allows aliased mutability. - /// You must make sure this call does not result in multiple mutable references to the same component. - /// - /// # See also - /// - /// - [`iter_combinations`](Self::iter_combinations) and [`iter_combinations_mut`](Self::iter_combinations_mut) for the safe versions. + /// This allows aliased mutability. You must make sure this call does not result in multiple + /// mutable references to the same component #[inline] pub unsafe fn iter_combinations_unsafe( &self, @@ -603,17 +577,14 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ) } - /// Returns an [`Iterator`] over the query items generated from an [`Entity`] list. + /// Returns an [`Iterator`] over the query results of a list of [`Entity`]'s. /// - /// # Safety + /// If you want safe mutable access to query results of a list of [`Entity`]'s. See [`Self::iter_many_mut`]. /// + /// # Safety /// This allows aliased mutability and does not check for entity uniqueness. /// You must make sure this call does not result in multiple mutable references to the same component. - /// Particular care must be taken when collecting the data (rather than iterating over it one item at a time) such as via [`Iterator::collect`]. - /// - /// # See also - /// - /// - [`iter_many_mut`](Self::iter_many_mut) to safely access the query items. + /// Particular care must be taken when collecting the data (rather than iterating over it one item at a time) such as via `[Iterator::collect()]`. pub unsafe fn iter_many_unsafe( &self, entities: EntityList, @@ -629,11 +600,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ) } - /// Runs `f` on each read-only query item. + /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot + /// be chained like a normal [`Iterator`]. + /// + /// This can only pass in immutable data, see [`Self::for_each_mut`] for mutable access. /// /// # Example /// - /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: + /// Here, the `report_names_system` iterates over the `Player` component of every entity + /// that contains it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -648,11 +623,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` - /// - /// # See also - /// - /// - [`for_each_mut`](Self::for_each_mut) to operate on mutable query items. - /// - [`iter`](Self::iter) for the iterator based alternative. #[inline] pub fn for_each<'this>(&'this self, f: impl FnMut(ROQueryItem<'this, Q>)) { // SAFETY: system runs without conflicts with other systems. @@ -667,11 +637,13 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query item. + /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot + /// be chained like a normal [`Iterator`]. /// /// # Example /// - /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: + /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in + /// the world that contains it in order to update it: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -686,11 +658,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` - /// - /// # See also - /// - /// - [`for_each`](Self::for_each) to operate on read-only query items. - /// - [`iter_mut`](Self::iter_mut) for the iterator based alternative. #[inline] pub fn for_each_mut<'a, FN: FnMut(QueryItem<'a, Q>)>(&'a mut self, f: FN) { // SAFETY: system runs without conflicts with other systems. same-system queries have runtime @@ -705,9 +672,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each read-only query item in parallel. + /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. /// - /// Parallelization is achieved by using the [`World`]'s [`ComputeTaskPool`]. + /// This can only be called for immutable data, see [`Self::par_for_each_mut`] for + /// mutable access. /// /// # Tasks and batch size /// @@ -719,16 +687,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// Rule of thumb: If the function body is (mostly) computationally expensive but there are not many items, a small batch size (=more batches) may help to even out the load. /// If the body is computationally cheap and you have many items, a large batch size (=fewer batches) avoids spawning additional futures that don't help to even out the load. /// - /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool - /// - /// # Panics + /// # Arguments /// - /// This method panics if the [`ComputeTaskPool`] resource is added to the `World` before using this method. - /// If using this from a query that is being initialized and run from the [`Schedule`](crate::schedule::Schedule), this should never panic. + ///* `batch_size` - The number of batches to spawn + ///* `f` - The function to run on each item in the query /// - /// # See also + /// # Panics + /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being + /// initialized and run from the ECS scheduler, this should never panic. /// - /// - [`par_for_each_mut`](Self::par_for_each_mut) for operating on mutable query items. + /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool #[inline] pub fn par_for_each<'this>( &'this self, @@ -748,20 +716,14 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each read-only query item in parallel. - /// - /// Parallelization is achieved by using the [`World`]'s [`ComputeTaskPool`]. + /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. + /// See [`Self::par_for_each`] for more details. /// /// # Panics - /// - /// This method panics if the [`ComputeTaskPool`] resource is added to the `World` before using this method. - /// If using this from a query that is being initialized and run from the [`Schedule`](crate::schedule::Schedule), this should never panic. + /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being + /// initialized and run from the ECS scheduler, this should never panic. /// /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool - /// - /// # See also - /// - /// - [`par_for_each`](Self::par_for_each) for more usage details. #[inline] pub fn par_for_each_mut<'a, FN: Fn(QueryItem<'a, Q>) + Send + Sync + Clone>( &'a mut self, @@ -781,13 +743,18 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Returns the read-only query item for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. + /// + /// This can only return immutable data (mutable data will be cast to an immutable form). + /// See [`get_mut`](Self::get_mut) for queries that contain at least one mutable component. /// /// # Example /// - /// Here, `get` is used to retrieve the exact query item of the entity specified by the `SelectedCharacter` resource. + /// Here, `get` is used to retrieve the exact query result of the entity specified by the + /// `SelectedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -808,10 +775,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` - /// - /// # See also - /// - /// - [`get_mut`](Self::get_mut) to get a mutable query item. #[inline] pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. @@ -826,15 +789,14 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the read-only query items for the given array of [`Entity`]. + /// Returns the read-only query results for the given array of [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. - /// The elements of the array do not need to be unique, unlike `get_many_mut`. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// - /// # See also + /// Note that the unlike [`Query::get_many_mut`], the entities passed in do not need to be unique. /// - /// - [`get_many_mut`](Self::get_many_mut) to get mutable query items. - /// - [`many`](Self::many) for the panicking version. + /// See [`Query::many`] for the infallible equivalent. #[inline] pub fn get_many( &self, @@ -851,11 +813,9 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the read-only query items for the given array of [`Entity`]. - /// - /// # Panics + /// Returns the read-only query items for the provided array of [`Entity`] /// - /// This method panics if there is a query mismatch or a non-existing entity. + /// See [`Query::get_many`] for the [`Result`]-returning equivalent. /// /// # Examples /// ```rust, no_run @@ -888,22 +848,20 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// } /// ``` - /// - /// # See also - /// - /// - [`get_many`](Self::get_many) for the non-panicking version. #[inline] pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, Q>; N] { self.get_many(entities).unwrap() } - /// Returns the query item for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Example /// - /// Here, `get_mut` is used to retrieve the exact query item of the entity specified by the `PoisonedCharacter` resource. + /// Here, `get_mut` is used to retrieve the exact query result of the entity specified by the + /// `PoisonedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -920,10 +878,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(poison_system); /// ``` - /// - /// # See also - /// - /// - [`get`](Self::get) to get a read-only query item. #[inline] pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. @@ -938,14 +892,12 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the query items for the given array of [`Entity`]. - /// - /// In case of a nonexisting entity, duplicate entities or mismatched component, a [`QueryEntityError`] is returned instead. + /// Returns the query results for the given array of [`Entity`]. /// - /// # See also + /// In case of a nonexisting entity, duplicate entities or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// - /// - [`get_many`](Self::get_many) to get read-only query items. - /// - [`many_mut`](Self::many_mut) for the panicking version. + /// See [`Query::many_mut`] for the infallible equivalent. #[inline] pub fn get_many_mut( &mut self, @@ -962,11 +914,9 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns the query items for the given array of [`Entity`]. + /// Returns the query items for the provided array of [`Entity`] /// - /// # Panics - /// - /// This method panics if there is a query mismatch, a non-existing entity, or the same `Entity` is included more than once in the array. + /// See [`Query::get_many_mut`] for the [`Result`]-returning equivalent. /// /// # Examples /// @@ -1005,28 +955,20 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// } /// ``` - /// - /// # See also - /// - /// - [`get_many_mut`](Self::get_many_mut) for the non panicking version. - /// - [`many`](Self::many) to get read-only query items. #[inline] pub fn many_mut(&mut self, entities: [Entity; N]) -> [QueryItem<'_, Q>; N] { self.get_many_mut(entities).unwrap() } - /// Returns the query item for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. - /// You must make sure this call does not result in multiple mutable references to the same component. - /// - /// # See also - /// - /// - [`get_mut`](Self::get_mut) for the safe version. + /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure + /// this call does not result in multiple mutable references to the same component #[inline] pub unsafe fn get_unchecked( &'s self, @@ -1038,13 +980,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { .get_unchecked_manual(self.world, entity, self.last_change_tick, self.change_tick) } - /// Returns a shared reference to the component `T` of the given [`Entity`]. + /// Returns a reference to the [`Entity`]'s [`Component`] of the given type. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Example /// - /// Here, `get_component` is used to retrieve the `Character` component of the entity specified by the `SelectedCharacter` resource. + /// Here, `get_component` is used to retrieve the `Character` component of the entity + /// specified by the `SelectedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -1065,10 +1009,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` - /// - /// # See also - /// - /// - [`get_component_mut`](Self::get_component_mut) to get a mutable reference of a component. #[inline] pub fn get_component(&self, entity: Entity) -> Result<&T, QueryComponentError> { let world = self.world; @@ -1096,13 +1036,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a mutable reference to the component `T` of the given entity. + /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Example /// - /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity specified by the `PoisonedCharacter` resource. + /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity + /// specified by the `PoisonedCharacter` resource. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -1119,10 +1061,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(poison_system); /// ``` - /// - /// # See also - /// - /// - [`get_component`](Self::get_component) to get a shared reference of a component. #[inline] pub fn get_component_mut( &mut self, @@ -1132,18 +1070,15 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { unsafe { self.get_component_unchecked_mut(entity) } } - /// Returns a mutable reference to the component `T` of the given entity. + /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. /// - /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Safety /// - /// This function makes it possible to violate Rust's aliasing guarantees. - /// You must make sure this call does not result in multiple mutable references to the same component. - /// - /// # See also - /// - /// - [`get_component_mut`](Self::get_component_mut) for the safe version. + /// This function makes it possible to violate Rust's aliasing guarantees. You must make sure + /// this call does not result in multiple mutable references to the same component #[inline] pub unsafe fn get_component_unchecked_mut( &self, @@ -1174,11 +1109,11 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a single read-only query item when there is exactly one entity matching the query. - /// - /// # Panics + /// Returns a single immutable query result when there is exactly one entity matching + /// the query. /// - /// This method panics if the number of query items is not exactly one. + /// This can only return immutable data. Use [`single_mut`](Self::single_mut) for + /// queries that contain at least one mutable component. /// /// # Example /// @@ -1195,18 +1130,23 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(player_system); /// ``` /// - /// # See also + /// # Panics /// - /// - [`get_single`](Self::get_single) for the non-panicking version. - /// - [`single_mut`](Self::single_mut) to get the mutable query item. + /// Panics if the number of query results is not exactly one. Use + /// [`get_single`](Self::get_single) to return a `Result` instead of panicking. #[track_caller] pub fn single(&self) -> ROQueryItem<'_, Q> { self.get_single().unwrap() } - /// Returns a single read-only query item when there is exactly one entity matching the query. + /// Returns a single immutable query result when there is exactly one entity matching + /// the query. /// - /// If the number of query items is not exactly one, a [`QuerySingleError`] is returned instead. + /// This can only return immutable data. Use [`get_single_mut`](Self::get_single_mut) + /// for queries that contain at least one mutable component. + /// + /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned + /// instead. /// /// # Example /// @@ -1230,11 +1170,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(player_scoring_system); /// ``` - /// - /// # See also - /// - /// - [`get_single_mut`](Self::get_single_mut) to get the mutable query item. - /// - [`single`](Self::single) for the panicking version. #[inline] pub fn get_single(&self) -> Result, QuerySingleError> { // SAFETY: @@ -1249,11 +1184,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns a single query item when there is exactly one entity matching the query. - /// - /// # Panics - /// - /// This method panics if the number of query item is not exactly one. + /// Returns a single mutable query result when there is exactly one entity matching + /// the query. /// /// # Example /// @@ -1272,18 +1204,20 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system); /// ``` /// - /// # See also + /// # Panics /// - /// - [`get_single_mut`](Self::get_single_mut) for the non-panicking version. - /// - [`single`](Self::single) to get the read-only query item. + /// Panics if the number of query results is not exactly one. Use + /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking. #[track_caller] pub fn single_mut(&mut self) -> QueryItem<'_, Q> { self.get_single_mut().unwrap() } - /// Returns a single query item when there is exactly one entity matching the query. + /// Returns a single mutable query result when there is exactly one entity matching + /// the query. /// - /// If the number of query items is not exactly one, a [`QuerySingleError`] is returned instead. + /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned + /// instead. /// /// # Example /// @@ -1301,11 +1235,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// } /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system); /// ``` - /// - /// # See also - /// - /// - [`get_single`](Self::get_single) to get the read-only query item. - /// - [`single_mut`](Self::single_mut) for the panicking version. #[inline] pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { // SAFETY: @@ -1320,11 +1249,12 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns `true` if there are no query items. + /// Returns `true` if there are no query results. /// /// # Example /// - /// Here, the score is increased only if an entity with a `Player` component is present in the world: + /// Here, the score is increased only if an entity with a `Player` component is present + /// in the world: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -1435,7 +1365,7 @@ impl std::fmt::Display for QueryComponentError { } impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { - /// Returns the query item for the given [`Entity`], with the actual "inner" world lifetime. + /// Returns the query result for the given [`Entity`], with the actual "inner" world lifetime. /// /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is /// returned instead. @@ -1445,7 +1375,7 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// # Example /// - /// Here, `get` is used to retrieve the exact query item of the entity specified by the + /// Here, `get` is used to retrieve the exact query result of the entity specified by the /// `SelectedCharacter` resource. /// /// ``` @@ -1481,7 +1411,7 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns an [`Iterator`] over the query items, with the actual "inner" world lifetime. + /// Returns an [`Iterator`] over the query results, with the actual "inner" world lifetime. /// /// This can only return immutable data (mutable data will be cast to an immutable form). /// See [`Self::iter_mut`] for queries that contain at least one mutable component. From 90dcf7109e6a1b4c624d5e3bb9ef065811a3ac25 Mon Sep 17 00:00:00 2001 From: Federico Rinaldi Date: Fri, 19 Aug 2022 22:47:01 +0200 Subject: [PATCH 26/26] Apply code review suggestion Co-authored-by: Afonso Lage --- crates/bevy_ecs/src/system/query.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 8375ef5109e77..30f865a511aa3 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -207,7 +207,7 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug}; /// [`Table`] component storage type is much more optimized for query iteration than [`SparseSet`]. /// /// Two systems cannot be executed in parallel if both access the same component type where at least one of the accesses is mutable. -/// This happens unless the schedule can verify that no entity could be found in both queries. +/// This happens unless the executor can verify that no entity could be found in both queries. /// /// Optional components increase the number of entities a query has to match against. /// This can hurt iteration performance, especially if the query solely consists of only optional components, since the query would iterate over each entity in the world.