use objc2_app_kit::NSEvent;
use crate::components::InputKey;
pub(crate) use crate::gfx::input::RenderInput as InputState;
#[derive(Default)]
pub(super) struct KeyState {
pub(super) forward: bool,
pub(super) backward: bool,
pub(super) left: bool,
pub(super) right: bool,
pub(super) sprint: bool,
pub(super) interact_pulse: bool,
pub(super) jump_pulse: bool,
pub(super) mouse_dx: f32,
pub(super) mouse_dy: f32,
pub(super) scroll_delta: f32,
pub(super) mouse_x: f32,
pub(super) mouse_y: f32,
pub(super) left_click_pulse: bool,
pub(super) left_button_down: bool,
pub(super) right_click_pulse: bool,
pub(super) hud_toggle_pulse: bool,
pub(super) escape_pulse: bool,
pub(super) captured_key: Option<InputKey>,
pub(super) typed_char: Option<char>,
pub(super) shift_down: bool,
pub(super) control_down: bool,
pub(super) alt_down: bool,
pub(super) command_down: bool,
pub(super) discard_next_motion: bool,
pub(super) cursor_outside_window: bool,
}
pub(super) fn is_printable_glyph(c: char) -> bool {
!c.is_control() && !('\u{F700}'..='\u{F8FF}').contains(&c)
}
pub(super) fn printable_char(event: &NSEvent) -> Option<char> {
let text = event.characters()?.to_string();
let c = text.chars().next()?;
is_printable_glyph(c).then_some(c)
}
pub(super) fn key_from_mac(kc: u16) -> Option<InputKey> {
Some(match kc {
0 => InputKey::A,
11 => InputKey::B,
8 => InputKey::C,
2 => InputKey::D,
14 => InputKey::E,
3 => InputKey::F,
5 => InputKey::G,
4 => InputKey::H,
34 => InputKey::I,
38 => InputKey::J,
40 => InputKey::K,
37 => InputKey::L,
46 => InputKey::M,
45 => InputKey::N,
31 => InputKey::O,
35 => InputKey::P,
12 => InputKey::Q,
15 => InputKey::R,
1 => InputKey::S,
17 => InputKey::T,
32 => InputKey::U,
9 => InputKey::V,
13 => InputKey::W,
7 => InputKey::X,
16 => InputKey::Y,
6 => InputKey::Z,
29 => InputKey::Num0,
18 => InputKey::Num1,
19 => InputKey::Num2,
20 => InputKey::Num3,
21 => InputKey::Num4,
23 => InputKey::Num5,
22 => InputKey::Num6,
26 => InputKey::Num7,
28 => InputKey::Num8,
25 => InputKey::Num9,
49 => InputKey::Space,
48 => InputKey::Tab,
36 => InputKey::Enter,
51 => InputKey::Backspace,
117 => InputKey::Delete,
123 => InputKey::Left,
124 => InputKey::Right,
125 => InputKey::Down,
126 => InputKey::Up,
27 => InputKey::Minus,
24 => InputKey::Equals,
33 => InputKey::LeftBracket,
30 => InputKey::RightBracket,
42 => InputKey::Backslash,
41 => InputKey::Semicolon,
39 => InputKey::Quote,
43 => InputKey::Comma,
47 => InputKey::Period,
44 => InputKey::Slash,
50 => InputKey::Backtick,
_ => return None,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_from_mac_covers_the_defaults() {
assert_eq!(key_from_mac(13), Some(InputKey::W));
assert_eq!(key_from_mac(0), Some(InputKey::A));
assert_eq!(key_from_mac(1), Some(InputKey::S));
assert_eq!(key_from_mac(2), Some(InputKey::D));
assert_eq!(key_from_mac(49), Some(InputKey::Space));
assert_eq!(key_from_mac(14), Some(InputKey::E));
assert_eq!(key_from_mac(53), None);
assert_eq!(key_from_mac(122), None);
}
#[test]
fn editing_keys_decode() {
assert_eq!(key_from_mac(51), Some(InputKey::Backspace));
assert_eq!(key_from_mac(117), Some(InputKey::Delete));
}
#[test]
fn printable_glyph_filter() {
assert!(is_printable_glyph('a'));
assert!(is_printable_glyph('Z'));
assert!(is_printable_glyph(' '));
assert!(is_printable_glyph('/'));
assert!(!is_printable_glyph('\u{8}')); assert!(!is_printable_glyph('\r')); assert!(!is_printable_glyph('\u{7f}')); assert!(!is_printable_glyph('\u{F702}')); }
}