Add World::trigger_ref and World::trigger_targets_ref (#14894)
# Objective Closes #14888. ## Solution Add non-consuming trigger functions: ```rust impl World { pub fn trigger_ref(&mut self, event: &mut impl Event); pub fn trigger_targets_ref(&mut self, event: &mut impl Event, targets: impl TriggerTargets); } ``` ## Testing - Added two new tests, `observer_trigger_ref` and `observer_trigger_targets_ref`. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
9386bd0114
commit
4682f33e0c
@ -349,16 +349,41 @@ impl World {
|
||||
self.spawn(Observer::new(system))
|
||||
}
|
||||
|
||||
/// Triggers the given `event`, which will run any observers watching for it.
|
||||
/// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
|
||||
///
|
||||
/// While event types commonly implement [`Copy`],
|
||||
/// those that don't will be consumed and will no longer be accessible.
|
||||
/// If you need to use the event after triggering it, use [`World::trigger_ref`] instead.
|
||||
pub fn trigger(&mut self, event: impl Event) {
|
||||
TriggerEvent { event, targets: () }.trigger(self);
|
||||
}
|
||||
|
||||
/// Triggers the given `event` for the given `targets`, which will run any observers watching for it.
|
||||
/// Triggers the given [`Event`] as a mutable reference, which will run any [`Observer`]s watching for it.
|
||||
///
|
||||
/// Compared to [`World::trigger`], this method is most useful when it's necessary to check
|
||||
/// or use the event after it has been modified by observers.
|
||||
pub fn trigger_ref(&mut self, event: &mut impl Event) {
|
||||
TriggerEvent { event, targets: () }.trigger_ref(self);
|
||||
}
|
||||
|
||||
/// Triggers the given [`Event`] for the given `targets`, which will run any [`Observer`]s watching for it.
|
||||
///
|
||||
/// While event types commonly implement [`Copy`],
|
||||
/// those that don't will be consumed and will no longer be accessible.
|
||||
/// If you need to use the event after triggering it, use [`World::trigger_targets_ref`] instead.
|
||||
pub fn trigger_targets(&mut self, event: impl Event, targets: impl TriggerTargets) {
|
||||
TriggerEvent { event, targets }.trigger(self);
|
||||
}
|
||||
|
||||
/// Triggers the given [`Event`] as a mutable reference for the given `targets`,
|
||||
/// which will run any [`Observer`]s watching for it.
|
||||
///
|
||||
/// Compared to [`World::trigger_targets`], this method is most useful when it's necessary to check
|
||||
/// or use the event after it has been modified by observers.
|
||||
pub fn trigger_targets_ref(&mut self, event: &mut impl Event, targets: impl TriggerTargets) {
|
||||
TriggerEvent { event, targets }.trigger_ref(self);
|
||||
}
|
||||
|
||||
/// Register an observer to the cache, called when an observer is created
|
||||
pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
|
||||
// SAFETY: References do not alias.
|
||||
@ -507,6 +532,11 @@ mod tests {
|
||||
#[derive(Event)]
|
||||
struct EventA;
|
||||
|
||||
#[derive(Event)]
|
||||
struct EventWithData {
|
||||
counter: usize,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
struct Order(Vec<&'static str>);
|
||||
|
||||
@ -652,6 +682,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn observer_trigger_ref() {
|
||||
let mut world = World::new();
|
||||
|
||||
world.observe(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 1);
|
||||
world.observe(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 2);
|
||||
world.observe(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 4);
|
||||
// This flush is required for the last observer to be called when triggering the event,
|
||||
// due to `World::observe` returning `WorldEntityMut`.
|
||||
world.flush();
|
||||
|
||||
let mut event = EventWithData { counter: 0 };
|
||||
world.trigger_ref(&mut event);
|
||||
assert_eq!(7, event.counter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn observer_trigger_targets_ref() {
|
||||
let mut world = World::new();
|
||||
|
||||
world.observe(|mut trigger: Trigger<EventWithData, A>| trigger.event_mut().counter += 1);
|
||||
world.observe(|mut trigger: Trigger<EventWithData, B>| trigger.event_mut().counter += 2);
|
||||
world.observe(|mut trigger: Trigger<EventWithData, A>| trigger.event_mut().counter += 4);
|
||||
// This flush is required for the last observer to be called when triggering the event,
|
||||
// due to `World::observe` returning `WorldEntityMut`.
|
||||
world.flush();
|
||||
|
||||
let mut event = EventWithData { counter: 0 };
|
||||
let component_a = world.init_component::<A>();
|
||||
world.trigger_targets_ref(&mut event, component_a);
|
||||
assert_eq!(5, event.counter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn observer_multiple_listeners() {
|
||||
let mut world = World::new();
|
||||
|
||||
@ -21,6 +21,13 @@ impl<E: Event, Targets: TriggerTargets> TriggerEvent<E, Targets> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event, Targets: TriggerTargets> TriggerEvent<&mut E, Targets> {
|
||||
pub(super) fn trigger_ref(self, world: &mut World) {
|
||||
let event_type = world.init_component::<E>();
|
||||
trigger_event(world, event_type, self.event, self.targets);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event, Targets: TriggerTargets + Send + Sync + 'static> Command
|
||||
for TriggerEvent<E, Targets>
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user