Simplify sending empty events (#2935)

# Objective

When using empty events, it can feel redundant to have to specify the type of the event when sending it.

## Solution

Add a new `fire()` function that sends the default value of the event. This requires that the event derives Default.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Charles 2022-02-04 01:24:47 +00:00
parent 6f111136b9
commit 7d712406fe
4 changed files with 62 additions and 12 deletions

View file

@ -915,5 +915,5 @@ fn run_once(mut app: App) {
} }
/// An event that indicates the app should exit. This will fully exit the app process. /// An event that indicates the app should exit. This will fully exit the app process.
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct AppExit; pub struct AppExit;

View file

@ -122,6 +122,10 @@ enum State {
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up, /// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
/// but can be done by adding your event as a resource instead of using /// but can be done by adding your event as a resource instead of using
/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event). /// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
///
/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/event.rs)
/// [Example usage standalone.](https://github.com/bevyengine/bevy/blob/latest/bevy_ecs/examples/events.rs)
///
#[derive(Debug)] #[derive(Debug)]
pub struct Events<T> { pub struct Events<T> {
events_a: Vec<EventInstance<T>>, events_a: Vec<EventInstance<T>>,
@ -169,6 +173,8 @@ pub struct EventWriter<'w, 's, T: Resource> {
} }
impl<'w, 's, T: Resource> EventWriter<'w, 's, T> { impl<'w, 's, T: Resource> EventWriter<'w, 's, T> {
/// Sends an `event`. [`EventReader`]s can then read the event.
/// See [`Events`] for details.
pub fn send(&mut self, event: T) { pub fn send(&mut self, event: T) {
self.events.send(event); self.events.send(event);
} }
@ -176,6 +182,14 @@ impl<'w, 's, T: Resource> EventWriter<'w, 's, T> {
pub fn send_batch(&mut self, events: impl Iterator<Item = T>) { pub fn send_batch(&mut self, events: impl Iterator<Item = T>) {
self.events.extend(events); self.events.extend(events);
} }
/// Sends the default value of the event. Useful when the event is an empty struct.
pub fn send_default(&mut self)
where
T: Default,
{
self.events.send_default();
}
} }
pub struct ManualEventReader<T> { pub struct ManualEventReader<T> {
@ -296,6 +310,14 @@ impl<T: Resource> Events<T> {
self.event_count += 1; self.event_count += 1;
} }
/// Sends the default value of the event. Useful when the event is an empty struct.
pub fn send_default(&mut self)
where
T: Default,
{
self.send(Default::default());
}
/// Gets a new [`ManualEventReader`]. This will include all events already in the event buffers. /// Gets a new [`ManualEventReader`]. This will include all events already in the event buffers.
pub fn get_reader(&self) -> ManualEventReader<T> { pub fn get_reader(&self) -> ManualEventReader<T> {
ManualEventReader { ManualEventReader {
@ -540,11 +562,11 @@ mod tests {
); );
} }
fn get_events( fn get_events<T: Resource + Clone>(
events: &Events<TestEvent>, events: &Events<T>,
reader: &mut ManualEventReader<TestEvent>, reader: &mut ManualEventReader<T>,
) -> Vec<TestEvent> { ) -> Vec<T> {
reader.iter(events).cloned().collect::<Vec<TestEvent>>() reader.iter(events).cloned().collect::<Vec<T>>()
} }
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
@ -652,4 +674,19 @@ mod tests {
events.update(); events.update();
assert!(reader.is_empty(&events)); assert!(reader.is_empty(&events));
} }
#[derive(Clone, PartialEq, Debug, Default)]
struct EmptyTestEvent;
#[test]
fn test_firing_empty_event() {
let mut events = Events::<EmptyTestEvent>::default();
events.send_default();
let mut reader = events.get_reader();
assert_eq!(
get_events(&events, &mut reader),
vec![EmptyTestEvent::default()]
);
}
} }

View file

@ -13,7 +13,7 @@ pub fn exit_on_esc_system(
for event in keyboard_input_events.iter() { for event in keyboard_input_events.iter() {
if let Some(key_code) = event.key_code { if let Some(key_code) = event.key_code {
if event.state == ElementState::Pressed && key_code == KeyCode::Escape { if event.state == ElementState::Pressed && key_code == KeyCode::Escape {
app_exit_events.send(AppExit); app_exit_events.send_default();
} }
} }
} }

View file

@ -6,9 +6,11 @@ fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins)
.add_event::<MyEvent>() .add_event::<MyEvent>()
.add_event::<PlaySound>()
.init_resource::<EventTriggerState>() .init_resource::<EventTriggerState>()
.add_system(event_trigger_system) .add_system(event_trigger)
.add_system(event_listener_system) .add_system(event_listener)
.add_system(sound_player)
.run(); .run();
} }
@ -16,6 +18,9 @@ struct MyEvent {
pub message: String, pub message: String,
} }
#[derive(Default)]
struct PlaySound;
struct EventTriggerState { struct EventTriggerState {
event_timer: Timer, event_timer: Timer,
} }
@ -28,22 +33,30 @@ impl Default for EventTriggerState {
} }
} }
// sends MyEvent every second // sends MyEvent and PlaySound every second
fn event_trigger_system( fn event_trigger(
time: Res<Time>, time: Res<Time>,
mut state: ResMut<EventTriggerState>, mut state: ResMut<EventTriggerState>,
mut my_events: EventWriter<MyEvent>, mut my_events: EventWriter<MyEvent>,
mut play_sound_events: EventWriter<PlaySound>,
) { ) {
if state.event_timer.tick(time.delta()).finished() { if state.event_timer.tick(time.delta()).finished() {
my_events.send(MyEvent { my_events.send(MyEvent {
message: "MyEvent just happened!".to_string(), message: "MyEvent just happened!".to_string(),
}); });
play_sound_events.send_default();
} }
} }
// prints events as they come in // prints events as they come in
fn event_listener_system(mut events: EventReader<MyEvent>) { fn event_listener(mut events: EventReader<MyEvent>) {
for my_event in events.iter() { for my_event in events.iter() {
info!("{}", my_event.message); info!("{}", my_event.message);
} }
} }
fn sound_player(mut play_sound_events: EventReader<PlaySound>) {
for _ in play_sound_events.iter() {
info!("Playing a sound");
}
}