From 7551e547bc2938c8c76de2b0bcac6354d2f934d3 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Wed, 15 Feb 2023 13:21:29 +0100 Subject: [PATCH 01/12] Add add method to App --- crates/bevy_app/src/app.rs | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index b3aaaf7c952c8..f852b9930365c 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1002,6 +1002,42 @@ impl App { self } + + /// TODO: Docs + pub fn add, M>(&mut self, value: V) -> &mut Self { + value.add_to(self); + self + } +} + +mod sealed { + use crate::{App, Plugin, PluginGroup}; + + pub trait Add { + fn add_to(self, app: &mut App); + } + + pub struct IsPlugin; + pub struct IsPluginGroup; + pub struct IsFunction; + + impl Add for P { + fn add_to(self, app: &mut App) { + app.add_plugin(self); + } + } + + impl Add for P { + fn add_to(self, app: &mut App) { + app.add_plugins(self); + } + } + + impl Add for F { + fn add_to(self, app: &mut App) { + self(app) + } + } } fn run_once(mut app: App) { @@ -1077,4 +1113,30 @@ mod tests { } App::new().add_plugin(PluginRun); } + + // Just for Demonstration purposes, will be removed + #[test] + fn logger_example() { + use bevy_ecs::system::Resource; + #[derive(Resource)] + struct Loggers; + + struct LoggerPlugin; + + impl LoggerPlugin { + fn with_loggers(loggers: Loggers) -> impl FnOnce(&mut App) { + |app| { + app.insert_resource::(loggers).add(LoggerPlugin); + } + } + } + + impl Plugin for LoggerPlugin { + fn build(&self, app: &mut App) { + let _loggers = app.world.remove_resource::(); + } + } + + App::new().add(LoggerPlugin::with_loggers(Loggers)).run(); + } } From e3910157dc1a9953b507492a76197bd371c0275b Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Wed, 15 Feb 2023 13:56:56 +0100 Subject: [PATCH 02/12] Fix clippy warning --- crates/bevy_app/src/app.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index f852b9930365c..b8389e71b4383 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1035,7 +1035,7 @@ mod sealed { impl Add for F { fn add_to(self, app: &mut App) { - self(app) + self(app); } } } @@ -1126,7 +1126,7 @@ mod tests { impl LoggerPlugin { fn with_loggers(loggers: Loggers) -> impl FnOnce(&mut App) { |app| { - app.insert_resource::(loggers).add(LoggerPlugin); + app.insert_resource(loggers).add(LoggerPlugin); } } } From 59bb5dd48b5309074b3568786457bd290624f82c Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Wed, 15 Feb 2023 16:29:15 +0100 Subject: [PATCH 03/12] Replace Add with IntoPlugin and IntoPluginGroup traits --- crates/bevy_app/src/app.rs | 105 ++++++++++++++++++++-------- crates/bevy_app/src/plugin_group.rs | 33 +++++++++ 2 files changed, 109 insertions(+), 29 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index b8389e71b4383..1b419248d2eba 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,4 +1,4 @@ -use crate::{CoreSchedule, CoreSet, Plugin, PluginGroup, StartupSet}; +use crate::{CoreSchedule, CoreSet, Plugin, StartupSet}; pub use bevy_derive::AppLabel; use bevy_ecs::{ prelude::*, @@ -13,6 +13,8 @@ use std::fmt::Debug; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; + +use self::sealed::{IntoPlugin, IntoPluginGroup}; bevy_utils::define_label!( /// A strongly-typed class of labels used to identify an [`App`]. AppLabel, @@ -742,11 +744,9 @@ impl App { /// # Panics /// /// Panics if the plugin was already added to the application. - pub fn add_plugin(&mut self, plugin: T) -> &mut Self - where - T: Plugin, - { - match self.add_boxed_plugin(Box::new(plugin)) { + pub fn add_plugin

