@@ -23,6 +23,7 @@ use core::{
23
23
marker:: PhantomData ,
24
24
ops:: { Deref , DerefMut } ,
25
25
} ;
26
+ use smallvec:: SmallVec ;
26
27
27
28
/// Type containing triggered [`Event`] information for a given run of an [`Observer`]. This contains the
28
29
/// [`Event`] data itself. If it was triggered for a specific [`Entity`], it includes that as well. It also
@@ -70,6 +71,13 @@ impl<'w, E, B: Bundle> Trigger<'w, E, B> {
70
71
self . trigger . entity
71
72
}
72
73
74
+ /// Returns the components that triggered the observer, out of the
75
+ /// components defined in `B`. Does not necessarily include all of them as
76
+ /// `B` acts like an `OR` filter rather than an `AND` filter.
77
+ pub fn components ( & self ) -> & [ ComponentId ] {
78
+ & self . trigger . components
79
+ }
80
+
73
81
/// Returns the [`Entity`] that observed the triggered event.
74
82
/// This allows you to despawn the observer, ceasing observation.
75
83
///
@@ -193,14 +201,21 @@ impl ObserverDescriptor {
193
201
pub struct ObserverTrigger {
194
202
/// The [`Entity`] of the observer handling the trigger.
195
203
pub observer : Entity ,
196
-
197
- /// The [`ComponentId`] the trigger targeted.
204
+ /// The [`Event`] the trigger targeted.
198
205
pub event_type : ComponentId ,
199
-
206
+ /// The [`ComponentId`]s the trigger targeted.
207
+ components : SmallVec < [ ComponentId ; 2 ] > ,
200
208
/// The entity the trigger targeted.
201
209
pub entity : Entity ,
202
210
}
203
211
212
+ impl ObserverTrigger {
213
+ /// Returns the components that the trigger targeted.
214
+ pub fn components ( & self ) -> & [ ComponentId ] {
215
+ & self . components
216
+ }
217
+ }
218
+
204
219
// Map between an observer entity and its runner
205
220
type ObserverMap = EntityHashMap < ObserverRunner > ;
206
221
@@ -262,7 +277,7 @@ impl Observers {
262
277
mut world : DeferredWorld ,
263
278
event_type : ComponentId ,
264
279
entity : Entity ,
265
- components : impl Iterator < Item = ComponentId > ,
280
+ components : impl Iterator < Item = ComponentId > + Clone ,
266
281
data : & mut T ,
267
282
propagate : & mut bool ,
268
283
) {
@@ -279,12 +294,15 @@ impl Observers {
279
294
( world. into_deferred ( ) , observers)
280
295
} ;
281
296
297
+ let trigger_for_components = components. clone ( ) ;
298
+
282
299
let mut trigger_observer = |( & observer, runner) : ( & Entity , & ObserverRunner ) | {
283
300
( runner) (
284
301
world. reborrow ( ) ,
285
302
ObserverTrigger {
286
303
observer,
287
304
event_type,
305
+ components : components. clone ( ) . collect ( ) ,
288
306
entity,
289
307
} ,
290
308
data. into ( ) ,
@@ -302,7 +320,7 @@ impl Observers {
302
320
}
303
321
304
322
// Trigger observers listening to this trigger targeting a specific component
305
- components . for_each ( |id| {
323
+ trigger_for_components . for_each ( |id| {
306
324
if let Some ( component_observers) = observers. component_observers . get ( & id) {
307
325
component_observers
308
326
. map
@@ -552,8 +570,10 @@ mod tests {
552
570
use alloc:: vec;
553
571
554
572
use bevy_ptr:: OwningPtr ;
573
+ use bevy_utils:: HashMap ;
555
574
556
575
use crate as bevy_ecs;
576
+ use crate :: component:: ComponentId ;
557
577
use crate :: {
558
578
observer:: { EmitDynamicTrigger , Observer , ObserverDescriptor , ObserverState , OnReplace } ,
559
579
prelude:: * ,
@@ -1268,9 +1288,6 @@ mod tests {
1268
1288
1269
1289
#[ test]
1270
1290
fn observer_invalid_params ( ) {
1271
- #[ derive( Event ) ]
1272
- struct EventA ;
1273
-
1274
1291
#[ derive( Resource ) ]
1275
1292
struct ResA ;
1276
1293
@@ -1289,9 +1306,6 @@ mod tests {
1289
1306
1290
1307
#[ test]
1291
1308
fn observer_apply_deferred_from_param_set ( ) {
1292
- #[ derive( Event ) ]
1293
- struct EventA ;
1294
-
1295
1309
#[ derive( Resource ) ]
1296
1310
struct ResA ;
1297
1311
@@ -1309,4 +1323,35 @@ mod tests {
1309
1323
1310
1324
assert ! ( world. get_resource:: <ResA >( ) . is_some( ) ) ;
1311
1325
}
1326
+
1327
+ #[ test]
1328
+ fn observer_triggered_components ( ) {
1329
+ #[ derive( Resource , Default ) ]
1330
+ struct Counter ( HashMap < ComponentId , usize > ) ;
1331
+
1332
+ let mut world = World :: new ( ) ;
1333
+ world. init_resource :: < Counter > ( ) ;
1334
+ let a_id = world. register_component :: < A > ( ) ;
1335
+ let b_id = world. register_component :: < B > ( ) ;
1336
+
1337
+ world. add_observer (
1338
+ |trigger : Trigger < EventA , ( A , B ) > , mut counter : ResMut < Counter > | {
1339
+ for & component in trigger. components ( ) {
1340
+ * counter. 0 . entry ( component) . or_default ( ) += 1 ;
1341
+ }
1342
+ } ,
1343
+ ) ;
1344
+ world. flush ( ) ;
1345
+
1346
+ world. trigger_targets ( EventA , [ a_id, b_id] ) ;
1347
+ world. trigger_targets ( EventA , a_id) ;
1348
+ world. trigger_targets ( EventA , b_id) ;
1349
+ world. trigger_targets ( EventA , [ a_id, b_id] ) ;
1350
+ world. trigger_targets ( EventA , a_id) ;
1351
+ world. flush ( ) ;
1352
+
1353
+ let counter = world. resource :: < Counter > ( ) ;
1354
+ assert_eq ! ( 4 , * counter. 0 . get( & a_id) . unwrap( ) ) ;
1355
+ assert_eq ! ( 3 , * counter. 0 . get( & b_id) . unwrap( ) ) ;
1356
+ }
1312
1357
}
0 commit comments