Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/event/collections.rs
6600 views
1
use alloc::vec::Vec;
2
use bevy_ecs::{
3
change_detection::MaybeLocation,
4
event::{BufferedEvent, EventCursor, EventId, EventInstance},
5
resource::Resource,
6
};
7
use core::{
8
marker::PhantomData,
9
ops::{Deref, DerefMut},
10
};
11
#[cfg(feature = "bevy_reflect")]
12
use {
13
bevy_ecs::reflect::ReflectResource,
14
bevy_reflect::{std_traits::ReflectDefault, Reflect},
15
};
16
17
/// An event collection that represents the events that occurred within the last two
18
/// [`Events::update`] calls.
19
/// Events can be written to using an [`EventWriter`]
20
/// and are typically cheaply read using an [`EventReader`].
21
///
22
/// Each event can be consumed by multiple systems, in parallel,
23
/// with consumption tracked by the [`EventReader`] on a per-system basis.
24
///
25
/// If no [ordering](https://github.com/bevyengine/bevy/blob/main/examples/ecs/ecs_guide.rs)
26
/// is applied between writing and reading systems, there is a risk of a race condition.
27
/// This means that whether the events arrive before or after the next [`Events::update`] is unpredictable.
28
///
29
/// This collection is meant to be paired with a system that calls
30
/// [`Events::update`] exactly once per update/frame.
31
///
32
/// [`event_update_system`] is a system that does this, typically initialized automatically using
33
/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
34
/// [`EventReader`]s are expected to read events from this collection at least once per loop/frame.
35
/// Events will persist across a single frame boundary and so ordering of event producers and
36
/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).
37
/// If events are not handled by the end of the frame after they are updated, they will be
38
/// dropped silently.
39
///
40
/// # Example
41
///
42
/// ```
43
/// use bevy_ecs::event::{BufferedEvent, Events};
44
///
45
/// #[derive(BufferedEvent)]
46
/// struct MyEvent {
47
/// value: usize
48
/// }
49
///
50
/// // setup
51
/// let mut events = Events::<MyEvent>::default();
52
/// let mut cursor = events.get_cursor();
53
///
54
/// // run this once per update/frame
55
/// events.update();
56
///
57
/// // somewhere else: write an event
58
/// events.write(MyEvent { value: 1 });
59
///
60
/// // somewhere else: read the events
61
/// for event in cursor.read(&events) {
62
/// assert_eq!(event.value, 1)
63
/// }
64
///
65
/// // events are only processed once per reader
66
/// assert_eq!(cursor.read(&events).count(), 0);
67
/// ```
68
///
69
/// # Details
70
///
71
/// [`Events`] is implemented using a variation of a double buffer strategy.
72
/// Each call to [`update`](Events::update) swaps buffers and clears out the oldest one.
73
/// - [`EventReader`]s will read events from both buffers.
74
/// - [`EventReader`]s that read at least once per update will never drop events.
75
/// - [`EventReader`]s that read once within two updates might still receive some events
76
/// - [`EventReader`]s that read after two updates are guaranteed to drop all events that occurred
77
/// before those updates.
78
///
79
/// The buffers in [`Events`] will grow indefinitely if [`update`](Events::update) is never called.
80
///
81
/// An alternative call pattern would be to call [`update`](Events::update)
82
/// manually across frames to control when events are cleared.
83
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
84
/// but can be done by adding your event as a resource instead of using
85
/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
86
///
87
/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/event.rs)
88
/// [Example usage standalone.](https://github.com/bevyengine/bevy/blob/latest/crates/bevy_ecs/examples/events.rs)
89
///
90
/// [`EventReader`]: super::EventReader
91
/// [`EventWriter`]: super::EventWriter
92
/// [`event_update_system`]: super::event_update_system
93
#[derive(Debug, Resource)]
94
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Resource, Default))]
95
pub struct Events<E: BufferedEvent> {
96
/// Holds the oldest still active events.
97
/// Note that `a.start_event_count + a.len()` should always be equal to `events_b.start_event_count`.
98
pub(crate) events_a: EventSequence<E>,
99
/// Holds the newer events.
100
pub(crate) events_b: EventSequence<E>,
101
pub(crate) event_count: usize,
102
}
103
104
// Derived Default impl would incorrectly require E: Default
105
impl<E: BufferedEvent> Default for Events<E> {
106
fn default() -> Self {
107
Self {
108
events_a: Default::default(),
109
events_b: Default::default(),
110
event_count: Default::default(),
111
}
112
}
113
}
114
115
impl<E: BufferedEvent> Events<E> {
116
/// Returns the index of the oldest event stored in the event buffer.
117
pub fn oldest_event_count(&self) -> usize {
118
self.events_a.start_event_count
119
}
120
121
/// Writes an `event` to the current event buffer.
122
/// [`EventReader`](super::EventReader)s can then read the event.
123
/// This method returns the [ID](`EventId`) of the written `event`.
124
#[track_caller]
125
pub fn write(&mut self, event: E) -> EventId<E> {
126
self.write_with_caller(event, MaybeLocation::caller())
127
}
128
129
pub(crate) fn write_with_caller(&mut self, event: E, caller: MaybeLocation) -> EventId<E> {
130
let event_id = EventId {
131
id: self.event_count,
132
caller,
133
_marker: PhantomData,
134
};
135
#[cfg(feature = "detailed_trace")]
136
tracing::trace!("Events::write() -> id: {}", event_id);
137
138
let event_instance = EventInstance { event_id, event };
139
140
self.events_b.push(event_instance);
141
self.event_count += 1;
142
143
event_id
144
}
145
146
/// Writes a list of `events` all at once, which can later be read by [`EventReader`](super::EventReader)s.
147
/// This is more efficient than writing each event individually.
148
/// This method returns the [IDs](`EventId`) of the written `events`.
149
#[track_caller]
150
pub fn write_batch(&mut self, events: impl IntoIterator<Item = E>) -> WriteBatchIds<E> {
151
let last_count = self.event_count;
152
153
self.extend(events);
154
155
WriteBatchIds {
156
last_count,
157
event_count: self.event_count,
158
_marker: PhantomData,
159
}
160
}
161
162
/// Writes the default value of the event. Useful when the event is an empty struct.
163
/// This method returns the [ID](`EventId`) of the written `event`.
164
#[track_caller]
165
pub fn write_default(&mut self) -> EventId<E>
166
where
167
E: Default,
168
{
169
self.write(Default::default())
170
}
171
172
/// "Sends" an `event` by writing it to the current event buffer.
173
/// [`EventReader`](super::EventReader)s can then read the event.
174
/// This method returns the [ID](`EventId`) of the sent `event`.
175
#[deprecated(since = "0.17.0", note = "Use `Events<E>::write` instead.")]
176
#[track_caller]
177
pub fn send(&mut self, event: E) -> EventId<E> {
178
self.write(event)
179
}
180
181
/// Sends a list of `events` all at once, which can later be read by [`EventReader`](super::EventReader)s.
182
/// This is more efficient than sending each event individually.
183
/// This method returns the [IDs](`EventId`) of the sent `events`.
184
#[deprecated(since = "0.17.0", note = "Use `Events<E>::write_batch` instead.")]
185
#[track_caller]
186
pub fn send_batch(&mut self, events: impl IntoIterator<Item = E>) -> WriteBatchIds<E> {
187
self.write_batch(events)
188
}
189
190
/// Sends the default value of the event. Useful when the event is an empty struct.
191
/// This method returns the [ID](`EventId`) of the sent `event`.
192
#[deprecated(since = "0.17.0", note = "Use `Events<E>::write_default` instead.")]
193
#[track_caller]
194
pub fn send_default(&mut self) -> EventId<E>
195
where
196
E: Default,
197
{
198
self.write_default()
199
}
200
201
/// Gets a new [`EventCursor`]. This will include all events already in the event buffers.
202
pub fn get_cursor(&self) -> EventCursor<E> {
203
EventCursor::default()
204
}
205
206
/// Gets a new [`EventCursor`]. This will ignore all events already in the event buffers.
207
/// It will read all future events.
208
pub fn get_cursor_current(&self) -> EventCursor<E> {
209
EventCursor {
210
last_event_count: self.event_count,
211
..Default::default()
212
}
213
}
214
215
/// Swaps the event buffers and clears the oldest event buffer. In general, this should be
216
/// called once per frame/update.
217
///
218
/// If you need access to the events that were removed, consider using [`Events::update_drain`].
219
pub fn update(&mut self) {
220
core::mem::swap(&mut self.events_a, &mut self.events_b);
221
self.events_b.clear();
222
self.events_b.start_event_count = self.event_count;
223
debug_assert_eq!(
224
self.events_a.start_event_count + self.events_a.len(),
225
self.events_b.start_event_count
226
);
227
}
228
229
/// Swaps the event buffers and drains the oldest event buffer, returning an iterator
230
/// of all events that were removed. In general, this should be called once per frame/update.
231
///
232
/// If you do not need to take ownership of the removed events, use [`Events::update`] instead.
233
#[must_use = "If you do not need the returned events, call .update() instead."]
234
pub fn update_drain(&mut self) -> impl Iterator<Item = E> + '_ {
235
core::mem::swap(&mut self.events_a, &mut self.events_b);
236
let iter = self.events_b.events.drain(..);
237
self.events_b.start_event_count = self.event_count;
238
debug_assert_eq!(
239
self.events_a.start_event_count + self.events_a.len(),
240
self.events_b.start_event_count
241
);
242
243
iter.map(|e| e.event)
244
}
245
246
#[inline]
247
fn reset_start_event_count(&mut self) {
248
self.events_a.start_event_count = self.event_count;
249
self.events_b.start_event_count = self.event_count;
250
}
251
252
/// Removes all events.
253
#[inline]
254
pub fn clear(&mut self) {
255
self.reset_start_event_count();
256
self.events_a.clear();
257
self.events_b.clear();
258
}
259
260
/// Returns the number of events currently stored in the event buffer.
261
#[inline]
262
pub fn len(&self) -> usize {
263
self.events_a.len() + self.events_b.len()
264
}
265
266
/// Returns true if there are no events currently stored in the event buffer.
267
#[inline]
268
pub fn is_empty(&self) -> bool {
269
self.len() == 0
270
}
271
272
/// Creates a draining iterator that removes all events.
273
pub fn drain(&mut self) -> impl Iterator<Item = E> + '_ {
274
self.reset_start_event_count();
275
276
// Drain the oldest events first, then the newest
277
self.events_a
278
.drain(..)
279
.chain(self.events_b.drain(..))
280
.map(|i| i.event)
281
}
282
283
/// Iterates over events that happened since the last "update" call.
284
/// WARNING: You probably don't want to use this call. In most cases you should use an
285
/// [`EventReader`]. You should only use this if you know you only need to consume events
286
/// between the last `update()` call and your call to `iter_current_update_events`.
287
/// If events happen outside that window, they will not be handled. For example, any events that
288
/// happen after this call and before the next `update()` call will be dropped.
289
///
290
/// [`EventReader`]: super::EventReader
291
pub fn iter_current_update_events(&self) -> impl ExactSizeIterator<Item = &E> {
292
self.events_b.iter().map(|i| &i.event)
293
}
294
295
/// Get a specific event by id if it still exists in the events buffer.
296
pub fn get_event(&self, id: usize) -> Option<(&E, EventId<E>)> {
297
if id < self.oldest_event_count() {
298
return None;
299
}
300
301
let sequence = self.sequence(id);
302
let index = id.saturating_sub(sequence.start_event_count);
303
304
sequence
305
.get(index)
306
.map(|instance| (&instance.event, instance.event_id))
307
}
308
309
/// Which event buffer is this event id a part of.
310
fn sequence(&self, id: usize) -> &EventSequence<E> {
311
if id < self.events_b.start_event_count {
312
&self.events_a
313
} else {
314
&self.events_b
315
}
316
}
317
}
318
319
impl<E: BufferedEvent> Extend<E> for Events<E> {
320
#[track_caller]
321
fn extend<I>(&mut self, iter: I)
322
where
323
I: IntoIterator<Item = E>,
324
{
325
let old_count = self.event_count;
326
let mut event_count = self.event_count;
327
let events = iter.into_iter().map(|event| {
328
let event_id = EventId {
329
id: event_count,
330
caller: MaybeLocation::caller(),
331
_marker: PhantomData,
332
};
333
event_count += 1;
334
EventInstance { event_id, event }
335
});
336
337
self.events_b.extend(events);
338
339
if old_count != event_count {
340
#[cfg(feature = "detailed_trace")]
341
tracing::trace!(
342
"Events::extend() -> ids: ({}..{})",
343
self.event_count,
344
event_count
345
);
346
}
347
348
self.event_count = event_count;
349
}
350
}
351
352
#[derive(Debug)]
353
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Default))]
354
pub(crate) struct EventSequence<E: BufferedEvent> {
355
pub(crate) events: Vec<EventInstance<E>>,
356
pub(crate) start_event_count: usize,
357
}
358
359
// Derived Default impl would incorrectly require E: Default
360
impl<E: BufferedEvent> Default for EventSequence<E> {
361
fn default() -> Self {
362
Self {
363
events: Default::default(),
364
start_event_count: Default::default(),
365
}
366
}
367
}
368
369
impl<E: BufferedEvent> Deref for EventSequence<E> {
370
type Target = Vec<EventInstance<E>>;
371
372
fn deref(&self) -> &Self::Target {
373
&self.events
374
}
375
}
376
377
impl<E: BufferedEvent> DerefMut for EventSequence<E> {
378
fn deref_mut(&mut self) -> &mut Self::Target {
379
&mut self.events
380
}
381
}
382
383
/// [`Iterator`] over written [`EventIds`](`EventId`) from a batch.
384
pub struct WriteBatchIds<E> {
385
last_count: usize,
386
event_count: usize,
387
_marker: PhantomData<E>,
388
}
389
390
/// [`Iterator`] over sent [`EventIds`](`EventId`) from a batch.
391
#[deprecated(since = "0.17.0", note = "Use `WriteBatchIds` instead.")]
392
pub type SendBatchIds<E> = WriteBatchIds<E>;
393
394
impl<E: BufferedEvent> Iterator for WriteBatchIds<E> {
395
type Item = EventId<E>;
396
397
fn next(&mut self) -> Option<Self::Item> {
398
if self.last_count >= self.event_count {
399
return None;
400
}
401
402
let result = Some(EventId {
403
id: self.last_count,
404
caller: MaybeLocation::caller(),
405
_marker: PhantomData,
406
});
407
408
self.last_count += 1;
409
410
result
411
}
412
}
413
414
impl<E: BufferedEvent> ExactSizeIterator for WriteBatchIds<E> {
415
fn len(&self) -> usize {
416
self.event_count.saturating_sub(self.last_count)
417
}
418
}
419
420
#[cfg(test)]
421
mod tests {
422
use crate::event::{BufferedEvent, Events};
423
424
#[test]
425
fn iter_current_update_events_iterates_over_current_events() {
426
#[derive(BufferedEvent, Clone)]
427
struct TestEvent;
428
429
let mut test_events = Events::<TestEvent>::default();
430
431
// Starting empty
432
assert_eq!(test_events.len(), 0);
433
assert_eq!(test_events.iter_current_update_events().count(), 0);
434
test_events.update();
435
436
// Writing one event
437
test_events.write(TestEvent);
438
439
assert_eq!(test_events.len(), 1);
440
assert_eq!(test_events.iter_current_update_events().count(), 1);
441
test_events.update();
442
443
// Writing two events on the next frame
444
test_events.write(TestEvent);
445
test_events.write(TestEvent);
446
447
assert_eq!(test_events.len(), 3); // Events are double-buffered, so we see 1 + 2 = 3
448
assert_eq!(test_events.iter_current_update_events().count(), 2);
449
test_events.update();
450
451
// Writing zero events
452
assert_eq!(test_events.len(), 2); // Events are double-buffered, so we see 2 + 0 = 2
453
assert_eq!(test_events.iter_current_update_events().count(), 0);
454
}
455
}
456
457