matrix_engine/engine/
events.rs

1use std::{
2    any::TypeId,
3    collections::{HashSet, VecDeque},
4    fmt::Debug,
5    hash::Hash,
6    time::Instant,
7};
8
9use winit::{
10    dpi::PhysicalSize,
11    event::{DeviceEvent, ElementState, MouseButton, MouseScrollDelta, WindowEvent},
12    event_loop::{EventLoopClosed, EventLoopProxy},
13    keyboard::{KeyCode, PhysicalKey},
14};
15
16use super::{
17    data_state::{DataState, DataStateAccessError, ReadDataState},
18    entity::SystemEntity,
19};
20
21#[derive(Debug, Clone)]
22pub enum MatrixEvent<Custom: MatrixEventable> {
23    Exit,
24    DestroySystem(SystemEntity),
25    ChangedResource(TypeId),
26    Custom(Custom),
27}
28
29pub trait MatrixEventable: Clone + Send + Sync + Debug + 'static {}
30impl<T: Clone + Send + Sync + Debug + 'static> MatrixEventable for T {}
31
32#[derive(Debug)]
33pub struct Events<CustomEvents: MatrixEventable> {
34    keyboard_input: InputManager<KeyCode>, // Input manager for keyboard
35    mouse_input: InputManager<MouseButton>, // Input manager for mouse buttons
36    close_requested: bool,
37    matrix_events: VecDeque<MatrixEvent<CustomEvents>>,
38    new_inner_size: Option<PhysicalSize<u32>>,
39    mouse_dx: (f32, f32),   // Mouse delta (movement)
40    mouse_pos: (f32, f32),  // Mouse position
41    mouse_wheel_delta: f32, // Mouse wheel delta
42    start_frame: Instant,
43    dt: f32,
44}
45
46impl<CustomEvents: MatrixEventable> Default for Events<CustomEvents> {
47    fn default() -> Self {
48        Self::new()
49    }
50}
51
52impl<CustomEvents: MatrixEventable> Events<CustomEvents> {
53    pub fn new() -> Self {
54        Events {
55            matrix_events: VecDeque::new(),
56            keyboard_input: InputManager::new(),
57            mouse_input: InputManager::new(),
58            mouse_pos: (0., 0.),
59            mouse_wheel_delta: 0.,
60            close_requested: false,
61            new_inner_size: None,
62            dt: 0.,
63            start_frame: Instant::now(),
64            mouse_dx: (0., 0.),
65        }
66    }
67
68    pub fn handle_window_event(&mut self, event: &WindowEvent) {
69        match event {
70            WindowEvent::KeyboardInput { event, .. } => {
71                if let PhysicalKey::Code(keycode) = event.physical_key {
72                    match event.state {
73                        ElementState::Pressed if !event.repeat => {
74                            self.keyboard_input.on_press(keycode)
75                        }
76                        ElementState::Released => self.keyboard_input.on_release(keycode),
77                        _ => {}
78                    }
79                }
80            }
81            WindowEvent::MouseInput { state, button, .. } => match state {
82                ElementState::Pressed => self.mouse_input.on_press(*button),
83                ElementState::Released => self.mouse_input.on_release(*button),
84            },
85            WindowEvent::CursorMoved { position, .. } => {
86                self.mouse_pos = (position.x as _, position.y as _);
87            }
88            WindowEvent::MouseWheel { delta, .. } => match delta {
89                MouseScrollDelta::LineDelta(_, y) => {
90                    self.mouse_wheel_delta = *y;
91                }
92                MouseScrollDelta::PixelDelta(pos) => {
93                    self.mouse_wheel_delta = pos.y as f32;
94                }
95            },
96            WindowEvent::CloseRequested => {
97                self.close_requested = true;
98            }
99            WindowEvent::Resized(size) => {
100                self.new_inner_size = Some(*size);
101            }
102
103            _ => (),
104        }
105    }
106    pub fn handle_matrix_event(&mut self, event: MatrixEvent<CustomEvents>) {
107        self.matrix_events.push_back(event);
108    }
109    pub(crate) fn handle_device_event(&mut self, event: DeviceEvent) {
110        match event {
111            DeviceEvent::MouseMotion { delta: (x, y) } => self.mouse_dx = (x as _, y as _),
112            DeviceEvent::Added => {
113                println!("added device");
114            }
115            _ => {}
116        }
117    }
118
119    pub fn matrix_events(&self) -> impl Iterator<Item = &MatrixEvent<CustomEvents>> {
120        self.matrix_events.iter()
121    }
122
123    pub fn reset(&mut self) {
124        self.keyboard_input.reset();
125        self.mouse_input.reset();
126        self.close_requested = false;
127        self.new_inner_size = None;
128
129        let now = Instant::now();
130        self.dt = (now - self.start_frame).as_secs_f32();
131        self.start_frame = now;
132
133        self.mouse_dx = (0., 0.);
134        self.mouse_wheel_delta = 0.;
135    }
136
137    pub fn new_inner_size(&self) -> Option<&PhysicalSize<u32>> {
138        self.new_inner_size.as_ref()
139    }
140
141    pub fn close_requested(&self) -> bool {
142        self.close_requested
143    }
144
145    pub fn dt(&self) -> f32 {
146        self.dt
147    }
148
149    pub fn keyboard(&self) -> &InputManager<KeyCode> {
150        &self.keyboard_input
151    }
152
153    pub fn mouse(&self) -> &InputManager<MouseButton> {
154        &self.mouse_input
155    }
156
157    pub fn mouse_dx(&self) -> (f32, f32) {
158        self.mouse_dx
159    }
160
161    pub fn mouse_wheel_delta(&self) -> f32 {
162        self.mouse_wheel_delta
163    }
164}
165
166#[derive(Debug)]
167pub struct EventWriter<CustomEvents: MatrixEventable> {
168    proxy: EventLoopProxy<MatrixEvent<CustomEvents>>,
169}
170
171impl<CustomEvents: MatrixEventable> EventWriter<CustomEvents> {
172    pub fn new(proxy: EventLoopProxy<MatrixEvent<CustomEvents>>) -> Self {
173        Self { proxy }
174    }
175    pub fn send(
176        &self,
177        event: MatrixEvent<CustomEvents>,
178    ) -> Result<(), EventLoopClosed<MatrixEvent<CustomEvents>>> {
179        self.proxy.send_event(event)
180    }
181}
182
183#[derive(Debug)]
184pub struct EventRegistry<CustomEvents: MatrixEventable> {
185    events: DataState<Events<CustomEvents>>,
186    event_loop_proxy: Option<DataState<EventWriter<CustomEvents>>>,
187}
188
189impl<CustomEvents: MatrixEventable> EventRegistry<CustomEvents> {
190    pub fn new(event_loop_proxy: Option<EventLoopProxy<MatrixEvent<CustomEvents>>>) -> Self {
191        Self {
192            events: DataState::new(Events::new()),
193            event_loop_proxy: event_loop_proxy.map(|x| DataState::new(EventWriter::new(x))),
194        }
195    }
196    pub fn new_with_events(event_loop_proxy: EventLoopProxy<MatrixEvent<CustomEvents>>) -> Self {
197        Self::new(Some(event_loop_proxy))
198    }
199    pub fn new_no_events() -> Self {
200        Self::new(None)
201    }
202
203    pub fn get_reader(
204        &mut self,
205    ) -> Result<ReadDataState<Events<CustomEvents>>, DataStateAccessError> {
206        self.events.read()
207    }
208    pub fn check_reader(&mut self) -> bool {
209        self.events.can_read()
210    }
211    pub fn consume_reader(
212        &mut self,
213        data: ReadDataState<Events<CustomEvents>>,
214    ) -> Result<(), DataStateAccessError> {
215        self.events.consume_read(data)
216    }
217
218    pub fn get_writer(
219        &mut self,
220    ) -> Option<Result<ReadDataState<EventWriter<CustomEvents>>, DataStateAccessError>> {
221        self.event_loop_proxy.as_mut().map(|x| x.read())
222    }
223    pub fn check_writer(&mut self) -> Option<bool> {
224        self.event_loop_proxy.as_mut().map(|x| x.can_read())
225    }
226    pub fn consume_writer(
227        &mut self,
228        data: ReadDataState<EventWriter<CustomEvents>>,
229    ) -> Result<(), DataStateAccessError> {
230        if let Some(proxy) = &mut self.event_loop_proxy {
231            proxy.consume_read(data)
232        } else {
233            panic!("consumed an event writer, whene there is no writer at all")
234        }
235    }
236
237    pub fn events(&mut self) -> &mut DataState<Events<CustomEvents>> {
238        &mut self.events
239    }
240}
241
242#[derive(Debug)]
243pub struct InputManager<T: Eq + Hash + Copy> {
244    currently_pressed: HashSet<T>,
245    just_pressed: HashSet<T>,
246    just_released: HashSet<T>,
247}
248
249impl<T: Eq + Hash + Copy> InputManager<T> {
250    // Create a new InputManager
251    pub fn new() -> Self {
252        Self {
253            currently_pressed: HashSet::new(),
254            just_pressed: HashSet::new(),
255            just_released: HashSet::new(),
256        }
257    }
258
259    // Handle input press event
260    pub fn on_press(&mut self, input: T) {
261        self.just_pressed.insert(input);
262        self.currently_pressed.insert(input);
263    }
264
265    // Handle input release event
266    pub fn on_release(&mut self, input: T) {
267        self.just_released.insert(input);
268        self.currently_pressed.remove(&input);
269    }
270
271    // Check if the input is currently pressed
272    pub fn is_pressed(&self, input: T) -> bool {
273        self.currently_pressed.contains(&input)
274    }
275
276    // Check if the input was just pressed in this frame
277    pub fn is_just_pressed(&self, input: T) -> bool {
278        self.just_pressed.contains(&input)
279    }
280
281    // Check if the input was just released in this frame
282    pub fn is_just_released(&self, input: T) -> bool {
283        self.just_released.contains(&input)
284    }
285
286    // Reset just_pressed and just_released for the next frame
287    pub fn reset(&mut self) {
288        self.just_pressed.clear();
289        self.just_released.clear();
290    }
291}
292
293impl<T: Eq + Hash + Copy> Default for InputManager<T> {
294    fn default() -> Self {
295        Self::new()
296    }
297}