Repository: bevyengine/bevy
File: crates/bevy_render/src/extract_plugin.rs (Rust)

Code before:
use core::ops::{Deref, DerefMut};

use crate::{
    sync_world::{despawn_temporary_render_entities, entity_sync_system, SyncWorldPlugin},
    Render, RenderApp, RenderSystems,
};
use bevy_app::{App, Plugin, SubApp};
use bevy_ecs::{
    resource::Resource,
    schedule::{IntoScheduleConfigs, Schedule, ScheduleBuildSettings, ScheduleLabel, Schedules},
    world::{Mut, World},
};
use bevy_utils::default;

/// Plugin that sets up the [`RenderApp`] and handles extracting data from the
/// main world to the render world.
#[derive(Default)]
pub struct ExtractPlugin {
    /// Function that gets run at the beginning of each extraction.
    ///
    /// Gets the main world and render world as arguments (in that order).
    pub extract_callback: Option<fn(&mut World, &mut World)>,
}

impl Plugin for ExtractPlugin {
    fn build(&self, app: &mut App) {
        app.add_plugins(SyncWorldPlugin);
        app.init_resource::<ScratchMainWorld>();

        let mut render_app = SubApp::new();

        let mut extract_schedule = Schedule::new(ExtractSchedule);
        // We skip applying any commands during the ExtractSchedule
        // so commands can be applied on the render thread.
        extract_schedule.set_build_settings(ScheduleBuildSettings {
            auto_insert_apply_deferred: false,
            ..default()
        });
        extract_schedule.set_apply_final_deferred(false);

        render_app.add_schedule(Render::base_schedule());
        render_app.add_schedule(extract_schedule);
        render_app.add_systems(
            Render,
            (
                // This set applies the commands from the extract schedule while the render schedule
                // is running in parallel with the main app.

Review comment (refactor):
bikeshed: call it pre_extract, don't make it Option, just impl Default and have `pre_extract: |_, _| {}`

Code after:
use crate::{
    sync_world::{despawn_temporary_render_entities, entity_sync_system, SyncWorldPlugin},
    Render, RenderApp, RenderSystems,
};
use bevy_app::{App, Plugin, SubApp};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
    resource::Resource,
    schedule::{IntoScheduleConfigs, Schedule, ScheduleBuildSettings, ScheduleLabel, Schedules},
    world::{Mut, World},
};
use bevy_utils::default;

/// Plugin that sets up the [`RenderApp`] and handles extracting data from the
/// main world to the render world.
pub struct ExtractPlugin {
    /// Function that gets run at the beginning of each extraction.
    ///
    /// Gets the main world and render world as arguments (in that order).
    pub pre_extract: fn(&mut World, &mut World),
}

impl Default for ExtractPlugin {
    fn default() -> Self {
        Self {
            pre_extract: |_, _| {},
        }
    }
}

impl Plugin for ExtractPlugin {
    fn build(&self, app: &mut App) {
        app.add_plugins(SyncWorldPlugin);
        app.init_resource::<ScratchMainWorld>();

        let mut render_app = SubApp::new();

        let mut extract_schedule = Schedule::new(ExtractSchedule);
        // We skip applying any commands during the ExtractSchedule
        // so commands can be applied on the render thread.
        extract_schedule.set_build_settings(ScheduleBuildSettings {
            auto_insert_apply_deferred: false,
            ..default()
        });
        extract_schedule.set_apply_final_deferred(false);

        render_app.add_schedule(Render::base_schedule());