mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Add condition_changed
and condition_became_true
to common_conditions
(#14917)
# Objective - I needed to run a system whenever a specific condition became true after being previously false. - Other users might also need to run a system when a condition changes, regardless of if it became true or false. ## Solution - This adds two systems to common_conditions: - `condition_changed` that changes whenever the inner condition changes - `condition_became_true` that returns true whenever the inner condition becomes true after previously being false ## Testing - I added a doctest for each function --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
This commit is contained in:
parent
23979b8160
commit
12f005a024
1 changed files with 118 additions and 15 deletions
|
@ -490,16 +490,16 @@ mod sealed {
|
|||
|
||||
/// A collection of [run conditions](Condition) that may be useful in any bevy app.
|
||||
pub mod common_conditions {
|
||||
use super::NotSystem;
|
||||
use super::{Condition, NotSystem};
|
||||
use crate::{
|
||||
change_detection::DetectChanges,
|
||||
event::{Event, EventReader},
|
||||
prelude::{Component, Query, With},
|
||||
removal_detection::RemovedComponents,
|
||||
system::{IntoSystem, Local, Res, Resource, System},
|
||||
system::{In, IntoSystem, Local, Res, Resource, System},
|
||||
};
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// on the first time the condition is run and false every time after.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -537,7 +537,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource exists.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -572,7 +572,7 @@ pub mod common_conditions {
|
|||
res.is_some()
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// Generates a [`Condition`]-satisfying closure that returns `true`
|
||||
/// if the resource is equal to `value`.
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -612,7 +612,7 @@ pub mod common_conditions {
|
|||
move |res: Res<T>| *res == value
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// Generates a [`Condition`]-satisfying closure that returns `true`
|
||||
/// if the resource exists and is equal to `value`.
|
||||
///
|
||||
/// The condition will return `false` if the resource does not exist.
|
||||
|
@ -657,7 +657,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource of the given type has been added since the condition was last checked.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -698,7 +698,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
|
@ -752,7 +752,7 @@ pub mod common_conditions {
|
|||
res.is_changed()
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
|
@ -812,7 +812,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
|
@ -889,7 +889,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if the resource of the given type has been removed since the condition was last checked.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -941,7 +941,7 @@ pub mod common_conditions {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if there are any new events of the given type since it was last called.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -985,7 +985,7 @@ pub mod common_conditions {
|
|||
reader.read().count() > 0
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if there are any entities with the given component type.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -1022,7 +1022,7 @@ pub mod common_conditions {
|
|||
!query.is_empty()
|
||||
}
|
||||
|
||||
/// A [`Condition`](super::Condition)-satisfying system that returns `true`
|
||||
/// A [`Condition`]-satisfying system that returns `true`
|
||||
/// if there are any entity with a component of the given type removed.
|
||||
pub fn any_component_removed<T: Component>(mut removals: RemovedComponents<T>) -> bool {
|
||||
// `RemovedComponents` based on events and therefore events need to be consumed,
|
||||
|
@ -1033,7 +1033,7 @@ pub mod common_conditions {
|
|||
removals.read().count() > 0
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition) that inverses the result of passed one.
|
||||
/// Generates a [`Condition`] that inverses the result of passed one.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -1071,6 +1071,109 @@ pub mod common_conditions {
|
|||
let name = format!("!{}", condition.name());
|
||||
NotSystem::new(super::NotMarker, condition, name.into())
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`] that returns true when the passed one changes.
|
||||
///
|
||||
/// The first time this is called, the passed condition is assumed to have been previously false.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Resource, Default)]
|
||||
/// # struct Counter(u8);
|
||||
/// # let mut app = Schedule::default();
|
||||
/// # let mut world = World::new();
|
||||
/// # world.init_resource::<Counter>();
|
||||
/// app.add_systems(
|
||||
/// my_system.run_if(condition_changed(resource_exists::<MyResource>)),
|
||||
/// );
|
||||
///
|
||||
/// #[derive(Resource)]
|
||||
/// struct MyResource;
|
||||
///
|
||||
/// fn my_system(mut counter: ResMut<Counter>) {
|
||||
/// counter.0 += 1;
|
||||
/// }
|
||||
///
|
||||
/// // `MyResource` is initially there, the inner condition is true, the system runs once
|
||||
/// world.insert_resource(MyResource);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 1);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 1);
|
||||
///
|
||||
/// // We remove `MyResource`, the inner condition is now false, the system runs one more time.
|
||||
/// world.remove_resource::<MyResource>();
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 2);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 2);
|
||||
/// ```
|
||||
pub fn condition_changed<Marker, CIn, C: Condition<Marker, CIn>>(
|
||||
condition: C,
|
||||
) -> impl Condition<(), CIn> {
|
||||
condition.pipe(|In(new): In<bool>, mut prev: Local<bool>| -> bool {
|
||||
let changed = *prev != new;
|
||||
*prev = new;
|
||||
changed
|
||||
})
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`] that returns true when the result of
|
||||
/// the passed one went from false to true since the last time this was called.
|
||||
///
|
||||
/// The first time this is called, the passed condition is assumed to have been previously false.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Resource, Default)]
|
||||
/// # struct Counter(u8);
|
||||
/// # let mut app = Schedule::default();
|
||||
/// # let mut world = World::new();
|
||||
/// # world.init_resource::<Counter>();
|
||||
/// app.add_systems(
|
||||
/// my_system.run_if(condition_changed_to(true, resource_exists::<MyResource>)),
|
||||
/// );
|
||||
///
|
||||
/// #[derive(Resource)]
|
||||
/// struct MyResource;
|
||||
///
|
||||
/// fn my_system(mut counter: ResMut<Counter>) {
|
||||
/// counter.0 += 1;
|
||||
/// }
|
||||
///
|
||||
/// // `MyResource` is initially there, the inner condition is true, the system runs once
|
||||
/// world.insert_resource(MyResource);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 1);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 1);
|
||||
///
|
||||
/// // We remove `MyResource`, the inner condition is now false, the system doesn't run.
|
||||
/// world.remove_resource::<MyResource>();
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 1);
|
||||
///
|
||||
/// // We reinsert `MyResource` again, so the system will run one more time
|
||||
/// world.insert_resource(MyResource);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 2);
|
||||
/// app.run(&mut world);
|
||||
/// assert_eq!(world.resource::<Counter>().0, 2);
|
||||
/// ```
|
||||
pub fn condition_changed_to<Marker, CIn, C: Condition<Marker, CIn>>(
|
||||
to: bool,
|
||||
condition: C,
|
||||
) -> impl Condition<(), CIn> {
|
||||
condition.pipe(move |In(new): In<bool>, mut prev: Local<bool>| -> bool {
|
||||
let now_true = *prev != new && new == to;
|
||||
*prev = new;
|
||||
now_true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes [`Not`] with the output of another system.
|
||||
|
|
Loading…
Reference in a new issue