dotzuki_renderer/
input.rs1#[cfg(feature = "gpu")]
2use winit::keyboard::KeyCode;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[repr(u8)]
6pub enum GbButton {
7 A = 0,
8 B = 1,
9 Select = 2,
10 Start = 3,
11 Right = 4,
12 Left = 5,
13 Up = 6,
14 Down = 7,
15}
16
17impl GbButton {
18 pub const ALL: [GbButton; 8] = [
19 GbButton::A,
20 GbButton::B,
21 GbButton::Select,
22 GbButton::Start,
23 GbButton::Right,
24 GbButton::Left,
25 GbButton::Up,
26 GbButton::Down,
27 ];
28
29 pub fn bit_mask(self) -> u8 {
30 1 << (self as u8)
31 }
32}
33
34#[derive(Debug, Clone)]
35pub struct InputState {
36 current: u8,
37 previous: u8,
38}
39
40impl InputState {
41 pub fn new() -> Self {
42 Self {
43 current: 0,
44 previous: 0,
45 }
46 }
47
48 pub fn is_held(&self, button: GbButton) -> bool {
49 self.current & button.bit_mask() != 0
50 }
51
52 pub fn is_just_pressed(&self, button: GbButton) -> bool {
53 let mask = button.bit_mask();
54 (self.current & mask != 0) && (self.previous & mask == 0)
55 }
56
57 pub fn is_just_released(&self, button: GbButton) -> bool {
58 let mask = button.bit_mask();
59 (self.current & mask == 0) && (self.previous & mask != 0)
60 }
61
62 pub fn any_held(&self) -> bool {
63 self.current != 0
64 }
65
66 pub fn any_just_pressed(&self) -> bool {
67 (self.current & !self.previous) != 0
68 }
69
70 pub fn raw_current(&self) -> u8 {
71 self.current
72 }
73
74 pub fn raw_previous(&self) -> u8 {
75 self.previous
76 }
77
78 pub fn begin_frame(&mut self) {
79 self.previous = self.current;
80 }
81
82 pub fn press(&mut self, button: GbButton) {
83 self.current |= button.bit_mask();
84 }
85
86 pub fn release(&mut self, button: GbButton) {
87 self.current &= !button.bit_mask();
88 }
89
90 #[cfg(feature = "gpu")]
91 pub fn set_from_keycode(&mut self, keycode: KeyCode, pressed: bool) {
92 if let Some(button) = keycode_to_gb_button(keycode) {
93 if pressed {
94 self.press(button);
95 } else {
96 self.release(button);
97 }
98 }
99 }
100
101 pub fn clear(&mut self) {
102 self.current = 0;
103 self.previous = 0;
104 }
105
106 pub fn set_from_bitmask(&mut self, mask: u8) {
107 self.current = mask;
108 }
109}
110
111impl Default for InputState {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117#[cfg(feature = "gpu")]
118pub fn keycode_to_gb_button(keycode: KeyCode) -> Option<GbButton> {
119 match keycode {
120 KeyCode::ArrowUp | KeyCode::KeyW => Some(GbButton::Up),
122 KeyCode::ArrowDown | KeyCode::KeyS => Some(GbButton::Down),
123 KeyCode::ArrowLeft | KeyCode::KeyA => Some(GbButton::Left),
124 KeyCode::ArrowRight | KeyCode::KeyD => Some(GbButton::Right),
125 KeyCode::KeyZ => Some(GbButton::A),
127 KeyCode::KeyX => Some(GbButton::B),
128 KeyCode::Enter | KeyCode::Space => Some(GbButton::Start),
130 KeyCode::Backspace | KeyCode::ShiftRight => Some(GbButton::Select),
131 _ => None,
132 }
133}