use std::collections::HashSet;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum KeyCode {
KeyA, KeyB, KeyC, KeyD, KeyE, KeyF, KeyG, KeyH, KeyI, KeyJ, KeyK, KeyL, KeyM,
KeyN, KeyO, KeyP, KeyQ, KeyR, KeyS, KeyT, KeyU, KeyV, KeyW, KeyX, KeyY, KeyZ,
Digit0, Digit1, Digit2, Digit3, Digit4,
Digit5, Digit6, Digit7, Digit8, Digit9,
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
NumpadAdd, NumpadSubtract, NumpadMultiply, NumpadDivide, NumpadDecimal, NumpadEnter,
NumLock,
F1, F2, F3, F4, F5, F6,
F7, F8, F9, F10, F11, F12,
F13, F14, F15, F16, F17, F18,
F19, F20, F21, F22, F23, F24,
ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
Home, End, PageUp, PageDown, Insert, Delete,
ShiftLeft, ShiftRight, ControlLeft, ControlRight, AltLeft, AltRight,
SuperLeft, SuperRight,
Backspace, Enter, Tab, Escape, Space, CapsLock,
Minus, Equal, BracketLeft, BracketRight, Backslash,
Semicolon, Quote, Backquote, Comma, Period, Slash,
ScrollLock, Pause, PrintScreen,
Unknown,
}
pub(crate) fn vk_to_keycode(vk: u16, extended: bool) -> KeyCode {
match vk {
0x08 => KeyCode::Backspace,
0x09 => KeyCode::Tab,
0x0D => if extended { KeyCode::NumpadEnter } else { KeyCode::Enter },
0x13 => KeyCode::Pause,
0x14 => KeyCode::CapsLock,
0x1B => KeyCode::Escape,
0x20 => KeyCode::Space,
0x21 => KeyCode::PageUp,
0x22 => KeyCode::PageDown,
0x23 => KeyCode::End,
0x24 => KeyCode::Home,
0x25 => KeyCode::ArrowLeft,
0x26 => KeyCode::ArrowUp,
0x27 => KeyCode::ArrowRight,
0x28 => KeyCode::ArrowDown,
0x2C => KeyCode::PrintScreen,
0x2D => KeyCode::Insert,
0x2E => KeyCode::Delete,
0x30 => KeyCode::Digit0,
0x31 => KeyCode::Digit1,
0x32 => KeyCode::Digit2,
0x33 => KeyCode::Digit3,
0x34 => KeyCode::Digit4,
0x35 => KeyCode::Digit5,
0x36 => KeyCode::Digit6,
0x37 => KeyCode::Digit7,
0x38 => KeyCode::Digit8,
0x39 => KeyCode::Digit9,
0x41 => KeyCode::KeyA,
0x42 => KeyCode::KeyB,
0x43 => KeyCode::KeyC,
0x44 => KeyCode::KeyD,
0x45 => KeyCode::KeyE,
0x46 => KeyCode::KeyF,
0x47 => KeyCode::KeyG,
0x48 => KeyCode::KeyH,
0x49 => KeyCode::KeyI,
0x4A => KeyCode::KeyJ,
0x4B => KeyCode::KeyK,
0x4C => KeyCode::KeyL,
0x4D => KeyCode::KeyM,
0x4E => KeyCode::KeyN,
0x4F => KeyCode::KeyO,
0x50 => KeyCode::KeyP,
0x51 => KeyCode::KeyQ,
0x52 => KeyCode::KeyR,
0x53 => KeyCode::KeyS,
0x54 => KeyCode::KeyT,
0x55 => KeyCode::KeyU,
0x56 => KeyCode::KeyV,
0x57 => KeyCode::KeyW,
0x58 => KeyCode::KeyX,
0x59 => KeyCode::KeyY,
0x5A => KeyCode::KeyZ,
0x5B => KeyCode::SuperLeft,
0x5C => KeyCode::SuperRight,
0x60 => KeyCode::Numpad0,
0x61 => KeyCode::Numpad1,
0x62 => KeyCode::Numpad2,
0x63 => KeyCode::Numpad3,
0x64 => KeyCode::Numpad4,
0x65 => KeyCode::Numpad5,
0x66 => KeyCode::Numpad6,
0x67 => KeyCode::Numpad7,
0x68 => KeyCode::Numpad8,
0x69 => KeyCode::Numpad9,
0x6A => KeyCode::NumpadMultiply,
0x6B => KeyCode::NumpadAdd,
0x6D => KeyCode::NumpadSubtract,
0x6E => KeyCode::NumpadDecimal,
0x6F => KeyCode::NumpadDivide,
0x70 => KeyCode::F1,
0x71 => KeyCode::F2,
0x72 => KeyCode::F3,
0x73 => KeyCode::F4,
0x74 => KeyCode::F5,
0x75 => KeyCode::F6,
0x76 => KeyCode::F7,
0x77 => KeyCode::F8,
0x78 => KeyCode::F9,
0x79 => KeyCode::F10,
0x7A => KeyCode::F11,
0x7B => KeyCode::F12,
0x7C => KeyCode::F13,
0x7D => KeyCode::F14,
0x7E => KeyCode::F15,
0x7F => KeyCode::F16,
0x80 => KeyCode::F17,
0x81 => KeyCode::F18,
0x82 => KeyCode::F19,
0x83 => KeyCode::F20,
0x84 => KeyCode::F21,
0x85 => KeyCode::F22,
0x86 => KeyCode::F23,
0x87 => KeyCode::F24,
0x90 => KeyCode::NumLock,
0x91 => KeyCode::ScrollLock,
0xA0 => KeyCode::ShiftLeft,
0xA1 => KeyCode::ShiftRight,
0xA2 => KeyCode::ControlLeft,
0xA3 => KeyCode::ControlRight,
0xA4 => KeyCode::AltLeft,
0xA5 => KeyCode::AltRight,
0xBA => KeyCode::Semicolon,
0xBB => KeyCode::Equal,
0xBC => KeyCode::Comma,
0xBD => KeyCode::Minus,
0xBE => KeyCode::Period,
0xBF => KeyCode::Slash,
0xC0 => KeyCode::Backquote,
0xDB => KeyCode::BracketLeft,
0xDC => KeyCode::Backslash,
0xDD => KeyCode::BracketRight,
0xDE => KeyCode::Quote,
_ => KeyCode::Unknown,
}
}
#[derive(Default)]
struct InputState {
current: HashSet<KeyCode>,
previous: HashSet<KeyCode>,
}
impl InputState {
fn commit(&mut self) { self.previous.clone_from(&self.current); }
fn press(&mut self, key: KeyCode) { self.current.insert(key); }
fn release(&mut self, key: KeyCode) { self.current.remove(&key); }
}
thread_local! {
static INPUT: std::cell::RefCell<InputState> = std::cell::RefCell::new(InputState::default());
}
pub(crate) fn process_key_event(key: KeyCode, pressed: bool) {
INPUT.with(|s| { let mut s = s.borrow_mut(); if pressed { s.press(key); } else { s.release(key); } });
}
pub(crate) fn commit_input() {
INPUT.with(|s| s.borrow_mut().commit());
}
pub fn is_pressed(key: KeyCode) -> bool {
INPUT.with(|s| s.borrow().current.contains(&key))
}
pub fn is_just_pressed(key: KeyCode) -> bool {
INPUT.with(|s| { let s = s.borrow(); s.current.contains(&key) && !s.previous.contains(&key) })
}
pub fn is_released(key: KeyCode) -> bool {
INPUT.with(|s| { let s = s.borrow(); !s.current.contains(&key) && s.previous.contains(&key) })
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum MouseButton { Left, Right, Middle }
struct MouseState {
x: i32,
y: i32,
current: [bool; 3],
previous: [bool; 3],
}
impl Default for MouseState {
fn default() -> Self { Self { x: 0, y: 0, current: [false; 3], previous: [false; 3] } }
}
fn btn_idx(b: MouseButton) -> usize {
match b { MouseButton::Left => 0, MouseButton::Right => 1, MouseButton::Middle => 2 }
}
thread_local! {
static MOUSE: std::cell::RefCell<MouseState> = std::cell::RefCell::new(MouseState::default());
}
pub(crate) fn commit_mouse_input() {
MOUSE.with(|m| { let mut m = m.borrow_mut(); m.previous = m.current; });
}
pub(crate) fn process_mouse_move(x: i32, y: i32) {
MOUSE.with(|m| { let mut m = m.borrow_mut(); m.x = x; m.y = y; });
}
pub(crate) fn process_mouse_button(btn: MouseButton, pressed: bool) {
MOUSE.with(|m| { m.borrow_mut().current[btn_idx(btn)] = pressed; });
}
pub(crate) fn mouse_position() -> (i32, i32) {
MOUSE.with(|m| { let m = m.borrow(); (m.x, m.y) })
}
pub fn is_mouse_pressed(btn: MouseButton) -> bool {
MOUSE.with(|m| m.borrow().current[btn_idx(btn)])
}
pub fn is_mouse_just_pressed(btn: MouseButton) -> bool {
MOUSE.with(|m| { let m = m.borrow(); m.current[btn_idx(btn)] && !m.previous[btn_idx(btn)] })
}
pub fn is_mouse_released(btn: MouseButton) -> bool {
MOUSE.with(|m| { let m = m.borrow(); !m.current[btn_idx(btn)] && m.previous[btn_idx(btn)] })
}