@@ -133,6 +133,9 @@ mod sealed {
133133pub mod common_conditions {
134134 use super :: Condition ;
135135 use crate :: {
136+ change_detection:: DetectChanges ,
137+ event:: { Event , EventReader } ,
138+ prelude:: { Component , Query , With } ,
136139 schedule:: { State , States } ,
137140 system:: { In , IntoPipeSystem , ReadOnlySystem , Res , Resource } ,
138141 } ;
@@ -187,6 +190,107 @@ pub mod common_conditions {
187190 }
188191 }
189192
193+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
194+ /// if the resource of the given type has been added since the condition was last checked.
195+ pub fn resource_added < T > ( ) -> impl FnMut ( Option < Res < T > > ) -> bool
196+ where
197+ T : Resource ,
198+ {
199+ move |res : Option < Res < T > > | match res {
200+ Some ( res) => res. is_added ( ) ,
201+ None => false ,
202+ }
203+ }
204+
205+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
206+ /// if the resource of the given type has had its value changed since the condition
207+ /// was last checked.
208+ ///
209+ /// The value is considered changed when it is added. The first time this condition
210+ /// is checked after the resource was added, it will return `true`.
211+ /// Change detection behaves like this everywhere in Bevy.
212+ ///
213+ /// # Panics
214+ ///
215+ /// The condition will panic if the resource does not exist.
216+ pub fn resource_changed < T > ( ) -> impl FnMut ( Res < T > ) -> bool
217+ where
218+ T : Resource ,
219+ {
220+ move |res : Res < T > | res. is_changed ( )
221+ }
222+
223+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
224+ /// if the resource of the given type has had its value changed since the condition
225+ /// was last checked.
226+ ///
227+ /// The value is considered changed when it is added. The first time this condition
228+ /// is checked after the resource was added, it will return `true`.
229+ /// Change detection behaves like this everywhere in Bevy.
230+ ///
231+ /// This run condition does not detect when the resource is removed.
232+ ///
233+ /// The condition will return `false` if the resource does not exist.
234+ pub fn resource_exists_and_changed < T > ( ) -> impl FnMut ( Option < Res < T > > ) -> bool
235+ where
236+ T : Resource ,
237+ {
238+ move |res : Option < Res < T > > | match res {
239+ Some ( res) => res. is_changed ( ) ,
240+ None => false ,
241+ }
242+ }
243+
244+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
245+ /// if the resource of the given type has had its value changed since the condition
246+ /// was last checked.
247+ ///
248+ /// The value is considered changed when it is added. The first time this condition
249+ /// is checked after the resource was added, it will return `true`.
250+ /// Change detection behaves like this everywhere in Bevy.
251+ ///
252+ /// This run condition also detects removal. It will return `true` if the resource
253+ /// has been removed since the run condition was last checked.
254+ ///
255+ /// The condition will return `false` if the resource does not exist.
256+ pub fn resource_changed_or_removed < T > ( ) -> impl FnMut ( Option < Res < T > > ) -> bool
257+ where
258+ T : Resource ,
259+ {
260+ let mut existed = false ;
261+ move |res : Option < Res < T > > | {
262+ if let Some ( value) = res {
263+ existed = true ;
264+ value. is_changed ( )
265+ } else if existed {
266+ existed = false ;
267+ true
268+ } else {
269+ false
270+ }
271+ }
272+ }
273+
274+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
275+ /// if the resource of the given type has been removed since the condition was last checked.
276+ pub fn resource_removed < T > ( ) -> impl FnMut ( Option < Res < T > > ) -> bool
277+ where
278+ T : Resource ,
279+ {
280+ let mut existed = false ;
281+ move |res : Option < Res < T > > | {
282+ if res. is_some ( ) {
283+ existed = true ;
284+ false
285+ } else if existed {
286+ existed = false ;
287+ true
288+ } else {
289+ false
290+ }
291+ }
292+ }
293+
190294 /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
191295 /// if the state machine exists.
192296 pub fn state_exists < S : States > ( ) -> impl FnMut ( Option < Res < State < S > > > ) -> bool {
@@ -216,6 +320,35 @@ pub mod common_conditions {
216320 }
217321 }
218322
323+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
324+ /// if the state machine changed state.
325+ ///
326+ /// To do things on transitions to/from specific states, use their respective OnEnter/OnExit
327+ /// schedules. Use this run condition if you want to detect any change, regardless of the value.
328+ ///
329+ /// # Panics
330+ ///
331+ /// The condition will panic if the resource does not exist.
332+ pub fn state_changed < S : States > ( ) -> impl FnMut ( Res < State < S > > ) -> bool {
333+ move |current_state : Res < State < S > > | current_state. is_changed ( )
334+ }
335+
336+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
337+ /// if there are any new events of the given type since it was last called.
338+ pub fn on_event < T : Event > ( ) -> impl FnMut ( EventReader < T > ) -> bool {
339+ // The events need to be consumed, so that there are no false positives on subsequent
340+ // calls of the run condition. Simply checking `is_empty` would not be enough.
341+ // PERF: note that `count` is efficient (not actually looping/iterating),
342+ // due to Bevy having a specialized implementation for events.
343+ move |mut reader : EventReader < T > | reader. iter ( ) . count ( ) > 0
344+ }
345+
346+ /// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
347+ /// if there are any entities with the given component type.
348+ pub fn any_with_component < T : Component > ( ) -> impl FnMut ( Query < ( ) , With < T > > ) -> bool {
349+ move |query : Query < ( ) , With < T > > | !query. is_empty ( )
350+ }
351+
219352 /// Generates a [`Condition`](super::Condition) that inverses the result of passed one.
220353 ///
221354 /// # Examples
0 commit comments