/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @author       Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var BaseSoundManager = require('../BaseSoundManager');
var Class = require('../../utils/Class');
var WebAudioSound = require('./WebAudioSound');

/**
 * @classdesc
 * Web Audio API implementation of the sound manager.
 *
 * @class WebAudioSoundManager
 * @extends Phaser.Sound.BaseSoundManager
 * @memberOf Phaser.Sound
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Game} game - Reference to the current game instance.
 */
var WebAudioSoundManager = new Class({

    Extends: BaseSoundManager,

    initialize:

    function WebAudioSoundManager (game)
    {
        /**
         * The AudioContext being used for playback.
         *
         * @name Phaser.Sound.WebAudioSoundManager#context
         * @type {AudioContext}
         * @private
         * @since 3.0.0
         */
        this.context = this.createAudioContext(game);

        /**
         * Gain node responsible for controlling global muting.
         *
         * @name Phaser.Sound.WebAudioSoundManager#masterMuteNode
         * @type {GainNode}
         * @private
         * @since 3.0.0
         */
        this.masterMuteNode = this.context.createGain();

        /**
         * Gain node responsible for controlling global volume.
         *
         * @name Phaser.Sound.WebAudioSoundManager#masterVolumeNode
         * @type {GainNode}
         * @private
         * @since 3.0.0
         */
        this.masterVolumeNode = this.context.createGain();

        this.masterMuteNode.connect(this.masterVolumeNode);

        this.masterVolumeNode.connect(this.context.destination);

        /**
         * Destination node for connecting individual sounds to.
         *
         * @name Phaser.Sound.WebAudioSoundManager#destination
         * @type {AudioNode}
         * @private
         * @since 3.0.0
         */
        this.destination = this.masterMuteNode;

        this.locked = this.context.state === 'suspended' && ('ontouchstart' in window || 'onclick' in window);

        BaseSoundManager.call(this, game);

        if (this.locked)
        {
            this.unlock();
        }
    },

    /**
     * Method responsible for instantiating and returning AudioContext instance.
     * If an instance of an AudioContext class was provided through the game config,
     * that instance will be returned instead. This can come in handy if you are reloading
     * a Phaser game on a page that never properly refreshes (such as in an SPA project)
     * and you want to reuse already instantiated AudioContext.
     *
     * @method Phaser.Sound.WebAudioSoundManager#createAudioContext
     * @private
     * @since 3.0.0
     *
     * @param {Phaser.Game} game - Reference to the current game instance.
     *
     * @return {AudioContext} The AudioContext instance to be used for playback.
     */
    createAudioContext: function (game)
    {
        var audioConfig = game.config.audio;

        if (audioConfig && audioConfig.context)
        {
            audioConfig.context.resume();

            return audioConfig.context;
        }

        return new AudioContext();
    },

    /**
     * Adds a new sound into the sound manager.
     *
     * @method Phaser.Sound.WebAudioSoundManager#add
     * @since 3.0.0
     *
     * @param {string} key - Asset key for the sound.
     * @param {SoundConfig} [config] - An optional config object containing default sound settings.
     *
     * @return {Phaser.Sound.WebAudioSound} The new sound instance.
     */
    add: function (key, config)
    {
        var sound = new WebAudioSound(this, key, config);

        this.sounds.push(sound);

        return sound;
    },

    /**
     * Unlocks Web Audio API on the initial input event.
     *
     * Read more about how this issue is handled here in [this article](https://medium.com/@pgoloskokovic/unlocking-web-audio-the-smarter-way-8858218c0e09).
     *
     * @method Phaser.Sound.WebAudioSoundManager#unlock
     * @since 3.0.0
     */
    unlock: function ()
    {
        var _this = this;

        var unlock = function ()
        {
            _this.context.resume().then(function ()
            {
                document.body.removeEventListener('touchstart', unlock);
                document.body.removeEventListener('touchend', unlock);
                document.body.removeEventListener('click', unlock);

                _this.unlocked = true;
            });
        };

        if (document.body)
        {
            document.body.addEventListener('touchstart', unlock, false);
            document.body.addEventListener('touchend', unlock, false);
            document.body.addEventListener('click', unlock, false);
        }
    },

    /**
     * Method used internally for pausing sound manager if
     * Phaser.Sound.WebAudioSoundManager#pauseOnBlur is set to true.
     *
     * @method Phaser.Sound.WebAudioSoundManager#onBlur
     * @protected
     * @since 3.0.0
     */
    onBlur: function ()
    {
        this.context.suspend();
    },

    /**
     * Method used internally for resuming sound manager if
     * Phaser.Sound.WebAudioSoundManager#pauseOnBlur is set to true.
     *
     * @method Phaser.Sound.WebAudioSoundManager#onFocus
     * @protected
     * @since 3.0.0
     */
    onFocus: function ()
    {
        this.context.resume();
    },

    /**
     * Calls Phaser.Sound.BaseSoundManager#destroy method
     * and cleans up all Web Audio API related stuff.
     *
     * @method Phaser.Sound.WebAudioSoundManager#destroy
     * @since 3.0.0
     */
    destroy: function ()
    {
        this.destination = null;
        this.masterVolumeNode.disconnect();
        this.masterVolumeNode = null;
        this.masterMuteNode.disconnect();
        this.masterMuteNode = null;

        if (this.game.config.audio && this.game.config.audio.context)
        {
            this.context.suspend();
        }
        else
        {
            var _this = this;

            this.context.close().then(function ()
            {

                _this.context = null;

            });
        }

        BaseSoundManager.prototype.destroy.call(this);
    },

    /**
     * @event Phaser.Sound.WebAudioSoundManager#muteEvent
     * @param {Phaser.Sound.WebAudioSoundManager} soundManager - Reference to the sound manager that emitted event.
     * @param {boolean} value - An updated value of Phaser.Sound.WebAudioSoundManager#mute property.
     */

    /**
     * Sets the muted state of all this Sound Manager.
     *
     * @method Phaser.Sound.WebAudioSoundManager#setMute
     * @fires Phaser.Sound.WebAudioSoundManager#muteEvent
     * @since 3.3.0
     *
     * @param {boolean} value - `true` to mute all sounds, `false` to unmute them.
     *
     * @return {Phaser.Sound.WebAudioSoundManager} This Sound Manager.
     */
    setMute: function (value)
    {
        this.mute = value;

        return this;
    },

    /**
     * @name Phaser.Sound.WebAudioSoundManager#mute
     * @type {boolean}
     * @fires Phaser.Sound.WebAudioSoundManager#MuteEvent
     * @since 3.0.0
     */
    mute: {

        get: function ()
        {
            return (this.masterMuteNode.gain.value === 0);
        },

        set: function (value)
        {
            this.masterMuteNode.gain.setValueAtTime(value ? 0 : 1, 0);

            this.emit('mute', this, value);
        }

    },

    /**
     * @event Phaser.Sound.WebAudioSoundManager#VolumeEvent
     * @param {Phaser.Sound.WebAudioSoundManager} soundManager - Reference to the sound manager that emitted event.
     * @param {number} value - An updated value of Phaser.Sound.WebAudioSoundManager#volume property.
     */

    /**
     * Sets the volume of this Sound Manager.
     *
     * @method Phaser.Sound.WebAudioSoundManager#setVolume
     * @fires Phaser.Sound.WebAudioSoundManager#VolumeEvent
     * @since 3.3.0
     *
     * @param {number} value - The global volume of this Sound Manager.
     *
     * @return {Phaser.Sound.WebAudioSoundManager} This Sound Manager.
     */
    setVolume: function (value)
    {
        this.volume = value;

        return this;
    },

    /**
     * @name Phaser.Sound.WebAudioSoundManager#volume
     * @type {number}
     * @fires Phaser.Sound.WebAudioSoundManager#VolumeEvent
     * @since 3.0.0
     */
    volume: {

        get: function ()
        {
            return this.masterVolumeNode.gain.value;
        },

        set: function (value)
        {
            this.masterVolumeNode.gain.setValueAtTime(value, 0);

            this.emit('volume', this, value);
        }

    }

});

module.exports = WebAudioSoundManager;


* graphics.strokeRect(50, 50, 200, 200);

* When a Graphics object is rendered it will render differently based on if the game is running under Canvas or WebGL.

* Under Canvas it will use the HTML Canvas context drawing operations to draw the path.

* Under WebGL the graphics data is decomposed into polygons. Both of these are expensive processes, especially with

keep keep keep keep replace replace keep keep keep keep keep

* graphics.strokeRect(50, 50, 400, 200);

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Cameras
 */

module.exports = {

    Controls: require('./controls'),
    Scene2D: require('./2d'),
    Sprite3D: require('./sprite3d')

};


* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.

* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.

* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested

* @param {CanvasRenderingContext2D} renderTargetCtx - [description]

* @param {boolean} allowClip - [description]

var GraphicsCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix, renderTargetCtx, allowClip)

if (GameObject.RENDER_MASK !== src.renderFlags || (src.cameraFilter > 0 && (src.cameraFilter & camera._id)))

keep keep keep replace keep keep keep keep keep

* @param {CanvasRenderingContext2D} [renderTargetCtx] - The target rendering context.

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Axis = require('./Axis');
var Button = require('./Button');
var Class = require('../../utils/Class');
var EventEmitter = require('eventemitter3');
var Vector2 = require('../../math/Vector2');

