Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow tuples and single plugins in add_plugins, deprecate add_plugin #8097

Merged
merged 3 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{
First, Main, MainSchedulePlugin, Plugin, PluginGroup, Startup, StateTransition, Update,
};
use crate::{First, Main, MainSchedulePlugin, Plugin, Plugins, Startup, StateTransition, Update};
pub use bevy_derive::AppLabel;
use bevy_ecs::{
prelude::*,
Expand All @@ -18,6 +16,7 @@ use std::{

#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;

bevy_utils::define_label!(
/// A strongly-typed class of labels used to identify an [`App`].
AppLabel,
Expand Down Expand Up @@ -188,7 +187,7 @@ impl Default for App {
#[cfg(feature = "bevy_reflect")]
app.init_resource::<AppTypeRegistry>();

app.add_plugin(MainSchedulePlugin);
app.add_plugins(MainSchedulePlugin);
app.add_event::<AppExit>();

#[cfg(feature = "bevy_ci_testing")]
Expand Down Expand Up @@ -690,19 +689,16 @@ impl App {
/// # Panics
///
/// Panics if the plugin was already added to the application.
#[deprecated(since = "0.11.0", note = "Please use `add_plugins` instead.")]
pub fn add_plugin<T>(&mut self, plugin: T) -> &mut Self
where
T: Plugin,
{
match self.add_boxed_plugin(Box::new(plugin)) {
Ok(app) => app,
Err(AppError::DuplicatePlugin { plugin_name }) => panic!(
"Error adding plugin {plugin_name}: : plugin was already added in application"
),
}
self.add_plugins(plugin)
}

/// Boxed variant of [`add_plugin`](App::add_plugin) that can be used from a [`PluginGroup`]
/// Boxed variant of [`add_plugin`](App::add_plugin) that can be used from a
/// [`PluginGroup`](super::PluginGroup)
pub(crate) fn add_boxed_plugin(
&mut self,
plugin: Box<dyn Plugin>,
Expand Down Expand Up @@ -757,7 +753,7 @@ impl App {
/// # fn build(&self, app: &mut App) {}
/// # }
/// # let mut app = App::new();
/// # app.add_plugin(ImagePlugin::default());
/// # app.add_plugins(ImagePlugin::default());
/// let default_sampler = app.get_added_plugins::<ImagePlugin>()[0].default_sampler;
/// ```
pub fn get_added_plugins<T>(&self) -> Vec<&T>
Expand All @@ -770,31 +766,46 @@ impl App {
.collect()
}

/// Adds a group of [`Plugin`]s.
/// Adds one or more [`Plugin`]s.
///
/// One of Bevy's core principles is modularity. All Bevy engine features are implemented
/// as [`Plugin`]s. This includes internal features like the renderer.
///
/// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`].
///
/// There are built-in [`PluginGroup`]s that provide core engine functionality.
/// 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
/// [`PluginGroup`]s. See [`Plugins`] for more details.
///
/// ## 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.
pub fn add_plugins<T: PluginGroup>(&mut self, group: T) -> &mut Self {
let builder = group.build();
builder.finish(self);
/// Panics if one of the plugins was already added to the application.
///
/// [`PluginGroup`]:super::PluginGroup
pub fn add_plugins<M>(&mut self, plugins: impl Plugins<M>) -> &mut Self {
plugins.add_to_app(self);
self
}

Expand Down Expand Up @@ -1011,23 +1022,23 @@ mod tests {

#[test]
fn can_add_two_plugins() {
App::new().add_plugin(PluginA).add_plugin(PluginB);
App::new().add_plugins((PluginA, PluginB));
}

#[test]
#[should_panic]
fn cant_add_twice_the_same_plugin() {
App::new().add_plugin(PluginA).add_plugin(PluginA);
App::new().add_plugins((PluginA, PluginA));
}

#[test]
fn can_add_twice_the_same_plugin_with_different_type_param() {
App::new().add_plugin(PluginC(0)).add_plugin(PluginC(true));
App::new().add_plugins((PluginC(0), PluginC(true)));
}

#[test]
fn can_add_twice_the_same_plugin_not_unique() {
App::new().add_plugin(PluginD).add_plugin(PluginD);
App::new().add_plugins((PluginD, PluginD));
}

#[test]
Expand All @@ -1040,10 +1051,10 @@ mod tests {
}
impl Plugin for PluginRun {
fn build(&self, app: &mut crate::App) {
app.add_plugin(InnerPlugin).run();
app.add_plugins(InnerPlugin).run();
}
}
App::new().add_plugin(PluginRun);
App::new().add_plugins(PluginRun);
}

#[derive(States, PartialEq, Eq, Debug, Default, Hash, Clone)]
Expand Down
58 changes: 58 additions & 0 deletions crates/bevy_app/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,61 @@ impl_downcast!(Plugin);
///
/// See `bevy_dynamic_plugin/src/loader.rs#dynamically_load_plugin`.
pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;

/// Types that represent a set of [`Plugin`]s.
///
/// This is implemented for all types which implement [`Plugin`],
/// [`PluginGroup`](super::PluginGroup), and tuples over [`Plugins`].
pub trait Plugins<Marker>: sealed::Plugins<Marker> {}

impl<Marker, T> Plugins<Marker> for T where T: sealed::Plugins<Marker> {}

mod sealed {

use bevy_ecs::all_tuples;

use crate::{App, AppError, Plugin, PluginGroup};

pub trait Plugins<Marker> {
fn add_to_app(self, app: &mut App);
}

pub struct PluginMarker;
pub struct PluginGroupMarker;
pub struct PluginsTupleMarker;

impl<P: Plugin> Plugins<PluginMarker> for P {
fn add_to_app(self, app: &mut App) {
if let Err(AppError::DuplicatePlugin { plugin_name }) =
app.add_boxed_plugin(Box::new(self))
{
panic!(
"Error adding plugin {plugin_name}: : plugin was already added in application"
)
}
}
}

impl<P: PluginGroup> Plugins<PluginGroupMarker> for P {
fn add_to_app(self, app: &mut App) {
self.build().finish(app);
}
}

macro_rules! impl_plugins_tuples {
($(($param: ident, $plugins: ident)),*) => {
impl<$($param, $plugins),*> Plugins<(PluginsTupleMarker, $($param,)*)> for ($($plugins,)*)
where
$($plugins: Plugins<$param>),*
{
#[allow(non_snake_case, unused_variables)]
fn add_to_app(self, app: &mut App) {
let ($($plugins,)*) = self;
$($plugins.add_to_app(app);)*
}
}
}
}

all_tuples!(impl_plugins_tuples, 0, 15, P, S);
}
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct AssetServerInternal {
/// # use bevy_utils::Duration;
/// # let mut app = App::new();
/// // The asset plugin can be configured to watch for asset changes.
/// app.add_plugin(AssetPlugin {
/// app.add_plugins(AssetPlugin {
/// watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)),
/// ..Default::default()
/// });
Expand Down
8 changes: 5 additions & 3 deletions crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,11 @@ mod tests {
#[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"]
struct MyAsset;
let mut app = App::new();
app.add_plugin(bevy_core::TaskPoolPlugin::default())
.add_plugin(bevy_core::TypeRegistrationPlugin::default())
.add_plugin(crate::AssetPlugin::default());
app.add_plugins((
bevy_core::TaskPoolPlugin::default(),
bevy_core::TypeRegistrationPlugin::default(),
crate::AssetPlugin::default(),
));
app.add_asset::<MyAsset>();
let mut assets_before = app.world.resource_mut::<Assets<MyAsset>>();
let handle = assets_before.add(MyAsset);
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/debug_asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Plugin for DebugAssetServerPlugin {
.build()
});
let mut debug_asset_app = App::new();
debug_asset_app.add_plugin(AssetPlugin {
debug_asset_app.add_plugins(AssetPlugin {
asset_folder: "crates".to_string(),
watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)),
});
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ mod tests {
#[test]
fn test_reflect_asset_operations() {
let mut app = App::new();
app.add_plugin(AssetPlugin::default())
app.add_plugins(AssetPlugin::default())
.add_asset::<AssetType>()
.register_asset_reflect::<AssetType>();

Expand Down
4 changes: 1 addition & 3 deletions crates/bevy_audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
//! # use bevy_app::{App, AppExit, NoopPluginGroup as MinimalPlugins, Startup};
//! fn main() {
//! App::new()
//! .add_plugins(MinimalPlugins)
//! .add_plugin(AssetPlugin::default())
//! .add_plugin(AudioPlugin::default())
//! .add_plugins((MinimalPlugins, AssetPlugin::default(), AudioPlugin::default()))
//! .add_systems(Startup, play_background_audio)
//! .run();
//! }
Expand Down
11 changes: 6 additions & 5 deletions crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ mod tests {
#[test]
fn runs_spawn_local_tasks() {
let mut app = App::new();
app.add_plugin(TaskPoolPlugin::default());
app.add_plugin(TypeRegistrationPlugin::default());
app.add_plugins((TaskPoolPlugin::default(), TypeRegistrationPlugin::default()));

let (async_tx, async_rx) = crossbeam_channel::unbounded();
AsyncComputeTaskPool::get()
Expand Down Expand Up @@ -199,9 +198,11 @@ mod tests {
#[test]
fn frame_counter_update() {
let mut app = App::new();
app.add_plugin(TaskPoolPlugin::default());
app.add_plugin(TypeRegistrationPlugin::default());
app.add_plugin(FrameCountPlugin::default());
app.add_plugins((
TaskPoolPlugin::default(),
TypeRegistrationPlugin::default(),
FrameCountPlugin::default(),
));
app.update();

let frame_count = app.world.resource::<FrameCount>();
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_core_pipeline/src/bloom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ impl Plugin for BloomPlugin {
app.register_type::<BloomSettings>();
app.register_type::<BloomPrefilterSettings>();
app.register_type::<BloomCompositeMode>();
app.add_plugin(ExtractComponentPlugin::<BloomSettings>::default());
app.add_plugin(UniformComponentPlugin::<BloomUniforms>::default());
app.add_plugins((
ExtractComponentPlugin::<BloomSettings>::default(),
UniformComponentPlugin::<BloomUniforms>::default(),
));

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ impl Plugin for CASPlugin {
);

app.register_type::<ContrastAdaptiveSharpeningSettings>();
app.add_plugin(ExtractComponentPlugin::<ContrastAdaptiveSharpeningSettings>::default());
app.add_plugin(UniformComponentPlugin::<CASUniform>::default());
app.add_plugins((
ExtractComponentPlugin::<ContrastAdaptiveSharpeningSettings>::default(),
UniformComponentPlugin::<CASUniform>::default(),
));

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct Core2dPlugin;
impl Plugin for Core2dPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Camera2d>()
.add_plugin(ExtractComponentPlugin::<Camera2d>::default());
.add_plugins(ExtractComponentPlugin::<Camera2d>::default());

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ impl Plugin for Core3dPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Camera3d>()
.register_type::<Camera3dDepthLoadOp>()
.add_plugin(SkyboxPlugin)
.add_plugin(ExtractComponentPlugin::<Camera3d>::default());
.add_plugins((SkyboxPlugin, ExtractComponentPlugin::<Camera3d>::default()));

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/fxaa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Plugin for FxaaPlugin {
load_internal_asset!(app, FXAA_SHADER_HANDLE, "fxaa.wgsl", Shader::from_wgsl);

app.register_type::<Fxaa>();
app.add_plugin(ExtractComponentPlugin::<Fxaa>::default());
app.add_plugins(ExtractComponentPlugin::<Fxaa>::default());

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
22 changes: 12 additions & 10 deletions crates/bevy_core_pipeline/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,17 @@ impl Plugin for CorePipelinePlugin {
.register_type::<DepthPrepass>()
.register_type::<NormalPrepass>()
.init_resource::<ClearColor>()
.add_plugin(ExtractResourcePlugin::<ClearColor>::default())
.add_plugin(Core2dPlugin)
.add_plugin(Core3dPlugin)
.add_plugin(BlitPlugin)
.add_plugin(MsaaWritebackPlugin)
.add_plugin(TonemappingPlugin)
.add_plugin(UpscalingPlugin)
.add_plugin(BloomPlugin)
.add_plugin(FxaaPlugin)
.add_plugin(CASPlugin);
.add_plugins((
ExtractResourcePlugin::<ClearColor>::default(),
Core2dPlugin,
Core3dPlugin,
BlitPlugin,
MsaaWritebackPlugin,
TonemappingPlugin,
UpscalingPlugin,
BloomPlugin,
FxaaPlugin,
CASPlugin,
));
}
}
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/skybox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Plugin for SkyboxPlugin {
fn build(&self, app: &mut App) {
load_internal_asset!(app, SKYBOX_SHADER_HANDLE, "skybox.wgsl", Shader::from_wgsl);

app.add_plugin(ExtractComponentPlugin::<Skybox>::default());
app.add_plugins(ExtractComponentPlugin::<Skybox>::default());

let render_app = match app.get_sub_app_mut(RenderApp) {
Ok(render_app) => render_app,
Expand Down
Loading