From ab8198ff428c717564b97fd7db859a77f00ac70b Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 01:39:37 -0800 Subject: [PATCH 1/6] expressively define plugins using functions --- crates/bevy_app/src/plugin.rs | 40 +++++++++++ examples/games/game_menu.rs | 129 +++++++++++++++------------------- 2 files changed, 97 insertions(+), 72 deletions(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index b722737ccb56a..52f8a7fe0c3b5 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -21,6 +21,40 @@ use std::any::Any; /// * once the app started, it will wait for all registered [`Plugin::ready`] to return `true` /// * it will then call all registered [`Plugin::finish`] /// * and call all registered [`Plugin::cleanup`] +/// +/// ## Defining a plugin. +/// +/// Most plugins are simply a function that adds configuration to an [`App`]. +/// +/// ``` +/// # use bevy_app::{App, Update}; +/// App::new().add_plugins(my_plugin); +/// +/// // This function implements `Plugin`, along with every other `fn(&mut World)`. +/// pub fn my_plugin(app: &mut App) { +/// app.add_systems(Update, hello_world); +/// } +/// # fn hello_world() {} +/// ``` +/// +/// For more advanced use cases, the `Plugin` trait can be implemented manually for a type. +/// +/// ``` +/// # use bevy_app::*; +/// pub struct AccessibilityPlugin { +/// pub flicker_damping: bool, +/// // ... +/// } +/// +/// impl Plugin for AccessibilityPlugin { +/// fn build(&self, app: &mut App) { +/// if self.flicker_damping { +/// app.add_systems(PostUpdate, damp_flickering); +/// } +/// } +/// } +/// # fn damp_flickering() {} +/// ```` pub trait Plugin: Downcast + Any + Send + Sync { /// Configures the [`App`] to which this plugin is added. fn build(&self, app: &mut App); @@ -60,6 +94,12 @@ pub trait Plugin: Downcast + Any + Send + Sync { impl_downcast!(Plugin); +impl Plugin for T { + fn build(&self, app: &mut App) { + self(app); + } +} + /// A type representing an unsafe function that returns a mutable pointer to a [`Plugin`]. /// It is used for dynamically loading plugins. /// diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 5b4b5a2457c81..764661496cc00 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -51,19 +51,15 @@ mod splash { use super::{despawn_screen, GameState}; // This plugin will display a splash screen with Bevy logo for 1 second before switching to the menu - pub struct SplashPlugin; - - impl Plugin for SplashPlugin { - fn build(&self, app: &mut App) { - // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash` - app - // When entering the state, spawn everything needed for this screen - .add_systems(OnEnter(GameState::Splash), splash_setup) - // While in this state, run the `countdown` system - .add_systems(Update, countdown.run_if(in_state(GameState::Splash))) - // When exiting the state, despawn everything that was spawned for this screen - .add_systems(OnExit(GameState::Splash), despawn_screen::); - } + pub fn splash_plugin(app: &mut App) { + // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash` + app + // When entering the state, spawn everything needed for this screen + .add_systems(OnEnter(GameState::Splash), splash_setup) + // While in this state, run the `countdown` system + .add_systems(Update, countdown.run_if(in_state(GameState::Splash))) + // When exiting the state, despawn everything that was spawned for this screen + .add_systems(OnExit(GameState::Splash), despawn_screen::); } // Tag component used to tag entities added on the splash screen @@ -125,14 +121,10 @@ mod game { // This plugin will contain the game. In this case, it's just be a screen that will // display the current settings for 5 seconds before returning to the menu - pub struct GamePlugin; - - impl Plugin for GamePlugin { - fn build(&self, app: &mut App) { - app.add_systems(OnEnter(GameState::Game), game_setup) - .add_systems(Update, game.run_if(in_state(GameState::Game))) - .add_systems(OnExit(GameState::Game), despawn_screen::); - } + pub fn game_plugin(app: &mut App) { + app.add_systems(OnEnter(GameState::Game), game_setup) + .add_systems(Update, game.run_if(in_state(GameState::Game))) + .add_systems(OnExit(GameState::Game), despawn_screen::); } // Tag component used to tag entities added on the game screen @@ -253,57 +245,50 @@ mod menu { // - a main menu with "New Game", "Settings", "Quit" // - a settings menu with two submenus and a back button // - two settings screen with a setting that can be set and a back button - pub struct MenuPlugin; - - impl Plugin for MenuPlugin { - fn build(&self, app: &mut App) { - app - // At start, the menu is not enabled. This will be changed in `menu_setup` when - // entering the `GameState::Menu` state. - // Current screen in the menu is handled by an independent state from `GameState` - .add_state::() - .add_systems(OnEnter(GameState::Menu), menu_setup) - // Systems to handle the main menu screen - .add_systems(OnEnter(MenuState::Main), main_menu_setup) - .add_systems(OnExit(MenuState::Main), despawn_screen::) - // Systems to handle the settings menu screen - .add_systems(OnEnter(MenuState::Settings), settings_menu_setup) - .add_systems( - OnExit(MenuState::Settings), - despawn_screen::, - ) - // Systems to handle the display settings screen - .add_systems( - OnEnter(MenuState::SettingsDisplay), - display_settings_menu_setup, - ) - .add_systems( - Update, - ( - setting_button:: - .run_if(in_state(MenuState::SettingsDisplay)), - ), - ) - .add_systems( - OnExit(MenuState::SettingsDisplay), - despawn_screen::, - ) - // Systems to handle the sound settings screen - .add_systems(OnEnter(MenuState::SettingsSound), sound_settings_menu_setup) - .add_systems( - Update, - setting_button::.run_if(in_state(MenuState::SettingsSound)), - ) - .add_systems( - OnExit(MenuState::SettingsSound), - despawn_screen::, - ) - // Common systems to all screens that handles buttons behavior - .add_systems( - Update, - (menu_action, button_system).run_if(in_state(GameState::Menu)), - ); - } + pub fn menu_plugin(app: &mut App) { + app + // At start, the menu is not enabled. This will be changed in `menu_setup` when + // entering the `GameState::Menu` state. + // Current screen in the menu is handled by an independent state from `GameState` + .add_state::() + .add_systems(OnEnter(GameState::Menu), menu_setup) + // Systems to handle the main menu screen + .add_systems(OnEnter(MenuState::Main), main_menu_setup) + .add_systems(OnExit(MenuState::Main), despawn_screen::) + // Systems to handle the settings menu screen + .add_systems(OnEnter(MenuState::Settings), settings_menu_setup) + .add_systems( + OnExit(MenuState::Settings), + despawn_screen::, + ) + // Systems to handle the display settings screen + .add_systems( + OnEnter(MenuState::SettingsDisplay), + display_settings_menu_setup, + ) + .add_systems( + Update, + (setting_button::.run_if(in_state(MenuState::SettingsDisplay)),), + ) + .add_systems( + OnExit(MenuState::SettingsDisplay), + despawn_screen::, + ) + // Systems to handle the sound settings screen + .add_systems(OnEnter(MenuState::SettingsSound), sound_settings_menu_setup) + .add_systems( + Update, + setting_button::.run_if(in_state(MenuState::SettingsSound)), + ) + .add_systems( + OnExit(MenuState::SettingsSound), + despawn_screen::, + ) + // Common systems to all screens that handles buttons behavior + .add_systems( + Update, + (menu_action, button_system).run_if(in_state(GameState::Menu)), + ); } // State used for the current menu screen From a9e3cd2eaa42cf5d86407f93f3a62da945cd3aad Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 01:59:25 -0800 Subject: [PATCH 2/6] update usages --- crates/bevy_app/src/plugin.rs | 14 +++++++------- examples/games/game_menu.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 52f8a7fe0c3b5..4ee19891a5570 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -21,31 +21,31 @@ use std::any::Any; /// * once the app started, it will wait for all registered [`Plugin::ready`] to return `true` /// * it will then call all registered [`Plugin::finish`] /// * and call all registered [`Plugin::cleanup`] -/// +/// /// ## Defining a plugin. -/// +/// /// Most plugins are simply a function that adds configuration to an [`App`]. -/// +/// /// ``` /// # use bevy_app::{App, Update}; /// App::new().add_plugins(my_plugin); -/// +/// /// // This function implements `Plugin`, along with every other `fn(&mut World)`. /// pub fn my_plugin(app: &mut App) { /// app.add_systems(Update, hello_world); /// } /// # fn hello_world() {} /// ``` -/// +/// /// For more advanced use cases, the `Plugin` trait can be implemented manually for a type. -/// +/// /// ``` /// # use bevy_app::*; /// pub struct AccessibilityPlugin { /// pub flicker_damping: bool, /// // ... /// } -/// +/// /// impl Plugin for AccessibilityPlugin { /// fn build(&self, app: &mut App) { /// if self.flicker_damping { diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 39d1212d88773..d315d4bddf048 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -37,7 +37,7 @@ fn main() { .init_state::() .add_systems(Startup, setup) // Adds the plugins for each state - .add_plugins((splash::SplashPlugin, menu::MenuPlugin, game::GamePlugin)) + .add_plugins((splash::splash_plugin, menu::menu_plugin, game::game_plugin)) .run(); } From 0fdaba6858dd90bda59d498f8c12ee6420997e9b Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:00:54 -0800 Subject: [PATCH 3/6] plurals --- crates/bevy_app/src/plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 4ee19891a5570..c467399fdf5d0 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -24,7 +24,7 @@ use std::any::Any; /// /// ## Defining a plugin. /// -/// Most plugins are simply a function that adds configuration to an [`App`]. +/// Most plugins are simply functions that add configuration to an [`App`]. /// /// ``` /// # use bevy_app::{App, Update}; From 51bfeac66b2f42204aca41afae9cc5156881066a Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:05:25 -0800 Subject: [PATCH 4/6] .run() --- crates/bevy_app/src/plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index c467399fdf5d0..a0cdb4242e91a 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -28,7 +28,7 @@ use std::any::Any; /// /// ``` /// # use bevy_app::{App, Update}; -/// App::new().add_plugins(my_plugin); +/// App::new().add_plugins(my_plugin).run(); /// /// // This function implements `Plugin`, along with every other `fn(&mut World)`. /// pub fn my_plugin(app: &mut App) { From ea07043c9e774215cd27ee815be30ab638bd2b00 Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:07:46 -0800 Subject: [PATCH 5/6] Send + Sync + 'static --- crates/bevy_app/src/plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index a0cdb4242e91a..0e78376026613 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -94,7 +94,7 @@ pub trait Plugin: Downcast + Any + Send + Sync { impl_downcast!(Plugin); -impl Plugin for T { +impl Plugin for T { fn build(&self, app: &mut App) { self(app); } From 64c94f6150bedbab12e8ac657096382bac211730 Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:47:21 -0800 Subject: [PATCH 6/6] Fix a parameter in documentation Co-authored-by: Federico Rinaldi --- crates/bevy_app/src/plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 0e78376026613..edf705447f00a 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -30,7 +30,7 @@ use std::any::Any; /// # use bevy_app::{App, Update}; /// App::new().add_plugins(my_plugin).run(); /// -/// // This function implements `Plugin`, along with every other `fn(&mut World)`. +/// // This function implements `Plugin`, along with every other `fn(&mut App)`. /// pub fn my_plugin(app: &mut App) { /// app.add_systems(Update, hello_world); /// }