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.
|
/// 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]
|
#[track_caller]
|
||||||
pub fn configure_set(
|
pub fn configure_set(
|
||||||
&mut self,
|
&mut self,
|
||||||
schedule: impl ScheduleLabel,
|
schedule: impl ScheduleLabel,
|
||||||
set: impl IntoSystemSetConfig,
|
set: impl IntoSystemSetConfigs,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let mut schedules = self.world.resource_mut::<Schedules>();
|
self.configure_sets(schedule, set)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures a collection of system sets in the default schedule, adding any sets that do not exist.
|
/// 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 {
|
impl Plugin for AudioPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(self.global_volume)
|
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>();
|
.init_resource::<AudioOutput>();
|
||||||
|
|
||||||
#[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))]
|
#[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))]
|
||||||
|
|||||||
@ -45,8 +45,8 @@ pub mod prelude {
|
|||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
schedule::{
|
schedule::{
|
||||||
apply_deferred, apply_state_transition, common_conditions::*, Condition,
|
apply_deferred, apply_state_transition, common_conditions::*, Condition,
|
||||||
IntoSystemConfigs, IntoSystemSet, IntoSystemSetConfig, IntoSystemSetConfigs, NextState,
|
IntoSystemConfigs, IntoSystemSet, IntoSystemSetConfigs, NextState, OnEnter, OnExit,
|
||||||
OnEnter, OnExit, OnTransition, Schedule, Schedules, State, States, SystemSet,
|
OnTransition, Schedule, Schedules, State, States, SystemSet,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
|
Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
|
||||||
|
|||||||
@ -47,21 +47,24 @@ impl IntoSystemConfigs<()> for BoxedSystem<(), ()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores configuration for a single system.
|
/// Stores configuration for a single generic node.
|
||||||
pub struct SystemConfig {
|
pub struct NodeConfig<T> {
|
||||||
pub(crate) system: BoxedSystem,
|
pub(crate) node: T,
|
||||||
pub(crate) graph_info: GraphInfo,
|
pub(crate) graph_info: GraphInfo,
|
||||||
pub(crate) conditions: Vec<BoxedCondition>,
|
pub(crate) conditions: Vec<BoxedCondition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of [`SystemConfig`].
|
/// Stores configuration for a single system.
|
||||||
pub enum SystemConfigs {
|
pub type SystemConfig = NodeConfig<BoxedSystem>;
|
||||||
/// Configuration for a single system.
|
|
||||||
SystemConfig(SystemConfig),
|
/// A collections of generic [`NodeConfig`]s.
|
||||||
/// Configuration for a tuple of nested `SystemConfigs` instances.
|
pub enum NodeConfigs<T> {
|
||||||
|
/// Configuratin for a single node.
|
||||||
|
NodeConfig(NodeConfig<T>),
|
||||||
|
/// Configuration for a tuple of nested `Configs` instances.
|
||||||
Configs {
|
Configs {
|
||||||
/// Configuration for each element of the tuple.
|
/// Configuration for each element of the tuple.
|
||||||
configs: Vec<SystemConfigs>,
|
configs: Vec<NodeConfigs<T>>,
|
||||||
/// Run conditions applied to everything in the tuple.
|
/// Run conditions applied to everything in the tuple.
|
||||||
collective_conditions: Vec<BoxedCondition>,
|
collective_conditions: Vec<BoxedCondition>,
|
||||||
/// If `true`, adds `before -> after` ordering constraints between the successive elements.
|
/// 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 {
|
impl SystemConfigs {
|
||||||
fn new_system(system: BoxedSystem) -> Self {
|
fn new_system(system: BoxedSystem) -> Self {
|
||||||
// include system in its default sets
|
// include system in its default sets
|
||||||
let sets = system.default_system_sets().into_iter().collect();
|
let sets = system.default_system_sets().into_iter().collect();
|
||||||
Self::SystemConfig(SystemConfig {
|
Self::NodeConfig(SystemConfig {
|
||||||
system,
|
node: system,
|
||||||
graph_info: GraphInfo {
|
graph_info: GraphInfo {
|
||||||
sets,
|
sets,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -82,14 +88,16 @@ impl SystemConfigs {
|
|||||||
conditions: Vec::new(),
|
conditions: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> NodeConfigs<T> {
|
||||||
/// Adds a new boxed system set to the systems.
|
/// Adds a new boxed system set to the systems.
|
||||||
pub fn in_set_dyn(&mut self, set: BoxedSystemSet) {
|
pub fn in_set_dyn(&mut self, set: BoxedSystemSet) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config.graph_info.sets.push(set);
|
config.graph_info.sets.push(set);
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.in_set_dyn(set.dyn_clone());
|
config.in_set_dyn(set.dyn_clone());
|
||||||
}
|
}
|
||||||
@ -99,13 +107,13 @@ impl SystemConfigs {
|
|||||||
|
|
||||||
fn before_inner(&mut self, set: BoxedSystemSet) {
|
fn before_inner(&mut self, set: BoxedSystemSet) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config
|
config
|
||||||
.graph_info
|
.graph_info
|
||||||
.dependencies
|
.dependencies
|
||||||
.push(Dependency::new(DependencyKind::Before, set));
|
.push(Dependency::new(DependencyKind::Before, set));
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.before_inner(set.dyn_clone());
|
config.before_inner(set.dyn_clone());
|
||||||
}
|
}
|
||||||
@ -115,13 +123,13 @@ impl SystemConfigs {
|
|||||||
|
|
||||||
fn after_inner(&mut self, set: BoxedSystemSet) {
|
fn after_inner(&mut self, set: BoxedSystemSet) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config
|
config
|
||||||
.graph_info
|
.graph_info
|
||||||
.dependencies
|
.dependencies
|
||||||
.push(Dependency::new(DependencyKind::After, set));
|
.push(Dependency::new(DependencyKind::After, set));
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.after_inner(set.dyn_clone());
|
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) {
|
fn distributive_run_if_inner<M>(&mut self, condition: impl Condition<M> + Clone) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config.conditions.push(new_condition(condition));
|
config.conditions.push(new_condition(condition));
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.distributive_run_if_inner(condition.clone());
|
config.distributive_run_if_inner(condition.clone());
|
||||||
}
|
}
|
||||||
@ -144,10 +152,10 @@ impl SystemConfigs {
|
|||||||
|
|
||||||
fn ambiguous_with_inner(&mut self, set: BoxedSystemSet) {
|
fn ambiguous_with_inner(&mut self, set: BoxedSystemSet) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
ambiguous_with(&mut config.graph_info, set);
|
ambiguous_with(&mut config.graph_info, set);
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.ambiguous_with_inner(set.dyn_clone());
|
config.ambiguous_with_inner(set.dyn_clone());
|
||||||
}
|
}
|
||||||
@ -157,10 +165,10 @@ impl SystemConfigs {
|
|||||||
|
|
||||||
fn ambiguous_with_all_inner(&mut self) {
|
fn ambiguous_with_all_inner(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
|
config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs { configs, .. } => {
|
Self::Configs { configs, .. } => {
|
||||||
for config in configs {
|
for config in configs {
|
||||||
config.ambiguous_with_all_inner();
|
config.ambiguous_with_all_inner();
|
||||||
}
|
}
|
||||||
@ -174,10 +182,10 @@ impl SystemConfigs {
|
|||||||
/// Prefer `run_if` for run conditions whose type is known at compile time.
|
/// Prefer `run_if` for run conditions whose type is known at compile time.
|
||||||
pub fn run_if_dyn(&mut self, condition: BoxedCondition) {
|
pub fn run_if_dyn(&mut self, condition: BoxedCondition) {
|
||||||
match self {
|
match self {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
Self::NodeConfig(config) => {
|
||||||
config.conditions.push(condition);
|
config.conditions.push(condition);
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs {
|
Self::Configs {
|
||||||
collective_conditions,
|
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`].
|
/// 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
|
/// 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.
|
/// 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
|
/// 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.
|
/// condition for each contained system separately.
|
||||||
fn distributive_run_if<M>(self, condition: impl Condition<M> + Clone) -> SystemConfigs {
|
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)]
|
/// # #[derive(SystemSet, Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
/// # struct C;
|
/// # struct C;
|
||||||
/// schedule.add_systems((a, b).run_if(condition));
|
/// 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
|
/// # Note
|
||||||
@ -350,14 +368,8 @@ impl IntoSystemConfigs<()> for SystemConfigs {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain(mut self) -> Self {
|
fn chain(self) -> Self {
|
||||||
match &mut self {
|
self.chain_inner()
|
||||||
SystemConfigs::SystemConfig(_) => { /* no op */ }
|
|
||||||
SystemConfigs::Configs { chained, .. } => {
|
|
||||||
*chained = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,15 +398,11 @@ macro_rules! impl_system_collection {
|
|||||||
all_tuples!(impl_system_collection, 1, 20, P, S);
|
all_tuples!(impl_system_collection, 1, 20, P, S);
|
||||||
|
|
||||||
/// A [`SystemSet`] with scheduling metadata.
|
/// A [`SystemSet`] with scheduling metadata.
|
||||||
pub struct SystemSetConfig {
|
pub type SystemSetConfig = NodeConfig<BoxedSystemSet>;
|
||||||
pub(super) set: BoxedSystemSet,
|
|
||||||
pub(super) graph_info: GraphInfo,
|
|
||||||
pub(super) conditions: Vec<BoxedCondition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SystemSetConfig {
|
impl SystemSetConfig {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn new(set: BoxedSystemSet) -> Self {
|
pub(super) fn new(set: BoxedSystemSet) -> Self {
|
||||||
// system type sets are automatically populated
|
// system type sets are automatically populated
|
||||||
// to avoid unintentionally broad changes, they cannot be configured
|
// to avoid unintentionally broad changes, they cannot be configured
|
||||||
assert!(
|
assert!(
|
||||||
@ -403,118 +411,15 @@ impl SystemSetConfig {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
set,
|
node: set,
|
||||||
graph_info: GraphInfo::default(),
|
graph_info: GraphInfo::default(),
|
||||||
conditions: Vec::new(),
|
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`].
|
/// A collection of [`SystemSetConfig`].
|
||||||
pub struct SystemSetConfigs {
|
pub type SystemSetConfigs = NodeConfigs<BoxedSystemSet>;
|
||||||
pub(super) sets: Vec<SystemSetConfig>,
|
|
||||||
/// If `true`, adds `before -> after` ordering constraints between the successive elements.
|
|
||||||
pub(super) chained: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Types that can convert into a [`SystemSetConfigs`].
|
/// Types that can convert into a [`SystemSetConfigs`].
|
||||||
pub trait IntoSystemSetConfigs
|
pub trait IntoSystemSetConfigs
|
||||||
@ -541,6 +446,14 @@ where
|
|||||||
self.into_configs().after(set)
|
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
|
/// Suppress warnings and errors that would result from systems in these sets having ambiguities
|
||||||
/// (conflicting access but indeterminate order) with systems in `set`.
|
/// (conflicting access but indeterminate order) with systems in `set`.
|
||||||
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
||||||
@ -572,69 +485,77 @@ impl IntoSystemSetConfigs for SystemSetConfigs {
|
|||||||
set.system_type().is_none(),
|
set.system_type().is_none(),
|
||||||
"adding arbitrary systems to a system type set is not allowed"
|
"adding arbitrary systems to a system type set is not allowed"
|
||||||
);
|
);
|
||||||
for config in &mut self.sets {
|
self.in_set_dyn(set.dyn_clone());
|
||||||
config.graph_info.sets.push(set.dyn_clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
fn before<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
||||||
let set = set.into_system_set();
|
let set = set.into_system_set();
|
||||||
for config in &mut self.sets {
|
self.before_inner(set.dyn_clone());
|
||||||
config
|
|
||||||
.graph_info
|
|
||||||
.dependencies
|
|
||||||
.push(Dependency::new(DependencyKind::Before, set.dyn_clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
fn after<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
||||||
let set = set.into_system_set();
|
let set = set.into_system_set();
|
||||||
for config in &mut self.sets {
|
self.after_inner(set.dyn_clone());
|
||||||
config
|
|
||||||
.graph_info
|
self
|
||||||
.dependencies
|
}
|
||||||
.push(Dependency::new(DependencyKind::After, set.dyn_clone()));
|
|
||||||
}
|
fn run_if<M>(mut self, condition: impl Condition<M>) -> SystemSetConfigs {
|
||||||
|
self.run_if_dyn(new_condition(condition));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
||||||
let set = set.into_system_set();
|
let set = set.into_system_set();
|
||||||
for config in &mut self.sets {
|
self.ambiguous_with_inner(set.dyn_clone());
|
||||||
ambiguous_with(&mut config.graph_info, set.dyn_clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ambiguous_with_all(mut self) -> Self {
|
fn ambiguous_with_all(mut self) -> Self {
|
||||||
for config in &mut self.sets {
|
self.ambiguous_with_all_inner();
|
||||||
config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain(mut self) -> Self {
|
fn chain(self) -> Self {
|
||||||
self.chained = true;
|
self.chain_inner()
|
||||||
self
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
macro_rules! impl_system_set_collection {
|
||||||
($($set: ident),*) => {
|
($($set: ident),*) => {
|
||||||
impl<$($set: IntoSystemSetConfig),*> IntoSystemSetConfigs for ($($set,)*)
|
impl<$($set: IntoSystemSetConfigs),*> IntoSystemSetConfigs for ($($set,)*)
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn into_configs(self) -> SystemSetConfigs {
|
fn into_configs(self) -> SystemSetConfigs {
|
||||||
let ($($set,)*) = self;
|
let ($($set,)*) = self;
|
||||||
SystemSetConfigs {
|
SystemSetConfigs::Configs {
|
||||||
sets: vec![$($set.into_config(),)*],
|
configs: vec![$($set.into_configs(),)*],
|
||||||
|
collective_conditions: Vec::new(),
|
||||||
chained: false,
|
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};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
pub use crate as bevy_ecs;
|
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::system::{Res, ResMut};
|
||||||
pub use crate::{prelude::World, system::Resource};
|
pub use crate::{prelude::World, system::Resource};
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ mod tests {
|
|||||||
assert_eq!(world.resource::<SystemOrder>().0, vec![]);
|
assert_eq!(world.resource::<SystemOrder>().0, vec![]);
|
||||||
|
|
||||||
// modify the schedule after it's been initialized and test ordering with sets
|
// 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((
|
schedule.add_systems((
|
||||||
make_function_system(3)
|
make_function_system(3)
|
||||||
.before(TestSet::A)
|
.before(TestSet::A)
|
||||||
@ -339,13 +339,13 @@ mod tests {
|
|||||||
|
|
||||||
world.init_resource::<Counter>();
|
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.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.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.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.add_systems(counting_system.in_set(TestSet::D));
|
||||||
|
|
||||||
schedule.run(&mut world);
|
schedule.run(&mut world);
|
||||||
@ -359,13 +359,13 @@ mod tests {
|
|||||||
|
|
||||||
world.init_resource::<Counter>();
|
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.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.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.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.add_systems(counting_system.in_set(TestSet::D).run_if(|| true));
|
||||||
|
|
||||||
schedule.run(&mut world);
|
schedule.run(&mut world);
|
||||||
@ -431,7 +431,7 @@ mod tests {
|
|||||||
world.init_resource::<Bool2>();
|
world.init_resource::<Bool2>();
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule.configure_set(
|
schedule.configure_sets(
|
||||||
TestSet::A
|
TestSet::A
|
||||||
.run_if(|res1: Res<RunConditionBool>| res1.is_changed())
|
.run_if(|res1: Res<RunConditionBool>| res1.is_changed())
|
||||||
.run_if(|res2: Res<Bool2>| res2.is_changed()),
|
.run_if(|res2: Res<Bool2>| res2.is_changed()),
|
||||||
@ -482,7 +482,7 @@ mod tests {
|
|||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule
|
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(
|
schedule.add_systems(
|
||||||
counting_system
|
counting_system
|
||||||
@ -529,7 +529,7 @@ mod tests {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn dependency_loop() {
|
fn dependency_loop() {
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
schedule.configure_set(TestSet::X.after(TestSet::X));
|
schedule.configure_sets(TestSet::X.after(TestSet::X));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -537,8 +537,8 @@ mod tests {
|
|||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule.configure_set(TestSet::A.after(TestSet::B));
|
schedule.configure_sets(TestSet::A.after(TestSet::B));
|
||||||
schedule.configure_set(TestSet::B.after(TestSet::A));
|
schedule.configure_sets(TestSet::B.after(TestSet::A));
|
||||||
|
|
||||||
let result = schedule.initialize(&mut world);
|
let result = schedule.initialize(&mut world);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
@ -564,7 +564,7 @@ mod tests {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn hierarchy_loop() {
|
fn hierarchy_loop() {
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
schedule.configure_set(TestSet::X.in_set(TestSet::X));
|
schedule.configure_sets(TestSet::X.in_set(TestSet::X));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -572,8 +572,8 @@ mod tests {
|
|||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule.configure_set(TestSet::A.in_set(TestSet::B));
|
schedule.configure_sets(TestSet::A.in_set(TestSet::B));
|
||||||
schedule.configure_set(TestSet::B.in_set(TestSet::A));
|
schedule.configure_sets(TestSet::B.in_set(TestSet::A));
|
||||||
|
|
||||||
let result = schedule.initialize(&mut world);
|
let result = schedule.initialize(&mut world);
|
||||||
assert!(matches!(result, Err(ScheduleBuildError::HierarchyCycle(_))));
|
assert!(matches!(result, Err(ScheduleBuildError::HierarchyCycle(_))));
|
||||||
@ -625,7 +625,7 @@ mod tests {
|
|||||||
fn configure_system_type_set() {
|
fn configure_system_type_set() {
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
schedule.configure_set(foo.into_system_set());
|
schedule.configure_sets(foo.into_system_set());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -639,13 +639,13 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add `A`.
|
// Add `A`.
|
||||||
schedule.configure_set(TestSet::A);
|
schedule.configure_sets(TestSet::A);
|
||||||
|
|
||||||
// Add `B` as child of `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`.
|
// 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.
|
// `X` cannot be the `A`'s child and grandchild at the same time.
|
||||||
let result = schedule.initialize(&mut world);
|
let result = schedule.initialize(&mut world);
|
||||||
@ -661,8 +661,8 @@ mod tests {
|
|||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
// Add `B` and give it both kinds of relationships with `A`.
|
// Add `B` and give it both kinds of relationships with `A`.
|
||||||
schedule.configure_set(TestSet::B.in_set(TestSet::A));
|
schedule.configure_sets(TestSet::B.in_set(TestSet::A));
|
||||||
schedule.configure_set(TestSet::B.after(TestSet::A));
|
schedule.configure_sets(TestSet::B.after(TestSet::A));
|
||||||
let result = schedule.initialize(&mut world);
|
let result = schedule.initialize(&mut world);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
|||||||
@ -192,15 +192,15 @@ impl Schedule {
|
|||||||
|
|
||||||
/// Add a collection of systems to the schedule.
|
/// Add a collection of systems to the schedule.
|
||||||
pub fn add_systems<M>(&mut self, systems: impl IntoSystemConfigs<M>) -> &mut Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures a system set in this schedule, adding it if it does not exist.
|
/// 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]
|
#[track_caller]
|
||||||
pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self {
|
pub fn configure_set(&mut self, set: impl IntoSystemSetConfigs) -> &mut Self {
|
||||||
self.graph.configure_set(set);
|
self.configure_sets(set)
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures a collection of system sets in this schedule, adding them if they does not exist.
|
/// 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
|
&self.conflicting_systems
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the systems to the graph. Returns a vector of all node ids contained the nested `SystemConfigs`
|
/// Adds the config nodes to the graph.
|
||||||
/// 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
|
/// `collect_nodes` controls whether the `NodeId`s of the processed config nodes are stored in the returned [`ProcessConfigsResult`].
|
||||||
fn add_systems_inner(
|
/// `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,
|
&mut self,
|
||||||
configs: SystemConfigs,
|
configs: NodeConfigs<T>,
|
||||||
ancestor_chained: bool,
|
collect_nodes: bool,
|
||||||
) -> AddSystemsInnerResult {
|
) -> ProcessConfigsResult {
|
||||||
match configs {
|
match configs {
|
||||||
SystemConfigs::SystemConfig(config) => {
|
NodeConfigs::NodeConfig(config) => {
|
||||||
let node_id = self.add_system_inner(config).unwrap();
|
let node_id = T::process_config(self, config);
|
||||||
if ancestor_chained {
|
if collect_nodes {
|
||||||
AddSystemsInnerResult {
|
ProcessConfigsResult {
|
||||||
densely_chained: true,
|
densely_chained: true,
|
||||||
nodes: vec![node_id],
|
nodes: vec![node_id],
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AddSystemsInnerResult {
|
ProcessConfigsResult {
|
||||||
densely_chained: true,
|
densely_chained: true,
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SystemConfigs::Configs {
|
NodeConfigs::Configs {
|
||||||
mut configs,
|
mut configs,
|
||||||
collective_conditions,
|
collective_conditions,
|
||||||
chained,
|
chained,
|
||||||
@ -557,9 +563,9 @@ impl ScheduleGraph {
|
|||||||
for config in &mut configs {
|
for config in &mut configs {
|
||||||
config.in_set_dyn(set.dyn_clone());
|
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);
|
set_config.conditions.extend(collective_conditions);
|
||||||
self.configure_set(set_config);
|
self.configure_set_inner(set_config).unwrap();
|
||||||
} else {
|
} else {
|
||||||
for condition in collective_conditions {
|
for condition in collective_conditions {
|
||||||
configs[0].run_if_dyn(condition);
|
configs[0].run_if_dyn(condition);
|
||||||
@ -571,15 +577,15 @@ impl ScheduleGraph {
|
|||||||
let mut densely_chained = true;
|
let mut densely_chained = true;
|
||||||
if chained {
|
if chained {
|
||||||
let Some(prev) = config_iter.next() else {
|
let Some(prev) = config_iter.next() else {
|
||||||
return AddSystemsInnerResult {
|
return ProcessConfigsResult {
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
densely_chained: true,
|
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;
|
densely_chained = previous_result.densely_chained;
|
||||||
for current in config_iter {
|
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;
|
densely_chained = densely_chained && current_result.densely_chained;
|
||||||
match (
|
match (
|
||||||
previous_result.densely_chained,
|
previous_result.densely_chained,
|
||||||
@ -635,7 +641,7 @@ impl ScheduleGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ancestor_chained {
|
if collect_nodes {
|
||||||
nodes_in_scope.append(&mut previous_result.nodes);
|
nodes_in_scope.append(&mut previous_result.nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,14 +649,14 @@ impl ScheduleGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensure the last config's nodes are added
|
// ensure the last config's nodes are added
|
||||||
if ancestor_chained {
|
if collect_nodes {
|
||||||
nodes_in_scope.append(&mut previous_result.nodes);
|
nodes_in_scope.append(&mut previous_result.nodes);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for config in config_iter {
|
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;
|
densely_chained = densely_chained && result.densely_chained;
|
||||||
if ancestor_chained {
|
if collect_nodes {
|
||||||
nodes_in_scope.extend(result.nodes);
|
nodes_in_scope.extend(result.nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -661,7 +667,7 @@ impl ScheduleGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSystemsInnerResult {
|
ProcessConfigsResult {
|
||||||
nodes: nodes_in_scope,
|
nodes: nodes_in_scope,
|
||||||
densely_chained,
|
densely_chained,
|
||||||
}
|
}
|
||||||
@ -677,7 +683,7 @@ impl ScheduleGraph {
|
|||||||
|
|
||||||
// system init has to be deferred (need `&mut World`)
|
// system init has to be deferred (need `&mut World`)
|
||||||
self.uninit.push((id, 0));
|
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);
|
self.system_conditions.push(config.conditions);
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
@ -685,46 +691,15 @@ impl ScheduleGraph {
|
|||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) {
|
fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) {
|
||||||
let SystemSetConfigs { sets, chained } = sets.into_configs();
|
self.process_configs(sets.into_configs(), false);
|
||||||
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}");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
fn configure_set_inner(&mut self, set: SystemSetConfig) -> Result<NodeId, ScheduleBuildError> {
|
||||||
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> {
|
|
||||||
let SystemSetConfig {
|
let SystemSetConfig {
|
||||||
set,
|
node: set,
|
||||||
graph_info,
|
graph_info,
|
||||||
mut conditions,
|
mut conditions,
|
||||||
} = set.into_config();
|
} = set;
|
||||||
|
|
||||||
let id = match self.system_set_ids.get(&set) {
|
let id = match self.system_set_ids.get(&set) {
|
||||||
Some(&id) => id,
|
Some(&id) => id,
|
||||||
@ -1240,14 +1215,35 @@ impl ScheduleGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Values returned by `ScheduleGraph::add_systems_inner`
|
/// Values returned by [`ScheduleGraph::process_configs`]
|
||||||
struct AddSystemsInnerResult {
|
struct ProcessConfigsResult {
|
||||||
/// All nodes contained inside this add_systems_inner call's SystemConfigs hierarchy
|
/// All nodes contained inside this process_configs call's [`NodeConfigs`] hierarchy,
|
||||||
|
/// if `ancestor_chained` is true
|
||||||
nodes: Vec<NodeId>,
|
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,
|
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.
|
/// Used to select the appropriate reporting function.
|
||||||
enum ReportCycles {
|
enum ReportCycles {
|
||||||
Hierarchy,
|
Hierarchy,
|
||||||
@ -1718,7 +1714,7 @@ impl ScheduleBuildSettings {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
self as bevy_ecs,
|
self as bevy_ecs,
|
||||||
schedule::{IntoSystemConfigs, IntoSystemSetConfig, Schedule, SystemSet},
|
schedule::{IntoSystemConfigs, IntoSystemSetConfigs, Schedule, SystemSet},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1731,7 +1727,7 @@ mod tests {
|
|||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule.configure_set(Set.run_if(|| false));
|
schedule.configure_sets(Set.run_if(|| false));
|
||||||
schedule.add_systems(
|
schedule.add_systems(
|
||||||
(|| panic!("This system must not run"))
|
(|| panic!("This system must not run"))
|
||||||
.ambiguous_with(|| ())
|
.ambiguous_with(|| ())
|
||||||
|
|||||||
@ -110,7 +110,8 @@ impl<T> SystemSet for SystemTypeSet<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A [`SystemSet`] implicitly created when using
|
/// 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)]
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct AnonymousSet(usize);
|
pub struct AnonymousSet(usize);
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
//! You can **explicitly order** systems:
|
//! You can **explicitly order** systems:
|
||||||
//!
|
//!
|
||||||
//! - by calling the `.before(this_system)` or `.after(that_system)` methods when adding them to your schedule
|
//! - 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())`
|
//! - through the use of `.add_systems((system_a, system_b, system_c).chain())`
|
||||||
//!
|
//!
|
||||||
//! [`SystemSet`]: crate::schedule::SystemSet
|
//! [`SystemSet`]: crate::schedule::SystemSet
|
||||||
|
|||||||
@ -161,7 +161,7 @@ impl Render {
|
|||||||
);
|
);
|
||||||
|
|
||||||
schedule.configure_sets((ExtractCommands, PrepareAssets, Prepare).chain());
|
schedule.configure_sets((ExtractCommands, PrepareAssets, Prepare).chain());
|
||||||
schedule.configure_set(
|
schedule.configure_sets(
|
||||||
QueueMeshes
|
QueueMeshes
|
||||||
.in_set(RenderSet::Queue)
|
.in_set(RenderSet::Queue)
|
||||||
.after(prepare_assets::<Mesh>),
|
.after(prepare_assets::<Mesh>),
|
||||||
|
|||||||
@ -216,7 +216,7 @@ impl Plugin for VisibilityPlugin {
|
|||||||
app
|
app
|
||||||
// We add an AABB component in CalculateBounds, which must be ready on the same frame.
|
// We add an AABB component in CalculateBounds, which must be ready on the same frame.
|
||||||
.add_systems(PostUpdate, apply_deferred.in_set(CalculateBoundsFlush))
|
.add_systems(PostUpdate, apply_deferred.in_set(CalculateBoundsFlush))
|
||||||
.configure_set(PostUpdate, CalculateBoundsFlush.after(CalculateBounds))
|
.configure_sets(PostUpdate, CalculateBoundsFlush.after(CalculateBounds))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
(
|
(
|
||||||
|
|||||||
@ -102,7 +102,7 @@ impl Plugin for TransformPlugin {
|
|||||||
app.register_type::<Transform>()
|
app.register_type::<Transform>()
|
||||||
.register_type::<GlobalTransform>()
|
.register_type::<GlobalTransform>()
|
||||||
.add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
|
.add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
|
||||||
.configure_set(
|
.configure_sets(
|
||||||
PostStartup,
|
PostStartup,
|
||||||
PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
|
PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
|
||||||
)
|
)
|
||||||
@ -119,7 +119,7 @@ impl Plugin for TransformPlugin {
|
|||||||
propagate_transforms.in_set(PropagateTransformsSet),
|
propagate_transforms.in_set(PropagateTransformsSet),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.configure_set(
|
.configure_sets(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
|
PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user