/**
 * @classdesc
 * A single Gamepad.
 *
 * These are created, updated and managed by the Gamepad Manager.
 *
 * @class Gamepad
 * @extends Phaser.Events.EventEmitter
 * @memberOf Phaser.Input.Gamepad
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Input.Gamepad.GamepadManager} manager - A reference to the Gamepad Manager.
 * @param {Pad} pad - The Gamepad object, as extracted from GamepadEvent.
 */
var Gamepad = new Class({

    Extends: EventEmitter,

    initialize:

    function Gamepad (manager, pad)
    {
        EventEmitter.call(this);

        /**
         * A reference to the Gamepad Manager.
         *
         * @name Phaser.Input.Gamepad.Gamepad#manager
         * @type {Phaser.Input.Gamepad.GamepadManager}
         * @since 3.0.0
         */
        this.manager = manager;

        /**
         * A reference to the native Gamepad object that is connected to the browser.
         *
         * @name Phaser.Input.Gamepad.Gamepad#pad
         * @type {any}
         * @since 3.10.0
         */
        this.pad = pad;

        /**
         * A string containing some information about the controller.
         *
         * This is not strictly specified, but in Firefox it will contain three pieces of information
         * separated by dashes (-): two 4-digit hexadecimal strings containing the USB vendor and
         * product id of the controller, and the name of the controller as provided by the driver.
         * In Chrome it will contain the name of the controller as provided by the driver,
         * followed by vendor and product 4-digit hexadecimal strings.
         *
         * @name Phaser.Input.Gamepad.Gamepad#id
         * @type {string}
         * @since 3.0.0
         */
        this.id = pad.id;

        /**
         * An integer that is unique for each Gamepad currently connected to the system.
         * This can be used to distinguish multiple controllers.
         * Note that disconnecting a device and then connecting a new device may reuse the previous index.
         *
         * @name Phaser.Input.Gamepad.Gamepad#index
         * @type {number}
         * @since 3.0.0
         */
        this.index = pad.index;

        var buttons = [];

        for (var i = 0; i < pad.buttons.length; i++)
        {
            buttons.push(new Button(this, i));
        }

        /**
         * An array of Gamepad Button objects, corresponding to the different buttons available on the Gamepad.
         *
         * @name Phaser.Input.Gamepad.Gamepad#buttons
         * @type {Phaser.Input.Gamepad.Button[]}
         * @since 3.0.0
         */
        this.buttons = buttons;

        var axes = [];

        for (i = 0; i < pad.axes.length; i++)
        {
            axes.push(new Axis(this, i));
        }

        /**
         * An array of Gamepad Axis objects, corresponding to the different axes available on the Gamepad, if any.
         *
         * @name Phaser.Input.Gamepad.Gamepad#axes
         * @type {Phaser.Input.Gamepad.Axis[]}
         * @since 3.0.0
         */
        this.axes = axes;

        /**
         * The Gamepad's Haptic Actuator (Vibration / Rumble support).
         * This is highly experimental and only set if both present on the device,
         * and exposed by both the hardware and browser.
         *
         * @name Phaser.Input.Gamepad.Gamepad#vibration
         * @type {GamepadHapticActuator}
         * @since 3.10.0
         */
        this.vibration = pad.vibrationActuator;

        // https://w3c.github.io/gamepad/#remapping

        var _noButton = { value: 0, pressed: false };

        /**
         * A reference to the Left Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCLeft = (buttons[14]) ? buttons[14] : _noButton;

        /**
         * A reference to the Right Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCRight = (buttons[15]) ? buttons[15] : _noButton;

        /**
         * A reference to the Top Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCTop = (buttons[12]) ? buttons[12] : _noButton;

        /**
         * A reference to the Bottom Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCBottom = (buttons[13]) ? buttons[13] : _noButton;

        /**
         * A reference to the Left Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCLeft = (buttons[2]) ? buttons[2] : _noButton;

        /**
         * A reference to the Right Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCRight = (buttons[1]) ? buttons[1] : _noButton;

        /**
         * A reference to the Top Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCTop = (buttons[3]) ? buttons[3] : _noButton;

        /**
         * A reference to the Bottom Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCBottom = (buttons[0]) ? buttons[0] : _noButton;

        /**
         * A reference to the Top Left Front Button (L1 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBLeftTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBLeftTop = (buttons[4]) ? buttons[4] : _noButton;

        /**
         * A reference to the Bottom Left Front Button (L2 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBLeftBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBLeftBottom = (buttons[6]) ? buttons[6] : _noButton;

        /**
         * A reference to the Top Right Front Button (R1 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBRightTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBRightTop = (buttons[5]) ? buttons[5] : _noButton;

        /**
         * A reference to the Bottom Right Front Button (R2 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBRightBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBRightBottom = (buttons[7]) ? buttons[7] : _noButton;

        var _noAxis = { value: 0 };

        /**
         * A reference to the Horizontal Axis for the Left Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_HAxisLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._HAxisLeft = (axes[0]) ? axes[0] : _noAxis;

        /**
         * A reference to the Vertical Axis for the Left Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_VAxisLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._VAxisLeft = (axes[1]) ? axes[1] : _noAxis;

        /**
         * A reference to the Horizontal Axis for the Right Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_HAxisRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._HAxisRight = (axes[2]) ? axes[2] : _noAxis;

        /**
         * A reference to the Vertical Axis for the Right Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_VAxisRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._VAxisRight = (axes[3]) ? axes[3] : _noAxis;

        /**
         * A Vector2 containing the most recent values from the Gamepad's left axis stick.
         * This is updated automatically as part of the Gamepad.update cycle.
         * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property.
         * The values are based on the Axis thresholds.
         * If the Gamepad does not have a left axis stick, the values will always be zero.
         *
         * @name Phaser.Input.Gamepad.Gamepad#leftStick
         * @type {Phaser.Math.Vector2}
         * @since 3.10.0
         */
        this.leftStick = new Vector2();

        /**
         * A Vector2 containing the most recent values from the Gamepad's right axis stick.
         * This is updated automatically as part of the Gamepad.update cycle.
         * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property.
         * The values are based on the Axis thresholds.
         * If the Gamepad does not have a right axis stick, the values will always be zero.
         *
         * @name Phaser.Input.Gamepad.Gamepad#rightStick
         * @type {Phaser.Math.Vector2}
         * @since 3.10.0
         */
        this.rightStick = new Vector2();
    },

    /**
     * Gets the total number of axis this Gamepad claims to support.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getAxisTotal
     * @since 3.10.0
     *
     * @return {integer} The total number of axes this Gamepad claims to support.
     */
    getAxisTotal: function ()
    {
        return this.axes.length;
    },

    /**
     * Gets the value of an axis based on the given index.
     * The index must be valid within the range of axes supported by this Gamepad.
     * The return value will be a float between 0 and 1.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getAxisValue
     * @since 3.10.0
     *
     * @param {integer} index - The index of the axes to get the value for.
     *
     * @return {number} The value of the axis, between 0 and 1.
     */
    getAxisValue: function (index)
    {
        return this.axes[index].getValue();
    },

    /**
     * Sets the threshold value of all axis on this Gamepad.
     * The value is a float between 0 and 1 and is the amount below which the axis is considered as not having been moved.
     *
     * @method Phaser.Input.Gamepad.Gamepad#setAxisThreshold
     * @since 3.10.0
     *
     * @param {number} value - A value between 0 and 1.
     */
    setAxisThreshold: function (value)
    {
        for (var i = 0; i < this.axes.length; i++)
        {
            this.axes[i].threshold = value;
        }
    },

    /**
     * Gets the total number of buttons this Gamepad claims to have.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getButtonTotal
     * @since 3.10.0
     *
     * @return {integer} The total number of buttons this Gamepad claims to have.
     */
    getButtonTotal: function ()
    {
        return this.buttons.length;
    },

    /**
     * Gets the value of a button based on the given index.
     * The index must be valid within the range of buttons supported by this Gamepad.
     *
     * The return value will be either 0 or 1 for an analogue button, or a float between 0 and 1
     * for a pressure-sensitive digital button, such as the shoulder buttons on a Dual Shock.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getButtonValue
     * @since 3.10.0
     *
     * @param {integer} index - The index of the button to get the value for.
     *
     * @return {number} The value of the button, between 0 and 1.
     */
    getButtonValue: function (index)
    {
        return this.buttons[index].value;
    },

    /**
     * Returns if the button is pressed down or not.
     * The index must be valid within the range of buttons supported by this Gamepad.
     *
     * @method Phaser.Input.Gamepad.Gamepad#isButtonDown
     * @since 3.10.0
     *
     * @param {integer} index - The index of the button to get the value for.
     *
     * @return {boolean} `true` if the button is considered as being pressed down, otherwise `false`.
     */
    isButtonDown: function (index)
    {
        return this.buttons[index].pressed;
    },

    /**
     * Internal update handler for this Gamepad.
     * Called automatically by the Gamepad Manager as part of its update.
     *
     * @method Phaser.Input.Gamepad.Gamepad#update
     * @private
     * @since 3.0.0
     */
    update: function (pad)
    {
        var i;

        //  Sync the button values

        var localButtons = this.buttons;
        var gamepadButtons = pad.buttons;

        var len = localButtons.length;

        for (i = 0; i < len; i++)
        {
            localButtons[i].update(gamepadButtons[i].value);
        }

        //  Sync the axis values

        var localAxes = this.axes;
        var gamepadAxes = pad.axes;

        len = localAxes.length;

        for (i = 0; i < len; i++)
        {
            localAxes[i].update(gamepadAxes[i]);
        }

        if (len >= 2)
        {
            this.leftStick.set(localAxes[0].getValue(), localAxes[1].getValue());

            if (len >= 4)
            {
                this.rightStick.set(localAxes[2].getValue(), localAxes[3].getValue());
            }
        }
    },

    /**
     * Destroys this Gamepad instance, its buttons and axes, and releases external references it holds.
     *
     * @method Phaser.Input.Gamepad.Gamepad#destroy
     * @since 3.10.0
     */
    destroy: function ()
    {
        this.removeAllListeners();

        this.manager = null;
        this.pad = null;

        var i;

        for (i = 0; i < this.buttons.length; i++)
        {
            this.buttons[i].destroy();
        }

        for (i = 0; i < this.axes.length; i++)
        {
            this.axes[i].destroy();
        }

        this.buttons = [];
        this.axes = [];
    },

    /**
     * Is this Gamepad currently connected or not?
     *
     * @name Phaser.Input.Gamepad.Gamepad#connected
     * @type {boolean}
     * @default true
     * @since 3.0.0
     */
    connected: {

        get: function ()
        {
            return this.pad.connected;
        }

    },

    /**
     * A timestamp containing the most recent time this Gamepad was updated.
     *
     * @name Phaser.Input.Gamepad.Gamepad#timestamp
     * @type {number}
     * @since 3.0.0
     */
    timestamp: {

        get: function ()
        {
            return this.pad.timestamp;
        }

    },

    /**
     * Is the Gamepad's Left button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad left button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#left
     * @type {boolean}
     * @since 3.10.0
     */
    left: {

        get: function ()
        {
            return this._LCLeft.pressed;
        }

    },

    /**
     * Is the Gamepad's Right button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad right button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#right
     * @type {boolean}
     * @since 3.10.0
     */
    right: {

        get: function ()
        {
            return this._LCRight.pressed;
        }

    },

    /**
     * Is the Gamepad's Up button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad up button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#up
     * @type {boolean}
     * @since 3.10.0
     */
    up: {

        get: function ()
        {
            return this._LCTop.pressed;
        }

    },

    /**
     * Is the Gamepad's Down button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad down button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#down
     * @type {boolean}
     * @since 3.10.0
     */
    down: {

        get: function ()
        {
            return this._LCBottom.pressed;
        }

    },

    /**
     * Is the Gamepad's bottom button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the X button.
     * On an XBox controller it's the A button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#A
     * @type {boolean}
     * @since 3.10.0
     */
    A: {

        get: function ()
        {
            return this._RCBottom.pressed;
        }

    },

    /**
     * Is the Gamepad's top button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Triangle button.
     * On an XBox controller it's the Y button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#Y
     * @type {boolean}
     * @since 3.10.0
     */
    Y: {

        get: function ()
        {
            return this._RCTop.pressed;
        }

    },

    /**
     * Is the Gamepad's left button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Square button.
     * On an XBox controller it's the X button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#X
     * @type {boolean}
     * @since 3.10.0
     */
    X: {

        get: function ()
        {
            return this._RCLeft.pressed;
        }

    },

    /**
     * Is the Gamepad's right button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Circle button.
     * On an XBox controller it's the B button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#B
     * @type {boolean}
     * @since 3.10.0
     */
    B: {

        get: function ()
        {
            return this._RCRight.pressed;
        }

    },

    /**
     * Returns the value of the Gamepad's top left shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the L1 button.
     * On an XBox controller it's the LB button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#L1
     * @type {number}
     * @since 3.10.0
     */
    L1: {

        get: function ()
        {
            return this._FBLeftTop.value
        }

    },

    /**
     * Returns the value of the Gamepad's bottom left shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the L2 button.
     * On an XBox controller it's the LT button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#L2
     * @type {number}
     * @since 3.10.0
     */
    L2: {

        get: function ()
        {
            return this._FBLeftBottom.value
        }

    },

    /**
     * Returns the value of the Gamepad's top right shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the R1 button.
     * On an XBox controller it's the RB button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#R1
     * @type {number}
     * @since 3.10.0
     */
    R1: {

        get: function ()
        {
            return this._FBRightTop.value
        }

    },

    /**
     * Returns the value of the Gamepad's bottom right shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the R2 button.
     * On an XBox controller it's the RT button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#R2
     * @type {number}
     * @since 3.10.0
     */
    R2: {

        get: function ()
        {
            return this._FBRightBottom.value
        }

    }

});

