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.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub struct AppExit;

View file

@ -122,6 +122,10 @@ enum State {
/// 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
/// [`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)]
pub struct Events<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> {
/// Sends an `event`. [`EventReader`]s can then read the event.
/// See [`Events`] for details.
pub fn send(&mut self, event: T) {
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>) {
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> {
@ -296,6 +310,14 @@ impl<T: Resource> Events<T> {
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.
pub fn get_reader(&self) -> ManualEventReader<T> {
ManualEventReader {
@ -540,11 +562,11 @@ mod tests {
);
}
fn get_events(
events: &Events<TestEvent>,
reader: &mut ManualEventReader<TestEvent>,
) -> Vec<TestEvent> {
reader.iter(events).cloned().collect::<Vec<TestEvent>>()
fn get_events<T: Resource + Clone>(
events: &Events<T>,
reader: &mut ManualEventReader<T>,
) -> Vec<T> {
reader.iter(events).cloned().collect::<Vec<T>>()
}
#[derive(PartialEq, Eq, Debug)]
@ -652,4 +674,19 @@ mod tests {
events.update();
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() {
if let Some(key_code) = event.key_code {
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()
.add_plugins(DefaultPlugins)
.add_event::<MyEvent>()
.add_event::<PlaySound>()
.init_resource::<EventTriggerState>()
.add_system(event_trigger_system)
.add_system(event_listener_system)
.add_system(event_trigger)
.add_system(event_listener)
.add_system(sound_player)
.run();
}
@ -16,6 +18,9 @@ struct MyEvent {
pub message: String,
}
#[derive(Default)]
struct PlaySound;
struct EventTriggerState {
event_timer: Timer,
}
@ -28,22 +33,30 @@ impl Default for EventTriggerState {
}
}
// sends MyEvent every second
fn event_trigger_system(
// sends MyEvent and PlaySound every second
fn event_trigger(
time: Res<Time>,
mut state: ResMut<EventTriggerState>,
mut my_events: EventWriter<MyEvent>,
mut play_sound_events: EventWriter<PlaySound>,
) {
if state.event_timer.tick(time.delta()).finished() {
my_events.send(MyEvent {
message: "MyEvent just happened!".to_string(),
});
play_sound_events.send_default();
}
}
// 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() {
info!("{}", my_event.message);
}
}
fn sound_player(mut play_sound_events: EventReader<PlaySound>) {
for _ in play_sound_events.iter() {
info!("Playing a sound");
}
}