# Bevy Auto Plugin
[](https://github.com/StrikeForceZero/bevy_auto_plugin#license)
[](https://crates.io/crates/bevy_auto_plugin)
[](https://crates.io/crates/bevy_auto_plugin)
[](https://docs.rs/bevy_auto_plugin/latest/bevy_auto_plugin/)
[](https://github.com/StrikeForceZero/bevy_auto_plugin/actions?query=branch%3Amain)
Bevy Auto Plugin provides attribute macros that automatically handle the repetitive setup usually required in Bevy plugins.
Instead of manually wiring up components, resources, events, states, and systems - and remembering all their respective derives - you can declare them with concise annotations tied to a plugin.
If you’ve ever added several components only to hit runtime errors or discover a missing `TypeRegistry` entry when using tools like `bevy-inspector-egui`, this plugin is for you.
It helps keep your code ***focused on game logic rather than framework plumbing.***
The following examples demonstrate how common Bevy patterns can be expressed more ergonomically with `#[auto_*]` macros, while still generating the underlying bevy-specific code you would normally write by hand.
## Examples
### Basic
#### Component
instead of having to specify all these derives and remember to reflect:
```rust
#[derive(Component, Debug, Default, Reflect)]
#[reflect(Component, Debug, Default)]
#[require(Name::new("FooComponent"))]
struct FooComponent;
```
and then later having to remember to register your component in the type registry:
```rust
struct MyPlugin;
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.register_type::<FooComponent>();
}
}
```
you can do:
```rust
#[derive(AutoPlugin)]
#[auto_plugin(impl_plugin_trait)]
struct MyPlugin;
#[auto_component(
plugin = MyPlugin,
derive(Debug, Default),
reflect(Debug, Default),
register,
auto_name,
)]
struct FooComponent;
```
#### System
instead of writing a function then scheduling in your plugin's build function:
```rust
fn my_system() {}
fn plugin(app: &mut App) {
app.add_systems(Update, my_system.run_if(some_condition).after(some_other_system));
}
```
you can do it via the `auto_system(..)` attribute macro:
```rust
#[auto_system(
plugin = MyPlugin,
schedule = Update,
config(
run_if = some_condition,
after = some_other_system,
),
)]
fn my_system() {}
```
### Generics
#### Component
if your items have generics, you can specify the types using the `generics(...)` meta argument for each concrete type.
Note: Clippy will complain if you have duplicate generic type names. For those you can use named generics: `generics(A = ..., B = ...)`.
```rust
#[derive(AutoPlugin)]
#[auto_plugin(impl_plugin_trait)]
struct MyPlugin;
#[auto_component(
plugin = MyPlugin,
generics(usize, bool),
generics(A = bool, B = bool),
derive(Debug, Default),
reflect(Debug, Default),
register,
auto_name,
)]
struct FooComponent<A, B>(A, B);
```
this will generate something equivalent to:
```rust
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.register_type::<FooComponent<usize, bool>>();
app.register_type::<FooComponent<bool, bool>>();
}
}
```
#### System
if your systems have generics, you can specify the types using the `generics(...)` meta argument for each concrete type.
Note: Clippy will complain if you have duplicate generic type names. For those you can use named generics: `generics(A = ..., B = ...)`.
```rust
#[auto_system(
plugin = MyPlugin,
schedule = Update,
generics(Name),
generics(A = Transform),
config(
run_if = some_condition,
after = some_other_system,
),
)]
fn my_system<A: Component>(q: Query<&A>) {
for item in q.iter() {
//
}
}
```
this will generate something equivalent to:
```rust
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, my_system::<Name>.run_if(some_condition).after(some_other_system));
app.add_systems(Update, my_system::<Transform>.run_if(some_condition).after(some_other_system));
}
}
```
### Plugin
There are three distinct ways to make a bindable plugin:
```rust
#[derive(AutoPlugin)]
#[auto_plugin(impl_plugin_trait)]
struct MyPlugin;
```
```rust
#[derive(AutoPlugin)]
struct MyPlugin;
impl Plugin for MyPlugin {
#[auto_plugin]
fn build(&self, app: &mut App) {
//
}
}
```
```rust
#[derive(AutoPlugin)]
struct MyPlugin;
#[auto_plugin(plugin = MyPlugin)]
fn plugin(app: &mut App) {
//
}
```
There is `auto_plugin` arguments if your plugin has generics.
See [tests](tests/e2e) for other examples
### Expanded
If you were looking to cherry-pick certain functionality like `auto_name` or `auto_register_type` for example you could use them individually:
Only requirement is you need to make sure you are binding to a plugin that derives `AutoPlugin`
#### Usage Examples
```rust
use bevy::prelude::*;
use bevy_auto_plugin::prelude::*;
#[derive(AutoPlugin)]
#[auto_plugin(impl_plugin_trait)]
struct MyPlugin;
#[derive(Component, Reflect)]
#[reflect(Component)]
#[auto_register_type(plugin = MyPlugin)]
#[auto_name(plugin = MyPlugin)]
struct FooComponent;
// or if you want to omit plugin for each auto_* item:
#[auto_bind_plugin(plugin = MyPlugin)]
#[derive(Component, Reflect)]
#[reflect(Component)]
#[auto_register_type]
#[auto_name]
struct FooComponent2;
#[derive(Resource, Debug, Default, Reflect)]
#[reflect(Resource)]
#[auto_register_type(plugin = MyPlugin)]
#[auto_init_resource(plugin = MyPlugin)]
struct FooDefaultResource(usize);
#[derive(Resource, Debug, Default, Reflect)]
#[reflect(Resource)]
#[auto_register_type(plugin = MyPlugin)]
#[auto_init_resource(plugin = MyPlugin)]
#[auto_insert_resource(plugin = MyPlugin, insert(FooResource(1)))]
struct FooResource(usize);
#[derive(Message, Debug, Default, Reflect)]
#[auto_register_type(plugin = MyPlugin)]
#[auto_add_message(plugin = MyPlugin)]
struct FooEvent(usize);
#[derive(States, Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Reflect)]
#[auto_init_state(plugin = MyPlugin)]
#[auto_register_state_type(plugin = MyPlugin)]
enum FooState {
#[default]
Start,
End,
}
#[auto_add_system(plugin = MyPlugin, schedule = Update)]
fn foo_system(mut foo_resource: ResMut<FooResource>) {
foo_resource.0 += 1;
}
fn main() {
App::new()
.add_plugins(MyPlugin)
// ... other plugins and setup
.run();
}
```
Which automatically implements the Plugin trait for `MyPlugin` and registers all the types, resources, events, and systems when the plugin is added to the app.
#### Known Limitations
- WASM should work, CI uses the `wasm-bindgen-test-runner` but maybe there's a specific wasm target/environment where it fails?
---
## [Changelog](CHANGELOG.md)
## [Migrations](MIGRATIONS.md)
## License
All code in this repository is dual-licensed under either:
- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer.
### Your Contributions
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.