Bevy Queryable Reflect

Bevy tracking Latest version MIT/Apache 2.0 Documentation

Bevy's ReflectComponent allows extracting a value from a EntityRef or EntityMut, this can be useful, but generally not enough.

ReflectComponent is missing ways to query for the reflected thing. Without this ability, you would be stuck iterating over all EntityRef and checking if it contains the component in question. This is O(n) (where n is the total count of entities) while querying just for a single entity is O(1).

We introduce ReflectQueryable to fill this gap.

Should I use this crate?

In short, if you are asking this question, you most likely shouldn't!

If the second paragraph of this README means anything to you, as in: this is not complete technobable, and you are like "Wow! It's possible!" then yeah babe, that's for you!

Usage

First, add this crate as dependency to your Cargo.toml:

toml [dependencies] cuicui_reflect_query = "<current version>"

If you need to use ReflectQueryable on pre-existing bevy components, check the Features section.

Then, you would use ReflectQueryable in combination with the TypeRegistry and an exclusive access World as follow:

```rust use std::any::TypeId; use bevy::prelude::{Reflect, ReflectComponent, Component, World}; use bevy::reflect::TypeRegistryInternal as TypeRegistry; use cuicuireflectquery::{ReflectQueryable, Ref};

[derive(Debug, Clone, PartialEq, Component, Reflect, Default)]

[reflect(Component, Queryable)]

struct Zoobazee { bee: u32, baboo: String, }

fn reflectquery<'w>(world: &'w mut World, registry: &TypeRegistry) -> Ref<'w, dyn Reflect> { let typedata = registry .gettypedata::(TypeId::of::()) .unwrap();

let mut query = type_data.query(world);
for element in query.iter(world) {
    println!("{element:?}");
}
type_data.get_single_ref(world).unwrap()

} fn main() { let mut world = bevy::prelude::World::new(); let mut type_registry = TypeRegistry::new();

type_registry.register::<Zoobazee>();

let component = Zoobazee {
  bee: 32,
  baboo: "zoobalong".to_string(),
};

world.spawn(component.clone());

let single_result = reflect_query(&mut world, &type_registry);
assert_eq!(single_result.downcast_ref(), Some(&component));

} ```

Details

ReflectQueryable adds methods to query from a dynamic value:

A bit of precision:

```rust,ignore pub struct ReflectQueryableFns { pub reflect_ref: fn(EntityRef) -> Option>,

pub get_single: fn(&mut World) -> SingleResult<&dyn Reflect>,
pub get_single_entity: fn(&mut World) -> SingleResult<Entity>,
pub get_single_ref: fn(&mut World) -> SingleResult<Ref<dyn Reflect>>,
pub get_single_mut: fn(&mut World) -> SingleResult<Mut<dyn Reflect>>,

pub query: fn(&mut World) -> Querydyn,
pub query_entities: fn(&mut World) -> EntityQuerydyn,
pub query_ref: fn(&mut World) -> RefQuerydyn,
pub query_mut: fn(&mut World) -> MutQuerydyn,

} ```

Implementations for base bevy components

Since this is not part of bevy, we need to add those to the bevy components.

To add ReflectQueryable implementations for bevy components, use predefined::QueryablePlugin as follow:

```rust use bevy::prelude::*; use cuicuireflectquery::predefined::QueryablePlugin;

fn main() { let mut app = App::new();

app.add_plugins(DefaultPlugins)
  // … bunch of plugins …
  .add_plugin(QueryablePlugin);
  // … bunch of other things

} ```

This crate exposes one feature per bevy features, they are off by default, you must explicitly enable them to register ReflectQueryable for bevy components:

You'd then add them as follow:

toml [dependencies] cuicui_reflect_query = { version = "<current version>", features = ["register_…" ] }

Beware that you can add them yourself. But please, if anything is missing open an issue, it's hard to make sure I didn't forget anything.

Implementing for your own types

Like with ReflectComponent, you need to register the trait information for your own types. It will look like this:

```diff + use cuicuireflectquery::ReflectQueryable;

#[derive(Reflect, Component, Default)] - #[reflect(Component)] + #[reflect(Component, Queryable)] struct Zoobaroo { bidoo: u32, bubble: String, padiwoop: AlphaMode, } ```

Make sure to app.register_type::<Zoobaroo>()! and you should be good to go.

Version matrix

| bevy | latest supported version | |------|--------------------------| | 0.10 | <current version> |

License

Copyright © 2023 Nicola Papale

This software is licensed under either MIT or Apache 2.0 at your leisure. See licenses directory at the root of the cuicui repository for details.