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

Create a System Builder Syntax instead of using System Descriptors #2736

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0c6a837
Add SystemConfig and some basic options
thechubbypanda Aug 27, 2021
569513c
Cargo format
thechubbypanda Aug 27, 2021
983a2be
System Builder Rework - In Progress
thechubbypanda Aug 28, 2021
abd6d8b
Rename StartupConfig to conform with other traits
thechubbypanda Aug 28, 2021
52e7fff
Remove trait_casting feature
thechubbypanda Aug 28, 2021
011af54
SystemSet handle ExclusiveSystems
thechubbypanda Aug 29, 2021
ecb855b
Testing SubType impl for StageConfig
thechubbypanda Aug 29, 2021
20fd625
Sort imports and remove double refs in app.rs
thechubbypanda Aug 29, 2021
d9f7558
Attempt at fixing `SystemConfig`, `StartupConfig`.
Ratysz Aug 31, 2021
e83c519
Merge pull request #1 from Ratysz/system-builder-syntax
thechubbypanda Sep 1, 2021
b540f79
Separate configs and conform with StageConfig
thechubbypanda Sep 1, 2021
3bad094
Make more system additions use the new methods
thechubbypanda Sep 1, 2021
325689b
Found a solution to exclusive errors
thechubbypanda Sep 1, 2021
9aeb408
Revert solution
thechubbypanda Sep 1, 2021
d7e1e2a
Fix broken startup functionality
thechubbypanda Sep 1, 2021
4514032
Actually use the correct impl
thechubbypanda Sep 1, 2021
251fb40
.stage all the things
thechubbypanda Sep 1, 2021
0995f85
Fix bevy_render error
thechubbypanda Sep 1, 2021
2d062e6
Fix final stage.rs error
thechubbypanda Sep 1, 2021
9a2284e
Fix all remaining crate errors
thechubbypanda Sep 1, 2021
5487f83
Fix examples
thechubbypanda Sep 1, 2021
1d34d96
Format
thechubbypanda Sep 1, 2021
9822b19
Merge branch 'main' into system-builder-syntax
thechubbypanda Sep 1, 2021
e80fded
Format again
thechubbypanda Sep 1, 2021
7b4bb30
Fix some ci errors
thechubbypanda Sep 1, 2021
aee8c9d
Fix InsertionPoint panic
thechubbypanda Sep 2, 2021
eb207e5
Fix startup error
thechubbypanda Sep 2, 2021
0c9ac6a
Fixed copy pasta failure (insertion point test)
thechubbypanda Sep 2, 2021
6c28d69
Remove redundant fn impl
thechubbypanda Sep 2, 2021
085a5ef
Update System docs
thechubbypanda Sep 4, 2021
55b797c
Reduce internal config function visibility and doc
thechubbypanda Sep 4, 2021
c8914c1
More docs
thechubbypanda Sep 4, 2021
0a32358
Update crates/bevy_ecs/src/schedule/stage.rs
thechubbypanda Sep 5, 2021
0f6494b
Update crates/bevy_ecs/src/system/config/system_config.rs
thechubbypanda Sep 5, 2021
91cb4c2
Update crates/bevy_ecs/src/system/system.rs
thechubbypanda Sep 5, 2021
b272cb4
Add specific config trait docs
thechubbypanda Sep 7, 2021
cf372a7
Add link to SystemStage doc
thechubbypanda Sep 7, 2021
25b1d31
Add system set conflict validation
thechubbypanda Sep 13, 2021
d360e14
Use .any rather than for loops
thechubbypanda Oct 2, 2021
a762965
Maybe cleaner add system set conflict checking
thechubbypanda Oct 2, 2021
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
177 changes: 99 additions & 78 deletions crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use crate::{CoreStage, Events, Plugin, PluginGroup, PluginGroupBuilder, StartupStage};
use bevy_ecs::{
component::{Component, ComponentDescriptor},
prelude::{FromWorld, IntoExclusiveSystem},
schedule::{
IntoSystemDescriptor, RunOnce, Schedule, Stage, StageLabel, State, SystemSet, SystemStage,
},
prelude::{ExclusiveSystem, FromWorld, IntoExclusiveSystem, IntoSystem, StageConfig, System},
schedule::{RunOnce, Schedule, Stage, StageLabel, State, SystemSet, SystemStage},
world::World,
};
use bevy_utils::tracing::debug;
Expand Down Expand Up @@ -50,7 +48,7 @@ impl Default for App {

app.add_default_stages()
.add_event::<AppExit>()
.add_system_to_stage(CoreStage::Last, World::clear_trackers.exclusive_system());
.add_exclusive(World::clear_trackers.stage(CoreStage::Last));

#[cfg(feature = "bevy_ci_testing")]
{
Expand Down Expand Up @@ -203,85 +201,108 @@ impl App {
/// App::new()
/// .add_system(my_system);
/// ```
pub fn add_system<Params>(&mut self, system: impl IntoSystemDescriptor<Params>) -> &mut Self {
self.add_system_to_stage(CoreStage::Update, system)
}

pub fn add_system_set(&mut self, system_set: SystemSet) -> &mut Self {
self.add_system_set_to_stage(CoreStage::Update, system_set)
}

pub fn add_system_to_stage<Params>(
&mut self,
stage_label: impl StageLabel,
system: impl IntoSystemDescriptor<Params>,
) -> &mut Self {
self.schedule.add_system_to_stage(stage_label, system);
self
}

pub fn add_system_set_to_stage(
&mut self,
stage_label: impl StageLabel,
system_set: SystemSet,
) -> &mut Self {
self.schedule
.add_system_set_to_stage(stage_label, system_set);
pub fn add_system<Params>(&mut self, system: impl IntoSystem<(), (), Params>) -> &mut Self {
let system = system.system();
if system.config().startup {
let system = {
thechubbypanda marked this conversation as resolved.
Show resolved Hide resolved
if system.config().stage.is_some() {
system
} else {
system.stage(StartupStage::Startup)
}
};
self.schedule
.stage(CoreStage::Startup, |schedule: &mut Schedule| {
schedule.add_system(system)
});
} else {
let system = {
if system.config().stage.is_some() {
system
} else {
system.stage(CoreStage::Update)
}
};
self.schedule.add_system(system);
}
self
}

/// Adds a system that is run once at application startup
///
/// Startup systems run exactly once BEFORE all other systems. These are generally used for
/// app initialization code (ex: adding entities and resources).
///
/// * For adding a system that runs for every frame, see [`App::add_system`].
/// * For adding a system to specific stage, see [`App::add_system_to_stage`].
///
/// ## Example
/// ```
/// # use bevy_app::prelude::*;
/// # use bevy_ecs::prelude::*;
/// #
/// fn my_startup_system(_commands: Commands) {
/// println!("My startup system");
/// }
///
/// App::new()
/// .add_startup_system(my_startup_system);
/// ```
pub fn add_startup_system<Params>(
&mut self,
system: impl IntoSystemDescriptor<Params>,
) -> &mut Self {
self.add_startup_system_to_stage(StartupStage::Startup, system)
}

pub fn add_startup_system_set(&mut self, system_set: SystemSet) -> &mut Self {
self.add_startup_system_set_to_stage(StartupStage::Startup, system_set)
}
pub fn add_system_set(&mut self, set: SystemSet) -> &mut Self {
thechubbypanda marked this conversation as resolved.
Show resolved Hide resolved
fn ensure_no_conflicts(set: &SystemSet) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could keep a reference to the conflicting stage name and add that to the panic message.

Small suggestion, you could use this instead conflict = set.systems.iter().any(|system| system.config().stage != set.config().stage);, but that's entirely up to preference.

let mut conflict = false;
for system in set.systems.iter() {
if system.config().stage != set.config().stage {
conflict = true;
}
}
for system in set.exclusive_systems.iter() {
if system.config().stage != set.config().stage {
conflict = true;
}
}
if conflict {
panic!("There is a mismatch between a system set's stage and it's sub systems")
}
}

pub fn add_startup_system_to_stage<Params>(
&mut self,
stage_label: impl StageLabel,
system: impl IntoSystemDescriptor<Params>,
) -> &mut Self {
self.schedule
.stage(CoreStage::Startup, |schedule: &mut Schedule| {
schedule.add_system_to_stage(stage_label, system)
});
if set.config().startup {
let set = {
if set.config().stage.is_some() {
set
} else {
set.stage(StartupStage::Startup)
}
};
ensure_no_conflicts(&set);
self.schedule
.stage(CoreStage::Startup, |schedule: &mut Schedule| {
schedule.add_system_set(set)
});
} else {
let set = {
if set.config().stage.is_some() {
set
} else {
set.stage(CoreStage::Update)
}
};
ensure_no_conflicts(&set);
self.schedule.add_system_set(set);
}
self
}

pub fn add_startup_system_set_to_stage(
pub fn add_exclusive<Params, SystemType>(
&mut self,
stage_label: impl StageLabel,
system_set: SystemSet,
) -> &mut Self {
self.schedule
.stage(CoreStage::Startup, |schedule: &mut Schedule| {
schedule.add_system_set_to_stage(stage_label, system_set)
});
system: impl IntoExclusiveSystem<Params, SystemType>,
) -> &mut Self
where
SystemType: ExclusiveSystem + StageConfig<Params, SystemType>,
{
let system = system.exclusive_system();
if system.config().startup {
let system = {
if system.config().stage.is_some() {
system
} else {
system.exclusive_system().stage(StartupStage::Startup)
}
};
self.schedule
.stage(CoreStage::Startup, |schedule: &mut Schedule| {
schedule.add_exclusive(system)
});
} else {
let system = {
if system.config().stage.is_some() {
system
} else {
system.exclusive_system().stage(CoreStage::Update)
}
};
self.schedule.add_exclusive(system);
}
self
}

Expand All @@ -307,7 +328,7 @@ impl App {
T: Component + Debug + Clone + Eq + Hash,
{
self.insert_resource(State::new(initial))
.add_system_set_to_stage(stage, State::<T>::get_driver())
.add_system_set(State::<T>::get_driver().stage(stage))
}

pub fn add_default_stages(&mut self) -> &mut Self {
Expand Down Expand Up @@ -335,7 +356,7 @@ impl App {
T: Component,
{
self.insert_resource(Events::<T>::default())
.add_system_to_stage(CoreStage::First, Events::<T>::update_system)
.add_system(Events::<T>::update_system.stage(CoreStage::First))
}

/// Inserts a resource to the current [App] and overwrites any resource previously added of the same type.
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
RefChange,
};
use bevy_app::{App, EventWriter, Events};
use bevy_ecs::{system::ResMut, world::FromWorld};
use bevy_ecs::{prelude::StageConfig, system::ResMut, world::FromWorld};
use bevy_utils::HashMap;
use crossbeam_channel::Sender;
use std::fmt::Debug;
Expand Down Expand Up @@ -214,8 +214,8 @@ impl AddAsset for App {
};

self.insert_resource(assets)
.add_system_to_stage(AssetStage::AssetEvents, Assets::<T>::asset_event_system)
.add_system_to_stage(AssetStage::LoadAssets, update_asset_storage_system::<T>)
.add_system(Assets::<T>::asset_event_system.stage(AssetStage::AssetEvents))
.add_system(update_asset_storage_system::<T>.stage(AssetStage::LoadAssets))
.register_type::<Handle<T>>()
.add_event::<AssetEvent<T>>()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::{Asset, Assets};
use bevy_app::prelude::*;
use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics, MAX_DIAGNOSTIC_NAME_WIDTH};
use bevy_ecs::system::{Res, ResMut};
use bevy_ecs::{
prelude::StartupConfig,
system::{Res, ResMut},
};

/// Adds "asset count" diagnostic to an App
pub struct AssetCountDiagnosticsPlugin<T: Asset> {
Expand All @@ -18,7 +21,7 @@ impl<T: Asset> Default for AssetCountDiagnosticsPlugin<T> {

impl<T: Asset> Plugin for AssetCountDiagnosticsPlugin<T> {
fn build(&self, app: &mut App) {
app.add_startup_system(Self::setup_system)
app.add_system(Self::setup_system.startup())
.add_system(Self::diagnostic_system);
}
}
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ pub use loader::*;
pub use path::*;

use bevy_app::{prelude::Plugin, App};
use bevy_ecs::schedule::{StageLabel, SystemStage};
use bevy_ecs::{
prelude::StageConfig,
schedule::{StageLabel, SystemStage},
};
use bevy_tasks::IoTaskPool;

/// The names of asset stages in an App Schedule
Expand Down Expand Up @@ -101,15 +104,12 @@ impl Plugin for AssetPlugin {
SystemStage::parallel(),
)
.register_type::<HandleId>()
.add_system_to_stage(
bevy_app::CoreStage::PreUpdate,
asset_server::free_unused_assets_system,
);
.add_system(asset_server::free_unused_assets_system.stage(bevy_app::CoreStage::PreUpdate));

#[cfg(all(
feature = "filesystem_watcher",
all(not(target_arch = "wasm32"), not(target_os = "android"))
))]
app.add_system_to_stage(AssetStage::LoadAssets, io::filesystem_watcher_system);
app.add_system(io::filesystem_watcher_system.stage(AssetStage::LoadAssets));
}
}
9 changes: 5 additions & 4 deletions crates/bevy_audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub use audio_source::*;

use bevy_app::prelude::*;
use bevy_asset::AddAsset;
use bevy_ecs::system::IntoExclusiveSystem;
use bevy_ecs::{prelude::StageConfig, system::IntoExclusiveSystem};

/// Adds support for audio playback to an App
#[derive(Default)]
Expand All @@ -24,9 +24,10 @@ impl Plugin for AudioPlugin {
app.init_non_send_resource::<AudioOutput<AudioSource>>()
.add_asset::<AudioSource>()
.init_resource::<Audio<AudioSource>>()
.add_system_to_stage(
CoreStage::PostUpdate,
play_queued_audio_system::<AudioSource>.exclusive_system(),
.add_exclusive(
play_queued_audio_system::<AudioSource>
.exclusive_system()
.stage(CoreStage::PostUpdate),
);

#[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))]
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_core/src/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub(crate) fn entity_labels_system(
#[cfg(test)]
mod tests {
use bevy_ecs::{
prelude::StageConfig,
schedule::{Schedule, Stage, SystemStage},
world::World,
};
Expand All @@ -133,7 +134,7 @@ mod tests {
world.insert_resource(EntityLabels::default());
let mut schedule = Schedule::default();
schedule.add_stage("test", SystemStage::single_threaded());
schedule.add_system_to_stage("test", entity_labels_system);
schedule.add_system(entity_labels_system.stage("test"));
(world, schedule)
}

Expand Down
15 changes: 8 additions & 7 deletions crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub mod prelude {
use bevy_app::prelude::*;
use bevy_ecs::{
entity::Entity,
schedule::{ExclusiveSystemDescriptorCoercion, SystemLabel},
system::IntoExclusiveSystem,
prelude::{ScheduleConfig, StageConfig, StartupConfig},
schedule::SystemLabel,
};
use bevy_utils::HashSet;
use std::ops::Range;
Expand Down Expand Up @@ -58,12 +58,13 @@ impl Plugin for CorePlugin {
.register_type::<Timer>()
// time system is added as an "exclusive system" to ensure it runs before other systems
// in CoreStage::First
.add_system_to_stage(
CoreStage::First,
time_system.exclusive_system().label(CoreSystem::Time),
.add_exclusive(time_system.stage(CoreStage::First).label(CoreSystem::Time))
.add_system(
entity_labels_system
.startup()
.stage(StartupStage::PostStartup),
)
.add_startup_system_to_stage(StartupStage::PostStartup, entity_labels_system)
.add_system_to_stage(CoreStage::PostUpdate, entity_labels_system);
.add_system(entity_labels_system.stage(CoreStage::PostUpdate));

register_rust_types(app);
register_math_types(app);
Expand Down
12 changes: 11 additions & 1 deletion crates/bevy_core/src/time/fixed_timestep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy_ecs::{
component::ComponentId,
query::Access,
schedule::ShouldRun,
system::{ConfigurableSystem, IntoSystem, Local, Res, ResMut, System, SystemId},
system::{ConfigurableSystem, IntoSystem, Local, Res, ResMut, System, SystemConfig, SystemId},
world::World,
};
use bevy_utils::HashMap;
Expand Down Expand Up @@ -51,13 +51,15 @@ impl FixedTimesteps {
pub struct FixedTimestep {
state: State,
internal_system: Box<dyn System<In = (), Out = ShouldRun>>,
config: SystemConfig,
}

impl Default for FixedTimestep {
fn default() -> Self {
Self {
state: State::default(),
internal_system: Box::new(Self::prepare_system.system()),
config: SystemConfig::default(),
}
}
}
Expand Down Expand Up @@ -197,4 +199,12 @@ impl System for FixedTimestep {
fn check_change_tick(&mut self, change_tick: u32) {
self.internal_system.check_change_tick(change_tick);
}

fn config(&self) -> &SystemConfig {
&self.config
}

fn config_mut(&mut self) -> &mut SystemConfig {
&mut self.config
}
}
Loading