bevy_plugin_builder/
lib.rs

1//! # bevy-plugin-builder
2//!
3//! Declarative plugin system for Bevy
4//!
5//! This crate provides the `define_plugin!` macro that eliminates boilerplate
6//! from Bevy plugin registration. Instead of manually implementing `Plugin`,
7//! you declare your plugin's requirements and the macro handles all registration.
8//!
9//! ## Features
10//!
11//! - Eliminates repetitive `impl Plugin for` blocks
12//! - Compile-time validation of all registrations
13//! - Supports all Bevy registration patterns
14//!
15//! ## Quick Start
16//!
17//! Add to your `Cargo.toml`:
18//! ```toml
19//! [dependencies]
20//! bevy-plugin-builder = "0.1"
21//! bevy = "0.16"
22//! ```
23//!
24//! Then transform your plugins:
25//!
26//! ```rust
27//! use bevy_plugin_builder::define_plugin;
28//! use bevy::prelude::*;
29//!
30//! // Define your game types
31//! #[derive(Resource, Default)]
32//! struct GameSettings;
33//!
34//! #[derive(Resource, Default)]
35//! struct PlayerStats;
36//!
37//! #[derive(Event)]
38//! struct PlayerDied;
39//!
40//! #[derive(Event)]
41//! struct ScoreChanged;
42//!
43//! #[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
44//! enum GameState {
45//!     #[default]
46//!     Menu,
47//!     Playing,
48//! }
49//!
50//! // Define your systems
51//! fn setup_game() {}
52//! fn handle_input() {}
53//! fn update_physics() {}
54//! fn render_game() {}
55//!
56//! define_plugin!(MyGamePlugin {
57//!     resources: [GameSettings, PlayerStats],
58//!     events: [PlayerDied, ScoreChanged],
59//!     startup: [setup_game],
60//!     update: [
61//!         (handle_input, update_physics, render_game)
62//!             .chain()
63//!             .run_if(in_state(GameState::Playing))
64//!     ]
65//! });
66//! ```
67//!
68//! ## Supported Configuration Options
69//!
70//! - **`resources: [Type1, Type2]`** - Initialize resources with `init_resource`
71//! - **`events: [Event1, Event2]`** - Register events with `add_event`
72//! - **`plugins: [Plugin1, Plugin2]`** - Add sub-plugins with `add_plugins`
73//! - **`states: [State1]`** - Initialize states with `init_state`
74//! - **`sub_states: [SubState1]`** - Add sub-states with `add_sub_state`
75//! - **`reflect: [Type1, Type2]`** - Register types for reflection
76//! - **`startup: [system1, system2]`** - Add startup systems
77//! - **`update: [system3, system4]`** - Add update systems (supports conditions/ordering)
78//! - **`fixed_update: [system5]`** - Add fixed update systems
79//! - **`on_enter: { State::Variant => [system6] }`** - Add state enter systems
80//! - **`on_exit: { State::Variant => [system7] }`** - Add state exit systems
81//! - **`custom_init: |app| { ... }`** - Custom initialization logic
82//! - **`custom_finish: |app| { ... }`** - Custom finish logic
83//!
84//! ## Advanced Example
85//!
86//! ```rust
87//! use bevy_plugin_builder::define_plugin;
88//! use bevy::prelude::*;
89//!
90//! #[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
91//! enum GameState {
92//!     #[default]
93//!     Menu,
94//!     Playing,
95//!     Paused,
96//! }
97//!
98//! #[derive(Resource, Default, Reflect)]
99//! #[reflect(Resource)]
100//! struct GameSettings { volume: f32 }
101//!
102//! #[derive(Event)]
103//! struct GameStarted;
104//!
105//! define_plugin!(ComplexGamePlugin {
106//!     // Type registration
107//!     resources: [GameSettings],
108//!     events: [GameStarted],
109//!     states: [GameState],
110//!     reflect: [GameSettings],
111//!
112//!     // System scheduling
113//!     startup: [initialize_audio, load_assets],
114//!
115//!     update: [
116//!         handle_menu_input.run_if(in_state(GameState::Menu)),
117//!         (update_game, process_events).chain().run_if(in_state(GameState::Playing))
118//!     ],
119//!
120//!     fixed_update: [
121//!         physics_simulation.run_if(in_state(GameState::Playing))
122//!     ],
123//!
124//!     // State transitions
125//!     on_enter: {
126//!         GameState::Playing => [setup_level, spawn_player],
127//!         GameState::Paused => [show_pause_menu]
128//!     },
129//!
130//!     on_exit: {
131//!         GameState::Playing => [cleanup_level]
132//!     },
133//!
134//!     // Custom logic
135//!     custom_init: |app: &mut App| {
136//!         #[cfg(debug_assertions)]
137//!         app.add_plugins(bevy::diagnostic::DiagnosticsPlugin::default());
138//!     }
139//! });
140//!
141//! fn initialize_audio() { /* ... */ }
142//! fn load_assets() { /* ... */ }
143//! fn handle_menu_input() { /* ... */ }
144//! fn update_game() { /* ... */ }
145//! fn process_events() { /* ... */ }
146//! fn physics_simulation() { /* ... */ }
147//! fn setup_level() { /* ... */ }
148//! fn spawn_player() { /* ... */ }
149//! fn show_pause_menu() { /* ... */ }
150//! fn cleanup_level() { /* ... */ }
151//! ```
152//!
153//! ## Migration Guide
154//!
155//! Converting existing plugins is straightforward:
156//!
157//! 1. **Replace `impl Plugin`** with `define_plugin!`
158//! 2. **Group registrations by type** (resources, events, systems)
159//! 3. **Use declarative syntax** instead of method chains
160//!
161//! See the [examples](https://github.com/noahsabaj/bevy-plugin-builder/tree/main/examples) for complete migration examples.
162//!
163
164// Private implementation modules
165mod macros;
166
167// Re-export commonly used Bevy types for convenience
168pub use bevy::prelude::{App, FixedUpdate, OnEnter, OnExit, Plugin, Startup, Update};
169
170// The macro is automatically available via #[macro_export] in macros.rs