#[cfg(feature = "multi_threaded")]1use bevy_ecs::event::EventMutParIter;2use bevy_ecs::{3event::{BufferedEvent, EventCursor, EventMutIterator, EventMutIteratorWithId, Events},4system::{Local, ResMut, SystemParam},5};67/// Mutably reads events of type `T` keeping track of which events have already been read8/// by each system allowing multiple systems to read the same events. Ideal for chains of systems9/// that all want to modify the same events.10///11/// # Usage12///13/// `EventMutators`s are usually declared as a [`SystemParam`].14/// ```15/// # use bevy_ecs::prelude::*;16///17/// #[derive(BufferedEvent, Debug)]18/// pub struct MyEvent(pub u32); // Custom event type.19/// fn my_system(mut reader: EventMutator<MyEvent>) {20/// for event in reader.read() {21/// event.0 += 1;22/// println!("received event: {:?}", event);23/// }24/// }25/// ```26///27/// # Concurrency28///29/// Multiple systems with `EventMutator<T>` of the same event type can not run concurrently.30/// They also can not be executed in parallel with [`EventReader`] or [`EventWriter`].31///32/// # Clearing, Reading, and Peeking33///34/// Events are stored in a double buffered queue that switches each frame. This switch also clears the previous35/// frame's events. Events should be read each frame otherwise they may be lost. For manual control over this36/// behavior, see [`Events`].37///38/// Most of the time systems will want to use [`EventMutator::read()`]. This function creates an iterator over39/// all events that haven't been read yet by this system, marking the event as read in the process.40///41/// [`EventReader`]: super::EventReader42/// [`EventWriter`]: super::EventWriter43#[derive(SystemParam, Debug)]44pub struct EventMutator<'w, 's, E: BufferedEvent> {45pub(super) reader: Local<'s, EventCursor<E>>,46#[system_param(validation_message = "BufferedEvent not initialized")]47events: ResMut<'w, Events<E>>,48}4950impl<'w, 's, E: BufferedEvent> EventMutator<'w, 's, E> {51/// Iterates over the events this [`EventMutator`] has not seen yet. This updates the52/// [`EventMutator`]'s event counter, which means subsequent event reads will not include events53/// that happened before now.54pub fn read(&mut self) -> EventMutIterator<'_, E> {55self.reader.read_mut(&mut self.events)56}5758/// Like [`read`](Self::read), except also returning the [`EventId`](super::EventId) of the events.59pub fn read_with_id(&mut self) -> EventMutIteratorWithId<'_, E> {60self.reader.read_mut_with_id(&mut self.events)61}6263/// Returns a parallel iterator over the events this [`EventMutator`] has not seen yet.64/// See also [`for_each`](super::EventParIter::for_each).65///66/// # Example67/// ```68/// # use bevy_ecs::prelude::*;69/// # use std::sync::atomic::{AtomicUsize, Ordering};70///71/// #[derive(BufferedEvent)]72/// struct MyEvent {73/// value: usize,74/// }75///76/// #[derive(Resource, Default)]77/// struct Counter(AtomicUsize);78///79/// // setup80/// let mut world = World::new();81/// world.init_resource::<Events<MyEvent>>();82/// world.insert_resource(Counter::default());83///84/// let mut schedule = Schedule::default();85/// schedule.add_systems(|mut events: EventMutator<MyEvent>, counter: Res<Counter>| {86/// events.par_read().for_each(|MyEvent { value }| {87/// counter.0.fetch_add(*value, Ordering::Relaxed);88/// });89/// });90/// for value in 0..100 {91/// world.write_event(MyEvent { value });92/// }93/// schedule.run(&mut world);94/// let Counter(counter) = world.remove_resource::<Counter>().unwrap();95/// // all events were processed96/// assert_eq!(counter.into_inner(), 4950);97/// ```98#[cfg(feature = "multi_threaded")]99pub fn par_read(&mut self) -> EventMutParIter<'_, E> {100self.reader.par_read_mut(&mut self.events)101}102103/// Determines the number of events available to be read from this [`EventMutator`] without consuming any.104pub fn len(&self) -> usize {105self.reader.len(&self.events)106}107108/// Returns `true` if there are no events available to read.109///110/// # Example111///112/// The following example shows a useful pattern where some behavior is triggered if new events are available.113/// [`EventMutator::clear()`] is used so the same events don't re-trigger the behavior the next time the system runs.114///115/// ```116/// # use bevy_ecs::prelude::*;117/// #118/// #[derive(BufferedEvent)]119/// struct CollisionEvent;120///121/// fn play_collision_sound(mut events: EventMutator<CollisionEvent>) {122/// if !events.is_empty() {123/// events.clear();124/// // Play a sound125/// }126/// }127/// # bevy_ecs::system::assert_is_system(play_collision_sound);128/// ```129pub fn is_empty(&self) -> bool {130self.reader.is_empty(&self.events)131}132133/// Consumes all available events.134///135/// This means these events will not appear in calls to [`EventMutator::read()`] or136/// [`EventMutator::read_with_id()`] and [`EventMutator::is_empty()`] will return `true`.137///138/// For usage, see [`EventMutator::is_empty()`].139pub fn clear(&mut self) {140self.reader.clear(&self.events);141}142}143144145