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

Schedule v2 #1021

Merged
merged 3 commits into from
Dec 13, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,18 @@ path = "examples/diagnostics/print_diagnostics.rs"
name = "event"
path = "examples/ecs/event.rs"

[[example]]
name = "fixed_timestep"
path = "examples/ecs/fixed_timestep.rs"

[[example]]
name = "startup_system"
path = "examples/ecs/startup_system.rs"

[[example]]
name = "state"
path = "examples/ecs/state.rs"

[[example]]
name = "system_chaining"
path = "examples/ecs/system_chaining.rs"
Expand Down
33 changes: 3 additions & 30 deletions crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::app_builder::AppBuilder;
use bevy_ecs::{ParallelExecutor, Resources, Schedule, World};
use bevy_ecs::{Resources, Schedule, Stage, World};
#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;

Expand Down Expand Up @@ -30,9 +30,6 @@ pub struct App {
pub resources: Resources,
pub runner: Box<dyn Fn(App)>,
pub schedule: Schedule,
pub executor: ParallelExecutor,
pub startup_schedule: Schedule,
pub startup_executor: ParallelExecutor,
}

impl Default for App {
Expand All @@ -41,16 +38,12 @@ impl Default for App {
world: Default::default(),
resources: Default::default(),
schedule: Default::default(),
executor: Default::default(),
startup_schedule: Default::default(),
startup_executor: ParallelExecutor::without_tracker_clears(),
runner: Box::new(run_once),
}
}
}

fn run_once(mut app: App) {
app.initialize();
app.update();
}

Expand All @@ -60,35 +53,15 @@ impl App {
}

pub fn update(&mut self) {
self.schedule
.initialize(&mut self.world, &mut self.resources);
self.executor
.run(&mut self.schedule, &mut self.world, &mut self.resources);
}

pub fn initialize(&mut self) {
#[cfg(feature = "trace")]
let startup_schedule_span = info_span!("startup_schedule");
#[cfg(feature = "trace")]
let _startup_schedule_guard = startup_schedule_span.enter();
self.startup_schedule
.initialize(&mut self.world, &mut self.resources);
self.startup_executor.initialize(&mut self.resources);
self.startup_executor.run(
&mut self.startup_schedule,
&mut self.world,
&mut self.resources,
);
self.schedule.run(&mut self.world, &mut self.resources);
}

pub fn run(mut self) {
#[cfg(feature = "trace")]
let bevy_app_run_span = info_span!("bevy_app_run");
let bevy_app_run_span = info_span!("bevy_app");
#[cfg(feature = "trace")]
let _bevy_app_run_guard = bevy_app_run_span.enter();

self.executor.initialize(&mut self.resources);

let runner = std::mem::replace(&mut self.runner, Box::new(run_once));
(runner)(self);
}
Expand Down
186 changes: 131 additions & 55 deletions crates/bevy_app/src/app_builder.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use std::any::Any;

use crate::{
app::{App, AppExit},
event::Events,
plugin::Plugin,
stage, startup_stage, PluginGroup, PluginGroupBuilder,
};
use bevy_ecs::{FromResources, IntoSystem, Resources, System, World};
use bevy_ecs::{
clear_trackers_system, FromResources, IntoStage, IntoSystem, Resource, Resources, RunOnce,
Schedule, Stage, State, StateStage, System, SystemStage, World,
};
use bevy_utils::tracing::debug;

/// Configure [App]s using the builder pattern
Expand All @@ -18,8 +23,10 @@ impl Default for AppBuilder {
app: App::default(),
};

app_builder.add_default_stages();
app_builder.add_event::<AppExit>();
app_builder
.add_default_stages()
.add_event::<AppExit>()
.add_system_to_stage(stage::LAST, clear_trackers_system);
app_builder
}
}
Expand Down Expand Up @@ -49,55 +56,88 @@ impl AppBuilder {
self
}

