kaige_ecs/internals/
event.rs1use std::{fmt::Debug, iter::Iterator, sync::Arc};
2
3use super::{
4 entity::Entity,
5 query::filter::LayoutFilter,
6 storage::{
7 archetype::{Archetype, ArchetypeIndex},
8 component::ComponentTypeId,
9 },
10};
11
12#[derive(Debug, Clone)]
14pub enum Event {
15 ArchetypeCreated(ArchetypeIndex),
17 EntityInserted(Entity, ArchetypeIndex),
19 EntityRemoved(Entity, ArchetypeIndex),
21}
22
23pub trait EventSender: Send + Sync {
25 fn send(&self, event: Event) -> bool;
28}
29
30#[cfg(feature = "crossbeam-events")]
31impl EventSender for crossbeam_channel::Sender<Event> {
32 fn send(&self, event: Event) -> bool {
33 !matches!(
34 self.try_send(event),
35 Err(crossbeam_channel::TrySendError::Disconnected(_))
36 )
37 }
38}
39
40#[derive(Clone)]
41pub(crate) struct Subscriber {
42 filter: Arc<dyn LayoutFilter + Send + Sync>,
43 sender: Arc<dyn EventSender>,
44}
45
46impl Subscriber {
47 pub(crate) fn new<F, S>(filter: F, sender: S) -> Self
48 where
49 F: LayoutFilter + Send + Sync + 'static,
50 S: EventSender + 'static,
51 {
52 Self {
53 filter: Arc::new(filter),
54 sender: Arc::new(sender),
55 }
56 }
57
58 pub(crate) fn is_interested(&self, archetype: &Archetype) -> bool {
59 self.filter
60 .matches_layout(archetype.layout().component_types())
61 .is_pass()
62 }
63
64 pub(crate) fn send(&self, message: Event) -> bool {
65 self.sender.send(message)
66 }
67}
68
69#[derive(Clone, Default)]
70pub(crate) struct Subscribers {
71 subscribers: Vec<Subscriber>,
72}
73
74impl Subscribers {
75 pub fn push(&mut self, subscriber: Subscriber) {
76 self.subscribers.push(subscriber);
77 }
78
79 pub fn send(&mut self, message: Event) {
80 for i in (0..self.subscribers.len()).rev() {
81 if !self.subscribers[i].send(message.clone()) {
82 self.subscribers.swap_remove(i);
83 }
84 }
85 }
86
87 pub fn matches_layout(&self, components: &[ComponentTypeId]) -> Self {
88 Self {
89 subscribers: self
90 .subscribers
91 .iter()
92 .filter(|sub| sub.filter.matches_layout(components).is_pass())
93 .cloned()
94 .collect(),
95 }
96 }
97}
98
99impl Debug for Subscribers {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 f.debug_struct("Subscribers")
102 .field("len", &self.subscribers.len())
103 .finish()
104 }
105}