bevy_ecs/event/
reader.rs

1#[cfg(feature = "multi_threaded")]
2use bevy_ecs::event::EventParIter;
3use bevy_ecs::{
4    event::{Event, EventCursor, EventIterator, EventIteratorWithId, Events},
5    system::{Local, Res, SystemParam},
6};
7
8/// Reads events of type `T` in order and tracks which events have already been read.
9///
10/// # Concurrency
11///
12/// Unlike [`EventWriter<T>`], systems with `EventReader<T>` param can be executed concurrently
13/// (but not concurrently with `EventWriter<T>` or `EventMutator<T>` systems for the same event type).
14///
15/// [`EventWriter<T>`]: super::EventWriter
16#[derive(SystemParam, Debug)]
17pub struct EventReader<'w, 's, E: Event> {
18    pub(super) reader: Local<'s, EventCursor<E>>,
19    #[system_param(validation_message = "Event not initialized")]
20    events: Res<'w, Events<E>>,
21}
22
23impl<'w, 's, E: Event> EventReader<'w, 's, E> {
24    /// Iterates over the events this [`EventReader`] has not seen yet. This updates the
25    /// [`EventReader`]'s event counter, which means subsequent event reads will not include events
26    /// that happened before now.
27    pub fn read(&mut self) -> EventIterator<'_, E> {
28        self.reader.read(&self.events)
29    }
30
31    /// Like [`read`](Self::read), except also returning the [`EventId`](super::EventId) of the events.
32    pub fn read_with_id(&mut self) -> EventIteratorWithId<'_, E> {
33        self.reader.read_with_id(&self.events)
34    }
35
36    /// Returns a parallel iterator over the events this [`EventReader`] has not seen yet.
37    /// See also [`for_each`](EventParIter::for_each).
38    ///
39    /// # Example
40    /// ```
41    /// # use bevy_ecs::prelude::*;
42    /// # use std::sync::atomic::{AtomicUsize, Ordering};
43    ///
44    /// #[derive(Event)]
45    /// struct MyEvent {
46    ///     value: usize,
47    /// }
48    ///
49    /// #[derive(Resource, Default)]
50    /// struct Counter(AtomicUsize);
51    ///
52    /// // setup
53    /// let mut world = World::new();
54    /// world.init_resource::<Events<MyEvent>>();
55    /// world.insert_resource(Counter::default());
56    ///
57    /// let mut schedule = Schedule::default();
58    /// schedule.add_systems(|mut events: EventReader<MyEvent>, counter: Res<Counter>| {
59    ///     events.par_read().for_each(|MyEvent { value }| {
60    ///         counter.0.fetch_add(*value, Ordering::Relaxed);
61    ///     });
62    /// });
63    /// for value in 0..100 {
64    ///     world.send_event(MyEvent { value });
65    /// }
66    /// schedule.run(&mut world);
67    /// let Counter(counter) = world.remove_resource::<Counter>().unwrap();
68    /// // all events were processed
69    /// assert_eq!(counter.into_inner(), 4950);
70    /// ```
71    #[cfg(feature = "multi_threaded")]
72    pub fn par_read(&mut self) -> EventParIter<'_, E> {
73        self.reader.par_read(&self.events)
74    }
75
76    /// Determines the number of events available to be read from this [`EventReader`] without consuming any.
77    pub fn len(&self) -> usize {
78        self.reader.len(&self.events)
79    }
80
81    /// Returns `true` if there are no events available to read.
82    ///
83    /// # Example
84    ///
85    /// The following example shows a useful pattern where some behavior is triggered if new events are available.
86    /// [`EventReader::clear()`] is used so the same events don't re-trigger the behavior the next time the system runs.
87    ///
88    /// ```
89    /// # use bevy_ecs::prelude::*;
90    /// #
91    /// #[derive(Event)]
92    /// struct CollisionEvent;
93    ///
94    /// fn play_collision_sound(mut events: EventReader<CollisionEvent>) {
95    ///     if !events.is_empty() {
96    ///         events.clear();
97    ///         // Play a sound
98    ///     }
99    /// }
100    /// # bevy_ecs::system::assert_is_system(play_collision_sound);
101    /// ```
102    pub fn is_empty(&self) -> bool {
103        self.reader.is_empty(&self.events)
104    }
105
106    /// Consumes all available events.
107    ///
108    /// This means these events will not appear in calls to [`EventReader::read()`] or
109    /// [`EventReader::read_with_id()`] and [`EventReader::is_empty()`] will return `true`.
110    ///
111    /// For usage, see [`EventReader::is_empty()`].
112    pub fn clear(&mut self) {
113        self.reader.clear(&self.events);
114    }
115}