module.exports = Gamepad;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Snap a value to nearest grid slice, using rounding.
 *
 * Example: if you have an interval gap of `5` and a position of `12`... you will snap to `10` whereas `14` will snap to `15`.
 *
 * @function Phaser.Math.Snap.To
 * @since 3.0.0
 *
 * @param {number} value - The value to snap.
 * @param {number} gap - The interval gap of the grid.
 * @param {number} [start=0] - Optional starting offset for gap.
 *
 * @return {number} The snapped value.
 */
var SnapTo = function (value, gap, start)
{
    if (start === undefined) { start = 0; }

    if (gap === 0)
    {
        return value;
    }

    value -= start;
    value = gap * Math.round(value / gap);

    return start + value;
};

module.exports = SnapTo;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var GetTilesWithin = require('./GetTilesWithin');

/**
 * @callback FindTileCallback
 *
 * @param {Phaser.Tilemaps.Tile} value - [description]
 * @param {number} index - [description]
 * @param {Phaser.Tilemaps.Tile[]} array - [description]
 *
 * @return {boolean} [description]
 */

/**
 * Find the first tile in the given rectangular area (in tile coordinates) of the layer that
 * satisfies the provided testing function. I.e. finds the first tile for which `callback` returns
 * true. Similar to Array.prototype.find in vanilla JS.
 *
 * @function Phaser.Tilemaps.Components.FindTile
 * @private
 * @since 3.0.0
 *
 * @param {FindTileCallback} callback - The callback. Each tile in the given area will be passed to this
 * callback as the first and only parameter.
 * @param {object} [context] - The context under which the callback should be run.
 * @param {integer} [tileX=0] - [description]
 * @param {integer} [tileY=0] - [description]
 * @param {integer} [width=max width based on tileX] - [description]
 * @param {integer} [height=max height based on tileY] - [description]
 * @param {object} [filteringOptions] - Optional filters to apply when getting the tiles.
 * @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have
 * -1 for an index.
 * @param {boolean} [filteringOptions.isColliding=false] - If true, only return tiles that collide
 * on at least one side.
 * @param {boolean} [filteringOptions.hasInterestingFace=false] - If true, only return tiles that
 * have at least one interesting face.
 * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon.
 *
 * @return {?Phaser.Tilemaps.Tile} A Tile that matches the search, or null if no Tile found
 */
var FindTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer)
{
    var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer);
    return tiles.find(callback, context) || null;
};

module.exports = FindTile;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

// Centers this Rectangle so that the center coordinates match the given x and y values.

/**
 * [description]
 *
 * @function Phaser.Geom.Rectangle.CenterOn
 * @since 3.0.0
 *
 * @generic {Phaser.Geom.Rectangle} O - [rect,$return]
 *
 * @param {Phaser.Geom.Rectangle} rect - [description]
 * @param {number} x - [description]
 * @param {number} y - [description]
 *
 * @return {Phaser.Geom.Rectangle} [description]
 */
var CenterOn = function (rect, x, y)
{
    rect.x = x - (rect.width / 2);
    rect.y = y - (rect.height / 2);

    return rect;
};

module.exports = CenterOn;


* @param {object} [config] - [description]

* @return {Phaser.GameObjects.Graphics} The Game Object that was created.

keep keep keep replace replace keep keep keep

* @param {GraphicsOptions} [config] - The Graphics configuration.


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var OS = require('./OS');
var Browser = require('./Browser');
var CanvasPool = require('../display/canvas/CanvasPool');

/**
 * Determines the features of the browser running this Phaser Game instance.
 * These values are read-only and populated during the boot sequence of the game.
 * They are then referenced by internal game systems and are available for you to access
 * via `this.sys.game.device.features` from within any Scene.
 *
 * @typedef {object} Phaser.Device.Features
 * @since 3.0.0
 *
 * @property {?boolean} canvasBitBltShift - True if canvas supports a 'copy' bitblt onto itself when the source and destination regions overlap.
 * @property {boolean} canvas - Is canvas available?
 * @property {boolean} file - Is file available?
 * @property {boolean} fileSystem - Is fileSystem available?
 * @property {boolean} getUserMedia - Does the device support the getUserMedia API?
 * @property {boolean} littleEndian - Is the device big or little endian? (only detected if the browser supports TypedArrays)
 * @property {boolean} localStorage - Is localStorage available?
 * @property {boolean} pointerLock - Is Pointer Lock available?
 * @property {boolean} support32bit - Does the device context support 32bit pixel manipulation using array buffer views?
 * @property {boolean} vibration - Does the device support the Vibration API?
 * @property {boolean} webGL - Is webGL available?
 * @property {boolean} worker - Is worker available?
 */
