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