Skip to main content

pebble/ecs/
events.rs

1use crate::ecs::{
2    resources::{Read, Resources, Write},
3    system_param::SystemParam,
4};
5
6pub struct Events<T> {
7    current: Vec<(usize, T)>,
8    previous: Vec<(usize, T)>,
9    next_id: usize,
10}
11
12impl<T> Default for Events<T> {
13    fn default() -> Self {
14        Self { current: Vec::new(), previous: Vec::new(), next_id: 0 }
15    }
16}
17
18impl<T> Events<T> {
19    pub fn send(&mut self, event: T) {
20        self.current.push((self.next_id, event));
21        self.next_id += 1;
22    }
23
24    pub(crate) fn update(&mut self) {
25        self.previous = std::mem::take(&mut self.current);
26    }
27}
28
29pub struct EventReader<'a, T: 'static> {
30    events: Read<'a, Events<T>>,
31    last_seen: &'a mut usize,
32}
33
34impl<'a, T: 'static> EventReader<'a, T> {
35    pub fn iter(&mut self) -> impl Iterator<Item = &T> + '_ {
36        let seen = *self.last_seen;
37        let unread: Vec<&T> = self
38            .events
39            .previous
40            .iter()
41            .chain(self.events.current.iter())
42            .filter(|(id, _)| *id >= seen)
43            .map(|(_, event)| event)
44            .collect();
45        *self.last_seen = self.events.next_id;
46        unread.into_iter()
47    }
48
49    pub fn is_empty(&self) -> bool {
50        let seen = *self.last_seen;
51        !self.events.previous.iter().chain(self.events.current.iter()).any(|(id, _)| *id >= seen)
52    }
53}
54
55impl<T: 'static> SystemParam for EventReader<'static, T> {
56    type Item<'a> = EventReader<'a, T>;
57    type State = usize;
58
59    fn fetch<'a>(_world: &'a hecs::World, resources: &'a Resources, state: &'a mut Self::State) -> Self::Item<'a> {
60        EventReader { events: Read { inner: resources.get::<Events<T>>() }, last_seen: state }
61    }
62}
63
64impl<T> SystemParam for Option<EventReader<'static, T>>
65where
66    T: 'static + Sync + Send,
67{
68    type Item<'a> = Option<EventReader<'a, T>>;
69    type State = usize;
70
71    fn fetch<'a>(world: &'a hecs::World, resources: &'a Resources, state: &'a mut Self::State) -> Self::Item<'a> {
72        resources.contains::<Events<T>>().then(|| EventReader::fetch(world, resources, state))
73    }
74}
75
76pub struct EventWriter<'a, T: 'static> {
77    events: Write<'a, Events<T>>,
78}
79
80impl<'a, T: 'static> EventWriter<'a, T> {
81    pub fn send(&mut self, event: T) {
82        self.events.send(event);
83    }
84}
85
86impl<T: 'static> SystemParam for EventWriter<'static, T> {
87    type Item<'a> = EventWriter<'a, T>;
88    type State = ();
89
90    fn fetch<'a>(_world: &'a hecs::World, resources: &'a Resources, _state: &'a mut Self::State) -> Self::Item<'a> {
91        EventWriter { events: Write { inner: resources.get_mut::<Events<T>>() } }
92    }
93}
94
95impl<T> SystemParam for Option<EventWriter<'static, T>>
96where
97    T: 'static + Sync + Send,
98{
99    type Item<'a> = Option<EventWriter<'a, T>>;
100    type State = ();
101
102    fn fetch<'a>(world: &'a hecs::World, resources: &'a Resources, state: &'a mut Self::State) -> Self::Item<'a> {
103        resources.contains::<Events<T>>().then(|| EventWriter::fetch(world, resources, state))
104    }
105}
106
107pub(crate) fn age_events<T: Send + Sync + 'static>(mut events: Write<Events<T>>) {
108    events.update();
109}