@@ -1721,33 +1721,43 @@ impl World {
17211721 schedules. insert ( label, schedule) ;
17221722 }
17231723
1724- /// Attempts to run the [`Schedule`] associated with the `label` a single time,
1725- /// and returns a [`TryRunScheduleError`] if the schedule does not exist.
1724+ /// Temporarily removes the schedule associated with `label` from the world,
1725+ /// runs user code, and finally re-adds the schedule.
1726+ /// This returns a [`TryRunScheduleError`] if there is no schedule
1727+ /// associated with `label`.
17261728 ///
17271729 /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
17281730 /// and system state is cached.
17291731 ///
1730- /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
1731- pub fn try_run_schedule (
1732+ /// For simple cases where you just need to call the schedule once,
1733+ /// consider using [`World::try_run_schedule`] instead.
1734+ /// For other use cases, see the example on [`World::schedule_scope`].
1735+ pub fn try_schedule_scope < R > (
17321736 & mut self ,
17331737 label : impl ScheduleLabel ,
1734- ) -> Result < ( ) , TryRunScheduleError > {
1735- self . try_run_schedule_ref ( & label)
1738+ f : impl FnOnce ( & mut World , & mut Schedule ) -> R ,
1739+ ) -> Result < R , TryRunScheduleError > {
1740+ self . try_schedule_scope_ref ( & label, f)
17361741 }
17371742
1738- /// Attempts to run the [`Schedule`] associated with the `label` a single time,
1739- /// and returns a [`TryRunScheduleError`] if the schedule does not exist.
1743+ /// Temporarily removes the schedule associated with `label` from the world,
1744+ /// runs user code, and finally re-adds the schedule.
1745+ /// This returns a [`TryRunScheduleError`] if there is no schedule
1746+ /// associated with `label`.
17401747 ///
17411748 /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone.
17421749 ///
17431750 /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
17441751 /// and system state is cached.
17451752 ///
1746- /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
1747- pub fn try_run_schedule_ref (
1753+ /// For simple cases where you just need to call the schedule once,
1754+ /// consider using [`World::try_run_schedule_ref`] instead.
1755+ /// For other use cases, see the example on [`World::schedule_scope`].
1756+ pub fn try_schedule_scope_ref < R > (
17481757 & mut self ,
17491758 label : & dyn ScheduleLabel ,
1750- ) -> Result < ( ) , TryRunScheduleError > {
1759+ f : impl FnOnce ( & mut World , & mut Schedule ) -> R ,
1760+ ) -> Result < R , TryRunScheduleError > {
17511761 let Some ( ( extracted_label, mut schedule) )
17521762 = self . get_resource_mut :: < Schedules > ( ) . and_then ( |mut s| s. remove_entry ( label) )
17531763 else {
@@ -1757,11 +1767,115 @@ impl World {
17571767 // TODO: move this span to Schedule::run
17581768 #[ cfg( feature = "trace" ) ]
17591769 let _span = bevy_utils:: tracing:: info_span!( "schedule" , name = ?extracted_label) . entered ( ) ;
1760- schedule. run ( self ) ;
1761- self . resource_mut :: < Schedules > ( )
1770+ let value = f ( self , & mut schedule) ;
1771+
1772+ let old = self
1773+ . resource_mut :: < Schedules > ( )
17621774 . insert ( extracted_label, schedule) ;
1775+ if old. is_some ( ) {
1776+ warn ! ( "Schedule `{label:?}` was inserted during a call to `World::schedule_scope`: its value has been overwritten" ) ;
1777+ }
1778+
1779+ Ok ( value)
1780+ }
1781+
1782+ /// Temporarily removes the schedule associated with `label` from the world,
1783+ /// runs user code, and finally re-adds the schedule.
1784+ ///
1785+ /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
1786+ /// and system state is cached.
1787+ ///
1788+ /// # Examples
1789+ ///
1790+ /// ```
1791+ /// # use bevy_ecs::{prelude::*, schedule::ScheduleLabel};
1792+ /// # #[derive(ScheduleLabel, Debug, Clone, Copy, PartialEq, Eq, Hash)]
1793+ /// # pub struct MySchedule;
1794+ /// # #[derive(Resource)]
1795+ /// # struct Counter(usize);
1796+ /// #
1797+ /// # let mut world = World::new();
1798+ /// # world.insert_resource(Counter(0));
1799+ /// # let mut schedule = Schedule::new();
1800+ /// # schedule.add_systems(tick_counter);
1801+ /// # world.init_resource::<Schedules>();
1802+ /// # world.add_schedule(schedule, MySchedule);
1803+ /// # fn tick_counter(mut counter: ResMut<Counter>) { counter.0 += 1; }
1804+ /// // Run the schedule five times.
1805+ /// world.schedule_scope(MySchedule, |world, schedule| {
1806+ /// for _ in 0..5 {
1807+ /// schedule.run(world);
1808+ /// }
1809+ /// });
1810+ /// # assert_eq!(world.resource::<Counter>().0, 5);
1811+ /// ```
1812+ ///
1813+ /// For simple cases where you just need to call the schedule once,
1814+ /// consider using [`World::run_schedule`] instead.
1815+ ///
1816+ /// # Panics
1817+ ///
1818+ /// If the requested schedule does not exist.
1819+ pub fn schedule_scope < R > (
1820+ & mut self ,
1821+ label : impl ScheduleLabel ,
1822+ f : impl FnOnce ( & mut World , & mut Schedule ) -> R ,
1823+ ) -> R {
1824+ self . schedule_scope_ref ( & label, f)
1825+ }
17631826
1764- Ok ( ( ) )
1827+ /// Temporarily removes the schedule associated with `label` from the world,
1828+ /// runs user code, and finally re-adds the schedule.
1829+ ///
1830+ /// Unlike the `run_schedule` method, this method takes the label by reference, which can save a clone.
1831+ ///
1832+ /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
1833+ /// and system state is cached.
1834+ ///
1835+ /// For simple cases where you just need to call the schedule,
1836+ /// consider using [`World::run_schedule_ref`] instead.
1837+ /// For other use cases, see the example on [`World::schedule_scope`].
1838+ ///
1839+ /// # Panics
1840+ ///
1841+ /// If the requested schedule does not exist.
1842+ pub fn schedule_scope_ref < R > (
1843+ & mut self ,
1844+ label : & dyn ScheduleLabel ,
1845+ f : impl FnOnce ( & mut World , & mut Schedule ) -> R ,
1846+ ) -> R {
1847+ self . try_schedule_scope_ref ( label, f)
1848+ . unwrap_or_else ( |e| panic ! ( "{e}" ) )
1849+ }
1850+
1851+ /// Attempts to run the [`Schedule`] associated with the `label` a single time,
1852+ /// and returns a [`TryRunScheduleError`] if the schedule does not exist.
1853+ ///
1854+ /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
1855+ /// and system state is cached.
1856+ ///
1857+ /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
1858+ pub fn try_run_schedule (
1859+ & mut self ,
1860+ label : impl ScheduleLabel ,
1861+ ) -> Result < ( ) , TryRunScheduleError > {
1862+ self . try_run_schedule_ref ( & label)
1863+ }
1864+
1865+ /// Attempts to run the [`Schedule`] associated with the `label` a single time,
1866+ /// and returns a [`TryRunScheduleError`] if the schedule does not exist.
1867+ ///
1868+ /// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone.
1869+ ///
1870+ /// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
1871+ /// and system state is cached.
1872+ ///
1873+ /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
1874+ pub fn try_run_schedule_ref (
1875+ & mut self ,
1876+ label : & dyn ScheduleLabel ,
1877+ ) -> Result < ( ) , TryRunScheduleError > {
1878+ self . try_schedule_scope_ref ( label, |world, sched| sched. run ( world) )
17651879 }
17661880
17671881 /// Runs the [`Schedule`] associated with the `label` a single time.
@@ -1773,7 +1887,7 @@ impl World {
17731887 ///
17741888 /// # Panics
17751889 ///
1776- /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added .
1890+ /// If the requested schedule does not exist.
17771891 pub fn run_schedule ( & mut self , label : impl ScheduleLabel ) {
17781892 self . run_schedule_ref ( & label) ;
17791893 }
@@ -1789,10 +1903,9 @@ impl World {
17891903 ///
17901904 /// # Panics
17911905 ///
1792- /// Panics if the requested schedule does not exist, or the [`Schedules`] resource was not added .
1906+ /// If the requested schedule does not exist.
17931907 pub fn run_schedule_ref ( & mut self , label : & dyn ScheduleLabel ) {
1794- self . try_run_schedule_ref ( label)
1795- . unwrap_or_else ( |e| panic ! ( "{}" , e) ) ;
1908+ self . schedule_scope_ref ( label, |world, sched| sched. run ( world) ) ;
17961909 }
17971910}
17981911
0 commit comments