goud_engine/core/event/resource.rs
1//! ECS resource wrapper for the event system.
2
3use crate::core::event::{
4 queue::EventQueue, reader::EventReader, traits::Event, writer::EventWriter,
5};
6
7/// ECS-compatible resource wrapper for event queues.
8///
9/// `Events<E>` wraps an [`EventQueue<E>`] and provides a high-level API
10/// suitable for use as an ECS resource. It manages the event lifecycle
11/// automatically and provides convenient accessor methods.
12///
13/// # Resource Integration
14///
15/// In a typical ECS architecture, `Events<E>` is stored as a resource in the
16/// World. Systems that need to send or receive events request it via the
17/// resource system.
18///
19/// # Frame Lifecycle
20///
21/// The `update()` method must be called once per frame (typically at the start
22/// or end of the frame) to:
23/// 1. Swap the double buffers
24/// 2. Clear stale events from the previous frame
25///
26/// This ensures events persist for exactly one frame after being sent.
27///
28/// # Example
29///
30/// ```rust
31/// use goud_engine::core::event::Events;
32///
33/// #[derive(Debug, Clone)]
34/// struct DamageEvent {
35/// entity_id: u32,
36/// amount: i32,
37/// }
38///
39/// // Create the events resource
40/// let mut events: Events<DamageEvent> = Events::new();
41///
42/// // Systems can send events
43/// events.send(DamageEvent { entity_id: 1, amount: 50 });
44/// events.send(DamageEvent { entity_id: 2, amount: 25 });
45///
46/// // At frame boundary, call update
47/// events.update();
48///
49/// // Now systems can read the events
50/// let mut reader = events.reader();
51/// for event in reader.read() {
52/// println!("Entity {} took {} damage", event.entity_id, event.amount);
53/// }
54/// ```
55///
56/// # Thread Safety
57///
58/// `Events<E>` is `Send + Sync` when `E` is `Send + Sync`, enabling safe
59/// use in multi-threaded ECS systems.
60pub struct Events<E: Event> {
61 /// The underlying double-buffered event queue
62 queue: EventQueue<E>,
63}
64
65impl<E: Event> Events<E> {
66 /// Creates a new empty `Events` resource.
67 ///
68 /// # Example
69 ///
70 /// ```rust
71 /// use goud_engine::core::event::Events;
72 ///
73 /// struct MyEvent { data: i32 }
74 /// let events: Events<MyEvent> = Events::new();
75 /// ```
76 #[must_use]
77 pub fn new() -> Self {
78 Self {
79 queue: EventQueue::new(),
80 }
81 }
82
83 /// Creates an `EventReader` for reading events from this resource.
84 ///
85 /// Multiple readers can be created simultaneously, as they only require
86 /// shared access to the underlying queue.
87 ///
88 /// # Example
89 ///
90 /// ```rust
91 /// use goud_engine::core::event::Events;
92 ///
93 /// #[derive(Debug)]
94 /// struct MyEvent { id: u32 }
95 ///
96 /// let mut events: Events<MyEvent> = Events::new();
97 /// events.send(MyEvent { id: 1 });
98 /// events.update();
99 ///
100 /// let mut reader = events.reader();
101 /// for event in reader.read() {
102 /// println!("Got event: {:?}", event);
103 /// }
104 /// ```
105 #[must_use]
106 pub fn reader(&self) -> EventReader<'_, E> {
107 EventReader::new(&self.queue)
108 }
109
110 /// Creates an `EventWriter` for sending events to this resource.
111 ///
112 /// Only one writer can exist at a time due to the mutable borrow requirement.
113 ///
114 /// # Example
115 ///
116 /// ```rust
117 /// use goud_engine::core::event::Events;
118 ///
119 /// struct SpawnEvent { entity_type: String }
120 ///
121 /// let mut events: Events<SpawnEvent> = Events::new();
122 ///
123 /// {
124 /// let mut writer = events.writer();
125 /// writer.send(SpawnEvent { entity_type: "enemy".to_string() });
126 /// writer.send(SpawnEvent { entity_type: "item".to_string() });
127 /// }
128 /// ```
129 #[must_use]
130 pub fn writer(&mut self) -> EventWriter<'_, E> {
131 EventWriter::new(&mut self.queue)
132 }
133
134 /// Sends an event directly to the write buffer.
135 ///
136 /// This is a convenience method equivalent to creating a writer and
137 /// calling `send()` on it.
138 ///
139 /// # Example
140 ///
141 /// ```rust
142 /// use goud_engine::core::event::Events;
143 ///
144 /// struct InputEvent { key: char }
145 ///
146 /// let mut events: Events<InputEvent> = Events::new();
147 /// events.send(InputEvent { key: 'w' });
148 /// events.send(InputEvent { key: 'a' });
149 /// ```
150 pub fn send(&mut self, event: E) {
151 self.queue.send(event);
152 }
153
154 /// Sends multiple events to the write buffer in batch.
155 ///
156 /// More efficient than calling `send()` multiple times when you have
157 /// a collection of events.
158 ///
159 /// # Example
160 ///
161 /// ```rust
162 /// use goud_engine::core::event::Events;
163 ///
164 /// #[derive(Clone)]
165 /// struct ParticleEvent { x: f32, y: f32 }
166 ///
167 /// let mut events: Events<ParticleEvent> = Events::new();
168 /// let particles = vec![
169 /// ParticleEvent { x: 0.0, y: 0.0 },
170 /// ParticleEvent { x: 1.0, y: 1.0 },
171 /// ParticleEvent { x: 2.0, y: 2.0 },
172 /// ];
173 /// events.send_batch(particles);
174 /// ```
175 pub fn send_batch(&mut self, events: impl IntoIterator<Item = E>) {
176 for event in events {
177 self.queue.send(event);
178 }
179 }
180
181 /// Updates the event system at frame boundary.
182 ///
183 /// This method MUST be called exactly once per frame, typically at the
184 /// start or end of the game loop. It:
185 /// 1. Clears events from the previous read buffer (they've had their chance)
186 /// 2. Swaps the buffers so newly written events become readable
187 ///
188 /// # Frame Timing
189 ///
190 /// ```text
191 /// Frame N:
192 /// 1. update() called - events from Frame N-1 become readable
193 /// 2. Systems read events
194 /// 3. Systems write new events
195 ///
196 /// Frame N+1:
197 /// 1. update() called - Frame N-1 events cleared, Frame N events readable
198 /// ... and so on
199 /// ```
200 ///
201 /// # Important
202 ///
203 /// - Calling `update()` more than once per frame will cause events to be
204 /// lost (the write buffer gets swapped to read before systems can write)
205 /// - Not calling `update()` will cause events to accumulate and never
206 /// become readable
207 ///
208 /// # Example
209 ///
210 /// ```rust
211 /// use goud_engine::core::event::Events;
212 ///
213 /// struct GameEvent;
214 ///
215 /// let mut events: Events<GameEvent> = Events::new();
216 ///
217 /// // Game loop
218 /// for frame in 0..3 {
219 /// // Start of frame: update events
220 /// events.update();
221 ///
222 /// // Read events from previous frame
223 /// let mut reader = events.reader();
224 /// for _ in reader.read() {
225 /// // Process events...
226 /// }
227 ///
228 /// // Systems write new events
229 /// events.send(GameEvent);
230 /// }
231 /// ```
232 pub fn update(&mut self) {
233 self.queue.swap_buffers();
234 }
235
236 /// Drains all events from the read buffer, consuming them.
237 ///
238 /// Unlike using a reader, this removes the events entirely from the buffer.
239 ///
240 /// # Example
241 ///
242 /// ```rust
243 /// use goud_engine::core::event::Events;
244 ///
245 /// struct Event { id: u32 }
246 ///
247 /// let mut events: Events<Event> = Events::new();
248 /// events.send(Event { id: 1 });
249 /// events.send(Event { id: 2 });
250 /// events.update();
251 ///
252 /// let collected: Vec<Event> = events.drain().collect();
253 /// assert_eq!(collected.len(), 2);
254 /// ```
255 pub fn drain(&mut self) -> impl Iterator<Item = E> + '_ {
256 self.queue.drain()
257 }
258
259 /// Clears all events from both buffers.
260 ///
261 /// Use this when transitioning between game states or when you need
262 /// to discard all pending events.
263 ///
264 /// # Example
265 ///
266 /// ```rust
267 /// use goud_engine::core::event::Events;
268 ///
269 /// struct Event;
270 ///
271 /// let mut events: Events<Event> = Events::new();
272 /// events.send(Event);
273 /// events.update();
274 /// events.send(Event);
275 ///
276 /// events.clear();
277 /// assert!(events.is_empty());
278 /// ```
279 pub fn clear(&mut self) {
280 self.queue.clear();
281 }
282
283 /// Returns `true` if no events are pending in the write buffer.
284 ///
285 /// Note: The read buffer may still contain events from the previous frame.
286 ///
287 /// # Example
288 ///
289 /// ```rust
290 /// use goud_engine::core::event::Events;
291 ///
292 /// struct Event;
293 ///
294 /// let mut events: Events<Event> = Events::new();
295 /// assert!(events.is_empty());
296 ///
297 /// events.send(Event);
298 /// assert!(!events.is_empty());
299 /// ```
300 #[must_use]
301 pub fn is_empty(&self) -> bool {
302 self.queue.is_empty()
303 }
304
305 /// Returns the number of events in the write buffer.
306 ///
307 /// # Example
308 ///
309 /// ```rust
310 /// use goud_engine::core::event::Events;
311 ///
312 /// struct Event;
313 ///
314 /// let mut events: Events<Event> = Events::new();
315 /// events.send(Event);
316 /// events.send(Event);
317 ///
318 /// assert_eq!(events.len(), 2);
319 /// ```
320 #[must_use]
321 pub fn len(&self) -> usize {
322 self.queue.len()
323 }
324
325 /// Returns the number of events available for reading.
326 ///
327 /// # Example
328 ///
329 /// ```rust
330 /// use goud_engine::core::event::Events;
331 ///
332 /// struct Event;
333 ///
334 /// let mut events: Events<Event> = Events::new();
335 /// events.send(Event);
336 /// events.send(Event);
337 ///
338 /// // Events are in write buffer
339 /// assert_eq!(events.read_len(), 0);
340 ///
341 /// events.update();
342 ///
343 /// // Now in read buffer
344 /// assert_eq!(events.read_len(), 2);
345 /// ```
346 #[must_use]
347 pub fn read_len(&self) -> usize {
348 self.queue.read_len()
349 }
350
351 /// Returns a slice of events available for reading.
352 ///
353 /// This provides direct access to the read buffer, enabling cursor-based
354 /// reading patterns used by ECS system parameters.
355 ///
356 /// # Example
357 ///
358 /// ```rust
359 /// use goud_engine::core::event::Events;
360 ///
361 /// struct Event { id: u32 }
362 ///
363 /// let mut events: Events<Event> = Events::new();
364 /// events.send(Event { id: 1 });
365 /// events.send(Event { id: 2 });
366 /// events.update();
367 ///
368 /// let buffer = events.read_buffer();
369 /// assert_eq!(buffer.len(), 2);
370 /// ```
371 #[must_use]
372 pub fn read_buffer(&self) -> &[E] {
373 self.queue.read_buffer()
374 }
375}
376
377impl<E: Event> Default for Events<E> {
378 fn default() -> Self {
379 Self::new()
380 }
381}
382
383// Note: Events<E> is automatically Send + Sync because EventQueue<E> is Send + Sync
384// when E is Send + Sync, which is guaranteed by the Event trait bound.
385// This is enforced by the test `test_events_is_send_sync`.