mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
11 changed files with 197 additions and 286 deletions
|
@ -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 a new issue