diff --git a/benches/benches/bevy_ecs/scheduling/run_criteria.rs b/benches/benches/bevy_ecs/scheduling/run_criteria.rs index 11a0b1efd56e8..b1e132e80afaa 100644 --- a/benches/benches/bevy_ecs/scheduling/run_criteria.rs +++ b/benches/benches/bevy_ecs/scheduling/run_criteria.rs @@ -1,7 +1,7 @@ use bevy_ecs::{ component::Component, prelude::{ParallelSystemDescriptorCoercion, Res, Resource, RunCriteriaDescriptorCoercion}, - schedule::{ShouldRun, Stage, SystemStage}, + schedule::{RunCriteriaLabel, ShouldRun, Stage, SystemStage}, system::Query, world::World, }; @@ -11,6 +11,13 @@ fn run_stage(stage: &mut SystemStage, world: &mut World) { stage.run(world); } +/// Labels for run criteria which either always return yes, or always return no. +#[derive(RunCriteriaLabel)] +enum Always { + Yes, + No, +} + pub fn run_criteria_yes(criterion: &mut Criterion) { let mut world = World::new(); let mut group = criterion.benchmark_group("run_criteria/yes"); @@ -85,14 +92,15 @@ pub fn run_criteria_yes_with_labels(criterion: &mut Criterion) { } for amount in 0..21 { let mut stage = SystemStage::parallel(); - stage.add_system(empty.with_run_criteria(always_yes.label("always yes"))); + + stage.add_system(empty.with_run_criteria(always_yes.label(Always::Yes))); for _ in 0..amount { stage - .add_system(empty.with_run_criteria("always yes")) - .add_system(empty.with_run_criteria("always yes")) - .add_system(empty.with_run_criteria("always yes")) - .add_system(empty.with_run_criteria("always yes")) - .add_system(empty.with_run_criteria("always yes")); + .add_system(empty.with_run_criteria(Always::Yes)) + .add_system(empty.with_run_criteria(Always::Yes)) + .add_system(empty.with_run_criteria(Always::Yes)) + .add_system(empty.with_run_criteria(Always::Yes)) + .add_system(empty.with_run_criteria(Always::Yes)); } // run once to initialize systems run_stage(&mut stage, &mut world); @@ -116,14 +124,15 @@ pub fn run_criteria_no_with_labels(criterion: &mut Criterion) { } for amount in 0..21 { let mut stage = SystemStage::parallel(); - stage.add_system(empty.with_run_criteria(always_no.label("always no"))); + + stage.add_system(empty.with_run_criteria(always_no.label(Always::No))); for _ in 0..amount { stage - .add_system(empty.with_run_criteria("always no")) - .add_system(empty.with_run_criteria("always no")) - .add_system(empty.with_run_criteria("always no")) - .add_system(empty.with_run_criteria("always no")) - .add_system(empty.with_run_criteria("always no")); + .add_system(empty.with_run_criteria(Always::No)) + .add_system(empty.with_run_criteria(Always::No)) + .add_system(empty.with_run_criteria(Always::No)) + .add_system(empty.with_run_criteria(Always::No)) + .add_system(empty.with_run_criteria(Always::No)); } // run once to initialize systems run_stage(&mut stage, &mut world); diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 7d6c027da0cdf..f5f2adbd28747 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -151,7 +151,9 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # - /// app.add_stage("my_stage", SystemStage::parallel()); + /// #[derive(StageLabel)] + /// struct MyStage; + /// app.add_stage(MyStage, SystemStage::parallel()); /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { self.schedule.add_stage(label, stage); @@ -168,7 +170,9 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # - /// app.add_stage_after(CoreStage::Update, "my_stage", SystemStage::parallel()); + /// #[derive(StageLabel)] + /// struct MyStage; + /// app.add_stage_after(CoreStage::Update, MyStage, SystemStage::parallel()); /// ``` pub fn add_stage_after( &mut self, @@ -190,7 +194,9 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # - /// app.add_stage_before(CoreStage::Update, "my_stage", SystemStage::parallel()); + /// #[derive(StageLabel)] + /// struct MyStage; + /// app.add_stage_before(CoreStage::Update, MyStage, SystemStage::parallel()); /// ``` pub fn add_stage_before( &mut self, @@ -212,7 +218,9 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # - /// app.add_startup_stage("my_startup_stage", SystemStage::parallel()); + /// #[derive(StageLabel)] + /// struct MyStartupStage; + /// app.add_startup_stage(MyStartupStage, SystemStage::parallel()); /// ``` pub fn add_startup_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { self.schedule @@ -234,9 +242,11 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # + /// #[derive(StageLabel)] + /// struct MyStartupStage; /// app.add_startup_stage_after( /// StartupStage::Startup, - /// "my_startup_stage", + /// MyStartupStage, /// SystemStage::parallel() /// ); /// ``` @@ -265,9 +275,11 @@ impl App { /// # use bevy_ecs::prelude::*; /// # let mut app = App::new(); /// # + /// #[derive(StageLabel)] + /// struct MyStartupStage; /// app.add_startup_stage_before( /// StartupStage::Startup, - /// "my_startup_stage", + /// MyStartupStage, /// SystemStage::parallel() /// ); /// ``` diff --git a/crates/bevy_ecs/README.md b/crates/bevy_ecs/README.md index 5f497161d2401..c3e93ffb11a4a 100644 --- a/crates/bevy_ecs/README.md +++ b/crates/bevy_ecs/README.md @@ -148,9 +148,13 @@ fn main() { // Create a new Schedule, which defines an execution strategy for Systems let mut schedule = Schedule::default(); + // Define a unique public name for a new Stage. + #[derive(StageLabel)] + pub struct UpdateLabel; + // Add a Stage to our schedule. Each Stage in a schedule runs all of its systems // before moving on to the next Stage - schedule.add_stage("update", SystemStage::parallel() + schedule.add_stage(UpdateLabel, SystemStage::parallel() .with_system(movement) ); diff --git a/crates/bevy_ecs/examples/change_detection.rs b/crates/bevy_ecs/examples/change_detection.rs index 4a72343bb6552..506b027b87ecb 100644 --- a/crates/bevy_ecs/examples/change_detection.rs +++ b/crates/bevy_ecs/examples/change_detection.rs @@ -30,7 +30,9 @@ fn main() { update.add_system(remove_old_entities.after(SimulationSystem::Age)); update.add_system(print_changed_entities.after(SimulationSystem::Age)); // Add the Stage with our systems to the Schedule - schedule.add_stage("update", update); + #[derive(StageLabel)] + struct Update; + schedule.add_stage(Update, update); // Simulate 10 frames in our world for iteration in 1..=10 { diff --git a/crates/bevy_ecs/examples/events.rs b/crates/bevy_ecs/examples/events.rs index acf66282e26dd..02bc0f5071368 100644 --- a/crates/bevy_ecs/examples/events.rs +++ b/crates/bevy_ecs/examples/events.rs @@ -10,6 +10,12 @@ fn main() { // Create a schedule and a stage let mut schedule = Schedule::default(); + #[derive(StageLabel)] + enum Stages { + First, + Second, + } + // Events need to be updated in every frame. This update should happen before we use // the events. To guarantee this, we can let the update run in an earlier stage than our logic. // Here we will use a stage called "first" that will always run it's systems before the Stage @@ -17,7 +23,7 @@ fn main() { // sending and receiving events. let mut first = SystemStage::parallel(); first.add_system(Events::::update_system); - schedule.add_stage("first", first); + schedule.add_stage(Stages::First, first); // Add systems sending and receiving events to a "second" Stage let mut second = SystemStage::parallel(); @@ -25,7 +31,7 @@ fn main() { second.add_system(receiving_system.after(sending_system)); // Run the "second" Stage after the "first" Stage, so our Events always get updated before we use them - schedule.add_stage_after("first", "second", second); + schedule.add_stage_after(Stages::First, Stages::Second, second); // Simulate 10 frames of our world for iteration in 1..=10 { diff --git a/crates/bevy_ecs/examples/resources.rs b/crates/bevy_ecs/examples/resources.rs index 3127f52d90732..9f764a1d20a96 100644 --- a/crates/bevy_ecs/examples/resources.rs +++ b/crates/bevy_ecs/examples/resources.rs @@ -18,7 +18,13 @@ fn main() { // Add systems to increase the counter and to print out the current value update.add_system(increase_counter); update.add_system(print_counter.after(increase_counter)); - schedule.add_stage("update", update); + + // Declare a unique label for the stage. + #[derive(StageLabel)] + struct Update; + + // Add the stage to the schedule. + schedule.add_stage(Update, update); for iteration in 1..=10 { println!("Simulating frame {}/10", iteration); diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index 0ac1e8702d685..a402523c2dd7d 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -106,7 +106,11 @@ impl Schedule { /// # use bevy_ecs::prelude::*; /// # /// # let mut schedule = Schedule::default(); - /// schedule.add_stage("my_stage", SystemStage::parallel()); + /// // Define a new label for the stage. + /// #[derive(StageLabel)] + /// struct MyStage; + /// // Add a stage with that label to the schedule. + /// schedule.add_stage(MyStage, SystemStage::parallel()); /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { let label = label.as_label(); @@ -124,8 +128,14 @@ impl Schedule { /// # use bevy_ecs::prelude::*; /// # /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("target_stage", SystemStage::parallel()); - /// schedule.add_stage_after("target_stage", "my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct TargetStage; + /// # schedule.add_stage(TargetStage, SystemStage::parallel()); + /// // Define a new label for the stage. + /// #[derive(StageLabel)] + /// struct NewStage; + /// // Add a stage with that label to the schedule. + /// schedule.add_stage_after(TargetStage, NewStage, SystemStage::parallel()); /// ``` pub fn add_stage_after( &mut self, @@ -157,9 +167,15 @@ impl Schedule { /// # use bevy_ecs::prelude::*; /// # /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("target_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct TargetStage; + /// # schedule.add_stage(TargetStage, SystemStage::parallel()); /// # - /// schedule.add_stage_before("target_stage", "my_stage", SystemStage::parallel()); + /// // Define a new, private label for the stage. + /// #[derive(StageLabel)] + /// struct NewStage; + /// // Add a stage with that label to the schedule. + /// schedule.add_stage_before(TargetStage, NewStage, SystemStage::parallel()); /// ``` pub fn add_stage_before( &mut self, @@ -192,9 +208,11 @@ impl Schedule { /// # /// # fn my_system() {} /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct MyStage; + /// # schedule.add_stage(MyStage, SystemStage::parallel()); /// # - /// schedule.add_system_to_stage("my_stage", my_system); + /// schedule.add_system_to_stage(MyStage, my_system); /// ``` pub fn add_system_to_stage( &mut self, @@ -228,10 +246,12 @@ impl Schedule { /// # /// # fn my_system() {} /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct MyStage; + /// # schedule.add_stage(MyStage, SystemStage::parallel()); /// # /// schedule.add_system_set_to_stage( - /// "my_stage", + /// MyStage, /// SystemSet::new() /// .with_system(system_a) /// .with_system(system_b) @@ -265,9 +285,11 @@ impl Schedule { /// # use bevy_ecs::prelude::*; /// # /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct MyStage; + /// # schedule.add_stage(MyStage, SystemStage::parallel()); /// # - /// schedule.stage("my_stage", |stage: &mut SystemStage| { + /// schedule.stage(MyStage, |stage: &mut SystemStage| { /// stage.add_system(my_system) /// }); /// # @@ -301,9 +323,11 @@ impl Schedule { /// # /// # fn my_system() {} /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct MyStage; + /// # schedule.add_stage(MyStage, SystemStage::parallel()); /// # - /// let stage = schedule.get_stage::("my_stage").unwrap(); + /// let stage = schedule.get_stage::(MyStage).unwrap(); /// ``` pub fn get_stage(&self, stage_label: impl StageLabel) -> Option<&T> { let label = stage_label.as_label(); @@ -323,9 +347,11 @@ impl Schedule { /// # /// # fn my_system() {} /// # let mut schedule = Schedule::default(); - /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # #[derive(StageLabel)] + /// # struct MyStage; + /// # schedule.add_stage(MyStage, SystemStage::parallel()); /// # - /// let stage = schedule.get_stage_mut::("my_stage").unwrap(); + /// let stage = schedule.get_stage_mut::(MyStage).unwrap(); /// ``` pub fn get_stage_mut(&mut self, stage_label: impl StageLabel) -> Option<&mut T> { let label = stage_label.as_label(); diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 72e7e39933830..9152df7466ffa 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -972,6 +972,8 @@ impl Stage for SystemStage { #[cfg(test)] mod tests { + use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel}; + use crate::{ schedule::{ ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, @@ -1060,14 +1062,27 @@ mod tests { ); } + #[derive(SystemLabel)] + enum TestLabels { + L0, + L1, + L2, + L3, + L4, + First, + L01, + L234, + } + use TestLabels::*; + #[test] fn exclusive_after() { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(1).exclusive_system().label("1").after("0")) - .with_system(make_exclusive(2).exclusive_system().after("1")) - .with_system(make_exclusive(0).exclusive_system().label("0")); + .with_system(make_exclusive(1).exclusive_system().label(L1).after(L0)) + .with_system(make_exclusive(2).exclusive_system().after(L1)) + .with_system(make_exclusive(0).exclusive_system().label(L0)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1079,9 +1094,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(1).exclusive_system().label("1").before("2")) - .with_system(make_exclusive(2).exclusive_system().label("2")) - .with_system(make_exclusive(0).exclusive_system().before("1")); + .with_system(make_exclusive(1).exclusive_system().label(L1).before(L2)) + .with_system(make_exclusive(2).exclusive_system().label(L2)) + .with_system(make_exclusive(0).exclusive_system().before(L1)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1093,11 +1108,11 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(2).exclusive_system().label("2")) - .with_system(make_exclusive(1).exclusive_system().after("0").before("2")) - .with_system(make_exclusive(0).exclusive_system().label("0")) - .with_system(make_exclusive(4).exclusive_system().label("4")) - .with_system(make_exclusive(3).exclusive_system().after("2").before("4")); + .with_system(make_exclusive(2).exclusive_system().label(L2)) + .with_system(make_exclusive(1).exclusive_system().after(L0).before(L2)) + .with_system(make_exclusive(0).exclusive_system().label(L0)) + .with_system(make_exclusive(4).exclusive_system().label(L4)) + .with_system(make_exclusive(3).exclusive_system().after(L2).before(L4)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1112,19 +1127,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system( - make_exclusive(1) - .exclusive_system() - .label("first") - .after("0"), - ) - .with_system(make_exclusive(2).exclusive_system().after("first")) - .with_system( - make_exclusive(0) - .exclusive_system() - .label("first") - .label("0"), - ); + .with_system(make_exclusive(1).exclusive_system().label(First).after(L0)) + .with_system(make_exclusive(2).exclusive_system().after(First)) + .with_system(make_exclusive(0).exclusive_system().label(First).label(L0)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1132,11 +1137,11 @@ mod tests { world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(2).exclusive_system().after("01").label("2")) - .with_system(make_exclusive(1).exclusive_system().label("01").after("0")) - .with_system(make_exclusive(0).exclusive_system().label("01").label("0")) - .with_system(make_exclusive(4).exclusive_system().label("4")) - .with_system(make_exclusive(3).exclusive_system().after("2").before("4")); + .with_system(make_exclusive(2).exclusive_system().after(L01).label(L2)) + .with_system(make_exclusive(1).exclusive_system().label(L01).after(L0)) + .with_system(make_exclusive(0).exclusive_system().label(L01).label(L0)) + .with_system(make_exclusive(4).exclusive_system().label(L4)) + .with_system(make_exclusive(3).exclusive_system().after(L2).before(L4)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1147,21 +1152,16 @@ mod tests { world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(2).exclusive_system().label("234").label("2")) - .with_system( - make_exclusive(1) - .exclusive_system() - .before("234") - .after("0"), - ) - .with_system(make_exclusive(0).exclusive_system().label("0")) - .with_system(make_exclusive(4).exclusive_system().label("234").label("4")) + .with_system(make_exclusive(2).exclusive_system().label(L234).label(L2)) + .with_system(make_exclusive(1).exclusive_system().before(L234).after(L0)) + .with_system(make_exclusive(0).exclusive_system().label(L0)) + .with_system(make_exclusive(4).exclusive_system().label(L234).label(L4)) .with_system( make_exclusive(3) .exclusive_system() - .label("234") - .after("2") - .before("4"), + .label(L234) + .after(L2) + .before(L4), ); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1180,27 +1180,27 @@ mod tests { .with_system( make_exclusive(2) .exclusive_system() - .label("2") - .after("1") - .before("3") - .before("3"), + .label(L2) + .after(L1) + .before(L3) + .before(L3), ) .with_system( make_exclusive(1) .exclusive_system() - .label("1") - .after("0") - .after("0") - .before("2"), + .label(L1) + .after(L0) + .after(L0) + .before(L2), ) - .with_system(make_exclusive(0).exclusive_system().label("0").before("1")) - .with_system(make_exclusive(4).exclusive_system().label("4").after("3")) + .with_system(make_exclusive(0).exclusive_system().label(L0).before(L1)) + .with_system(make_exclusive(4).exclusive_system().label(L4).after(L3)) .with_system( make_exclusive(3) .exclusive_system() - .label("3") - .after("2") - .before("4"), + .label(L3) + .after(L2) + .before(L4), ); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1216,14 +1216,14 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(2).exclusive_system().label("2")) + .with_system(make_exclusive(2).exclusive_system().label(L2)) .with_system_set( SystemSet::new() - .with_system(make_exclusive(0).exclusive_system().label("0")) - .with_system(make_exclusive(4).exclusive_system().label("4")) - .with_system(make_exclusive(3).exclusive_system().after("2").before("4")), + .with_system(make_exclusive(0).exclusive_system().label(L0)) + .with_system(make_exclusive(4).exclusive_system().label(L4)) + .with_system(make_exclusive(3).exclusive_system().after(L2).before(L4)), ) - .with_system(make_exclusive(1).exclusive_system().after("0").before("2")); + .with_system(make_exclusive(1).exclusive_system().after(L0).before(L2)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1238,13 +1238,13 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(0).exclusive_system().before("1")) + .with_system(make_exclusive(0).exclusive_system().before(L1)) .with_system_set( SystemSet::new() .with_run_criteria(every_other_time) - .with_system(make_exclusive(1).exclusive_system().label("1")), + .with_system(make_exclusive(1).exclusive_system().label(L1)), ) - .with_system(make_exclusive(2).exclusive_system().after("1")); + .with_system(make_exclusive(2).exclusive_system().after(L1)); stage.run(&mut world); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1262,7 +1262,7 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(0).exclusive_system().label("0").after("0")); + .with_system(make_exclusive(0).exclusive_system().label(L0).after(L0)); stage.run(&mut world); } @@ -1272,8 +1272,8 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(0).exclusive_system().label("0").after("1")) - .with_system(make_exclusive(1).exclusive_system().label("1").after("0")); + .with_system(make_exclusive(0).exclusive_system().label(L0).after(L1)) + .with_system(make_exclusive(1).exclusive_system().label(L1).after(L0)); stage.run(&mut world); } @@ -1283,9 +1283,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_exclusive(0).exclusive_system().label("0")) - .with_system(make_exclusive(1).exclusive_system().after("0").before("2")) - .with_system(make_exclusive(2).exclusive_system().label("2").before("0")); + .with_system(make_exclusive(0).exclusive_system().label(L0)) + .with_system(make_exclusive(1).exclusive_system().after(L0).before(L2)) + .with_system(make_exclusive(2).exclusive_system().label(L2).before(L0)); stage.run(&mut world); } @@ -1294,9 +1294,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(1).after("0").label("1")) - .with_system(make_parallel(2).after("1")) - .with_system(make_parallel(0).label("0")); + .with_system(make_parallel(1).after(L0).label(L1)) + .with_system(make_parallel(2).after(L1)) + .with_system(make_parallel(0).label(L0)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1308,9 +1308,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(1).label("1").before("2")) - .with_system(make_parallel(2).label("2")) - .with_system(make_parallel(0).before("1")); + .with_system(make_parallel(1).label(L1).before(L2)) + .with_system(make_parallel(2).label(L2)) + .with_system(make_parallel(0).before(L1)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1322,11 +1322,11 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(2).label("2")) - .with_system(make_parallel(1).after("0").before("2")) - .with_system(make_parallel(0).label("0")) - .with_system(make_parallel(4).label("4")) - .with_system(make_parallel(3).after("2").before("4")); + .with_system(make_parallel(2).label(L2)) + .with_system(make_parallel(1).after(L0).before(L2)) + .with_system(make_parallel(0).label(L0)) + .with_system(make_parallel(4).label(L4)) + .with_system(make_parallel(3).after(L2).before(L4)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1341,9 +1341,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(1).label("first").after("0")) - .with_system(make_parallel(2).after("first")) - .with_system(make_parallel(0).label("first").label("0")); + .with_system(make_parallel(1).label(First).after(L0)) + .with_system(make_parallel(2).after(First)) + .with_system(make_parallel(0).label(First).label(L0)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1351,11 +1351,11 @@ mod tests { world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(2).after("01").label("2")) - .with_system(make_parallel(1).label("01").after("0")) - .with_system(make_parallel(0).label("01").label("0")) - .with_system(make_parallel(4).label("4")) - .with_system(make_parallel(3).after("2").before("4")); + .with_system(make_parallel(2).after(L01).label(L2)) + .with_system(make_parallel(1).label(L01).after(L0)) + .with_system(make_parallel(0).label(L01).label(L0)) + .with_system(make_parallel(4).label(L4)) + .with_system(make_parallel(3).after(L2).before(L4)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1366,11 +1366,11 @@ mod tests { world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(2).label("234").label("2")) - .with_system(make_parallel(1).before("234").after("0")) - .with_system(make_parallel(0).label("0")) - .with_system(make_parallel(4).label("234").label("4")) - .with_system(make_parallel(3).label("234").after("2").before("4")); + .with_system(make_parallel(2).label(L234).label(L2)) + .with_system(make_parallel(1).before(L234).after(L0)) + .with_system(make_parallel(0).label(L0)) + .with_system(make_parallel(4).label(L234).label(L4)) + .with_system(make_parallel(3).label(L234).after(L2).before(L4)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1385,23 +1385,11 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system( - make_parallel(2) - .label("2") - .after("1") - .before("3") - .before("3"), - ) - .with_system( - make_parallel(1) - .label("1") - .after("0") - .after("0") - .before("2"), - ) - .with_system(make_parallel(0).label("0").before("1")) - .with_system(make_parallel(4).label("4").after("3")) - .with_system(make_parallel(3).label("3").after("2").before("4")); + .with_system(make_parallel(2).label(L2).after(L1).before(L3).before(L3)) + .with_system(make_parallel(1).label(L1).after(L0).after(L0).before(L2)) + .with_system(make_parallel(0).label(L0).before(L1)) + .with_system(make_parallel(4).label(L4).after(L3)) + .with_system(make_parallel(3).label(L3).after(L2).before(L4)); stage.run(&mut world); for container in &stage.parallel { assert!(container.dependencies().len() <= 1); @@ -1419,14 +1407,14 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(2).label("2")) + .with_system(make_parallel(2).label(L2)) .with_system_set( SystemSet::new() - .with_system(make_parallel(0).label("0")) - .with_system(make_parallel(4).label("4")) - .with_system(make_parallel(3).after("2").before("4")), + .with_system(make_parallel(0).label(L0)) + .with_system(make_parallel(4).label(L4)) + .with_system(make_parallel(3).after(L2).before(L4)), ) - .with_system(make_parallel(1).after("0").before("2")); + .with_system(make_parallel(1).after(L0).before(L2)); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); @@ -1436,6 +1424,9 @@ mod tests { ); } + #[derive(RunCriteriaLabel)] + struct EveryOtherTime; + #[test] fn parallel_run_criteria() { let mut world = World::new(); @@ -1444,10 +1435,10 @@ mod tests { let mut stage = SystemStage::parallel() .with_system( make_parallel(0) - .label("0") + .label(L0) .with_run_criteria(every_other_time), ) - .with_system(make_parallel(1).after("0")); + .with_system(make_parallel(1).after(L0)); stage.run(&mut world); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1457,13 +1448,13 @@ mod tests { world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(0).before("1")) + .with_system(make_parallel(0).before(L1)) .with_system_set( SystemSet::new() .with_run_criteria(every_other_time) - .with_system(make_parallel(1).label("1")), + .with_system(make_parallel(1).label(L1)), ) - .with_system(make_parallel(2).after("1")); + .with_system(make_parallel(2).after(L1)); stage.run(&mut world); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1477,20 +1468,16 @@ mod tests { // Reusing criteria. world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() - .with_system_run_criteria(every_other_time.label("every other time")) - .with_system(make_parallel(0).before("1")) - .with_system( - make_parallel(1) - .label("1") - .with_run_criteria("every other time"), - ) + .with_system_run_criteria(every_other_time.label(EveryOtherTime)) + .with_system(make_parallel(0).before(L1)) + .with_system(make_parallel(1).label(L1).with_run_criteria(EveryOtherTime)) .with_system( make_parallel(2) - .label("2") - .after("1") - .with_run_criteria("every other time"), + .label(L2) + .after(L1) + .with_run_criteria(EveryOtherTime), ) - .with_system(make_parallel(3).after("2")); + .with_system(make_parallel(3).after(L2)); stage.run(&mut world); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1511,25 +1498,31 @@ mod tests { ShouldRun::No } } - let mut stage = - SystemStage::parallel() - .with_system(make_parallel(0).label("0")) - .with_system( - make_parallel(1) - .label("1") - .after("0") - .with_run_criteria(every_other_time.label("every other time")), - ) - .with_system( - make_parallel(2) - .label("2") - .after("1") - .with_run_criteria(RunCriteria::pipe("every other time", eot_piped)), - ) - .with_system(make_parallel(3).label("3").after("2").with_run_criteria( - RunCriteria::pipe("every other time", eot_piped).label("piped"), - )) - .with_system(make_parallel(4).after("3").with_run_criteria("piped")); + + #[derive(RunCriteriaLabel)] + struct Piped; + + let mut stage = SystemStage::parallel() + .with_system(make_parallel(0).label(L0)) + .with_system( + make_parallel(1) + .label(L1) + .after(L0) + .with_run_criteria(every_other_time.label(EveryOtherTime)), + ) + .with_system( + make_parallel(2) + .label(L2) + .after(L1) + .with_run_criteria(RunCriteria::pipe(EveryOtherTime, eot_piped)), + ) + .with_system( + make_parallel(3) + .label(L3) + .after(L2) + .with_run_criteria(RunCriteria::pipe(EveryOtherTime, eot_piped).label(Piped)), + ) + .with_system(make_parallel(4).after(L3).with_run_criteria(Piped)); for _ in 0..4 { stage.run(&mut world); } @@ -1545,16 +1538,20 @@ mod tests { // Discarding extra criteria with matching labels. world.resource_mut::().0.clear(); - let mut stage = - SystemStage::parallel() - .with_system(make_parallel(0).before("1")) - .with_system(make_parallel(1).label("1").with_run_criteria( - every_other_time.label_discard_if_duplicate("every other time"), - )) - .with_system(make_parallel(2).label("2").after("1").with_run_criteria( - every_other_time.label_discard_if_duplicate("every other time"), - )) - .with_system(make_parallel(3).after("2")); + let mut stage = SystemStage::parallel() + .with_system(make_parallel(0).before(L1)) + .with_system( + make_parallel(1) + .label(L1) + .with_run_criteria(every_other_time.label_discard_if_duplicate(EveryOtherTime)), + ) + .with_system( + make_parallel(2) + .label(L2) + .after(L1) + .with_run_criteria(every_other_time.label_discard_if_duplicate(EveryOtherTime)), + ) + .with_system(make_parallel(3).after(L2)); stage.run(&mut world); stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); @@ -1572,8 +1569,8 @@ mod tests { fn duplicate_run_criteria_label_panic() { let mut world = World::new(); let mut stage = SystemStage::parallel() - .with_system_run_criteria(every_other_time.label("every other time")) - .with_system_run_criteria(every_other_time.label("every other time")); + .with_system_run_criteria(every_other_time.label(EveryOtherTime)) + .with_system_run_criteria(every_other_time.label(EveryOtherTime)); stage.run(&mut world); } @@ -1582,7 +1579,7 @@ mod tests { fn parallel_cycle_1() { let mut world = World::new(); world.init_resource::(); - let mut stage = SystemStage::parallel().with_system(make_parallel(0).label("0").after("0")); + let mut stage = SystemStage::parallel().with_system(make_parallel(0).label(L0).after(L0)); stage.run(&mut world); } @@ -1592,8 +1589,8 @@ mod tests { let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(0).label("0").after("1")) - .with_system(make_parallel(1).label("1").after("0")); + .with_system(make_parallel(0).label(L0).after(L1)) + .with_system(make_parallel(1).label(L1).after(L0)); stage.run(&mut world); } @@ -1604,9 +1601,9 @@ mod tests { world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(make_parallel(0).label("0")) - .with_system(make_parallel(1).after("0").before("2")) - .with_system(make_parallel(2).label("2").before("0")); + .with_system(make_parallel(0).label(L0)) + .with_system(make_parallel(1).after(L0).before(L2)) + .with_system(make_parallel(2).label(L2).before(L0)); stage.run(&mut world); } @@ -1614,7 +1611,29 @@ mod tests { fn ambiguity_detection() { use super::{find_ambiguities, SystemContainer}; - fn find_ambiguities_first_str_labels( + // these labels must all be the same type in order for + // `find_ambiguities_first_labels` to work + #[derive(SystemLabel)] + enum Labels { + A0, + A1, + A2, + A3, + A4, + A5, + A6, + A7, + } + use Labels::*; + + #[derive(AmbiguitySetLabel)] + enum SetLabels { + SetA, + SetB, + } + use SetLabels::*; + + fn find_ambiguities_first_labels( systems: &[impl SystemContainer], ) -> Vec<(SystemLabelId, SystemLabelId)> { find_ambiguities(systems) @@ -1624,12 +1643,12 @@ mod tests { *systems[index_a] .labels() .iter() - .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .find(|a| a.type_id() == std::any::TypeId::of::()) .unwrap(), *systems[index_b] .labels() .iter() - .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .find(|a| a.type_id() == std::any::TypeId::of::()) .unwrap(), ) }) @@ -1643,355 +1662,334 @@ mod tests { let mut world = World::new(); let mut stage = SystemStage::parallel() - .with_system(empty.label("0")) - .with_system(empty.label("1").after("0")) - .with_system(empty.label("2")) - .with_system(empty.label("3").after("2").before("4")) - .with_system(empty.label("4")); + .with_system(empty.label(A0)) + .with_system(empty.label(A1).after(A0)) + .with_system(empty.label(A2)) + .with_system(empty.label(A3).after(A2).before(A4)) + .with_system(empty.label(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); assert_eq!(find_ambiguities(&stage.parallel).len(), 0); let mut stage = SystemStage::parallel() - .with_system(empty.label("0")) - .with_system(component.label("1").after("0")) - .with_system(empty.label("2")) - .with_system(empty.label("3").after("2").before("4")) - .with_system(component.label("4")); + .with_system(empty.label(A0)) + .with_system(component.label(A1).after(A0)) + .with_system(empty.label(A2)) + .with_system(empty.label(A3).after(A2).before(A4)) + .with_system(component.label(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(empty.label("0")) - .with_system(resource.label("1").after("0")) - .with_system(empty.label("2")) - .with_system(empty.label("3").after("2").before("4")) - .with_system(resource.label("4")); + .with_system(empty.label(A0)) + .with_system(resource.label(A1).after(A0)) + .with_system(empty.label(A2)) + .with_system(empty.label(A3).after(A2).before(A4)) + .with_system(resource.label(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(empty.label("0")) - .with_system(resource.label("1").after("0")) - .with_system(empty.label("2")) - .with_system(empty.label("3").after("2").before("4")) - .with_system(component.label("4")); + .with_system(empty.label(A0)) + .with_system(resource.label(A1).after(A0)) + .with_system(empty.label(A2)) + .with_system(empty.label(A3).after(A2).before(A4)) + .with_system(component.label(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); assert_eq!(find_ambiguities(&stage.parallel).len(), 0); let mut stage = SystemStage::parallel() - .with_system(component.label("0")) - .with_system(resource.label("1").after("0")) - .with_system(empty.label("2")) - .with_system(component.label("3").after("2").before("4")) - .with_system(resource.label("4")); + .with_system(component.label(A0)) + .with_system(resource.label(A1).after(A0)) + .with_system(empty.label(A2)) + .with_system(component.label(A3).after(A2).before(A4)) + .with_system(resource.label(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("0".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "0".as_label())) + ambiguities.contains(&(A0.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A0.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 2); let mut stage = SystemStage::parallel() - .with_system(component.label("0")) - .with_system(resource.label("1").after("0").in_ambiguity_set("a")) - .with_system(empty.label("2")) - .with_system(component.label("3").after("2").before("4")) - .with_system(resource.label("4").in_ambiguity_set("a")); + .with_system(component.label(A0)) + .with_system(resource.label(A1).after(A0).in_ambiguity_set(SetA)) + .with_system(empty.label(A2)) + .with_system(component.label(A3).after(A2).before(A4)) + .with_system(resource.label(A4).in_ambiguity_set(SetA)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("0".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "0".as_label())) + ambiguities.contains(&(A0.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A0.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(component.label("0").before("2")) - .with_system(component.label("1").before("2")) - .with_system(component.label("2")); + .with_system(component.label(A0).before(A2)) + .with_system(component.label(A1).before(A2)) + .with_system(component.label(A2)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("0".as_label(), "1".as_label())) - || ambiguities.contains(&("1".as_label(), "0".as_label())) + ambiguities.contains(&(A0.as_label(), A1.as_label())) + || ambiguities.contains(&(A1.as_label(), A0.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(component.label("0")) - .with_system(component.label("1").after("0")) - .with_system(component.label("2").after("0")); + .with_system(component.label(A0)) + .with_system(component.label(A1).after(A0)) + .with_system(component.label(A2).after(A0)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "2".as_label())) - || ambiguities.contains(&("2".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A2.as_label())) + || ambiguities.contains(&(A2.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(component.label("0").before("1").before("2")) - .with_system(component.label("1")) - .with_system(component.label("2")) - .with_system(component.label("3").after("1").after("2")); + .with_system(component.label(A0).before(A1).before(A2)) + .with_system(component.label(A1)) + .with_system(component.label(A2)) + .with_system(component.label(A3).after(A1).after(A2)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "2".as_label())) - || ambiguities.contains(&("2".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A2.as_label())) + || ambiguities.contains(&(A2.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() - .with_system(component.label("0").before("1").before("2")) - .with_system(component.label("1").in_ambiguity_set("a")) - .with_system(component.label("2").in_ambiguity_set("a")) - .with_system(component.label("3").after("1").after("2")); + .with_system(component.label(A0).before(A1).before(A2)) + .with_system(component.label(A1).in_ambiguity_set(SetA)) + .with_system(component.label(A2).in_ambiguity_set(SetA)) + .with_system(component.label(A3).after(A1).after(A2)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert_eq!(ambiguities.len(), 0); let mut stage = SystemStage::parallel() - .with_system(component.label("0").before("1").before("2")) - .with_system(component.label("1").in_ambiguity_set("a")) - .with_system(component.label("2").in_ambiguity_set("b")) - .with_system(component.label("3").after("1").after("2")); + .with_system(component.label(A0).before(A1).before(A2)) + .with_system(component.label(A1).in_ambiguity_set(SetA)) + .with_system(component.label(A2).in_ambiguity_set(SetB)) + .with_system(component.label(A3).after(A1).after(A2)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "2".as_label())) - || ambiguities.contains(&("2".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A2.as_label())) + || ambiguities.contains(&(A2.as_label(), A1.as_label())) ); assert_eq!(ambiguities.len(), 1); let mut stage = SystemStage::parallel() .with_system( component - .label("0") - .before("1") - .before("2") - .before("3") - .before("4"), + .label(A0) + .before(A1) + .before(A2) + .before(A3) + .before(A4), ) - .with_system(component.label("1")) - .with_system(component.label("2")) - .with_system(component.label("3")) - .with_system(component.label("4")) - .with_system( - component - .label("5") - .after("1") - .after("2") - .after("3") - .after("4"), - ); + .with_system(component.label(A1)) + .with_system(component.label(A2)) + .with_system(component.label(A3)) + .with_system(component.label(A4)) + .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "2".as_label())) - || ambiguities.contains(&("2".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A2.as_label())) + || ambiguities.contains(&(A2.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("3".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "3".as_label())) + ambiguities.contains(&(A3.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A3.as_label())) ); assert_eq!(ambiguities.len(), 6); let mut stage = SystemStage::parallel() .with_system( component - .label("0") - .before("1") - .before("2") - .before("3") - .before("4"), + .label(A0) + .before(A1) + .before(A2) + .before(A3) + .before(A4), ) - .with_system(component.label("1").in_ambiguity_set("a")) - .with_system(component.label("2").in_ambiguity_set("a")) - .with_system(component.label("3").in_ambiguity_set("a")) - .with_system(component.label("4").in_ambiguity_set("a")) - .with_system( - component - .label("5") - .after("1") - .after("2") - .after("3") - .after("4"), - ); + .with_system(component.label(A1).in_ambiguity_set(SetA)) + .with_system(component.label(A2).in_ambiguity_set(SetA)) + .with_system(component.label(A3).in_ambiguity_set(SetA)) + .with_system(component.label(A4).in_ambiguity_set(SetA)) + .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert_eq!(ambiguities.len(), 0); let mut stage = SystemStage::parallel() .with_system( component - .label("0") - .before("1") - .before("2") - .before("3") - .before("4"), + .label(A0) + .before(A1) + .before(A2) + .before(A3) + .before(A4), ) - .with_system(component.label("1").in_ambiguity_set("a")) - .with_system(component.label("2").in_ambiguity_set("a")) + .with_system(component.label(A1).in_ambiguity_set(SetA)) + .with_system(component.label(A2).in_ambiguity_set(SetA)) .with_system( component - .label("3") - .in_ambiguity_set("a") - .in_ambiguity_set("b"), + .label(A3) + .in_ambiguity_set(SetA) + .in_ambiguity_set(SetB), ) - .with_system(component.label("4").in_ambiguity_set("b")) - .with_system( - component - .label("5") - .after("1") - .after("2") - .after("3") - .after("4"), - ); + .with_system(component.label(A4).in_ambiguity_set(SetB)) + .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); + let ambiguities = find_ambiguities_first_labels(&stage.parallel); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A2.as_label())) ); assert_eq!(ambiguities.len(), 2); let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label("0")) - .with_system(empty.exclusive_system().label("1").after("0")) - .with_system(empty.exclusive_system().label("2").after("1")) - .with_system(empty.exclusive_system().label("3").after("2")) - .with_system(empty.exclusive_system().label("4").after("3")) - .with_system(empty.exclusive_system().label("5").after("4")) - .with_system(empty.exclusive_system().label("6").after("5")) - .with_system(empty.exclusive_system().label("7").after("6")); + .with_system(empty.exclusive_system().label(A0)) + .with_system(empty.exclusive_system().label(A1).after(A0)) + .with_system(empty.exclusive_system().label(A2).after(A1)) + .with_system(empty.exclusive_system().label(A3).after(A2)) + .with_system(empty.exclusive_system().label(A4).after(A3)) + .with_system(empty.exclusive_system().label(A5).after(A4)) + .with_system(empty.exclusive_system().label(A6).after(A5)) + .with_system(empty.exclusive_system().label(A7).after(A6)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); assert_eq!(find_ambiguities(&stage.exclusive_at_start).len(), 0); let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label("0").before("1").before("3")) - .with_system(empty.exclusive_system().label("1")) - .with_system(empty.exclusive_system().label("2").after("1")) - .with_system(empty.exclusive_system().label("3")) - .with_system(empty.exclusive_system().label("4").after("3").before("5")) - .with_system(empty.exclusive_system().label("5")) - .with_system(empty.exclusive_system().label("6").after("2").after("5")); + .with_system(empty.exclusive_system().label(A0).before(A1).before(A3)) + .with_system(empty.exclusive_system().label(A1)) + .with_system(empty.exclusive_system().label(A2).after(A1)) + .with_system(empty.exclusive_system().label(A3)) + .with_system(empty.exclusive_system().label(A4).after(A3).before(A5)) + .with_system(empty.exclusive_system().label(A5)) + .with_system(empty.exclusive_system().label(A6).after(A2).after(A5)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); + let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&("1".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "5".as_label())) - || ambiguities.contains(&("5".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A5.as_label())) + || ambiguities.contains(&(A5.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "5".as_label())) - || ambiguities.contains(&("5".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A5.as_label())) + || ambiguities.contains(&(A5.as_label(), A2.as_label())) ); assert_eq!(ambiguities.len(), 6); let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label("0").before("1").before("3")) - .with_system(empty.exclusive_system().label("1").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("2").after("1")) - .with_system(empty.exclusive_system().label("3").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("4").after("3").before("5")) - .with_system(empty.exclusive_system().label("5").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("6").after("2").after("5")); + .with_system(empty.exclusive_system().label(A0).before(A1).before(A3)) + .with_system(empty.exclusive_system().label(A1).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A2).after(A1)) + .with_system(empty.exclusive_system().label(A3).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A4).after(A3).before(A5)) + .with_system(empty.exclusive_system().label(A5).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A6).after(A2).after(A5)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); + let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&("2".as_label(), "3".as_label())) - || ambiguities.contains(&("3".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A3.as_label())) + || ambiguities.contains(&(A3.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("1".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "1".as_label())) + ambiguities.contains(&(A1.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A1.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "4".as_label())) - || ambiguities.contains(&("4".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A4.as_label())) + || ambiguities.contains(&(A4.as_label(), A2.as_label())) ); assert!( - ambiguities.contains(&("2".as_label(), "5".as_label())) - || ambiguities.contains(&("5".as_label(), "2".as_label())) + ambiguities.contains(&(A2.as_label(), A5.as_label())) + || ambiguities.contains(&(A5.as_label(), A2.as_label())) ); assert_eq!(ambiguities.len(), 4); let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label("0").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("1").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("2").in_ambiguity_set("a")) - .with_system(empty.exclusive_system().label("3").in_ambiguity_set("a")); + .with_system(empty.exclusive_system().label(A0).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A1).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A2).in_ambiguity_set(SetA)) + .with_system(empty.exclusive_system().label(A3).in_ambiguity_set(SetA)); stage.initialize_systems(&mut world); stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); + let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); assert_eq!(ambiguities.len(), 0); } @@ -2067,14 +2065,17 @@ mod tests { res.0.push(query.iter().len()); } + #[derive(SystemLabel)] + struct Spawn; + let mut world = World::new(); world.init_resource::(); let mut stage = SystemStage::parallel() - .with_system(spawn_entity.label("spawn")) + .with_system(spawn_entity.label(Spawn)) .with_system_set( SystemSet::new() .with_run_criteria(even_number_of_entities_critiera) - .with_system(count_entities.before("spawn")), + .with_system(count_entities.before(Spawn)), ); stage.run(&mut world); stage.run(&mut world); diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index c08dfaa886e52..3037500b6caa6 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -501,6 +501,12 @@ mod test { let mut stage = SystemStage::parallel(); + #[derive(SystemLabel)] + enum Inactive { + S4, + S5, + } + stage.add_system_set(State::::get_driver()); stage .add_system_set( @@ -548,7 +554,7 @@ mod test { }, )) .add_system_set(State::on_inactive_update_set(MyState::S4).with_system( - (|mut r: ResMut| r.0.push("inactive S4")).label("inactive s4"), + (|mut r: ResMut| r.0.push("inactive S4")).label(Inactive::S4), )) .add_system_set( State::on_update_set(MyState::S5).with_system( @@ -556,14 +562,14 @@ mod test { r.0.push("update S5"); s.overwrite_push(MyState::S6).unwrap(); }) - .after("inactive s4"), + .after(Inactive::S4), ), ) .add_system_set( State::on_inactive_update_set(MyState::S5).with_system( (|mut r: ResMut| r.0.push("inactive S5")) - .label("inactive s5") - .after("inactive s4"), + .label(Inactive::S5) + .after(Inactive::S4), ), ) .add_system_set( @@ -572,7 +578,7 @@ mod test { r.0.push("update S6"); s.overwrite_push(MyState::Final).unwrap(); }) - .after("inactive s5"), + .after(Inactive::S5), ), ) .add_system_set( diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index aef76c277a5ec..6dca2d5f4ed2f 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -130,6 +130,8 @@ pub fn assert_is_exclusive_system( mod tests { use std::any::TypeId; + use crate::prelude::StageLabel; + use crate::{ self as bevy_ecs, archetype::{ArchetypeComponentId, Archetypes}, @@ -168,6 +170,9 @@ mod tests { #[derive(Component)] struct W(T); + #[derive(StageLabel)] + struct UpdateStage; + #[test] fn simple_system() { fn sys(query: Query<&A>) { @@ -188,7 +193,7 @@ mod tests { let mut schedule = Schedule::default(); let mut update = SystemStage::parallel(); update.add_system(system); - schedule.add_stage("update", update); + schedule.add_stage(UpdateStage, update); schedule.run(world); } @@ -310,12 +315,15 @@ mod tests { world.insert_resource(Added(0)); world.insert_resource(Changed(0)); + #[derive(StageLabel)] + struct ClearTrackers; + let mut schedule = Schedule::default(); let mut update = SystemStage::parallel(); update.add_system(incr_e_on_flip); - schedule.add_stage("update", update); + schedule.add_stage(UpdateStage, update); schedule.add_stage( - "clear_trackers", + ClearTrackers, SystemStage::single(World::clear_trackers.exclusive_system()), ); diff --git a/crates/bevy_time/src/fixed_timestep.rs b/crates/bevy_time/src/fixed_timestep.rs index 8f1c44065c0af..8f8818f3e58a4 100644 --- a/crates/bevy_time/src/fixed_timestep.rs +++ b/crates/bevy_time/src/fixed_timestep.rs @@ -249,8 +249,10 @@ mod test { world.insert_resource(Count(0)); let mut schedule = Schedule::default(); + #[derive(StageLabel)] + struct Update; schedule.add_stage( - "update", + Update, SystemStage::parallel() .with_run_criteria(FixedTimestep::step(0.5).with_label(LABEL)) .with_system(fixed_update), diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index 9406149fb0847..9ec02dedffb33 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -105,6 +105,9 @@ mod test { use crate::TransformBundle; use bevy_hierarchy::{BuildChildren, BuildWorldChildren, Children, Parent}; + #[derive(StageLabel)] + struct Update; + #[test] fn did_propagate() { let mut world = World::default(); @@ -113,7 +116,7 @@ mod test { update_stage.add_system(transform_propagate_system); let mut schedule = Schedule::default(); - schedule.add_stage("update", update_stage); + schedule.add_stage(Update, update_stage); // Root entity world @@ -156,7 +159,7 @@ mod test { update_stage.add_system(transform_propagate_system); let mut schedule = Schedule::default(); - schedule.add_stage("update", update_stage); + schedule.add_stage(Update, update_stage); // Root entity let mut queue = CommandQueue::default(); @@ -198,7 +201,7 @@ mod test { update_stage.add_system(transform_propagate_system); let mut schedule = Schedule::default(); - schedule.add_stage("update", update_stage); + schedule.add_stage(Update, update_stage); // Add parent entities let mut children = Vec::new(); diff --git a/crates/bevy_ui/src/update.rs b/crates/bevy_ui/src/update.rs index 05628555f1980..edae4dbdaee6a 100644 --- a/crates/bevy_ui/src/update.rs +++ b/crates/bevy_ui/src/update.rs @@ -135,7 +135,7 @@ fn update_clipping( mod tests { use bevy_ecs::{ component::Component, - schedule::{Schedule, Stage, SystemStage}, + schedule::{Schedule, Stage, StageLabel, SystemStage}, system::{CommandQueue, Commands}, world::World, }; @@ -161,6 +161,9 @@ mod tests { (transform.translation.z / UI_Z_STEP).round() as u32 } + #[derive(StageLabel)] + struct Update; + #[test] fn test_ui_z_system() { let mut world = World::default(); @@ -209,7 +212,7 @@ mod tests { let mut schedule = Schedule::default(); let mut update_stage = SystemStage::parallel(); update_stage.add_system(ui_z_system); - schedule.add_stage("update", update_stage); + schedule.add_stage(Update, update_stage); schedule.run(&mut world); let mut actual_result = world diff --git a/examples/ecs/system_sets.rs b/examples/ecs/system_sets.rs index 035103ca2789e..0e591e59c0d2e 100644 --- a/examples/ecs/system_sets.rs +++ b/examples/ecs/system_sets.rs @@ -40,6 +40,9 @@ struct PostPhysics; struct Done(bool); fn main() { + #[derive(RunCriteriaLabel)] + struct IsDone; + App::new() .add_plugins(DefaultPlugins) .init_resource::() @@ -70,8 +73,7 @@ fn main() { // This shows that we can modify existing run criteria results. // Here we create a _not done_ criteria by piping the output of // the `is_done` system and inverting the output. - // Notice a string literal also works as a label. - .with_run_criteria(RunCriteria::pipe("is_done_label", inverse)) + .with_run_criteria(RunCriteria::pipe(IsDone, inverse)) // `collision` and `sfx` are not ordered with respect to // each other, and may run in any order .with_system(collision) @@ -80,7 +82,7 @@ fn main() { .add_system( exit.after(PostPhysics) // Label the run criteria such that the `PostPhysics` set can reference it - .with_run_criteria(is_done.label("is_done_label")), + .with_run_criteria(is_done.label(IsDone)), ) .run(); }