Skip to content

Commit

Permalink
add Clone to common conditions (#8060)
Browse files Browse the repository at this point in the history
  • Loading branch information
B-Reif authored and mockersf committed Mar 27, 2023
1 parent c8e519f commit 64d7db3
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 20 deletions.
31 changes: 17 additions & 14 deletions crates/bevy_ecs/src/schedule/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().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 {
Expand Down Expand Up @@ -209,7 +209,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn resource_exists<T>() -> impl FnMut(Option<Res<T>>) -> bool
pub fn resource_exists<T>() -> impl FnMut(Option<Res<T>>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -332,7 +332,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn resource_added<T>() -> impl FnMut(Option<Res<T>>) -> bool
pub fn resource_added<T>() -> impl FnMut(Option<Res<T>>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -389,7 +389,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 51);
/// ```
pub fn resource_changed<T>() -> impl FnMut(Res<T>) -> bool
pub fn resource_changed<T>() -> impl FnMut(Res<T>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -446,7 +446,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 51);
/// ```
pub fn resource_exists_and_changed<T>() -> impl FnMut(Option<Res<T>>) -> bool
pub fn resource_exists_and_changed<T>() -> impl FnMut(Option<Res<T>>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -518,7 +518,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.contains_resource::<MyResource>(), true);
/// ```
pub fn resource_changed_or_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool
pub fn resource_changed_or_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -573,7 +573,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn resource_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool
pub fn resource_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool + Clone
where
T: Resource,
{
Expand Down Expand Up @@ -630,7 +630,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn state_exists<S: States>() -> impl FnMut(Option<Res<State<S>>>) -> bool {
pub fn state_exists<S: States>() -> impl FnMut(Option<Res<State<S>>>) -> bool + Clone {
move |current_state: Option<Res<State<S>>>| current_state.is_some()
}

Expand Down Expand Up @@ -684,7 +684,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 0);
/// ```
pub fn in_state<S: States>(state: S) -> impl FnMut(Res<State<S>>) -> bool {
pub fn in_state<S: States>(state: S) -> impl FnMut(Res<State<S>>) -> bool + Clone {
move |current_state: Res<State<S>>| current_state.0 == state
}

Expand Down Expand Up @@ -742,7 +742,7 @@ pub mod common_conditions {
/// ```
pub fn state_exists_and_equals<S: States>(
state: S,
) -> impl FnMut(Option<Res<State<S>>>) -> bool {
) -> impl FnMut(Option<Res<State<S>>>) -> bool + Clone {
move |current_state: Option<Res<State<S>>>| match current_state {
Some(current_state) => current_state.0 == state,
None => false,
Expand Down Expand Up @@ -802,7 +802,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 2);
/// ```
pub fn state_changed<S: States>() -> impl FnMut(Res<State<S>>) -> bool {
pub fn state_changed<S: States>() -> impl FnMut(Res<State<S>>) -> bool + Clone {
move |current_state: Res<State<S>>| current_state.is_changed()
}

Expand Down Expand Up @@ -841,7 +841,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn on_event<T: Event>() -> impl FnMut(EventReader<T>) -> bool {
pub fn on_event<T: Event>() -> impl FnMut(EventReader<T>) -> 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),
Expand Down Expand Up @@ -882,7 +882,7 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 1);
/// ```
pub fn any_with_component<T: Component>() -> impl FnMut(Query<(), With<T>>) -> bool {
pub fn any_with_component<T: Component>() -> impl FnMut(Query<(), With<T>>) -> bool + Clone {
move |query: Query<(), With<T>>| !query.is_empty()
}

Expand Down Expand Up @@ -915,7 +915,10 @@ pub mod common_conditions {
/// app.run(&mut world);
/// assert_eq!(world.resource::<Counter>().0, 0);
/// ```
pub fn not<Marker>(condition: impl Condition<Marker>) -> impl Condition<()> {
pub fn not<Marker, T>(condition: T) -> impl Condition<()>
where
T: Condition<Marker>,
{
condition.pipe(|In(val): In<bool>| !val)
}
}
Expand Down
28 changes: 24 additions & 4 deletions crates/bevy_input/src/common_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use std::hash::Hash;
/// }
///
/// ```
pub fn input_toggle_active<T>(default: bool, input: T) -> impl FnMut(Res<Input<T>>) -> bool
pub fn input_toggle_active<T>(default: bool, input: T) -> impl FnMut(Res<Input<T>>) -> bool + Clone
where
T: Copy + Eq + Hash + Send + Sync + 'static,
{
Expand All @@ -60,7 +60,7 @@ where
}

/// Run condition that is active if [`Input::pressed`] is true for the given input.
pub fn input_pressed<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool
pub fn input_pressed<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool + Clone
where
T: Copy + Eq + Hash + Send + Sync + 'static,
{
Expand All @@ -81,17 +81,37 @@ where
///
/// # fn jump() {}
/// ```
pub fn input_just_pressed<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool
pub fn input_just_pressed<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool + Clone
where
T: Copy + Eq + Hash + Send + Sync + 'static,
{
move |inputs: Res<Input<T>>| inputs.just_pressed(input)
}

/// Run condition that is active if [`Input::just_released`] is true for the given input.
pub fn input_just_released<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool
pub fn input_just_released<T>(input: T) -> impl FnMut(Res<Input<T>>) -> bool + Clone
where
T: Copy + Eq + Hash + Send + Sync + 'static,
{
move |inputs: Res<Input<T>>| 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)),
);
}
}
22 changes: 20 additions & 2 deletions crates/bevy_time/src/common_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Time>) -> bool {
pub fn on_timer(duration: Duration) -> impl FnMut(Res<Time>) -> bool + Clone {
let mut timer = Timer::new(duration, TimerMode::Repeating);
move |time: Res<Time>| {
timer.tick(time.delta());
Expand Down Expand Up @@ -67,10 +67,28 @@ pub fn on_timer(duration: Duration) -> impl FnMut(Res<Time>) -> bool {
/// Note that this run condition may not behave as expected if `duration` is smaller
/// than the fixed timestep period, since the timer may complete multiple times in
/// one fixed update.
pub fn on_fixed_timer(duration: Duration) -> impl FnMut(Res<FixedTime>) -> bool {
pub fn on_fixed_timer(duration: Duration) -> impl FnMut(Res<FixedTime>) -> bool + Clone {
let mut timer = Timer::new(duration, TimerMode::Repeating);
move |time: Res<FixedTime>| {
timer.tick(time.period);
timer.just_finished()
}
}

#[cfg(test)]
mod tests {
use super::*;
use bevy_ecs::schedule::{IntoSystemConfigs, 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(on_timer(Duration::new(1, 0)))
.distributive_run_if(on_fixed_timer(Duration::new(1, 0))),
);
}
}

0 comments on commit 64d7db3

Please sign in to comment.