pub fn add_stage(&mut self, stage_name: &'static str) -> &mut Self {
self.app.schedule.add_stage(stage_name);
pub fn add_stage<Params, S: IntoStage<Params>>(
&mut self,
name: &'static str,
stage: S,
) -> &mut Self {
self.app.schedule.add_stage(name, stage);
self
}

pub fn add_stage_after(&mut self, target: &'static str, stage_name: &'static str) -> &mut Self {
self.app.schedule.add_stage_after(target, stage_name);
pub fn add_stage_after<Params, S: IntoStage<Params>>(
&mut self,
target: &'static str,
name: &'static str,
stage: S,
) -> &mut Self {
self.app.schedule.add_stage_after(target, name, stage);
self
}

pub fn add_stage_before(
pub fn add_stage_before<Params, S: IntoStage<Params>>(
&mut self,
target: &'static str,
stage_name: &'static str,
name: &'static str,
stage: S,
) -> &mut Self {
self.app.schedule.add_stage_before(target, stage_name);
self.app.schedule.add_stage_before(target, name, stage);
self
}

pub fn add_startup_stage(&mut self, stage_name: &'static str) -> &mut Self {
self.app.startup_schedule.add_stage(stage_name);
pub fn add_startup_stage<Params, S: IntoStage<Params>>(
&mut self,
name: &'static str,
stage: S,
) -> &mut Self {
self.app
.schedule
.stage(stage::STARTUP, |schedule: &mut Schedule| {
schedule.add_stage(name, stage)
});
self
}

pub fn add_startup_stage_after(
pub fn add_startup_stage_after<Params, S: IntoStage<Params>>(
&mut self,
target: &'static str,
stage_name: &'static str,
name: &'static str,
stage: S,
) -> &mut Self {
self.app
.startup_schedule
.add_stage_after(target, stage_name);
.schedule
.stage(stage::STARTUP, |schedule: &mut Schedule| {
schedule.add_stage_after(target, name, stage)
});
self
}

pub fn add_startup_stage_before(
pub fn add_startup_stage_before<Params, S: IntoStage<Params>>(
&mut self,
target: &'static str,
stage_name: &'static str,
name: &'static str,
stage: S,
) -> &mut Self {
self.app
.startup_schedule
.add_stage_before(target, stage_name);
.schedule
.stage(stage::STARTUP, |schedule: &mut Schedule| {
schedule.add_stage_before(target, name, stage)
});
self
}

pub fn stage<T: Stage, F: FnOnce(&mut T) -> &mut T>(
&mut self,
name: &str,
func: F,
) -> &mut Self {
self.app.schedule.stage(name, func);
self
}

pub fn add_system<S, Params, IntoS>(&mut self, system: IntoS) -> &mut Self
where
S: System<Input = (), Output = ()>,
S: System<In = (), Out = ()>,
IntoS: IntoSystem<Params, S>,
{
self.add_system_to_stage(stage::UPDATE, system)
Expand All @@ -109,37 +149,41 @@ impl AppBuilder {
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
S: System<In = (), Out = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.startup_schedule
.add_system_to_stage(stage_name, system);
.schedule
.stage(stage::STARTUP, |schedule: &mut Schedule| {
schedule.add_system_to_stage(stage_name, system)
});
self
}

pub fn add_startup_system<S, Params, IntoS>(&mut self, system: IntoS) -> &mut Self
where
S: System<Input = (), Output = ()>,
S: System<In = (), Out = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.startup_schedule
.add_system_to_stage(startup_stage::STARTUP, system);
self
self.add_startup_system_to_stage(startup_stage::STARTUP, system)
}

pub fn add_default_stages(&mut self) -> &mut Self {
self.add_startup_stage(startup_stage::PRE_STARTUP)
.add_startup_stage(startup_stage::STARTUP)
.add_startup_stage(startup_stage::POST_STARTUP)
.add_stage(stage::FIRST)
.add_stage(stage::PRE_EVENT)
.add_stage(stage::EVENT)
.add_stage(stage::PRE_UPDATE)
.add_stage(stage::UPDATE)
.add_stage(stage::POST_UPDATE)
.add_stage(stage::LAST)
self.add_stage(
stage::STARTUP,
Schedule::default()
.with_run_criteria(RunOnce::default())
.with_stage(startup_stage::PRE_STARTUP, SystemStage::parallel())
.with_stage(startup_stage::STARTUP, SystemStage::parallel())
.with_stage(startup_stage::POST_STARTUP, SystemStage::parallel()),
)
.add_stage(stage::FIRST, SystemStage::parallel())
.add_stage(stage::PRE_EVENT, SystemStage::parallel())
.add_stage(stage::EVENT, SystemStage::parallel())
.add_stage(stage::PRE_UPDATE, SystemStage::parallel())
.add_stage(stage::UPDATE, SystemStage::parallel())
.add_stage(stage::POST_UPDATE, SystemStage::parallel())
.add_stage(stage::LAST, SystemStage::parallel())
}

pub fn add_system_to_stage<S, Params, IntoS>(
Expand All @@ -148,28 +192,13 @@ impl AppBuilder {
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
S: System<In = (), Out = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app.schedule.add_system_to_stage(stage_name, system);
self
}

pub fn add_system_to_stage_front<S, Params, IntoS>(
&mut self,
stage_name: &'static str,
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.schedule
.add_system_to_stage_front(stage_name, system.system());
self
}

pub fn add_event<T>(&mut self) -> &mut Self
where
T: Send + Sync + 'static,
Expand All @@ -178,6 +207,53 @@ impl AppBuilder {
.add_system_to_stage(stage::EVENT, Events::<T>::update_system)
}

pub fn state_stage_name<T: Any>() -> String {
format!("state({})", std::any::type_name::<T>())
}

pub fn add_state<T: Clone + Resource>(&mut self, initial: T) -> &mut Self {
self.add_resource(State::new(initial));
self.app.schedule.add_stage_after(
stage::UPDATE,
&Self::state_stage_name::<T>(),
StateStage::<T>::default(),
);
self
}

pub fn on_state_enter<T: Clone + Resource, Params, S: IntoStage<Params>>(
&mut self,
value: T,
stage: S,
) -> &mut Self {
self.stage(
&Self::state_stage_name::<T>(),
|state_stage: &mut StateStage<T>| state_stage.on_state_enter(value, stage),
)
}

pub fn on_state_update<T: Clone + Resource, Params, S: IntoStage<Params>>(
&mut self,
value: T,
stage: S,
) -> &mut Self {
self.stage(
&Self::state_stage_name::<T>(),
|state_stage: &mut StateStage<T>| state_stage.on_state_update(value, stage),
)
}

pub fn on_state_exit<T: Clone + Resource, Params, S: IntoStage<Params>>(
&mut self,
value: T,
stage: S,
) -> &mut Self {
self.stage(
&Self::state_stage_name::<T>(),
|state_stage: &mut StateStage<T>| state_stage.on_state_exit(value, stage),
)
}

/// Adds a resource to the current [App] and overwrites any resource previously added of the same type.
pub fn add_resource<T>(&mut self, resource: T) -> &mut Self
where
Expand Down
2 changes: 0 additions & 2 deletions crates/bevy_app/src/schedule_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ impl Plugin for ScheduleRunnerPlugin {
.get_or_insert_with(ScheduleRunnerSettings::default)
.to_owned();
app.set_runner(move |mut app: App| {
app.initialize();

let mut app_exit_event_reader = EventReader::<AppExit>::default();
match settings.run_mode {
RunMode::Once => {
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_app/src/stage.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/// Name of the app stage that runs once at the beginning of the app
pub const STARTUP: &str = "startup";

/// Name of app stage that runs before all other app stages
pub const FIRST: &str = "first";

/// Name of app stage that runs before EVENT
pub const PRE_EVENT: &str = "pre_events";
pub const PRE_EVENT: &str = "pre_event";

/// Name of app stage that updates events. Runs before UPDATE
pub const EVENT: &str = "events";
pub const EVENT: &str = "event";

/// Name of app stage responsible for performing setup before an update. Runs before UPDATE.
pub const PRE_UPDATE: &str = "pre_update";
Expand Down
Loading