Add more "common run conditions" (#7579)
Add some more useful common run conditions. Some of these existed in `iyes_loopless`. I know people used them, and it would be a regression for those users, when they try to migrate to new Bevy stageless, if they are missing. I also took the opportunity to add a few more new ones. --- ## Changelog ### Added - More "common run conditions": on_event, resource change detection, state_changed, any_with_component
This commit is contained in:
parent
c4f0de52eb
commit
17d1fa4a8b
@ -133,6 +133,9 @@ mod sealed {
|
||||
pub mod common_conditions {
|
||||
use super::Condition;
|
||||
use crate::{
|
||||
change_detection::DetectChanges,
|
||||
event::{Event, EventReader},
|
||||
prelude::{Component, Query, With},
|
||||
schedule::{State, States},
|
||||
system::{In, IntoPipeSystem, ReadOnlySystem, Res, Resource},
|
||||
};
|
||||
@ -187,6 +190,107 @@ pub mod common_conditions {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the resource of the given type has been added since the condition was last checked.
|
||||
pub fn resource_added<T>() -> impl FnMut(Option<Res<T>>) -> bool
|
||||
where
|
||||
T: Resource,
|
||||
{
|
||||
move |res: Option<Res<T>>| match res {
|
||||
Some(res) => res.is_added(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
/// The value is considered changed when it is added. The first time this condition
|
||||
/// is checked after the resource was added, it will return `true`.
|
||||
/// Change detection behaves like this everywhere in Bevy.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The condition will panic if the resource does not exist.
|
||||
pub fn resource_changed<T>() -> impl FnMut(Res<T>) -> bool
|
||||
where
|
||||
T: Resource,
|
||||
{
|
||||
move |res: Res<T>| res.is_changed()
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
/// The value is considered changed when it is added. The first time this condition
|
||||
/// is checked after the resource was added, it will return `true`.
|
||||
/// Change detection behaves like this everywhere in Bevy.
|
||||
///
|
||||
/// This run condition does not detect when the resource is removed.
|
||||
///
|
||||
/// The condition will return `false` if the resource does not exist.
|
||||
pub fn resource_exists_and_changed<T>() -> impl FnMut(Option<Res<T>>) -> bool
|
||||
where
|
||||
T: Resource,
|
||||
{
|
||||
move |res: Option<Res<T>>| match res {
|
||||
Some(res) => res.is_changed(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the resource of the given type has had its value changed since the condition
|
||||
/// was last checked.
|
||||
///
|
||||
/// The value is considered changed when it is added. The first time this condition
|
||||
/// is checked after the resource was added, it will return `true`.
|
||||
/// Change detection behaves like this everywhere in Bevy.
|
||||
///
|
||||
/// This run condition also detects removal. It will return `true` if the resource
|
||||
/// has been removed since the run condition was last checked.
|
||||
///
|
||||
/// The condition will return `false` if the resource does not exist.
|
||||
pub fn resource_changed_or_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool
|
||||
where
|
||||
T: Resource,
|
||||
{
|
||||
let mut existed = false;
|
||||
move |res: Option<Res<T>>| {
|
||||
if let Some(value) = res {
|
||||
existed = true;
|
||||
value.is_changed()
|
||||
} else if existed {
|
||||
existed = false;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the resource of the given type has been removed since the condition was last checked.
|
||||
pub fn resource_removed<T>() -> impl FnMut(Option<Res<T>>) -> bool
|
||||
where
|
||||
T: Resource,
|
||||
{
|
||||
let mut existed = false;
|
||||
move |res: Option<Res<T>>| {
|
||||
if res.is_some() {
|
||||
existed = true;
|
||||
false
|
||||
} else if existed {
|
||||
existed = false;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the state machine exists.
|
||||
pub fn state_exists<S: States>() -> impl FnMut(Option<Res<State<S>>>) -> bool {
|
||||
@ -216,6 +320,35 @@ pub mod common_conditions {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if the state machine changed state.
|
||||
///
|
||||
/// To do things on transitions to/from specific states, use their respective OnEnter/OnExit
|
||||
/// schedules. Use this run condition if you want to detect any change, regardless of the value.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The condition will panic if the resource does not exist.
|
||||
pub fn state_changed<S: States>() -> impl FnMut(Res<State<S>>) -> bool {
|
||||
move |current_state: Res<State<S>>| current_state.is_changed()
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if there are any new events of the given type since it was last called.
|
||||
pub fn on_event<T: Event>() -> impl FnMut(EventReader<T>) -> bool {
|
||||
// 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),
|
||||
// due to Bevy having a specialized implementation for events.
|
||||
move |mut reader: EventReader<T>| reader.iter().count() > 0
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||
/// if there are any entities with the given component type.
|
||||
pub fn any_with_component<T: Component>() -> impl FnMut(Query<(), With<T>>) -> bool {
|
||||
move |query: Query<(), With<T>>| !query.is_empty()
|
||||
}
|
||||
|
||||
/// Generates a [`Condition`](super::Condition) that inverses the result of passed one.
|
||||
///
|
||||
/// # Examples
|
||||
|
||||
Loading…
Reference in New Issue
Block a user