bevy_ecs/observer/
trigger_event.rs

1use crate::{
2    component::ComponentId,
3    entity::Entity,
4    event::Event,
5    world::{Command, DeferredWorld, World},
6};
7
8/// A [`Command`] that emits a given trigger for a given set of targets.
9pub struct TriggerEvent<E, Targets: TriggerTargets = ()> {
10    /// The event to trigger.
11    pub event: E,
12
13    /// The targets to trigger the event for.
14    pub targets: Targets,
15}
16
17impl<E: Event, Targets: TriggerTargets> TriggerEvent<E, Targets> {
18    pub(super) fn trigger(mut self, world: &mut World) {
19        let event_type = world.register_component::<E>();
20        trigger_event(world, event_type, &mut self.event, self.targets);
21    }
22}
23
24impl<E: Event, Targets: TriggerTargets> TriggerEvent<&mut E, Targets> {
25    pub(super) fn trigger_ref(self, world: &mut World) {
26        let event_type = world.register_component::<E>();
27        trigger_event(world, event_type, self.event, self.targets);
28    }
29}
30
31impl<E: Event, Targets: TriggerTargets + Send + Sync + 'static> Command
32    for TriggerEvent<E, Targets>
33{
34    fn apply(self, world: &mut World) {
35        self.trigger(world);
36    }
37}
38
39/// Emit a trigger for a dynamic component id. This is unsafe and must be verified manually.
40pub struct EmitDynamicTrigger<T, Targets: TriggerTargets = ()> {
41    event_type: ComponentId,
42    event_data: T,
43    targets: Targets,
44}
45
46impl<E, Targets: TriggerTargets> EmitDynamicTrigger<E, Targets> {
47    /// Sets the event type of the resulting trigger, used for dynamic triggers
48    /// # Safety
49    /// Caller must ensure that the component associated with `event_type` is accessible as E
50    pub unsafe fn new_with_id(event_type: ComponentId, event_data: E, targets: Targets) -> Self {
51        Self {
52            event_type,
53            event_data,
54            targets,
55        }
56    }
57}
58
59impl<E: Event, Targets: TriggerTargets + Send + Sync + 'static> Command
60    for EmitDynamicTrigger<E, Targets>
61{
62    fn apply(mut self, world: &mut World) {
63        trigger_event(world, self.event_type, &mut self.event_data, self.targets);
64    }
65}
66
67#[inline]
68fn trigger_event<E: Event, Targets: TriggerTargets>(
69    world: &mut World,
70    event_type: ComponentId,
71    event_data: &mut E,
72    targets: Targets,
73) {
74    let mut world = DeferredWorld::from(world);
75    if targets.entities().is_empty() {
76        // SAFETY: T is accessible as the type represented by self.trigger, ensured in `Self::new`
77        unsafe {
78            world.trigger_observers_with_data::<_, E::Traversal>(
79                event_type,
80                Entity::PLACEHOLDER,
81                targets.components(),
82                event_data,
83                false,
84            );
85        };
86    } else {
87        for target in targets.entities() {
88            // SAFETY: T is accessible as the type represented by self.trigger, ensured in `Self::new`
89            unsafe {
90                world.trigger_observers_with_data::<_, E::Traversal>(
91                    event_type,
92                    *target,
93                    targets.components(),
94                    event_data,
95                    E::AUTO_PROPAGATE,
96                );
97            };
98        }
99    }
100}
101
102/// Represents a collection of targets for a specific [`Trigger`] of an [`Event`]. Targets can be of type [`Entity`] or [`ComponentId`].
103///
104/// When a trigger occurs for a given event and [`TriggerTargets`], any [`Observer`] that watches for that specific event-target combination
105/// will run.
106///
107/// [`Trigger`]: crate::observer::Trigger
108/// [`Observer`]: crate::observer::Observer
109pub trait TriggerTargets {
110    /// The components the trigger should target.
111    fn components(&self) -> &[ComponentId];
112
113    /// The entities the trigger should target.
114    fn entities(&self) -> &[Entity];
115}
116
117impl TriggerTargets for () {
118    fn components(&self) -> &[ComponentId] {
119        &[]
120    }
121
122    fn entities(&self) -> &[Entity] {
123        &[]
124    }
125}
126
127impl TriggerTargets for Entity {
128    fn components(&self) -> &[ComponentId] {
129        &[]
130    }
131
132    fn entities(&self) -> &[Entity] {
133        core::slice::from_ref(self)
134    }
135}
136
137impl TriggerTargets for Vec<Entity> {
138    fn components(&self) -> &[ComponentId] {
139        &[]
140    }
141
142    fn entities(&self) -> &[Entity] {
143        self.as_slice()
144    }
145}
146
147impl<const N: usize> TriggerTargets for [Entity; N] {
148    fn components(&self) -> &[ComponentId] {
149        &[]
150    }
151
152    fn entities(&self) -> &[Entity] {
153        self.as_slice()
154    }
155}
156
157impl TriggerTargets for ComponentId {
158    fn components(&self) -> &[ComponentId] {
159        core::slice::from_ref(self)
160    }
161
162    fn entities(&self) -> &[Entity] {
163        &[]
164    }
165}
166
167impl TriggerTargets for Vec<ComponentId> {
168    fn components(&self) -> &[ComponentId] {
169        self.as_slice()
170    }
171
172    fn entities(&self) -> &[Entity] {
173        &[]
174    }
175}
176
177impl<const N: usize> TriggerTargets for [ComponentId; N] {
178    fn components(&self) -> &[ComponentId] {
179        self.as_slice()
180    }
181
182    fn entities(&self) -> &[Entity] {
183        &[]
184    }
185}
186
187impl TriggerTargets for &Vec<Entity> {
188    fn components(&self) -> &[ComponentId] {
189        &[]
190    }
191
192    fn entities(&self) -> &[Entity] {
193        self.as_slice()
194    }
195}