Repository

js/Mobilizing/input/Gamepad.js

import Component from '../core/Component';

export default class Gamepad extends Component {
    /**
    Gamepad class is a simple layer on top of the official Gamepad API : https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API

    @param {Object} params
    */
    constructor() {
        super(...arguments);

        /**
        True is the Gamepad API is supported
        @type {Boolean}
        */
        this.available = false;

        if (navigator.getGamepads || navigator.webkitGetGamepads) {
            //this.getGamepads = navigator.getGamepads;
            this.available = true;
        }
        else {
            console.error("this navigator has no gamepad support!")
        }
    }

    setup() {
        if (!this._setupDone) {
            //all gamepads
            this.gamepads = {};
            //the most recently connected gamepad index
            this.currentGamepadIndex = undefined;

            super.setup();
        }
    }

    on() {
        window.addEventListener("gamepadconnected", this.gamepadConnectedHandler.bind(this));
        window.addEventListener("gamepaddisconnected", this.gamepadDisconnectedHandler.bind(this));
    }

    off() {
        window.removeEventListener("gamepadconnected", this.gamepadConnectedHandler.bind(this));
        window.removeEventListener("gamepaddisconnected", this.gamepadDisconnectedHandler.bind(this));
    }

    /**
    Gamepad connection handler
    @param {Event} event
    */
    gamepadConnectedHandler(event) {
        const incomingGamepad = event.gamepad;
        this.gamepads[incomingGamepad.index] = incomingGamepad;

        this.currentGamepadIndex = incomingGamepad.index;
        console.log(this.currentGamepadIndex, this.gamepads[incomingGamepad.index]);
    }

    /**
    Gamepad disconnection handler
    @param {Event} event
    */
    gamepadDisconnectedHandler(event) {
        const incomingGamepad = event.gamepad;
        delete this.gamepads[incomingGamepad.index];
    }

    /**
    Updates the gamepads state, according to the API
    @private
    */
    updateGamePads() {
        if (this.available) {
            //list from navigator service
            const gamepads = navigator.getGamepads();

            for (let i = 0; i < gamepads.length; i++) {
                if (gamepads[i]) {
                    const index = gamepads[i].index;
                    this.gamepads[index] = gamepads[i];
                }
            }
        }
    }

    /**
    Method to get a gamepad joysticks axes values
    @param index the gamapad's index to get axes from.
    @returns {Object} the axes as {0 : {x,y}, 1 : {x,y}, ...} according to the capacities of the gamepad
    */
    getAllAxes(index) {
        this.updateGamePads();

        if (!index) {
            index = this.currentGamepadIndex;
        }

        const gamepad = this.gamepads[index];
        const axes = {}

        if (gamepad) {
            //generates an object to organize all axis coordinates
            for (let axeIndex = 0, coordIndex = 0; axeIndex < gamepad.axes.length; axeIndex += 2, coordIndex++) {
                axes[coordIndex] = {};
                axes[coordIndex].x = gamepad.axes[axeIndex];
                axes[coordIndex].y = gamepad.axes[axeIndex + 1];
            }
        }

        return axes;
    }

    /**
    Method to get a specific axes's deltas
    @param {Number} axeIndex
    @param {Number} gamepadIndex
    */
    getAxes(axesIndex, gamepadIndex) {
        const axes = this.getAllAxes(gamepadIndex);

        return axes[axesIndex];
    }

    /**
    Method to get all the buttons of this gamepad
    @param {Number} index
    @returns {Object} all buttons object in their original format
    */
    getAllButtons(index) {
        this.updateGamePads();

        if (!index) {
            index = this.currentGamepadIndex;
        }

        const gamepad = this.gamepads[index];
        let buttons = {}

        if (gamepad) {
            buttons = gamepad.buttons;
        }
        return buttons;
    }

    /**
    Method to get a specific button's state
    @param {Number} buttonIndex
    @param {Number} gamepadIndex
    */
    getButton(buttonIndex, gamepadIndex) {
        const buttons = this.getAllButtons(gamepadIndex);

        return buttons[buttonIndex];
    }
}