Crate bevy_query_ext

Source
Expand description

Bevy tracking

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:

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.

bevybevy_query_ext
0.160.6
0.150.5
0.140.4
0.130.3
0.120.2
0.110.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::* over bevy_query_ext::* to avoid importing our internal modules.

Type Aliases§

AsDeref
Returns the dereferenced component
AsDerefCloned
Returns a clone of the dereferenced value (alias of Cloned<AsDeref<T>>)
AsDerefClonedOfClonedOrDefault
First either clones component T or gets the default value, then dereferences this value and clones it.
AsDerefClonedOrDefault
Returns a clone of component’s dereferenced value, or default for that type. See Cloned, AsDeref and OrDefault
AsDerefCopied
Returns a copy of the dereferenced value (alias of Copied<AsDeref<T>)
AsDerefCopiedOfClonedOrDefault
First either clones component T or gets the default value, then dereferences this value and copies it.
AsDerefCopiedOfCopiedOrDefault
First either copies component T or gets the default value, then dereferences this value and copies it.
AsDerefCopiedOrDefault
Returns a copy of component’s dereferenced value, or default for that type. See Copied, AsDeref and OrDefault
AsDerefMut
Returns the dereferenced component as a Mut, or a reference if it is readonly.
AsDerefOrBool
When T implements Deref for bool , this will return that value or the specified value if T has no result
AsDerefOrChar
When T implements Deref for char , this will return that value or the specified value if T has no result
AsDerefOrI8
When T implements Deref for i8 , this will return that value or the specified value if T has no result
AsDerefOrI16
When T implements Deref for i16 , this will return that value or the specified value if T has no result
AsDerefOrI32
When T implements Deref for i32 , this will return that value or the specified value if T has no result
AsDerefOrI64
When T implements Deref for i64 , this will return that value or the specified value if T has no result
AsDerefOrI128
When T implements Deref for i128 , this will return that value or the specified value if T has no result
AsDerefOrIsize
When T implements Deref for isize , this will return that value or the specified value if T has no result
AsDerefOrU8
When T implements Deref for u8 , this will return that value or the specified value if T has no result
AsDerefOrU16
When T implements Deref for u16 , this will return that value or the specified value if T has no result
AsDerefOrU32
When T implements Deref for u32 , this will return that value or the specified value if T has no result
AsDerefOrU64
When T implements Deref for u64 , this will return that value or the specified value if T has no result
AsDerefOrU128
When T implements Deref for u128 , this will return that value or the specified value if T has no result
AsDerefOrUsize
When T implements Deref for usize , this will return that value or the specified value if T has no result
Cloned
Clones a type when it is retrieved
ClonedOrDefault
Returns a clone of component or default. See Cloned and OrDefault
Copied
Copies a type when it is retrieved
CopiedOrDefault
Returns a copy of component or default. See Copied and OrDefault
OrBool
When T implements Borrow for bool, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrBool for example of its use.
OrChar
When T implements Borrow for char, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrChar 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 implements Borrow for i8, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrI8 for example of its use.
OrI16
When T implements Borrow for i16, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrI16 for example of its use.
OrI32
When T implements Borrow for i32, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrI32 for example of its use.
OrI64
When T implements Borrow for i64, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrI64 for example of its use.
OrI128
When T implements Borrow for i128, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrI128 for example of its use.
OrIsize
When T implements Borrow for isize, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrIsize for example of its use.
OrU8
When T implements Borrow for u8, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrU8 for example of its use.
OrU16
When T implements Borrow for u16, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrU16 for example of its use.
OrU32
When T implements Borrow for u32, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrU32 for example of its use.
OrU64
When T implements Borrow for u64, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrU64 for example of its use.
OrU128
When T implements Borrow for u128, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrU128 for example of its use.
OrUsize
When T implements Borrow for usize, this will return that value or the specified value if T has no result. It’s unlikely you’ll use this by itself, see AsDerefOrUsize for example of its use.