diff options
| author | gingerBill <bill@gingerbill.org> | 2024-09-22 19:29:05 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2024-09-22 19:29:05 +0100 |
| commit | 95721fe29670e404a2fb5e5fe5e51b39f5c7b9d6 (patch) | |
| tree | 2c31e09149bb133dafadddef54b6bc408c806048 /core/sys/wasm | |
| parent | 66e83ef30d990f544abf08fe47f1d83c4bc18168 (diff) | |
Add gamepad support
Diffstat (limited to 'core/sys/wasm')
| -rw-r--r-- | core/sys/wasm/js/events.odin | 60 | ||||
| -rw-r--r-- | core/sys/wasm/js/events_all_targets.odin | 3 | ||||
| -rw-r--r-- | core/sys/wasm/js/odin.js | 111 |
3 files changed, 142 insertions, 32 deletions
diff --git a/core/sys/wasm/js/events.odin b/core/sys/wasm/js/events.odin index 71191e3ab..905b3eba9 100644 --- a/core/sys/wasm/js/events.odin +++ b/core/sys/wasm/js/events.odin @@ -192,11 +192,8 @@ KEYBOARD_MAX_CODE_SIZE :: 16 GAMEPAD_MAX_ID_SIZE :: 64 GAMEPAD_MAX_MAPPING_SIZE :: 64 -Gamepad_Button :: struct { - pressed: bool, - touched: bool, - value: f64, -} +GAMEPAD_MAX_BUTTONS :: 64 +GAMEPAD_MAX_AXES :: 16 Event_Target_Kind :: enum u32 { Element = 0, @@ -218,6 +215,30 @@ Event_Option :: enum u8 { } Event_Options :: distinct bit_set[Event_Option; u8] +Gamepad_Button :: struct { + value: f64, + pressed: bool, + touched: bool, +} + +Gamepad_State :: struct { + id: string, + mapping: string, + index: int, + connected: bool, + timestamp: f64, + + button_count: int, + axis_count: int, + buttons: [GAMEPAD_MAX_BUTTONS]Gamepad_Button `fmt:"v,button_count"`, + axes: [GAMEPAD_MAX_AXES]f64 `fmt:"v,axes_count"`, + + _id_len: int `fmt:"-"`, + _mapping_len: int `fmt:"-"`, + _id_buf: [GAMEPAD_MAX_ID_SIZE]byte `fmt:"-"`, + _mapping_buf: [GAMEPAD_MAX_MAPPING_SIZE]byte `fmt:"-"`, +} + Event :: struct { kind: Event_Kind, target_kind: Event_Target_Kind, @@ -276,20 +297,7 @@ Event :: struct { buttons: bit_set[0..<16; u16], }, - gamepad: struct { - id: string, - mapping: string, - index: int, - connected: bool, - timestamp: f64, - button_count: int, - axes_count: int, - - _id_len: int `fmt:"-"`, - _mapping_len: int `fmt:"-"`, - _id_buf: [GAMEPAD_MAX_ID_SIZE]byte `fmt:"-"`, - _mapping_buf: [GAMEPAD_MAX_MAPPING_SIZE]byte `fmt:"-"`, - }, + gamepad: Gamepad_State, }, @@ -366,6 +374,20 @@ remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr return _remove_event_listener(id, name, user_data, callback) } +get_gamepad_state :: proc "contextless" (index: int, s: ^Gamepad_State) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="get_gamepad_state") + _get_gamepad_state :: proc(index: int, s: ^Gamepad_State) -> bool --- + } + + if s == nil { + return false + } + return _get_gamepad_state(index, s) +} + + @(export, link_name="odin_dom_do_event_callback") do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) { @(default_calling_convention="contextless") diff --git a/core/sys/wasm/js/events_all_targets.odin b/core/sys/wasm/js/events_all_targets.odin index ccf39015d..b7e01ca10 100644 --- a/core/sys/wasm/js/events_all_targets.odin +++ b/core/sys/wasm/js/events_all_targets.odin @@ -284,5 +284,4 @@ add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, c } remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool { panic("vendor:wasm/js not supported on non JS targets") -} - +}
\ No newline at end of file diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index 26c47255c..bf002da74 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -1533,28 +1533,47 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev wmi.storeU8(off(1), !!e.repeat); - wmi.storeInt(off(W), e.key.length) - wmi.storeInt(off(W), e.code.length) + wmi.storeInt(off(W, W), e.key.length) + wmi.storeInt(off(W, W), e.code.length) wmi.storeString(off(16, 1), e.key); wmi.storeString(off(16, 1), e.code); } else if (e.type === 'scroll') { - wmi.storeF64(off(8), window.scrollX); - wmi.storeF64(off(8), window.scrollY); + wmi.storeF64(off(8, 8), window.scrollX); + wmi.storeF64(off(8, 8), window.scrollY); } else if (e.type === 'visibilitychange') { wmi.storeU8(off(1), !document.hidden); } else if (e instanceof GamepadEvent) { const idPtr = off(W*2, W); const mappingPtr = off(W*2, W); - wmi.storeI32(off(W), e.gamepad.index); + wmi.storeI32(off(W, W), e.gamepad.index); wmi.storeU8(off(1), !!e.gamepad.connected); - wmi.storeF64(off(8), e.gamepad.timestamp); - - wmi.storeInt(off(W), e.gamepad.buttons.length); - wmi.storeInt(off(W), e.gamepad.axes.length); + wmi.storeF64(off(8, 8), e.gamepad.timestamp); + + wmi.storeInt(off(W, W), e.gamepad.buttons.length); + wmi.storeInt(off(W, W), e.gamepad.axes.length); + + for (let i = 0; i < 64; i++) { + if (i < e.gamepad.buttons.length) { + let b = e.gamepad.buttons[i]; + wmi.storeF64(off(8, 8), b.value); + wmi.storeU8(off(1), !!b.pressed); + wmi.storeU8(off(1), !!b.touched); + } else { + off(16, 8); + } + } + for (let i = 0; i < 16; i++) { + if (i < e.gamepad.axes.length) { + let a = e.gamepad.axes[i]; + wmi.storeF64(off(8, 8), a); + } else { + off(8, 8); + } + } - wmi.storeInt(off(W), e.gamepad.id.length) - wmi.storeInt(off(W), e.gamepad.mapping.length) + wmi.storeInt(off(W, W), e.gamepad.id.length) + wmi.storeInt(off(W, W), e.gamepad.mapping.length) wmi.storeString(off(64, 1), e.gamepad.id); wmi.storeString(off(64, 1), e.gamepad.mapping); } @@ -1661,6 +1680,76 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev return false; }, + get_gamepad_state: (gamepad_id, ep) => { + let index = gamepad_id; + let gps = navigator.getGamepads(); + if (0 <= index && index < gps.length) { + let gamepad = gps[index]; + if (!gamepad) { + return false; + } + + const W = wasmMemoryInterface.intSize; + let offset = ep; + let off = (amount, alignment) => { + if (alignment === undefined) { + alignment = Math.min(amount, W); + } + if (offset % alignment != 0) { + offset += alignment - (offset%alignment); + } + let x = offset; + offset += amount; + return x; + }; + + let align = (alignment) => { + const modulo = offset & (alignment-1); + if (modulo != 0) { + offset += alignment - modulo + } + }; + + let wmi = wasmMemoryInterface; + + const idPtr = off(W*2, W); + const mappingPtr = off(W*2, W); + + wmi.storeI32(off(W), gamepad.index); + wmi.storeU8(off(1), !!gamepad.connected); + wmi.storeF64(off(8), gamepad.timestamp); + + wmi.storeInt(off(W), gamepad.buttons.length); + wmi.storeInt(off(W), gamepad.axes.length); + + for (let i = 0; i < 64; i++) { + if (i < gamepad.buttons.length) { + let b = gamepad.buttons[i]; + wmi.storeF64(off(8, 8), b.value); + wmi.storeU8(off(1), !!b.pressed); + wmi.storeU8(off(1), !!b.touched); + } else { + off(16, 8); + } + } + for (let i = 0; i < 16; i++) { + if (i < gamepad.axes.length) { + wmi.storeF64(off(8, 8), gamepad.axes[i]); + } else { + off(8, 8); + } + } + + wmi.storeInt(off(W, W), gamepad.id.length) + wmi.storeInt(off(W, W), gamepad.mapping.length) + wmi.storeString(off(64, 1), gamepad.id); + wmi.storeString(off(64, 1), gamepad.mapping); + + return true; + } + return false; + }, + get_element_value_f64: (id_ptr, id_len) => { let id = wasmMemoryInterface.loadString(id_ptr, id_len); let element = getElement(id); |