pub unsafe trait QueryData: WorldQuery {
type ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>;
type Item<'a>;
const IS_READ_ONLY: bool;
// Required methods
fn shrink<'wlong: 'wshort, 'wshort>(
item: Self::Item<'wlong>,
) -> Self::Item<'wshort>;
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Self::Item<'w>;
}
Expand description
Types that can be fetched from a World
using a Query
.
There are many types that natively implement this trait:
- Component references. (&T and &mut T) Fetches a component by reference (immutably or mutably).
QueryData
tuples. If every element of a tuple implementsQueryData
, then the tuple itself also implements the same trait. This enables a singleQuery
to access multiple components. 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 infiniteWorldQuery
s.Entity
. Gets the identifier of the queried entity.EntityLocation
. Gets the location metadata of the queried entity.EntityRef
. Read-only access to arbitrary components on the queried entity.EntityMut
. Mutable access to arbitrary components on the queried entity.&Archetype
. Read-only access to the archetype-level metadata of the queried entity.Option
. By default, a world query only tests entities that have the matching component types. Wrapping it into anOption
will increase the query search space, and it will returnNone
if an entity doesn’t satisfy theWorldQuery
.AnyOf
. Equivalent to wrapping each world query inside it into anOption
.Ref
. 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.Has
. Returns a bool indicating whether the entity has the specified component.
Implementing the trait manually can allow for a fundamentally new type of behavior.
§Trait derivation
Query design can be easily structured by deriving QueryData
for custom types.
Despite the added complexity, this approach has several advantages over using QueryData
tuples.
The most relevant improvements are:
- 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.
This trait can only be derived for structs, if each field also implements QueryData
.
use bevy_ecs::query::QueryData;
#[derive(QueryData)]
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,
}
fn my_system(query: Query<MyQuery>) {
for q in &query {
q.component_a;
}
}
§Macro expansion
Expanding the macro will declare one or three 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 for X |
XReadOnlyItem | ✓ | The type of the query item for XReadOnly |
XReadOnly | ✓ | ReadOnly variant of X |
§Adding mutable references
Simply adding mutable references to a derived QueryData
will result in a compilation error:
#[derive(QueryData)]
struct CustomQuery {
component_a: &'static mut ComponentA,
}
To grant mutable access to components, the struct must be marked with the #[query_data(mutable)]
attribute.
This will also create three more structs that will be used for accessing the query immutably (see table above).
#[derive(QueryData)]
#[query_data(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.
#[derive(Component)]
struct Health(f32);
#[derive(Component)]
struct Buff(f32);
#[derive(QueryData)]
#[query_data(mutable)]
struct HealthQuery {
health: &'static mut Health,
buff: Option<&'static mut Buff>,
}
// `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;
}
fn total(&self) -> f32 {
self.health.0 + self.buff.as_deref().map_or(0.0, |Buff(buff)| *buff)
}
}
// `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)
}
}
fn my_system(mut health_query: Query<HealthQuery>) {
// The item returned by the iterator is of type `HealthQueryReadOnlyItem`.
for health in health_query.iter() {
println!("Total: {}", health.total());
}
// The item returned by the iterator is of type `HealthQueryItem`.
for mut health in &mut health_query {
health.damage(1.0);
println!("Total (mut): {}", health.total());
}
}
§Deriving traits for query items
The QueryData
derive macro does not automatically implement the traits of the struct to the query item types.
Something similar can be done by using the #[query_data(derive(...))]
attribute.
This will apply the listed derivable traits to the query item structs.
#[derive(QueryData)]
#[query_data(mutable, derive(Debug))]
struct CustomQuery {
component_a: &'static ComponentA,
}
// This function statically checks that `T` implements `Debug`.
fn assert_debug<T: std::fmt::Debug>() {}
assert_debug::<CustomQueryItem>();
assert_debug::<CustomQueryReadOnlyItem>();
§Query composition
It is possible to use any QueryData
as a field of another one.
This means that a QueryData
can also be used as a subquery, potentially in multiple places.
#[derive(QueryData)]
struct SubQuery {
component_a: &'static ComponentA,
component_b: &'static ComponentB,
}
#[derive(QueryData)]
struct MyQuery {
subquery: SubQuery,
component_c: &'static ComponentC,
}
§Generic Queries
When writing generic code, it is often necessary to use PhantomData
to constrain type parameters. Since QueryData
is implemented for all
PhantomData<T>
types, this pattern can be used with this macro.
#[derive(QueryData)]
pub struct GenericQuery<T> {
id: Entity,
marker: PhantomData<T>,
}
§Safety
- Component access of
Self::ReadOnly
must be a subset ofSelf
andSelf::ReadOnly
must match exactly the same archetypes/tables asSelf
IS_READ_ONLY
must betrue
if and only ifSelf: ReadOnlyQueryData
Required Associated Constants§
Sourceconst IS_READ_ONLY: bool
const IS_READ_ONLY: bool
True if this query is read-only and may not perform mutable access.
Required Associated Types§
Sourcetype ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>
type ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>
The read-only variant of this QueryData
, which satisfies the ReadOnlyQueryData
trait.
Sourcetype Item<'a>
type Item<'a>
The item returned by this WorldQuery
This will be the data retrieved by the query,
and is visible to the end user when calling e.g. Query<Self>::get
.
Required Methods§
Sourcefn shrink<'wlong: 'wshort, 'wshort>(
item: Self::Item<'wlong>,
) -> Self::Item<'wshort>
fn shrink<'wlong: 'wshort, 'wshort>( item: Self::Item<'wlong>, ) -> Self::Item<'wshort>
This function manually implements subtyping for the query items.
Sourceunsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Self::Item<'w>
unsafe fn fetch<'w>( fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w>
Fetch Self::Item
for either the given entity
in the current Table
,
or for the given entity
in the current Archetype
. This must always be called after
WorldQuery::set_table
with a table_row
in the range of the current Table
or after
WorldQuery::set_archetype
with an entity
in the current archetype.
Accesses components registered in WorldQuery::update_component_access
.
§Safety
- Must always be called after
WorldQuery::set_table
orWorldQuery::set_archetype
.entity
andtable_row
must be in the range of the current table and archetype. - There must not be simultaneous conflicting component access registered in
update_component_access
.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl<'__w, T: Component<Mutability = Mutable>> QueryData for &'__w mut T
SAFETY: access of &T
is a subset of &mut T
impl<'__w, T: Component<Mutability = Mutable>> QueryData for &'__w mut T
SAFETY: access of &T
is a subset of &mut T
Source§impl<F: QueryData> QueryData for (F₁, F₂, …, Fₙ)
This trait is implemented for tuples up to 16 items long.
impl<F: QueryData> QueryData for (F₁, F₂, …, Fₙ)
This trait is implemented for tuples up to 16 items long.
const IS_READ_ONLY: bool
type ReadOnly = (<F as QueryData>::ReadOnly,)
type Item<'w> = (<F as QueryData>::Item<'w>,)
fn shrink<'wlong: 'wshort, 'wshort>( item: Self::Item<'wlong>, ) -> Self::Item<'wshort>
unsafe fn fetch<'w>( fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w>
Source§impl<T: QueryData> QueryData for Option<T>
impl<T: QueryData> QueryData for Option<T>
const IS_READ_ONLY: bool = T::IS_READ_ONLY
type ReadOnly = Option<<T as QueryData>::ReadOnly>
type Item<'w> = Option<<T as QueryData>::Item<'w>>
fn shrink<'wlong: 'wshort, 'wshort>( item: Self::Item<'wlong>, ) -> Self::Item<'wshort>
unsafe fn fetch<'w>( fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w>
Source§impl<T: ?Sized> QueryData for PhantomData<T>
SAFETY: Self::ReadOnly
is Self
impl<T: ?Sized> QueryData for PhantomData<T>
SAFETY: Self::ReadOnly
is Self
const IS_READ_ONLY: bool = true
type ReadOnly = PhantomData<T>
type Item<'a> = ()
fn shrink<'wlong: 'wshort, 'wshort>( _item: Self::Item<'wlong>, ) -> Self::Item<'wshort>
unsafe fn fetch<'w>( _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w>
Implementors§
Source§impl QueryData for EntityLocation
SAFETY: Self
is the same as Self::ReadOnly
impl QueryData for EntityLocation
SAFETY: Self
is the same as Self::ReadOnly
const IS_READ_ONLY: bool = true
type ReadOnly = EntityLocation
type Item<'w> = EntityLocation
Source§impl QueryData for NameOrEntity
SAFETY: we assert fields are readonly below
impl QueryData for NameOrEntity
SAFETY: we assert fields are readonly below
const IS_READ_ONLY: bool = true
type ReadOnly = NameOrEntity
type Item<'__w> = NameOrEntityItem<'__w>
Source§impl<'__w, T: Component> QueryData for Ref<'__w, T>
SAFETY: Self
is the same as Self::ReadOnly
impl<'__w, T: Component> QueryData for Ref<'__w, T>
SAFETY: Self
is the same as Self::ReadOnly
Source§impl<'a> QueryData for FilteredEntityMut<'a>
SAFETY: access of FilteredEntityRef
is a subset of FilteredEntityMut
impl<'a> QueryData for FilteredEntityMut<'a>
SAFETY: access of FilteredEntityRef
is a subset of FilteredEntityMut
const IS_READ_ONLY: bool = false
type ReadOnly = FilteredEntityRef<'a>
type Item<'w> = FilteredEntityMut<'w>
Source§impl<'a> QueryData for FilteredEntityRef<'a>
SAFETY: Self
is the same as Self::ReadOnly
impl<'a> QueryData for FilteredEntityRef<'a>
SAFETY: Self
is the same as Self::ReadOnly
const IS_READ_ONLY: bool = true
type ReadOnly = FilteredEntityRef<'a>
type Item<'w> = FilteredEntityRef<'w>
Source§impl<'a, B> QueryData for EntityMutExcept<'a, B>where
B: Bundle,
SAFETY: All accesses that EntityRefExcept
provides are also accesses that
EntityMutExcept
provides.
impl<'a, B> QueryData for EntityMutExcept<'a, B>where
B: Bundle,
SAFETY: All accesses that EntityRefExcept
provides are also accesses that
EntityMutExcept
provides.
const IS_READ_ONLY: bool = false
type ReadOnly = EntityRefExcept<'a, B>
type Item<'w> = EntityMutExcept<'w, B>
Source§impl<'a, B> QueryData for EntityRefExcept<'a, B>where
B: Bundle,
SAFETY: Self
is the same as Self::ReadOnly
.
impl<'a, B> QueryData for EntityRefExcept<'a, B>where
B: Bundle,
SAFETY: Self
is the same as Self::ReadOnly
.