From 969ccfff89804e11cb205123e1788058be08fec6 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:09:49 -0500 Subject: [PATCH 01/40] make `IntoSystemConfig` more generic --- crates/bevy_ecs/src/schedule/config.rs | 47 +++++++++++------------- crates/bevy_ecs/src/schedule/schedule.rs | 16 ++++---- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 28fe775acd903..51a737834484a 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -274,39 +274,43 @@ impl IntoSystemSetConfig for SystemSetConfig { /// /// This has been implemented for boxed [`System`](crate::system::System) /// trait objects and all functions that turn into such. -pub trait IntoSystemConfig: sealed::IntoSystemConfig { +pub trait IntoSystemConfig { + type Config; + /// Convert into a [`SystemConfig`]. #[doc(hidden)] - fn into_config(self) -> SystemConfig; + fn into_config(self) -> Self::Config; /// Add to `set` membership. #[track_caller] - fn in_set(self, set: impl SystemSet) -> SystemConfig; + fn in_set(self, set: impl SystemSet) -> Self::Config; /// Add to the provided "base" `set`. For more information on base sets, see [`SystemSet::is_base`]. #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> SystemConfig; + fn in_base_set(self, set: impl SystemSet) -> Self::Config; /// Don't add this system to the schedules's default set. - fn no_default_base_set(self) -> SystemConfig; + fn no_default_base_set(self) -> Self::Config; /// Run before all systems in `set`. - fn before(self, set: impl IntoSystemSet) -> SystemConfig; + fn before(self, set: impl IntoSystemSet) -> Self::Config; /// Run after all systems in `set`. - fn after(self, set: impl IntoSystemSet) -> SystemConfig; + fn after(self, set: impl IntoSystemSet) -> Self::Config; /// Run only if the [`Condition`] is `true`. /// /// The `Condition` will be evaluated at most once (per schedule run), /// when the system prepares to run. - fn run_if

(self, condition: impl Condition

) -> SystemConfig; + fn run_if

(self, condition: impl Condition

) -> Self::Config; /// Suppress warnings and errors that would result from this system having ambiguities /// (conflicting access but indeterminate order) with systems in `set`. - fn ambiguous_with(self, set: impl IntoSystemSet) -> SystemConfig; + fn ambiguous_with(self, set: impl IntoSystemSet) -> Self::Config; /// Suppress warnings and errors that would result from this system having ambiguities /// (conflicting access but indeterminate order) with any other system. - fn ambiguous_with_all(self) -> SystemConfig; + fn ambiguous_with_all(self) -> Self::Config; } impl IntoSystemConfig for F where - F: IntoSystem<(), (), Params> + sealed::IntoSystemConfig, + F: IntoSystem<(), (), Params>, { + type Config = SystemConfig; + fn into_config(self) -> SystemConfig { SystemConfig::new(Box::new(IntoSystem::into_system(self))) } @@ -347,6 +351,8 @@ where } impl IntoSystemConfig<()> for BoxedSystem<(), ()> { + type Config = SystemConfig; + fn into_config(self) -> SystemConfig { SystemConfig::new(self) } @@ -387,6 +393,8 @@ impl IntoSystemConfig<()> for BoxedSystem<(), ()> { } impl IntoSystemConfig<()> for SystemConfig { + type Config = Self; + fn into_config(self) -> Self { self } @@ -458,20 +466,9 @@ impl IntoSystemConfig<()> for SystemConfig { // only `System` system objects can be scheduled mod sealed { - use crate::{ - schedule::{BoxedSystemSet, SystemSet}, - system::{BoxedSystem, IntoSystem}, - }; - - use super::{SystemConfig, SystemSetConfig}; - - pub trait IntoSystemConfig {} - - impl> IntoSystemConfig for F {} - - impl IntoSystemConfig<()> for BoxedSystem<(), ()> {} + use crate::schedule::{BoxedSystemSet, SystemSet}; - impl IntoSystemConfig<()> for SystemConfig {} + use super::SystemSetConfig; pub trait IntoSystemSetConfig {} @@ -824,7 +821,7 @@ macro_rules! impl_system_collection { ($(($param: ident, $sys: ident)),*) => { impl<$($param, $sys),*> IntoSystemConfigs<($($param,)*)> for ($($sys,)*) where - $($sys: IntoSystemConfig<$param>),* + $($sys: IntoSystemConfig<$param, Config = SystemConfig>),* { #[allow(non_snake_case)] fn into_configs(self) -> SystemConfigs { diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 04aaafbccb255..25609f8e2c25b 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -190,7 +190,10 @@ impl Schedule { } /// Add a system to the schedule. - pub fn add_system

(&mut self, system: impl IntoSystemConfig

) -> &mut Self { + pub fn add_system

( + &mut self, + system: impl IntoSystemConfig, + ) -> &mut Self { self.graph.add_system(system); self } @@ -574,19 +577,16 @@ impl ScheduleGraph { } } - fn add_system

(&mut self, system: impl IntoSystemConfig

) { - self.add_system_inner(system).unwrap(); + fn add_system

(&mut self, system: impl IntoSystemConfig) { + self.add_system_inner(system.into_config()).unwrap(); } - fn add_system_inner

( - &mut self, - system: impl IntoSystemConfig

, - ) -> Result { + fn add_system_inner(&mut self, system: SystemConfig) -> Result { let SystemConfig { system, graph_info, conditions, - } = system.into_config(); + } = system; let id = NodeId::System(self.systems.len()); From 94f10f36a8b0e7a0cf5d14e49e94cb85b6431a95 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:10:14 -0500 Subject: [PATCH 02/40] add extension methods for inserting systems into a schedule --- crates/bevy_app/src/app.rs | 25 ++++-- crates/bevy_app/src/config.rs | 139 ++++++++++++++++++++++++++++++++++ crates/bevy_app/src/lib.rs | 5 +- 3 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 crates/bevy_app/src/config.rs diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index be19d82da4910..79c9961a7e70e 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,11 +1,13 @@ -use crate::{CoreSchedule, CoreSet, Plugin, PluginGroup, StartupSet}; +use crate::{ + CoreSchedule, CoreSet, IntoSystemAppConfig, Plugin, PluginGroup, StartupSet, SystemAppConfig, +}; pub use bevy_derive::AppLabel; use bevy_ecs::{ prelude::*, schedule::{ apply_state_transition, common_conditions::run_once as run_once_condition, run_enter_schedule, BoxedScheduleLabel, IntoSystemConfig, IntoSystemSetConfigs, - ScheduleLabel, + ScheduleLabel, SystemConfig, }, }; use bevy_utils::{tracing::debug, HashMap, HashSet}; @@ -378,10 +380,18 @@ impl App { /// # /// app.add_system(my_system); /// ``` - pub fn add_system

(&mut self, system: impl IntoSystemConfig

) -> &mut Self { + pub fn add_system

(&mut self, system: impl IntoSystemAppConfig

) -> &mut Self { let mut schedules = self.world.resource_mut::(); - if let Some(default_schedule) = schedules.get_mut(&*self.default_schedule_label) { + let SystemAppConfig { system, schedule } = system.into_app_config(); + + if let Some(schedule_label) = schedule { + if let Some(schedule) = schedules.get_mut(&schedule_label) { + schedule.add_system(system); + } else { + panic!("Schedule {schedule_label:?} does not exist.") + } + } else if let Some(default_schedule) = schedules.get_mut(&*self.default_schedule_label) { default_schedule.add_system(system); } else { let schedule_label = &self.default_schedule_label; @@ -423,7 +433,7 @@ impl App { pub fn add_system_to_schedule

( &mut self, schedule_label: impl ScheduleLabel, - system: impl IntoSystemConfig

, + system: impl IntoSystemConfig, ) -> &mut Self { let mut schedules = self.world.resource_mut::(); @@ -471,7 +481,10 @@ impl App { /// App::new() /// .add_startup_system(my_startup_system); /// ``` - pub fn add_startup_system

(&mut self, system: impl IntoSystemConfig

) -> &mut Self { + pub fn add_startup_system

( + &mut self, + system: impl IntoSystemConfig, + ) -> &mut Self { self.add_system_to_schedule(CoreSchedule::Startup, system) } diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs new file mode 100644 index 0000000000000..54562d55534bb --- /dev/null +++ b/crates/bevy_app/src/config.rs @@ -0,0 +1,139 @@ +use bevy_ecs::schedule::{ + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, ScheduleLabel, SystemConfig, + SystemSet, +}; + +/// A [`System`] with [`App`]-aware scheduling metadata. +/// +/// [`System`]: bevy_ecs::prelude::System +/// [`App`]: crate::App +pub struct SystemAppConfig { + pub(crate) system: SystemConfig, + pub(crate) schedule: Option, +} + +/*mod sealed { + use bevy_ecs::schedule::IntoSystemConfig; + + #[doc(hidden)] + pub trait IntoSystemAppConfig {} + + impl IntoSystemAppConfig<()> for super::SystemAppConfig {} + + impl IntoSystemAppConfig for T where T: IntoSystemConfig {} +}*/ + +/// Types that can be converted into a [`SystemAppConfig`]. +/// +/// This has been implemented for all `System` trait objects +/// and all functions that convert into such. +pub trait IntoSystemAppConfig: Sized + IntoSystemConfig { + /// Converts into a [`SystemAppConfig`]. + fn into_app_config(self) -> SystemAppConfig; + + /// Add to the provided `schedule`. + #[track_caller] + fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemAppConfig { + let mut config = self.into_app_config(); + if let Some(old_schedule) = &config.schedule { + panic!( + "Cannot add system to schedule '{schedule:?}': it is already in {old_schedule:?}." + ); + } + config.schedule = Some(Box::new(schedule)); + + config + } +} + +impl IntoSystemConfig<()> for SystemAppConfig { + type Config = Self; + + fn into_config(self) -> Self { + self + } + + #[track_caller] + fn in_set(self, set: impl SystemSet) -> Self { + let Self { system, schedule } = self; + Self { + system: system.in_set(set), + schedule, + } + } + + #[track_caller] + fn in_base_set(self, set: impl SystemSet) -> Self { + let Self { system, schedule } = self; + Self { + system: system.in_base_set(set), + schedule, + } + } + + fn no_default_base_set(self) -> Self { + let Self { system, schedule } = self; + Self { + system: system.no_default_base_set(), + schedule, + } + } + + fn before(self, set: impl IntoSystemSet) -> Self { + let Self { system, schedule } = self; + Self { + system: system.before(set), + schedule, + } + } + + fn after(self, set: impl IntoSystemSet) -> Self { + let Self { system, schedule } = self; + Self { + system: system.after(set), + schedule, + } + } + + fn run_if

(self, condition: impl Condition

) -> Self { + let Self { system, schedule } = self; + Self { + system: system.run_if(condition), + schedule, + } + } + + fn ambiguous_with(self, set: impl IntoSystemSet) -> Self { + let Self { system, schedule } = self; + Self { + system: system.ambiguous_with(set), + schedule, + } + } + + fn ambiguous_with_all(self) -> Self { + let Self { system, schedule } = self; + Self { + system: system.ambiguous_with_all(), + schedule, + } + } +} + +impl IntoSystemAppConfig<()> for SystemAppConfig { + fn into_app_config(self) -> SystemAppConfig { + self + } +} + +impl IntoSystemAppConfig for T +where + T: IntoSystemConfig, +{ + fn into_app_config(self) -> SystemAppConfig { + SystemAppConfig { + system: self.into_config(), + schedule: None, + } + } +} diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index f03856aa18e45..1c8b2689f4b7c 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -3,6 +3,7 @@ #![warn(missing_docs)] mod app; +mod config; mod plugin; mod plugin_group; mod schedule_runner; @@ -12,6 +13,7 @@ mod ci_testing; pub use app::*; pub use bevy_derive::DynamicPlugin; +pub use config::*; pub use plugin::*; pub use plugin_group::*; pub use schedule_runner::*; @@ -23,7 +25,8 @@ pub mod prelude { pub use crate::AppTypeRegistry; #[doc(hidden)] pub use crate::{ - app::App, CoreSchedule, CoreSet, DynamicPlugin, Plugin, PluginGroup, StartupSet, + app::App, config::IntoSystemAppConfig, CoreSchedule, CoreSet, DynamicPlugin, Plugin, + PluginGroup, StartupSet, }; } From fe9d5f014ea0766d7b6ed0ab3e616b6828fcd5ff Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:18:50 -0500 Subject: [PATCH 03/40] remove dead code --- crates/bevy_app/src/config.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 54562d55534bb..03757ac1e4fe5 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -12,17 +12,6 @@ pub struct SystemAppConfig { pub(crate) schedule: Option, } -/*mod sealed { - use bevy_ecs::schedule::IntoSystemConfig; - - #[doc(hidden)] - pub trait IntoSystemAppConfig {} - - impl IntoSystemAppConfig<()> for super::SystemAppConfig {} - - impl IntoSystemAppConfig for T where T: IntoSystemConfig {} -}*/ - /// Types that can be converted into a [`SystemAppConfig`]. /// /// This has been implemented for all `System` trait objects From c19dd545b206e36368b3489f3c3a21e0a8077898 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:43:37 -0500 Subject: [PATCH 04/40] add app-aware set configuration --- crates/bevy_app/src/app.rs | 13 ++- crates/bevy_app/src/config.rs | 121 ++++++++++++++++++++++- crates/bevy_ecs/src/schedule/config.rs | 50 ++++------ crates/bevy_ecs/src/schedule/schedule.rs | 18 ++-- 4 files changed, 155 insertions(+), 47 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 79c9961a7e70e..dfe31747571e8 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,5 +1,6 @@ use crate::{ - CoreSchedule, CoreSet, IntoSystemAppConfig, Plugin, PluginGroup, StartupSet, SystemAppConfig, + CoreSchedule, CoreSet, IntoSystemAppConfig, IntoSystemSetAppConfig, Plugin, PluginGroup, + StartupSet, SystemAppConfig, SystemSetAppConfig, }; pub use bevy_derive::AppLabel; use bevy_ecs::{ @@ -513,13 +514,15 @@ impl App { self.add_systems_to_schedule(CoreSchedule::Startup, systems) } - /// Configures a system set in the default schedule, adding the set if it does not exist. - pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { + /// Configures a system set, adding the set if it does not exist. + pub fn configure_set(&mut self, set: impl IntoSystemSetAppConfig) -> &mut Self { + let SystemSetAppConfig { config, schedule } = set.into_app_config(); + self.world .resource_mut::() - .get_mut(&*self.default_schedule_label) + .get_mut(schedule.as_deref().unwrap_or(&self.default_schedule_label)) .unwrap() - .configure_set(set); + .configure_set(config); self } diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 03757ac1e4fe5..ae4add38b29a9 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -1,8 +1,123 @@ use bevy_ecs::schedule::{ - BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, ScheduleLabel, SystemConfig, - SystemSet, + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, IntoSystemSetConfig, + ScheduleLabel, SystemConfig, SystemSet, SystemSetConfig, }; +/// A [`SystemSet`] with [`App`]-aware scheduling metadata. +/// +/// [`App`]: crate::App +pub struct SystemSetAppConfig { + pub(crate) config: SystemSetConfig, + pub(crate) schedule: Option, +} + +/// Types that can be converted into a [`SystemSetAppConfig`]. +pub trait IntoSystemSetAppConfig: Sized + IntoSystemSetConfig { + /// Converts into a [`SystemSetAppConfig`]. + #[doc(hidden)] + fn into_app_config(self) -> SystemSetAppConfig; + + /// Add to the provided `schedule`. + #[track_caller] + fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemSetAppConfig { + let mut config = self.into_app_config(); + if let Some(old_schedule) = &config.schedule { + panic!( + "Cannot add system set to schedule '{schedule:?}': it is already in '{old_schedule:?}'." + ); + } + config.schedule = Some(Box::new(schedule)); + + config + } +} + +impl IntoSystemSetConfig for SystemSetAppConfig { + type Config = Self; + + fn into_config(self) -> Self::Config { + self + } + + #[track_caller] + fn in_set(self, set: impl SystemSet) -> Self { + let Self { config, schedule } = self; + Self { + config: config.in_set(set), + schedule, + } + } + + #[track_caller] + fn in_base_set(self, set: impl SystemSet) -> Self { + let Self { config, schedule } = self; + Self { + config: config.in_base_set(set), + schedule, + } + } + + fn in_default_base_set(self) -> Self { + let Self { config, schedule } = self; + Self { + config: config.in_default_base_set(), + schedule, + } + } + + fn before(self, set: impl IntoSystemSet) -> Self { + let Self { config, schedule } = self; + Self { + config: config.before(set), + schedule, + } + } + + fn after(self, set: impl IntoSystemSet) -> Self { + let Self { config, schedule } = self; + Self { + config: config.after(set), + schedule, + } + } + + fn run_if

(self, condition: impl Condition

) -> Self { + let Self { config, schedule } = self; + Self { + config: config.run_if(condition), + schedule, + } + } + + fn ambiguous_with(self, set: impl IntoSystemSet) -> Self { + let Self { config, schedule } = self; + Self { + config: config.ambiguous_with(set), + schedule, + } + } + + fn ambiguous_with_all(self) -> Self { + let Self { config, schedule } = self; + Self { + config: config.ambiguous_with_all(), + schedule, + } + } +} + +impl IntoSystemSetAppConfig for T +where + T: IntoSystemSetConfig, +{ + fn into_app_config(self) -> SystemSetAppConfig { + SystemSetAppConfig { + config: self.into_config(), + schedule: None, + } + } +} + /// A [`System`] with [`App`]-aware scheduling metadata. /// /// [`System`]: bevy_ecs::prelude::System @@ -26,7 +141,7 @@ pub trait IntoSystemAppConfig: Sized + IntoSystemConfig { let mut config = self.into_app_config(); if let Some(old_schedule) = &config.schedule { panic!( - "Cannot add system to schedule '{schedule:?}': it is already in {old_schedule:?}." + "Cannot add system to schedule '{schedule:?}': it is already in '{old_schedule:?}'." ); } config.schedule = Some(Box::new(schedule)); diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 51a737834484a..48864b6f3927d 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -80,39 +80,40 @@ fn ambiguous_with(graph_info: &mut GraphInfo, set: BoxedSystemSet) { /// Types that can be converted into a [`SystemSetConfig`]. /// /// This has been implemented for all types that implement [`SystemSet`] and boxed trait objects. -pub trait IntoSystemSetConfig: sealed::IntoSystemSetConfig { +pub trait IntoSystemSetConfig { + type Config; + /// Convert into a [`SystemSetConfig`]. #[doc(hidden)] - fn into_config(self) -> SystemSetConfig; + fn into_config(self) -> Self::Config; /// Add to the provided `set`. #[track_caller] - fn in_set(self, set: impl SystemSet) -> SystemSetConfig; + fn in_set(self, set: impl SystemSet) -> Self::Config; /// Add to the provided "base" `set`. For more information on base sets, see [`SystemSet::is_base`]. #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> SystemSetConfig; + fn in_base_set(self, set: impl SystemSet) -> Self::Config; /// Add this set to the schedules's default base set. - fn in_default_base_set(self) -> SystemSetConfig; + fn in_default_base_set(self) -> Self::Config; /// Run before all systems in `set`. - fn before(self, set: impl IntoSystemSet) -> SystemSetConfig; + fn before(self, set: impl IntoSystemSet) -> Self::Config; /// Run after all systems in `set`. - fn after(self, set: impl IntoSystemSet) -> SystemSetConfig; + fn after(self, set: impl IntoSystemSet) -> Self::Config; /// Run the systems in this set only if the [`Condition`] is `true`. /// /// The `Condition` will be evaluated at most once (per schedule run), /// the first time a system in this set prepares to run. - fn run_if

(self, condition: impl Condition

) -> SystemSetConfig; + fn run_if

(self, condition: impl Condition

) -> Self::Config; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with systems in `set`. - fn ambiguous_with(self, set: impl IntoSystemSet) -> SystemSetConfig; + fn ambiguous_with(self, set: impl IntoSystemSet) -> Self::Config; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with any other system. - fn ambiguous_with_all(self) -> SystemSetConfig; + fn ambiguous_with_all(self) -> Self::Config; } -impl IntoSystemSetConfig for S -where - S: SystemSet + sealed::IntoSystemSetConfig, -{ +impl IntoSystemSetConfig for S { + type Config = SystemSetConfig; + fn into_config(self) -> SystemSetConfig { SystemSetConfig::new(Box::new(self)) } @@ -153,6 +154,8 @@ where } impl IntoSystemSetConfig for BoxedSystemSet { + type Config = SystemSetConfig; + fn into_config(self) -> SystemSetConfig { SystemSetConfig::new(self) } @@ -193,6 +196,8 @@ impl IntoSystemSetConfig for BoxedSystemSet { } impl IntoSystemSetConfig for SystemSetConfig { + type Config = SystemSetConfig; + fn into_config(self) -> Self { self } @@ -464,21 +469,6 @@ impl IntoSystemConfig<()> for SystemConfig { } } -// only `System` system objects can be scheduled -mod sealed { - use crate::schedule::{BoxedSystemSet, SystemSet}; - - use super::SystemSetConfig; - - pub trait IntoSystemSetConfig {} - - impl IntoSystemSetConfig for S {} - - impl IntoSystemSetConfig for BoxedSystemSet {} - - impl IntoSystemSetConfig for SystemSetConfig {} -} - /// A collection of [`SystemConfig`]. pub struct SystemConfigs { pub(super) systems: Vec, @@ -837,7 +827,7 @@ macro_rules! impl_system_collection { macro_rules! impl_system_set_collection { ($($set: ident),*) => { - impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*) + impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*) { #[allow(non_snake_case)] fn into_configs(self) -> SystemSetConfigs { diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 25609f8e2c25b..a19864df58e81 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -205,8 +205,11 @@ impl Schedule { } /// Configures a system set in this schedule, adding it if it does not exist. - pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { - self.graph.configure_set(set); + pub fn configure_set( + &mut self, + set: impl IntoSystemSetConfig, + ) -> &mut Self { + self.graph.configure_set(set.into_config()); self } @@ -619,19 +622,16 @@ impl ScheduleGraph { } } - fn configure_set(&mut self, set: impl IntoSystemSetConfig) { - self.configure_set_inner(set).unwrap(); + fn configure_set(&mut self, set: impl IntoSystemSetConfig) { + self.configure_set_inner(set.into_config()).unwrap(); } - fn configure_set_inner( - &mut self, - set: impl IntoSystemSetConfig, - ) -> Result { + fn configure_set_inner(&mut self, set: SystemSetConfig) -> Result { let SystemSetConfig { set, graph_info, mut conditions, - } = set.into_config(); + } = set; let id = match self.system_set_ids.get(&set) { Some(&id) => id, From 05bf8c64e0ea5df3503e2d6b2d135a68f090e0a1 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:37:22 -0500 Subject: [PATCH 05/40] add a trait to the prelude --- crates/bevy_app/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 1c8b2689f4b7c..ac5c1fca9d790 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -25,8 +25,9 @@ pub mod prelude { pub use crate::AppTypeRegistry; #[doc(hidden)] pub use crate::{ - app::App, config::IntoSystemAppConfig, CoreSchedule, CoreSet, DynamicPlugin, Plugin, - PluginGroup, StartupSet, + app::App, + config::{IntoSystemAppConfig, IntoSystemSetAppConfig}, + CoreSchedule, CoreSet, DynamicPlugin, Plugin, PluginGroup, StartupSet, }; } From b462ce95c8e9e2b303198cdd416bbf9194764ec0 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:42:12 -0500 Subject: [PATCH 06/40] add an extension method for startup systems --- crates/bevy_app/src/config.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index ae4add38b29a9..b39852ca07dee 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -3,6 +3,8 @@ use bevy_ecs::schedule::{ ScheduleLabel, SystemConfig, SystemSet, SystemSetConfig, }; +use crate::CoreSchedule; + /// A [`SystemSet`] with [`App`]-aware scheduling metadata. /// /// [`App`]: crate::App @@ -148,6 +150,37 @@ pub trait IntoSystemAppConfig: Sized + IntoSystemConfig { config } + + /// Add to [`CoreSchedule::Startup`]. + /// + /// These systems will run exactly once, at the start of the [`App`]'s lifecycle. + /// To add a system that runs every frame, see [`add_system`](Self::add_system). + /// + /// # Examples + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// fn my_startup_system(_commands: Commands) { + /// println!("My startup system"); + /// } + /// + /// App::new() + /// .add_system(my_startup_system.on_startup()) + /// .run(); + /// ``` + fn on_startup(self) -> SystemAppConfig { + let mut config = self.into_app_config(); + if let Some(old_schedule) = &config.schedule { + panic!( + "Cannot add system to the startup schedule: it is already in '{old_schedule:?}'." + ); + } + config.schedule = Some(Box::new(CoreSchedule::Startup)); + + config + } } impl IntoSystemConfig<()> for SystemAppConfig { From 661ecf59244cdc16b89d26df92302f9bd9ac8950 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:56:44 -0500 Subject: [PATCH 07/40] use a defaulted type param instead of an associated type --- crates/bevy_app/src/app.rs | 9 +++---- crates/bevy_app/src/config.rs | 17 ++++++++++---- crates/bevy_ecs/src/schedule/config.rs | 30 +++++++++--------------- crates/bevy_ecs/src/schedule/schedule.rs | 16 ++++++------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index dfe31747571e8..cda806c2537c6 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ schedule::{ apply_state_transition, common_conditions::run_once as run_once_condition, run_enter_schedule, BoxedScheduleLabel, IntoSystemConfig, IntoSystemSetConfigs, - ScheduleLabel, SystemConfig, + ScheduleLabel, }, }; use bevy_utils::{tracing::debug, HashMap, HashSet}; @@ -434,7 +434,7 @@ impl App { pub fn add_system_to_schedule

( &mut self, schedule_label: impl ScheduleLabel, - system: impl IntoSystemConfig, + system: impl IntoSystemConfig

, ) -> &mut Self { let mut schedules = self.world.resource_mut::(); @@ -482,10 +482,7 @@ impl App { /// App::new() /// .add_startup_system(my_startup_system); /// ``` - pub fn add_startup_system

( - &mut self, - system: impl IntoSystemConfig, - ) -> &mut Self { + pub fn add_startup_system

(&mut self, system: impl IntoSystemConfig

) -> &mut Self { self.add_system_to_schedule(CoreSchedule::Startup, system) } diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index b39852ca07dee..e0e38bd194379 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -133,7 +133,12 @@ pub struct SystemAppConfig { /// /// This has been implemented for all `System` trait objects /// and all functions that convert into such. -pub trait IntoSystemAppConfig: Sized + IntoSystemConfig { +pub trait IntoSystemAppConfig: + Sized + IntoSystemConfig +{ + #[doc(hidden)] + type InnerConfig; + /// Converts into a [`SystemAppConfig`]. fn into_app_config(self) -> SystemAppConfig; @@ -183,9 +188,7 @@ pub trait IntoSystemAppConfig: Sized + IntoSystemConfig { } } -impl IntoSystemConfig<()> for SystemAppConfig { - type Config = Self; - +impl IntoSystemConfig<(), Self> for SystemAppConfig { fn into_config(self) -> Self { self } @@ -258,6 +261,8 @@ impl IntoSystemConfig<()> for SystemAppConfig { } impl IntoSystemAppConfig<()> for SystemAppConfig { + type InnerConfig = Self; + fn into_app_config(self) -> SystemAppConfig { self } @@ -265,8 +270,10 @@ impl IntoSystemAppConfig<()> for SystemAppConfig { impl IntoSystemAppConfig for T where - T: IntoSystemConfig, + T: IntoSystemConfig, { + type InnerConfig = SystemConfig; + fn into_app_config(self) -> SystemAppConfig { SystemAppConfig { system: self.into_config(), diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 48864b6f3927d..910ce1bcd9779 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -279,43 +279,39 @@ impl IntoSystemSetConfig for SystemSetConfig { /// /// This has been implemented for boxed [`System`](crate::system::System) /// trait objects and all functions that turn into such. -pub trait IntoSystemConfig { - type Config; - +pub trait IntoSystemConfig { /// Convert into a [`SystemConfig`]. #[doc(hidden)] - fn into_config(self) -> Self::Config; + fn into_config(self) -> Config; /// Add to `set` membership. #[track_caller] - fn in_set(self, set: impl SystemSet) -> Self::Config; + fn in_set(self, set: impl SystemSet) -> Config; /// Add to the provided "base" `set`. For more information on base sets, see [`SystemSet::is_base`]. #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> Self::Config; + fn in_base_set(self, set: impl SystemSet) -> Config; /// Don't add this system to the schedules's default set. - fn no_default_base_set(self) -> Self::Config; + fn no_default_base_set(self) -> Config; /// Run before all systems in `set`. - fn before(self, set: impl IntoSystemSet) -> Self::Config; + fn before(self, set: impl IntoSystemSet) -> Config; /// Run after all systems in `set`. - fn after(self, set: impl IntoSystemSet) -> Self::Config; + fn after(self, set: impl IntoSystemSet) -> Config; /// Run only if the [`Condition`] is `true`. /// /// The `Condition` will be evaluated at most once (per schedule run), /// when the system prepares to run. - fn run_if

(self, condition: impl Condition

) -> Self::Config; + fn run_if

(self, condition: impl Condition

) -> Config; /// Suppress warnings and errors that would result from this system having ambiguities /// (conflicting access but indeterminate order) with systems in `set`. - fn ambiguous_with(self, set: impl IntoSystemSet) -> Self::Config; + fn ambiguous_with(self, set: impl IntoSystemSet) -> Config; /// Suppress warnings and errors that would result from this system having ambiguities /// (conflicting access but indeterminate order) with any other system. - fn ambiguous_with_all(self) -> Self::Config; + fn ambiguous_with_all(self) -> Config; } impl IntoSystemConfig for F where F: IntoSystem<(), (), Params>, { - type Config = SystemConfig; - fn into_config(self) -> SystemConfig { SystemConfig::new(Box::new(IntoSystem::into_system(self))) } @@ -356,8 +352,6 @@ where } impl IntoSystemConfig<()> for BoxedSystem<(), ()> { - type Config = SystemConfig; - fn into_config(self) -> SystemConfig { SystemConfig::new(self) } @@ -398,8 +392,6 @@ impl IntoSystemConfig<()> for BoxedSystem<(), ()> { } impl IntoSystemConfig<()> for SystemConfig { - type Config = Self; - fn into_config(self) -> Self { self } @@ -811,7 +803,7 @@ macro_rules! impl_system_collection { ($(($param: ident, $sys: ident)),*) => { impl<$($param, $sys),*> IntoSystemConfigs<($($param,)*)> for ($($sys,)*) where - $($sys: IntoSystemConfig<$param, Config = SystemConfig>),* + $($sys: IntoSystemConfig<$param>),* { #[allow(non_snake_case)] fn into_configs(self) -> SystemConfigs { diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index a19864df58e81..05de5b6867205 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -190,10 +190,7 @@ impl Schedule { } /// Add a system to the schedule. - pub fn add_system

( - &mut self, - system: impl IntoSystemConfig, - ) -> &mut Self { + pub fn add_system

(&mut self, system: impl IntoSystemConfig

) -> &mut Self { self.graph.add_system(system); self } @@ -580,16 +577,19 @@ impl ScheduleGraph { } } - fn add_system

(&mut self, system: impl IntoSystemConfig) { - self.add_system_inner(system.into_config()).unwrap(); + fn add_system

(&mut self, system: impl IntoSystemConfig

) { + self.add_system_inner(system).unwrap(); } - fn add_system_inner(&mut self, system: SystemConfig) -> Result { + fn add_system_inner

( + &mut self, + system: impl IntoSystemConfig

, + ) -> Result { let SystemConfig { system, graph_info, conditions, - } = system; + } = system.into_config(); let id = NodeId::System(self.systems.len()); From e4c3a8c2a89cd55ca29a7637603ed67b9bfc67f8 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:00:49 -0500 Subject: [PATCH 08/40] simplify `IntoSystemSetConfig` --- crates/bevy_app/src/config.rs | 8 +++---- crates/bevy_ecs/src/schedule/config.rs | 30 +++++++++--------------- crates/bevy_ecs/src/schedule/schedule.rs | 16 ++++++------- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index e0e38bd194379..cf7d984399316 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -34,10 +34,8 @@ pub trait IntoSystemSetAppConfig: Sized + IntoSystemSetConfig { } } -impl IntoSystemSetConfig for SystemSetAppConfig { - type Config = Self; - - fn into_config(self) -> Self::Config { +impl IntoSystemSetConfig for SystemSetAppConfig { + fn into_config(self) -> Self { self } @@ -110,7 +108,7 @@ impl IntoSystemSetConfig for SystemSetAppConfig { impl IntoSystemSetAppConfig for T where - T: IntoSystemSetConfig, + T: IntoSystemSetConfig, { fn into_app_config(self) -> SystemSetAppConfig { SystemSetAppConfig { diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 910ce1bcd9779..8e115e0285409 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -80,40 +80,36 @@ fn ambiguous_with(graph_info: &mut GraphInfo, set: BoxedSystemSet) { /// Types that can be converted into a [`SystemSetConfig`]. /// /// This has been implemented for all types that implement [`SystemSet`] and boxed trait objects. -pub trait IntoSystemSetConfig { - type Config; - +pub trait IntoSystemSetConfig { /// Convert into a [`SystemSetConfig`]. #[doc(hidden)] - fn into_config(self) -> Self::Config; + fn into_config(self) -> Config; /// Add to the provided `set`. #[track_caller] - fn in_set(self, set: impl SystemSet) -> Self::Config; + fn in_set(self, set: impl SystemSet) -> Config; /// Add to the provided "base" `set`. For more information on base sets, see [`SystemSet::is_base`]. #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> Self::Config; + fn in_base_set(self, set: impl SystemSet) -> Config; /// Add this set to the schedules's default base set. - fn in_default_base_set(self) -> Self::Config; + fn in_default_base_set(self) -> Config; /// Run before all systems in `set`. - fn before(self, set: impl IntoSystemSet) -> Self::Config; + fn before(self, set: impl IntoSystemSet) -> Config; /// Run after all systems in `set`. - fn after(self, set: impl IntoSystemSet) -> Self::Config; + fn after(self, set: impl IntoSystemSet) -> Config; /// Run the systems in this set only if the [`Condition`] is `true`. /// /// The `Condition` will be evaluated at most once (per schedule run), /// the first time a system in this set prepares to run. - fn run_if

(self, condition: impl Condition

) -> Self::Config; + fn run_if

(self, condition: impl Condition

) -> Config; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with systems in `set`. - fn ambiguous_with(self, set: impl IntoSystemSet) -> Self::Config; + fn ambiguous_with(self, set: impl IntoSystemSet) -> Config; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with any other system. - fn ambiguous_with_all(self) -> Self::Config; + fn ambiguous_with_all(self) -> Config; } impl IntoSystemSetConfig for S { - type Config = SystemSetConfig; - fn into_config(self) -> SystemSetConfig { SystemSetConfig::new(Box::new(self)) } @@ -154,8 +150,6 @@ impl IntoSystemSetConfig for S { } impl IntoSystemSetConfig for BoxedSystemSet { - type Config = SystemSetConfig; - fn into_config(self) -> SystemSetConfig { SystemSetConfig::new(self) } @@ -196,8 +190,6 @@ impl IntoSystemSetConfig for BoxedSystemSet { } impl IntoSystemSetConfig for SystemSetConfig { - type Config = SystemSetConfig; - fn into_config(self) -> Self { self } @@ -819,7 +811,7 @@ macro_rules! impl_system_collection { macro_rules! impl_system_set_collection { ($($set: ident),*) => { - impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*) + impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*) { #[allow(non_snake_case)] fn into_configs(self) -> SystemSetConfigs { diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 05de5b6867205..b5bd6d2c0f55d 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -202,10 +202,7 @@ impl Schedule { } /// Configures a system set in this schedule, adding it if it does not exist. - pub fn configure_set( - &mut self, - set: impl IntoSystemSetConfig, - ) -> &mut Self { + pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { self.graph.configure_set(set.into_config()); self } @@ -622,16 +619,19 @@ impl ScheduleGraph { } } - fn configure_set(&mut self, set: impl IntoSystemSetConfig) { - self.configure_set_inner(set.into_config()).unwrap(); + fn configure_set(&mut self, set: impl IntoSystemSetConfig) { + self.configure_set_inner(set).unwrap(); } - fn configure_set_inner(&mut self, set: SystemSetConfig) -> Result { + fn configure_set_inner( + &mut self, + set: impl IntoSystemSetConfig, + ) -> Result { let SystemSetConfig { set, graph_info, mut conditions, - } = set; + } = set.into_config(); let id = match self.system_set_ids.get(&set) { Some(&id) => id, From c29a7663e5c3034f3e91333eede4d59d061090bd Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:11:04 -0500 Subject: [PATCH 09/40] add a missing impl --- crates/bevy_app/src/config.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index cf7d984399316..c78f56c24bca8 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -14,7 +14,10 @@ pub struct SystemSetAppConfig { } /// Types that can be converted into a [`SystemSetAppConfig`]. -pub trait IntoSystemSetAppConfig: Sized + IntoSystemSetConfig { +pub trait IntoSystemSetAppConfig: Sized + IntoSystemSetConfig { + #[doc(hidden)] + type InnerConfig; + /// Converts into a [`SystemSetAppConfig`]. #[doc(hidden)] fn into_app_config(self) -> SystemSetAppConfig; @@ -106,10 +109,19 @@ impl IntoSystemSetConfig for SystemSetAppConfig { } } +impl IntoSystemSetAppConfig for SystemSetAppConfig { + type InnerConfig = Self; + + fn into_app_config(self) -> SystemSetAppConfig { + self + } +} + impl IntoSystemSetAppConfig for T where T: IntoSystemSetConfig, { + type InnerConfig = SystemSetConfig; fn into_app_config(self) -> SystemSetAppConfig { SystemSetAppConfig { config: self.into_config(), From c52c844de7cdc38b3541eec6e86ebe8937c12b5a Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:25:15 -0500 Subject: [PATCH 10/40] revert system set changes --- crates/bevy_app/src/app.rs | 13 +-- crates/bevy_app/src/config.rs | 129 +------------------------ crates/bevy_app/src/lib.rs | 5 +- crates/bevy_ecs/src/schedule/config.rs | 20 ++-- 4 files changed, 19 insertions(+), 148 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index cda806c2537c6..06c000ad101bd 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,6 +1,5 @@ use crate::{ - CoreSchedule, CoreSet, IntoSystemAppConfig, IntoSystemSetAppConfig, Plugin, PluginGroup, - StartupSet, SystemAppConfig, SystemSetAppConfig, + CoreSchedule, CoreSet, IntoSystemAppConfig, Plugin, PluginGroup, StartupSet, SystemAppConfig, }; pub use bevy_derive::AppLabel; use bevy_ecs::{ @@ -8,7 +7,7 @@ use bevy_ecs::{ schedule::{ apply_state_transition, common_conditions::run_once as run_once_condition, run_enter_schedule, BoxedScheduleLabel, IntoSystemConfig, IntoSystemSetConfigs, - ScheduleLabel, + ScheduleLabel, SystemSetConfig, }, }; use bevy_utils::{tracing::debug, HashMap, HashSet}; @@ -512,14 +511,12 @@ impl App { } /// Configures a system set, adding the set if it does not exist. - pub fn configure_set(&mut self, set: impl IntoSystemSetAppConfig) -> &mut Self { - let SystemSetAppConfig { config, schedule } = set.into_app_config(); - + pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { self.world .resource_mut::() - .get_mut(schedule.as_deref().unwrap_or(&self.default_schedule_label)) + .get_mut(&*self.default_schedule_label) .unwrap() - .configure_set(config); + .configure_set(set); self } diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index c78f56c24bca8..bdc68de1ad514 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -1,135 +1,10 @@ use bevy_ecs::schedule::{ - BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, IntoSystemSetConfig, - ScheduleLabel, SystemConfig, SystemSet, SystemSetConfig, + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, ScheduleLabel, SystemConfig, + SystemSet, }; use crate::CoreSchedule; -/// A [`SystemSet`] with [`App`]-aware scheduling metadata. -/// -/// [`App`]: crate::App -pub struct SystemSetAppConfig { - pub(crate) config: SystemSetConfig, - pub(crate) schedule: Option, -} - -/// Types that can be converted into a [`SystemSetAppConfig`]. -pub trait IntoSystemSetAppConfig: Sized + IntoSystemSetConfig { - #[doc(hidden)] - type InnerConfig; - - /// Converts into a [`SystemSetAppConfig`]. - #[doc(hidden)] - fn into_app_config(self) -> SystemSetAppConfig; - - /// Add to the provided `schedule`. - #[track_caller] - fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemSetAppConfig { - let mut config = self.into_app_config(); - if let Some(old_schedule) = &config.schedule { - panic!( - "Cannot add system set to schedule '{schedule:?}': it is already in '{old_schedule:?}'." - ); - } - config.schedule = Some(Box::new(schedule)); - - config - } -} - -impl IntoSystemSetConfig for SystemSetAppConfig { - fn into_config(self) -> Self { - self - } - - #[track_caller] - fn in_set(self, set: impl SystemSet) -> Self { - let Self { config, schedule } = self; - Self { - config: config.in_set(set), - schedule, - } - } - - #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> Self { - let Self { config, schedule } = self; - Self { - config: config.in_base_set(set), - schedule, - } - } - - fn in_default_base_set(self) -> Self { - let Self { config, schedule } = self; - Self { - config: config.in_default_base_set(), - schedule, - } - } - - fn before(self, set: impl IntoSystemSet) -> Self { - let Self { config, schedule } = self; - Self { - config: config.before(set), - schedule, - } - } - - fn after(self, set: impl IntoSystemSet) -> Self { - let Self { config, schedule } = self; - Self { - config: config.after(set), - schedule, - } - } - - fn run_if

(self, condition: impl Condition

) -> Self { - let Self { config, schedule } = self; - Self { - config: config.run_if(condition), - schedule, - } - } - - fn ambiguous_with(self, set: impl IntoSystemSet) -> Self { - let Self { config, schedule } = self; - Self { - config: config.ambiguous_with(set), - schedule, - } - } - - fn ambiguous_with_all(self) -> Self { - let Self { config, schedule } = self; - Self { - config: config.ambiguous_with_all(), - schedule, - } - } -} - -impl IntoSystemSetAppConfig for SystemSetAppConfig { - type InnerConfig = Self; - - fn into_app_config(self) -> SystemSetAppConfig { - self - } -} - -impl IntoSystemSetAppConfig for T -where - T: IntoSystemSetConfig, -{ - type InnerConfig = SystemSetConfig; - fn into_app_config(self) -> SystemSetAppConfig { - SystemSetAppConfig { - config: self.into_config(), - schedule: None, - } - } -} - /// A [`System`] with [`App`]-aware scheduling metadata. /// /// [`System`]: bevy_ecs::prelude::System diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index ac5c1fca9d790..1c8b2689f4b7c 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -25,9 +25,8 @@ pub mod prelude { pub use crate::AppTypeRegistry; #[doc(hidden)] pub use crate::{ - app::App, - config::{IntoSystemAppConfig, IntoSystemSetAppConfig}, - CoreSchedule, CoreSet, DynamicPlugin, Plugin, PluginGroup, StartupSet, + app::App, config::IntoSystemAppConfig, CoreSchedule, CoreSet, DynamicPlugin, Plugin, + PluginGroup, StartupSet, }; } diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 8e115e0285409..dde63699e5b40 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -80,33 +80,33 @@ fn ambiguous_with(graph_info: &mut GraphInfo, set: BoxedSystemSet) { /// Types that can be converted into a [`SystemSetConfig`]. /// /// This has been implemented for all types that implement [`SystemSet`] and boxed trait objects. -pub trait IntoSystemSetConfig { +pub trait IntoSystemSetConfig { /// Convert into a [`SystemSetConfig`]. #[doc(hidden)] - fn into_config(self) -> Config; + fn into_config(self) -> SystemSetConfig; /// Add to the provided `set`. #[track_caller] - fn in_set(self, set: impl SystemSet) -> Config; + fn in_set(self, set: impl SystemSet) -> SystemSetConfig; /// Add to the provided "base" `set`. For more information on base sets, see [`SystemSet::is_base`]. #[track_caller] - fn in_base_set(self, set: impl SystemSet) -> Config; + fn in_base_set(self, set: impl SystemSet) -> SystemSetConfig; /// Add this set to the schedules's default base set. - fn in_default_base_set(self) -> Config; + fn in_default_base_set(self) -> SystemSetConfig; /// Run before all systems in `set`. - fn before(self, set: impl IntoSystemSet) -> Config; + fn before(self, set: impl IntoSystemSet) -> SystemSetConfig; /// Run after all systems in `set`. - fn after(self, set: impl IntoSystemSet) -> Config; + fn after(self, set: impl IntoSystemSet) -> SystemSetConfig; /// Run the systems in this set only if the [`Condition`] is `true`. /// /// The `Condition` will be evaluated at most once (per schedule run), /// the first time a system in this set prepares to run. - fn run_if

(self, condition: impl Condition

) -> Config; + fn run_if

(self, condition: impl Condition

) -> SystemSetConfig; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with systems in `set`. - fn ambiguous_with(self, set: impl IntoSystemSet) -> Config; + fn ambiguous_with(self, set: impl IntoSystemSet) -> SystemSetConfig; /// Suppress warnings and errors that would result from systems in this set having ambiguities /// (conflicting access but indeterminate order) with any other system. - fn ambiguous_with_all(self) -> Config; + fn ambiguous_with_all(self) -> SystemSetConfig; } impl IntoSystemSetConfig for S { From 56f991a85fb903ae92eaef3a589a7f9ae42d64fe Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:25:57 -0500 Subject: [PATCH 11/40] revert a comment --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 06c000ad101bd..63450b76da82c 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -510,7 +510,7 @@ impl App { self.add_systems_to_schedule(CoreSchedule::Startup, systems) } - /// Configures a system set, adding the set if it does not exist. + /// Configures a system set in the default schedule, adding the set if it does not exist. pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { self.world .resource_mut::() From 373076e6d16627b62a539bea9be9cf52d14a75ec Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:27:16 -0500 Subject: [PATCH 12/40] remove an unused import --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 63450b76da82c..d32548a7273a1 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -7,7 +7,7 @@ use bevy_ecs::{ schedule::{ apply_state_transition, common_conditions::run_once as run_once_condition, run_enter_schedule, BoxedScheduleLabel, IntoSystemConfig, IntoSystemSetConfigs, - ScheduleLabel, SystemSetConfig, + ScheduleLabel, }, }; use bevy_utils::{tracing::debug, HashMap, HashSet}; From 568efa2f23c9b7d81fc4ecae97867e4041ddd738 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 21:48:51 -0500 Subject: [PATCH 13/40] DRY --- crates/bevy_app/src/config.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index bdc68de1ad514..fa2ddf33fc315 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -60,16 +60,9 @@ pub trait IntoSystemAppConfig: /// .add_system(my_startup_system.on_startup()) /// .run(); /// ``` + #[inline] fn on_startup(self) -> SystemAppConfig { - let mut config = self.into_app_config(); - if let Some(old_schedule) = &config.schedule { - panic!( - "Cannot add system to the startup schedule: it is already in '{old_schedule:?}'." - ); - } - config.schedule = Some(Box::new(CoreSchedule::Startup)); - - config + self.in_schedule(CoreSchedule::Startup) } } From 70c9b234487243536be67d98948c6a1e9787010c Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 22:40:07 -0500 Subject: [PATCH 14/40] add extension methods to system collections --- crates/bevy_app/src/app.rs | 36 +++++++++-- crates/bevy_app/src/config.rs | 90 +++++++++++++++++++++++++- crates/bevy_ecs/src/schedule/config.rs | 14 ++++ 3 files changed, 130 insertions(+), 10 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index d32548a7273a1..0a216a0e1fc48 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,5 +1,6 @@ use crate::{ - CoreSchedule, CoreSet, IntoSystemAppConfig, Plugin, PluginGroup, StartupSet, SystemAppConfig, + CoreSchedule, CoreSet, IntoSystemAppConfig, IntoSystemAppConfigs, Plugin, PluginGroup, + ScheduleMode, StartupSet, SystemAppConfig, SystemAppConfigs, }; pub use bevy_derive::AppLabel; use bevy_ecs::{ @@ -416,14 +417,35 @@ impl App { /// # /// app.add_systems((system_a, system_b, system_c)); /// ``` - pub fn add_systems

(&mut self, systems: impl IntoSystemConfigs

) -> &mut Self { + pub fn add_systems

(&mut self, systems: impl IntoSystemAppConfigs

) -> &mut Self { let mut schedules = self.world.resource_mut::(); - if let Some(default_schedule) = schedules.get_mut(&*self.default_schedule_label) { - default_schedule.add_systems(systems); - } else { - let schedule_label = &self.default_schedule_label; - panic!("Default schedule {schedule_label:?} does not exist.") + let SystemAppConfigs { + systems, + schedule: schedule_mode, + } = systems.into_app_configs(); + + match schedule_mode { + ScheduleMode::None => { + if let Some(default_schedule) = schedules.get_mut(&*self.default_schedule_label) { + default_schedule.add_systems(systems); + } else { + let schedule_label = &self.default_schedule_label; + panic!("Default schedule {schedule_label:?} does not exist.") + } + } + ScheduleMode::Blanket(schedule) => { + if let Some(schedule) = schedules.get_mut(&*schedule) { + schedule.add_systems(systems); + } else { + panic!("Schedule {schedule:?} does not exist.") + } + } + ScheduleMode::Granular(schedule_labels) => { + for (system, schedule) in std::iter::zip(systems, schedule_labels) { + self.add_system(SystemAppConfig { system, schedule }); + } + } } self diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index fa2ddf33fc315..7745578d5804f 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -1,6 +1,9 @@ -use bevy_ecs::schedule::{ - BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemSet, ScheduleLabel, SystemConfig, - SystemSet, +use bevy_ecs::{ + all_tuples, + schedule::{ + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, + ScheduleLabel, SystemConfig, SystemConfigs, SystemSet, + }, }; use crate::CoreSchedule; @@ -159,3 +162,84 @@ where } } } + +/// A collection of [`SystemAppConfig`]s. +pub struct SystemAppConfigs { + pub(crate) systems: SystemConfigs, + pub(crate) schedule: ScheduleMode, +} + +pub(crate) enum ScheduleMode { + None, + Blanket(BoxedScheduleLabel), + Granular(Vec>), +} + +/// Types that can convert into [`SystemAppConfigs`]. +pub trait IntoSystemAppConfigs: Sized { + /// Converts to [`SystemAppConfigs`]. + fn into_app_configs(self) -> SystemAppConfigs; + + /// Adds the systems to the provided `schedule`. + fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemAppConfigs { + let mut configs = self.into_app_configs(); + + match &configs.schedule { + ScheduleMode::None => {} + ScheduleMode::Blanket(old_schedule) => panic!( + "Cannot add systems to the schedule '{schedule:?}: they are already in '{old_schedule:?}'" + ), + ScheduleMode::Granular(slots) => { + for slot in slots { + if let Some(old_schedule) = &slot { + panic!( + "Cannot add system to the schedule '{schedule:?}': it is already in '{old_schedule:?}'." + ); + } + } + } + } + + configs.schedule = ScheduleMode::Blanket(Box::new(schedule)); + + configs + } +} + +impl IntoSystemAppConfigs<()> for SystemAppConfigs { + fn into_app_configs(self) -> SystemAppConfigs { + self + } +} + +impl IntoSystemAppConfigs<()> for SystemConfigs { + fn into_app_configs(self) -> SystemAppConfigs { + SystemAppConfigs { + systems: self, + schedule: ScheduleMode::None, + } + } +} + +macro_rules! impl_system_collection { + ($(($param: ident, $sys: ident)),*) => { + impl<$($param, $sys),*> IntoSystemAppConfigs<($($param,)*)> for ($($sys,)*) + where + $($sys: IntoSystemAppConfig<$param>),* + { + #[allow(non_snake_case)] + fn into_app_configs(self) -> SystemAppConfigs { + let ($($sys,)*) = self; + $( + let mut $sys = $sys.into_app_config(); + )* + SystemAppConfigs { + schedule: ScheduleMode::Granular(vec![$($sys.schedule.take(),)*]), + systems: ($($sys.system,)*).into_configs(), + } + } + } + } +} + +all_tuples!(impl_system_collection, 0, 15, P, S); diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index dde63699e5b40..be60101622f6f 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -460,6 +460,20 @@ pub struct SystemConfigs { pub(super) chained: bool, } +impl SystemConfigs { + pub fn is_chained(&self) -> bool { + self.chained + } +} + +impl IntoIterator for SystemConfigs { + type Item = SystemConfig; + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.systems.into_iter() + } +} + /// Types that can convert into a [`SystemConfigs`]. pub trait IntoSystemConfigs where From ea3ce9409a219af4be6e50e98a033d7341601ad7 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 22:45:06 -0500 Subject: [PATCH 15/40] add a `.on_startup()` extension method --- crates/bevy_app/src/config.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 7745578d5804f..4964460f21243 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -204,6 +204,32 @@ pub trait IntoSystemAppConfigs: Sized { configs } + + /// Adds the systems to [`CoreSchedule::Startup`]. + /// + /// # Examples + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn first_system() {} + /// # fn startup_system_b() {} + /// # fn startup_system_c() {} + /// # + /// app.add_systems( + /// ( + /// first_system.on_startup(), + /// startup_system_b, + /// startup_system_c, + /// ) + /// .on_startup() + /// ); + /// ``` + fn on_startup(self) -> SystemAppConfigs { + self.in_schedule(CoreSchedule::Startup) + } } impl IntoSystemAppConfigs<()> for SystemAppConfigs { From 9e66a598d43ac55ccb4e6435836fc3d90baaa790 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 22:59:22 -0500 Subject: [PATCH 16/40] add extension methods for state schedules --- crates/bevy_app/src/config.rs | 14 ++++++++++++-- crates/bevy_app/src/lib.rs | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 4964460f21243..4a56b3c11532d 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -1,8 +1,8 @@ use bevy_ecs::{ all_tuples, schedule::{ - BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, - ScheduleLabel, SystemConfig, SystemConfigs, SystemSet, + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, OnEnter, + OnExit, ScheduleLabel, States, SystemConfig, SystemConfigs, SystemSet, }, }; @@ -67,6 +67,16 @@ pub trait IntoSystemAppConfig: fn on_startup(self) -> SystemAppConfig { self.in_schedule(CoreSchedule::Startup) } + + /// Run this system whenever `State` enters `state`. + fn on_enter(self, state: S) -> SystemAppConfig { + self.in_schedule(OnEnter(state)) + } + + /// Run this system whenever `State` exits `state`. + fn on_exit(self, state: S) -> SystemAppConfig { + self.in_schedule(OnExit(state)) + } } impl IntoSystemConfig<(), Self> for SystemAppConfig { diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 1c8b2689f4b7c..8348a7c16e15e 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -25,8 +25,9 @@ pub mod prelude { pub use crate::AppTypeRegistry; #[doc(hidden)] pub use crate::{ - app::App, config::IntoSystemAppConfig, CoreSchedule, CoreSet, DynamicPlugin, Plugin, - PluginGroup, StartupSet, + app::App, + config::{IntoSystemAppConfig, IntoSystemAppConfigs}, + CoreSchedule, CoreSet, DynamicPlugin, Plugin, PluginGroup, StartupSet, }; } From 4809e5301b8892ce3c884a4a39c7a638b7d16b2d Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:10:19 -0500 Subject: [PATCH 17/40] update some examples --- crates/bevy_pbr/src/lib.rs | 6 +-- examples/2d/texture_atlas.rs | 4 +- examples/ecs/generic_system.rs | 11 +++--- examples/ecs/state.rs | 8 ++-- examples/games/alien_cake_addict.rs | 16 +++++--- examples/games/game_menu.rs | 61 ++++++++++++----------------- 6 files changed, 50 insertions(+), 56 deletions(-) diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 7635dc1b8ff73..884b08a423ac7 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -268,12 +268,12 @@ impl Plugin for PbrPlugin { .configure_set(RenderLightSystems::PrepareLights.in_set(RenderSet::Prepare)) .configure_set(RenderLightSystems::PrepareClusters.in_set(RenderSet::Prepare)) .configure_set(RenderLightSystems::QueueShadows.in_set(RenderSet::Queue)) - .add_systems_to_schedule( - ExtractSchedule, + .add_systems( ( render::extract_clusters.in_set(RenderLightSystems::ExtractClusters), render::extract_lights.in_set(RenderLightSystems::ExtractLights), - ), + ) + .in_schedule(ExtractSchedule), ) .add_system( render::prepare_lights diff --git a/examples/2d/texture_atlas.rs b/examples/2d/texture_atlas.rs index fbb101426429d..6950cbfc722e9 100644 --- a/examples/2d/texture_atlas.rs +++ b/examples/2d/texture_atlas.rs @@ -8,9 +8,9 @@ fn main() { .init_resource::() .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) // prevents blurry sprites .add_state::() - .add_system_to_schedule(OnEnter(AppState::Setup), load_textures) + .add_system(load_textures.on_enter(AppState::Setup)) .add_system(check_textures.in_set(OnUpdate(AppState::Setup))) - .add_system_to_schedule(OnEnter(AppState::Finished), setup) + .add_system(setup.on_enter(AppState::Finished)) .run(); } diff --git a/examples/ecs/generic_system.rs b/examples/ecs/generic_system.rs index 2427985b1a9e3..bc12894c1a7c6 100644 --- a/examples/ecs/generic_system.rs +++ b/examples/ecs/generic_system.rs @@ -42,16 +42,15 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_state::() - .add_startup_system(setup_system) + .add_system(setup_system.on_startup()) .add_system(print_text_system) .add_system(transition_to_in_game_system.in_set(OnUpdate(AppState::MainMenu))) // add the cleanup systems - .add_system_to_schedule( - OnExit(AppState::MainMenu), + .add_systems(( // Pass in the types your system should operate on using the :: (turbofish) syntax - cleanup_system::, - ) - .add_system_to_schedule(OnExit(AppState::InGame), cleanup_system::) + cleanup_system::.on_exit(AppState::MainMenu), + cleanup_system::.on_exit(AppState::InGame), + )) .run(); } diff --git a/examples/ecs/state.rs b/examples/ecs/state.rs index 8e1802edd2d2e..1a43bd12674bd 100644 --- a/examples/ecs/state.rs +++ b/examples/ecs/state.rs @@ -11,16 +11,16 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_state::() - .add_startup_system(setup) + .add_system(setup.on_startup()) // This system runs when we enter `AppState::Menu`, during `CoreSet::StateTransitions`. // All systems from the exit schedule of the state we're leaving are run first, // and then all systems from the enter schedule of the state we're entering are run second. - .add_system_to_schedule(OnEnter(AppState::Menu), setup_menu) + .add_system(setup_menu.on_enter(AppState::Menu)) // By contrast, on_update systems are stored in the main schedule, during CoreSet::Update, // and simply check the value of the `State` resource to see if they should run each frame. .add_system(menu.in_set(OnUpdate(AppState::Menu))) - .add_system_to_schedule(OnExit(AppState::Menu), cleanup_menu) - .add_system_to_schedule(OnEnter(AppState::InGame), setup_game) + .add_system(cleanup_menu.on_exit(AppState::Menu)) + .add_system(setup_game.on_enter(AppState::InGame)) .add_systems((movement, change_color).in_set(OnUpdate(AppState::InGame))) .run(); } diff --git a/examples/games/alien_cake_addict.rs b/examples/games/alien_cake_addict.rs index e3d20575aa89c..73230430f12e2 100644 --- a/examples/games/alien_cake_addict.rs +++ b/examples/games/alien_cake_addict.rs @@ -24,8 +24,10 @@ fn main() { ))) .add_plugins(DefaultPlugins) .add_state::() - .add_startup_system(setup_cameras) - .add_system_to_schedule(OnEnter(GameState::Playing), setup) + .add_systems(( + setup_cameras.on_startup(), + setup.on_enter(GameState::Playing), + )) .add_systems( ( move_player, @@ -36,10 +38,12 @@ fn main() { ) .in_set(OnUpdate(GameState::Playing)), ) - .add_system_to_schedule(OnExit(GameState::Playing), teardown) - .add_system_to_schedule(OnEnter(GameState::GameOver), display_score) - .add_system(gameover_keyboard.in_set(OnUpdate(GameState::GameOver))) - .add_system_to_schedule(OnExit(GameState::GameOver), teardown) + .add_systems(( + teardown.on_exit(GameState::Playing), + display_score.on_enter(GameState::GameOver), + gameover_keyboard.in_set(OnUpdate(GameState::GameOver)), + teardown.on_exit(GameState::GameOver), + )) .add_system(bevy::window::close_on_esc) .run(); } diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index c7ea05559e347..95f38e2b0ed6d 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -60,14 +60,11 @@ mod splash { // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash` app // When entering the state, spawn everything needed for this screen - .add_system_to_schedule(OnEnter(GameState::Splash), splash_setup) + .add_system(splash_setup.on_enter(GameState::Splash)) // While in this state, run the `countdown` system .add_system(countdown.in_set(OnUpdate(GameState::Splash))) // When exiting the state, despawn everything that was spawned for this screen - .add_system_to_schedule( - OnExit(GameState::Splash), - despawn_screen::, - ); + .add_system(despawn_screen::.on_exit(GameState::Splash)); } } @@ -133,9 +130,11 @@ mod game { impl Plugin for GamePlugin { fn build(&self, app: &mut App) { - app.add_system_to_schedule(OnEnter(GameState::Game), game_setup) - .add_system(game.in_set(OnUpdate(GameState::Game))) - .add_system_to_schedule(OnExit(GameState::Game), despawn_screen::); + app.add_systems(( + game_setup.on_enter(GameState::Game), + game.in_set(OnUpdate(GameState::Game)), + despawn_screen::.on_exit(GameState::Game), + )); } } @@ -268,38 +267,30 @@ mod menu { // entering the `GameState::Menu` state. // Current screen in the menu is handled by an independent state from `GameState` .add_state::() - .add_system_to_schedule(OnEnter(GameState::Menu), menu_setup) + .add_system(menu_setup.on_enter(GameState::Menu)) // Systems to handle the main menu screen - .add_system_to_schedule(OnEnter(MenuState::Main), main_menu_setup) - .add_system_to_schedule(OnExit(MenuState::Main), despawn_screen::) + .add_systems(( + main_menu_setup.on_enter(MenuState::Main), + despawn_screen::.on_exit(MenuState::Main), + )) // Systems to handle the settings menu screen - .add_system_to_schedule(OnEnter(MenuState::Settings), settings_menu_setup) - .add_system_to_schedule( - OnExit(MenuState::Settings), - despawn_screen::, - ) + .add_systems(( + settings_menu_setup.on_enter(MenuState::Settings), + despawn_screen::.on_exit(MenuState::Settings), + )) // Systems to handle the display settings screen - .add_system_to_schedule( - OnEnter(MenuState::SettingsDisplay), - display_settings_menu_setup, - ) - .add_system( + .add_systems(( + display_settings_menu_setup.on_enter(MenuState::SettingsDisplay), setting_button::.in_set(OnUpdate(MenuState::SettingsDisplay)), - ) - .add_system_to_schedule( - OnExit(MenuState::SettingsDisplay), - despawn_screen::, - ) + despawn_screen:: + .on_exit(MenuState::SettingsDisplay), + )) // Systems to handle the sound settings screen - .add_system_to_schedule( - OnEnter(MenuState::SettingsSound), - sound_settings_menu_setup, - ) - .add_system(setting_button::.in_set(OnUpdate(MenuState::SettingsSound))) - .add_system_to_schedule( - OnExit(MenuState::SettingsSound), - despawn_screen::, - ) + .add_systems(( + sound_settings_menu_setup.on_enter(MenuState::SettingsSound), + setting_button::.in_set(OnUpdate(MenuState::SettingsSound)), + despawn_screen::.on_exit(MenuState::SettingsSound), + )) // Common systems to all screens that handles buttons behaviour .add_systems((menu_action, button_system).in_set(OnUpdate(GameState::Menu))); } From 9027c76a26a55c2555123aaa385ec363943e0a8c Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:14:36 -0500 Subject: [PATCH 18/40] track callers --- crates/bevy_app/src/config.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 4a56b3c11532d..f8ca3b5fefad8 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -69,11 +69,13 @@ pub trait IntoSystemAppConfig: } /// Run this system whenever `State` enters `state`. + #[track_caller] fn on_enter(self, state: S) -> SystemAppConfig { self.in_schedule(OnEnter(state)) } /// Run this system whenever `State` exits `state`. + #[track_caller] fn on_exit(self, state: S) -> SystemAppConfig { self.in_schedule(OnExit(state)) } @@ -191,6 +193,7 @@ pub trait IntoSystemAppConfigs: Sized { fn into_app_configs(self) -> SystemAppConfigs; /// Adds the systems to the provided `schedule`. + #[track_caller] fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemAppConfigs { let mut configs = self.into_app_configs(); @@ -237,6 +240,7 @@ pub trait IntoSystemAppConfigs: Sized { /// .on_startup() /// ); /// ``` + #[track_caller] fn on_startup(self) -> SystemAppConfigs { self.in_schedule(CoreSchedule::Startup) } From b147c6d47dd872558d34b443cc420063ef034727 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:17:50 -0500 Subject: [PATCH 19/40] fix a doctest --- crates/bevy_app/src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index f8ca3b5fefad8..7bf5e17548de0 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -227,13 +227,13 @@ pub trait IntoSystemAppConfigs: Sized { /// # use bevy_ecs::prelude::*; /// # /// # let mut app = App::new(); - /// # fn first_system() {} + /// # fn startup_system_a() {} /// # fn startup_system_b() {} /// # fn startup_system_c() {} /// # /// app.add_systems( /// ( - /// first_system.on_startup(), + /// startup_system_a, /// startup_system_b, /// startup_system_c, /// ) From 9a8067404c41e56cae1e212e94710a5677fc8a70 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:21:14 -0500 Subject: [PATCH 20/40] Update config.rs --- crates/bevy_app/src/config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 7bf5e17548de0..ef4f5659a4661 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -60,8 +60,7 @@ pub trait IntoSystemAppConfig: /// } /// /// App::new() - /// .add_system(my_startup_system.on_startup()) - /// .run(); + /// .add_system(my_startup_system.on_startup()); /// ``` #[inline] fn on_startup(self) -> SystemAppConfig { From bc4fddb49b3840aa7d5de30a541e6a3185fbabab Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:27:27 -0500 Subject: [PATCH 21/40] use an explicit deref --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 0a216a0e1fc48..cda146634eaba 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -387,7 +387,7 @@ impl App { let SystemAppConfig { system, schedule } = system.into_app_config(); if let Some(schedule_label) = schedule { - if let Some(schedule) = schedules.get_mut(&schedule_label) { + if let Some(schedule) = schedules.get_mut(&*schedule_label) { schedule.add_system(system); } else { panic!("Schedule {schedule_label:?} does not exist.") From 1a7cfe09156052f8eb4f9edffc737b1a0ead4932 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:28:02 -0500 Subject: [PATCH 22/40] Revert "Update config.rs" This reverts commit 9a8067404c41e56cae1e212e94710a5677fc8a70. --- crates/bevy_app/src/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index ef4f5659a4661..7bf5e17548de0 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -60,7 +60,8 @@ pub trait IntoSystemAppConfig: /// } /// /// App::new() - /// .add_system(my_startup_system.on_startup()); + /// .add_system(my_startup_system.on_startup()) + /// .run(); /// ``` #[inline] fn on_startup(self) -> SystemAppConfig { From 420b8d87fc7be93a383ec572d45930efa679b5fb Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:33:37 -0500 Subject: [PATCH 23/40] remove an unused method --- crates/bevy_ecs/src/schedule/config.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index be60101622f6f..282a378d57bad 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -460,12 +460,6 @@ pub struct SystemConfigs { pub(super) chained: bool, } -impl SystemConfigs { - pub fn is_chained(&self) -> bool { - self.chained - } -} - impl IntoIterator for SystemConfigs { type Item = SystemConfig; type IntoIter = std::vec::IntoIter; From b4167fb30037f2eeebbf117321fec66f7f35e302 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:37:40 -0500 Subject: [PATCH 24/40] add state extension methods to system configs --- crates/bevy_app/src/config.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 7bf5e17548de0..7340d09bb8c99 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -244,6 +244,18 @@ pub trait IntoSystemAppConfigs: Sized { fn on_startup(self) -> SystemAppConfigs { self.in_schedule(CoreSchedule::Startup) } + + /// Run these systems whenever `State` enters `state`. + #[track_caller] + fn on_enter(self, state: S) -> SystemAppConfigs { + self.in_schedule(OnEnter(state)) + } + + /// Run these systems whenever `State` exits `state`. + #[track_caller] + fn on_exit(self, state: S) -> SystemAppConfigs { + self.in_schedule(OnExit(state)) + } } impl IntoSystemAppConfigs<()> for SystemAppConfigs { From c900ce7f40f79337872eba5674ac18f45eb73485 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:39:43 -0500 Subject: [PATCH 25/40] qualify a doc link --- crates/bevy_app/src/config.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 7340d09bb8c99..8b562a20854f3 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -49,6 +49,8 @@ pub trait IntoSystemAppConfig: /// These systems will run exactly once, at the start of the [`App`]'s lifecycle. /// To add a system that runs every frame, see [`add_system`](Self::add_system). /// + /// [`App`]: crate::App + /// /// # Examples /// /// ``` From ab5deb1844ca9cb8e8c76a42fe1ede51566e3f26 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:40:45 -0500 Subject: [PATCH 26/40] remove an inaccurate doc note --- crates/bevy_app/src/config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 8b562a20854f3..b27e4b1e29eda 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -44,10 +44,9 @@ pub trait IntoSystemAppConfig: config } - /// Add to [`CoreSchedule::Startup`]. + /// Add this system to [`CoreSchedule::Startup`]. /// /// These systems will run exactly once, at the start of the [`App`]'s lifecycle. - /// To add a system that runs every frame, see [`add_system`](Self::add_system). /// /// [`App`]: crate::App /// From 38f3fcc38e5782519949fd7ae3c07af0f24fb7a8 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:52:32 -0500 Subject: [PATCH 27/40] reduce churn --- crates/bevy_ecs/src/schedule/schedule.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index b5bd6d2c0f55d..04aaafbccb255 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -203,7 +203,7 @@ impl Schedule { /// Configures a system set in this schedule, adding it if it does not exist. pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self { - self.graph.configure_set(set.into_config()); + self.graph.configure_set(set); self } From f8f43ea51a5b1f7f04ed4d5eeacc35f65709ee10 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 00:23:02 -0500 Subject: [PATCH 28/40] simplify `IntoSystemAppConfig` generics --- crates/bevy_app/src/config.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index b27e4b1e29eda..3e5a442534dc5 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -21,12 +21,7 @@ pub struct SystemAppConfig { /// /// This has been implemented for all `System` trait objects /// and all functions that convert into such. -pub trait IntoSystemAppConfig: - Sized + IntoSystemConfig -{ - #[doc(hidden)] - type InnerConfig; - +pub trait IntoSystemAppConfig: Sized { /// Converts into a [`SystemAppConfig`]. fn into_app_config(self) -> SystemAppConfig; @@ -155,8 +150,6 @@ impl IntoSystemConfig<(), Self> for SystemAppConfig { } impl IntoSystemAppConfig<()> for SystemAppConfig { - type InnerConfig = Self; - fn into_app_config(self) -> SystemAppConfig { self } @@ -166,8 +159,6 @@ impl IntoSystemAppConfig for T where T: IntoSystemConfig, { - type InnerConfig = SystemConfig; - fn into_app_config(self) -> SystemAppConfig { SystemAppConfig { system: self.into_config(), From cd7b09f5c2c7bda8f48c4015a7c56d74982e3e2d Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 00:40:16 -0500 Subject: [PATCH 29/40] document an enum --- crates/bevy_app/src/config.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 3e5a442534dc5..d82b3518873ac 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -175,7 +175,9 @@ pub struct SystemAppConfigs { pub(crate) enum ScheduleMode { None, + // All systems in the same schedule. Blanket(BoxedScheduleLabel), + // Each system gets its own schedule. Granular(Vec>), } From e87f21fd01589854b92ae6dc910aa4cba8227b62 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 09:59:31 -0500 Subject: [PATCH 30/40] improve documentation --- crates/bevy_app/src/config.rs | 64 +++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index d82b3518873ac..6e6b15f851613 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -25,7 +25,15 @@ pub trait IntoSystemAppConfig: Sized { /// Converts into a [`SystemAppConfig`]. fn into_app_config(self) -> SystemAppConfig; - /// Add to the provided `schedule`. + /// Adds the system to the provided `schedule`. + /// + /// If a schedule is not specified, it will be added to the [`App`]'s default schedule. + /// + /// [`App`]: crate::App + /// + /// # Panics + /// + /// If the system has already been assigned to a schedule. #[track_caller] fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemAppConfig { let mut config = self.into_app_config(); @@ -39,9 +47,10 @@ pub trait IntoSystemAppConfig: Sized { config } - /// Add this system to [`CoreSchedule::Startup`]. + /// Adds the system to [`CoreSchedule::Startup`]. + /// This is a shorthand for `self.in_schedule(CoreSchedule::Startup)`. /// - /// These systems will run exactly once, at the start of the [`App`]'s lifecycle. + /// Systems in this schedule will run exactly once, at the start of the [`App`]'s lifecycle. /// /// [`App`]: crate::App /// @@ -59,18 +68,34 @@ pub trait IntoSystemAppConfig: Sized { /// .add_system(my_startup_system.on_startup()) /// .run(); /// ``` + /// + /// # Panics + /// + /// If the system has already been assigned to a schedule. #[inline] fn on_startup(self) -> SystemAppConfig { self.in_schedule(CoreSchedule::Startup) } - /// Run this system whenever `State` enters `state`. + /// Adds the system to [`OnEnter(state)`]. + /// + /// Systems in this schedule will run whenever [`States`] enters `state`. + /// + /// # Panics + /// + /// If the system has already been assigned to a schedule. #[track_caller] fn on_enter(self, state: S) -> SystemAppConfig { self.in_schedule(OnEnter(state)) } - /// Run this system whenever `State` exits `state`. + /// Adds the system to [`OnExit(state)`]. + /// + /// Systems in this schedule will run whenever [`States`] leaves `state`. + /// + /// # Panics + /// + /// If the system has already been assigned to a schedule. #[track_caller] fn on_exit(self, state: S) -> SystemAppConfig { self.in_schedule(OnExit(state)) @@ -187,6 +212,14 @@ pub trait IntoSystemAppConfigs: Sized { fn into_app_configs(self) -> SystemAppConfigs; /// Adds the systems to the provided `schedule`. + /// + /// If a schedule is not specified, they will be added to the [`App`]'s default schedule. + /// + /// [`App`]: crate::App + /// + /// # Panics + /// + /// If any of the systems have already been assigned to a schedule. #[track_caller] fn in_schedule(self, schedule: impl ScheduleLabel) -> SystemAppConfigs { let mut configs = self.into_app_configs(); @@ -213,6 +246,7 @@ pub trait IntoSystemAppConfigs: Sized { } /// Adds the systems to [`CoreSchedule::Startup`]. + /// This is a shorthand for `self.in_schedule(CoreSchedule::Startup)`. /// /// # Examples /// @@ -234,18 +268,34 @@ pub trait IntoSystemAppConfigs: Sized { /// .on_startup() /// ); /// ``` + /// + /// # Panics + /// + /// If any of the systems have already been assigned to a schedule. #[track_caller] fn on_startup(self) -> SystemAppConfigs { self.in_schedule(CoreSchedule::Startup) } - /// Run these systems whenever `State` enters `state`. + /// Adds the systems to [`OnEnter(state)`]. + /// + /// Systems in this schedule will run whenever [`States`] enters `state`. + /// + /// # Panics + /// + /// If any of the systems have already been assigned to a schedule. #[track_caller] fn on_enter(self, state: S) -> SystemAppConfigs { self.in_schedule(OnEnter(state)) } - /// Run these systems whenever `State` exits `state`. + /// Adds the systems to [`OnExit(state)`]. + /// + /// Systems in this schedule will run whenever [`States`] leaves `state`. + /// + /// # Panics + /// + /// If any of the systems have already been assigned to a schedule. #[track_caller] fn on_exit(self, state: S) -> SystemAppConfigs { self.in_schedule(OnExit(state)) From 8506485cee039aab5821923fb426e07f3bd00721 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 12:37:48 -0500 Subject: [PATCH 31/40] add more docs to `ScheduleMode` --- crates/bevy_app/src/config.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 6e6b15f851613..927ed29bc4099 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -198,11 +198,13 @@ pub struct SystemAppConfigs { pub(crate) schedule: ScheduleMode, } + +/// Stores the schedule/s associated with a set of [`SystemConfigs`]. pub(crate) enum ScheduleMode { None, - // All systems in the same schedule. + /// All systems in the same schedule. Blanket(BoxedScheduleLabel), - // Each system gets its own schedule. + /// Each system gets its own schedule. Granular(Vec>), } From c262c030993f3dd3df7ede708771d1927b31be0a Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 12:54:18 -0500 Subject: [PATCH 32/40] cargo fmt --- crates/bevy_app/src/config.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 927ed29bc4099..6c3c77f1b7f73 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -198,7 +198,6 @@ pub struct SystemAppConfigs { pub(crate) schedule: ScheduleMode, } - /// Stores the schedule/s associated with a set of [`SystemConfigs`]. pub(crate) enum ScheduleMode { None, From 63c8563659fe35da1693aacb827382972a397b94 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:21:54 -0500 Subject: [PATCH 33/40] remove `on_enter`/`on_exit` --- crates/bevy_app/src/config.rs | 52 ++--------------------------------- 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/crates/bevy_app/src/config.rs b/crates/bevy_app/src/config.rs index 6c3c77f1b7f73..ef508e86fa87b 100644 --- a/crates/bevy_app/src/config.rs +++ b/crates/bevy_app/src/config.rs @@ -1,8 +1,8 @@ use bevy_ecs::{ all_tuples, schedule::{ - BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, OnEnter, - OnExit, ScheduleLabel, States, SystemConfig, SystemConfigs, SystemSet, + BoxedScheduleLabel, Condition, IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, + ScheduleLabel, SystemConfig, SystemConfigs, SystemSet, }, }; @@ -76,30 +76,6 @@ pub trait IntoSystemAppConfig: Sized { fn on_startup(self) -> SystemAppConfig { self.in_schedule(CoreSchedule::Startup) } - - /// Adds the system to [`OnEnter(state)`]. - /// - /// Systems in this schedule will run whenever [`States`] enters `state`. - /// - /// # Panics - /// - /// If the system has already been assigned to a schedule. - #[track_caller] - fn on_enter(self, state: S) -> SystemAppConfig { - self.in_schedule(OnEnter(state)) - } - - /// Adds the system to [`OnExit(state)`]. - /// - /// Systems in this schedule will run whenever [`States`] leaves `state`. - /// - /// # Panics - /// - /// If the system has already been assigned to a schedule. - #[track_caller] - fn on_exit(self, state: S) -> SystemAppConfig { - self.in_schedule(OnExit(state)) - } } impl IntoSystemConfig<(), Self> for SystemAppConfig { @@ -277,30 +253,6 @@ pub trait IntoSystemAppConfigs: Sized { fn on_startup(self) -> SystemAppConfigs { self.in_schedule(CoreSchedule::Startup) } - - /// Adds the systems to [`OnEnter(state)`]. - /// - /// Systems in this schedule will run whenever [`States`] enters `state`. - /// - /// # Panics - /// - /// If any of the systems have already been assigned to a schedule. - #[track_caller] - fn on_enter(self, state: S) -> SystemAppConfigs { - self.in_schedule(OnEnter(state)) - } - - /// Adds the systems to [`OnExit(state)`]. - /// - /// Systems in this schedule will run whenever [`States`] leaves `state`. - /// - /// # Panics - /// - /// If any of the systems have already been assigned to a schedule. - #[track_caller] - fn on_exit(self, state: S) -> SystemAppConfigs { - self.in_schedule(OnExit(state)) - } } impl IntoSystemAppConfigs<()> for SystemAppConfigs { From bd453adccfb72f31aacb9e28496294d8831b78f0 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:27:15 -0500 Subject: [PATCH 34/40] update examples --- examples/2d/texture_atlas.rs | 4 ++-- examples/ecs/generic_system.rs | 4 ++-- examples/ecs/state.rs | 6 +++--- examples/games/alien_cake_addict.rs | 8 ++++---- examples/games/game_menu.rs | 29 ++++++++++++++++------------- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/examples/2d/texture_atlas.rs b/examples/2d/texture_atlas.rs index 6950cbfc722e9..678fb7d97be76 100644 --- a/examples/2d/texture_atlas.rs +++ b/examples/2d/texture_atlas.rs @@ -8,9 +8,9 @@ fn main() { .init_resource::() .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) // prevents blurry sprites .add_state::() - .add_system(load_textures.on_enter(AppState::Setup)) + .add_system(load_textures.in_schedule(OnEnter(AppState::Setup))) .add_system(check_textures.in_set(OnUpdate(AppState::Setup))) - .add_system(setup.on_enter(AppState::Finished)) + .add_system(setup.in_schedule(OnEnter(AppState::Finished))) .run(); } diff --git a/examples/ecs/generic_system.rs b/examples/ecs/generic_system.rs index bc12894c1a7c6..aa63428f669f1 100644 --- a/examples/ecs/generic_system.rs +++ b/examples/ecs/generic_system.rs @@ -48,8 +48,8 @@ fn main() { // add the cleanup systems .add_systems(( // Pass in the types your system should operate on using the :: (turbofish) syntax - cleanup_system::.on_exit(AppState::MainMenu), - cleanup_system::.on_exit(AppState::InGame), + cleanup_system::.in_schedule(OnExit(AppState::MainMenu)), + cleanup_system::.in_schedule(OnExit(AppState::InGame)), )) .run(); } diff --git a/examples/ecs/state.rs b/examples/ecs/state.rs index 1a43bd12674bd..ed03f9417a296 100644 --- a/examples/ecs/state.rs +++ b/examples/ecs/state.rs @@ -15,12 +15,12 @@ fn main() { // This system runs when we enter `AppState::Menu`, during `CoreSet::StateTransitions`. // All systems from the exit schedule of the state we're leaving are run first, // and then all systems from the enter schedule of the state we're entering are run second. - .add_system(setup_menu.on_enter(AppState::Menu)) + .add_system(setup_menu.in_schedule(OnEnter(AppState::Menu))) // By contrast, on_update systems are stored in the main schedule, during CoreSet::Update, // and simply check the value of the `State` resource to see if they should run each frame. .add_system(menu.in_set(OnUpdate(AppState::Menu))) - .add_system(cleanup_menu.on_exit(AppState::Menu)) - .add_system(setup_game.on_enter(AppState::InGame)) + .add_system(cleanup_menu.in_schedule(OnExit(AppState::Menu))) + .add_system(setup_game.in_schedule(OnEnter(AppState::InGame))) .add_systems((movement, change_color).in_set(OnUpdate(AppState::InGame))) .run(); } diff --git a/examples/games/alien_cake_addict.rs b/examples/games/alien_cake_addict.rs index 73230430f12e2..e9c27a6e928bf 100644 --- a/examples/games/alien_cake_addict.rs +++ b/examples/games/alien_cake_addict.rs @@ -26,7 +26,7 @@ fn main() { .add_state::() .add_systems(( setup_cameras.on_startup(), - setup.on_enter(GameState::Playing), + setup.in_schedule(OnEnter(GameState::Playing)), )) .add_systems( ( @@ -39,10 +39,10 @@ fn main() { .in_set(OnUpdate(GameState::Playing)), ) .add_systems(( - teardown.on_exit(GameState::Playing), - display_score.on_enter(GameState::GameOver), + teardown.in_schedule(OnExit(GameState::Playing)), + display_score.in_schedule(OnEnter(GameState::GameOver)), gameover_keyboard.in_set(OnUpdate(GameState::GameOver)), - teardown.on_exit(GameState::GameOver), + teardown.in_schedule(OnExit(GameState::GameOver)), )) .add_system(bevy::window::close_on_esc) .run(); diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 95f38e2b0ed6d..972aa93ffbf16 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -60,11 +60,13 @@ mod splash { // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash` app // When entering the state, spawn everything needed for this screen - .add_system(splash_setup.on_enter(GameState::Splash)) + .add_system(splash_setup.in_schedule(OnEnter(GameState::Splash))) // While in this state, run the `countdown` system .add_system(countdown.in_set(OnUpdate(GameState::Splash))) // When exiting the state, despawn everything that was spawned for this screen - .add_system(despawn_screen::.on_exit(GameState::Splash)); + .add_system( + despawn_screen::.in_schedule(OnExit(GameState::Splash)), + ); } } @@ -131,9 +133,9 @@ mod game { impl Plugin for GamePlugin { fn build(&self, app: &mut App) { app.add_systems(( - game_setup.on_enter(GameState::Game), + game_setup.in_schedule(OnEnter(GameState::Game)), game.in_set(OnUpdate(GameState::Game)), - despawn_screen::.on_exit(GameState::Game), + despawn_screen::.in_schedule(OnExit(GameState::Game)), )); } } @@ -267,29 +269,30 @@ mod menu { // entering the `GameState::Menu` state. // Current screen in the menu is handled by an independent state from `GameState` .add_state::() - .add_system(menu_setup.on_enter(GameState::Menu)) + .add_system(menu_setup.in_schedule(OnEnter(GameState::Menu))) // Systems to handle the main menu screen .add_systems(( - main_menu_setup.on_enter(MenuState::Main), - despawn_screen::.on_exit(MenuState::Main), + main_menu_setup.in_schedule(OnEnter(MenuState::Main)), + despawn_screen::.in_schedule(OnExit(MenuState::Main)), )) // Systems to handle the settings menu screen .add_systems(( - settings_menu_setup.on_enter(MenuState::Settings), - despawn_screen::.on_exit(MenuState::Settings), + settings_menu_setup.in_schedule(OnEnter(MenuState::Settings)), + despawn_screen::.in_schedule(OnExit(MenuState::Settings)), )) // Systems to handle the display settings screen .add_systems(( - display_settings_menu_setup.on_enter(MenuState::SettingsDisplay), + display_settings_menu_setup.in_schedule(OnEnter(MenuState::SettingsDisplay)), setting_button::.in_set(OnUpdate(MenuState::SettingsDisplay)), despawn_screen:: - .on_exit(MenuState::SettingsDisplay), + .in_schedule(OnExit(MenuState::SettingsDisplay)), )) // Systems to handle the sound settings screen .add_systems(( - sound_settings_menu_setup.on_enter(MenuState::SettingsSound), + sound_settings_menu_setup.in_schedule(OnEnter(MenuState::SettingsSound)), setting_button::.in_set(OnUpdate(MenuState::SettingsSound)), - despawn_screen::.on_exit(MenuState::SettingsSound), + despawn_screen:: + .in_schedule(OnExit(MenuState::SettingsSound)), )) // Common systems to all screens that handles buttons behaviour .add_systems((menu_action, button_system).in_set(OnUpdate(GameState::Menu))); From e8862af708cda409dd681d7380a6f908f43c082e Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:40:09 -0500 Subject: [PATCH 35/40] replace usages of `add_system_to_schedule` --- crates/bevy_app/src/app.rs | 4 ++-- crates/bevy_core_pipeline/src/core_2d/mod.rs | 4 ++-- crates/bevy_core_pipeline/src/core_3d/mod.rs | 4 ++-- crates/bevy_pbr/src/material.rs | 4 ++-- crates/bevy_pbr/src/prepass/mod.rs | 4 ++-- crates/bevy_pbr/src/render/mesh.rs | 4 ++-- crates/bevy_render/src/camera/mod.rs | 4 ++-- crates/bevy_render/src/extract_component.rs | 6 +++--- crates/bevy_render/src/extract_resource.rs | 4 ++-- crates/bevy_render/src/globals.rs | 4 ++-- crates/bevy_render/src/render_asset.rs | 4 ++-- crates/bevy_render/src/view/window.rs | 4 ++-- crates/bevy_sprite/src/mesh2d/material.rs | 4 ++-- crates/bevy_sprite/src/mesh2d/mesh.rs | 4 ++-- examples/2d/mesh2d_manual.rs | 2 +- examples/ecs/fixed_timestep.rs | 2 +- examples/ecs/iter_combinations.rs | 2 +- examples/stress_tests/bevymark.rs | 2 +- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 7336d9f850341..bd40053cb6e62 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -504,7 +504,7 @@ impl App { /// .add_startup_system(my_startup_system); /// ``` pub fn add_startup_system(&mut self, system: impl IntoSystemConfig) -> &mut Self { - self.add_system_to_schedule(CoreSchedule::Startup, system) + self.add_system(system.in_schedule(CoreSchedule::Startup)) } /// Adds a collection of systems to [`CoreSchedule::Startup`]. @@ -529,7 +529,7 @@ impl App { /// ); /// ``` pub fn add_startup_systems(&mut self, systems: impl IntoSystemConfigs) -> &mut Self { - self.add_systems_to_schedule(CoreSchedule::Startup, systems) + self.add_systems(systems.into_configs().in_schedule(CoreSchedule::Startup)) } /// Configures a system set in the default schedule, adding the set if it does not exist. diff --git a/crates/bevy_core_pipeline/src/core_2d/mod.rs b/crates/bevy_core_pipeline/src/core_2d/mod.rs index f02c78cf6d0f6..233671a159ab0 100644 --- a/crates/bevy_core_pipeline/src/core_2d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_2d/mod.rs @@ -19,7 +19,7 @@ pub mod graph { pub use camera_2d::*; pub use main_pass_2d_node::*; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_ecs::prelude::*; use bevy_render::{ camera::Camera, @@ -51,7 +51,7 @@ impl Plugin for Core2dPlugin { render_app .init_resource::>() - .add_system_to_schedule(ExtractSchedule, extract_core_2d_camera_phases) + .add_system(extract_core_2d_camera_phases.in_schedule(ExtractSchedule)) .add_system(sort_phase_system::.in_set(RenderSet::PhaseSort)) .add_system( batch_phase_system:: diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 98042adcee5ee..ab3f68df20904 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -22,7 +22,7 @@ use std::cmp::Reverse; pub use camera_3d::*; pub use main_pass_3d_node::*; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_ecs::prelude::*; use bevy_render::{ camera::{Camera, ExtractedCamera}, @@ -67,7 +67,7 @@ impl Plugin for Core3dPlugin { .init_resource::>() .init_resource::>() .init_resource::>() - .add_system_to_schedule(ExtractSchedule, extract_core_3d_camera_phases) + .add_system(extract_core_3d_camera_phases.in_schedule(ExtractSchedule)) .add_system( prepare_core_3d_depth_textures .in_set(RenderSet::Prepare) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 410b702c4933e..7ab25bdd9d553 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -2,7 +2,7 @@ use crate::{ AlphaMode, DrawMesh, EnvironmentMapLight, MeshPipeline, MeshPipelineKey, MeshUniform, PrepassPlugin, SetMeshBindGroup, SetMeshViewBindGroup, }; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle}; use bevy_core_pipeline::{ core_3d::{AlphaMask3d, Opaque3d, Transparent3d}, @@ -195,7 +195,7 @@ where .init_resource::>() .init_resource::>() .init_resource::>>() - .add_system_to_schedule(ExtractSchedule, extract_materials::) + .add_system(extract_materials::.in_schedule(ExtractSchedule)) .add_system( prepare_materials:: .in_set(RenderSet::Prepare) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index f4f75f7a04b99..9f63d7b9ff4ea 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -1,4 +1,4 @@ -use bevy_app::Plugin; +use bevy_app::{IntoSystemAppConfig, Plugin}; use bevy_asset::{load_internal_asset, AssetServer, Handle, HandleUntyped}; use bevy_core_pipeline::{ prelude::Camera3d, @@ -97,7 +97,7 @@ where }; render_app - .add_system_to_schedule(ExtractSchedule, extract_camera_prepass_phase) + .add_system(extract_camera_prepass_phase.in_schedule(ExtractSchedule)) .add_system( prepare_prepass_textures .in_set(RenderSet::Prepare) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 0b4f5463eb758..477e29795014a 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -5,7 +5,7 @@ use crate::{ ViewShadowBindings, CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT, MAX_CASCADES_PER_LIGHT, MAX_DIRECTIONAL_LIGHTS, }; -use bevy_app::Plugin; +use bevy_app::{IntoSystemAppConfigs, Plugin}; use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped}; use bevy_core_pipeline::{ prepass::ViewPrepassTextures, @@ -108,7 +108,7 @@ impl Plugin for MeshRenderPlugin { render_app .init_resource::() .init_resource::() - .add_systems_to_schedule(ExtractSchedule, (extract_meshes, extract_skinned_meshes)) + .add_systems((extract_meshes, extract_skinned_meshes).in_schedule(ExtractSchedule)) .add_system(prepare_skinned_meshes.in_set(RenderSet::Prepare)) .add_system(queue_mesh_bind_group.in_set(RenderSet::Queue)) .add_system( diff --git a/crates/bevy_render/src/camera/mod.rs b/crates/bevy_render/src/camera/mod.rs index cdd26a36c638a..e1639a348f991 100644 --- a/crates/bevy_render/src/camera/mod.rs +++ b/crates/bevy_render/src/camera/mod.rs @@ -8,7 +8,7 @@ pub use camera_driver_node::*; pub use projection::*; use crate::{render_graph::RenderGraph, ExtractSchedule, RenderApp}; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; #[derive(Default)] pub struct CameraPlugin; @@ -26,7 +26,7 @@ impl Plugin for CameraPlugin { .add_plugin(CameraProjectionPlugin::::default()); if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { - render_app.add_system_to_schedule(ExtractSchedule, extract_cameras); + render_app.add_system(extract_cameras.in_schedule(ExtractSchedule)); let camera_driver_node = CameraDriverNode::new(&mut render_app.world); let mut render_graph = render_app.world.resource_mut::(); render_graph.add_node(crate::main_graph::node::CAMERA_DRIVER, camera_driver_node); diff --git a/crates/bevy_render/src/extract_component.rs b/crates/bevy_render/src/extract_component.rs index 6f6241a59ebcb..2b70a897a16fc 100644 --- a/crates/bevy_render/src/extract_component.rs +++ b/crates/bevy_render/src/extract_component.rs @@ -4,7 +4,7 @@ use crate::{ view::ComputedVisibility, Extract, ExtractSchedule, RenderApp, RenderSet, }; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_asset::{Asset, Handle}; use bevy_ecs::{ component::Component, @@ -180,9 +180,9 @@ impl Plugin for ExtractComponentPlugin { fn build(&self, app: &mut App) { if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { if self.only_extract_visible { - render_app.add_system_to_schedule(ExtractSchedule, extract_visible_components::); + render_app.add_system(extract_visible_components::.in_schedule(ExtractSchedule)); } else { - render_app.add_system_to_schedule(ExtractSchedule, extract_components::); + render_app.add_system(extract_components::.in_schedule(ExtractSchedule)); } } } diff --git a/crates/bevy_render/src/extract_resource.rs b/crates/bevy_render/src/extract_resource.rs index 65b3d954fbb15..a1e8b122f0857 100644 --- a/crates/bevy_render/src/extract_resource.rs +++ b/crates/bevy_render/src/extract_resource.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_ecs::prelude::*; pub use bevy_render_macros::ExtractResource; @@ -32,7 +32,7 @@ impl Default for ExtractResourcePlugin { impl Plugin for ExtractResourcePlugin { fn build(&self, app: &mut App) { if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { - render_app.add_system_to_schedule(ExtractSchedule, extract_resource::); + render_app.add_system(extract_resource::.in_schedule(ExtractSchedule)); } } } diff --git a/crates/bevy_render/src/globals.rs b/crates/bevy_render/src/globals.rs index 474defa802e1b..6b9fbdbc7f3d2 100644 --- a/crates/bevy_render/src/globals.rs +++ b/crates/bevy_render/src/globals.rs @@ -5,7 +5,7 @@ use crate::{ renderer::{RenderDevice, RenderQueue}, Extract, ExtractSchedule, RenderApp, RenderSet, }; -use bevy_app::{App, Plugin}; +use bevy_app::{App, IntoSystemAppConfigs, Plugin}; use bevy_asset::{load_internal_asset, HandleUntyped}; use bevy_core::FrameCount; use bevy_ecs::prelude::*; @@ -26,7 +26,7 @@ impl Plugin for GlobalsPlugin { render_app .init_resource::() .init_resource::