bevy_ecs/observer/
trigger_event.rs1use crate::{
2 component::ComponentId,
3 entity::Entity,
4 event::Event,
5 world::{Command, DeferredWorld, World},
6};
7
8pub struct TriggerEvent<E, Targets: TriggerTargets = ()> {
10 pub event: E,
12
13 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
39pub 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 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 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 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
102pub trait TriggerTargets {
110 fn components(&self) -> &[ComponentId];
112
113 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}