Skip to main content

gizmo_core/
event.rs

1use crate::system::{AccessInfo, Res, ResMut, SystemParam, SystemParamFetchError};
2use crate::world::World;
3
4/// Gizmo ECS Event System — Double-buffered olay kuyruğu.
5///
6/// Her frame'de `update()` çağrıldığında, önceki frame'in eventleri atılır ve
7/// mevcut frame'in eventleri "önceki" konumuna taşınır. Bu sayede:
8/// - Yazarlar (`send`) her zaman `current` buffer'a yazar.
9/// - Okuyucular (`iter`) her zaman `previous` buffer'dan okur (non-destructive).
10/// - Birden fazla sistem aynı eventleri bağımsız olarak okuyabilir.
11///
12/// # Kullanım
13/// ```rust,ignore
14/// // Kayıt (App seviyesinde):
15/// app.add_event::<CollisionEvent>();
16///
17/// // Olay gönderme (herhangi bir sistem):
18/// world.get_resource_mut::<Events<CollisionEvent>>().unwrap().send(CollisionEvent(..));
19///
20/// // Olay okuma (herhangi bir sistem, non-destructive):
21/// let events = world.get_resource::<Events<CollisionEvent>>().unwrap();
22/// for event in events.iter() {
23///     tracing::info!("Çarpışma oldu: {:?}", event);
24/// }
25/// ```
26pub struct Events<T> {
27    /// Bu frame'e yazılan eventler.
28    current: Vec<T>,
29    /// Önceki frame'den kalan, okunabilir eventler.
30    previous: Vec<T>,
31}
32
33impl<T> Events<T> {
34    pub fn new() -> Self {
35        Self {
36            current: Vec::new(),
37            previous: Vec::new(),
38        }
39    }
40
41    /// Yeni bir event gönderir (mevcut frame'in buffer'ına yazar).
42    #[inline]
43    pub fn send(&mut self, event: T) {
44        self.current.push(event);
45    }
46
47    /// Geriye dönük uyumluluk — `send()` ile aynı.
48    #[inline]
49    pub fn push(&mut self, event: T) {
50        self.send(event);
51    }
52
53    /// Frame sonu: önceki frame'in eventlerini temizler, mevcut frame'i önceki konuma taşır.
54    ///
55    /// Bu metot her frame sonunda **bir kez** çağrılmalıdır — `App::add_event()` bunu
56    /// otomatik olarak yapar.
57    pub fn update(&mut self) {
58        self.previous.clear();
59        std::mem::swap(&mut self.current, &mut self.previous);
60    }
61
62    /// Önceki frame'in eventlerini okumak için non-destructive iterator.
63    /// Birden fazla sistem aynı eventleri bağımsız olarak okuyabilir.
64    pub fn iter(&self) -> impl Iterator<Item = &T> {
65        self.previous.iter()
66    }
67
68    /// Önceki frame'deki event sayısı.
69    #[inline]
70    pub fn len(&self) -> usize {
71        self.previous.len()
72    }
73
74    /// Önceki frame'de event var mı?
75    #[inline]
76    pub fn is_empty(&self) -> bool {
77        self.previous.is_empty()
78    }
79
80    /// Tüm eventleri (hem mevcut hem önceki) temizler.
81    pub fn clear(&mut self) {
82        self.current.clear();
83        self.previous.clear();
84    }
85
86    /// Eventleri tüketmek için destructive iterator.
87    /// **Dikkat:** Bu metot tüm eventleri (önceki frame) tüketir. Birden fazla okuyucu
88    /// varsa diğer okuyucular eventleri kaçırır. Mümkünse `iter()` tercih edin.
89    pub fn drain(&mut self) -> std::vec::IntoIter<T> {
90        self.previous.drain(..).collect::<Vec<_>>().into_iter()
91    }
92}
93
94impl<T> Default for Events<T> {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100// ==============================================================
101// EventReader
102// ==============================================================
103
104pub struct EventReader<'w, T: 'static> {
105    events: Res<'w, Events<T>>,
106}
107
108impl<'w, T: 'static> EventReader<'w, T> {
109    /// Olayları okumak için iterator döndürür (önceki frame'in eventleri).
110    pub fn iter(&self) -> impl Iterator<Item = &T> {
111        self.events.iter()
112    }
113
114    pub fn len(&self) -> usize {
115        self.events.len()
116    }
117
118    pub fn is_empty(&self) -> bool {
119        self.events.is_empty()
120    }
121}
122
123impl<T: 'static> SystemParam for EventReader<'static, T> {
124    type Item<'w> = EventReader<'w, T>;
125    fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
126        let events = Res::<Events<T>>::fetch(world, _dt)?;
127        Ok(EventReader { events })
128    }
129    fn get_access_info(info: &mut AccessInfo) {
130        Res::<'static, Events<T>>::get_access_info(info);
131    }
132}
133
134// ==============================================================
135// EventWriter
136// ==============================================================
137
138pub struct EventWriter<'w, T: 'static> {
139    events: ResMut<'w, Events<T>>,
140}
141
142impl<'w, T: 'static> EventWriter<'w, T> {
143    /// Yeni bir olay fırlatır (mevcut frame'in buffer'ına yazar).
144    pub fn send(&mut self, event: T) {
145        self.events.send(event);
146    }
147
148    /// Birden fazla olay fırlatır.
149    pub fn send_batch(&mut self, events: impl IntoIterator<Item = T>) {
150        for event in events {
151            self.events.send(event);
152        }
153    }
154}
155
156impl<T: 'static> SystemParam for EventWriter<'static, T> {
157    type Item<'w> = EventWriter<'w, T>;
158    fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
159        let events = ResMut::<Events<T>>::fetch(world, _dt)?;
160        Ok(EventWriter { events })
161    }
162    fn get_access_info(info: &mut AccessInfo) {
163        ResMut::<'static, Events<T>>::get_access_info(info);
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_send_and_iter() {
173        let mut events = Events::new();
174        events.send(1);
175        events.send(2);
176        events.send(3);
177
178        // Henüz update() çağrılmadı — iter() önceki frame (boş)
179        assert!(events.iter().next().is_none());
180        assert!(events.is_empty());
181
182        // Frame ilerlet
183        events.update();
184
185        // Artık eventler okunabilir
186        let collected: Vec<&i32> = events.iter().collect();
187        assert_eq!(collected, vec![&1, &2, &3]);
188        assert_eq!(events.len(), 3);
189    }
190
191    #[test]
192    fn test_non_destructive_iter() {
193        let mut events = Events::new();
194        events.send(42);
195        events.update();
196
197        // İlk okuma
198        assert_eq!(events.iter().next(), Some(&42));
199        // İkinci okuma — hâlâ erişilebilir
200        assert_eq!(events.iter().next(), Some(&42));
201    }
202
203    #[test]
204    fn test_double_buffer_isolation() {
205        let mut events = Events::new();
206
207        // Frame 1: event gönder
208        events.send(1);
209        events.update();
210
211        // Frame 2: yeni event gönder + eski eventleri oku
212        events.send(2);
213        let frame1_events: Vec<&i32> = events.iter().collect();
214        assert_eq!(frame1_events, vec![&1]); // Sadece önceki frame
215
216        events.update();
217
218        // Frame 3: frame 2'nin eventleri okunabilir, frame 1'inkiler gitmiş
219        let frame2_events: Vec<&i32> = events.iter().collect();
220        assert_eq!(frame2_events, vec![&2]);
221    }
222
223    #[test]
224    fn test_update_clears_previous() {
225        let mut events = Events::new();
226        events.send(1);
227        events.update();
228        assert_eq!(events.len(), 1);
229
230        // Yeni frame — eski event temizlenmeli
231        events.update();
232        assert!(events.is_empty());
233        assert_eq!(events.len(), 0);
234    }
235
236    #[test]
237    fn test_push_backward_compat() {
238        let mut events = Events::new();
239        events.push(99); // Eski API
240        events.update();
241        assert_eq!(events.iter().next(), Some(&99));
242    }
243
244    #[test]
245    fn test_clear() {
246        let mut events = Events::new();
247        events.send(1);
248        events.update();
249        events.send(2);
250
251        events.clear();
252        assert!(events.is_empty());
253
254        events.update();
255        assert!(events.is_empty());
256    }
257
258    #[test]
259    fn test_drain_consumes() {
260        let mut events = Events::new();
261        events.send(10);
262        events.send(20);
263        events.update();
264
265        let drained: Vec<i32> = events.drain().collect();
266        assert_eq!(drained, vec![10, 20]);
267
268        // drain sonrası boş
269        assert!(events.is_empty());
270    }
271
272    #[test]
273    fn test_no_static_bound() {
274        // 'static bound kaldırıldığını doğrula — kısa ömürlü tipler de çalışır
275        struct Ephemeral<'a>(&'a str);
276        let mut events = Events::new();
277        let msg = String::from("test");
278        events.send(Ephemeral(&msg));
279        events.update();
280        assert_eq!(events.iter().next().unwrap().0, "test");
281    }
282}