Remove App::add_sub_app (#7290)

# Objective
Fixes #7286. Both `App::add_sub_app` and `App::insert_sub_app` are rather redundant. Before 0.10 is shipped, one of them should be removed.

## Solution
Remove `App::add_sub_app` to prefer `App::insert_sub_app`.

Also hid away `SubApp::extract` since that can be a footgun if someone mutates it for whatever reason. Willing to revert this change if there are objections.

Perhaps we should make `SubApp: Deref<Target=App>`? Might change if we decide to move `!Send` resources into it.

---

## Changelog
Added: `SubApp::new`
Removed: `App::add_sub_app`

## Migration Guide
`App::add_sub_app` has been removed in favor of `App::insert_sub_app`. Use `SubApp::new` and insert it via `App::add_sub_app`

Old:

```rust
let mut sub_app = App::new()
// Build subapp here
app.add_sub_app(MySubAppLabel, sub_app);
```

New:

```rust
let mut sub_app = App::new()
// Build subapp here
app.insert_sub_app(MySubAppLabel, SubApp::new(sub_app, extract_fn));
```
This commit is contained in:
James Liu 2023-01-24 21:24:25 +00:00
parent 3c63c0dab7
commit 958a898b4a
3 changed files with 23 additions and 32 deletions

View File

@ -61,7 +61,7 @@ pub struct App {
/// The main ECS [`World`] of the [`App`]. /// The main ECS [`World`] of the [`App`].
/// This stores and provides access to all the main data of the application. /// This stores and provides access to all the main data of the application.
/// The systems of the [`App`] will run using this [`World`]. /// The systems of the [`App`] will run using this [`World`].
/// If additional separate [`World`]-[`Schedule`] pairs are needed, you can use [`sub_app`](App::add_sub_app)s. /// If additional separate [`World`]-[`Schedule`] pairs are needed, you can use [`sub_app`](App::insert_sub_app)s.
pub world: World, pub world: World,
/// The [runner function](Self::set_runner) is primarily responsible for managing /// The [runner function](Self::set_runner) is primarily responsible for managing
/// the application's event loop and advancing the [`Schedule`]. /// the application's event loop and advancing the [`Schedule`].
@ -94,7 +94,7 @@ impl Debug for App {
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// # use bevy_app::{App, AppLabel}; /// # use bevy_app::{App, AppLabel, SubApp};
/// # use bevy_ecs::prelude::*; /// # use bevy_ecs::prelude::*;
/// ///
/// #[derive(Resource, Default)] /// #[derive(Resource, Default)]
@ -122,9 +122,9 @@ impl Debug for App {
/// sub_app.add_stage(ExampleStage, example_stage); /// sub_app.add_stage(ExampleStage, example_stage);
/// ///
/// // add the sub_app to the app /// // add the sub_app to the app
/// app.add_sub_app(ExampleApp, sub_app, |main_world, sub_app| { /// app.insert_sub_app(ExampleApp, SubApp::new(sub_app, |main_world, sub_app| {
/// sub_app.world.resource_mut::<Val>().0 = main_world.resource::<Val>().0; /// sub_app.world.resource_mut::<Val>().0 = main_world.resource::<Val>().0;
/// }); /// }));
/// ///
/// // This will run the schedules once, since we're using the default runner /// // This will run the schedules once, since we're using the default runner
/// app.run(); /// app.run();
@ -135,10 +135,23 @@ pub struct SubApp {
/// A function that allows access to both the [`SubApp`] [`World`] and the main [`App`]. This is /// A function that allows access to both the [`SubApp`] [`World`] and the main [`App`]. This is
/// useful for moving data between the sub app and the main app. /// useful for moving data between the sub app and the main app.
pub extract: Box<dyn Fn(&mut World, &mut App) + Send>, extract: Box<dyn Fn(&mut World, &mut App) + Send>,
} }
impl SubApp { impl SubApp {
/// Creates a new [`SubApp`].
///
/// The provided function `extract` is normally called by the [`update`](App::update) method.
/// After extract is called, the [`Schedule`] of the sub app is run. The [`World`]
/// parameter represents the main app world, while the [`App`] parameter is just a mutable
/// reference to the `SubApp` itself.
pub fn new(app: App, extract: impl Fn(&mut World, &mut App) + Send + 'static) -> Self {
Self {
app,
extract: Box::new(extract),
}
}
/// Runs the `SubApp`'s schedule. /// Runs the `SubApp`'s schedule.
pub fn run(&mut self) { pub fn run(&mut self) {
self.app.schedule.run(&mut self.app.world); self.app.schedule.run(&mut self.app.world);
@ -204,7 +217,7 @@ impl App {
/// ///
/// This method also updates sub apps. /// This method also updates sub apps.
/// ///
/// See [`add_sub_app`](Self::add_sub_app) and [`run_once`](Schedule::run_once) for more details. /// See [`insert_sub_app`](Self::insert_sub_app) and [`run_once`](Schedule::run_once) for more details.
pub fn update(&mut self) { pub fn update(&mut self) {
{ {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
@ -1081,28 +1094,6 @@ impl App {
self self
} }
/// Adds an [`App`] as a child of the current one.
///
/// The provided function `extract` is normally called by the [`update`](Self::update) method.
/// After extract is called, the [`Schedule`] of the sub app is run. The [`World`]
/// parameter represents the main app world, while the [`App`] parameter is just a mutable
/// reference to the `SubApp` itself.
pub fn add_sub_app(
&mut self,
label: impl AppLabel,
app: App,
extract: impl Fn(&mut World, &mut App) + 'static + Send,
) -> &mut Self {
self.sub_apps.insert(
label.as_label(),
SubApp {
app,
extract: Box::new(extract),
},
);
self
}
/// Retrieves a `SubApp` stored inside this [`App`]. /// Retrieves a `SubApp` stored inside this [`App`].
/// ///
/// # Panics /// # Panics

View File

@ -50,7 +50,7 @@ use crate::{
settings::WgpuSettings, settings::WgpuSettings,
view::{ViewPlugin, WindowRenderPlugin}, view::{ViewPlugin, WindowRenderPlugin},
}; };
use bevy_app::{App, AppLabel, Plugin}; use bevy_app::{App, AppLabel, Plugin, SubApp};
use bevy_asset::{AddAsset, AssetServer}; use bevy_asset::{AddAsset, AssetServer};
use bevy_ecs::{prelude::*, system::SystemState}; use bevy_ecs::{prelude::*, system::SystemState};
use bevy_utils::tracing::debug; use bevy_utils::tracing::debug;
@ -231,7 +231,7 @@ impl Plugin for RenderPlugin {
app.insert_resource(receiver); app.insert_resource(receiver);
render_app.insert_resource(sender); render_app.insert_resource(sender);
app.add_sub_app(RenderApp, render_app, move |app_world, render_app| { app.insert_sub_app(RenderApp, SubApp::new(render_app, move |app_world, render_app| {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _render_span = bevy_utils::tracing::info_span!("extract main app to render subapp").entered(); let _render_span = bevy_utils::tracing::info_span!("extract main app to render subapp").entered();
{ {
@ -267,7 +267,7 @@ impl Plugin for RenderPlugin {
// extract // extract
extract(app_world, render_app); extract(app_world, render_app);
} }
}); }));
} }
app.add_plugin(ValidParentCheckPlugin::<view::ComputedVisibility>::default()) app.add_plugin(ValidParentCheckPlugin::<view::ComputedVisibility>::default())

View File

@ -82,7 +82,7 @@ impl Plugin for PipelinedRenderingPlugin {
RenderExtractStage::BeforeIoAfterRenderStart, RenderExtractStage::BeforeIoAfterRenderStart,
SystemStage::parallel(), SystemStage::parallel(),
); );
app.add_sub_app(RenderExtractApp, sub_app, update_rendering); app.insert_sub_app(RenderExtractApp, SubApp::new(sub_app, update_rendering));
} }
// Sets up the render thread and inserts resources into the main app used for controlling the render thread. // Sets up the render thread and inserts resources into the main app used for controlling the render thread.