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> crate::system::sealed::Sealed for EventReader<'static, T> {}
124impl<T: 'static> SystemParam for EventReader<'static, T> {
125    type Item<'w> = EventReader<'w, T>;
126    fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
127        let events = Res::<Events<T>>::fetch(world, _dt)?;
128        Ok(EventReader { events })
129    }
130    fn get_access_info(info: &mut AccessInfo) {
131        Res::<'static, Events<T>>::get_access_info(info);
132    }
133}
134
135// ==============================================================
136// EventWriter
137// ==============================================================
138
139pub struct EventWriter<'w, T: 'static> {
140    events: ResMut<'w, Events<T>>,
141}
142
143impl<'w, T: 'static> EventWriter<'w, T> {
144    /// Yeni bir olay fırlatır (mevcut frame'in buffer'ına yazar).
145    pub fn send(&mut self, event: T) {
146        self.events.send(event);
147    }
148
149    /// Birden fazla olay fırlatır.
150    pub fn send_batch(&mut self, events: impl IntoIterator<Item = T>) {
151        for event in events {
152            self.events.send(event);
153        }
154    }
155}
156
157impl<T: 'static> crate::system::sealed::Sealed for EventWriter<'static, T> {}
158impl<T: 'static> SystemParam for EventWriter<'static, T> {
159    type Item<'w> = EventWriter<'w, T>;
160    fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
161        let events = ResMut::<Events<T>>::fetch(world, _dt)?;
162        Ok(EventWriter { events })
163    }
164    fn get_access_info(info: &mut AccessInfo) {
165        ResMut::<'static, Events<T>>::get_access_info(info);
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172
173    #[test]
174    fn test_send_and_iter() {
175        let mut events = Events::new();
176        events.send(1);
177        events.send(2);
178        events.send(3);
179
180        // Henüz update() çağrılmadı — iter() önceki frame (boş)
181        assert!(events.iter().next().is_none());
182        assert!(events.is_empty());
183
184        // Frame ilerlet
185        events.update();
186
187        // Artık eventler okunabilir
188        let collected: Vec<&i32> = events.iter().collect();
189        assert_eq!(collected, vec![&1, &2, &3]);
190        assert_eq!(events.len(), 3);
191    }
192
193    #[test]
194    fn test_non_destructive_iter() {
195        let mut events = Events::new();
196        events.send(42);
197        events.update();
198
199        // İlk okuma
200        assert_eq!(events.iter().next(), Some(&42));
201        // İkinci okuma — hâlâ erişilebilir
202        assert_eq!(events.iter().next(), Some(&42));
203    }
204
205    #[test]
206    fn test_double_buffer_isolation() {
207        let mut events = Events::new();
208
209        // Frame 1: event gönder
210        events.send(1);
211        events.update();
212
213        // Frame 2: yeni event gönder + eski eventleri oku
214        events.send(2);
215        let frame1_events: Vec<&i32> = events.iter().collect();
216        assert_eq!(frame1_events, vec![&1]); // Sadece önceki frame
217
218        events.update();
219
220        // Frame 3: frame 2'nin eventleri okunabilir, frame 1'inkiler gitmiş
221        let frame2_events: Vec<&i32> = events.iter().collect();
222        assert_eq!(frame2_events, vec![&2]);
223    }
224
225    #[test]
226    fn test_update_clears_previous() {
227        let mut events = Events::new();
228        events.send(1);
229        events.update();
230        assert_eq!(events.len(), 1);
231
232        // Yeni frame — eski event temizlenmeli
233        events.update();
234        assert!(events.is_empty());
235        assert_eq!(events.len(), 0);
236    }
237
238    #[test]
239    fn test_push_backward_compat() {
240        let mut events = Events::new();
241        events.push(99); // Eski API
242        events.update();
243        assert_eq!(events.iter().next(), Some(&99));
244    }
245
246    #[test]
247    fn test_clear() {
248        let mut events = Events::new();
249        events.send(1);
250        events.update();
251        events.send(2);
252
253        events.clear();
254        assert!(events.is_empty());
255
256        events.update();
257        assert!(events.is_empty());
258    }
259
260    #[test]
261    fn test_drain_consumes() {
262        let mut events = Events::new();
263        events.send(10);
264        events.send(20);
265        events.update();
266
267        let drained: Vec<i32> = events.drain().collect();
268        assert_eq!(drained, vec![10, 20]);
269
270        // drain sonrası boş
271        assert!(events.is_empty());
272    }
273
274    #[test]
275    fn test_no_static_bound() {
276        // 'static bound kaldırıldığını doğrula — kısa ömürlü tipler de çalışır
277        struct Ephemeral<'a>(&'a str);
278        let mut events = Events::new();
279        let msg = String::from("test");
280        events.send(Ephemeral(&msg));
281        events.update();
282        assert_eq!(events.iter().next().unwrap().0, "test");
283    }
284}