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 {
|
pub mod common_conditions {
|
||||||
use super::Condition;
|
use super::Condition;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
change_detection::DetectChanges,
|
||||||
|
event::{Event, EventReader},
|
||||||
|
prelude::{Component, Query, With},
|
||||||
schedule::{State, States},
|
schedule::{State, States},
|
||||||
system::{In, IntoPipeSystem, ReadOnlySystem, Res, Resource},
|
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`
|
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
|
||||||
/// if the state machine exists.
|
/// if the state machine exists.
|
||||||
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 {
|
||||||
@ -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.
|
/// Generates a [`Condition`](super::Condition) that inverses the result of passed one.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user