mirror of
https://github.com/bevyengine/bevy
synced 2024-11-29 16:10:19 +00:00
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:
parent
6f111136b9
commit
7d712406fe
4 changed files with 62 additions and 12 deletions
|
@ -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;
|
||||||
|
|
|
@ -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()]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue