Add distributive_run_if to IntoSystemConfigs (#7724)
# Objective - Fixes #7659. ## Solution - This PR extracted the `distributive_run_if` part of #7676, because it does not require the controversial introduction of anonymous system sets. - The distinctive name should make the user aware about the differences between `IntoSystemConfig::run_if` and `IntoSystemConfigs::distributive_run_if`. - The documentation explains in detail the consequences of using the API and possible pit falls when using it. - A test demonstrates the possibility of changing the condition result, resulting in some of the systems not being run. --- ## Changelog ### Added - Add `distributive_run_if` to `IntoSystemConfigs` to enable adding a run condition to each system when using `add_systems`.
This commit is contained in:
parent
609ad5aaa6
commit
67a89e9c58
@ -520,6 +520,40 @@ where
|
||||
self.into_configs().after(set)
|
||||
}
|
||||
|
||||
/// Add a run condition to each contained system.
|
||||
///
|
||||
/// Each system will receive its own clone of the [`Condition`] and will only run
|
||||
/// if the `Condition` is true.
|
||||
///
|
||||
/// Each individual condition will be evaluated at most once (per schedule run),
|
||||
/// right before the corresponding system prepares to run.
|
||||
///
|
||||
/// This is equivalent to calling [`run_if`](IntoSystemConfig::run_if) on each individual
|
||||
/// system, as shown below:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # let mut app = Schedule::new();
|
||||
/// # fn a() {}
|
||||
/// # fn b() {}
|
||||
/// # fn condition() -> bool { true }
|
||||
/// app.add_systems((a, b).distributive_run_if(condition));
|
||||
/// app.add_systems((a.run_if(condition), b.run_if(condition)));
|
||||
/// ```
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Because the conditions are evaluated separately for each system, there is no guarantee
|
||||
/// 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
|
||||
/// 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<P>(self, condition: impl Condition<P> + Clone) -> SystemConfigs {
|
||||
self.into_configs().distributive_run_if(condition)
|
||||
}
|
||||
|
||||
/// Suppress warnings and errors that would result from these systems having ambiguities
|
||||
/// (conflicting access but indeterminate order) with systems in `set`.
|
||||
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
|
||||
@ -603,6 +637,14 @@ impl IntoSystemConfigs<()> for SystemConfigs {
|
||||
self
|
||||
}
|
||||
|
||||
fn distributive_run_if<P>(mut self, condition: impl Condition<P> + Clone) -> SystemConfigs {
|
||||
for config in &mut self.systems {
|
||||
config.conditions.push(new_condition(condition.clone()));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
|
||||
let set = set.into_system_set();
|
||||
for config in &mut self.systems {
|
||||
|
||||
@ -222,6 +222,32 @@ mod tests {
|
||||
assert_eq!(world.resource::<SystemOrder>().0, vec![0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn systems_with_distributive_condition() {
|
||||
let mut world = World::default();
|
||||
let mut schedule = Schedule::default();
|
||||
|
||||
world.insert_resource(RunConditionBool(true));
|
||||
world.init_resource::<SystemOrder>();
|
||||
|
||||
fn change_condition(mut condition: ResMut<RunConditionBool>) {
|
||||
condition.0 = false;
|
||||
}
|
||||
|
||||
schedule.add_systems(
|
||||
(
|
||||
make_function_system(0),
|
||||
change_condition,
|
||||
make_function_system(1),
|
||||
)
|
||||
.chain()
|
||||
.distributive_run_if(|condition: Res<RunConditionBool>| condition.0),
|
||||
);
|
||||
|
||||
schedule.run(&mut world);
|
||||
assert_eq!(world.resource::<SystemOrder>().0, vec![0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_exclusive_system_with_condition() {
|
||||
let mut world = World::default();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user