use-control
Version:
A powerful set of hooks for elegantly handling keyboard, mouse and gamepad input (soon)
69 lines • 3.32 kB
JavaScript
import { useEffect } from 'react';
import { Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
var buttonCache = {};
var poll;
export var gamepadButtonPress$ = new Subject();
export var gamepadButtonHeld$ = new Subject();
export var gamepadButtonReleased$ = new Subject();
export var gamepadAxes$ = new Subject();
// TODO(ben): consider using an interval() stream for the tick
export function initGamepad(pollIntervalMs) {
if (pollIntervalMs === void 0) { pollIntervalMs = 1000 / 60; }
// makes init idempotent
if (poll)
clearInterval(poll);
poll = setInterval(function () {
var _a;
var gamepads = navigator.getGamepads
? navigator.getGamepads()
: navigator.webkitGetGamepads
? navigator.webkitGetGamepads()
: [];
if (!gamepads)
return;
for (var ctrlIdx = 0; ctrlIdx < gamepads.length; ctrlIdx++) {
if (gamepads[ctrlIdx]) {
for (var btnIdx = 0; btnIdx < gamepads[0].buttons.length; btnIdx++) {
var btn = gamepads[ctrlIdx].buttons[btnIdx];
var cachedBtn = ((_a = buttonCache === null || buttonCache === void 0 ? void 0 : buttonCache[ctrlIdx]) === null || _a === void 0 ? void 0 : _a[btnIdx]) || {};
if (btn.pressed) {
// TODO(ben): technically speaking this isn't used, we actually handle "held" through the higher level hook useButtonHeld
gamepadButtonHeld$.next({ controllerIndex: 0, buttonIndex: btnIdx });
}
if (!btn.pressed && cachedBtn.pressed) {
gamepadButtonReleased$.next({ controllerIndex: ctrlIdx, buttonIndex: btnIdx });
}
if (btn.pressed && !cachedBtn.pressed) {
gamepadButtonPress$.next({ controllerIndex: ctrlIdx, buttonIndex: btnIdx });
}
}
buttonCache[ctrlIdx] = gamepads[ctrlIdx].buttons.slice();
for (var axisIdx = 0; axisIdx < gamepads[ctrlIdx].axes.length; axisIdx++) {
var axis = gamepads[ctrlIdx].axes[axisIdx];
gamepadAxes$.next({ controllerIndex: ctrlIdx, axisIndex: axisIdx, value: axis });
}
}
}
}, pollIntervalMs);
}
export function teardownGamepad() {
clearInterval(poll);
}
export function useGamepadButtonPressed(controllerIndex, buttonIndex, sink) {
useEffect(function () {
var sub = gamepadButtonPress$
.pipe(filter(function (p) { return p.buttonIndex === buttonIndex && p.controllerIndex === controllerIndex; }))
.subscribe(sink);
return function () { return sub.unsubscribe(); };
}, [controllerIndex, buttonIndex, sink]);
}
export function useGamepadAxis(controllerIndex, axisIndex, sink) {
useEffect(function () {
var sub = gamepadAxes$
.pipe(filter(function (p) { return p.axisIndex === axisIndex && p.controllerIndex === controllerIndex; }), map(function (p) { return p.value; }))
.subscribe(sink);
return function () { return sub.unsubscribe(); };
}, [controllerIndex, axisIndex, sink]);
}
//# sourceMappingURL=gamepad.js.map