mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Add gamepad support
This commit is contained in:
@@ -192,11 +192,8 @@ KEYBOARD_MAX_CODE_SIZE :: 16
|
|||||||
GAMEPAD_MAX_ID_SIZE :: 64
|
GAMEPAD_MAX_ID_SIZE :: 64
|
||||||
GAMEPAD_MAX_MAPPING_SIZE :: 64
|
GAMEPAD_MAX_MAPPING_SIZE :: 64
|
||||||
|
|
||||||
Gamepad_Button :: struct {
|
GAMEPAD_MAX_BUTTONS :: 64
|
||||||
pressed: bool,
|
GAMEPAD_MAX_AXES :: 16
|
||||||
touched: bool,
|
|
||||||
value: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
Event_Target_Kind :: enum u32 {
|
Event_Target_Kind :: enum u32 {
|
||||||
Element = 0,
|
Element = 0,
|
||||||
@@ -218,6 +215,30 @@ Event_Option :: enum u8 {
|
|||||||
}
|
}
|
||||||
Event_Options :: distinct bit_set[Event_Option; 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 {
|
Event :: struct {
|
||||||
kind: Event_Kind,
|
kind: Event_Kind,
|
||||||
target_kind: Event_Target_Kind,
|
target_kind: Event_Target_Kind,
|
||||||
@@ -276,20 +297,7 @@ Event :: struct {
|
|||||||
buttons: bit_set[0..<16; u16],
|
buttons: bit_set[0..<16; u16],
|
||||||
},
|
},
|
||||||
|
|
||||||
gamepad: struct {
|
gamepad: Gamepad_State,
|
||||||
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:"-"`,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@@ -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)
|
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")
|
@(export, link_name="odin_dom_do_event_callback")
|
||||||
do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) {
|
do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) {
|
||||||
@(default_calling_convention="contextless")
|
@(default_calling_convention="contextless")
|
||||||
|
|||||||
@@ -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 {
|
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")
|
panic("vendor:wasm/js not supported on non JS targets")
|
||||||
}
|
}
|
||||||
|
|
||||||
+99
-10
@@ -1533,28 +1533,47 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev
|
|||||||
|
|
||||||
wmi.storeU8(off(1), !!e.repeat);
|
wmi.storeU8(off(1), !!e.repeat);
|
||||||
|
|
||||||
wmi.storeInt(off(W), e.key.length)
|
wmi.storeInt(off(W, W), e.key.length)
|
||||||
wmi.storeInt(off(W), e.code.length)
|
wmi.storeInt(off(W, W), e.code.length)
|
||||||
wmi.storeString(off(16, 1), e.key);
|
wmi.storeString(off(16, 1), e.key);
|
||||||
wmi.storeString(off(16, 1), e.code);
|
wmi.storeString(off(16, 1), e.code);
|
||||||
} else if (e.type === 'scroll') {
|
} else if (e.type === 'scroll') {
|
||||||
wmi.storeF64(off(8), window.scrollX);
|
wmi.storeF64(off(8, 8), window.scrollX);
|
||||||
wmi.storeF64(off(8), window.scrollY);
|
wmi.storeF64(off(8, 8), window.scrollY);
|
||||||
} else if (e.type === 'visibilitychange') {
|
} else if (e.type === 'visibilitychange') {
|
||||||
wmi.storeU8(off(1), !document.hidden);
|
wmi.storeU8(off(1), !document.hidden);
|
||||||
} else if (e instanceof GamepadEvent) {
|
} else if (e instanceof GamepadEvent) {
|
||||||
const idPtr = off(W*2, W);
|
const idPtr = off(W*2, W);
|
||||||
const mappingPtr = 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.storeU8(off(1), !!e.gamepad.connected);
|
||||||
wmi.storeF64(off(8), e.gamepad.timestamp);
|
wmi.storeF64(off(8, 8), e.gamepad.timestamp);
|
||||||
|
|
||||||
wmi.storeInt(off(W), e.gamepad.buttons.length);
|
wmi.storeInt(off(W, W), e.gamepad.buttons.length);
|
||||||
wmi.storeInt(off(W), e.gamepad.axes.length);
|
wmi.storeInt(off(W, W), e.gamepad.axes.length);
|
||||||
|
|
||||||
wmi.storeInt(off(W), e.gamepad.id.length)
|
for (let i = 0; i < 64; i++) {
|
||||||
wmi.storeInt(off(W), e.gamepad.mapping.length)
|
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, 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.id);
|
||||||
wmi.storeString(off(64, 1), e.gamepad.mapping);
|
wmi.storeString(off(64, 1), e.gamepad.mapping);
|
||||||
}
|
}
|
||||||
@@ -1661,6 +1680,76 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev
|
|||||||
return false;
|
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) => {
|
get_element_value_f64: (id_ptr, id_len) => {
|
||||||
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
let element = getElement(id);
|
let element = getElement(id);
|
||||||
|
|||||||
Reference in New Issue
Block a user