Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mrgvsv/bevy_enum_filter

Filter by enum variant in Bevy queries
https://github.com/mrgvsv/bevy_enum_filter

Last synced: 3 months ago
JSON representation

Filter by enum variant in Bevy queries

Awesome Lists containing this project

README

        

# bevy_enum_filter

[![Crates.io](https://img.shields.io/crates/v/bevy_enum_filter)](https://crates.io/crates/bevy_enum_filter)
[![Docs](https://img.shields.io/docsrs/bevy_enum_filter)](https://docs.rs/bevy_enum_filter/)
[![License](https://img.shields.io/crates/l/bevy_enum_filter)](./LICENSE.md)

Filter queries by enum variants!

In Rust, enum variants *aren't* types. This means we normally can't filter for them in a Bevy `Query`. The alternative, then is to use a set of "marker" components. This works well enough, but we miss out on the semantics of using an enum (and the ability to perform enum-specific operations such as `match`-ing).

This crate allows us to query for entities based on the *specific* variant of an enum component:

```rust
use bevy::prelude::*;
use bevy_enum_filter::prelude::*;

#[derive(Component, EnumFilter)]
enum ItemType {
Equippable(usize),
Weapon(usize),
Potion(usize)
}

fn apply_potion(item_query: Query<(Entity, &ItemType), Added>) {
// ...
}

fn main() {
App::new()
// ...
.add_enum_filter::()
.add_systems(Update, apply_potion)
.run()
}
```

## ๐Ÿ“ฒ Installation

Add the following to the `[dependencies]` section of your `Cargo.toml`.

```text
bevy_enum_filter = "0.3.0"
```

## ๐Ÿคจ How it works

*Surprise! It's just marker structs!*

Deriving `EnumFilter` generates a module containing a marker struct per variant. The module is named using the enum's name (snake-cased) followed by `_filters`. For example, our `ItemType` enum generates the following module:

```rust
// Auto-generated!
mod item_type_filters {
#[derive(bevy::prelude::Component)]
pub struct Equippable;
#[derive(bevy::prelude::Component)]
pub struct Weapon;
#[derive(bevy::prelude::Component)]
pub struct Potion;
}
```

When we then register our enum using `app.add_enum_filter`, we are adding a system that watches for changes (additions/mutations) related to that enum component. The system will then add or remove the appropriate marker struct whenever there's a change.

The `Enum!` macro then takes the given enum path and grabs the corresponding marker struct from the module. So `Enum!(ItemType::Potion)` corresponds to the `item_type_filters::Potion` type.

> ๐Ÿ“ข: This is why you *must* have your generated module in scope!

##### Caveats

Because this is basically just change detection under the hood, it's important to remember when the filter actually takes effect. By default, the system added by `app.add_enum_filter` runs in the `PostUpdate` stage. This means you will not see the filter work until the that stage is complete.

> And remember that any components changed in `Update` would not see their filters work until `PostUpdate` anyway since we need to cross a stage boundary for commands to flush. This means we realistically only lose out on a single stage.

If you need it to run after a certain system or within a certain stage, you could always add the `watch_for_enum` system yourself.

## ๐Ÿ•Š Bevy Compatibility

| bevy | bevy_enum_filter |
| :----- | ---------------- |
| 0.8.1 | 0.1.0 |
| 0.11.x | 0.2.0 |
| 0.12.x | 0.3.0 |