From 87afcbf67be49ef490409b645c3c493772945f25 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Sat, 7 May 2022 16:47:03 -0400 Subject: [PATCH 01/15] add any() check to event reader that consumes the iterator --- crates/bevy_ecs/src/event.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 00e0c6b74607e..070dd9fe924b8 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -365,6 +365,41 @@ impl ExactSizeIterator for ExactSize { } } +impl<'w, 's, E: Event> EventReader<'w, 's, E> { + /// Iterates over the events this [`EventReader`] has not seen yet. This updates the + /// [`EventReader`]'s event counter, which means subsequent event reads will not include events + /// that happened before now. + pub fn iter(&mut self) -> impl DoubleEndedIterator + ExactSizeIterator { + self.iter_with_id().map(|(event, _id)| event) + } + + /// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events. + pub fn iter_with_id( + &mut self, + ) -> impl DoubleEndedIterator)> + ExactSizeIterator)> + { + internal_event_reader(&mut self.last_event_count.0, &self.events).map(|(event, id)| { + trace!("EventReader::iter() -> {}", id); + (event, id) + }) + } + + /// Determines the number of events available to be read from this [`EventReader`] without consuming any. + pub fn len(&self) -> usize { + internal_event_reader(&mut self.last_event_count.0.clone(), &self.events).len() + } + + /// Determines if there are any events available to be read without consuming any. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Determines if there are any events available to be read and consumes all events. + pub fn any(&mut self) -> bool { + self.iter().last().is_some() + } +} + impl Events { /// "Sends" an `event` by writing it to the current event buffer. [`EventReader`]s can then read /// the event. From cbbdd2f8432027c6a79cc42674c417de0d838919 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Sat, 7 May 2022 17:06:42 -0400 Subject: [PATCH 02/15] update doc --- crates/bevy_ecs/src/event.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 070dd9fe924b8..6f36a5751f696 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -390,11 +390,14 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { } /// Determines if there are any events available to be read without consuming any. + /// If you need to consume the iterator you can use [`EventReader::any`] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Determines if there are any events available to be read and consumes all events. + /// If you don't need to consume the iterator you can use [`EventReader::is_empty`] + /// WARNING: `events.any()` is not the same as doing `!events.is_empty()` pub fn any(&mut self) -> bool { self.iter().last().is_some() } From 4a69efd9b12d2aaec1e860a6f09199a9b225f65c Mon Sep 17 00:00:00 2001 From: IceSentry Date: Sat, 7 May 2022 17:09:07 -0400 Subject: [PATCH 03/15] add warning to is_empty --- crates/bevy_ecs/src/event.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 6f36a5751f696..ad196babc464e 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -391,6 +391,7 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { /// Determines if there are any events available to be read without consuming any. /// If you need to consume the iterator you can use [`EventReader::any`] + /// WARNING: `events.is_empty()` is not the same as doing `!events.any()` pub fn is_empty(&self) -> bool { self.len() == 0 } From 39fd84bba7fb24c91c2110fe668edb23c1eccf95 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Sat, 7 May 2022 17:32:37 -0400 Subject: [PATCH 04/15] rephrase is_empty docs --- crates/bevy_ecs/src/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index ad196babc464e..e3f1c7518133b 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -389,7 +389,7 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { internal_event_reader(&mut self.last_event_count.0.clone(), &self.events).len() } - /// Determines if there are any events available to be read without consuming any. + /// Determines if no events are available to be read without consuming any. /// If you need to consume the iterator you can use [`EventReader::any`] /// WARNING: `events.is_empty()` is not the same as doing `!events.any()` pub fn is_empty(&self) -> bool { From 228a4a8ba91496a1cb9c0424bc4d8e203e3cbdab Mon Sep 17 00:00:00 2001 From: IceSentry Date: Mon, 9 May 2022 13:20:16 -0400 Subject: [PATCH 05/15] use clear instead of any --- crates/bevy_ecs/src/event.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index e3f1c7518133b..15e05f25db171 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -390,17 +390,14 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { } /// Determines if no events are available to be read without consuming any. - /// If you need to consume the iterator you can use [`EventReader::any`] - /// WARNING: `events.is_empty()` is not the same as doing `!events.any()` + /// If you need to consume the iterator you can use [`EventReader::clear`] pub fn is_empty(&self) -> bool { self.len() == 0 } - /// Determines if there are any events available to be read and consumes all events. - /// If you don't need to consume the iterator you can use [`EventReader::is_empty`] - /// WARNING: `events.any()` is not the same as doing `!events.is_empty()` - pub fn any(&mut self) -> bool { - self.iter().last().is_some() + /// Consumes the iterator. This means all currently available events will be removed before the next frame. + pub fn clear(mut self) { + self.iter().last(); } } @@ -766,6 +763,29 @@ mod tests { assert!(reader.is_empty(&events)); } + #[test] + fn test_event_reader_clear() { + use bevy_ecs::prelude::*; + + let mut world = World::new(); + let mut events = Events::::default(); + events.send(TestEvent { i: 0 }); + world.insert_resource(events); + + let mut reader = IntoSystem::into_system(|events: EventReader| -> bool { + if !events.is_empty() { + events.clear(); + return false; + } else { + return true; + } + }); + reader.initialize(&mut world); + + assert_eq!(reader.run((), &mut world), false); + assert_eq!(reader.run((), &mut world), true); + } + #[derive(Clone, PartialEq, Debug, Default)] struct EmptyTestEvent; From 87262e528d20a005a6f4d0eded2d03cddcd205ad Mon Sep 17 00:00:00 2001 From: IceSentry Date: Mon, 9 May 2022 13:20:27 -0400 Subject: [PATCH 06/15] use clear in breakout example --- examples/games/breakout.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/games/breakout.rs b/examples/games/breakout.rs index 06d091f76d93c..4c777fe325abd 100644 --- a/examples/games/breakout.rs +++ b/examples/games/breakout.rs @@ -411,13 +411,14 @@ fn check_for_collisions( } fn play_collision_sound( - mut collision_events: EventReader, + collision_events: EventReader, audio: Res