Replace IntoSystemSetConfig with IntoSystemSetConfigs (#9247)
				
					
				
			# Objective - Fixes #9244. ## Solution - Changed the `(Into)SystemSetConfigs` traits and structs be more like the `(Into)SystemConfigs` traits and structs. - Replaced uses of `IntoSystemSetConfig` with `IntoSystemSetConfigs` - Added generic `ItemConfig` and `ItemConfigs` types. - Changed `SystemConfig(s)` and `SystemSetConfig(s)` to be type aliases to `ItemConfig(s)`. - Added generic `process_configs` to `ScheduleGraph`. - Changed `configure_sets_inner` and `add_systems_inner` to reuse `process_configs`. --- ## Changelog - Added `run_if` to `IntoSystemSetConfigs` - Deprecated `Schedule::configure_set` and `App::configure_set` - Removed `IntoSystemSetConfig` ## Migration Guide - Use `App::configure_sets` instead of `App::configure_set` - Use `Schedule::configure_sets` instead of `Schedule::configure_set` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
		
							parent
							
								
									04885eb49c
								
							
						
					
					
						commit
						118509e4aa
					
				@ -393,21 +393,14 @@ impl App {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Configures a system set in the default schedule, adding the set if it does not exist.
 | 
			
		||||
    #[deprecated(since = "0.12.0", note = "Please use `configure_sets` instead.")]
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    pub fn configure_set(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        schedule: impl ScheduleLabel,
 | 
			
		||||
        set: impl IntoSystemSetConfig,
 | 
			
		||||
        set: impl IntoSystemSetConfigs,
 | 
			
		||||
    ) -> &mut Self {
 | 
			
		||||
        let mut schedules = self.world.resource_mut::<Schedules>();
 | 
			
		||||
        if let Some(schedule) = schedules.get_mut(&schedule) {
 | 
			
		||||
            schedule.configure_set(set);
 | 
			
		||||
        } else {
 | 
			
		||||
            let mut new_schedule = Schedule::new(schedule);
 | 
			
		||||
            new_schedule.configure_set(set);
 | 
			
		||||
            schedules.insert(new_schedule);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
        self.configure_sets(schedule, set)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Configures a collection of system sets in the default schedule, adding any sets that do not exist.
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ pub struct AudioPlugin {
 | 
			
		||||
impl Plugin for AudioPlugin {
 | 
			
		||||
    fn build(&self, app: &mut App) {
 | 
			
		||||
        app.insert_resource(self.global_volume)
 | 
			
		||||
            .configure_set(PostUpdate, AudioPlaySet.run_if(audio_output_available))
 | 
			
		||||
            .configure_sets(PostUpdate, AudioPlaySet.run_if(audio_output_available))
 | 
			
		||||
            .init_resource::<AudioOutput>();
 | 
			
		||||
 | 
			
		||||
        #[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))]
 | 
			
		||||
 | 
			
		||||
@ -45,8 +45,8 @@ pub mod prelude {
 | 
			
		||||
        removal_detection::RemovedComponents,
 | 
			
		||||
        schedule::{
 | 
			
		||||
            apply_deferred, apply_state_transition, common_conditions::*, Condition,
 | 
			
		||||
            IntoSystemConfigs, IntoSystemSet, IntoSystemSetConfig, IntoSystemSetConfigs, NextState,
 | 
			
		||||
            OnEnter, OnExit, OnTransition, Schedule, Schedules, State, States, SystemSet,
 | 
			
		||||
            IntoSystemConfigs, IntoSystemSet, IntoSystemSetConfigs, NextState, OnEnter, OnExit,
 | 
			
		||||
            OnTransition, Schedule, Schedules, State, States, SystemSet,
 | 
			
		||||
        },
 | 
			
		||||
        system::{
 | 
			
		||||
            Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
 | 
			
		||||
 | 
			
		||||
@ -47,21 +47,24 @@ impl IntoSystemConfigs<()> for BoxedSystem<(), ()> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Stores configuration for a single system.
 | 
			
		||||
pub struct SystemConfig {
 | 
			
		||||
    pub(crate) system: BoxedSystem,
 | 
			
		||||
/// Stores configuration for a single generic node.
 | 
			
		||||
pub struct NodeConfig<T> {
 | 
			
		||||
    pub(crate) node: T,
 | 
			
		||||
    pub(crate) graph_info: GraphInfo,
 | 
			
		||||
    pub(crate) conditions: Vec<BoxedCondition>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A collection of [`SystemConfig`].
 | 
			
		||||
pub enum SystemConfigs {
 | 
			
		||||
    /// Configuration for a single system.
 | 
			
		||||
    SystemConfig(SystemConfig),
 | 
			
		||||
    /// Configuration for a tuple of nested `SystemConfigs` instances.
 | 
			
		||||
/// Stores configuration for a single system.
 | 
			
		||||
pub type SystemConfig = NodeConfig<BoxedSystem>;
 | 
			
		||||
 | 
			
		||||
/// A collections of generic [`NodeConfig`]s.
 | 
			
		||||
pub enum NodeConfigs<T> {
 | 
			
		||||
    /// Configuratin for a single node.
 | 
			
		||||
    NodeConfig(NodeConfig<T>),
 | 
			
		||||
    /// Configuration for a tuple of nested `Configs` instances.
 | 
			
		||||
    Configs {
 | 
			
		||||
        /// Configuration for each element of the tuple.
 | 
			
		||||
        configs: Vec<SystemConfigs>,
 | 
			
		||||
        configs: Vec<NodeConfigs<T>>,
 | 
			
		||||
        /// Run conditions applied to everything in the tuple.
 | 
			
		||||
        collective_conditions: Vec<BoxedCondition>,
 | 
			
		||||
        /// If `true`, adds `before -> after` ordering constraints between the successive elements.
 | 
			
		||||
@ -69,12 +72,15 @@ pub enum SystemConfigs {
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A collection of [`SystemConfig`].
 | 
			
		||||
pub type SystemConfigs = NodeConfigs<BoxedSystem>;
 | 
			
		||||
 | 
			
		||||
impl SystemConfigs {
 | 
			
		||||
    fn new_system(system: BoxedSystem) -> Self {
 | 
			
		||||
        // include system in its default sets
 | 
			
		||||
        let sets = system.default_system_sets().into_iter().collect();
 | 
			
		||||
        Self::SystemConfig(SystemConfig {
 | 
			
		||||
            system,
 | 
			
		||||
        Self::NodeConfig(SystemConfig {
 | 
			
		||||
            node: system,
 | 
			
		||||
            graph_info: GraphInfo {
 | 
			
		||||
                sets,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
@ -82,14 +88,16 @@ impl SystemConfigs {
 | 
			
		||||
            conditions: Vec::new(),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> NodeConfigs<T> {
 | 
			
		||||
    /// Adds a new boxed system set to the systems.
 | 
			
		||||
    pub fn in_set_dyn(&mut self, set: BoxedSystemSet) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config.graph_info.sets.push(set);
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.in_set_dyn(set.dyn_clone());
 | 
			
		||||
                }
 | 
			
		||||
@ -99,13 +107,13 @@ impl SystemConfigs {
 | 
			
		||||
 | 
			
		||||
    fn before_inner(&mut self, set: BoxedSystemSet) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config
 | 
			
		||||
                    .graph_info
 | 
			
		||||
                    .dependencies
 | 
			
		||||
                    .push(Dependency::new(DependencyKind::Before, set));
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.before_inner(set.dyn_clone());
 | 
			
		||||
                }
 | 
			
		||||
@ -115,13 +123,13 @@ impl SystemConfigs {
 | 
			
		||||
 | 
			
		||||
    fn after_inner(&mut self, set: BoxedSystemSet) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config
 | 
			
		||||
                    .graph_info
 | 
			
		||||
                    .dependencies
 | 
			
		||||
                    .push(Dependency::new(DependencyKind::After, set));
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.after_inner(set.dyn_clone());
 | 
			
		||||
                }
 | 
			
		||||
@ -131,10 +139,10 @@ impl SystemConfigs {
 | 
			
		||||
 | 
			
		||||
    fn distributive_run_if_inner<M>(&mut self, condition: impl Condition<M> + Clone) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config.conditions.push(new_condition(condition));
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.distributive_run_if_inner(condition.clone());
 | 
			
		||||
                }
 | 
			
		||||
@ -144,10 +152,10 @@ impl SystemConfigs {
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with_inner(&mut self, set: BoxedSystemSet) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                ambiguous_with(&mut config.graph_info, set);
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.ambiguous_with_inner(set.dyn_clone());
 | 
			
		||||
                }
 | 
			
		||||
@ -157,10 +165,10 @@ impl SystemConfigs {
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with_all_inner(&mut self) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs { configs, .. } => {
 | 
			
		||||
            Self::Configs { configs, .. } => {
 | 
			
		||||
                for config in configs {
 | 
			
		||||
                    config.ambiguous_with_all_inner();
 | 
			
		||||
                }
 | 
			
		||||
@ -174,10 +182,10 @@ impl SystemConfigs {
 | 
			
		||||
    /// Prefer `run_if` for run conditions whose type is known at compile time.
 | 
			
		||||
    pub fn run_if_dyn(&mut self, condition: BoxedCondition) {
 | 
			
		||||
        match self {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
            Self::NodeConfig(config) => {
 | 
			
		||||
                config.conditions.push(condition);
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs {
 | 
			
		||||
            Self::Configs {
 | 
			
		||||
                collective_conditions,
 | 
			
		||||
                ..
 | 
			
		||||
            } => {
 | 
			
		||||
@ -185,6 +193,16 @@ impl SystemConfigs {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn chain_inner(mut self) -> Self {
 | 
			
		||||
        match &mut self {
 | 
			
		||||
            Self::NodeConfig(_) => { /* no op */ }
 | 
			
		||||
            Self::Configs { chained, .. } => {
 | 
			
		||||
                *chained = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Types that can convert into a [`SystemConfigs`].
 | 
			
		||||
@ -239,7 +257,7 @@ where
 | 
			
		||||
    /// that all evaluations in a single schedule run will yield the same result. If another
 | 
			
		||||
    /// system is run inbetween two evaluations it could cause the result of the condition to change.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Use [`run_if`](IntoSystemSetConfig::run_if) on a [`SystemSet`] if you want to make sure
 | 
			
		||||
    /// Use [`run_if`](IntoSystemSetConfigs::run_if) on a [`SystemSet`] if you want to make sure
 | 
			
		||||
    /// that either all or none of the systems are run, or you don't want to evaluate the run
 | 
			
		||||
    /// condition for each contained system separately.
 | 
			
		||||
    fn distributive_run_if<M>(self, condition: impl Condition<M> + Clone) -> SystemConfigs {
 | 
			
		||||
@ -265,7 +283,7 @@ where
 | 
			
		||||
    /// # #[derive(SystemSet, Debug, Eq, PartialEq, Hash, Clone, Copy)]
 | 
			
		||||
    /// # struct C;
 | 
			
		||||
    /// schedule.add_systems((a, b).run_if(condition));
 | 
			
		||||
    /// schedule.add_systems((a, b).in_set(C)).configure_set(C.run_if(condition));
 | 
			
		||||
    /// schedule.add_systems((a, b).in_set(C)).configure_sets(C.run_if(condition));
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Note
 | 
			
		||||
@ -350,14 +368,8 @@ impl IntoSystemConfigs<()> for SystemConfigs {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn chain(mut self) -> Self {
 | 
			
		||||
        match &mut self {
 | 
			
		||||
            SystemConfigs::SystemConfig(_) => { /* no op */ }
 | 
			
		||||
            SystemConfigs::Configs { chained, .. } => {
 | 
			
		||||
                *chained = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    fn chain(self) -> Self {
 | 
			
		||||
        self.chain_inner()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -386,15 +398,11 @@ macro_rules! impl_system_collection {
 | 
			
		||||
all_tuples!(impl_system_collection, 1, 20, P, S);
 | 
			
		||||
 | 
			
		||||
/// A [`SystemSet`] with scheduling metadata.
 | 
			
		||||
pub struct SystemSetConfig {
 | 
			
		||||
    pub(super) set: BoxedSystemSet,
 | 
			
		||||
    pub(super) graph_info: GraphInfo,
 | 
			
		||||
    pub(super) conditions: Vec<BoxedCondition>,
 | 
			
		||||
}
 | 
			
		||||
pub type SystemSetConfig = NodeConfig<BoxedSystemSet>;
 | 
			
		||||
 | 
			
		||||
impl SystemSetConfig {
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn new(set: BoxedSystemSet) -> Self {
 | 
			
		||||
    pub(super) fn new(set: BoxedSystemSet) -> Self {
 | 
			
		||||
        // system type sets are automatically populated
 | 
			
		||||
        // to avoid unintentionally broad changes, they cannot be configured
 | 
			
		||||
        assert!(
 | 
			
		||||
@ -403,118 +411,15 @@ impl SystemSetConfig {
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            set,
 | 
			
		||||
            node: set,
 | 
			
		||||
            graph_info: GraphInfo::default(),
 | 
			
		||||
            conditions: Vec::new(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Types that can be converted into a [`SystemSetConfig`].
 | 
			
		||||
///
 | 
			
		||||
/// This has been implemented for all types that implement [`SystemSet`] and boxed trait objects.
 | 
			
		||||
pub trait IntoSystemSetConfig: Sized {
 | 
			
		||||
    /// Convert into a [`SystemSetConfig`].
 | 
			
		||||
    #[doc(hidden)]
 | 
			
		||||
    fn into_config(self) -> SystemSetConfig;
 | 
			
		||||
    /// Add to the provided `set`.
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn in_set(self, set: impl SystemSet) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().in_set(set)
 | 
			
		||||
    }
 | 
			
		||||
    /// Run before all systems in `set`.
 | 
			
		||||
    fn before<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().before(set)
 | 
			
		||||
    }
 | 
			
		||||
    /// Run after all systems in `set`.
 | 
			
		||||
    fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().after(set)
 | 
			
		||||
    }
 | 
			
		||||
    /// Run the systems in this set only if the [`Condition`] is `true`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The `Condition` will be evaluated at most once (per schedule run),
 | 
			
		||||
    /// the first time a system in this set prepares to run.
 | 
			
		||||
    fn run_if<M>(self, condition: impl Condition<M>) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().run_if(condition)
 | 
			
		||||
    }
 | 
			
		||||
    /// Suppress warnings and errors that would result from systems in this set having ambiguities
 | 
			
		||||
    /// (conflicting access but indeterminate order) with systems in `set`.
 | 
			
		||||
    fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().ambiguous_with(set)
 | 
			
		||||
    }
 | 
			
		||||
    /// Suppress warnings and errors that would result from systems in this set having ambiguities
 | 
			
		||||
    /// (conflicting access but indeterminate order) with any other system.
 | 
			
		||||
    fn ambiguous_with_all(self) -> SystemSetConfig {
 | 
			
		||||
        self.into_config().ambiguous_with_all()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<S: SystemSet> IntoSystemSetConfig for S {
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn into_config(self) -> SystemSetConfig {
 | 
			
		||||
        SystemSetConfig::new(Box::new(self))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IntoSystemSetConfig for BoxedSystemSet {
 | 
			
		||||
    fn into_config(self) -> SystemSetConfig {
 | 
			
		||||
        SystemSetConfig::new(self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IntoSystemSetConfig for SystemSetConfig {
 | 
			
		||||
    fn into_config(self) -> Self {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn in_set(mut self, set: impl SystemSet) -> Self {
 | 
			
		||||
        assert!(
 | 
			
		||||
            set.system_type().is_none(),
 | 
			
		||||
            "adding arbitrary systems to a system type set is not allowed"
 | 
			
		||||
        );
 | 
			
		||||
        self.graph_info.sets.push(Box::new(set));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn before<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        self.graph_info.dependencies.push(Dependency::new(
 | 
			
		||||
            DependencyKind::Before,
 | 
			
		||||
            Box::new(set.into_system_set()),
 | 
			
		||||
        ));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn after<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        self.graph_info.dependencies.push(Dependency::new(
 | 
			
		||||
            DependencyKind::After,
 | 
			
		||||
            Box::new(set.into_system_set()),
 | 
			
		||||
        ));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn run_if<M>(mut self, condition: impl Condition<M>) -> Self {
 | 
			
		||||
        self.conditions.push(new_condition(condition));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        ambiguous_with(&mut self.graph_info, Box::new(set.into_system_set()));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with_all(mut self) -> Self {
 | 
			
		||||
        self.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A collection of [`SystemSetConfig`].
 | 
			
		||||
pub struct SystemSetConfigs {
 | 
			
		||||
    pub(super) sets: Vec<SystemSetConfig>,
 | 
			
		||||
    /// If `true`, adds `before -> after` ordering constraints between the successive elements.
 | 
			
		||||
    pub(super) chained: bool,
 | 
			
		||||
}
 | 
			
		||||
pub type SystemSetConfigs = NodeConfigs<BoxedSystemSet>;
 | 
			
		||||
 | 
			
		||||
/// Types that can convert into a [`SystemSetConfigs`].
 | 
			
		||||
pub trait IntoSystemSetConfigs
 | 
			
		||||
@ -541,6 +446,14 @@ where
 | 
			
		||||
        self.into_configs().after(set)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Run the systems in this set(s) only if the [`Condition`] is `true`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The `Condition` will be evaluated at most once (per schedule run),
 | 
			
		||||
    /// the first time a system in this set(s) prepares to run.
 | 
			
		||||
    fn run_if<M>(self, condition: impl Condition<M>) -> SystemSetConfigs {
 | 
			
		||||
        self.into_configs().run_if(condition)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Suppress warnings and errors that would result from systems in these sets having ambiguities
 | 
			
		||||
    /// (conflicting access but indeterminate order) with systems in `set`.
 | 
			
		||||
    fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
 | 
			
		||||
@ -572,69 +485,77 @@ impl IntoSystemSetConfigs for SystemSetConfigs {
 | 
			
		||||
            set.system_type().is_none(),
 | 
			
		||||
            "adding arbitrary systems to a system type set is not allowed"
 | 
			
		||||
        );
 | 
			
		||||
        for config in &mut self.sets {
 | 
			
		||||
            config.graph_info.sets.push(set.dyn_clone());
 | 
			
		||||
        }
 | 
			
		||||
        self.in_set_dyn(set.dyn_clone());
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn before<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        let set = set.into_system_set();
 | 
			
		||||
        for config in &mut self.sets {
 | 
			
		||||
            config
 | 
			
		||||
                .graph_info
 | 
			
		||||
                .dependencies
 | 
			
		||||
                .push(Dependency::new(DependencyKind::Before, set.dyn_clone()));
 | 
			
		||||
        }
 | 
			
		||||
        self.before_inner(set.dyn_clone());
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn after<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        let set = set.into_system_set();
 | 
			
		||||
        for config in &mut self.sets {
 | 
			
		||||
            config
 | 
			
		||||
                .graph_info
 | 
			
		||||
                .dependencies
 | 
			
		||||
                .push(Dependency::new(DependencyKind::After, set.dyn_clone()));
 | 
			
		||||
        }
 | 
			
		||||
        self.after_inner(set.dyn_clone());
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn run_if<M>(mut self, condition: impl Condition<M>) -> SystemSetConfigs {
 | 
			
		||||
        self.run_if_dyn(new_condition(condition));
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
 | 
			
		||||
        let set = set.into_system_set();
 | 
			
		||||
        for config in &mut self.sets {
 | 
			
		||||
            ambiguous_with(&mut config.graph_info, set.dyn_clone());
 | 
			
		||||
        }
 | 
			
		||||
        self.ambiguous_with_inner(set.dyn_clone());
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ambiguous_with_all(mut self) -> Self {
 | 
			
		||||
        for config in &mut self.sets {
 | 
			
		||||
            config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
 | 
			
		||||
        }
 | 
			
		||||
        self.ambiguous_with_all_inner();
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn chain(mut self) -> Self {
 | 
			
		||||
        self.chained = true;
 | 
			
		||||
        self
 | 
			
		||||
    fn chain(self) -> Self {
 | 
			
		||||
        self.chain_inner()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<S: SystemSet> IntoSystemSetConfigs for S {
 | 
			
		||||
    fn into_configs(self) -> SystemSetConfigs {
 | 
			
		||||
        SystemSetConfigs::NodeConfig(SystemSetConfig::new(Box::new(self)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IntoSystemSetConfigs for BoxedSystemSet {
 | 
			
		||||
    fn into_configs(self) -> SystemSetConfigs {
 | 
			
		||||
        SystemSetConfigs::NodeConfig(SystemSetConfig::new(self))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IntoSystemSetConfigs for SystemSetConfig {
 | 
			
		||||
    fn into_configs(self) -> SystemSetConfigs {
 | 
			
		||||
        SystemSetConfigs::NodeConfig(self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_system_set_collection {
 | 
			
		||||
    ($($set: ident),*) => {
 | 
			
		||||
        impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*)
 | 
			
		||||
        impl<$($set: IntoSystemSetConfigs),*> IntoSystemSetConfigs for ($($set,)*)
 | 
			
		||||
        {
 | 
			
		||||
            #[allow(non_snake_case)]
 | 
			
		||||
            fn into_configs(self) -> SystemSetConfigs {
 | 
			
		||||
                let ($($set,)*) = self;
 | 
			
		||||
                SystemSetConfigs {
 | 
			
		||||
                    sets: vec![$($set.into_config(),)*],
 | 
			
		||||
                SystemSetConfigs::Configs {
 | 
			
		||||
                    configs: vec![$($set.into_configs(),)*],
 | 
			
		||||
                    collective_conditions: Vec::new(),
 | 
			
		||||
                    chained: false,
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -642,4 +563,4 @@ macro_rules! impl_system_set_collection {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
all_tuples!(impl_system_set_collection, 0, 15, S);
 | 
			
		||||
all_tuples!(impl_system_set_collection, 1, 20, S);
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ mod tests {
 | 
			
		||||
    use std::sync::atomic::{AtomicU32, Ordering};
 | 
			
		||||
 | 
			
		||||
    pub use crate as bevy_ecs;
 | 
			
		||||
    pub use crate::schedule::{IntoSystemSetConfig, Schedule, SystemSet};
 | 
			
		||||
    pub use crate::schedule::{IntoSystemSetConfigs, Schedule, SystemSet};
 | 
			
		||||
    pub use crate::system::{Res, ResMut};
 | 
			
		||||
    pub use crate::{prelude::World, system::Resource};
 | 
			
		||||
 | 
			
		||||
@ -145,7 +145,7 @@ mod tests {
 | 
			
		||||
            assert_eq!(world.resource::<SystemOrder>().0, vec![]);
 | 
			
		||||
 | 
			
		||||
            // modify the schedule after it's been initialized and test ordering with sets
 | 
			
		||||
            schedule.configure_set(TestSet::A.after(named_system));
 | 
			
		||||
            schedule.configure_sets(TestSet::A.after(named_system));
 | 
			
		||||
            schedule.add_systems((
 | 
			
		||||
                make_function_system(3)
 | 
			
		||||
                    .before(TestSet::A)
 | 
			
		||||
@ -339,13 +339,13 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
            world.init_resource::<Counter>();
 | 
			
		||||
 | 
			
		||||
            schedule.configure_set(TestSet::A.run_if(|| false).run_if(|| false));
 | 
			
		||||
            schedule.configure_sets(TestSet::A.run_if(|| false).run_if(|| false));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::A));
 | 
			
		||||
            schedule.configure_set(TestSet::B.run_if(|| true).run_if(|| false));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.run_if(|| true).run_if(|| false));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::B));
 | 
			
		||||
            schedule.configure_set(TestSet::C.run_if(|| false).run_if(|| true));
 | 
			
		||||
            schedule.configure_sets(TestSet::C.run_if(|| false).run_if(|| true));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::C));
 | 
			
		||||
            schedule.configure_set(TestSet::D.run_if(|| true).run_if(|| true));
 | 
			
		||||
            schedule.configure_sets(TestSet::D.run_if(|| true).run_if(|| true));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::D));
 | 
			
		||||
 | 
			
		||||
            schedule.run(&mut world);
 | 
			
		||||
@ -359,13 +359,13 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
            world.init_resource::<Counter>();
 | 
			
		||||
 | 
			
		||||
            schedule.configure_set(TestSet::A.run_if(|| false));
 | 
			
		||||
            schedule.configure_sets(TestSet::A.run_if(|| false));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::A).run_if(|| false));
 | 
			
		||||
            schedule.configure_set(TestSet::B.run_if(|| true));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.run_if(|| true));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::B).run_if(|| false));
 | 
			
		||||
            schedule.configure_set(TestSet::C.run_if(|| false));
 | 
			
		||||
            schedule.configure_sets(TestSet::C.run_if(|| false));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::C).run_if(|| true));
 | 
			
		||||
            schedule.configure_set(TestSet::D.run_if(|| true));
 | 
			
		||||
            schedule.configure_sets(TestSet::D.run_if(|| true));
 | 
			
		||||
            schedule.add_systems(counting_system.in_set(TestSet::D).run_if(|| true));
 | 
			
		||||
 | 
			
		||||
            schedule.run(&mut world);
 | 
			
		||||
@ -431,7 +431,7 @@ mod tests {
 | 
			
		||||
            world.init_resource::<Bool2>();
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
            schedule.configure_set(
 | 
			
		||||
            schedule.configure_sets(
 | 
			
		||||
                TestSet::A
 | 
			
		||||
                    .run_if(|res1: Res<RunConditionBool>| res1.is_changed())
 | 
			
		||||
                    .run_if(|res2: Res<Bool2>| res2.is_changed()),
 | 
			
		||||
@ -482,7 +482,7 @@ mod tests {
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
            schedule
 | 
			
		||||
                .configure_set(TestSet::A.run_if(|res1: Res<RunConditionBool>| res1.is_changed()));
 | 
			
		||||
                .configure_sets(TestSet::A.run_if(|res1: Res<RunConditionBool>| res1.is_changed()));
 | 
			
		||||
 | 
			
		||||
            schedule.add_systems(
 | 
			
		||||
                counting_system
 | 
			
		||||
@ -529,7 +529,7 @@ mod tests {
 | 
			
		||||
        #[should_panic]
 | 
			
		||||
        fn dependency_loop() {
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
            schedule.configure_set(TestSet::X.after(TestSet::X));
 | 
			
		||||
            schedule.configure_sets(TestSet::X.after(TestSet::X));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[test]
 | 
			
		||||
@ -537,8 +537,8 @@ mod tests {
 | 
			
		||||
            let mut world = World::new();
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
            schedule.configure_set(TestSet::A.after(TestSet::B));
 | 
			
		||||
            schedule.configure_set(TestSet::B.after(TestSet::A));
 | 
			
		||||
            schedule.configure_sets(TestSet::A.after(TestSet::B));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.after(TestSet::A));
 | 
			
		||||
 | 
			
		||||
            let result = schedule.initialize(&mut world);
 | 
			
		||||
            assert!(matches!(
 | 
			
		||||
@ -564,7 +564,7 @@ mod tests {
 | 
			
		||||
        #[should_panic]
 | 
			
		||||
        fn hierarchy_loop() {
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
            schedule.configure_set(TestSet::X.in_set(TestSet::X));
 | 
			
		||||
            schedule.configure_sets(TestSet::X.in_set(TestSet::X));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[test]
 | 
			
		||||
@ -572,8 +572,8 @@ mod tests {
 | 
			
		||||
            let mut world = World::new();
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
            schedule.configure_set(TestSet::A.in_set(TestSet::B));
 | 
			
		||||
            schedule.configure_set(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
            schedule.configure_sets(TestSet::A.in_set(TestSet::B));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
 | 
			
		||||
            let result = schedule.initialize(&mut world);
 | 
			
		||||
            assert!(matches!(result, Err(ScheduleBuildError::HierarchyCycle(_))));
 | 
			
		||||
@ -625,7 +625,7 @@ mod tests {
 | 
			
		||||
        fn configure_system_type_set() {
 | 
			
		||||
            fn foo() {}
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
            schedule.configure_set(foo.into_system_set());
 | 
			
		||||
            schedule.configure_sets(foo.into_system_set());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[test]
 | 
			
		||||
@ -639,13 +639,13 @@ mod tests {
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Add `A`.
 | 
			
		||||
            schedule.configure_set(TestSet::A);
 | 
			
		||||
            schedule.configure_sets(TestSet::A);
 | 
			
		||||
 | 
			
		||||
            // Add `B` as child of `A`.
 | 
			
		||||
            schedule.configure_set(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
 | 
			
		||||
            // Add `X` as child of both `A` and `B`.
 | 
			
		||||
            schedule.configure_set(TestSet::X.in_set(TestSet::A).in_set(TestSet::B));
 | 
			
		||||
            schedule.configure_sets(TestSet::X.in_set(TestSet::A).in_set(TestSet::B));
 | 
			
		||||
 | 
			
		||||
            // `X` cannot be the `A`'s child and grandchild at the same time.
 | 
			
		||||
            let result = schedule.initialize(&mut world);
 | 
			
		||||
@ -661,8 +661,8 @@ mod tests {
 | 
			
		||||
            let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
            // Add `B` and give it both kinds of relationships with `A`.
 | 
			
		||||
            schedule.configure_set(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
            schedule.configure_set(TestSet::B.after(TestSet::A));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.in_set(TestSet::A));
 | 
			
		||||
            schedule.configure_sets(TestSet::B.after(TestSet::A));
 | 
			
		||||
            let result = schedule.initialize(&mut world);
 | 
			
		||||
            assert!(matches!(
 | 
			
		||||
                result,
 | 
			
		||||
 | 
			
		||||
@ -192,15 +192,15 @@ impl Schedule {
 | 
			
		||||
 | 
			
		||||
    /// Add a collection of systems to the schedule.
 | 
			
		||||
    pub fn add_systems<M>(&mut self, systems: impl IntoSystemConfigs<M>) -> &mut Self {
 | 
			
		||||
        self.graph.add_systems_inner(systems.into_configs(), false);
 | 
			
		||||
        self.graph.process_configs(systems.into_configs(), false);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Configures a system set in this schedule, adding it if it does not exist.
 | 
			
		||||
    #[deprecated(since = "0.12.0", note = "Please use `configure_sets` instead.")]
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self {
 | 
			
		||||
        self.graph.configure_set(set);
 | 
			
		||||
        self
 | 
			
		||||
    pub fn configure_set(&mut self, set: impl IntoSystemSetConfigs) -> &mut Self {
 | 
			
		||||
        self.configure_sets(set)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Configures a collection of system sets in this schedule, adding them if they does not exist.
 | 
			
		||||
@ -522,30 +522,36 @@ impl ScheduleGraph {
 | 
			
		||||
        &self.conflicting_systems
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Adds the systems to the graph. Returns a vector of all node ids contained the nested `SystemConfigs`
 | 
			
		||||
    /// if `ancestor_chained` is true. Also returns true if "densely chained", meaning that all nested items
 | 
			
		||||
    /// are linearly chained in the order they are defined
 | 
			
		||||
    fn add_systems_inner(
 | 
			
		||||
    /// Adds the config nodes to the graph.
 | 
			
		||||
    ///
 | 
			
		||||
    /// `collect_nodes` controls whether the `NodeId`s of the processed config nodes are stored in the returned [`ProcessConfigsResult`].
 | 
			
		||||
    /// `process_config` is the function which processes each individual config node and returns a corresponding `NodeId`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The fields on the returned [`ProcessConfigsResult`] are:
 | 
			
		||||
    /// - `nodes`: a vector of all node ids contained in the nested `NodeConfigs`
 | 
			
		||||
    /// - `densely_chained`: a boolean that is true if all nested nodes are linearly chained (with successive `after` orderings) in the order they are defined
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn process_configs<T: ProcessNodeConfig>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        configs: SystemConfigs,
 | 
			
		||||
        ancestor_chained: bool,
 | 
			
		||||
    ) -> AddSystemsInnerResult {
 | 
			
		||||
        configs: NodeConfigs<T>,
 | 
			
		||||
        collect_nodes: bool,
 | 
			
		||||
    ) -> ProcessConfigsResult {
 | 
			
		||||
        match configs {
 | 
			
		||||
            SystemConfigs::SystemConfig(config) => {
 | 
			
		||||
                let node_id = self.add_system_inner(config).unwrap();
 | 
			
		||||
                if ancestor_chained {
 | 
			
		||||
                    AddSystemsInnerResult {
 | 
			
		||||
            NodeConfigs::NodeConfig(config) => {
 | 
			
		||||
                let node_id = T::process_config(self, config);
 | 
			
		||||
                if collect_nodes {
 | 
			
		||||
                    ProcessConfigsResult {
 | 
			
		||||
                        densely_chained: true,
 | 
			
		||||
                        nodes: vec![node_id],
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    AddSystemsInnerResult {
 | 
			
		||||
                    ProcessConfigsResult {
 | 
			
		||||
                        densely_chained: true,
 | 
			
		||||
                        nodes: Vec::new(),
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            SystemConfigs::Configs {
 | 
			
		||||
            NodeConfigs::Configs {
 | 
			
		||||
                mut configs,
 | 
			
		||||
                collective_conditions,
 | 
			
		||||
                chained,
 | 
			
		||||
@ -557,9 +563,9 @@ impl ScheduleGraph {
 | 
			
		||||
                        for config in &mut configs {
 | 
			
		||||
                            config.in_set_dyn(set.dyn_clone());
 | 
			
		||||
                        }
 | 
			
		||||
                        let mut set_config = set.into_config();
 | 
			
		||||
                        let mut set_config = SystemSetConfig::new(set.dyn_clone());
 | 
			
		||||
                        set_config.conditions.extend(collective_conditions);
 | 
			
		||||
                        self.configure_set(set_config);
 | 
			
		||||
                        self.configure_set_inner(set_config).unwrap();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        for condition in collective_conditions {
 | 
			
		||||
                            configs[0].run_if_dyn(condition);
 | 
			
		||||
@ -571,15 +577,15 @@ impl ScheduleGraph {
 | 
			
		||||
                let mut densely_chained = true;
 | 
			
		||||
                if chained {
 | 
			
		||||
                    let Some(prev) = config_iter.next() else {
 | 
			
		||||
                        return AddSystemsInnerResult {
 | 
			
		||||
                        return ProcessConfigsResult {
 | 
			
		||||
                            nodes: Vec::new(),
 | 
			
		||||
                            densely_chained: true,
 | 
			
		||||
                        };
 | 
			
		||||
                    };
 | 
			
		||||
                    let mut previous_result = self.add_systems_inner(prev, true);
 | 
			
		||||
                    let mut previous_result = self.process_configs(prev, true);
 | 
			
		||||
                    densely_chained = previous_result.densely_chained;
 | 
			
		||||
                    for current in config_iter {
 | 
			
		||||
                        let current_result = self.add_systems_inner(current, true);
 | 
			
		||||
                        let current_result = self.process_configs(current, true);
 | 
			
		||||
                        densely_chained = densely_chained && current_result.densely_chained;
 | 
			
		||||
                        match (
 | 
			
		||||
                            previous_result.densely_chained,
 | 
			
		||||
@ -635,7 +641,7 @@ impl ScheduleGraph {
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if ancestor_chained {
 | 
			
		||||
                        if collect_nodes {
 | 
			
		||||
                            nodes_in_scope.append(&mut previous_result.nodes);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -643,14 +649,14 @@ impl ScheduleGraph {
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // ensure the last config's nodes are added
 | 
			
		||||
                    if ancestor_chained {
 | 
			
		||||
                    if collect_nodes {
 | 
			
		||||
                        nodes_in_scope.append(&mut previous_result.nodes);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    for config in config_iter {
 | 
			
		||||
                        let result = self.add_systems_inner(config, ancestor_chained);
 | 
			
		||||
                        let result = self.process_configs(config, collect_nodes);
 | 
			
		||||
                        densely_chained = densely_chained && result.densely_chained;
 | 
			
		||||
                        if ancestor_chained {
 | 
			
		||||
                        if collect_nodes {
 | 
			
		||||
                            nodes_in_scope.extend(result.nodes);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -661,7 +667,7 @@ impl ScheduleGraph {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                AddSystemsInnerResult {
 | 
			
		||||
                ProcessConfigsResult {
 | 
			
		||||
                    nodes: nodes_in_scope,
 | 
			
		||||
                    densely_chained,
 | 
			
		||||
                }
 | 
			
		||||
@ -677,7 +683,7 @@ impl ScheduleGraph {
 | 
			
		||||
 | 
			
		||||
        // system init has to be deferred (need `&mut World`)
 | 
			
		||||
        self.uninit.push((id, 0));
 | 
			
		||||
        self.systems.push(SystemNode::new(config.system));
 | 
			
		||||
        self.systems.push(SystemNode::new(config.node));
 | 
			
		||||
        self.system_conditions.push(config.conditions);
 | 
			
		||||
 | 
			
		||||
        Ok(id)
 | 
			
		||||
@ -685,46 +691,15 @@ impl ScheduleGraph {
 | 
			
		||||
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) {
 | 
			
		||||
        let SystemSetConfigs { sets, chained } = sets.into_configs();
 | 
			
		||||
        let mut set_iter = sets.into_iter();
 | 
			
		||||
        if chained {
 | 
			
		||||
            let Some(prev) = set_iter.next() else { return };
 | 
			
		||||
            let mut prev_id = self.configure_set_inner(prev).unwrap();
 | 
			
		||||
            for next in set_iter {
 | 
			
		||||
                let next_id = self.configure_set_inner(next).unwrap();
 | 
			
		||||
                self.dependency.graph.add_edge(prev_id, next_id, ());
 | 
			
		||||
                prev_id = next_id;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            for set in set_iter {
 | 
			
		||||
                if let Err(e) = self.configure_set_inner(set) {
 | 
			
		||||
                    // using `unwrap_or_else(panic!)` led to the error being reported
 | 
			
		||||
                    // from this line instead of in the user code
 | 
			
		||||
                    panic!("{e}");
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self.process_configs(sets.into_configs(), false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn configure_set(&mut self, set: impl IntoSystemSetConfig) {
 | 
			
		||||
        if let Err(e) = self.configure_set_inner(set) {
 | 
			
		||||
            // using `unwrap_or_else(panic!)` led to the error being reported
 | 
			
		||||
            // from this line instead of in the user code
 | 
			
		||||
            panic!("{e}");
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    fn configure_set_inner(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        set: impl IntoSystemSetConfig,
 | 
			
		||||
    ) -> Result<NodeId, ScheduleBuildError> {
 | 
			
		||||
    fn configure_set_inner(&mut self, set: SystemSetConfig) -> Result<NodeId, ScheduleBuildError> {
 | 
			
		||||
        let SystemSetConfig {
 | 
			
		||||
            set,
 | 
			
		||||
            node: set,
 | 
			
		||||
            graph_info,
 | 
			
		||||
            mut conditions,
 | 
			
		||||
        } = set.into_config();
 | 
			
		||||
        } = set;
 | 
			
		||||
 | 
			
		||||
        let id = match self.system_set_ids.get(&set) {
 | 
			
		||||
            Some(&id) => id,
 | 
			
		||||
@ -1240,14 +1215,35 @@ impl ScheduleGraph {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Values returned by `ScheduleGraph::add_systems_inner`
 | 
			
		||||
struct AddSystemsInnerResult {
 | 
			
		||||
    /// All nodes contained inside this add_systems_inner call's SystemConfigs hierarchy
 | 
			
		||||
/// Values returned by [`ScheduleGraph::process_configs`]
 | 
			
		||||
struct ProcessConfigsResult {
 | 
			
		||||
    /// All nodes contained inside this process_configs call's [`NodeConfigs`] hierarchy,
 | 
			
		||||
    /// if `ancestor_chained` is true
 | 
			
		||||
    nodes: Vec<NodeId>,
 | 
			
		||||
    /// True if and only if all nodes are "densely chained"
 | 
			
		||||
    /// True if and only if all nodes are "densely chained", meaning that all nested nodes
 | 
			
		||||
    /// are linearly chained (as if `after` system ordering had been applied between each node)
 | 
			
		||||
    /// in the order they are defined
 | 
			
		||||
    densely_chained: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Trait used by [`ScheduleGraph::process_configs`] to process a single [`NodeConfig`].
 | 
			
		||||
trait ProcessNodeConfig: Sized {
 | 
			
		||||
    /// Process a single [`NodeConfig`].
 | 
			
		||||
    fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ProcessNodeConfig for BoxedSystem {
 | 
			
		||||
    fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId {
 | 
			
		||||
        schedule_graph.add_system_inner(config).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ProcessNodeConfig for BoxedSystemSet {
 | 
			
		||||
    fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId {
 | 
			
		||||
        schedule_graph.configure_set_inner(config).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Used to select the appropriate reporting function.
 | 
			
		||||
enum ReportCycles {
 | 
			
		||||
    Hierarchy,
 | 
			
		||||
@ -1718,7 +1714,7 @@ impl ScheduleBuildSettings {
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::{
 | 
			
		||||
        self as bevy_ecs,
 | 
			
		||||
        schedule::{IntoSystemConfigs, IntoSystemSetConfig, Schedule, SystemSet},
 | 
			
		||||
        schedule::{IntoSystemConfigs, IntoSystemSetConfigs, Schedule, SystemSet},
 | 
			
		||||
        world::World,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -1731,7 +1727,7 @@ mod tests {
 | 
			
		||||
        let mut world = World::new();
 | 
			
		||||
        let mut schedule = Schedule::default();
 | 
			
		||||
 | 
			
		||||
        schedule.configure_set(Set.run_if(|| false));
 | 
			
		||||
        schedule.configure_sets(Set.run_if(|| false));
 | 
			
		||||
        schedule.add_systems(
 | 
			
		||||
            (|| panic!("This system must not run"))
 | 
			
		||||
                .ambiguous_with(|| ())
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,8 @@ impl<T> SystemSet for SystemTypeSet<T> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A [`SystemSet`] implicitly created when using
 | 
			
		||||
/// [`Schedule::add_systems`](super::Schedule::add_systems).
 | 
			
		||||
/// [`Schedule::add_systems`](super::Schedule::add_systems) or
 | 
			
		||||
/// [`Schedule::configure_sets`](super::Schedule::configure_sets).
 | 
			
		||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
 | 
			
		||||
pub struct AnonymousSet(usize);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@
 | 
			
		||||
//! You can **explicitly order** systems:
 | 
			
		||||
//!
 | 
			
		||||
//! - by calling the `.before(this_system)` or `.after(that_system)` methods when adding them to your schedule
 | 
			
		||||
//! - by adding them to a [`SystemSet`], and then using `.configure_set(ThisSet.before(ThatSet))` syntax to configure many systems at once
 | 
			
		||||
//! - by adding them to a [`SystemSet`], and then using `.configure_sets(ThisSet.before(ThatSet))` syntax to configure many systems at once
 | 
			
		||||
//! - through the use of `.add_systems((system_a, system_b, system_c).chain())`
 | 
			
		||||
//!
 | 
			
		||||
//! [`SystemSet`]: crate::schedule::SystemSet
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,7 @@ impl Render {
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        schedule.configure_sets((ExtractCommands, PrepareAssets, Prepare).chain());
 | 
			
		||||
        schedule.configure_set(
 | 
			
		||||
        schedule.configure_sets(
 | 
			
		||||
            QueueMeshes
 | 
			
		||||
                .in_set(RenderSet::Queue)
 | 
			
		||||
                .after(prepare_assets::<Mesh>),
 | 
			
		||||
 | 
			
		||||
@ -216,7 +216,7 @@ impl Plugin for VisibilityPlugin {
 | 
			
		||||
        app
 | 
			
		||||
            // We add an AABB component in CalculateBounds, which must be ready on the same frame.
 | 
			
		||||
            .add_systems(PostUpdate, apply_deferred.in_set(CalculateBoundsFlush))
 | 
			
		||||
            .configure_set(PostUpdate, CalculateBoundsFlush.after(CalculateBounds))
 | 
			
		||||
            .configure_sets(PostUpdate, CalculateBoundsFlush.after(CalculateBounds))
 | 
			
		||||
            .add_systems(
 | 
			
		||||
                PostUpdate,
 | 
			
		||||
                (
 | 
			
		||||
 | 
			
		||||
@ -102,7 +102,7 @@ impl Plugin for TransformPlugin {
 | 
			
		||||
        app.register_type::<Transform>()
 | 
			
		||||
            .register_type::<GlobalTransform>()
 | 
			
		||||
            .add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
 | 
			
		||||
            .configure_set(
 | 
			
		||||
            .configure_sets(
 | 
			
		||||
                PostStartup,
 | 
			
		||||
                PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
 | 
			
		||||
            )
 | 
			
		||||
@ -119,7 +119,7 @@ impl Plugin for TransformPlugin {
 | 
			
		||||
                    propagate_transforms.in_set(PropagateTransformsSet),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            .configure_set(
 | 
			
		||||
            .configure_sets(
 | 
			
		||||
                PostUpdate,
 | 
			
		||||
                PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user