Add browser gamepad support with pad button pictograms
Co-Authored-By: deepseek-v4.1-flash (opencode-go) via CodeCraft
This commit is contained in:
1 parent
073999d592
commit
8d51d6ec6a
26 files changed
+1066
-22
No files matched your search
@@ -11,6 +11,16 @@
|
||||
var fetched = { state: 0 }; // download of a file from the server: 0 idle, 1 running, 2 done, 3 failed
|
||||
var ws = {}; // socket id -> { state, queue, sock }
|
||||
var wsNext = 1;
|
||||
var gpPad = null; // the gamepad handed out by dc_gamepad_slot (reused for its buttons/axes)
|
||||
var gpSlot = -1;
|
||||
// browsers offer the Gamepad API only in a secure context (https or localhost)
|
||||
function gamepads() {
|
||||
try {
|
||||
return navigator.getGamepads ? navigator.getGamepads() : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function bytes(ptr, len) {
|
||||
return new Uint8Array(wasm_memory.buffer, ptr, len);
|
||||
@@ -193,6 +203,66 @@
|
||||
env.dc_coarse_pointer = function () {
|
||||
try { return window.matchMedia("(pointer: coarse)").matches ? 1 : 0; } catch (e) { return 0; }
|
||||
};
|
||||
// ---- gamepads: the game polls these functions once per frame (see src/pad.rs).
|
||||
// The Gamepad API needs a secure context (https or localhost) and shows a pad only after
|
||||
// its first button press. slot = the index in navigator.getGamepads(), -1 = no gamepad.
|
||||
env.dc_gamepad_slot = function () {
|
||||
gpPad = null;
|
||||
gpSlot = -1;
|
||||
var pads = gamepads();
|
||||
for (var i = 0; i < pads.length; i++) {
|
||||
if (pads[i] && pads[i].connected && pads[i].mapping === "standard") {
|
||||
gpPad = pads[i];
|
||||
gpSlot = i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// a pad without the standard mapping (old DirectInput devices): use it anyway
|
||||
for (var j = 0; j < pads.length; j++) {
|
||||
if (pads[j] && pads[j].connected) {
|
||||
gpPad = pads[j];
|
||||
gpSlot = j;
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
function gamepad(slot) {
|
||||
if (gpPad && slot === gpSlot) return gpPad;
|
||||
var pads = gamepads();
|
||||
return pads[slot] && pads[slot].connected ? pads[slot] : null;
|
||||
}
|
||||
// bit i set: standard button i is down (triggers count from 40 % on)
|
||||
env.dc_gamepad_buttons = function (slot) {
|
||||
var p = gamepad(slot);
|
||||
if (!p) return 0;
|
||||
var m = 0;
|
||||
for (var i = 0; i < p.buttons.length && i < 16; i++) {
|
||||
var b = p.buttons[i];
|
||||
if (b && (b.pressed || b.value > 0.4)) m |= 1 << i;
|
||||
}
|
||||
return m;
|
||||
};
|
||||
// axis 0/1 = left stick x/y, 2/3 = right stick x/y (all -1..1)
|
||||
env.dc_gamepad_axis = function (slot, axis) {
|
||||
var p = gamepad(slot);
|
||||
if (!p || !p.axes || axis < 0 || axis >= p.axes.length) return 0;
|
||||
return p.axes[axis];
|
||||
};
|
||||
// 0 unknown, 1 Xbox, 2 PlayStation, 3 Nintendo (from the pad's id)
|
||||
// (the Xbox check comes first: its id contains "Wireless Controller" too)
|
||||
env.dc_gamepad_kind = function (slot) {
|
||||
var p = gamepad(slot);
|
||||
if (!p) return 0;
|
||||
var id = (p.id || "").toLowerCase();
|
||||
if (id.indexOf("xbox") >= 0 || id.indexOf("xinput") >= 0 || id.indexOf("microsoft") >= 0) return 1;
|
||||
if (id.indexOf("nintendo") >= 0 || id.indexOf("switch") >= 0 || id.indexOf("joy-con") >= 0 ||
|
||||
id.indexOf("joycon") >= 0 || id.indexOf("pro controller") >= 0) return 3;
|
||||
if (id.indexOf("playstation") >= 0 || id.indexOf("dualshock") >= 0 || id.indexOf("dualsense") >= 0 ||
|
||||
id.indexOf("sony") >= 0 || id.indexOf("wireless controller") >= 0 || id.indexOf("054c") >= 0 ||
|
||||
/(^|[^0-9])ps[345]([^0-9]|$)/.test(id)) return 2;
|
||||
return 0;
|
||||
};
|
||||
env.dc_storage_set = function (kp, kl, vp, vl) {
|
||||
try { window.localStorage.setItem(str(kp, kl), str(vp, vl)); } catch (e) { }
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user