virtual key codes

This commit is contained in:
2021-10-19 04:23:20 +02:00
parent 020fcd21dc
commit deaed7b456
5 changed files with 318 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ toml = "0.5.6"
gilrs = "0.7.4" gilrs = "0.7.4"
gltf = "0.15.2" gltf = "0.15.2"
glyph_brush = "0.7" glyph_brush = "0.7"
winapi = "0.3.9"
[profile.release] [profile.release]
debug = 1 debug = 1

View File

@@ -1,9 +1,9 @@
# Scan codes are in decimal # Scan codes are in decimal: https://www.millisecond.com/support/docs/v6/html/language/scancodes.htm
# See here: 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]] [[button]]
name = "quit" name = "quit"
scan_code = 1 vk_code = "VK_ESCAPE"
[[button]] [[button]]
name = "toggle_edit" name = "toggle_edit"

View File

@@ -20,7 +20,7 @@ scan_code = 30
[[button]] [[button]]
name = "button_right" name = "button_right"
scan_code = 32 vk_code = "VK_D"
[[axis]] [[axis]]
name = "move_sideways" name = "move_sideways"

View File

@@ -10,6 +10,8 @@ use gilrs;
use gilrs::{EventType, Gilrs}; use gilrs::{EventType, Gilrs};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use toml; 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 winit::event::{DeviceEvent, ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, ScanCode, Touch, TouchPhase, VirtualKeyCode, WindowEvent};
use crate::config::LogConfig; use crate::config::LogConfig;
@@ -47,6 +49,7 @@ struct InputConfigConfig {
struct InputConfigButton { struct InputConfigButton {
name: String, name: String,
scan_code: Option<u32>, scan_code: Option<u32>,
vk_code: Option<String>,
mouse: Option<String>, mouse: Option<String>,
touch: Option<u8>, touch: Option<u8>,
controller_button: Option<String>, controller_button: Option<String>,
@@ -133,6 +136,11 @@ impl InputState {
if let Some(scan_code) = bn.scan_code { if let Some(scan_code) = bn.scan_code {
inputs.push(DigitalInput::Keyboard(KeyboardInput { scan_code, key_code: None, modifiers: modifiers.clone() })); 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 // Mouse buttons
if let Some(button_name) = &bn.mouse { if let Some(button_name) = &bn.mouse {
@@ -807,4 +815,292 @@ fn string_to_touch_axis(touch_axis_name: &str) -> Option<TouchAxis> {
"rotate" => Some(TouchAxis::Rotate), "rotate" => Some(TouchAxis::Rotate),
_ => None, _ => 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<ScanCode> {
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
} }

View File

@@ -4,6 +4,7 @@ mod tests {
use winit::{dpi::PhysicalPosition, event::{DeviceId, ElementState, Event, Force, KeyboardInput, ModifiersState, Touch, TouchPhase, WindowEvent}, window::WindowId}; 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::{config::LogConfig, game::player::{intersect_triangle}, input::InputState};
use crate::input::vk_to_scan_code;
fn epsilon_eq(f1: f32, f2: f32) { fn epsilon_eq(f1: f32, f2: f32) {
assert!(f32::abs(f1 - f2) < f32::EPSILON, "{} == {}", f1, f2); assert!(f32::abs(f1 - f2) < f32::EPSILON, "{} == {}", f1, f2);
@@ -71,6 +72,16 @@ mod tests {
} }
state.frame_start(); state.frame_start();
assert_eq!(state.button_down("quit"), false); 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) { 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_just_released("doubletouchclick"), false);
assert_eq!(state.button_down("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));
}
} }