Expand description
A collection of types used to simplify how components are used in queries, by implementing
bevy’s QueryData
on generics.
§Example of use
use bevy::prelude::*;
use std::ops::Deref;
use bevy_query_ext::AsDerefOrU32;
// Component which indicates ammo left in a weapon
// A weapon with an ammo component can't be used if ammo is 0
// A weapon with no ammo component, like a knife, can be used
#[derive(Component, Deref)]
struct Ammo(u32);
fn identify_usable_weapons_1(weapons: Query<(&Name, Option<&Ammo>)>) {
for (name, ammo_count) in weapons.iter() {
if ammo_count.map(|ammo_count|*ammo_count.deref()).unwrap_or(1) > 0 {
println!("{:?} can be used!", name)
}
}
}
// AsDerefOrU32<T, V> is a type alias for OrU32<AsDeref<T>, V>
fn identify_usable_weapons_2(weapons: Query<(&Name, AsDerefOrU32<Ammo, 1>)>) {
for (name, ammo_count) in weapons.iter() {
if ammo_count > 0 {
println!("{:?} can be used!", name)
}
}
}
// If you find yourself reusing a type in the same way across multiple systems, just use a type
// alias for it and you can use it like that in code.
type AmmoCount = AsDerefOrU32<Ammo, 1>;
§Basic types
Our crate is composed of these basic types:
AsDeref<T>
- Returns T dereferenced (a laDeref
trait)AsDerefMut<T>
- Returns T dereferenced (a laDerefMut
trait)Copied<T>
- Returns T copied (a laCopy
trait)Cloned<T>
- Returns T cloned (a laClone
trait)OrDefault<T>
- Returns T if the entity has this component, or its default (a laDefault
trait)OrBool<T, const V: bool>
,OrChar<T, const V: bool>
,OrUsize<T, const V: usize>
, etc. - Returns T.borrow() (a laBorrow
trait), or the constant provided if the entity does not have this component
You can use these basic types by themselves, but they are most useful composed with each other (except DerefMut
).
There are type aliases for most valid compositions of these types. For example,
type AsDerefCopied<T> = Copied<AsDeref<T>>
.
§Note about destructors and Entity components
A common use case the author has had is having components that dereference to entities. But using AsDerefCopied
in
long tuple-queries can lead to you getting entities mixed up since they are no longer type-protected. It is better
in these cases to make the dereference fields public and use destructuring assignments if possible. For instance, if
your component was pub struct PointsTo(Entity)
, you can get the value using something like
for (&PointsTo(points_to), <..>) = query.iter()
instead.
This is also not a problem for derived queries with named fields.
§Note on limitations of composition
Because of the way QueryData works, in order to implement it, we need to know that the
lifetime for all parameters is “covariant,” or rather that if 'a : 'b
then T<'a> : T<'b>
.
For more information on variance, see here.
However, Rust’s associated types are assumed to be invariant, and there is no language feature
that allows us to enforce that the associated types are covariant types so even if we could get
around it with unsafe code we couldn’t restrict it to the proper types. This means we can’t
simply implement <T: QueryData> Copied<T>
. However, thanks to the way Rust’s typing works,
we can manually implement composed types like Copied<AsDeref<T>>
even with Copied<T>
already implemented.
This crate attempts to manually implement all useful compositions of the types here, and to
indicate these with specialized type aliases. AsDerefCopiedOfClonedOrDefault
is probably the
most egregious of these.
§Bevy Compatibility
Since there can be breaking changes to our APIs we will have different versions for our code than the compatible bevy library, but we’ll list compatibility here.
bevy | bevy_query_ext |
---|---|
0.16 | 0.6 |
0.15 | 0.5 |
0.14 | 0.4 |
0.13 | 0.3 |
0.12 | 0.2 |
0.11 | 0.1 |
§Feedback
Could the docs be clearer? Is a useful composition missing? Is there a type I haven’t considered? For any of these, please open an issue or PR on Github!
Modules§
- prelude
- Prelude module - Contains only the parts of the crate that are useful to consumers
Everything in this module can also be imported from the crate directly, but you
can import
bevy_query_ext::prelude::*
overbevy_query_ext::*
to avoid importing our internal modules.
Type Aliases§
- AsDeref
- Returns the dereferenced component
- AsDeref
Cloned - Returns a clone of the dereferenced value (alias of
Cloned<AsDeref<T>>
) - AsDeref
Cloned OfCloned OrDefault - First either clones component T or gets the default value, then dereferences this value and clones it.
- AsDeref
Cloned OrDefault - Returns a clone of component’s dereferenced value, or default for that type. See
Cloned
,AsDeref
andOrDefault
- AsDeref
Copied - Returns a copy of the dereferenced value (alias of
Copied<AsDeref<T>
) - AsDeref
Copied OfCloned OrDefault - First either clones component T or gets the default value, then dereferences this value and copies it.
- AsDeref
Copied OfCopied OrDefault - First either copies component T or gets the default value, then dereferences this value and copies it.
- AsDeref
Copied OrDefault - Returns a copy of component’s dereferenced value, or default for that type. See
Copied
,AsDeref
andOrDefault
- AsDeref
Mut - Returns the dereferenced component as a
Mut
, or a reference if it is readonly. - AsDeref
OrBool - When
T
implementsDeref
for bool , this will return that value or the specified value if T has no result - AsDeref
OrChar - When
T
implementsDeref
for char , this will return that value or the specified value if T has no result - AsDeref
OrI8 - When
T
implementsDeref
for i8 , this will return that value or the specified value if T has no result - AsDeref
OrI16 - When
T
implementsDeref
for i16 , this will return that value or the specified value if T has no result - AsDeref
OrI32 - When
T
implementsDeref
for i32 , this will return that value or the specified value if T has no result - AsDeref
OrI64 - When
T
implementsDeref
for i64 , this will return that value or the specified value if T has no result - AsDeref
OrI128 - When
T
implementsDeref
for i128 , this will return that value or the specified value if T has no result - AsDeref
OrIsize - When
T
implementsDeref
for isize , this will return that value or the specified value if T has no result - AsDeref
OrU8 - When
T
implementsDeref
for u8 , this will return that value or the specified value if T has no result - AsDeref
OrU16 - When
T
implementsDeref
for u16 , this will return that value or the specified value if T has no result - AsDeref
OrU32 - When
T
implementsDeref
for u32 , this will return that value or the specified value if T has no result - AsDeref
OrU64 - When
T
implementsDeref
for u64 , this will return that value or the specified value if T has no result - AsDeref
OrU128 - When
T
implementsDeref
for u128 , this will return that value or the specified value if T has no result - AsDeref
OrUsize - When
T
implementsDeref
for usize , this will return that value or the specified value if T has no result - Cloned
- Clones a type when it is retrieved
- Cloned
OrDefault - Returns a clone of component or default. See
Cloned
andOrDefault
- Copied
- Copies a type when it is retrieved
- Copied
OrDefault - Returns a copy of component or default. See
Copied
andOrDefault
- OrBool
- When
T
implementsBorrow
forbool
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrBool
for example of its use. - OrChar
- When
T
implementsBorrow
forchar
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrChar
for example of its use. - OrDefault
- If the query exists on the entity it is returned, or else the default for the query result
- OrI8
- When
T
implementsBorrow
fori8
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrI8
for example of its use. - OrI16
- When
T
implementsBorrow
fori16
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrI16
for example of its use. - OrI32
- When
T
implementsBorrow
fori32
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrI32
for example of its use. - OrI64
- When
T
implementsBorrow
fori64
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrI64
for example of its use. - OrI128
- When
T
implementsBorrow
fori128
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrI128
for example of its use. - OrIsize
- When
T
implementsBorrow
forisize
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrIsize
for example of its use. - OrU8
- When
T
implementsBorrow
foru8
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrU8
for example of its use. - OrU16
- When
T
implementsBorrow
foru16
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrU16
for example of its use. - OrU32
- When
T
implementsBorrow
foru32
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrU32
for example of its use. - OrU64
- When
T
implementsBorrow
foru64
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrU64
for example of its use. - OrU128
- When
T
implementsBorrow
foru128
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrU128
for example of its use. - OrUsize
- When
T
implementsBorrow
forusize
, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, seeAsDerefOrUsize
for example of its use.