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`].
/// This stores and provides access to all the main data of the application.
/// 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,
/// The [runner function](Self::set_runner) is primarily responsible for managing
/// the application's event loop and advancing the [`Schedule`].
@ -94,7 +94,7 @@ impl Debug for App {
/// # Example
///
/// ```rust
/// # use bevy_app::{App, AppLabel};
/// # use bevy_app::{App, AppLabel, SubApp};
/// # use bevy_ecs::prelude::*;
///
/// #[derive(Resource, Default)]
@ -122,9 +122,9 @@ impl Debug for App {
/// sub_app.add_stage(ExampleStage, example_stage);
///
/// // 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;
/// });
/// }));
///
/// // This will run the schedules once, since we're using the default runner
/// 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
/// 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 {
/// 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.
pub fn run(&mut self) {
self.app.schedule.run(&mut self.app.world);
@ -204,7 +217,7 @@ impl App {
///
/// 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) {
{
#[cfg(feature = "trace")]
@ -1081,28 +1094,6 @@ impl App {
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`].
///
/// # Panics

View file

@ -50,7 +50,7 @@ use crate::{
settings::WgpuSettings,
view::{ViewPlugin, WindowRenderPlugin},
};
use bevy_app::{App, AppLabel, Plugin};
use bevy_app::{App, AppLabel, Plugin, SubApp};
use bevy_asset::{AddAsset, AssetServer};
use bevy_ecs::{prelude::*, system::SystemState};
use bevy_utils::tracing::debug;
@ -231,7 +231,7 @@ impl Plugin for RenderPlugin {
app.insert_resource(receiver);
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")]
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(app_world, render_app);
}
});
}));
}
app.add_plugin(ValidParentCheckPlugin::<view::ComputedVisibility>::default())

View file

@ -82,7 +82,7 @@ impl Plugin for PipelinedRenderingPlugin {
RenderExtractStage::BeforeIoAfterRenderStart,
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.