@@ -133,6 +133,9 @@ mod sealed {
133
133
pub mod common_conditions {
134
134
use super :: Condition ;
135
135
use crate :: {
136
+ change_detection:: DetectChanges ,
137
+ event:: { Event , EventReader } ,
138
+ prelude:: { Component , Query , With } ,
136
139
schedule:: { State , States } ,
137
140
system:: { In , IntoPipeSystem , ReadOnlySystem , Res , Resource } ,
138
141
} ;
@@ -187,6 +190,107 @@ pub mod common_conditions {
187
190
}
188
191
}
189
192
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
+
190
294
/// Generates a [`Condition`](super::Condition)-satisfying closure that returns `true`
191
295
/// if the state machine exists.
192
296
pub fn state_exists < S : States > ( ) -> impl FnMut ( Option < Res < State < S > > > ) -> bool {
@@ -216,6 +320,35 @@ pub mod common_conditions {
216
320
}
217
321
}
218
322
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
+
219
352
/// Generates a [`Condition`](super::Condition) that inverses the result of passed one.
220
353
///
221
354
/// # Examples
0 commit comments