var Features = {

    canvas: false,
    canvasBitBltShift: null,
    file: false,
    fileSystem: false,
    getUserMedia: true,
    littleEndian: false,
    localStorage: false,
    pointerLock: false,
    support32bit: false,
    vibration: false,
    webGL: false,
    worker: false

};

// Check Little or Big Endian system.
// @author Matt DesLauriers (@mattdesl)
function checkIsLittleEndian ()
{
    var a = new ArrayBuffer(4);
    var b = new Uint8Array(a);
    var c = new Uint32Array(a);

    b[0] = 0xa1;
    b[1] = 0xb2;
    b[2] = 0xc3;
    b[3] = 0xd4;

    if (c[0] === 0xd4c3b2a1)
    {
        return true;
    }

    if (c[0] === 0xa1b2c3d4)
    {
        return false;
    }
    else
    {
        //  Could not determine endianness
        return null;
    }
}

function init ()
{
    Features.canvas = !!window['CanvasRenderingContext2D'] || OS.cocoonJS;

    try
    {
        Features.localStorage = !!localStorage.getItem;
    }
    catch (error)
    {
        Features.localStorage = false;
    }

    Features.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob'];
    Features.fileSystem = !!window['requestFileSystem'];

    var isUint8 = false;

    var testWebGL = function ()
    {
        if (window['WebGLRenderingContext'])
        {
            try
            {
                var canvas = CanvasPool.createWebGL(this);

                if (OS.cocoonJS)
                {
                    canvas.screencanvas = false;
                }

                var ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

                var canvas2D = CanvasPool.create2D(this);

                var ctx2D = canvas2D.getContext('2d');

                //  Can't be done on a webgl context
                var image = ctx2D.createImageData(1, 1);

                //  Test to see if ImageData uses CanvasPixelArray or Uint8ClampedArray.
                //  @author Matt DesLauriers (@mattdesl)
                isUint8 = image.data instanceof Uint8ClampedArray;

                CanvasPool.remove(canvas);
                CanvasPool.remove(canvas2D);

                return !!ctx;
            }
            catch (e)
            {
                return false;
            }
        }

        return false;
    };

    Features.webGL = testWebGL();

    Features.worker = !!window['Worker'];

    Features.pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;

    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;

    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

    Features.getUserMedia = Features.getUserMedia && !!navigator.getUserMedia && !!window.URL;

    // Older versions of firefox (< 21) apparently claim support but user media does not actually work
    if (Browser.firefox && Browser.firefoxVersion < 21)
    {
        Features.getUserMedia = false;
    }

    // Excludes iOS versions as they generally wrap UIWebView (eg. Safari WebKit) and it
    // is safer to not try and use the fast copy-over method.
    if (!OS.iOS && (Browser.ie || Browser.firefox || Browser.chrome))
    {
        Features.canvasBitBltShift = true;
    }

    // Known not to work
    if (Browser.safari || Browser.mobileSafari)
    {
        Features.canvasBitBltShift = false;
    }

    navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;

    if (navigator.vibrate)
    {
        Features.vibration = true;
    }

    if (typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined' && typeof Uint32Array !== 'undefined')
    {
        Features.littleEndian = checkIsLittleEndian();
    }

    Features.support32bit = (
        typeof ArrayBuffer !== 'undefined' &&
        typeof Uint8ClampedArray !== 'undefined' &&
        typeof Int32Array !== 'undefined' &&
        Features.littleEndian !== null &&
        isUint8
    );

    return Features;
}

module.exports = init();


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Exponential ease-out.
 *
 * @function Phaser.Math.Easing.Expo.Out
 * @since 3.0.0
 *
 * @param {number} v - The value to be tweened.
 *
 * @return {number} The tweened value.
 */
var Out = function (v)
{
    return 1 - Math.pow(2, -10 * v);
};

module.exports = Out;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Geom
 */

module.exports = {

    Circle: require('./circle'),
    Ellipse: require('./ellipse'),
    Intersects: require('./intersects'),
    Line: require('./line'),
    Point: require('./point'),
    Polygon: require('./polygon'),
    Rectangle: require('./rectangle'),
    Triangle: require('./triangle')

};


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Graphics = require('./Graphics');
var GameObjectFactory = require('../GameObjectFactory');

/**
 * Creates a new Graphics Game Object and adds it to the Scene.
 *
 * Note: This method will only be available if the Graphics Game Object has been built into Phaser.
 *
 * @method Phaser.GameObjects.GameObjectFactory#graphics
 * @since 3.0.0
 *
 * @param {object} [config] - [description]
 *
 * @return {Phaser.GameObjects.Graphics} The Game Object that was created.
 */
GameObjectFactory.register('graphics', function (config)
{
    return this.displayList.add(new Graphics(this.scene, config));
});

//  When registering a factory function 'this' refers to the GameObjectFactory context.
//
//  There are several properties available to use:
//
//  this.scene - a reference to the Scene that owns the GameObjectFactory
//  this.displayList - a reference to the Display List the Scene owns
//  this.updateList - a reference to the Update List the Scene owns


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Class = require('../../utils/Class');

/**
 * @classdesc
 * [description]
 *
 * @class GeometryMask
 * @memberOf Phaser.Display.Masks
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Scene} scene - [description]
 * @param {Phaser.GameObjects.Graphics} graphicsGeometry - [description]
 */
var GeometryMask = new Class({

    initialize:

    function GeometryMask (scene, graphicsGeometry)
    {
        /**
         * [description]
         *
         * @name Phaser.Display.Masks.GeometryMask#geometryMask
         * @type {Phaser.GameObjects.Graphics}
         * @since 3.0.0
         */
        this.geometryMask = graphicsGeometry;
    },

    /**
     * [description]
     *
     * @method Phaser.Display.Masks.GeometryMask#setShape
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Graphics} graphicsGeometry - [description]
     */
    setShape: function (graphicsGeometry)
    {
        this.geometryMask = graphicsGeometry;
    },

    /**
     * [description]
     *
     * @method Phaser.Display.Masks.GeometryMask#preRenderWebGL
     * @since 3.0.0
     *
     * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - [description]
     * @param {Phaser.GameObjects.GameObject} mask - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     */
    preRenderWebGL: function (renderer, mask, camera)
    {
        var gl = renderer.gl;
        var geometryMask = this.geometryMask;

        // Force flushing before drawing to stencil buffer
        renderer.flush();

        // Enable and setup GL state to write to stencil buffer
        gl.enable(gl.STENCIL_TEST);
        gl.clear(gl.STENCIL_BUFFER_BIT);
        gl.colorMask(false, false, false, false);
        gl.stencilFunc(gl.NOTEQUAL, 1, 1);
        gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);

        // Write stencil buffer
        geometryMask.renderWebGL(renderer, geometryMask, 0.0, camera);
        renderer.flush();

        // Use stencil buffer to affect next rendering object
        gl.colorMask(true, true, true, true);
        gl.stencilFunc(gl.EQUAL, 1, 1);
        gl.stencilOp(gl.INVERT, gl.INVERT, gl.INVERT);
    },

    /**
     * [description]
     *
     * @method Phaser.Display.Masks.GeometryMask#postRenderWebGL
     * @since 3.0.0
     *
     * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - [description]
     */
    postRenderWebGL: function (renderer)
    {
        var gl = renderer.gl;

        // Force flush before disabling stencil test
        renderer.flush();
        gl.disable(gl.STENCIL_TEST);
    },

    /**
     * [description]
     *
     * @method Phaser.Display.Masks.GeometryMask#preRenderCanvas
     * @since 3.0.0
     *
     * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - [description]
     * @param {Phaser.GameObjects.GameObject} mask - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     */
    preRenderCanvas: function (renderer, mask, camera)
    {
        var geometryMask = this.geometryMask;

        renderer.currentContext.save();

        geometryMask.renderCanvas(renderer, geometryMask, 0.0, camera, undefined, null, true);

        renderer.currentContext.clip();
    },

    /**
     * [description]
     *
     * @method Phaser.Display.Masks.GeometryMask#postRenderCanvas
     * @since 3.0.0
     *
     * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - [description]
     */
    postRenderCanvas: function (renderer)
    {
        renderer.currentContext.restore();
    },

    /**
     * Destroys this GeometryMask and nulls any references it holds.
     *
     * Note that if a Game Object is currently using this mask it will _not_ automatically detect you have destroyed it,
     * so be sure to call `clearMask` on any Game Object using it, before destroying it.
     *
     * @method Phaser.Display.Masks.GeometryMask#destroy
     * @since 3.7.0
     */
    destroy: function ()
    {
        this.geometryMask = null;
    }

});

module.exports = GeometryMask;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var BuildGameObject = require('../../BuildGameObject');
var GameObjectCreator = require('../../GameObjectCreator');
var GetAdvancedValue = require('../../../utils/object/GetAdvancedValue');
var Text = require('./Text');

/**
 * Creates a new Text Game Object and returns it.
 *
 * Note: This method will only be available if the Text Game Object has been built into Phaser.
 *
 * @method Phaser.GameObjects.GameObjectCreator#text
 * @since 3.0.0
 *
 * @param {object} config - The configuration object this Game Object will use to create itself.
 * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object.
 *
 * @return {Phaser.GameObjects.Text} The Game Object that was created.
 */
