Skip to content

Commit

Permalink
Simplify sending empty events
Browse files Browse the repository at this point in the history
  • Loading branch information
IceSentry committed Feb 4, 2022
1 parent 6f11113 commit 8c5eec3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
47 changes: 42 additions & 5 deletions crates/bevy_ecs/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>,
Expand Down Expand Up @@ -169,13 +173,23 @@ 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);
}

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> {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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()]
);
}
}
2 changes: 1 addition & 1 deletion crates/bevy_input/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down
25 changes: 20 additions & 5 deletions examples/ecs/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ 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();
}

struct MyEvent {
pub message: String,
}

#[derive(Default)]
struct PlaySound;

struct EventTriggerState {
event_timer: Timer,
}
Expand All @@ -28,22 +33,32 @@ 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(),
});
// When sending an event which implements `Default` you can use `fire()` to send the default
// value.
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");
}
}

0 comments on commit 8c5eec3

Please sign in to comment.