fix(input): keys are physical positions on every layout; Input.key_label names them
The Windows runtime keyed the held set by the character MapVirtualKeyA gave a virtual key, so a game's WASD belonged to whatever the active layout put there, and with an input method on every letter arrived as VK_PROCESSKEY. The typing block is now read from the scancode (the arrows, numpad and F-keys still by virtual key); macOS reads keyCode the same way. Input.key_label(key) names a key in the player's own layout (Windows) or as its US character elsewhere. Verified on Windows with SendInput into a live window: VK_Z carrying W's scancode holds 'w', VK_PROCESSKEY carrying A's holds 'a', Caps Lock changes nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
2a2f463d5b
commit
619476ffed
14 changed files with 60552 additions and 60168 deletions
|
|
@ -449,6 +449,7 @@ function emit_ns_call(ns: pointer, meth: pointer, e: Node) -> Val {
|
|||
if (meth == "key_down") { bare = "input_key_down"; push(labels, "key") }
|
||||
if (meth == "key_pressed") { bare = "input_key_pressed"; push(labels, "key") }
|
||||
if (meth == "key_released") { bare = "input_key_released"; push(labels, "key") }
|
||||
if (meth == "key_label") { bare = "input_key_label"; push(labels, "key") }
|
||||
if (meth == "press") { bare = "input_press"; push(labels, "key") }
|
||||
if (meth == "release") { bare = "input_release"; push(labels, "key") }
|
||||
if (meth == "axis") { bare = "input_axis"; push(labels, "neg"); push(labels, "pos") }
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ function emit_header() -> void {
|
|||
emith("declare i32 @win_running()\n")
|
||||
emith("declare void @win_close()\n")
|
||||
emith("declare void @win_held(ptr)\n")
|
||||
emith("declare i32 @win_key_char(i32)\n")
|
||||
emith("declare void @win_mouse(ptr)\n")
|
||||
emith("declare void @win_pad(ptr)\n")
|
||||
emith("declare void @win_touch(ptr)\n")
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ function is_intrinsic2(name: pointer) -> bool {
|
|||
if (name == "win_open") or (name == "win_poll") or (name == "win_present") { return true }
|
||||
if (name == "win_running") or (name == "win_close") { return true }
|
||||
if (name == "win_held") or (name == "win_mouse") { return true } # #50 device layer
|
||||
if (name == "win_key_char") { return true } # Input.key_label
|
||||
if (name == "win_pad") or (name == "win_touch") { return true } # #51 gamepad / touch
|
||||
if (name == "win_cursor_mode") { return true } # #89 cursor capture
|
||||
if (name == "snd_load") or (name == "snd_play") or (name == "snd_stop") { return true } # #22 audio
|
||||
|
|
@ -71,6 +72,9 @@ function emit_intrinsic2(name: pointer, e: Node) -> Val {
|
|||
# button-mask, wheel-delta].
|
||||
if (name == "win_held") { let a = arg_code(e, 0); emit(" call void @win_held(ptr "); emit(a); emit(")\n"); return val("0", "void") }
|
||||
if (name == "win_mouse") { let a = arg_code(e, 0); emit(" call void @win_mouse(ptr "); emit(a); emit(")\n"); return val("0", "void") }
|
||||
# what the active keyboard layout types on a held-set key position (windowed only,
|
||||
# DCE'd headless): a code point, 0 for none.
|
||||
if (name == "win_key_char") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @win_key_char(i32 {a})`), "int") }
|
||||
# #51 — win_pad: 6 words/pad [connected, mask, lx, ly, rx, ry]; win_touch: 3
|
||||
# words/point [active, x, y]. Both windowed-only, DCE'd headless.
|
||||
if (name == "win_pad") { let a = arg_code(e, 0); emit(" call void @win_pad(ptr "); emit(a); emit(")\n"); return val("0", "void") }
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ function p_postfix() -> Node {
|
|||
if e.a.kind == E_ID and e.a.s == "Input" and (e.s == "bind" or e.s == "rebind" or e.s == "poll" or e.s == "down" or e.s == "pressed" or e.s == "record" or e.s == "replay" or e.s == "action" or e.s == "bind_pad" or e.s == "active" or e.s == "just_pressed" or e.s == "just_released") { g_uses_input = true }
|
||||
# #50 device layer — any of the multi-key / analog / mouse / gamepad / touch
|
||||
# methods also splices input.ludic (Input.key stays bare, no runtime).
|
||||
if e.a.kind == E_ID and e.a.s == "Input" and (e.s == "key_down" or e.s == "key_pressed" or e.s == "key_released" or e.s == "press" or e.s == "release" or e.s == "axis" or e.s == "axis_i" or e.s == "vector" or e.s == "strength" or e.s == "mouse_x" or e.s == "mouse_y" or e.s == "mouse_dx" or e.s == "mouse_dy" or e.s == "mouse_down" or e.s == "wheel" or e.s == "set_mouse" or e.s == "pad_connected" or e.s == "pad_button" or e.s == "pad_axis" or e.s == "move_i" or e.s == "set_pad" or e.s == "touch_count" or e.s == "touch_x" or e.s == "touch_y" or e.s == "set_touch" or e.s == "cursor_mode") { g_uses_input = true }
|
||||
if e.a.kind == E_ID and e.a.s == "Input" and (e.s == "key_down" or e.s == "key_pressed" or e.s == "key_released" or e.s == "key_label" or e.s == "press" or e.s == "release" or e.s == "axis" or e.s == "axis_i" or e.s == "vector" or e.s == "strength" or e.s == "mouse_x" or e.s == "mouse_y" or e.s == "mouse_dx" or e.s == "mouse_dy" or e.s == "mouse_down" or e.s == "wheel" or e.s == "set_mouse" or e.s == "pad_connected" or e.s == "pad_button" or e.s == "pad_axis" or e.s == "move_i" or e.s == "set_pad" or e.s == "touch_count" or e.s == "touch_x" or e.s == "touch_y" or e.s == "set_touch" or e.s == "cursor_mode") { g_uses_input = true }
|
||||
# Anim.play/clip/on_frame/fired + Motion.to (#48): the ergonomic writes over
|
||||
# the SpriteAnim/Motion components live in systems.ludic and use the world
|
||||
# table, so splice it and force the reflection ABI even if the game leaves
|
||||
|
|
|
|||
60248
selfhost/ludicc.seed.ll
60248
selfhost/ludicc.seed.ll
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue