virtual-gamepad-lib
Version:
Emulate and display virtual and real gamepads on the web
113 lines (112 loc) • 7.95 kB
TypeScript
import { EGamepad } from './GamepadEmulator.js';
declare global {
interface Window {
mozRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
webkitRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
msRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
}
interface Navigator {
mozGetGamepads?: () => Gamepad[];
webkitGetGamepads?: () => Gamepad[];
msGetGamepads?: () => Gamepad[];
gamepadInputEmulation?: string;
getNativeGamepads?: () => (Gamepad | null)[] | undefined;
}
}
export interface wrapperConfig {
/** The (rough) delay between each update of the gamepad state in ms.
* A value of 0 means the gamepad state will be updated every frame */
updateDelay?: number;
/** A range in which axis values closer to zero than this are simply treated as zero
* Used to prevent noise from analog sticks from registering as changes when they are not being used */
axisDeadZone?: number;
/** An array of {@link wrapperButtonConfig} that tell the wrapper how to respond to button changes. Array index corresponds the the index of the button the a native browser gamepad.buttons array as returned from eg: `navigator.getGamepads()[0].buttons` */
buttonConfigs?: wrapperButtonConfig[];
}
export interface wrapperButtonConfig {
/** If true, the gamepad wrapper will keep firing button change events, while the button is held down */
fireWhileHolding: boolean;
}
export interface buttonChangeDetails {
/** This button was touched this gamepad update */
touchDown?: boolean;
/** This button was no longer touched this gamepad update */
touchUp?: boolean;
/** This button was pressed this gamepad update */
pressed?: boolean;
/** This button was released this gamepad update */
released?: boolean;
/** This button was pressed last update and is still pressed
* (only present if {@link wrapperButtonConfig.fireWhileHolding} was set to true on this button when the {@link GamepadApiWrapper} was initilized)*/
heldDown?: boolean;
/** The value of the button changed (e.g. for variable pressure buttons like shoulder triggers) */
valueChanged?: boolean;
}
export type ButtonChangeCallback = (gpadIndex: number, gpad: EGamepad | Gamepad, changesMask: readonly (buttonChangeDetails | false)[]) => void;
export type AxisChangeCallback = (gpadIndex: number, gpad: EGamepad | Gamepad, changesMask: readonly boolean[]) => void;
export type GamepadEventCallback = (e: GamepadEvent) => void;
/** Wrapper for the Gamepad API that smooths out browser inconsistancies.
* Exposes changes to gamepads, buttons and axes as events. */
export declare class GamepadApiWrapper {
protected updateDelay: number;
protected axisDeadZone: number;
protected buttonConfigs: wrapperButtonConfig[];
protected currentStateOfGamepads: (Gamepad | EGamepad | undefined)[];
protected gamepadConnectListeners: GamepadEventCallback[];
protected gamepadDisconnectListeners: GamepadEventCallback[];
protected gamepadButtonChangeListeners: ButtonChangeCallback[];
protected gamepadAxisChangeListeners: AxisChangeCallback[];
protected _requestAnimationFrame: (callback: FrameRequestCallback) => number;
protected _getGamepads: () => (Gamepad | null)[];
/** Create a new GamepadApiWrapper
* @param config The configuration options for this wrapper @see {@link wrapperConfig} */
constructor(config: wrapperConfig);
/** Changes the button configs used by the wrapper (takes effect after the next gamepad update) */
setButtonsConfig(buttonConfigs: wrapperButtonConfig[]): void;
/** Changes the update delay between browser gamepad api checks (takes effect after the next gamepad update)
* @param delay The new delay between gamepad updates in ms */
setUpdateDelay(delay: number): void;
/** Add an event listener for when a gamepad (either real or emulated) is connected
* @param Callback The calback function to call when a gamepad is connected */
onGamepadConnect(Callback: GamepadEventCallback): GamepadEventCallback;
/** remove an existing event listener for when a gamepad (either real or emulated) is connected
* @param Callback The calback function to remove (must be the same function passed to onGamepadConnect()) */
offGamepadConnect(Callback: GamepadEventCallback): void;
/** add an event listener for when a gamepad (either real or emulated) is disconnected
* @param Callback The calback function to call when a gamepad is disconnected */
onGamepadDisconnect(Callback: GamepadEventCallback): GamepadEventCallback;
/** remove an existing event listener for when a gamepad (either real or emulated) is disconnected
* @param Callback The calback function to remove (must be the same function passed to onGamepadDisconnect()) */
offGamepadDisconnect(Callback: GamepadEventCallback): void;
/** add an event listener for each time a gamepad axis changes.
* The callback function will be called with the gamepad index, the gamepad object, and a boolean array of the changed axes,
* The callback is called separately for each gamepad where axes have changed.
* @param Callback The calback function to call when a gamepad axis state changes */
onGamepadAxisChange(Callback: AxisChangeCallback): AxisChangeCallback;
/** offGamepadAxisChange: remove an existing event listener for when a gamepad axis changes
* @param Callback The calback function to remove (must be the same function passed to onGamepadAxisChange()) */
offGamepadAxisChange(Callback: AxisChangeCallback): void;
/**onGamepadButtonChange add an event listener for each time a gamepad button changes.
* The callback function will be called with the gamepad index, the gamepad object, and a array of the changed buttons containing details about how the button transitioned
* or false if the button state didn't change this frame. Callback is called separately for each gamepad where buttons have changed.
* @param Callback The calback function to call when a gamepad button state changes */
onGamepadButtonChange(Callback: ButtonChangeCallback): ButtonChangeCallback;
/** offGamepadButtonChange: remove an existing event listener for when a gamepad button changes
* @param Callback The calback function to remove (must be the same function passed to onGamepadButtonChange()) */
offGamepadButtonChange(Callback: ButtonChangeCallback): void;
/** gamepadApiSupported: returns true if the native gamepad api is supported by the browser context */
gamepadApiSupported(): boolean;
/** returns the value of navigator.getGamepads() in a cross-browser compatible way
* @returns An array of gamepad objects (including any emulated gamepads if the GamepadEmulator was set up), or an empty array if the gamepad api is not supported or gampad permissions haven't been granted. */
getGamepads(): (null | Gamepad | EGamepad)[];
/** Returns the result of navigator.getGamepads() from the last update
* @param forceUpdate If true, navigator.getGamepads() will be called inmediately before returning, if gamepad changes happened since the last update, this will cause those change events to fire.
* @returns An array of gamepad objects, or an empty array if the gamepad api is not supported */
getCurrentGamepadStates(forceUpdate?: boolean): (EGamepad | Gamepad | undefined)[];
/** (destructor) - Cleans up any event listeners and stops the gamepad check loop. Do not re-use class instance after calling cleanup(). */
cleanup(): void;
protected tickLoop(): void;
protected checkForGamepadChanges(): void;
protected checkForAxisChanges(gamepadIndex: number, gpad: EGamepad | Gamepad): void;
protected checkForButtonChanges(gpadIndex: number, gpad: EGamepad | Gamepad): void;
}