use bevy_ecs::ResMut; use std::marker::PhantomData; #[derive(Debug)] struct EventInstance { pub event_count: usize, pub event: T, } #[derive(Debug)] enum State { A, B, } /// An event collection that represents the events that occurred within the last two [Events::update] calls. Events can be cheaply read using /// an [EventReader]. This collection is meant to be paired with a system that calls [Events::update] exactly once per update/frame. [Events::update_system] /// is a system that does this. [EventReader]s are expected to read events from this collection at least once per update/frame. If events are not handled /// within one frame/update, they will be dropped. /// /// # Example /// ``` /// use bevy_app::Events; /// /// struct MyEvent { /// value: usize /// } /// /// // setup /// let mut events = Events::::default(); /// let mut reader = events.get_reader(); /// /// // run this once per update/frame /// events.update(); /// /// // somewhere else: send an event /// events.send(MyEvent { value: 1 }); /// /// // somewhere else: read the events /// for event in reader.iter(&events) { /// assert_eq!(event.value, 1) /// } /// /// // events are only processed once per reader /// assert_eq!(reader.iter(&events).count(), 0); /// ``` /// /// # Details /// /// [Events] is implemented using a double buffer. Each call to [Events::update] swaps buffers and clears out the oldest buffer. /// [EventReader]s that read at least once per update will never drop events. [EventReader]s that read once within two updates might /// still receive some events. [EventReader]s that read after two updates are guaranteed to drop all events that occurred before those updates. /// /// The buffers in [Events] will grow indefinitely if [Events::update] is never called. /// /// An alternative call pattern would be to call [Events::update] manually across frames to control when events are cleared. However /// this complicates consumption #[derive(Debug)] pub struct Events { events_a: Vec>, events_b: Vec>, a_start_event_count: usize, b_start_event_count: usize, event_count: usize, state: State, } impl Default for Events { fn default() -> Self { Events { a_start_event_count: 0, b_start_event_count: 0, event_count: 0, events_a: Vec::new(), events_b: Vec::new(), state: State::A, } } } fn map_instance_event(event_instance: &EventInstance) -> &T { &event_instance.event } /// Reads events of type `T` in order and tracks which events have already been read. pub struct EventReader { last_event_count: usize, _marker: PhantomData, } impl Default for EventReader { fn default() -> Self { Self { last_event_count: 0, _marker: PhantomData::default(), } } } impl EventReader { /// Iterates over the events this EventReader has not seen yet. This updates the EventReader's /// event counter, which means subsequent event reads will not include events that happened before now. pub fn iter<'a>(&mut self, events: &'a Events) -> impl DoubleEndedIterator { // if the reader has seen some of the events in a buffer, find the proper index offset. // otherwise read all events in the buffer let a_index = if self.last_event_count > events.a_start_event_count { self.last_event_count - events.a_start_event_count } else { 0 }; let b_index = if self.last_event_count > events.b_start_event_count { self.last_event_count - events.b_start_event_count } else { 0 }; self.last_event_count = events.event_count; match events.state { State::A => events .events_b .get(b_index..) .unwrap_or_else(|| &[]) .iter() .map(map_instance_event) .chain( events .events_a .get(a_index..) .unwrap_or_else(|| &[]) .iter() .map(map_instance_event), ), State::B => events .events_a .get(a_index..) .unwrap_or_else(|| &[]) .iter() .map(map_instance_event) .chain( events .events_b .get(b_index..) .unwrap_or_else(|| &[]) .iter() .map(map_instance_event), ), } } /// Retrieves the latest event that this EventReader hasn't seen yet. This updates the EventReader's /// event counter, which means subsequent event reads will not include events that happened before now. pub fn latest<'a>(&mut self, events: &'a Events) -> Option<&'a T> { self.iter(events).rev().next() } /// Retrieves the latest event that matches the given `predicate` that this reader hasn't seen yet. This updates the EventReader's /// event counter, which means subsequent event reads will not include events that happened before now. pub fn find_latest<'a>( &mut self, events: &'a Events, predicate: impl FnMut(&&T) -> bool, ) -> Option<&'a T> { self.iter(events).rev().find(predicate) } /// Retrieves the earliest event in `events` that this reader hasn't seen yet. This updates the EventReader's /// event counter, which means subsequent event reads will not include events that happened before now. pub fn earliest<'a>(&mut self, events: &'a Events) -> Option<&'a T> { self.iter(events).next() } } impl Events { /// "Sends" an `event` by writing it to the current event buffer. [EventReader]s can then read the event. pub fn send(&mut self, event: T) { let event_instance = EventInstance { event, event_count: self.event_count, }; match self.state { State::A => self.events_a.push(event_instance), State::B => self.events_b.push(event_instance), } self.event_count += 1; } /// Gets a new [EventReader]. This will include all events already in the event buffers. pub fn get_reader(&self) -> EventReader { EventReader { last_event_count: 0, _marker: PhantomData, } } /// Gets a new [EventReader]. This will ignore all events already in the event buffers. It will read all future events. pub fn get_reader_current(&self) -> EventReader { EventReader { last_event_count: self.event_count, _marker: PhantomData, } } /// Swaps the event buffers and clears the oldest event buffer. In general, this should be called once per frame/update. pub fn update(&mut self) { match self.state { State::A => { self.events_b = Vec::new(); self.state = State::B; self.b_start_event_count = self.event_count; } State::B => { self.events_a = Vec::new(); self.state = State::A; self.a_start_event_count = self.event_count; } } } /// A system that calls [Events::update] once per frame. pub fn update_system(mut events: ResMut) { events.update(); } /// Removes all events. pub fn clear(&mut self) { self.events_a.clear(); self.events_b.clear(); } /// Creates a draining iterator that removes all events. pub fn drain<'a>(&'a mut self) -> impl Iterator + 'a { let map = |i: EventInstance| i.event; match self.state { State::A => self .events_b .drain(..) .map(map) .chain(self.events_a.drain(..).map(map)), State::B => self .events_a .drain(..) .map(map) .chain(self.events_b.drain(..).map(map)), } } pub fn extend(&mut self, events: I) where I: Iterator, { for event in events { self.send(event); } } /// Iterates over events that happened since the last "update" call. /// WARNING: You probably don't want to use this call. In most cases you should use an `EventReader`. You should only use /// this if you know you only need to consume events between the last `update()` call and your call to `iter_current_update_events`. /// If events happen outside that window, they will not be handled. For example, any events that happen after this call and before /// the next `update()` call will be dropped. pub fn iter_current_update_events(&self) -> impl DoubleEndedIterator { match self.state { State::A => self.events_a.iter().map(map_instance_event), State::B => self.events_b.iter().map(map_instance_event), } } } #[cfg(test)] mod tests { use super::*; #[derive(Copy, Clone, PartialEq, Eq, Debug)] struct TestEvent { i: usize, } #[test] fn test_events() { let mut events = Events::::default(); let event_0 = TestEvent { i: 0 }; let event_1 = TestEvent { i: 1 }; let event_2 = TestEvent { i: 2 }; // this reader will miss event_0 and event_1 because it wont read them over the course of two updates let mut reader_missed = events.get_reader(); let mut reader_a = events.get_reader(); events.send(event_0); assert_eq!( get_events(&events, &mut reader_a), vec![event_0], "reader_a created before event receives event" ); assert_eq!( get_events(&events, &mut reader_a), vec![], "second iteration of reader_a created before event results in zero events" ); let mut reader_b = events.get_reader(); assert_eq!( get_events(&events, &mut reader_b), vec![event_0], "reader_b created after event receives event" ); assert_eq!( get_events(&events, &mut reader_b), vec![], "second iteration of reader_b created after event results in zero events" ); events.send(event_1); let mut reader_c = events.get_reader(); assert_eq!( get_events(&events, &mut reader_c), vec![event_0, event_1], "reader_c created after two events receives both events" ); assert_eq!( get_events(&events, &mut reader_c), vec![], "second iteration of reader_c created after two event results in zero events" ); assert_eq!( get_events(&events, &mut reader_a), vec![event_1], "reader_a receives next unread event" ); events.update(); let mut reader_d = events.get_reader(); events.send(event_2); assert_eq!( get_events(&events, &mut reader_a), vec![event_2], "reader_a receives event created after update" ); assert_eq!( get_events(&events, &mut reader_b), vec![event_1, event_2], "reader_b receives events created before and after update" ); assert_eq!( get_events(&events, &mut reader_d), vec![event_0, event_1, event_2], "reader_d receives all events created before and after update" ); events.update(); assert_eq!( get_events(&events, &mut reader_missed), vec![event_2], "reader_missed missed events unread after to update() calls" ); } fn get_events( events: &Events, reader: &mut EventReader, ) -> Vec { reader.iter(events).cloned().collect::>() } }