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;
            console.error("this navigator has no gamepad support!")
        }
        else {
            this.available =  true;
        }

        this.connected = false;
    }

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

            super.setup();
        }
    }

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

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

    /**
    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]);

        this.connected = true;
        //send connected event
        this.events.trigger("connected", incomingGamepad);
    }

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

        this.connected = false;
        //send disconnected event
        this.events.trigger("disconnected", incomingGamepad);
    }

    /**
    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];
                }
            }
        }
    }

    getGamePadFromIndex(index){
        this.updateGamePads();
        return this.gamepads[index];
    }

    /**
    Method to get a gamepad joysticks axes values
    @param index the gamapad's index to get axes from.
    @returns {Array} the axes array according to the capacities of the gamepad
    */
    getAllAxes(index) {
        if (this.available) {
            this.updateGamePads();

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

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

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

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

            this.updateGamePads();

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

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

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

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