diff --git a/crates/bevy_ecs/src/schedule/condition.rs b/crates/bevy_ecs/src/schedule/condition.rs index 3628eef5bd183..939d04b19114e 100644 --- a/crates/bevy_ecs/src/schedule/condition.rs +++ b/crates/bevy_ecs/src/schedule/condition.rs @@ -169,7 +169,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn run_once() -> impl FnMut() -> bool { + pub fn run_once() -> impl FnMut() -> bool + Clone { let mut has_run = false; move || { if !has_run { @@ -209,7 +209,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn resource_exists() -> impl FnMut(Option>) -> bool + pub fn resource_exists() -> impl FnMut(Option>) -> bool + Clone where T: Resource, { @@ -332,7 +332,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn resource_added() -> impl FnMut(Option>) -> bool + pub fn resource_added() -> impl FnMut(Option>) -> bool + Clone where T: Resource, { @@ -389,7 +389,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 51); /// ``` - pub fn resource_changed() -> impl FnMut(Res) -> bool + pub fn resource_changed() -> impl FnMut(Res) -> bool + Clone where T: Resource, { @@ -446,7 +446,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 51); /// ``` - pub fn resource_exists_and_changed() -> impl FnMut(Option>) -> bool + pub fn resource_exists_and_changed() -> impl FnMut(Option>) -> bool + Clone where T: Resource, { @@ -518,7 +518,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.contains_resource::(), true); /// ``` - pub fn resource_changed_or_removed() -> impl FnMut(Option>) -> bool + pub fn resource_changed_or_removed() -> impl FnMut(Option>) -> bool + Clone where T: Resource, { @@ -573,7 +573,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn resource_removed() -> impl FnMut(Option>) -> bool + pub fn resource_removed() -> impl FnMut(Option>) -> bool + Clone where T: Resource, { @@ -630,7 +630,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn state_exists() -> impl FnMut(Option>>) -> bool { + pub fn state_exists() -> impl FnMut(Option>>) -> bool + Clone { move |current_state: Option>>| current_state.is_some() } @@ -684,7 +684,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 0); /// ``` - pub fn in_state(state: S) -> impl FnMut(Res>) -> bool { + pub fn in_state(state: S) -> impl FnMut(Res>) -> bool + Clone { move |current_state: Res>| current_state.0 == state } @@ -742,7 +742,7 @@ pub mod common_conditions { /// ``` pub fn state_exists_and_equals( state: S, - ) -> impl FnMut(Option>>) -> bool { + ) -> impl FnMut(Option>>) -> bool + Clone { move |current_state: Option>>| match current_state { Some(current_state) => current_state.0 == state, None => false, @@ -802,7 +802,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 2); /// ``` - pub fn state_changed() -> impl FnMut(Res>) -> bool { + pub fn state_changed() -> impl FnMut(Res>) -> bool + Clone { move |current_state: Res>| current_state.is_changed() } @@ -841,7 +841,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn on_event() -> impl FnMut(EventReader) -> bool { + pub fn on_event() -> impl FnMut(EventReader) -> bool + Clone { // The events need to be consumed, so that there are no false positives on subsequent // calls of the run condition. Simply checking `is_empty` would not be enough. // PERF: note that `count` is efficient (not actually looping/iterating), @@ -882,7 +882,7 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 1); /// ``` - pub fn any_with_component() -> impl FnMut(Query<(), With>) -> bool { + pub fn any_with_component() -> impl FnMut(Query<(), With>) -> bool + Clone { move |query: Query<(), With>| !query.is_empty() } @@ -915,7 +915,10 @@ pub mod common_conditions { /// app.run(&mut world); /// assert_eq!(world.resource::().0, 0); /// ``` - pub fn not(condition: impl Condition) -> impl Condition<()> { + pub fn not(condition: T) -> impl Condition<()> + where + T: Condition, + { condition.pipe(|In(val): In| !val) } } diff --git a/crates/bevy_input/src/common_conditions.rs b/crates/bevy_input/src/common_conditions.rs index 265b1c0c4dc50..dd93d2bdf1a1b 100644 --- a/crates/bevy_input/src/common_conditions.rs +++ b/crates/bevy_input/src/common_conditions.rs @@ -48,7 +48,7 @@ use std::hash::Hash; /// } /// /// ``` -pub fn input_toggle_active(default: bool, input: T) -> impl FnMut(Res>) -> bool +pub fn input_toggle_active(default: bool, input: T) -> impl FnMut(Res>) -> bool + Clone where T: Copy + Eq + Hash + Send + Sync + 'static, { @@ -60,7 +60,7 @@ where } /// Run condition that is active if [`Input::pressed`] is true for the given input. -pub fn input_pressed(input: T) -> impl FnMut(Res>) -> bool +pub fn input_pressed(input: T) -> impl FnMut(Res>) -> bool + Clone where T: Copy + Eq + Hash + Send + Sync + 'static, { @@ -81,7 +81,7 @@ where /// /// # fn jump() {} /// ``` -pub fn input_just_pressed(input: T) -> impl FnMut(Res>) -> bool +pub fn input_just_pressed(input: T) -> impl FnMut(Res>) -> bool + Clone where T: Copy + Eq + Hash + Send + Sync + 'static, { @@ -89,9 +89,29 @@ where } /// Run condition that is active if [`Input::just_released`] is true for the given input. -pub fn input_just_released(input: T) -> impl FnMut(Res>) -> bool +pub fn input_just_released(input: T) -> impl FnMut(Res>) -> bool + Clone where T: Copy + Eq + Hash + Send + Sync + 'static, { move |inputs: Res>| inputs.just_released(input) } + +#[cfg(test)] +mod tests { + use super::*; + use bevy::prelude::{IntoSystemConfigs, KeyCode, Schedule}; + + fn test_system() {} + + // Ensure distributive_run_if compiles with the common conditions. + #[test] + fn distributive_run_if_compiles() { + Schedule::default().add_systems( + (test_system, test_system) + .distributive_run_if(input_toggle_active(false, KeyCode::Escape)) + .distributive_run_if(input_pressed(KeyCode::Escape)) + .distributive_run_if(input_just_pressed(KeyCode::Escape)) + .distributive_run_if(input_just_released(KeyCode::Escape)), + ); + } +} diff --git a/crates/bevy_time/src/common_conditions.rs b/crates/bevy_time/src/common_conditions.rs index 357f83cbe2dcc..1f5625515e81a 100644 --- a/crates/bevy_time/src/common_conditions.rs +++ b/crates/bevy_time/src/common_conditions.rs @@ -32,7 +32,7 @@ use bevy_utils::Duration; /// For more accurate timers, use the [`Timer`] class directly (see /// [`Timer::times_finished_this_tick`] to address the problem mentioned above), or /// use fixed timesteps that allow systems to run multiple times per frame. -pub fn on_timer(duration: Duration) -> impl FnMut(Res