feat(bevy_app): expose an API to perform updates for a specific sub-app. (#14009)

# Objective

- Fixes https://github.com/bevyengine/bevy/issues/14003

## Solution

- Expose an API to perform updates for a specific sub-app, so we can
avoid mutable borrow the app twice.

## Testing

- I have tested the API by modifying the code in the `many_lights`
example with the following changes:
```rust
impl Plugin for LogVisibleLights {
    fn build(&self, app: &mut App) {
        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
            return;
        };

        render_app.add_systems(Render, print_visible_light_count.in_set(RenderSet::Prepare));
    }

    fn finish(&self, app: &mut App) {
        app.update_sub_app_by_label(RenderApp);
    }
}
```

---

## Changelog
- add the `update_sub_app_by_label` API to `App` and `SubApps`.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
This commit is contained in:
Sou1gh0st 2024-06-25 22:04:31 +08:00 committed by François
parent a0e7429363
commit 8c1b9a6c18
No known key found for this signature in database
2 changed files with 14 additions and 1 deletions

View file

@ -663,6 +663,11 @@ impl App {
self.sub_apps.sub_apps.remove(&label.intern())
}
/// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.
pub fn update_sub_app_by_label(&mut self, label: impl AppLabel) {
self.sub_apps.update_subapp_by_label(label);
}
/// Inserts a new `schedule` under the provided `label`, overwriting any existing
/// schedule with the same label.
pub fn add_schedule(&mut self, schedule: Schedule) -> &mut Self {

View file

@ -1,4 +1,4 @@
use crate::{App, InternedAppLabel, Plugin, Plugins, PluginsState};
use crate::{App, AppLabel, InternedAppLabel, Plugin, Plugins, PluginsState};
use bevy_ecs::{
event::EventRegistry,
prelude::*,
@ -449,4 +449,12 @@ impl SubApps {
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut SubApp> + '_ {
std::iter::once(&mut self.main).chain(self.sub_apps.values_mut())
}
/// Extract data from the main world into the [`SubApp`] with the given label and perform an update if it exists.
pub fn update_subapp_by_label(&mut self, label: impl AppLabel) {
if let Some(sub_app) = self.sub_apps.get_mut(&label.intern()) {
sub_app.extract(&mut self.main.world);
sub_app.update();
}
}
}