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>, mouse_input: InputManager<MouseButton>, close_requested: bool,
37 matrix_events: VecDeque<MatrixEvent<CustomEvents>>,
38 new_inner_size: Option<PhysicalSize<u32>>,
39 mouse_dx: (f32, f32), mouse_pos: (f32, f32), mouse_wheel_delta: f32, 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 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 pub fn on_press(&mut self, input: T) {
261 self.just_pressed.insert(input);
262 self.currently_pressed.insert(input);
263 }
264
265 pub fn on_release(&mut self, input: T) {
267 self.just_released.insert(input);
268 self.currently_pressed.remove(&input);
269 }
270
271 pub fn is_pressed(&self, input: T) -> bool {
273 self.currently_pressed.contains(&input)
274 }
275
276 pub fn is_just_pressed(&self, input: T) -> bool {
278 self.just_pressed.contains(&input)
279 }
280
281 pub fn is_just_released(&self, input: T) -> bool {
283 self.just_released.contains(&input)
284 }
285
286 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}