2020-04-06 23:15:59 +00:00
use legion ::prelude ::{ Resources , Schedulable , SystemBuilder } ;
2020-03-30 05:44:38 +00:00
use std ::marker ::PhantomData ;
struct EventInstance < T > {
pub event_count : usize ,
pub event : T ,
}
enum State {
A ,
B ,
}
2020-04-01 01:04:54 +00:00
/// 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::build_update_system]
/// will produce 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::core::event::Events;
2020-04-04 19:43:16 +00:00
///
2020-04-01 01:04:54 +00:00
/// struct MyEvent {
/// value: usize
/// }
///
/// // setup
/// let mut events = Events::<MyEvent>::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 events.iter(&mut reader) {
/// assert_eq!(event.value, 1)
/// }
///
/// // events are only processed once per reader
/// assert_eq!(events.iter(&mut reader).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
pub struct Events < T >
2020-03-30 05:44:38 +00:00
where
T : Send + Sync + 'static ,
{
events_a : Vec < EventInstance < T > > ,
events_b : Vec < EventInstance < T > > ,
a_start_event_count : usize ,
b_start_event_count : usize ,
event_count : usize ,
state : State ,
}
2020-04-01 01:04:54 +00:00
impl < T > Default for Events < T >
2020-03-30 05:44:38 +00:00
where
T : Send + Sync + 'static ,
{
fn default ( ) -> Self {
2020-04-01 01:04:54 +00:00
Events {
2020-03-30 05:44:38 +00:00
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_event_instance < T > ( event_instance : & EventInstance < T > ) -> & T
where
T : Send + Sync + 'static ,
{
& event_instance . event
}
2020-04-01 01:04:54 +00:00
pub struct EventReader < T > {
2020-03-30 05:44:38 +00:00
last_event_count : usize ,
_marker : PhantomData < T > ,
}
2020-04-01 01:04:54 +00:00
impl < T > Events < T >
2020-03-30 05:44:38 +00:00
where
T : Send + Sync + 'static ,
{
2020-04-01 01:04:54 +00:00
/// "Sends" an `event` by writing it to the current event buffer. [EventReader]s can then read the event.
2020-03-30 21:53:32 +00:00
pub fn send ( & mut self , event : T ) {
2020-03-30 05:44:38 +00:00
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 ;
}
2020-04-01 01:04:54 +00:00
/// Iterates over the events the `event_reader` has not seen yet.
pub fn iter ( & self , event_reader : & mut EventReader < T > ) -> impl DoubleEndedIterator < Item = & T > {
// 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 event_reader . last_event_count > self . a_start_event_count {
event_reader . last_event_count - self . a_start_event_count
} else {
0
} ;
let b_index = if event_reader . last_event_count > self . b_start_event_count {
event_reader . last_event_count - self . b_start_event_count
} else {
0
} ;
event_reader . last_event_count = self . event_count ;
2020-03-30 05:44:38 +00:00
match self . state {
State ::A = > self
. events_b
. get ( b_index .. )
. unwrap_or_else ( | | & [ ] )
. iter ( )
. map ( map_event_instance )
. chain (
self . events_a
. get ( a_index .. )
. unwrap_or_else ( | | & [ ] )
. iter ( )
. map ( map_event_instance ) ,
) ,
State ::B = > self
. events_a
. get ( a_index .. )
. unwrap_or_else ( | | & [ ] )
. iter ( )
. map ( map_event_instance )
. chain (
self . events_b
. get ( b_index .. )
. unwrap_or_else ( | | & [ ] )
. iter ( )
. map ( map_event_instance ) ,
) ,
}
}
2020-04-01 01:04:54 +00:00
/// Gets a new [EventReader]. This will include all events already in the event buffers.
pub fn get_reader ( & self ) -> EventReader < T > {
EventReader {
2020-03-30 21:53:32 +00:00
last_event_count : 0 ,
2020-03-30 05:44:38 +00:00
_marker : PhantomData ,
}
}
2020-04-01 01:04:54 +00:00
/// 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 < T > {
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.
2020-03-30 05:44:38 +00:00
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 ;
}
}
}
2020-04-01 01:04:54 +00:00
/// Builds a system that calls [Events::update] once per frame.
pub fn build_update_system ( ) -> Box < dyn Schedulable > {
SystemBuilder ::new ( format! ( " events_update:: {} " , std ::any ::type_name ::< T > ( ) ) )
2020-03-30 05:44:38 +00:00
. write_resource ::< Self > ( )
2020-04-01 01:04:54 +00:00
. build ( | _ , _ , events , _ | events . update ( ) )
2020-03-30 05:44:38 +00:00
}
}
2020-03-30 21:53:32 +00:00
2020-04-01 01:04:54 +00:00
pub trait GetEventReader {
/// returns an [EventReader] of the given type
fn get_event_reader < T > ( & self ) -> EventReader < T >
2020-03-30 21:53:32 +00:00
where
T : Send + Sync + 'static ;
}
2020-04-01 01:04:54 +00:00
impl GetEventReader for Resources {
fn get_event_reader < T > ( & self ) -> EventReader < T >
2020-03-30 21:53:32 +00:00
where
T : Send + Sync + 'static ,
{
let my_event = self
2020-04-01 01:04:54 +00:00
. get ::< Events < T > > ( )
2020-03-30 21:53:32 +00:00
. unwrap_or_else ( | | panic! ( " Event does not exist: {} " , std ::any ::type_name ::< T > ( ) ) ) ;
2020-04-01 01:04:54 +00:00
my_event . get_reader ( )
}
}
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ derive(Copy, Clone, PartialEq, Eq, Debug) ]
struct TestEvent {
i : usize ,
}
#[ test ]
fn test_events ( ) {
let mut events = Events ::< TestEvent > ::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 < TestEvent > ,
reader : & mut EventReader < TestEvent > ,
) -> Vec < TestEvent > {
events . iter ( reader ) . cloned ( ) . collect ::< Vec < TestEvent > > ( )
2020-03-30 21:53:32 +00:00
}
}