(&mut self, plugin: impl IntoPlugin

) -> &mut Self { + let plugin = Box::new(plugin.into_plugin(self)); + match self.add_boxed_plugin(plugin) { Ok(app) => app, Err(AppError::DuplicatePlugin { plugin_name }) => panic!( "Error adding plugin {plugin_name}: : plugin was already added in application" @@ -836,8 +836,8 @@ impl App { /// # Panics /// /// Panics if one of the plugin in the group was already added to the application. - pub fn add_plugins(&mut self, group: T) -> &mut Self { - let builder = group.build(); + pub fn add_plugins

(&mut self, group: impl IntoPluginGroup

) -> &mut Self { + let builder = group.into_plugin_group_builder(self); builder.finish(self); self } @@ -1002,42 +1002,86 @@ impl App { self } - - /// TODO: Docs - pub fn add, M>(&mut self, value: V) -> &mut Self { - value.add_to(self); - self - } } mod sealed { - use crate::{App, Plugin, PluginGroup}; + use bevy_ecs::all_tuples; - pub trait Add { - fn add_to(self, app: &mut App); + use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; + + pub trait IntoPlugin { + type Plugin: Plugin; + fn into_plugin(self, app: &mut App) -> Self::Plugin; + } + + pub trait IntoPluginGroup: IntoPluginGroupBuilder {} + + pub trait IntoPluginGroupBuilder { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; } pub struct IsPlugin; pub struct IsPluginGroup; pub struct IsFunction; - impl Add for P { - fn add_to(self, app: &mut App) { - app.add_plugin(self); + impl IntoPlugin for P { + type Plugin = Self; + fn into_plugin(self, _: &mut App) -> Self { + self + } + } + + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + PluginGroupBuilder::from_plugin(self) } } - impl Add for P { - fn add_to(self, app: &mut App) { - app.add_plugins(self); + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + self.build() } } - impl Add for F { - fn add_to(self, app: &mut App) { - self(app); + impl IntoPluginGroup for P {} + + impl P, P: Plugin> IntoPlugin for F { + type Plugin = P; + + fn into_plugin(self, app: &mut App) -> Self::Plugin { + self(app) } } + + impl PG, PG: PluginGroup> IntoPluginGroupBuilder for F { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + self(app).build() + } + } + + impl PG, PG: PluginGroup> IntoPluginGroup for F {} + + macro_rules! impl_plugin_collection { + ($(($param: ident, $plugins: ident)),*) => { + impl<$($param, $plugins),*> IntoPluginGroupBuilder<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + { + #[allow(non_snake_case, unused_variables)] + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + let ($($plugins,)*) = self; + PluginGroupBuilder::merge(vec![$($plugins.into_plugin_group_builder(app),)*]) + } + } + + impl<$($param, $plugins),*> IntoPluginGroup<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + {} + } + } + + all_tuples!(impl_plugin_collection, 0, 15, P, S); } fn run_once(mut app: App) { @@ -1124,9 +1168,10 @@ mod tests { struct LoggerPlugin; impl LoggerPlugin { - fn with_loggers(loggers: Loggers) -> impl FnOnce(&mut App) { + fn with_loggers(loggers: Loggers) -> impl FnOnce(&mut App) -> LoggerPlugin { |app| { - app.insert_resource(loggers).add(LoggerPlugin); + app.insert_resource(loggers); + LoggerPlugin } } } @@ -1137,6 +1182,8 @@ mod tests { } } - App::new().add(LoggerPlugin::with_loggers(Loggers)).run(); + App::new() + .add_plugin(LoggerPlugin::with_loggers(Loggers)) + .run(); } } diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index d5c7be8dcb602..0617e3d20da46 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -47,6 +47,39 @@ impl PluginGroupBuilder { } } + pub(crate) fn from_plugin(plugin: P) -> Self { + Self { + group_name: plugin.name().to_string(), + plugins: Default::default(), + order: Default::default(), + } + .add(plugin) + } + + pub(crate) fn merge(builders: Vec) -> Self { + let mut group_name = "(".to_string(); + let mut plugins = HashMap::new(); + let mut order = Vec::new(); + let mut first = true; + for mut builder in builders { + if first { + first = false; + } else { + group_name += ", "; + } + for (type_id, entry) in builder.plugins { + plugins.insert(type_id, entry); + } + order.append(&mut builder.order); + } + group_name += ")"; + Self { + group_name, + plugins, + order, + } + } + /// Finds the index of a target [`Plugin`]. Panics if the target's [`TypeId`] is not found. fn index_of(&self) -> usize { let index = self From d98078d64b1c7e50ae585df0c54dca7cfd40fc7e Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Wed, 15 Feb 2023 21:53:11 +0100 Subject: [PATCH 04/12] Move sealed module from app to plugin --- crates/bevy_app/src/app.rs | 82 +---------------------------------- crates/bevy_app/src/plugin.rs | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 1b419248d2eba..30b51ffaeece2 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -14,7 +14,7 @@ use std::fmt::Debug; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -use self::sealed::{IntoPlugin, IntoPluginGroup}; +use super::sealed::{IntoPlugin, IntoPluginGroup}; bevy_utils::define_label!( /// A strongly-typed class of labels used to identify an [`App`]. AppLabel, @@ -1004,86 +1004,6 @@ impl App { } } -mod sealed { - use bevy_ecs::all_tuples; - - use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; - - pub trait IntoPlugin { - type Plugin: Plugin; - fn into_plugin(self, app: &mut App) -> Self::Plugin; - } - - pub trait IntoPluginGroup: IntoPluginGroupBuilder {} - - pub trait IntoPluginGroupBuilder { - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; - } - - pub struct IsPlugin; - pub struct IsPluginGroup; - pub struct IsFunction; - - impl IntoPlugin for P { - type Plugin = Self; - fn into_plugin(self, _: &mut App) -> Self { - self - } - } - - impl IntoPluginGroupBuilder for P { - fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { - PluginGroupBuilder::from_plugin(self) - } - } - - impl IntoPluginGroupBuilder for P { - fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { - self.build() - } - } - - impl IntoPluginGroup for P {} - - impl P, P: Plugin> IntoPlugin for F { - type Plugin = P; - - fn into_plugin(self, app: &mut App) -> Self::Plugin { - self(app) - } - } - - impl PG, PG: PluginGroup> IntoPluginGroupBuilder for F { - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { - self(app).build() - } - } - - impl PG, PG: PluginGroup> IntoPluginGroup for F {} - - macro_rules! impl_plugin_collection { - ($(($param: ident, $plugins: ident)),*) => { - impl<$($param, $plugins),*> IntoPluginGroupBuilder<($($param,)*)> for ($($plugins,)*) - where - $($plugins: IntoPluginGroupBuilder<$param>),* - { - #[allow(non_snake_case, unused_variables)] - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { - let ($($plugins,)*) = self; - PluginGroupBuilder::merge(vec![$($plugins.into_plugin_group_builder(app),)*]) - } - } - - impl<$($param, $plugins),*> IntoPluginGroup<($($param,)*)> for ($($plugins,)*) - where - $($plugins: IntoPluginGroupBuilder<$param>),* - {} - } - } - - all_tuples!(impl_plugin_collection, 0, 15, P, S); -} - fn run_once(mut app: App) { app.update(); } diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 8120bc9be5aab..3fb817e56e21d 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -44,3 +44,83 @@ impl_downcast!(Plugin); /// /// See `bevy_dynamic_plugin/src/loader.rs#dynamically_load_plugin`. pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin; + +pub(super) mod sealed { + use bevy_ecs::all_tuples; + + use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; + + pub trait IntoPlugin { + type Plugin: Plugin; + fn into_plugin(self, app: &mut App) -> Self::Plugin; + } + + pub trait IntoPluginGroup: IntoPluginGroupBuilder {} + + pub trait IntoPluginGroupBuilder { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; + } + + pub struct IsPlugin; + pub struct IsPluginGroup; + pub struct IsFunction; + + impl IntoPlugin for P { + type Plugin = Self; + fn into_plugin(self, _: &mut App) -> Self { + self + } + } + + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + PluginGroupBuilder::from_plugin(self) + } + } + + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + self.build() + } + } + + impl IntoPluginGroup for P {} + + impl P, P: Plugin> IntoPlugin for F { + type Plugin = P; + + fn into_plugin(self, app: &mut App) -> Self::Plugin { + self(app) + } + } + + impl PG, PG: PluginGroup> IntoPluginGroupBuilder for F { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + self(app).build() + } + } + + impl PG, PG: PluginGroup> IntoPluginGroup for F {} + + macro_rules! impl_plugin_collection { + ($(($param: ident, $plugins: ident)),*) => { + impl<$($param, $plugins),*> IntoPluginGroupBuilder<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + { + #[allow(non_snake_case, unused_variables)] + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + let ($($plugins,)*) = self; + PluginGroupBuilder::merge(vec![$($plugins.into_plugin_group_builder(app),)*]) + } + } + + impl<$($param, $plugins),*> IntoPluginGroup<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + {} + } + } + + all_tuples!(impl_plugin_collection, 0, 15, P, S); +} From 5d1b64664a425adad560b5bc3b7641e22f37e57e Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Wed, 15 Feb 2023 21:56:15 +0100 Subject: [PATCH 05/12] Rename Marker to Params --- crates/bevy_app/src/plugin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 3fb817e56e21d..a4fb239cb4600 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -50,14 +50,14 @@ pub(super) mod sealed { use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; - pub trait IntoPlugin { + pub trait IntoPlugin { type Plugin: Plugin; fn into_plugin(self, app: &mut App) -> Self::Plugin; } - pub trait IntoPluginGroup: IntoPluginGroupBuilder {} + pub trait IntoPluginGroup: IntoPluginGroupBuilder {} - pub trait IntoPluginGroupBuilder { + pub trait IntoPluginGroupBuilder { fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; } From 54e0163a10f8ea896cf4581734dec9bb894759cf Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 00:26:14 +0100 Subject: [PATCH 06/12] Move PluginGroup related traits from plugin to plugin_group --- crates/bevy_app/src/plugin.rs | 54 +------------------------- crates/bevy_app/src/plugin_group.rs | 60 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index a4fb239cb4600..197614e3da7b6 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -46,23 +46,15 @@ impl_downcast!(Plugin); pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin; pub(super) mod sealed { - use bevy_ecs::all_tuples; - use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; + use crate::{App, Plugin}; pub trait IntoPlugin { type Plugin: Plugin; fn into_plugin(self, app: &mut App) -> Self::Plugin; } - pub trait IntoPluginGroup: IntoPluginGroupBuilder {} - - pub trait IntoPluginGroupBuilder { - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; - } - pub struct IsPlugin; - pub struct IsPluginGroup; pub struct IsFunction; impl IntoPlugin for P { @@ -72,20 +64,6 @@ pub(super) mod sealed { } } - impl IntoPluginGroupBuilder for P { - fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { - PluginGroupBuilder::from_plugin(self) - } - } - - impl IntoPluginGroupBuilder for P { - fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { - self.build() - } - } - - impl IntoPluginGroup for P {} - impl P, P: Plugin> IntoPlugin for F { type Plugin = P; @@ -93,34 +71,4 @@ pub(super) mod sealed { self(app) } } - - impl PG, PG: PluginGroup> IntoPluginGroupBuilder for F { - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { - self(app).build() - } - } - - impl PG, PG: PluginGroup> IntoPluginGroup for F {} - - macro_rules! impl_plugin_collection { - ($(($param: ident, $plugins: ident)),*) => { - impl<$($param, $plugins),*> IntoPluginGroupBuilder<($($param,)*)> for ($($plugins,)*) - where - $($plugins: IntoPluginGroupBuilder<$param>),* - { - #[allow(non_snake_case, unused_variables)] - fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { - let ($($plugins,)*) = self; - PluginGroupBuilder::merge(vec![$($plugins.into_plugin_group_builder(app),)*]) - } - } - - impl<$($param, $plugins),*> IntoPluginGroup<($($param,)*)> for ($($plugins,)*) - where - $($plugins: IntoPluginGroupBuilder<$param>),* - {} - } - } - - all_tuples!(impl_plugin_collection, 0, 15, P, S); } diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index 0617e3d20da46..cec1dd7751677 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -225,6 +225,66 @@ impl PluginGroupBuilder { } } +pub(super) mod sealed { + use bevy_ecs::all_tuples; + + use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; + + pub trait IntoPluginGroup: IntoPluginGroupBuilder {} + + pub trait IntoPluginGroupBuilder { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder; + } + + pub struct IsPlugin; + pub struct IsPluginGroup; + pub struct IsFunction; + + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + PluginGroupBuilder::from_plugin(self) + } + } + + impl IntoPluginGroupBuilder for P { + fn into_plugin_group_builder(self, _: &mut App) -> PluginGroupBuilder { + self.build() + } + } + + impl IntoPluginGroup for P {} + + impl PG, PG: PluginGroup> IntoPluginGroupBuilder for F { + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + self(app).build() + } + } + + impl PG, PG: PluginGroup> IntoPluginGroup for F {} + + macro_rules! impl_plugin_collection { + ($(($param: ident, $plugins: ident)),*) => { + impl<$($param, $plugins),*> IntoPluginGroupBuilder<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + { + #[allow(non_snake_case, unused_variables)] + fn into_plugin_group_builder(self, app: &mut App) -> PluginGroupBuilder { + let ($($plugins,)*) = self; + PluginGroupBuilder::merge(vec![$($plugins.into_plugin_group_builder(app),)*]) + } + } + + impl<$($param, $plugins),*> IntoPluginGroup<($($param,)*)> for ($($plugins,)*) + where + $($plugins: IntoPluginGroupBuilder<$param>),* + {} + } + } + + all_tuples!(impl_plugin_collection, 0, 15, P, S); +} + /// A plugin group which doesn't do anything. Useful for examples: /// ```rust /// # use bevy_app::prelude::*; From a866f6b04731e1611257c6c4ca0c259bf3d5f3f4 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 00:44:27 +0100 Subject: [PATCH 07/12] Document traits --- crates/bevy_app/src/app.rs | 3 +-- crates/bevy_app/src/plugin.rs | 10 +++++++++- crates/bevy_app/src/plugin_group.rs | 11 ++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 30b51ffaeece2..23a64b111a38e 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,4 +1,4 @@ -use crate::{CoreSchedule, CoreSet, Plugin, StartupSet}; +use crate::{CoreSchedule, CoreSet, IntoPlugin, IntoPluginGroup, Plugin, StartupSet}; pub use bevy_derive::AppLabel; use bevy_ecs::{ prelude::*, @@ -14,7 +14,6 @@ use std::fmt::Debug; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -use super::sealed::{IntoPlugin, IntoPluginGroup}; bevy_utils::define_label!( /// A strongly-typed class of labels used to identify an [`App`]. AppLabel, diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 197614e3da7b6..126950744da32 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -45,7 +45,15 @@ impl_downcast!(Plugin); /// See `bevy_dynamic_plugin/src/loader.rs#dynamically_load_plugin`. pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin; -pub(super) mod sealed { +/// Types that can be converted into a [`Plugin`]. +/// +/// This is implemented for all types which implement [`Plugin`] or +/// [`FnOnce(&mut App) -> impl Plugin`](FnOnce). +pub trait IntoPlugin: sealed::IntoPlugin {} + +impl IntoPlugin for T where T: sealed::IntoPlugin {} + +mod sealed { use crate::{App, Plugin}; diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index cec1dd7751677..bfed8a4866967 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -225,7 +225,16 @@ impl PluginGroupBuilder { } } -pub(super) mod sealed { +/// Types that can be converted into a [`PluginGroup`]. +/// +/// This is implemented for all types which implement [`PluginGroup`] or +/// [`FnOnce(&mut App) -> impl PluginGroup`](FnOnce) and for tuples over types that implement +/// [`IntoPlugin`](super::IntoPlugin) or [`IntoPluginGroup`]. +pub trait IntoPluginGroup: sealed::IntoPluginGroup {} + +impl IntoPluginGroup for T where T: sealed::IntoPluginGroup {} + +mod sealed { use bevy_ecs::all_tuples; use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; From 1bac3e65d833db4b8af4679246ff3d4829877b67 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 00:45:08 +0100 Subject: [PATCH 08/12] Fix and expand `add_plugins` documentation --- crates/bevy_app/src/app.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 23a64b111a38e..0577a6da0e8e1 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -824,17 +824,30 @@ impl App { /// before / after another plugin), call [`build()`](PluginGroup::build) on the group, /// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder). /// + /// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and + /// [`PluginGroup`]s. + /// /// ## Examples /// ``` /// # use bevy_app::{prelude::*, PluginGroupBuilder, NoopPluginGroup as MinimalPlugins}; /// # + /// # // Dummies created to avoid using `bevy_log`, + /// # // which pulls in too many dependencies and breaks rust-analyzer + /// # pub struct LogPlugin; + /// # impl Plugin for LogPlugin { + /// # fn build(&self, app: &mut App) {} + /// # } /// App::new() /// .add_plugins(MinimalPlugins); + /// App::new() + /// .add_plugins((MinimalPlugins, LogPlugin)); /// ``` /// /// # Panics /// /// Panics if one of the plugin in the group was already added to the application. + /// + /// [`PluginGroup`]:super::PluginGroup pub fn add_plugins

(&mut self, group: impl IntoPluginGroup

) -> &mut Self { let builder = group.into_plugin_group_builder(self); builder.finish(self); From d01a3a8c2df2e395d47016195b3c075a7fcd3625 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 00:48:24 +0100 Subject: [PATCH 09/12] Rename logger_example test --- crates/bevy_app/src/app.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 0577a6da0e8e1..2bac56bb2e622 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1090,9 +1090,8 @@ mod tests { App::new().add_plugin(PluginRun); } - // Just for Demonstration purposes, will be removed #[test] - fn logger_example() { + fn add_plugin_via_factory_fn() { use bevy_ecs::system::Resource; #[derive(Resource)] struct Loggers; From f7d0398681206dfaa2b8aea6b30f32789c266087 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 00:54:10 +0100 Subject: [PATCH 10/12] Add test for adding multiple plugins at once --- crates/bevy_app/src/app.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 2bac56bb2e622..31f1d6f0396ea 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1035,7 +1035,7 @@ pub struct AppExit; #[cfg(test)] mod tests { - use crate::{App, Plugin}; + use crate::{App, Plugin, PluginGroup, PluginGroupBuilder}; struct PluginA; impl Plugin for PluginA { @@ -1057,6 +1057,15 @@ mod tests { } } + struct PluginGroupAB; + impl PluginGroup for PluginGroupAB { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + .add(PluginA) + .add(PluginB) + } + } + #[test] fn can_add_two_plugins() { App::new().add_plugin(PluginA).add_plugin(PluginB); @@ -1117,4 +1126,11 @@ mod tests { .add_plugin(LoggerPlugin::with_loggers(Loggers)) .run(); } + + #[test] + fn add_multiple_plugins_at_once() { + App::new() + .add_plugins((PluginC(()), PluginD, PluginGroupAB, PluginD)) + .run(); + } } From f040c50dcd594d61bb6f9b4a223e9fee8d4019e7 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 11:29:02 +0100 Subject: [PATCH 11/12] Fix rustdoc item link --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 31f1d6f0396ea..fb2a4883d750e 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -753,7 +753,7 @@ impl App { } } - /// Boxed variant of `add_plugin`, can be used from a [`PluginGroup`] + /// Boxed variant of `add_plugin`, can be used from a [`PluginGroup`](super::PluginGroup) pub(crate) fn add_boxed_plugin( &mut self, plugin: Box, From f431271293a9aeb0521b7dca158eb8715dd844dc Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 16 Feb 2023 11:56:49 +0100 Subject: [PATCH 12/12] Fix broken intra-doc-link --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index fb2a4883d750e..14de3c9b54b5f 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -821,7 +821,7 @@ impl App { /// The [`PluginGroup`]s available by default are `DefaultPlugins` and `MinimalPlugins`. /// /// To customize the plugins in the group (reorder, disable a plugin, add a new plugin - /// before / after another plugin), call [`build()`](PluginGroup::build) on the group, + /// before / after another plugin), call [`build()`](super::PluginGroup::build) on the group, /// which will convert it to a [`PluginGroupBuilder`](crate::PluginGroupBuilder). /// /// You can also specify a group of [`Plugin`]s by using a tuple over [`Plugin`]s and