@flyskypie/joypad-ts
Version:
A JavaScript library that lets you connect various gaming controllers to your browser using the Gamepad API.
203 lines (202 loc) • 6.59 kB
JavaScript
var O = Object.defineProperty;
var L = (t, e, s) => e in t ? O(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
var E = (t, e, s) => (L(t, typeof e != "symbol" ? e + "" : e, s), s);
class N {
constructor() {
E(this, "events", {});
}
publish(e, s) {
this.events.hasOwnProperty(e) && this.events[e].forEach((n) => n(s));
}
subscribe(e, s) {
return this.events.hasOwnProperty(e) || (this.events[e] = []), this.events[e].push(s), {
unsubscribe: () => {
const n = this.events[e].indexOf(s);
n !== -1 && this.events[e].splice(n, 1);
}
};
}
}
const A = new N();
var o = /* @__PURE__ */ ((t) => (t.CONNECT_NATIVE = "gamepadconnected", t.CONNECT_ALIAS = "connect", t.DISCONNECT_NATIVE = "gamepaddisconnected", t.DISCONNECT_ALIAS = "disconnect", t.BUTTON_PRESS_ALIAS = "button_press", t.BUTTON_RELEASE_ALIAS = "button_release", t.AXIS_MOVEMENT_ALIAS = "axis_move", t))(o || {});
const S = {
LEFT: {
NAME: "left_stick",
AXES: {
X: 0,
Y: 1
}
},
RIGHT: {
NAME: "right_stick",
AXES: {
X: 2,
Y: 3
}
}
}, T = {
LEFT: "left",
RIGHT: "right",
TOP: "top",
BOTTOM: "bottom"
}, M = {
button_0: 0,
button_1: 1,
button_2: 2,
button_3: 3,
button_4: 4,
button_5: 5,
button_6: 6,
button_7: 7,
button_8: 8,
button_9: 9,
button_10: 10,
button_11: 11,
button_12: 12,
button_13: 13,
button_14: 14,
button_15: 15,
button_16: 16,
button_17: 17
}, b = 0.8, f = (...t) => {
console.warn && typeof console.warn == "function" ? console.warn(...t) : console.log(...t);
}, w = (t, e) => {
let s = [];
return Object.keys(e).forEach((n) => {
e[n] === t && s.push(n);
const i = e[n];
Array.isArray(i) && i.indexOf(t) !== -1 && s.push(n);
}), s;
}, g = (t) => !!(t && t.type && t.playEffect && typeof t.playEffect == "function"), v = () => !!(window.navigator.getGamepads && typeof window.navigator.getGamepads == "function");
class C {
constructor() {
E(this, "loopStarted", !1);
E(this, "instances", {});
E(this, "buttonEvents", {
joypad: []
});
E(this, "settings", {
axisMovementThreshold: b
});
}
remove(e) {
return delete this.instances[e];
}
on(e, s) {
switch (e) {
case o.CONNECT_ALIAS:
return A.subscribe(o.CONNECT_ALIAS, s);
case o.DISCONNECT_ALIAS:
return A.subscribe(o.DISCONNECT_ALIAS, s);
case o.BUTTON_PRESS_ALIAS:
return A.subscribe(o.BUTTON_PRESS_ALIAS, s);
case o.BUTTON_RELEASE_ALIAS:
return A.subscribe(o.BUTTON_RELEASE_ALIAS, s);
case o.AXIS_MOVEMENT_ALIAS:
return A.subscribe(o.AXIS_MOVEMENT_ALIAS, s);
}
}
vibrate(e, s) {
const { vibrationActuator: n } = e, i = s || this.settings.vibration;
if (g(n)) {
const { type: r } = n;
return n.playEffect(r, i);
} else
f(
"No vibration actuator interface found - https://developer.mozilla.org/en-US/docs/Web/API/GamepadHapticActuator"
);
}
set(e) {
const { axisMovementThreshold: s, vibration: n, customButtonMapping: i } = e;
if (s !== void 0) {
const r = typeof s == "string" ? parseFloat(s) : s;
this.settings.axisMovementThreshold = r;
}
this.settings.vibration = n, this.settings.customButtonMapping = i;
}
trigger(e, s) {
return A.publish(e, s);
}
}
const l = new C();
class B {
constructor() {
E(this, "id", null);
E(this, "start", () => {
const e = window.requestAnimationFrame, { buttonEvents: s } = l;
let n = window.navigator.getGamepads();
n = Array.prototype.slice.call(n), n.forEach((i, r) => {
i && (s.joypad[r] || (s.joypad[r] = {}), l.instances[r] = i, m(i), y(i));
}), s.joypad.forEach((i) => {
i && Object.keys(i).forEach((r) => {
P(r, i);
});
}), this.id = e(this.start);
});
}
stop(e) {
if (e === null)
return;
const s = window.cancelAnimationFrame;
return s(e);
}
}
const _ = new B(), R = () => {
window.addEventListener(o.CONNECT_NATIVE, (t) => {
if (A.publish(o.CONNECT_ALIAS, t), !l.loopStarted)
return l.loopStarted = !0, _.start();
}), window.addEventListener(o.DISCONNECT_NATIVE, (t) => {
if (A.publish(o.DISCONNECT_ALIAS, t), l.remove(t.gamepad.index), l.buttonEvents.joypad[t.gamepad.index] = null, !Object.keys(l.instances).length)
return l.loopStarted = !1, _.stop(_.id);
}), window.addEventListener(o.BUTTON_PRESS_ALIAS, (t) => A.publish(o.BUTTON_PRESS_ALIAS, t)), window.addEventListener(o.BUTTON_RELEASE_ALIAS, (t) => A.publish(o.BUTTON_RELEASE_ALIAS, t)), window.addEventListener(o.AXIS_MOVEMENT_ALIAS, (t) => A.publish(o.AXIS_MOVEMENT_ALIAS, t));
}, m = (t) => {
t.buttons.forEach((e, s) => {
const { customButtonMapping: n } = l.settings, r = w(s, n || M), { buttonEvents: d } = l;
r && r.length && r.forEach((a) => {
const c = d.joypad[t.index];
c && (e.pressed ? (c[a] || (c[a] = {
pressed: !0,
hold: !1,
released: !1
}), c[a].button = e, c[a].index = s, c[a].gamepad = t) : !e.pressed && c[a] && (c[a].released = !0, c[a].hold = !1));
});
});
}, y = (t) => {
const e = (d) => new CustomEvent(o.AXIS_MOVEMENT_ALIAS, { detail: d }), { axisMovementThreshold: s } = l.settings, { axes: n } = t, r = n.length / 2;
n.forEach((d, a) => {
if (s && Math.abs(d) > s) {
let c = null, p = T.BOTTOM, h = d;
a < r ? c = S.LEFT.NAME : c = S.RIGHT.NAME, (a === S.LEFT.AXES.X || a === S.RIGHT.AXES.X) && (p = d < 0 ? T.LEFT : T.RIGHT), (a === S.LEFT.AXES.Y || a === S.RIGHT.AXES.Y) && (p = d < 0 ? T.TOP : T.BOTTOM);
const I = {
gamepad: t,
totalSticks: r,
stickMoved: c,
directionOfMovement: p,
axisMovementValue: h,
axis: a
};
return window.dispatchEvent(e(I));
}
});
}, u = (t, e, s) => {
const n = (a) => new CustomEvent(t, { detail: a }), { index: i, gamepad: r } = e[s], d = {
buttonName: s,
button: e[s].button,
index: i,
gamepad: r
};
window.dispatchEvent(n(d));
}, P = (t, e) => {
e[t].pressed ? (u(o.BUTTON_PRESS_ALIAS, e, t), e[t].pressed = !1, e[t].hold = !0, e[t].last_event = o.BUTTON_PRESS_ALIAS) : e[t].hold || e[t].released && e[t].last_event === o.BUTTON_PRESS_ALIAS && (u(
o.BUTTON_RELEASE_ALIAS,
e,
t
), delete e[t]);
};
R();
v() || f(
"Your browser does not support the Gamepad API - https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API"
);
export {
l as default
};