From deaed7b4569aa2c956b870d061659ed2ee0f949f Mon Sep 17 00:00:00 2001 From: Asuro Date: Tue, 19 Oct 2021 04:23:20 +0200 Subject: [PATCH] virtual key codes --- Cargo.toml | 1 + config/input.toml | 6 +- config/testinput.toml | 2 +- src/input.rs | 296 ++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 17 +++ 5 files changed, 318 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3410318..ac9a754 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ toml = "0.5.6" gilrs = "0.7.4" gltf = "0.15.2" glyph_brush = "0.7" +winapi = "0.3.9" [profile.release] debug = 1 diff --git a/config/input.toml b/config/input.toml index e77c6ce..abceb91 100644 --- a/config/input.toml +++ b/config/input.toml @@ -1,9 +1,9 @@ -# Scan codes are in decimal -# See here: https://www.millisecond.com/support/docs/v6/html/language/scancodes.htm +# Scan codes are in decimal: https://www.millisecond.com/support/docs/v6/html/language/scancodes.htm +# VK code here: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes [[button]] name = "quit" -scan_code = 1 +vk_code = "VK_ESCAPE" [[button]] name = "toggle_edit" diff --git a/config/testinput.toml b/config/testinput.toml index ce1abf7..d6c2b57 100644 --- a/config/testinput.toml +++ b/config/testinput.toml @@ -20,7 +20,7 @@ scan_code = 30 [[button]] name = "button_right" -scan_code = 32 +vk_code = "VK_D" [[axis]] name = "move_sideways" diff --git a/src/input.rs b/src/input.rs index f915f7d..4172e8d 100644 --- a/src/input.rs +++ b/src/input.rs @@ -10,6 +10,8 @@ use gilrs; use gilrs::{EventType, Gilrs}; use serde_derive::{Deserialize, Serialize}; use toml; +use winapi::shared::minwindef::UINT; +use winapi::um::winuser; use winit::event::{DeviceEvent, ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, ScanCode, Touch, TouchPhase, VirtualKeyCode, WindowEvent}; use crate::config::LogConfig; @@ -47,6 +49,7 @@ struct InputConfigConfig { struct InputConfigButton { name: String, scan_code: Option, + vk_code: Option, mouse: Option, touch: Option, controller_button: Option, @@ -133,6 +136,11 @@ impl InputState { if let Some(scan_code) = bn.scan_code { inputs.push(DigitalInput::Keyboard(KeyboardInput { scan_code, key_code: None, modifiers: modifiers.clone() })); } + if let Some(vk_code) = &bn.vk_code { + if let Some(scan_code) = vk_to_scan_code(&vk_code) { + inputs.push(DigitalInput::Keyboard(KeyboardInput { scan_code, key_code: None, modifiers: modifiers.clone() })) + } + } // Mouse buttons if let Some(button_name) = &bn.mouse { @@ -807,4 +815,292 @@ fn string_to_touch_axis(touch_axis_name: &str) -> Option { "rotate" => Some(TouchAxis::Rotate), _ => None, } +} + + +// https://searchfox.org/mozilla-central/source/widget/windows/KeyboardLayout.cpp +const VIRTUAL_KEY_CODES: [&str; 256] = [ + "NULL", + "VK_LBUTTON", + "VK_RBUTTON", + "VK_CANCEL", + "VK_MBUTTON", + "VK_XBUTTON1", + "VK_XBUTTON2", + "0x07", + "VK_BACK", + "VK_TAB", + "0x0A", + "0x0B", + "VK_CLEAR", + "VK_RETURN", + "0x0E", + "0x0F", + + "VK_SHIFT", + "VK_CONTROL", + "VK_MENU", + "VK_PAUSE", + "VK_CAPITAL", + "VK_KANA, VK_HANGUL", + "0x16", + "VK_JUNJA", + "VK_FINAL", + "VK_HANJA, VK_KANJI", + "0x1A", + "VK_ESCAPE", + "VK_CONVERT", + "VK_NONCONVERT", + "VK_ACCEPT", + "VK_MODECHANGE", + + "VK_SPACE", + "VK_PRIOR", + "VK_NEXT", + "VK_END", + "VK_HOME", + "VK_LEFT", + "VK_UP", + "VK_RIGHT", + "VK_DOWN", + "VK_SELECT", + "VK_PRINT", + "VK_EXECUTE", + "VK_SNAPSHOT", + "VK_INSERT", + "VK_DELETE", + "VK_HELP", + + "VK_0", + "VK_1", + "VK_2", + "VK_3", + "VK_4", + "VK_5", + "VK_6", + "VK_7", + "VK_8", + "VK_9", + "0x3A", + "0x3B", + "0x3C", + "0x3D", + "0x3E", + "0x3F", + + "0x40", + "VK_A", + "VK_B", + "VK_C", + "VK_D", + "VK_E", + "VK_F", + "VK_G", + "VK_H", + "VK_I", + "VK_J", + "VK_K", + "VK_L", + "VK_M", + "VK_N", + "VK_O", + + "VK_P", + "VK_Q", + "VK_R", + "VK_S", + "VK_T", + "VK_U", + "VK_V", + "VK_W", + "VK_X", + "VK_Y", + "VK_Z", + "VK_LWIN", + "VK_RWIN", + "VK_APPS", + "0x5E", + "VK_SLEEP", + + "VK_NUMPAD0", + "VK_NUMPAD1", + "VK_NUMPAD2", + "VK_NUMPAD3", + "VK_NUMPAD4", + "VK_NUMPAD5", + "VK_NUMPAD6", + "VK_NUMPAD7", + "VK_NUMPAD8", + "VK_NUMPAD9", + "VK_MULTIPLY", + "VK_ADD", + "VK_SEPARATOR", + "VK_SUBTRACT", + "VK_DECIMAL", + "VK_DIVIDE", + + "VK_F1", + "VK_F2", + "VK_F3", + "VK_F4", + "VK_F5", + "VK_F6", + "VK_F7", + "VK_F8", + "VK_F9", + "VK_F10", + "VK_F11", + "VK_F12", + "VK_F13", + "VK_F14", + "VK_F15", + "VK_F16", + + "VK_F17", + "VK_F18", + "VK_F19", + "VK_F20", + "VK_F21", + "VK_F22", + "VK_F23", + "VK_F24", + "0x88", + "0x89", + "0x8A", + "0x8B", + "0x8C", + "0x8D", + "0x8E", + "0x8F", + + "VK_NUMLOCK", + "VK_SCROLL", + "VK_OEM_NEC_EQUAL, VK_OEM_FJ_JISHO", + "VK_OEM_FJ_MASSHOU", + "VK_OEM_FJ_TOUROKU", + "VK_OEM_FJ_LOYA", + "VK_OEM_FJ_ROYA", + "0x97", + "0x98", + "0x99", + "0x9A", + "0x9B", + "0x9C", + "0x9D", + "0x9E", + "0x9F", + + "VK_LSHIFT", + "VK_RSHIFT", + "VK_LCONTROL", + "VK_RCONTROL", + "VK_LMENU", + "VK_RMENU", + "VK_BROWSER_BACK", + "VK_BROWSER_FORWARD", + "VK_BROWSER_REFRESH", + "VK_BROWSER_STOP", + "VK_BROWSER_SEARCH", + "VK_BROWSER_FAVORITES", + "VK_BROWSER_HOME", + "VK_VOLUME_MUTE", + "VK_VOLUME_DOWN", + "VK_VOLUME_UP", + + "VK_MEDIA_NEXT_TRACK", + "VK_MEDIA_PREV_TRACK", + "VK_MEDIA_STOP", + "VK_MEDIA_PLAY_PAUSE", + "VK_LAUNCH_MAIL", + "VK_LAUNCH_MEDIA_SELECT", + "VK_LAUNCH_APP1", + "VK_LAUNCH_APP2", + "0xB8", + "0xB9", + "VK_OEM_1", + "VK_OEM_PLUS", + "VK_OEM_COMMA", + "VK_OEM_MINUS", + "VK_OEM_PERIOD", + "VK_OEM_2", + + "VK_OEM_3", + "VK_ABNT_C1", + "VK_ABNT_C2", + "0xC3", + "0xC4", + "0xC5", + "0xC6", + "0xC7", + "0xC8", + "0xC9", + "0xCA", + "0xCB", + "0xCC", + "0xCD", + "0xCE", + "0xCF", + + "0xD0", + "0xD1", + "0xD2", + "0xD3", + "0xD4", + "0xD5", + "0xD6", + "0xD7", + "0xD8", + "0xD9", + "0xDA", + "VK_OEM_4", + "VK_OEM_5", + "VK_OEM_6", + "VK_OEM_7", + "VK_OEM_8", + + "0xE0", + "VK_OEM_AX", + "VK_OEM_102", + "VK_ICO_HELP", + "VK_ICO_00", + "VK_PROCESSKEY", + "VK_ICO_CLEAR", + "VK_PACKET", + "0xE8", + "VK_OEM_RESET", + "VK_OEM_JUMP", + "VK_OEM_PA1", + "VK_OEM_PA2", + "VK_OEM_PA3", + "VK_OEM_WSCTRL", + "VK_OEM_CUSEL", + + "VK_OEM_ATTN", + "VK_OEM_FINISH", + "VK_OEM_COPY", + "VK_OEM_AUTO", + "VK_OEM_ENLW", + "VK_OEM_BACKTAB", + "VK_ATTN", + "VK_CRSEL", + "VK_EXSEL", + "VK_EREOF", + "VK_PLAY", + "VK_ZOOM", + "VK_NONAME", + "VK_PA1", + "VK_OEM_CLEAR", + "0xFF" +]; + +pub fn vk_to_scan_code(name: &str) -> Option { + let index = VIRTUAL_KEY_CODES.iter().position(|c| c == &name); + if let Some(idx) = index { + unsafe { + let vc = winuser::MapVirtualKeyA(idx as UINT, winuser::MAPVK_VK_TO_VSC); + if vc == 0 { return None } + return Some(vc as ScanCode); + } + } + None } \ No newline at end of file diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 13414a5..15d4a03 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -4,6 +4,7 @@ mod tests { use winit::{dpi::PhysicalPosition, event::{DeviceId, ElementState, Event, Force, KeyboardInput, ModifiersState, Touch, TouchPhase, WindowEvent}, window::WindowId}; use crate::{config::LogConfig, game::player::{intersect_triangle}, input::InputState}; + use crate::input::vk_to_scan_code; fn epsilon_eq(f1: f32, f2: f32) { assert!(f32::abs(f1 - f2) < f32::EPSILON, "{} == {}", f1, f2); @@ -71,6 +72,16 @@ mod tests { } state.frame_start(); assert_eq!(state.button_down("quit"), false); + state.frame_end(); + unsafe { + state.on_window_event(&Event::WindowEvent{ window_id: WindowId::dummy(), event: WindowEvent::KeyboardInput { + device_id: DeviceId::dummy(), + input: KeyboardInput { scancode: 32, state: ElementState::Pressed, virtual_keycode: None, modifiers: ModifiersState::empty() }, + is_synthetic: true, + }}); + } + state.frame_start(); + assert_eq!(state.button_down("button_right"), true); } fn touch_event(state: &mut InputState, phase: TouchPhase, id: u64) { @@ -136,4 +147,10 @@ mod tests { // assert_eq!(state.button_just_released("doubletouchclick"), false); assert_eq!(state.button_down("doubletouchclick"), false); } + + #[test] + fn vk_input_name_test() { + let vk = "VK_ESCAPE"; + assert_eq!(vk_to_scan_code(vk), Some(1)); + } } \ No newline at end of file