kaige_ecs/internals/
event.rs

1use 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/// Events emitted by a world to subscribers. See `World.subscribe(Sender, EntityFilter)`.
13#[derive(Debug, Clone)]
14pub enum Event {
15    /// A new archetype has been created.
16    ArchetypeCreated(ArchetypeIndex),
17    /// An entity has been inserted into an archetype.
18    EntityInserted(Entity, ArchetypeIndex),
19    /// An entity has been removed from an archetype.
20    EntityRemoved(Entity, ArchetypeIndex),
21}
22
23/// Describes a type which can send entity events.
24pub trait EventSender: Send + Sync {
25    /// Sends the given event to all listeners.
26    /// Returns `true` if the sender is still alive.
27    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}