From 9c9480fbd460b0db183803cd1b6cf6a60a6d16ed Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:30:21 -0400 Subject: [PATCH 01/19] rename schedule error --- crates/bevy_ecs/src/world/error.rs | 2 +- crates/bevy_ecs/src/world/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/world/error.rs b/crates/bevy_ecs/src/world/error.rs index a6197ac44c36d..60fd5dd1a91d1 100644 --- a/crates/bevy_ecs/src/world/error.rs +++ b/crates/bevy_ecs/src/world/error.rs @@ -7,4 +7,4 @@ use crate::schedule::BoxedScheduleLabel; /// [`World::try_run_schedule`]: crate::world::World::try_run_schedule #[derive(Error, Debug)] #[error("The schedule with the label {0:?} was not found.")] -pub struct TryRunScheduleError(pub BoxedScheduleLabel); +pub struct ScheduleNotFoundError(pub BoxedScheduleLabel); diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index a7060b9e73b04..73ec68771f016 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -21,7 +21,7 @@ use crate::{ schedule::{Schedule, ScheduleLabel, Schedules}, storage::{ResourceData, Storages}, system::Resource, - world::error::TryRunScheduleError, + world::error::ScheduleNotFoundError, }; use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::tracing::warn; @@ -1726,7 +1726,7 @@ impl World { pub fn try_run_schedule( &mut self, label: impl ScheduleLabel, - ) -> Result<(), TryRunScheduleError> { + ) -> Result<(), ScheduleNotFoundError> { self.try_run_schedule_ref(&label) } @@ -1742,9 +1742,9 @@ impl World { pub fn try_run_schedule_ref( &mut self, label: &dyn ScheduleLabel, - ) -> Result<(), TryRunScheduleError> { + ) -> Result<(), ScheduleNotFoundError> { let Some((extracted_label, mut schedule)) = self.resource_mut::().remove_entry(label) else { - return Err(TryRunScheduleError(label.dyn_clone())); + return Err(ScheduleNotFoundError(label.dyn_clone())); }; // TODO: move this span to Schedule::run From 4bc5eaa92f895459241cfb803342d2c762b16fca Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:39:40 -0400 Subject: [PATCH 02/19] add schedule scope methods --- crates/bevy_ecs/src/world/mod.rs | 61 ++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 73ec68771f016..6d9f6883643bf 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1716,6 +1716,51 @@ impl World { schedules.insert(label, schedule); } + pub fn try_schedule_scope( + &mut self, + label: impl ScheduleLabel, + f: impl FnOnce(&mut World, &mut Schedule) -> R, + ) -> Result { + self.try_schedule_scope_ref(&label, f) + } + + pub fn try_schedule_scope_ref( + &mut self, + label: &dyn ScheduleLabel, + f: impl FnOnce(&mut World, &mut Schedule) -> R, + ) -> Result { + let Some((extracted_label, mut schedule)) = self.resource_mut::().remove_entry(label) else { + return Err(ScheduleNotFoundError(label.dyn_clone())); + }; + + // TODO: move this span to Schedule::run + #[cfg(feature = "trace")] + let _span = bevy_utils::tracing::info_span!("schedule", name = ?extracted_label).entered(); + let value = f(self, &mut schedule); + + self.resource_mut::() + .insert(extracted_label, schedule); + + Ok(value) + } + + pub fn schedule_scope( + &mut self, + label: impl ScheduleLabel, + f: impl FnOnce(&mut World, &mut Schedule) -> R, + ) -> R { + self.schedule_scope_ref(&label, f) + } + + pub fn schedule_scope_ref( + &mut self, + label: &dyn ScheduleLabel, + f: impl FnOnce(&mut World, &mut Schedule) -> R, + ) -> R { + self.try_schedule_scope_ref(label, f) + .unwrap_or_else(|e| panic!("{e}")) + } + /// Attempts to run the [`Schedule`] associated with the `label` a single time, /// and returns a [`TryRunScheduleError`] if the schedule does not exist. /// @@ -1743,18 +1788,7 @@ impl World { &mut self, label: &dyn ScheduleLabel, ) -> Result<(), ScheduleNotFoundError> { - let Some((extracted_label, mut schedule)) = self.resource_mut::().remove_entry(label) else { - return Err(ScheduleNotFoundError(label.dyn_clone())); - }; - - // TODO: move this span to Schedule::run - #[cfg(feature = "trace")] - let _span = bevy_utils::tracing::info_span!("schedule", name = ?extracted_label).entered(); - schedule.run(self); - self.resource_mut::() - .insert(extracted_label, schedule); - - Ok(()) + self.try_schedule_scope_ref(label, |world, sched| sched.run(world)) } /// Runs the [`Schedule`] associated with the `label` a single time. @@ -1784,8 +1818,7 @@ impl World { /// /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. pub fn run_schedule_ref(&mut self, label: &dyn ScheduleLabel) { - self.try_run_schedule_ref(label) - .unwrap_or_else(|e| panic!("{}", e)); + self.schedule_scope_ref(label, |world, sched| sched.run(world)); } } From ecedbcc36fe85d1b2a621bf4601f30a3bc198464 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:41:25 -0400 Subject: [PATCH 03/19] update some doc links --- crates/bevy_ecs/src/world/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6d9f6883643bf..4acc55c291b46 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1762,7 +1762,7 @@ impl World { } /// Attempts to run the [`Schedule`] associated with the `label` a single time, - /// and returns a [`TryRunScheduleError`] if the schedule does not exist. + /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached. @@ -1776,7 +1776,7 @@ impl World { } /// Attempts to run the [`Schedule`] associated with the `label` a single time, - /// and returns a [`TryRunScheduleError`] if the schedule does not exist. + /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. /// /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// From 70333b1f271c429c5736f4396d25c0574e962910 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:47:12 -0400 Subject: [PATCH 04/19] add docs --- crates/bevy_ecs/src/world/mod.rs | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 4acc55c291b46..4ef3f587379be 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1716,6 +1716,16 @@ impl World { schedules.insert(label, schedule); } + /// Temporarily removes the schedule associated with `label` from the world, + /// runs user code, and finally re-adds the schedule. + /// This returns a [`ScheduleNotFoundError`] if there is no schedule + /// associated with `label`. + /// + /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, + /// and system state is cached. + /// + /// For simple cases where you just need to call the schedule, + /// consider using [`World::try_run_schedule`] instead. pub fn try_schedule_scope( &mut self, label: impl ScheduleLabel, @@ -1724,6 +1734,18 @@ impl World { self.try_schedule_scope_ref(&label, f) } + /// Temporarily removes the schedule associated with `label` from the world, + /// runs user code, and finally re-adds the schedule. + /// This returns a [`ScheduleNotFoundError`] if there is no schedule + /// associated with `label`. + /// + /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. + /// + /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, + /// and system state is cached. + /// + /// For simple cases where you just need to call the schedule, + /// consider using [`World::try_run_schedule`] instead. pub fn try_schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, @@ -1744,6 +1766,18 @@ impl World { Ok(value) } + /// Temporarily removes the schedule associated with `label` from the world, + /// runs user code, and finally re-adds the schedule. + /// + /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, + /// and system state is cached. + /// + /// For simple cases where you just need to call the schedule, + /// consider using [`World::try_run_schedule`] instead. + /// + /// # Panics + /// + /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. pub fn schedule_scope( &mut self, label: impl ScheduleLabel, @@ -1752,6 +1786,20 @@ impl World { self.schedule_scope_ref(&label, f) } + /// Temporarily removes the schedule associated with `label` from the world, + /// runs user code, and finally re-adds the schedule. + /// + /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. + /// + /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, + /// and system state is cached. + /// + /// For simple cases where you just need to call the schedule, + /// consider using [`World::try_run_schedule`] instead. + /// + /// # Panics + /// + /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. pub fn schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, From 0e61de6e70a92323df71429b2cccbac5876e330a Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:17:55 -0400 Subject: [PATCH 05/19] initialize `Schedules` if it doesn't exist --- crates/bevy_ecs/src/world/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 4ef3f587379be..4581e0218f23c 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1751,7 +1751,9 @@ impl World { label: &dyn ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R, ) -> Result { - let Some((extracted_label, mut schedule)) = self.resource_mut::().remove_entry(label) else { + let Some((extracted_label, mut schedule)) + = self.get_resource_or_insert_with(Schedules::default).remove_entry(label) + else { return Err(ScheduleNotFoundError(label.dyn_clone())); }; From 2f6024218fa53774fbc9685362bf2c8f73a94cde Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:19:08 -0400 Subject: [PATCH 06/19] update docs --- crates/bevy_ecs/src/world/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 4581e0218f23c..a9f65c0eeb59a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1745,7 +1745,7 @@ impl World { /// and system state is cached. /// /// For simple cases where you just need to call the schedule, - /// consider using [`World::try_run_schedule`] instead. + /// consider using [`World::try_run_schedule_ref`] instead. pub fn try_schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, @@ -1775,11 +1775,11 @@ impl World { /// and system state is cached. /// /// For simple cases where you just need to call the schedule, - /// consider using [`World::try_run_schedule`] instead. + /// consider using [`World::run_schedule`] instead. /// /// # Panics /// - /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. + /// Panics if the requested schedule does not exist. pub fn schedule_scope( &mut self, label: impl ScheduleLabel, @@ -1797,11 +1797,11 @@ impl World { /// and system state is cached. /// /// For simple cases where you just need to call the schedule, - /// consider using [`World::try_run_schedule`] instead. + /// consider using [`World::run_schedule_ref`] instead. /// /// # Panics /// - /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. + /// Panics if the requested schedule does not exist. pub fn schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, @@ -1850,7 +1850,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. + /// Panics if the requested schedule does not exist. pub fn run_schedule(&mut self, label: impl ScheduleLabel) { self.run_schedule_ref(&label); } @@ -1866,7 +1866,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added. + /// Panics if the requested schedule does not exist. pub fn run_schedule_ref(&mut self, label: &dyn ScheduleLabel) { self.schedule_scope_ref(label, |world, sched| sched.run(world)); } From 0eed91d54fb081426b6833e5691d72275427146a Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:23:09 -0400 Subject: [PATCH 07/19] document `Schedules` initialization --- crates/bevy_ecs/src/world/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index a9f65c0eeb59a..37b0e5c2690c6 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1722,7 +1722,7 @@ impl World { /// associated with `label`. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::try_run_schedule`] instead. @@ -1742,7 +1742,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::try_run_schedule_ref`] instead. @@ -1772,7 +1772,7 @@ impl World { /// runs user code, and finally re-adds the schedule. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule`] instead. @@ -1794,7 +1794,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule_ref`] instead. @@ -1815,7 +1815,7 @@ impl World { /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. pub fn try_run_schedule( @@ -1831,7 +1831,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. pub fn try_run_schedule_ref( @@ -1844,7 +1844,7 @@ impl World { /// Runs the [`Schedule`] associated with the `label` a single time. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. /// @@ -1860,7 +1860,7 @@ impl World { /// Unlike the `run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. + /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. /// From a90732171d2ac7b9089e1f738fcf75c96d3df4cf Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:24:40 -0400 Subject: [PATCH 08/19] Revert "document `Schedules` initialization" This reverts commit 0eed91d54fb081426b6833e5691d72275427146a. --- crates/bevy_ecs/src/world/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 37b0e5c2690c6..a9f65c0eeb59a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1722,7 +1722,7 @@ impl World { /// associated with `label`. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::try_run_schedule`] instead. @@ -1742,7 +1742,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::try_run_schedule_ref`] instead. @@ -1772,7 +1772,7 @@ impl World { /// runs user code, and finally re-adds the schedule. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule`] instead. @@ -1794,7 +1794,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule_ref`] instead. @@ -1815,7 +1815,7 @@ impl World { /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. pub fn try_run_schedule( @@ -1831,7 +1831,7 @@ impl World { /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. pub fn try_run_schedule_ref( @@ -1844,7 +1844,7 @@ impl World { /// Runs the [`Schedule`] associated with the `label` a single time. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. /// @@ -1860,7 +1860,7 @@ impl World { /// Unlike the `run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, - /// and system state is cached. The `Schedules` resource will be initialized if it does not exist. + /// and system state is cached. /// /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. /// From fbc950b1396cf11f3bccd850a5fc6a9d3bd9523e Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:28:53 -0400 Subject: [PATCH 09/19] don't initialize `Schedules` if it doesn't exist --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index a9f65c0eeb59a..71904985aa527 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1752,7 +1752,7 @@ impl World { f: impl FnOnce(&mut World, &mut Schedule) -> R, ) -> Result { let Some((extracted_label, mut schedule)) - = self.get_resource_or_insert_with(Schedules::default).remove_entry(label) + = self.get_resource_mut::().and_then(|mut s| s.remove_entry(label)) else { return Err(ScheduleNotFoundError(label.dyn_clone())); }; From 5fa806f0e10f60ceb737745bb8578da4c1555bff Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 10:29:51 -0400 Subject: [PATCH 10/19] un-rename an error --- crates/bevy_ecs/src/world/error.rs | 2 +- crates/bevy_ecs/src/world/mod.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/src/world/error.rs b/crates/bevy_ecs/src/world/error.rs index 60fd5dd1a91d1..a6197ac44c36d 100644 --- a/crates/bevy_ecs/src/world/error.rs +++ b/crates/bevy_ecs/src/world/error.rs @@ -7,4 +7,4 @@ use crate::schedule::BoxedScheduleLabel; /// [`World::try_run_schedule`]: crate::world::World::try_run_schedule #[derive(Error, Debug)] #[error("The schedule with the label {0:?} was not found.")] -pub struct ScheduleNotFoundError(pub BoxedScheduleLabel); +pub struct TryRunScheduleError(pub BoxedScheduleLabel); diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 71904985aa527..c6ab37d5b4f6d 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -21,7 +21,7 @@ use crate::{ schedule::{Schedule, ScheduleLabel, Schedules}, storage::{ResourceData, Storages}, system::Resource, - world::error::ScheduleNotFoundError, + world::error::TryRunScheduleError, }; use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::tracing::warn; @@ -1730,7 +1730,7 @@ impl World { &mut self, label: impl ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R, - ) -> Result { + ) -> Result { self.try_schedule_scope_ref(&label, f) } @@ -1750,11 +1750,11 @@ impl World { &mut self, label: &dyn ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R, - ) -> Result { + ) -> Result { let Some((extracted_label, mut schedule)) = self.get_resource_mut::().and_then(|mut s| s.remove_entry(label)) else { - return Err(ScheduleNotFoundError(label.dyn_clone())); + return Err(TryRunScheduleError(label.dyn_clone())); }; // TODO: move this span to Schedule::run @@ -1821,7 +1821,7 @@ impl World { pub fn try_run_schedule( &mut self, label: impl ScheduleLabel, - ) -> Result<(), ScheduleNotFoundError> { + ) -> Result<(), TryRunScheduleError> { self.try_run_schedule_ref(&label) } @@ -1837,7 +1837,7 @@ impl World { pub fn try_run_schedule_ref( &mut self, label: &dyn ScheduleLabel, - ) -> Result<(), ScheduleNotFoundError> { + ) -> Result<(), TryRunScheduleError> { self.try_schedule_scope_ref(label, |world, sched| sched.run(world)) } From 9dc79652b33792db2409e01b97b3f6891a763b49 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:18:30 -0400 Subject: [PATCH 11/19] undo a branch --- crates/bevy_ecs/src/world/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index c6ab37d5b4f6d..ca3e7f3582376 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1751,9 +1751,7 @@ impl World { label: &dyn ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R, ) -> Result { - let Some((extracted_label, mut schedule)) - = self.get_resource_mut::().and_then(|mut s| s.remove_entry(label)) - else { + let Some((extracted_label, mut schedule)) = self.resource_mut::().remove_entry(label) else { return Err(TryRunScheduleError(label.dyn_clone())); }; From faaeb13977f96d564155fb6f8e6c28fa88466711 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:22:10 -0400 Subject: [PATCH 12/19] panic panic docs less redundant --- crates/bevy_ecs/src/world/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index ca3e7f3582376..8b6c2c997e35a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1777,7 +1777,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist. + /// If the requested schedule does not exist. pub fn schedule_scope( &mut self, label: impl ScheduleLabel, @@ -1799,7 +1799,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist. + /// If the requested schedule does not exist. pub fn schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, @@ -1848,7 +1848,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist. + /// If the requested schedule does not exist. pub fn run_schedule(&mut self, label: impl ScheduleLabel) { self.run_schedule_ref(&label); } @@ -1864,7 +1864,7 @@ impl World { /// /// # Panics /// - /// Panics if the requested schedule does not exist. + /// If the requested schedule does not exist. pub fn run_schedule_ref(&mut self, label: &dyn ScheduleLabel) { self.schedule_scope_ref(label, |world, sched| sched.run(world)); } From 9ba631a95dc5064766aa4a50c5da4835ba5a6d7d Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:04:17 -0400 Subject: [PATCH 13/19] add a doctest to `schedule_scope` --- crates/bevy_ecs/src/world/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 8b6c2c997e35a..6b910ae7d0e86 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1775,6 +1775,31 @@ impl World { /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule`] instead. /// + /// # Examples + /// + /// ``` + /// # use bevy_ecs::{prelude::*, schedule::ScheduleLabel}; + /// # #[derive(ScheduleLabel, Debug, Clone, Copy, PartialEq, Eq, Hash)] + /// # pub struct MySchedule; + /// # #[derive(Resource)] + /// # struct Counter(usize); + /// # + /// # let mut world = World::new(); + /// # world.insert_resource(Counter(0)); + /// # let mut schedule = Schedule::new(); + /// # schedule.add_systems(tick_counter); + /// # world.init_resource::(); + /// # world.add_schedule(schedule, MySchedule); + /// # fn tick_counter(mut counter: ResMut) { counter.0 += 1; } + /// // Run the schedule five times. + /// world.schedule_scope(MySchedule, |world, schedule| { + /// for _ in 0..5 { + /// schedule.run(world); + /// } + /// }); + /// # assert_eq!(world.resource::().0, 5); + /// ``` + /// /// # Panics /// /// If the requested schedule does not exist. From 62551054df8fbfc3681af6a48f6ae79a64b102fc Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:06:27 -0400 Subject: [PATCH 14/19] link to `schedule_scope` on all methods --- crates/bevy_ecs/src/world/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6b910ae7d0e86..85a153bb61f0b 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1724,8 +1724,9 @@ impl World { /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached. /// - /// For simple cases where you just need to call the schedule, + /// For simple cases where you just need to call the schedule once, /// consider using [`World::try_run_schedule`] instead. + /// For other use cases, see the example on [`World::schedule_scope`]. pub fn try_schedule_scope( &mut self, label: impl ScheduleLabel, @@ -1744,8 +1745,9 @@ impl World { /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached. /// - /// For simple cases where you just need to call the schedule, + /// For simple cases where you just need to call the schedule once, /// consider using [`World::try_run_schedule_ref`] instead. + /// For other use cases, see the example on [`World::schedule_scope`]. pub fn try_schedule_scope_ref( &mut self, label: &dyn ScheduleLabel, @@ -1772,9 +1774,6 @@ impl World { /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached. /// - /// For simple cases where you just need to call the schedule, - /// consider using [`World::run_schedule`] instead. - /// /// # Examples /// /// ``` @@ -1800,6 +1799,9 @@ impl World { /// # assert_eq!(world.resource::().0, 5); /// ``` /// + /// For simple cases where you just need to call the schedule once, + /// consider using [`World::run_schedule`] instead. + /// /// # Panics /// /// If the requested schedule does not exist. @@ -1821,6 +1823,7 @@ impl World { /// /// For simple cases where you just need to call the schedule, /// consider using [`World::run_schedule_ref`] instead. + /// For other use cases, see the example on [`World::schedule_scope`]. /// /// # Panics /// From 91f3cba034a89c01cfdd8dfd9727dd856b4b1b45 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:06:51 -0400 Subject: [PATCH 15/19] finish reverting a rename --- crates/bevy_ecs/src/world/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 85a153bb61f0b..f0cb3fa053e95 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1718,7 +1718,7 @@ impl World { /// Temporarily removes the schedule associated with `label` from the world, /// runs user code, and finally re-adds the schedule. - /// This returns a [`ScheduleNotFoundError`] if there is no schedule + /// This returns a [`TryRunScheduleError`] if there is no schedule /// associated with `label`. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, @@ -1737,7 +1737,7 @@ impl World { /// Temporarily removes the schedule associated with `label` from the world, /// runs user code, and finally re-adds the schedule. - /// This returns a [`ScheduleNotFoundError`] if there is no schedule + /// This returns a [`TryRunScheduleError`] if there is no schedule /// associated with `label`. /// /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. @@ -1838,7 +1838,7 @@ impl World { } /// Attempts to run the [`Schedule`] associated with the `label` a single time, - /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. + /// and returns a [`TryRunScheduleError`] if the schedule does not exist. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached. @@ -1852,7 +1852,7 @@ impl World { } /// Attempts to run the [`Schedule`] associated with the `label` a single time, - /// and returns a [`ScheduleNotFoundError`] if the schedule does not exist. + /// and returns a [`TryRunScheduleError`] if the schedule does not exist. /// /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. /// From 0d2a1994426fed232507ee0b791b8bccd57550a6 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:36:17 -0400 Subject: [PATCH 16/19] warn if a schedule is invalidly re-inserted --- crates/bevy_ecs/src/world/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index f0cb3fa053e95..7864bdc369a78 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1762,8 +1762,12 @@ impl World { let _span = bevy_utils::tracing::info_span!("schedule", name = ?extracted_label).entered(); let value = f(self, &mut schedule); - self.resource_mut::() + let old = self + .resource_mut::() .insert(extracted_label, schedule); + if old.is_some() { + warn!("Schedule `{label:?}` was inserted during a call to `World::schedule_scope`: its value has been overwritten") + } Ok(value) } From c2f5ace5ee1f3fe7f09ab9ce9ca78703e95e78bd Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 14 Apr 2023 08:28:50 -0400 Subject: [PATCH 17/19] use `schedule_scope` for fixed timestep --- crates/bevy_time/src/fixed_timestep.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/bevy_time/src/fixed_timestep.rs b/crates/bevy_time/src/fixed_timestep.rs index eaf2eb675d00d..1fe442035fdbb 100644 --- a/crates/bevy_time/src/fixed_timestep.rs +++ b/crates/bevy_time/src/fixed_timestep.rs @@ -106,16 +106,11 @@ pub fn run_fixed_update_schedule(world: &mut World) { fixed_time.tick(delta_time); // Run the schedule until we run out of accumulated time - let mut check_again = true; - while check_again { - let mut fixed_time = world.resource_mut::(); - let fixed_time_run = fixed_time.expend().is_ok(); - if fixed_time_run { - let _ = world.try_run_schedule(FixedUpdate); - } else { - check_again = false; + let _ = world.try_schedule_scope(FixedUpdate, |world, schedule| { + while world.resource_mut::().expend().is_ok() { + schedule.run(world); } - } + }); } #[cfg(test)] From 6e3f73a6dc47283934d736f8807b61330ce523df Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:20:57 -0400 Subject: [PATCH 18/19] fix clippy --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6ef70e3f3d025..e6baf848bd923 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1773,7 +1773,7 @@ impl World { .resource_mut::() .insert(extracted_label, schedule); if old.is_some() { - warn!("Schedule `{label:?}` was inserted during a call to `World::schedule_scope`: its value has been overwritten") + warn!("Schedule `{label:?}` was inserted during a call to `World::schedule_scope`: its value has been overwritten"); } Ok(value) From 2f612fb189511e362283ff26de450669def8da20 Mon Sep 17 00:00:00 2001 From: James Liu Date: Sat, 15 Apr 2023 21:57:17 -0700 Subject: [PATCH 19/19] Fix docs --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index e6baf848bd923..c14b4ab8d4e90 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1827,7 +1827,7 @@ impl World { /// Temporarily removes the schedule associated with `label` from the world, /// runs user code, and finally re-adds the schedule. /// - /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone. + /// Unlike the `run_schedule` method, this method takes the label by reference, which can save a clone. /// /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label, /// and system state is cached.