Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/robertdodd/bevy_reflect_utils
A small, plugin-less utility library making it easier to work with reflection in bevy.
https://github.com/robertdodd/bevy_reflect_utils
bevy bevy-engine game-development gamedev gui ui
Last synced: 2 months ago
JSON representation
A small, plugin-less utility library making it easier to work with reflection in bevy.
- Host: GitHub
- URL: https://github.com/robertdodd/bevy_reflect_utils
- Owner: robertdodd
- License: apache-2.0
- Created: 2024-06-24T02:47:37.000Z (6 months ago)
- Default Branch: master
- Last Pushed: 2024-07-05T05:21:20.000Z (6 months ago)
- Last Synced: 2024-09-27T07:03:29.305Z (3 months ago)
- Topics: bevy, bevy-engine, game-development, gamedev, gui, ui
- Language: Rust
- Homepage:
- Size: 104 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# Bevy Reflect Utils
A small, plugin-less utility library making it easier to work with reflection
in [bevy](https://bevyengine.org/).---
## Development
> [!WARNING]
> UNDER DEVELOPMENT, EXPECT BREAKING CHANGES## Motivation
This library was written to build re-usable UI widgets.
Reflection code is usually very verbose and hard to follow. The functions in this library only require a `ReflectTarget`
pointing to a field and an `&mut World`, and return an easy-to-handle `Result`.The [menu](https://github.com/robertdodd/bevy_reflect_utils/blob/master/examples/menu.rs) (`cargo run --example menu`)
example demonstrates a few simple UI widgets used on a settings page.## Simple Example
```rust
use bevy::prelude::*;
use bevy_reflect_utils::*;fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::()
.add_systems(Startup, setup)
// IMPORTANT: The types you want to operate on must be registered
.register_type::()
.run();
}// IMPORTANT: The types you operate on must derive `Reflect`
#[derive(Resource, Reflect, Debug, Default)]
#[reflect(Resource, Default, Debug)]
pub struct ExampleResource {
value: bool,
}fn setup(world: &mut World) {
// Define a `ReflectTarget` pointing to `ExampleResource::value`
let target = ReflectTarget::new_resource::("value");// Read the initial value
let initial_value = target.read_value::(world).unwrap();
println!("initial value: {}", initial_value);// Set a new value
target.set_value(world, !initial_value).unwrap();// Read the new value
let new_value = target.read_value::(world).unwrap();
println!("new value: {}", new_value);
}
```This example will print the following:
```
initial value: false
new value: true
```You can run this same example with:
```shell
cargo run --example simple
```## Recommended Usage
Use `Commands` to perform reflection when possible. Use exclusive systems
when you can't avoid it.For example, to update a value when a button is clicked:
```rust
fn handle_click_events(mut commands: &mut Commands) {
// if button was clicked...
let target = ReflectTarget::new_resource::("value");
commands.add(move |world: &mut World| {
match target.set_value(world, true) {
Ok(ReflectSetSuccess::Changed) => info!("Success"),
Ok(ReflectSetSuccess::NoChanges) => warn!("Value not changed"),
Err(err) => error!("{err:?}"),
}
});
}
```## `ReflectTarget` Target Types
Create a `ReflectTarget` referencing a field on an `Entity` and `Component`:
```rust
let target = ReflectTarget::new_component::(entity, "value");
```Create a `ReflectTarget` referencing a field on a `Resource`:
```rust
let target = ReflectTarget::new_resource::("value");
```## `ReflectTarget` Operations
`ReflectTarget` provides the following operations:
### Read Value
> Requires knowing the underlying type.
```rust
target.read_value::(world);
```Return Value:
```rust
Result
```### Set Value
> Requires knowing the underlying type.
```rust
target.set_value(world, 0.5);
```Return Value:
```rust
Result
```### Toggle Between Enum Variant
Toggle between the previous/next enum variants.
Also works with data variants, provided the variant implements and reflects `Default`.
> Does not require knowing the underlying type.
> **Important:** Does not wrap around when reaching the beginning or end of
> the list of variants.```rust
target.toggle_enum_variant(world, EnumDirection::Forward);
target.toggle_enum_variant(world, EnumDirection::Backward);
```Return Value:
```rust
Result
```### Read Enum Variant Name
> Does not require knowing the underlying type.
```rust
target.read_enum_variant_name(world);
```Return Value:
```rust
Result
```### Read Serialized Value
> Does not require knowing the underlying type.
```rust
target.read_value_serialized(world);
```Return Value:
```rust
Result
```Example:
```rust
Ok("{\"f32\":0.5}")
```### Set Serialized Value
> Does not require knowing the underlying type.
```rust
target.set_value_serialized(world, "{\"f32\":0.5}".to_string());
```Return Value:
```rust
Result
```### Partial Equality Against a Serialized Value
> Does not require knowing the underlying type.
```rust
target.partial_eq_serialized(world, "{\"f32\":0.5}".to_string());
```Return Value:
```rust
Result
```## Errors
The primary error type is [`ReflectError`](https://github.com/robertdodd/bevy_reflect_utils/blob/master/src/errors.rs).
## Set Value Return Type
Most operations that set a value have the following return type:
```rust
Result
```Where [`ReflectSetSuccess`](https://github.com/robertdodd/bevy_reflect_utils/blob/master/src/errors.rs)
allows you know whether the field was changed by the operation:```rust
pub enum ReflectSetSuccess {
Changed,
NoChanges,
}
```## Compatible Bevy versions
| `bevy_reflect_utils` | `bevy` |
|:---------------------|:-------|
| `0.2` | `0.14` |
| `0.1` | `0.13` |## License
Dual-licensed under either of
- Apache License, Version 2.0,
([LICENSE-APACHE](https://github.com/robertdodd/bevy_round_ui/blob/master/LICENSE-APACHE) or
https://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](https://github.com/robertdodd/bevy_round_ui/blob/master/LICENSE-MIT) or
https://opensource.org/licenses/MIT)at your option.
## Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as
defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.