1use crate::prelude::*;
2use crate::core::Display;
3
4pub const NUM_KEYS: usize = 256;
5pub const NUM_BUTTONS: usize = 16;
6
7#[derive(Debug, PartialEq, Copy, Clone)]
9pub enum InputState {
10 Up,
12 Pressed,
14 Down,
16 Released,
18 Repeat,
20}
21
22pub struct InputData {
23 pub mouse : (i32, i32),
24 pub mouse_delta : (i32, i32),
25 pub button : [ InputState; NUM_BUTTONS ],
26 pub key : [ InputState; NUM_KEYS ],
27 pub should_close : bool,
28 pub cursor_grabbed : bool,
29 pub has_focus : bool,
30 pub dimensions : (u32, u32),
31}
32
33impl InputData {
34 pub fn new() -> InputData {
35 InputData {
36 mouse : (0, 0),
37 mouse_delta : (0, 0),
38 button : [ InputState::Up; NUM_BUTTONS ],
39 key : [ InputState::Up; NUM_KEYS ],
40 should_close : false,
41 cursor_grabbed : false,
42 has_focus : true,
43 dimensions : (0, 0),
44 }
45 }
46 pub fn reset(self: &mut Self) {
47 for key_id in 0..NUM_KEYS {
49 match self.key[key_id] {
50 InputState::Pressed | InputState::Repeat => {
51 self.key[key_id] = InputState::Down;
52 }
53 InputState::Released => {
54 self.key[key_id] = InputState::Up;
55 }
56 _ => { }
57 }
58 }
59
60 for button_id in 0..NUM_BUTTONS {
61 match self.button[button_id] {
62 InputState::Pressed => {
63 self.button[button_id] = InputState::Down;
64 }
65 InputState::Released => {
66 self.button[button_id] = InputState::Up;
67 }
68 _ => { }
69 }
70 }
71
72 self.mouse_delta = (0, 0);
73 }
74}
75
76enum_from_primitive! {
77 #[derive(Clone, Copy, Debug, PartialEq)]
78 pub enum InputId {
80 Key1,
81 Key2,
82 Key3,
83 Key4,
84 Key5,
85 Key6,
86 Key7,
87 Key8,
88 Key9,
89 Key0,
90
91 A,
92 B,
93 C,
94 D,
95 E,
96 F,
97 G,
98 H,
99 I,
100 J,
101 K,
102 L,
103 M,
104 N,
105 O,
106 P,
107 Q,
108 R,
109 S,
110 T,
111 U,
112 V,
113 W,
114 X,
115 Y,
116 Z,
117
118 Escape,
119
120 F1,
121 F2,
122 F3,
123 F4,
124 F5,
125 F6,
126 F7,
127 F8,
128 F9,
129 F10,
130 F11,
131 F12,
132 F13,
133 F14,
134 F15,
135
136 Snapshot,
137 Scroll,
138 Pause,
139
140 Insert,
141 Home,
142 Delete,
143 End,
144 PageDown,
145 PageUp,
146
147 CursorLeft,
148 CursorUp,
149 CursorRight,
150 CursorDown,
151
152 Backspace,
153 Return,
154 Space,
155
156 Numlock,
157 Numpad0,
158 Numpad1,
159 Numpad2,
160 Numpad3,
161 Numpad4,
162 Numpad5,
163 Numpad6,
164 Numpad7,
165 Numpad8,
166 Numpad9,
167
168 AbntC1,
169 AbntC2,
170 Add,
171 Apostrophe,
172 Apps,
173 At,
174 Ax,
175 Backslash,
176 Calculator,
177 Capital,
178 Caret,
179 Colon,
180 Comma,
181 Convert,
182 Decimal,
183 Divide,
184 Equals,
185 Grave,
186 Kana,
187 Kanji,
188 LAlt,
189 LBracket,
190 LControl,
191 LMenu,
192 LShift,
193 LWin,
194 Mail,
195 MediaSelect,
196 MediaStop,
197 Minus,
198 Multiply,
199 Mute,
200 MyComputer,
201 NextTrack,
202 NoConvert,
203 NumpadComma,
204 NumpadEnter,
205 NumpadEquals,
206 OEM102,
207 Period,
208 PlayPause,
209 Power,
210 PrevTrack,
211 RAlt,
212 RBracket,
213 RControl,
214 RMenu,
215 RShift,
216 RWin,
217 Semicolon,
218 Slash,
219 Sleep,
220 Stop,
221 Subtract,
222 Sysrq,
223 Tab,
224 Underline,
225 Unlabeled,
226 VolumeDown,
227 VolumeUp,
228 Wake,
229 WebBack,
230 WebFavorites,
231 WebForward,
232 WebHome,
233 WebRefresh,
234 WebSearch,
235 WebStop,
236 Yen,
237 Compose,
238 NavigateForward,
239 NavigateBackward,
240
241 Mouse1 = NUM_KEYS as isize +0,
242 Mouse2 = NUM_KEYS as isize +1,
243 Mouse3 = NUM_KEYS as isize +2,
244 Mouse4 = NUM_KEYS as isize +3,
245 Mouse5 = NUM_KEYS as isize +4,
246 Mouse6 = NUM_KEYS as isize +5,
247 Mouse7 = NUM_KEYS as isize +6,
248 Mouse8 = NUM_KEYS as isize +7,
249 Mouse9 = NUM_KEYS as isize +8,
250 Mouse10 = NUM_KEYS as isize +9,
251 Mouse11 = NUM_KEYS as isize +10,
252 Mouse12 = NUM_KEYS as isize +11,
253 Mouse13 = NUM_KEYS as isize +12,
254 Mouse14 = NUM_KEYS as isize +13,
255 Mouse15 = NUM_KEYS as isize +14,
256 Mouse16 = NUM_KEYS as isize +15,
257
258 Unsupported = (NUM_KEYS + NUM_BUTTONS) as isize,
259 }
260}
261
262impl InputId {
263 pub fn button(id: usize) -> InputId {
264 use enum_primitive::FromPrimitive;
265 let base = InputId::Mouse1 as isize;
266 if (id >= 1) & (id <= 16) {
267 InputId::from_isize(base + (id as isize - 1)).unwrap()
268 } else {
269 InputId::Unsupported
270 }
271 }
272}
273
274#[derive(Clone)]
276pub struct Input {
277 pub (crate) input_data: Arc<RwLock<InputData>>,
278}
279
280impl Debug for Input {
281 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
282 write!(f, "Input")
283 }
284}
285
286impl Input {
287
288 pub fn new(display: &Display) -> Self {
290 Input {
291 input_data: display.input_data.clone(),
292 }
293 }
294
295 pub fn iter(self: &Self) -> InputIterator<'_> {
297 InputIterator {
298 input_data: self.input_data.read().unwrap(),
299 position: 0,
300 }
301 }
302
303 pub fn mouse(self: &Self) -> (i32, i32) {
305 self.get().mouse
306 }
307
308 pub fn mouse_delta(self: &Self) -> (i32, i32) {
310 self.get().mouse_delta
311 }
312
313 pub fn down(self: &Self, key: InputId) -> bool {
315 let id = key as usize;
316 let data = self.get();
317 if id < NUM_KEYS {
318 (data.key[id] == InputState::Pressed) || (data.key[id] == InputState::Down) || (data.key[id] == InputState::Repeat)
319 } else {
320 (data.button[id - NUM_KEYS] == InputState::Pressed) || (data.button[id - NUM_KEYS] == InputState::Down)
321 }
322 }
323
324 pub fn pressed(self: &Self, key: InputId, report_repeats: bool) -> bool {
326 let id = key as usize;
327 let data = self.get();
328 if id < NUM_KEYS {
329 (data.key[id] == InputState::Pressed) || (report_repeats && data.key[id] == InputState::Repeat)
330 } else {
331 data.button[id - NUM_KEYS] == InputState::Pressed
332 }
333 }
334
335 pub fn up(self: &Self, key: InputId) -> bool {
337 let id = key as usize;
338 let data = self.get();
339 if id < NUM_KEYS {
340 data.key[id] == InputState::Released || (data.key[id] == InputState::Up)
341 } else {
342 data.button[id - NUM_KEYS] == InputState::Released || (data.button[id - NUM_KEYS] == InputState::Up)
343 }
344 }
345
346 pub fn released(self: &Self, key: InputId) -> bool {
348 let id = key as usize;
349 let data = self.get();
350 if id < NUM_KEYS {
351 data.key[id] == InputState::Released
352 } else {
353 data.button[id - NUM_KEYS] == InputState::Released
354 }
355 }
356
357 pub fn state(self: &Self, key: InputId) -> InputState {
359 let id = key as usize;
360 let data = self.get();
361 if id < NUM_KEYS {
362 data.key[id]
363 } else {
364 data.button[id - NUM_KEYS]
365 }
366 }
367
368 fn get(self: &Self) -> RwLockReadGuard<'_, InputData> {
370 self.input_data.read().unwrap()
371 }
372}
373
374pub struct InputIterator<'a> {
376 input_data: RwLockReadGuard<'a, InputData>,
377 position: usize,
378}
379
380impl<'a> InputIterator<'a> {
381 pub fn down(self: Self) -> InputDownIterator<'a> {
383 InputDownIterator(self)
384 }
385 pub fn up(self: Self) -> InputUpIterator<'a> {
387 InputUpIterator(self)
388 }
389}
390
391impl<'a> Iterator for InputIterator<'a> {
392 type Item = (InputId, InputState);
393
394 fn next(self: &mut Self) -> Option<(InputId, InputState)> {
395
396 use enum_primitive::FromPrimitive;
397 let position = self.position;
398 self.position += 1;
399
400 if position < NUM_KEYS {
401 Some((InputId::from_usize(position).unwrap_or(InputId::Unsupported), self.input_data.key[position]))
402 } else if position < NUM_KEYS + NUM_BUTTONS {
403 Some((InputId::from_usize(position).unwrap_or(InputId::Unsupported), self.input_data.button[position - NUM_KEYS]))
404 } else {
405 None
406 }
407 }
408}
409
410pub struct InputDownIterator<'a>(InputIterator<'a>);
412
413impl<'a> Iterator for InputDownIterator<'a> {
414 type Item = InputId;
415
416 fn next(self: &mut Self) -> Option<InputId> {
417 while let Some(current) = self.0.next() {
418 let (input_id, button_state) = current;
419 if (button_state == InputState::Down) || (button_state == InputState::Pressed) {
420 return Some(input_id);
421 }
422 }
423 None
424 }
425}
426
427pub struct InputUpIterator<'a>(InputIterator<'a>);
429
430impl<'a> Iterator for InputUpIterator<'a> {
431 type Item = InputId;
432
433 fn next(self: &mut Self) -> Option<InputId> {
434 while let Some(current) = self.0.next() {
435 let (input_id, button_state) = current;
436 if (button_state == InputState::Up) || (button_state == InputState::Released) {
437 return Some(input_id);
438 }
439 }
440 None
441 }
442}