GameObjectCreator.register('text', function (config, addToScene)
{
    if (config === undefined) { config = {}; }

    // style Object = {
    //     font: [ 'font', '16px Courier' ],
    //     backgroundColor: [ 'backgroundColor', null ],
    //     fill: [ 'fill', '#fff' ],
    //     stroke: [ 'stroke', '#fff' ],
    //     strokeThickness: [ 'strokeThickness', 0 ],
    //     shadowOffsetX: [ 'shadow.offsetX', 0 ],
    //     shadowOffsetY: [ 'shadow.offsetY', 0 ],
    //     shadowColor: [ 'shadow.color', '#000' ],
    //     shadowBlur: [ 'shadow.blur', 0 ],
    //     shadowStroke: [ 'shadow.stroke', false ],
    //     shadowFill: [ 'shadow.fill', false ],
    //     align: [ 'align', 'left' ],
    //     maxLines: [ 'maxLines', 0 ],
    //     fixedWidth: [ 'fixedWidth', false ],
    //     fixedHeight: [ 'fixedHeight', false ],
    //     rtl: [ 'rtl', false ]
    // }

    var content = GetAdvancedValue(config, 'text', '');
    var style = GetAdvancedValue(config, 'style', null);

    //  Padding
    //      { padding: 2 }
    //      { padding: { x: , y: }}
    //      { padding: { left: , top: }}
    //      { padding: { left: , right: , top: , bottom: }}

    var padding = GetAdvancedValue(config, 'padding', null);

    if (padding !== null)
    {
        style.padding = padding;
    }

    var text = new Text(this.scene, 0, 0, content, style);

    if (addToScene !== undefined)
    {
        config.add = addToScene;
    }

    BuildGameObject(this.scene, text, config);

    //  Text specific config options:

    text.autoRound = GetAdvancedValue(config, 'autoRound', true);
    text.resolution = GetAdvancedValue(config, 'resolution', 1);

    return text;
});

//  When registering a factory function 'this' refers to the GameObjectCreator context.


//  this.scene - a reference to the Scene that owns the GameObjectFactory

//  this.displayList - a reference to the Display List the Scene owns

//  this.updateList - a reference to the Update List the Scene owns


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Class = require('../utils/Class');

/**
 * @classdesc
 * An Image Collection is a special Tile Set containing multiple images, with no slicing into each image.
 *
 * Image Collections are normally created automatically when Tiled data is loaded.
 *
 * @class ImageCollection
 * @memberOf Phaser.Tilemaps
 * @constructor
 * @since 3.0.0
 *
 * @param {string} name - The name of the image collection in the map data.
 * @param {integer} firstgid - The first image index this image collection contains.
 * @param {integer} [width=32] - Width of widest image (in pixels).
 * @param {integer} [height=32] - Height of tallest image (in pixels).
 * @param {integer} [margin=0] - The margin around all images in the collection (in pixels).
 * @param {integer} [spacing=0] - The spacing between each image in the collection (in pixels).
 * @param {object} [properties={}] - Custom Image Collection properties.
 */
