1use alloc::vec::Vec;
2use itertools::Itertools;
3
4use crate::{
5 archetype::{Archetype, Slice, Storage},
6 component::{ComponentDesc, ComponentKey, ComponentValue},
7 filter::StaticFilter,
8 sink::Sink,
9 Component, Entity,
10};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Event {
15 pub id: Entity,
17 pub key: ComponentKey,
19 pub kind: EventKind,
21}
22
23impl Event {
24 pub fn new(id: Entity, key: ComponentKey, kind: EventKind) -> Self {
26 Self { id, key, kind }
27 }
28
29 pub fn modified(id: Entity, key: ComponentKey) -> Self {
31 Self::new(id, key, EventKind::Modified)
32 }
33
34 pub fn added(id: Entity, key: ComponentKey) -> Self {
36 Self::new(id, key, EventKind::Added)
37 }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub enum EventKind {
43 Added,
45 Removed,
47 Modified,
49}
50
51pub struct EventData<'a> {
53 pub ids: &'a [Entity],
55 pub slots: Slice,
57 pub key: ComponentKey,
59}
60
61pub trait EventSubscriber: ComponentValue {
67 fn on_added(&self, storage: &Storage, event: &EventData);
69 fn on_modified(&self, event: &EventData);
77 fn on_removed(&self, storage: &Storage, event: &EventData);
79
80 fn is_connected(&self) -> bool;
82
83 #[inline]
85 fn matches_arch(&self, _: &Archetype) -> bool {
86 true
87 }
88
89 #[inline]
91 fn matches_component(&self, _: ComponentDesc) -> bool {
92 true
93 }
94
95 fn filter<F>(self, func: F) -> FilterFunc<Self, F>
97 where
98 Self: Sized,
99 F: Fn(EventKind, &EventData) -> bool,
100 {
101 FilterFunc {
102 subscriber: self,
103 filter: func,
104 }
105 }
106
107 fn filter_arch<F: StaticFilter>(self, filter: F) -> FilterArch<Self, F>
109 where
110 Self: Sized,
111 {
112 FilterArch {
113 filter,
114 subscriber: self,
115 }
116 }
117
118 fn filter_components<I: IntoIterator<Item = ComponentKey>>(
120 self,
121 components: I,
122 ) -> FilterComponents<Self>
123 where
124 Self: Sized,
125 {
126 FilterComponents {
127 components: components.into_iter().collect(),
128 subscriber: self,
129 }
130 }
131
132 fn filter_event_kind(self, event_kind: EventKind) -> FilterEventKind<Self>
134 where
135 Self: Sized,
136 {
137 FilterEventKind {
138 event_kind,
139 subscriber: self,
140 }
141 }
142}
143
144impl<S> EventSubscriber for S
145where
146 S: 'static + Send + Sync + Sink<Event>,
147{
148 fn on_added(&self, _: &Storage, event: &EventData) {
149 for &id in event.ids {
150 self.send(Event {
151 id,
152 key: event.key,
153 kind: EventKind::Added,
154 });
155 }
156 }
157
158 fn on_modified(&self, event: &EventData) {
159 for &id in event.ids {
160 self.send(Event {
161 id,
162 key: event.key,
163 kind: EventKind::Modified,
164 });
165 }
166 }
167
168 fn on_removed(&self, _: &Storage, event: &EventData) {
169 for &id in event.ids {
170 self.send(Event {
171 id,
172 key: event.key,
173 kind: EventKind::Removed,
174 });
175 }
176 }
177
178 fn is_connected(&self) -> bool {
179 <Self as Sink<Event>>::is_connected(self)
180 }
181}
182
183pub struct WithValue<T, S> {
191 component: Component<T>,
192 sink: S,
193}
194
195impl<T, S> WithValue<T, S> {
196 pub fn new(component: Component<T>, sink: S) -> Self {
198 Self { component, sink }
199 }
200}
201
202impl<T: ComponentValue + Clone, S: 'static + Send + Sync + Sink<(Event, T)>> EventSubscriber
203 for WithValue<T, S>
204{
205 fn on_added(&self, storage: &Storage, event: &EventData) {
206 let values = storage.downcast_ref::<T>();
207 for (&id, slot) in event.ids.iter().zip_eq(event.slots.as_range()) {
208 let value = values[slot].clone();
209
210 self.sink.send((
211 Event {
212 id,
213 key: event.key,
214 kind: EventKind::Added,
215 },
216 value,
217 ));
218 }
219 }
220
221 fn on_modified(&self, _: &EventData) {}
222
223 fn on_removed(&self, storage: &Storage, event: &EventData) {
224 let values = storage.downcast_ref::<T>();
225 for (&id, slot) in event.ids.iter().zip_eq(event.slots.as_range()) {
226 let value = values[slot].clone();
227
228 self.sink.send((
229 Event {
230 id,
231 key: event.key,
232 kind: EventKind::Removed,
233 },
234 value,
235 ));
236 }
237 }
238
239 fn is_connected(&self) -> bool {
240 self.sink.is_connected()
241 }
242
243 fn matches_component(&self, desc: ComponentDesc) -> bool {
244 self.component.desc() == desc
245 }
246
247 fn matches_arch(&self, arch: &Archetype) -> bool {
248 arch.has(self.component.key())
249 }
250}
251
252pub struct FilterArch<S, F> {
254 filter: F,
255 subscriber: S,
256}
257
258impl<S, F> EventSubscriber for FilterArch<S, F>
259where
260 S: EventSubscriber,
261 F: ComponentValue + StaticFilter,
262{
263 fn on_added(&self, storage: &Storage, event: &EventData) {
264 self.subscriber.on_added(storage, event)
265 }
266
267 fn on_modified(&self, event: &EventData) {
268 self.subscriber.on_modified(event);
269 }
270
271 fn on_removed(&self, storage: &Storage, event: &EventData) {
272 self.subscriber.on_removed(storage, event)
273 }
274
275 #[inline]
276 fn is_connected(&self) -> bool {
277 self.subscriber.is_connected()
278 }
279
280 #[inline]
281 fn matches_arch(&self, arch: &Archetype) -> bool {
282 self.filter.filter_static(arch) && self.subscriber.matches_arch(arch)
283 }
284
285 #[inline]
286 fn matches_component(&self, desc: ComponentDesc) -> bool {
287 self.subscriber.matches_component(desc)
288 }
289}
290
291pub struct FilterFunc<S, F> {
293 filter: F,
294 subscriber: S,
295}
296
297impl<S, F> EventSubscriber for FilterFunc<S, F>
298where
299 S: EventSubscriber,
300 F: ComponentValue + Fn(EventKind, &EventData) -> bool,
301{
302 fn on_added(&self, storage: &Storage, event: &EventData) {
303 if (self.filter)(EventKind::Added, event) {
304 self.subscriber.on_added(storage, event)
305 }
306 }
307
308 fn on_modified(&self, event: &EventData) {
309 if (self.filter)(EventKind::Modified, event) {
310 self.subscriber.on_modified(event)
311 }
312 }
313
314 fn on_removed(&self, storage: &Storage, event: &EventData) {
315 if (self.filter)(EventKind::Removed, event) {
316 self.subscriber.on_removed(storage, event)
317 }
318 }
319
320 #[inline]
321 fn matches_arch(&self, arch: &Archetype) -> bool {
322 self.subscriber.matches_arch(arch)
323 }
324
325 #[inline]
326 fn matches_component(&self, desc: ComponentDesc) -> bool {
327 self.subscriber.matches_component(desc)
328 }
329
330 #[inline]
331 fn is_connected(&self) -> bool {
332 self.subscriber.is_connected()
333 }
334}
335
336pub struct FilterComponents<S> {
338 components: Vec<ComponentKey>,
339 subscriber: S,
340}
341
342impl<S> EventSubscriber for FilterComponents<S>
343where
344 S: EventSubscriber,
345{
346 fn on_added(&self, storage: &Storage, event: &EventData) {
347 self.subscriber.on_added(storage, event)
348 }
349
350 fn on_modified(&self, event: &EventData) {
351 self.subscriber.on_modified(event)
352 }
353
354 fn on_removed(&self, storage: &Storage, event: &EventData) {
355 self.subscriber.on_removed(storage, event)
356 }
357
358 #[inline]
359 fn matches_arch(&self, arch: &Archetype) -> bool {
360 self.components.iter().any(|&key| arch.has(key)) && self.subscriber.matches_arch(arch)
361 }
362
363 #[inline]
364 fn matches_component(&self, desc: ComponentDesc) -> bool {
365 self.components.contains(&desc.key()) && self.subscriber.matches_component(desc)
366 }
367
368 #[inline]
369 fn is_connected(&self) -> bool {
370 self.subscriber.is_connected()
371 }
372}
373
374pub struct FilterEventKind<S> {
376 event_kind: EventKind,
377 subscriber: S,
378}
379
380impl<S> EventSubscriber for FilterEventKind<S>
381where
382 S: EventSubscriber,
383{
384 fn on_added(&self, storage: &Storage, event: &EventData) {
385 if self.event_kind == EventKind::Added {
386 self.subscriber.on_added(storage, event)
387 }
388 }
389
390 fn on_modified(&self, event: &EventData) {
391 if self.event_kind == EventKind::Modified {
392 self.subscriber.on_modified(event)
393 }
394 }
395
396 fn on_removed(&self, storage: &Storage, event: &EventData) {
397 if self.event_kind == EventKind::Removed {
398 self.subscriber.on_removed(storage, event)
399 }
400 }
401
402 fn is_connected(&self) -> bool {
403 self.subscriber.is_connected()
404 }
405}
406
407pub struct WithIds<S> {
409 sink: S,
410}
411
412impl<S> WithIds<S> {
413 pub fn new(sink: S) -> Self {
415 Self { sink }
416 }
417}
418
419impl<S: Sink<Entity>> Sink<Event> for WithIds<S> {
420 fn send(&self, event: Event) {
421 self.sink.send(event.id);
422 }
423
424 fn is_connected(&self) -> bool {
425 self.sink.is_connected()
426 }
427}