Path: blob/main/crates/bevy_ecs/src/event/collections.rs
6600 views
use alloc::vec::Vec;1use bevy_ecs::{2change_detection::MaybeLocation,3event::{BufferedEvent, EventCursor, EventId, EventInstance},4resource::Resource,5};6use core::{7marker::PhantomData,8ops::{Deref, DerefMut},9};10#[cfg(feature = "bevy_reflect")]11use {12bevy_ecs::reflect::ReflectResource,13bevy_reflect::{std_traits::ReflectDefault, Reflect},14};1516/// An event collection that represents the events that occurred within the last two17/// [`Events::update`] calls.18/// Events can be written to using an [`EventWriter`]19/// and are typically cheaply read using an [`EventReader`].20///21/// Each event can be consumed by multiple systems, in parallel,22/// with consumption tracked by the [`EventReader`] on a per-system basis.23///24/// If no [ordering](https://github.com/bevyengine/bevy/blob/main/examples/ecs/ecs_guide.rs)25/// is applied between writing and reading systems, there is a risk of a race condition.26/// This means that whether the events arrive before or after the next [`Events::update`] is unpredictable.27///28/// This collection is meant to be paired with a system that calls29/// [`Events::update`] exactly once per update/frame.30///31/// [`event_update_system`] is a system that does this, typically initialized automatically using32/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).33/// [`EventReader`]s are expected to read events from this collection at least once per loop/frame.34/// Events will persist across a single frame boundary and so ordering of event producers and35/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).36/// If events are not handled by the end of the frame after they are updated, they will be37/// dropped silently.38///39/// # Example40///41/// ```42/// use bevy_ecs::event::{BufferedEvent, Events};43///44/// #[derive(BufferedEvent)]45/// struct MyEvent {46/// value: usize47/// }48///49/// // setup50/// let mut events = Events::<MyEvent>::default();51/// let mut cursor = events.get_cursor();52///53/// // run this once per update/frame54/// events.update();55///56/// // somewhere else: write an event57/// events.write(MyEvent { value: 1 });58///59/// // somewhere else: read the events60/// for event in cursor.read(&events) {61/// assert_eq!(event.value, 1)62/// }63///64/// // events are only processed once per reader65/// assert_eq!(cursor.read(&events).count(), 0);66/// ```67///68/// # Details69///70/// [`Events`] is implemented using a variation of a double buffer strategy.71/// Each call to [`update`](Events::update) swaps buffers and clears out the oldest one.72/// - [`EventReader`]s will read events from both buffers.73/// - [`EventReader`]s that read at least once per update will never drop events.74/// - [`EventReader`]s that read once within two updates might still receive some events75/// - [`EventReader`]s that read after two updates are guaranteed to drop all events that occurred76/// before those updates.77///78/// The buffers in [`Events`] will grow indefinitely if [`update`](Events::update) is never called.79///80/// An alternative call pattern would be to call [`update`](Events::update)81/// manually across frames to control when events are cleared.82/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,83/// but can be done by adding your event as a resource instead of using84/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).85///86/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/event.rs)87/// [Example usage standalone.](https://github.com/bevyengine/bevy/blob/latest/crates/bevy_ecs/examples/events.rs)88///89/// [`EventReader`]: super::EventReader90/// [`EventWriter`]: super::EventWriter91/// [`event_update_system`]: super::event_update_system92#[derive(Debug, Resource)]93#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Resource, Default))]94pub struct Events<E: BufferedEvent> {95/// Holds the oldest still active events.96/// Note that `a.start_event_count + a.len()` should always be equal to `events_b.start_event_count`.97pub(crate) events_a: EventSequence<E>,98/// Holds the newer events.99pub(crate) events_b: EventSequence<E>,100pub(crate) event_count: usize,101}102103// Derived Default impl would incorrectly require E: Default104impl<E: BufferedEvent> Default for Events<E> {105fn default() -> Self {106Self {107events_a: Default::default(),108events_b: Default::default(),109event_count: Default::default(),110}111}112}113114impl<E: BufferedEvent> Events<E> {115/// Returns the index of the oldest event stored in the event buffer.116pub fn oldest_event_count(&self) -> usize {117self.events_a.start_event_count118}119120/// Writes an `event` to the current event buffer.121/// [`EventReader`](super::EventReader)s can then read the event.122/// This method returns the [ID](`EventId`) of the written `event`.123#[track_caller]124pub fn write(&mut self, event: E) -> EventId<E> {125self.write_with_caller(event, MaybeLocation::caller())126}127128pub(crate) fn write_with_caller(&mut self, event: E, caller: MaybeLocation) -> EventId<E> {129let event_id = EventId {130id: self.event_count,131caller,132_marker: PhantomData,133};134#[cfg(feature = "detailed_trace")]135tracing::trace!("Events::write() -> id: {}", event_id);136137let event_instance = EventInstance { event_id, event };138139self.events_b.push(event_instance);140self.event_count += 1;141142event_id143}144145/// Writes a list of `events` all at once, which can later be read by [`EventReader`](super::EventReader)s.146/// This is more efficient than writing each event individually.147/// This method returns the [IDs](`EventId`) of the written `events`.148#[track_caller]149pub fn write_batch(&mut self, events: impl IntoIterator<Item = E>) -> WriteBatchIds<E> {150let last_count = self.event_count;151152self.extend(events);153154WriteBatchIds {155last_count,156event_count: self.event_count,157_marker: PhantomData,158}159}160161/// Writes the default value of the event. Useful when the event is an empty struct.162/// This method returns the [ID](`EventId`) of the written `event`.163#[track_caller]164pub fn write_default(&mut self) -> EventId<E>165where166E: Default,167{168self.write(Default::default())169}170171/// "Sends" an `event` by writing it to the current event buffer.172/// [`EventReader`](super::EventReader)s can then read the event.173/// This method returns the [ID](`EventId`) of the sent `event`.174#[deprecated(since = "0.17.0", note = "Use `Events<E>::write` instead.")]175#[track_caller]176pub fn send(&mut self, event: E) -> EventId<E> {177self.write(event)178}179180/// Sends a list of `events` all at once, which can later be read by [`EventReader`](super::EventReader)s.181/// This is more efficient than sending each event individually.182/// This method returns the [IDs](`EventId`) of the sent `events`.183#[deprecated(since = "0.17.0", note = "Use `Events<E>::write_batch` instead.")]184#[track_caller]185pub fn send_batch(&mut self, events: impl IntoIterator<Item = E>) -> WriteBatchIds<E> {186self.write_batch(events)187}188189/// Sends the default value of the event. Useful when the event is an empty struct.190/// This method returns the [ID](`EventId`) of the sent `event`.191#[deprecated(since = "0.17.0", note = "Use `Events<E>::write_default` instead.")]192#[track_caller]193pub fn send_default(&mut self) -> EventId<E>194where195E: Default,196{197self.write_default()198}199200/// Gets a new [`EventCursor`]. This will include all events already in the event buffers.201pub fn get_cursor(&self) -> EventCursor<E> {202EventCursor::default()203}204205/// Gets a new [`EventCursor`]. This will ignore all events already in the event buffers.206/// It will read all future events.207pub fn get_cursor_current(&self) -> EventCursor<E> {208EventCursor {209last_event_count: self.event_count,210..Default::default()211}212}213214/// Swaps the event buffers and clears the oldest event buffer. In general, this should be215/// called once per frame/update.216///217/// If you need access to the events that were removed, consider using [`Events::update_drain`].218pub fn update(&mut self) {219core::mem::swap(&mut self.events_a, &mut self.events_b);220self.events_b.clear();221self.events_b.start_event_count = self.event_count;222debug_assert_eq!(223self.events_a.start_event_count + self.events_a.len(),224self.events_b.start_event_count225);226}227228/// Swaps the event buffers and drains the oldest event buffer, returning an iterator229/// of all events that were removed. In general, this should be called once per frame/update.230///231/// If you do not need to take ownership of the removed events, use [`Events::update`] instead.232#[must_use = "If you do not need the returned events, call .update() instead."]233pub fn update_drain(&mut self) -> impl Iterator<Item = E> + '_ {234core::mem::swap(&mut self.events_a, &mut self.events_b);235let iter = self.events_b.events.drain(..);236self.events_b.start_event_count = self.event_count;237debug_assert_eq!(238self.events_a.start_event_count + self.events_a.len(),239self.events_b.start_event_count240);241242iter.map(|e| e.event)243}244245#[inline]246fn reset_start_event_count(&mut self) {247self.events_a.start_event_count = self.event_count;248self.events_b.start_event_count = self.event_count;249}250251/// Removes all events.252#[inline]253pub fn clear(&mut self) {254self.reset_start_event_count();255self.events_a.clear();256self.events_b.clear();257}258259/// Returns the number of events currently stored in the event buffer.260#[inline]261pub fn len(&self) -> usize {262self.events_a.len() + self.events_b.len()263}264265/// Returns true if there are no events currently stored in the event buffer.266#[inline]267pub fn is_empty(&self) -> bool {268self.len() == 0269}270271/// Creates a draining iterator that removes all events.272pub fn drain(&mut self) -> impl Iterator<Item = E> + '_ {273self.reset_start_event_count();274275// Drain the oldest events first, then the newest276self.events_a277.drain(..)278.chain(self.events_b.drain(..))279.map(|i| i.event)280}281282/// Iterates over events that happened since the last "update" call.283/// WARNING: You probably don't want to use this call. In most cases you should use an284/// [`EventReader`]. You should only use this if you know you only need to consume events285/// between the last `update()` call and your call to `iter_current_update_events`.286/// If events happen outside that window, they will not be handled. For example, any events that287/// happen after this call and before the next `update()` call will be dropped.288///289/// [`EventReader`]: super::EventReader290pub fn iter_current_update_events(&self) -> impl ExactSizeIterator<Item = &E> {291self.events_b.iter().map(|i| &i.event)292}293294/// Get a specific event by id if it still exists in the events buffer.295pub fn get_event(&self, id: usize) -> Option<(&E, EventId<E>)> {296if id < self.oldest_event_count() {297return None;298}299300let sequence = self.sequence(id);301let index = id.saturating_sub(sequence.start_event_count);302303sequence304.get(index)305.map(|instance| (&instance.event, instance.event_id))306}307308/// Which event buffer is this event id a part of.309fn sequence(&self, id: usize) -> &EventSequence<E> {310if id < self.events_b.start_event_count {311&self.events_a312} else {313&self.events_b314}315}316}317318impl<E: BufferedEvent> Extend<E> for Events<E> {319#[track_caller]320fn extend<I>(&mut self, iter: I)321where322I: IntoIterator<Item = E>,323{324let old_count = self.event_count;325let mut event_count = self.event_count;326let events = iter.into_iter().map(|event| {327let event_id = EventId {328id: event_count,329caller: MaybeLocation::caller(),330_marker: PhantomData,331};332event_count += 1;333EventInstance { event_id, event }334});335336self.events_b.extend(events);337338if old_count != event_count {339#[cfg(feature = "detailed_trace")]340tracing::trace!(341"Events::extend() -> ids: ({}..{})",342self.event_count,343event_count344);345}346347self.event_count = event_count;348}349}350351#[derive(Debug)]352#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Default))]353pub(crate) struct EventSequence<E: BufferedEvent> {354pub(crate) events: Vec<EventInstance<E>>,355pub(crate) start_event_count: usize,356}357358// Derived Default impl would incorrectly require E: Default359impl<E: BufferedEvent> Default for EventSequence<E> {360fn default() -> Self {361Self {362events: Default::default(),363start_event_count: Default::default(),364}365}366}367368impl<E: BufferedEvent> Deref for EventSequence<E> {369type Target = Vec<EventInstance<E>>;370371fn deref(&self) -> &Self::Target {372&self.events373}374}375376impl<E: BufferedEvent> DerefMut for EventSequence<E> {377fn deref_mut(&mut self) -> &mut Self::Target {378&mut self.events379}380}381382/// [`Iterator`] over written [`EventIds`](`EventId`) from a batch.383pub struct WriteBatchIds<E> {384last_count: usize,385event_count: usize,386_marker: PhantomData<E>,387}388389/// [`Iterator`] over sent [`EventIds`](`EventId`) from a batch.390#[deprecated(since = "0.17.0", note = "Use `WriteBatchIds` instead.")]391pub type SendBatchIds<E> = WriteBatchIds<E>;392393impl<E: BufferedEvent> Iterator for WriteBatchIds<E> {394type Item = EventId<E>;395396fn next(&mut self) -> Option<Self::Item> {397if self.last_count >= self.event_count {398return None;399}400401let result = Some(EventId {402id: self.last_count,403caller: MaybeLocation::caller(),404_marker: PhantomData,405});406407self.last_count += 1;408409result410}411}412413impl<E: BufferedEvent> ExactSizeIterator for WriteBatchIds<E> {414fn len(&self) -> usize {415self.event_count.saturating_sub(self.last_count)416}417}418419#[cfg(test)]420mod tests {421use crate::event::{BufferedEvent, Events};422423#[test]424fn iter_current_update_events_iterates_over_current_events() {425#[derive(BufferedEvent, Clone)]426struct TestEvent;427428let mut test_events = Events::<TestEvent>::default();429430// Starting empty431assert_eq!(test_events.len(), 0);432assert_eq!(test_events.iter_current_update_events().count(), 0);433test_events.update();434435// Writing one event436test_events.write(TestEvent);437438assert_eq!(test_events.len(), 1);439assert_eq!(test_events.iter_current_update_events().count(), 1);440test_events.update();441442// Writing two events on the next frame443test_events.write(TestEvent);444test_events.write(TestEvent);445446assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3447assert_eq!(test_events.iter_current_update_events().count(), 2);448test_events.update();449450// Writing zero events451assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2452assert_eq!(test_events.iter_current_update_events().count(), 0);453}454}455456457