var ImageCollection = new Class({

    initialize:

    function ImageCollection (name, firstgid, width, height, margin, spacing, properties)
    {
        if (width === undefined || width <= 0) { width = 32; }
        if (height === undefined || height <= 0) { height = 32; }
        if (margin === undefined) { margin = 0; }
        if (spacing === undefined) { spacing = 0; }

        /**
         * The name of the Image Collection.
         *
         * @name Phaser.Tilemaps.ImageCollection#name
         * @type {string}
         * @since 3.0.0
        */
        this.name = name;

        /**
         * The Tiled firstgid value.
         * This is the starting index of the first image index this Image Collection contains.
         *
         * @name Phaser.Tilemaps.ImageCollection#firstgid
         * @type {integer}
         * @since 3.0.0
         */
        this.firstgid = firstgid | 0;

        /**
         * The width of the widest image (in pixels).
         *
         * @name Phaser.Tilemaps.ImageCollection#imageWidth
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.imageWidth = width | 0;

        /**
         * The height of the tallest image (in pixels).
         *
         * @name Phaser.Tilemaps.ImageCollection#imageHeight
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.imageHeight = height | 0;

        /**
         * The margin around the images in the collection (in pixels).
         * Use `setSpacing` to change.
         *
         * @name Phaser.Tilemaps.ImageCollection#imageMarge
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.imageMargin = margin | 0;

        /**
         * The spacing between each image in the collection (in pixels).
         * Use `setSpacing` to change.
         *
         * @name Phaser.Tilemaps.ImageCollection#imageSpacing
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.imageSpacing = spacing | 0;

        /**
         * Image Collection-specific properties that are typically defined in the Tiled editor.
         *
         * @name Phaser.Tilemaps.ImageCollection#properties
         * @type {object}
         * @since 3.0.0
         */
        this.properties = properties || {};

        /**
         * The cached images that are a part of this collection.
         *
         * @name Phaser.Tilemaps.ImageCollection#images
         * @type {array}
         * @readOnly
         * @since 3.0.0
         */
        this.images = [];

        /**
         * The total number of images in the image collection.
         *
         * @name Phaser.Tilemaps.ImageCollection#total
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.total = 0;
    },

    /**
     * Returns true if and only if this image collection contains the given image index.
     *
     * @method Phaser.Tilemaps.ImageCollection#containsImageIndex
     * @since 3.0.0
     *
     * @param {integer} imageIndex - The image index to search for.
     *
     * @return {boolean} True if this Image Collection contains the given index.
     */
    containsImageIndex: function (imageIndex)
    {
        return (imageIndex >= this.firstgid && imageIndex < (this.firstgid + this.total));
    },

    /**
     * Add an image to this Image Collection.
     *
     * @method Phaser.Tilemaps.ImageCollection#addImage
     * @since 3.0.0
     *
     * @param {integer} gid - The gid of the image in the Image Collection.
     * @param {string} image - The the key of the image in the Image Collection and in the cache.
     *
     * @return {Phaser.Tilemaps.ImageCollection} This ImageCollection object.
     */
    addImage: function (gid, image)
    {
        this.images.push({ gid: gid, image: image });
        this.total++;

        return this;
    }

});

module.exports = ImageCollection;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var PropertyValueSet = require('./PropertyValueSet');

/**
 * Takes an array of Game Objects, or any objects that have the public property `scaleX`
 * and then sets it to the given value.
 *
 * The optional `step` property is applied incrementally, multiplied by each item in the array.
 *
 * To use this with a Group: `SetScaleX(group.getChildren(), value, step)`
 *
 * @function Phaser.Actions.SetScaleX
 * @since 3.0.0
 *
 * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
 *
 * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
 * @param {number} value - The amount to set the property to.
 * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter.
 * @param {integer} [index=0] - An optional offset to start searching from within the items array.
 * @param {integer} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning.
 *
 * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
 */
var SetScaleX = function (items, value, step, index, direction)
{
    return PropertyValueSet(items, 'scaleX', value, step, index, direction);
};

module.exports = SetScaleX;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var TileToWorldX = require('./TileToWorldX');
var TileToWorldY = require('./TileToWorldY');
var GetTilesWithin = require('./GetTilesWithin');
var ReplaceByIndex = require('./ReplaceByIndex');

/**
 * Creates a Sprite for every object matching the given tile indexes in the layer. You can
 * optionally specify if each tile will be replaced with a new tile after the Sprite has been
 * created. This is useful if you want to lay down special tiles in a level that are converted to
 * Sprites, but want to replace the tile itself with a floor tile or similar once converted.
 *
 * @function Phaser.Tilemaps.Components.CreateFromTiles
 * @private
 * @since 3.0.0
 *
 * @param {(integer|array)} indexes - The tile index, or array of indexes, to create Sprites from.
 * @param {(integer|array)} replacements - The tile index, or array of indexes, to change a converted
 * tile to. Set to `null` to leave the tiles unchanged. If an array is given, it is assumed to be a
 * one-to-one mapping with the indexes array.
 * @param {object} spriteConfig - The config object to pass into the Sprite creator (i.e.
 * scene.make.sprite).
 * @param {Phaser.Scene} [scene=scene the map is within] - The Scene to create the Sprites within.
 * @param {Phaser.Cameras.Scene2D.Camera} [camera=main camera] - The Camera to use when determining the world XY
 * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon.
 *
 * @return {Phaser.GameObjects.Sprite[]} An array of the Sprites that were created.
 */
var CreateFromTiles = function (indexes, replacements, spriteConfig, scene, camera, layer)
{
    if (spriteConfig === undefined) { spriteConfig = {}; }

    if (!Array.isArray(indexes)) { indexes = [ indexes ]; }

    var tilemapLayer = layer.tilemapLayer;
    if (scene === undefined) { scene = tilemapLayer.scene; }
    if (camera === undefined) { camera = scene.cameras.main; }

    var tiles = GetTilesWithin(0, 0, layer.width, layer.height, null, layer);
    var sprites = [];
    var i;

    for (i = 0; i < tiles.length; i++)
    {
        var tile = tiles[i];

        if (indexes.indexOf(tile.index) !== -1)
        {
            spriteConfig.x = TileToWorldX(tile.x, camera, layer);
            spriteConfig.y = TileToWorldY(tile.y, camera, layer);

            var sprite = scene.make.sprite(spriteConfig);
            sprites.push(sprite);
        }
    }

    if (typeof replacements === 'number')
    {
        //  Assume 1 replacement for all types of tile given
        for (i = 0; i < indexes.length; i++)
        {
            ReplaceByIndex(indexes[i], replacements, 0, 0, layer.width, layer.height, layer);
        }
    }
    else if (Array.isArray(replacements))
    {
        //  Assume 1 to 1 mapping with indexes array
        for (i = 0; i < indexes.length; i++)
        {
            ReplaceByIndex(indexes[i], replacements[i], 0, 0, layer.width, layer.height, layer);
        }
    }

    return sprites;
};

module.exports = CreateFromTiles;


var localAxes = this.axes;
var gamepadAxes = pad.axes;
len = localAxes.length;
for (i = 0; i < len; i++)


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Contains = require('./Contains');

/**
 * [description]
 *
 * @function Phaser.Geom.Polygon.ContainsPoint
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Polygon} polygon - [description]
 * @param {Phaser.Geom.Point} point - [description]
 *
 * @return {boolean} [description]
 */
var ContainsPoint = function (polygon, point)
{
    return Contains(polygon, point.x, point.y);
};

module.exports = ContainsPoint;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Calculate the distance between two sets of coordinates (points).
 *
 * @function Phaser.Math.Distance.Between
 * @since 3.0.0
 *
 * @param {number} x1 - The x coordinate of the first point.
 * @param {number} y1 - The y coordinate of the first point.
 * @param {number} x2 - The x coordinate of the second point.
 * @param {number} y2 - The y coordinate of the second point.
 *
 * @return {number} The distance between each point.
 */
var DistanceBetween = function (x1, y1, x2, y2)
{
    var dx = x1 - x2;
    var dy = y1 - y2;

    return Math.sqrt(dx * dx + dy * dy);
};

module.exports = DistanceBetween;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @author       Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Sound
 */

/**
 * Config object containing various sound settings.
 *
 * @typedef {object} SoundConfig
 *
 * @property {boolean} [mute=false] - Boolean indicating whether the sound should be muted or not.
 * @property {number} [volume=1] - A value between 0 (silence) and 1 (full volume).
 * @property {number} [rate=1] - Defines the speed at which the sound should be played.
 * @property {number} [detune=0] - Represents detuning of sound in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29).
 * @property {number} [seek=0] - Position of playback for this sound, in seconds.
 * @property {boolean} [loop=false] - Whether or not the sound or current sound marker should loop.
 * @property {number} [delay=0] - Time, in seconds, that should elapse before the sound actually starts its playback.
 */

/**
 * Marked section of a sound represented by name, and optionally start time, duration, and config object.
 *
 * @typedef {object} SoundMarker
 *
 * @property {string} name - Unique identifier of a sound marker.
 * @property {number} [start=0] - Sound position offset at witch playback should start.
 * @property {number} [duration] - Playback duration of this marker.
 * @property {SoundConfig} [config] - An optional config object containing default marker settings.
 */

module.exports = {

    SoundManagerCreator: require('./SoundManagerCreator'),

    BaseSound: require('./BaseSound'),
    BaseSoundManager: require('./BaseSoundManager'),

    WebAudioSound: require('./webaudio/WebAudioSound'),
    WebAudioSoundManager: require('./webaudio/WebAudioSoundManager'),

    HTML5AudioSound: require('./html5/HTML5AudioSound'),
    HTML5AudioSoundManager: require('./html5/HTML5AudioSoundManager'),

    NoAudioSound: require('./noaudio/NoAudioSound'),
    NoAudioSoundManager: require('./noaudio/NoAudioSoundManager')

};


keep keep keep keep keep replace keep keep keep keep keep


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * [description]
 *
 * @function Phaser.Geom.Line.CopyFrom
 * @since 3.0.0
 *
 * @generic {Phaser.Geom.Line} O - [dest,$return]
 *
 * @param {Phaser.Geom.Line} source - [description]
 * @param {Phaser.Geom.Line} dest - [description]
 *
 * @return {Phaser.Geom.Line} [description]
 */
var CopyFrom = function (source, dest)
{
    return dest.setTo(source.x1, source.y1, source.x2, source.y2);
};

module.exports = CopyFrom;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var CONST = require('./tween/const');
var Extend = require('../utils/object/Extend');

/**
 * @namespace Phaser.Tweens
 */

var Tweens = {

    Builders: require('./builders'),

    TweenManager: require('./TweenManager'),
    Tween: require('./tween/Tween'),
    TweenData: require('./tween/TweenData'),
    Timeline: require('./Timeline')

};

//   Merge in the consts
Tweens = Extend(false, Tweens, CONST);

module.exports = Tweens;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Global consts.
 *
 * @ignore
 */

var CONST = {

    /**
     * Phaser Release Version
     *
     * @name Phaser.VERSION
     * @readOnly
     * @type {string}
     * @since 3.0.0
     */
    VERSION: '3.10.0-beta1',

    BlendModes: require('./renderer/BlendModes'),

    ScaleModes: require('./renderer/ScaleModes'),

    /**
     * AUTO Detect Renderer.
     *
     * @name Phaser.AUTO
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    AUTO: 0,

    /**
     * Canvas Renderer.
     *
     * @name Phaser.CANVAS
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    CANVAS: 1,

    /**
     * WebGL Renderer.
     *
     * @name Phaser.WEBGL
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    WEBGL: 2,

    /**
     * Headless Renderer.
     *
     * @name Phaser.HEADLESS
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    HEADLESS: 3,

    /**
     * In Phaser the value -1 means 'forever' in lots of cases, this const allows you to use it instead
     * to help you remember what the value is doing in your code.
     *
     * @name Phaser.FOREVER
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    FOREVER: -1,

    /**
     * Direction constant.
     *
     * @name Phaser.NONE
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    NONE: 4,

    /**
     * Direction constant.
     *
     * @name Phaser.UP
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    UP: 5,

    /**
     * Direction constant.
     *
     * @name Phaser.DOWN
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    DOWN: 6,

    /**
     * Direction constant.
     *
     * @name Phaser.LEFT
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    LEFT: 7,

    /**
     * Direction constant.
     *
     * @name Phaser.RIGHT
     * @readOnly
     * @type {integer}
     * @since 3.0.0
     */
    RIGHT: 8

};

module.exports = CONST;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Used internally by the KeyboardManager.
 *
 * @function Phaser.Input.Keyboard.ProcessKeyUp
 * @private
 * @since 3.0.0
 *
 * @param {Phaser.Input.Keyboard.Key} key - The Key to process the event for.
 * @param {KeyboardEvent} event - The native Keyboard event.
 *
 * @return {Phaser.Input.Keyboard.Key} The Key that was processed.
 */
var ProcessKeyUp = function (key, event)
{
    key.originalEvent = event;

    if (key.preventDefault)
    {
        event.preventDefault();
    }

    if (!key.enabled)
    {
        return;
    }

    key.isDown = false;
    key.isUp = true;
    key.timeUp = event.timeStamp;
    key.duration = key.timeUp - key.timeDown;
    key.repeats = 0;

    key._justDown = false;
    key._justUp = true;

    return key;
};

module.exports = ProcessKeyUp;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Length = require('../line/Length');

// The 2D area of a triangle. The area value is always non-negative.

/**
 * [description]
 *
 * @function Phaser.Geom.Triangle.Perimeter
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Triangle} triangle - [description]
 *
 * @return {number} [description]
 */
var Perimeter = function (triangle)
{
    var line1 = triangle.getLineA();
    var line2 = triangle.getLineB();
    var line3 = triangle.getLineC();

    return (Length(line1) + Length(line2) + Length(line3));
};

module.exports = Perimeter;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Class = require('../../utils/Class');
var GetFastValue = require('../../utils/object/GetFastValue');

/**
 * @classdesc
 * A class for representing data about about a layer in a map. Maps are parsed from CSV, Tiled,
 * etc. into this format. Tilemap, StaticTilemapLayer and DynamicTilemapLayer have a reference
 * to this data and use it to look up and perform operations on tiles.
 *
 * @class LayerData
 * @memberOf Phaser.Tilemaps
 * @constructor
 * @since 3.0.0
 *
 * @param {object} [config] - [description]
 */
var LayerData = new Class({

    initialize:

    function LayerData (config)
    {
        if (config === undefined) { config = {}; }

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#name
         * @type {string}
         * @since 3.0.0
         */
        this.name = GetFastValue(config, 'name', 'layer');

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#x
         * @type {number}
         * @since 3.0.0
         */
        this.x = GetFastValue(config, 'x', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#y
         * @type {number}
         * @since 3.0.0
         */
        this.y = GetFastValue(config, 'y', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#width
         * @type {number}
         * @since 3.0.0
         */
        this.width = GetFastValue(config, 'width', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#height
         * @type {number}
         * @since 3.0.0
         */
        this.height = GetFastValue(config, 'height', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#tileWidth
         * @type {number}
         * @since 3.0.0
         */
        this.tileWidth = GetFastValue(config, 'tileWidth', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#tileHeight
         * @type {number}
         * @since 3.0.0
         */
        this.tileHeight = GetFastValue(config, 'tileHeight', 0);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#baseTileWidth
         * @type {number}
         * @since 3.0.0
         */
        this.baseTileWidth = GetFastValue(config, 'baseTileWidth', this.tileWidth);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#baseTileHeight
         * @type {number}
         * @since 3.0.0
         */
        this.baseTileHeight = GetFastValue(config, 'baseTileHeight', this.tileHeight);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#widthInPixels
         * @type {number}
         * @since 3.0.0
         */
        this.widthInPixels = GetFastValue(config, 'widthInPixels', this.width * this.baseTileWidth);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#heightInPixels
         * @type {number}
         * @since 3.0.0
         */
        this.heightInPixels = GetFastValue(config, 'heightInPixels', this.height * this.baseTileHeight);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#alpha
         * @type {float}
         * @since 3.0.0
         */
        this.alpha = GetFastValue(config, 'alpha', 1);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#visible
         * @type {boolean}
         * @since 3.0.0
         */
        this.visible = GetFastValue(config, 'visible', true);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#properties
         * @type {object}
         * @since 3.0.0
         */
        this.properties = GetFastValue(config, 'properties', {});

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#indexes
         * @type {array}
         * @since 3.0.0
         */
        this.indexes = GetFastValue(config, 'indexes', []);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#collideIndexes
         * @type {array}
         * @since 3.0.0
         */
        this.collideIndexes = GetFastValue(config, 'collideIndexes', []);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#callbacks
         * @type {array}
         * @since 3.0.0
         */
        this.callbacks = GetFastValue(config, 'callbacks', []);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#bodies
         * @type {array}
         * @since 3.0.0
         */
        this.bodies = GetFastValue(config, 'bodies', []);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#data
         * @type {array}
         * @since 3.0.0
         */
        this.data = GetFastValue(config, 'data', []);

        /**
         * [description]
         *
         * @name Phaser.Tilemaps.LayerData#tilemapLayer
         * @type {(Phaser.Tilemaps.DynamicTilemapLayer|Phaser.Tilemaps.StaticTilemapLayer)}
         * @since 3.0.0
         */
        this.tilemapLayer = GetFastValue(config, 'tilemapLayer', null);
    }

});

module.exports = LayerData;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Cache
 */

module.exports = {

    BaseCache: require('./BaseCache'),
    CacheManager: require('./CacheManager')

};


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Finds the key within the top level of the {@link source} object, or returns {@link defaultValue}
 *
 * @function Phaser.Utils.Object.GetFastValue
 * @since 3.0.0
 *
 * @param {object} source - The object to search
 * @param {string} key - The key for the property on source. Must exist at the top level of the source object (no periods)
 * @param {*} [defaultValue] - The default value to use if the key does not exist.
 *
 * @return {*} The value if found; otherwise, defaultValue (null if none provided)
 */
var GetFastValue = function (source, key, defaultValue)
{
    var t = typeof(source);

    if (!source || t === 'number' || t === 'string')
    {
        return defaultValue;
    }
    else if (source.hasOwnProperty(key) && source[key] !== undefined)
    {
        return source[key];
    }
    else
    {
        return defaultValue;
    }
};

module.exports = GetFastValue;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Renderer.Canvas
 */

module.exports = {

    BlitImage: require('./utils/BlitImage'),
    CanvasRenderer: require('./CanvasRenderer'),
    DrawImage: require('./utils/DrawImage'),
    GetBlendModes: require('./utils/GetBlendModes')

};


keep keep keep keep replace keep keep keep keep

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Axis = require('./Axis');
var Button = require('./Button');
var Class = require('../../utils/Class');
var EventEmitter = require('eventemitter3');
var Vector2 = require('../../math/Vector2');

/**
 * @classdesc
 * A single Gamepad.
 *
 * These are created, updated and managed by the Gamepad Manager.
 *
 * @class Gamepad
 * @extends Phaser.Events.EventEmitter
 * @memberOf Phaser.Input.Gamepad
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Input.Gamepad.GamepadManager} manager - A reference to the Gamepad Manager.
 * @param {Pad} pad - The Gamepad object, as extracted from GamepadEvent.
 */
var Gamepad = new Class({

    Extends: EventEmitter,

    initialize:

    function Gamepad (manager, pad)
    {
        EventEmitter.call(this);

        /**
         * A reference to the Gamepad Manager.
         *
         * @name Phaser.Input.Gamepad.Gamepad#manager
         * @type {Phaser.Input.Gamepad.GamepadManager}
         * @since 3.0.0
         */
        this.manager = manager;

        /**
         * A reference to the native Gamepad object that is connected to the browser.
         *
         * @name Phaser.Input.Gamepad.Gamepad#pad
         * @type {any}
         * @since 3.10.0
         */
        this.pad = pad;

        /**
         * A string containing some information about the controller.
         *
         * This is not strictly specified, but in Firefox it will contain three pieces of information
         * separated by dashes (-): two 4-digit hexadecimal strings containing the USB vendor and
         * product id of the controller, and the name of the controller as provided by the driver.
         * In Chrome it will contain the name of the controller as provided by the driver,
         * followed by vendor and product 4-digit hexadecimal strings.
         *
         * @name Phaser.Input.Gamepad.Gamepad#id
         * @type {string}
         * @since 3.0.0
         */
        this.id = pad.id;

        /**
         * An integer that is unique for each Gamepad currently connected to the system.
         * This can be used to distinguish multiple controllers.
         * Note that disconnecting a device and then connecting a new device may reuse the previous index.
         *
         * @name Phaser.Input.Gamepad.Gamepad#index
         * @type {number}
         * @since 3.0.0
         */
        this.index = pad.index;

        var buttons = [];

        for (var i = 0; i < pad.buttons.length; i++)
        {
            buttons.push(new Button(this, i));
        }

        /**
         * An array of Gamepad Button objects, corresponding to the different buttons available on the Gamepad.
         *
         * @name Phaser.Input.Gamepad.Gamepad#buttons
         * @type {Phaser.Input.Gamepad.Button[]}
         * @since 3.0.0
         */
        this.buttons = buttons;

        var axes = [];

        for (i = 0; i < pad.axes.length; i++)
        {
            axes.push(new Axis(this, i));
        }

        /**
         * An array of Gamepad Axis objects, corresponding to the different axes available on the Gamepad, if any.
         *
         * @name Phaser.Input.Gamepad.Gamepad#axes
         * @type {Phaser.Input.Gamepad.Axis[]}
         * @since 3.0.0
         */
        this.axes = axes;

        /**
         * The Gamepad's Haptic Actuator (Vibration / Rumble support).
         * This is highly experimental and only set if both present on the device,
         * and exposed by both the hardware and browser.
         *
         * @name Phaser.Input.Gamepad.Gamepad#vibration
         * @type {GamepadHapticActuator}
         * @since 3.10.0
         */
        this.vibration = pad.vibrationActuator;

        // https://w3c.github.io/gamepad/#remapping

        var _noButton = { value: 0, pressed: false };

        /**
         * A reference to the Left Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCLeft = (buttons[14]) ? buttons[14] : _noButton;

        /**
         * A reference to the Right Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCRight = (buttons[15]) ? buttons[15] : _noButton;

        /**
         * A reference to the Top Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCTop = (buttons[12]) ? buttons[12] : _noButton;

        /**
         * A reference to the Bottom Button in the Left Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_LCBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._LCBottom = (buttons[13]) ? buttons[13] : _noButton;

        /**
         * A reference to the Left Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCLeft = (buttons[2]) ? buttons[2] : _noButton;

        /**
         * A reference to the Right Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCRight = (buttons[1]) ? buttons[1] : _noButton;

        /**
         * A reference to the Top Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCTop = (buttons[3]) ? buttons[3] : _noButton;

        /**
         * A reference to the Bottom Button in the Right Cluster.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_RCBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._RCBottom = (buttons[0]) ? buttons[0] : _noButton;

        /**
         * A reference to the Top Left Front Button (L1 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBLeftTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBLeftTop = (buttons[4]) ? buttons[4] : _noButton;

        /**
         * A reference to the Bottom Left Front Button (L2 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBLeftBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBLeftBottom = (buttons[6]) ? buttons[6] : _noButton;

        /**
         * A reference to the Top Right Front Button (R1 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBRightTop
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBRightTop = (buttons[5]) ? buttons[5] : _noButton;

        /**
         * A reference to the Bottom Right Front Button (R2 Shoulder Button)
         *
         * @name Phaser.Input.Gamepad.Gamepad#_FBRightBottom
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._FBRightBottom = (buttons[7]) ? buttons[7] : _noButton;

        var _noAxis = { value: 0 };

        /**
         * A reference to the Horizontal Axis for the Left Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_HAxisLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._HAxisLeft = (axes[0]) ? axes[0] : _noAxis;

        /**
         * A reference to the Vertical Axis for the Left Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_VAxisLeft
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._VAxisLeft = (axes[1]) ? axes[1] : _noAxis;

        /**
         * A reference to the Horizontal Axis for the Right Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_HAxisRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._HAxisRight = (axes[2]) ? axes[2] : _noAxis;

        /**
         * A reference to the Vertical Axis for the Right Stick.
         *
         * @name Phaser.Input.Gamepad.Gamepad#_VAxisRight
         * @type {Phaser.Input.Gamepad.Button}
         * @private
         * @since 3.10.0
         */
        this._VAxisRight = (axes[3]) ? axes[3] : _noAxis;

        /**
         * A Vector2 containing the most recent values from the Gamepad's left axis stick.
         * This is updated automatically as part of the Gamepad.update cycle.
         * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property.
         * The values are based on the Axis thresholds.
         * If the Gamepad does not have a left axis stick, the values will always be zero.
         *
         * @name Phaser.Input.Gamepad.Gamepad#leftStick
         * @type {Phaser.Math.Vector2}
         * @since 3.10.0
         */
        this.leftStick = new Vector2();

        /**
         * A Vector2 containing the most recent values from the Gamepad's right axis stick.
         * This is updated automatically as part of the Gamepad.update cycle.
         * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property.
         * The values are based on the Axis thresholds.
         * If the Gamepad does not have a right axis stick, the values will always be zero.
         *
         * @name Phaser.Input.Gamepad.Gamepad#rightStick
         * @type {Phaser.Math.Vector2}
         * @since 3.10.0
         */
        this.rightStick = new Vector2();
    },

    /**
     * Gets the total number of axis this Gamepad claims to support.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getAxisTotal
     * @since 3.10.0
     *
     * @return {integer} The total number of axes this Gamepad claims to support.
     */
    getAxisTotal: function ()
    {
        return this.axes.length;
    },

    /**
     * Gets the value of an axis based on the given index.
     * The index must be valid within the range of axes supported by this Gamepad.
     * The return value will be a float between 0 and 1.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getAxisValue
     * @since 3.10.0
     *
     * @param {integer} index - The index of the axes to get the value for.
     *
     * @return {number} The value of the axis, between 0 and 1.
     */
    getAxisValue: function (index)
    {
        return this.axes[index].getValue();
    },

    /**
     * Sets the threshold value of all axis on this Gamepad.
     * The value is a float between 0 and 1 and is the amount below which the axis is considered as not having been moved.
     *
     * @method Phaser.Input.Gamepad.Gamepad#setAxisThreshold
     * @since 3.10.0
     *
     * @param {number} value - A value between 0 and 1.
     */
    setAxisThreshold: function (value)
    {
        for (var i = 0; i < this.axes.length; i++)
        {
            this.axes[i].threshold = value;
        }
    },

    /**
     * Gets the total number of buttons this Gamepad claims to have.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getButtonTotal
     * @since 3.10.0
     *
     * @return {integer} The total number of buttons this Gamepad claims to have.
     */
    getButtonTotal: function ()
    {
        return this.buttons.length;
    },

    /**
     * Gets the value of a button based on the given index.
     * The index must be valid within the range of buttons supported by this Gamepad.
     *
     * The return value will be either 0 or 1 for an analogue button, or a float between 0 and 1
     * for a pressure-sensitive digital button, such as the shoulder buttons on a Dual Shock.
     *
     * @method Phaser.Input.Gamepad.Gamepad#getButtonValue
     * @since 3.10.0
     *
     * @param {integer} index - The index of the button to get the value for.
     *
     * @return {number} The value of the button, between 0 and 1.
     */
    getButtonValue: function (index)
    {
        return this.buttons[index].value;
    },

    /**
     * Returns if the button is pressed down or not.
     * The index must be valid within the range of buttons supported by this Gamepad.
     *
     * @method Phaser.Input.Gamepad.Gamepad#isButtonDown
     * @since 3.10.0
     *
     * @param {integer} index - The index of the button to get the value for.
     *
     * @return {boolean} `true` if the button is considered as being pressed down, otherwise `false`.
     */
    isButtonDown: function (index)
    {
        return this.buttons[index].pressed;
    },

    /**
     * Internal update handler for this Gamepad.
     * Called automatically by the Gamepad Manager as part of its update.
     *
     * @method Phaser.Input.Gamepad.Gamepad#update
     * @private
     * @since 3.0.0
     */
    update: function (pad)
    {
        var i;

        //  Sync the button values

        var localButtons = this.buttons;
        var gamepadButtons = pad.buttons;

        var len = localButtons.length;

        for (i = 0; i < len; i++)
        {
            localButtons[i].update(gamepadButtons[i].value);
        }

        //  Sync the axis values

        var localAxes = this.axes;
        var gamepadAxes = pad.axes;

        len = localAxes.length;

        for (i = 0; i < len; i++)
        {
            localAxes[i].update(gamepadAxes[i]);
        }

        if (len >= 2)
        {
            this.leftStick.set(localAxes[0].getValue(), localAxes[1].getValue());

            if (len >= 4)
            {
                this.rightStick.set(localAxes[2].getValue(), localAxes[3].getValue());
            }
        }
    },

    /**
     * Destroys this Gamepad instance, its buttons and axes, and releases external references it holds.
     *
     * @method Phaser.Input.Gamepad.Gamepad#destroy
     * @since 3.10.0
     */
    destroy: function ()
    {
        this.removeAllListeners();

        this.manager = null;
        this.pad = null;

        var i;

        for (i = 0; i < this.buttons.length; i++)
        {
            this.buttons[i].destroy();
        }

        for (i = 0; i < this.axes.length; i++)
        {
            this.axes[i].destroy();
        }

        this.buttons = [];
        this.axes = [];
    },

    /**
     * Is this Gamepad currently connected or not?
     *
     * @name Phaser.Input.Gamepad.Gamepad#connected
     * @type {boolean}
     * @default true
     * @since 3.0.0
     */
    connected: {

        get: function ()
        {
            return this.pad.connected;
        }

    },

    /**
     * A timestamp containing the most recent time this Gamepad was updated.
     *
     * @name Phaser.Input.Gamepad.Gamepad#timestamp
     * @type {number}
     * @since 3.0.0
     */
    timestamp: {

        get: function ()
        {
            return this.pad.timestamp;
        }

    },

    /**
     * Is the Gamepad's Left button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad left button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#left
     * @type {boolean}
     * @since 3.10.0
     */
    left: {

        get: function ()
        {
            return this._LCLeft.pressed;
        }

    },

    /**
     * Is the Gamepad's Right button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad right button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#right
     * @type {boolean}
     * @since 3.10.0
     */
    right: {

        get: function ()
        {
            return this._LCRight.pressed;
        }

    },

    /**
     * Is the Gamepad's Up button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad up button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#up
     * @type {boolean}
     * @since 3.10.0
     */
    up: {

        get: function ()
        {
            return this._LCTop.pressed;
        }

    },

    /**
     * Is the Gamepad's Down button being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * This is the d-pad down button under standard Gamepad mapping.
     *
     * @name Phaser.Input.Gamepad.Gamepad#down
     * @type {boolean}
     * @since 3.10.0
     */
    down: {

        get: function ()
        {
            return this._LCBottom.pressed;
        }

    },

    /**
     * Is the Gamepad's bottom button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the X button.
     * On an XBox controller it's the A button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#A
     * @type {boolean}
     * @since 3.10.0
     */
    A: {

        get: function ()
        {
            return this._RCBottom.pressed;
        }

    },

    /**
     * Is the Gamepad's top button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Triangle button.
     * On an XBox controller it's the Y button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#Y
     * @type {boolean}
     * @since 3.10.0
     */
    Y: {

        get: function ()
        {
            return this._RCTop.pressed;
        }

    },

    /**
     * Is the Gamepad's left button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Square button.
     * On an XBox controller it's the X button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#X
     * @type {boolean}
     * @since 3.10.0
     */
    X: {

        get: function ()
        {
            return this._RCLeft.pressed;
        }

    },

    /**
     * Is the Gamepad's right button in the right button cluster being pressed?
     * If the Gamepad doesn't have this button it will always return false.
     * On a Dual Shock controller it's the Circle button.
     * On an XBox controller it's the B button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#B
     * @type {boolean}
     * @since 3.10.0
     */
    B: {

        get: function ()
        {
            return this._RCRight.pressed;
        }

    },

    /**
     * Returns the value of the Gamepad's top left shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the L1 button.
     * On an XBox controller it's the LB button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#L1
     * @type {number}
     * @since 3.10.0
     */
    L1: {

        get: function ()
        {
            return this._FBLeftTop.value
        }

    },

    /**
     * Returns the value of the Gamepad's bottom left shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the L2 button.
     * On an XBox controller it's the LT button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#L2
     * @type {number}
     * @since 3.10.0
     */
    L2: {

        get: function ()
        {
            return this._FBLeftBottom.value
        }

    },

    /**
     * Returns the value of the Gamepad's top right shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the R1 button.
     * On an XBox controller it's the RB button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#R1
     * @type {number}
     * @since 3.10.0
     */
    R1: {

        get: function ()
        {
            return this._FBRightTop.value
        }

    },

    /**
     * Returns the value of the Gamepad's bottom right shoulder button.
     * If the Gamepad doesn't have this button it will always return zero.
     * The value is a float between 0 and 1, corresponding to how depressed the button is.
     * On a Dual Shock controller it's the R2 button.
     * On an XBox controller it's the RT button.
     *
     * @name Phaser.Input.Gamepad.Gamepad#R2
     * @type {number}
     * @since 3.10.0
     */
    R2: {

        get: function ()
        {
            return this._FBRightBottom.value
        }

    }

});

module.exports = Gamepad;