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