/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * The Key Up Event.
 *
 * This event is dispatched by the Keyboard Plugin when any key on the keyboard is released.
 *
 * Unlike the `ANY_KEY_UP` event, this one has a special dynamic event name. For example, to listen for the `A` key being released
 * use the following from within a Scene: `this.input.keyboard.on('keyup-A', listener)`. You can replace the `-A` part of the event
 * name with any valid [Key Code string]{@link Phaser.Input.Keyboard.KeyCodes}. For example, this will listen for the space bar:
 * `this.input.keyboard.on('keyup-SPACE', listener)`.
 *
 * You can also create a generic 'global' listener. See [Keyboard.Events.ANY_KEY_UP]{@linkcode Phaser.Input.Keyboard.Events#event:ANY_KEY_UP} for details.
 *
 * Finally, you can create Key objects, which you can also listen for events from. See [Keyboard.Events.UP]{@linkcode Phaser.Input.Keyboard.Events#event:UP} for details.
 *
 * @event Phaser.Input.Keyboard.Events#KEY_UP
 * @since 3.0.0
 *
 * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about the key that was released, any modifiers, etc.
 */
module.exports = 'keyup-';


* Specify a padding value which is added to the line width and height when calculating the Text size.

* Allows you to add extra spacing if the browser is unable to accurately determine the true font dimensions.

keep keep keep keep keep replace keep keep keep keep keep

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * @namespace Phaser.Math.Distance
 */

module.exports = {

    Between: require('./DistanceBetween'),
    Power: require('./DistancePower'),
    Squared: require('./DistanceSquared')

};


/**
 * @typedef {object} Phaser.Types.Loader.FileTypes.TilemapImpactFileConfig
 *
 * @property {string} key - The key of the file. Must be unique within both the Loader and the Tilemap Cache.
 * @property {string} [url] - The absolute or relative URL to load the file from.
 * @property {string} [extension='json'] - The default file extension to use if no url is provided.
 * @property {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
 */


if ((src.width === 0) || (src.height === 0))

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * Renders this Game Object with the Canvas Renderer to the given Camera.
 * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
 * This method should not be called directly. It is a utility function of the Render module.
 *
 * @method Phaser.GameObjects.Text#renderCanvas
 * @since 3.0.0
 * @private
 *
 * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
 * @param {Phaser.GameObjects.Text} src - The Game Object being rendered in this call.
 * @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
 */
var TextCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
    if (src.text !== '')
    {
        renderer.batchSprite(src, src.frame, camera, parentMatrix);
    }
};

module.exports = TextCanvasRenderer;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

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

/**
 * @callback EachSetCallback<E>
 *
 * @param {E} entry - The Set entry.
 * @param {number} index - The index of the entry within the Set.
 *
 * @return {?boolean} The callback result.
 */

/**
 * @classdesc
 * A Set is a collection of unique elements.
 *
 * @class Set
 * @memberof Phaser.Structs
 * @constructor
 * @since 3.0.0
 *
 * @generic T
 * @genericUse {T[]} - [elements]
 *
 * @param {Array.<*>} [elements] - An optional array of elements to insert into this Set.
 */
var Set = new Class({

    initialize:

    function Set (elements)
    {
        /**
         * The entries of this Set. Stored internally as an array.
         *
         * @genericUse {T[]} - [$type]
         *
         * @name Phaser.Structs.Set#entries
         * @type {Array.<*>}
         * @default []
         * @since 3.0.0
         */
        this.entries = [];

        if (Array.isArray(elements))
        {
            for (var i = 0; i < elements.length; i++)
            {
                this.set(elements[i]);
            }
        }
    },

    /**
     * Inserts the provided value into this Set. If the value is already contained in this Set this method will have no effect.
     *
     * @method Phaser.Structs.Set#set
     * @since 3.0.0
     *
     * @genericUse {T} - [value]
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @param {*} value - The value to insert into this Set.
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    set: function (value)
    {
        if (this.entries.indexOf(value) === -1)
        {
            this.entries.push(value);
        }

        return this;
    },

    /**
     * Get an element of this Set which has a property of the specified name, if that property is equal to the specified value.
     * If no elements of this Set satisfy the condition then this method will return `null`.
     *
     * @method Phaser.Structs.Set#get
     * @since 3.0.0
     *
     * @genericUse {T} - [value,$return]
     *
     * @param {string} property - The property name to check on the elements of this Set.
     * @param {*} value - The value to check for.
     *
     * @return {*} The first element of this Set that meets the required condition, or `null` if this Set contains no elements that meet the condition.
     */
    get: function (property, value)
    {
        for (var i = 0; i < this.entries.length; i++)
        {
            var entry = this.entries[i];

            if (entry[property] === value)
            {
                return entry;
            }
        }
    },

    /**
     * Returns an array containing all the values in this Set.
     *
     * @method Phaser.Structs.Set#getArray
     * @since 3.0.0
     *
     * @genericUse {T[]} - [$return]
     *
     * @return {Array.<*>} An array containing all the values in this Set.
     */
    getArray: function ()
    {
        return this.entries.slice(0);
    },

    /**
     * Removes the given value from this Set if this Set contains that value.
     *
     * @method Phaser.Structs.Set#delete
     * @since 3.0.0
     *
     * @genericUse {T} - [value]
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @param {*} value - The value to remove from the Set.
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    delete: function (value)
    {
        var index = this.entries.indexOf(value);

        if (index > -1)
        {
            this.entries.splice(index, 1);
        }

        return this;
    },

    /**
     * Dumps the contents of this Set to the console via `console.group`.
     *
     * @method Phaser.Structs.Set#dump
     * @since 3.0.0
     */
    dump: function ()
    {
        // eslint-disable-next-line no-console
        console.group('Set');

        for (var i = 0; i < this.entries.length; i++)
        {
            var entry = this.entries[i];
            console.log(entry);
        }

        // eslint-disable-next-line no-console
        console.groupEnd();
    },

    /**
     * Passes each value in this Set to the given callback.
     * Use this function when you know this Set will be modified during the iteration, otherwise use `iterate`.
     *
     * @method Phaser.Structs.Set#each
     * @since 3.0.0
     *
     * @genericUse {EachSetCallback.<T>} - [callback]
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @param {EachSetCallback} callback - The callback to be invoked and passed each value this Set contains.
     * @param {*} [callbackScope] - The scope of the callback.
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    each: function (callback, callbackScope)
    {
        var i;
        var temp = this.entries.slice();
        var len = temp.length;

        if (callbackScope)
        {
            for (i = 0; i < len; i++)
            {
                if (callback.call(callbackScope, temp[i], i) === false)
                {
                    break;
                }
            }
        }
        else
        {
            for (i = 0; i < len; i++)
            {
                if (callback(temp[i], i) === false)
                {
                    break;
                }
            }
        }

        return this;
    },

    /**
     * Passes each value in this Set to the given callback.
     * For when you absolutely know this Set won't be modified during the iteration.
     *
     * @method Phaser.Structs.Set#iterate
     * @since 3.0.0
     *
     * @genericUse {EachSetCallback.<T>} - [callback]
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @param {EachSetCallback} callback - The callback to be invoked and passed each value this Set contains.
     * @param {*} [callbackScope] - The scope of the callback.
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    iterate: function (callback, callbackScope)
    {
        var i;
        var len = this.entries.length;

        if (callbackScope)
        {
            for (i = 0; i < len; i++)
            {
                if (callback.call(callbackScope, this.entries[i], i) === false)
                {
                    break;
                }
            }
        }
        else
        {
            for (i = 0; i < len; i++)
            {
                if (callback(this.entries[i], i) === false)
                {
                    break;
                }
            }
        }

        return this;
    },

    /**
     * Goes through each entry in this Set and invokes the given function on them, passing in the arguments.
     *
     * @method Phaser.Structs.Set#iterateLocal
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @param {string} callbackKey - The key of the function to be invoked on each Set entry.
     * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child.
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    iterateLocal: function (callbackKey)
    {
        var i;
        var args = [];

        for (i = 1; i < arguments.length; i++)
        {
            args.push(arguments[i]);
        }

        var len = this.entries.length;

        for (i = 0; i < len; i++)
        {
            var entry = this.entries[i];

            entry[callbackKey].apply(entry, args);
        }

        return this;
    },

    /**
     * Clears this Set so that it no longer contains any values.
     *
     * @method Phaser.Structs.Set#clear
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Set.<T>} - [$return]
     *
     * @return {Phaser.Structs.Set} This Set object.
     */
    clear: function ()
    {
        this.entries.length = 0;

        return this;
    },

    /**
     * Returns `true` if this Set contains the given value, otherwise returns `false`.
     *
     * @method Phaser.Structs.Set#contains
     * @since 3.0.0
     *
     * @genericUse {T} - [value]
     *
     * @param {*} value - The value to check for in this Set.
     *
     * @return {boolean} `true` if the given value was found in this Set, otherwise `false`.
     */
    contains: function (value)
    {
        return (this.entries.indexOf(value) > -1);
    },

    /**
     * Returns a new Set containing all values that are either in this Set or in the Set provided as an argument.
     *
     * @method Phaser.Structs.Set#union
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Set.<T>} - [set,$return]
     *
     * @param {Phaser.Structs.Set} set - The Set to perform the union with.
     *
     * @return {Phaser.Structs.Set} A new Set containing all the values in this Set and the Set provided as an argument.
     */
    union: function (set)
    {
        var newSet = new Set();

        set.entries.forEach(function (value)
        {
            newSet.set(value);
        });

        this.entries.forEach(function (value)
        {
            newSet.set(value);
        });

        return newSet;
    },

    /**
     * Returns a new Set that contains only the values which are in this Set and that are also in the given Set.
     *
     * @method Phaser.Structs.Set#intersect
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Set.<T>} - [set,$return]
     *
     * @param {Phaser.Structs.Set} set - The Set to intersect this set with.
     *
     * @return {Phaser.Structs.Set} The result of the intersection, as a new Set.
     */
    intersect: function (set)
    {
        var newSet = new Set();

        this.entries.forEach(function (value)
        {
            if (set.contains(value))
            {
                newSet.set(value);
            }
        });

        return newSet;
    },

    /**
     * Returns a new Set containing all the values in this Set which are *not* also in the given Set.
     *
     * @method Phaser.Structs.Set#difference
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Set.<T>} - [set,$return]
     *
     * @param {Phaser.Structs.Set} set - The Set to perform the difference with.
     *
     * @return {Phaser.Structs.Set} A new Set containing all the values in this Set that are not also in the Set provided as an argument to this method.
     */
    difference: function (set)
    {
        var newSet = new Set();

        this.entries.forEach(function (value)
        {
            if (!set.contains(value))
            {
                newSet.set(value);
            }
        });

        return newSet;
    },

    /**
     * The size of this Set. This is the number of entries within it.
     * Changing the size will truncate the Set if the given value is smaller than the current size.
     * Increasing the size larger than the current size has no effect.
     *
     * @name Phaser.Structs.Set#size
     * @type {integer}
     * @since 3.0.0
     */
    size: {

        get: function ()
        {
            return this.entries.length;
        },

        set: function (value)
        {
            if (value < this.entries.length)
            {
                return this.entries.length = value;
            }
            else
            {
                return this.entries.length;
            }
        }

    }

});

module.exports = Set;


/**
 * @typedef {object} Phaser.Types.GameObjects.Particles.ParticleEmitterConfig
 * @since 3.0.0
 *
 * @property {boolean} [active] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#active}.
 * @property {(Phaser.BlendModes|string)} [blendMode] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#blendMode}.
 * @property {*} [callbackScope] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#deathCallbackScope} and {@link Phaser.GameObjects.Particles.ParticleEmitter#emitCallbackScope}.
 * @property {boolean} [collideBottom] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#collideBottom}.
 * @property {boolean} [collideLeft] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#collideLeft}.
 * @property {boolean} [collideRight] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#collideRight}.
 * @property {boolean} [collideTop] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#collideTop}.
 * @property {boolean} [deathCallback] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#deathCallback}.
 * @property {*} [deathCallbackScope] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#deathCallbackScope}.
 * @property {function} [emitCallback] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#emitCallback}.
 * @property {*} [emitCallbackScope] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#emitCallbackScope}.
 * @property {Phaser.GameObjects.GameObject} [follow] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#follow}.
 * @property {number} [frequency] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#frequency}.
 * @property {number} [gravityX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#gravityX}.
 * @property {number} [gravityY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#gravityY}.
 * @property {integer} [maxParticles] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#maxParticles}.
 * @property {string} [name] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#name}.
 * @property {boolean} [on] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#on}.
 * @property {boolean} [particleBringToTop] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#particleBringToTop}.
 * @property {Phaser.GameObjects.Particles.Particle} [particleClass] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#particleClass}.
 * @property {boolean} [radial] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#radial}.
 * @property {number} [timeScale] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#timeScale}.
 * @property {boolean} [trackVisible] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#trackVisible}.
 * @property {boolean} [visible] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#visible}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [accelerationX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#accelerationX} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [accelerationY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#accelerationY} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback|object} [alpha] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#alpha}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [angle] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#angle} (emit only)
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [bounce] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#bounce} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [delay] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#delay} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [lifespan] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#lifespan} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [maxVelocityX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityX} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [maxVelocityY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityY} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [moveToX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#moveToX} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [moveToY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#moveToY} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [quantity] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#quantity} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback|object} [rotate] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#rotate}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback|object} [scale] - As {@link Phaser.GameObjects.Particles.ParticleEmitter#setScale}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback|object} [scaleX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#scaleX}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback|object} [scaleY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#scaleY}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [speed] - As {@link Phaser.GameObjects.Particles.ParticleEmitter#setSpeed} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [speedX] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#speedX} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [speedY] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#speedY} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [tint] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#tint}.
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [x] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#x} (emit only).
 * @property {number|number[]|Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback|object} [y] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#y} (emit only).
 * @property {object} [emitZone] - As {@link Phaser.GameObjects.Particles.ParticleEmitter#setEmitZone}.
 * @property {Phaser.Types.GameObjects.Particles.ParticleEmitterBounds|Phaser.Types.GameObjects.Particles.ParticleEmitterBoundsAlt} [bounds] - As {@link Phaser.GameObjects.Particles.ParticleEmitter#setBounds}.
 * @property {object} [followOffset] - Assigns to {@link Phaser.GameObjects.Particles.ParticleEmitter#followOffset}.
 * @property {number} [followOffset.x] - x-coordinate of the offset.
 * @property {number} [followOffset.y] - y-coordinate of the offset.
 * @property {number|number[]|string|string[]|Phaser.Textures.Frame|Phaser.Textures.Frame[]|Phaser.Types.GameObjects.Particles.ParticleEmitterFrameConfig} [frame] - Sets {@link Phaser.GameObjects.Particles.ParticleEmitter#frames}.
 */


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * The Matter Physics Drag Event.
 *
 * This event is dispatched by a Matter Physics World instance when a Pointer Constraint
 * is actively dragging a body. It is emitted each time the pointer moves.
 *
 * Listen to it from a Scene using: `this.matter.world.on('drag', listener)`.
 *
 * @event Phaser.Physics.Matter.Events#DRAG
 * @since 3.16.2
 *
 * @param {MatterJS.Body} body - The Body that is being dragged. This is a Matter Body, not a Phaser Game Object.
 * @param {Phaser.Physics.Matter.PointerConstraint} constraint - The Pointer Constraint that is dragging the body.
 */
module.exports = 'drag';


renderer.batchSprite(src, src.frame, camera, parentMatrix);


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Clone = require('../../utils/object/Clone');
var Defaults = require('../tween/Defaults');
var GetAdvancedValue = require('../../utils/object/GetAdvancedValue');
var GetBoolean = require('./GetBoolean');
var GetEaseFunction = require('./GetEaseFunction');
var GetNewValue = require('./GetNewValue');
var GetTargets = require('./GetTargets');
var GetTweens = require('./GetTweens');
var GetValue = require('../../utils/object/GetValue');
var Timeline = require('../Timeline');
var TweenBuilder = require('./TweenBuilder');

/**
 * Builds a Timeline of Tweens based on a configuration object.
 *
 * The configuration object (`config`) can have the following properties:
 *
 * `tweens` - an array of tween configuration objects to create and add into the new Timeline, as described by `TweenBuilder`. If this doesn't exist or is empty, the Timeline will start off paused and none of the other configuration settings will be read. If it's a function, it will be called and its return value will be used as the array.
 * `targets` - an array (or function which returns one) of default targets to which to apply the Timeline. Each individual Tween configuration can override this value.
 * `totalDuration` - if specified, each Tween in the Timeline will get an equal portion of this duration, usually in milliseconds, by default. Each individual Tween configuration can override the Tween's duration.
 * `duration` - if `totalDuration` is not specified, the default duration, usually in milliseconds, of each Tween which will be created. Each individual Tween configuration can override the Tween's duration.
 * `delay`, `easeParams`, `ease`, `hold`, `repeat`, `repeatDelay`, `yoyo`, `flipX`, `flipY` - the default settings for each Tween which will be created, as specified by `TweenBuilder`. Each individual Tween configuration can override any of these values.
 * `completeDelay` - if specified, the time to wait, usually in milliseconds, before the Timeline completes.
 * `loop` - how many times the Timeline should loop, or -1 to loop indefinitely.
 * `loopDelay` - the time, usually in milliseconds, between each loop
 * `paused` - if `true`, the Timeline will start paused
 * `useFrames` - if `true`, all duration in the Timeline will be in frames instead of milliseconds
 * `callbackScope` - the default scope (`this` value) to use for each callback registered by the Timeline Builder. If not specified, the Timeline itself will be used.
 * `onStart` - if specified, the `onStart` callback for the Timeline, called every time it starts playing
 * `onStartScope` - the scope (`this` value) to use for the `onStart` callback. If not specified, the `callbackScope` will be used.
 * `onStartParams` - additional arguments to pass to the `onStart` callback. The Timeline will always be the first argument.
 * `onUpdate` - if specified, the `onUpdate` callback for the Timeline, called every frame it's active, regardless of its Tweens
 * `onUpdateScope` - the scope (`this` value) to use for the `onUpdate` callback. If not specified, the `callbackScope` will be used.
 * `onUpdateParams` - additional arguments to pass to the `onUpdate` callback. The Timeline will always be the first argument.
 * `onLoop` - if specified, the `onLoop` callback for the Timeline, called every time it loops
 * `onLoopScope` - the scope (`this` value) to use for the `onLoop` callback. If not specified, the `callbackScope` will be used.
 * `onLoopParams` - additional arguments to pass to the `onLoop` callback. The Timeline will always be the first argument.
 * `onYoyo` - if specified, the `onYoyo` callback for the Timeline, called every time it yoyos
 * `onYoyoScope` - the scope (`this` value) to use for the `onYoyo` callback. If not specified, the `callbackScope` will be used.
 * `onYoyoParams` - additional arguments to pass to the `onYoyo` callback. The first argument will always be `null`, while the Timeline will always be the second argument.
 * `onComplete` - if specified, the `onComplete` callback for the Timeline, called after it completes
 * `onCompleteScope` - the scope (`this` value) to use for the `onComplete` callback. If not specified, the `callbackScope` will be used.
 * `onCompleteParams` - additional arguments to pass to the `onComplete` callback. The Timeline will always be the first argument.
 *
 * @function Phaser.Tweens.Builders.TimelineBuilder
 * @since 3.0.0
 *
 * @param {Phaser.Tweens.TweenManager} manager - The Tween Manager to which the Timeline will belong.
 * @param {object} config - The configuration object for the Timeline, as described above.
 *
 * @return {Phaser.Tweens.Timeline} The created Timeline.
 */
var TimelineBuilder = function (manager, config)
{
    var timeline = new Timeline(manager);

    var tweens = GetTweens(config);

    if (tweens.length === 0)
    {
        timeline.paused = true;

        return timeline;
    }

    var defaults = Clone(Defaults);

    defaults.targets = GetTargets(config);

    //  totalDuration: If specified each tween in the Timeline is given an equal portion of the totalDuration

    var totalDuration = GetAdvancedValue(config, 'totalDuration', 0);

    if (totalDuration > 0)
    {
        defaults.duration = Math.floor(totalDuration / tweens.length);
    }
    else
    {
        defaults.duration = GetNewValue(config, 'duration', defaults.duration);
    }

    defaults.delay = GetNewValue(config, 'delay', defaults.delay);
    defaults.easeParams = GetValue(config, 'easeParams', defaults.easeParams);
    defaults.ease = GetEaseFunction(GetValue(config, 'ease', defaults.ease), defaults.easeParams);
    defaults.hold = GetNewValue(config, 'hold', defaults.hold);
    defaults.repeat = GetNewValue(config, 'repeat', defaults.repeat);
    defaults.repeatDelay = GetNewValue(config, 'repeatDelay', defaults.repeatDelay);
    defaults.yoyo = GetBoolean(config, 'yoyo', defaults.yoyo);
    defaults.flipX = GetBoolean(config, 'flipX', defaults.flipX);
    defaults.flipY = GetBoolean(config, 'flipY', defaults.flipY);

    //  Create the Tweens
    for (var i = 0; i < tweens.length; i++)
    {
        timeline.queue(TweenBuilder(timeline, tweens[i], defaults));
    }

    timeline.completeDelay = GetAdvancedValue(config, 'completeDelay', 0);
    timeline.loop = Math.round(GetAdvancedValue(config, 'loop', 0));
    timeline.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', 0));
    timeline.paused = GetBoolean(config, 'paused', false);
    timeline.useFrames = GetBoolean(config, 'useFrames', false);

    //  Callbacks

    var scope = GetValue(config, 'callbackScope', timeline);

    var timelineArray = [ timeline ];

    var onStart = GetValue(config, 'onStart', false);

    //  The Start of the Timeline
    if (onStart)
    {
        var onStartScope = GetValue(config, 'onStartScope', scope);
        var onStartParams = GetValue(config, 'onStartParams', []);

        timeline.setCallback('onStart', onStart, timelineArray.concat(onStartParams), onStartScope);
    }

    var onUpdate = GetValue(config, 'onUpdate', false);

    //  Every time the Timeline updates (regardless which Tweens are running)
    if (onUpdate)
    {
        var onUpdateScope = GetValue(config, 'onUpdateScope', scope);
        var onUpdateParams = GetValue(config, 'onUpdateParams', []);

        timeline.setCallback('onUpdate', onUpdate, timelineArray.concat(onUpdateParams), onUpdateScope);
    }

    var onLoop = GetValue(config, 'onLoop', false);

    //  Called when the whole Timeline loops
    if (onLoop)
    {
        var onLoopScope = GetValue(config, 'onLoopScope', scope);
        var onLoopParams = GetValue(config, 'onLoopParams', []);

        timeline.setCallback('onLoop', onLoop, timelineArray.concat(onLoopParams), onLoopScope);
    }

    var onYoyo = GetValue(config, 'onYoyo', false);

    //  Called when a Timeline yoyos
    if (onYoyo)
    {
        var onYoyoScope = GetValue(config, 'onYoyoScope', scope);
        var onYoyoParams = GetValue(config, 'onYoyoParams', []);

        timeline.setCallback('onYoyo', onYoyo, timelineArray.concat(null, onYoyoParams), onYoyoScope);
    }

    var onComplete = GetValue(config, 'onComplete', false);

    //  Called when the Timeline completes, after the completeDelay, etc.
    if (onComplete)
    {
        var onCompleteScope = GetValue(config, 'onCompleteScope', scope);
        var onCompleteParams = GetValue(config, 'onCompleteParams', []);

        timeline.setCallback('onComplete', onComplete, timelineArray.concat(onCompleteParams), onCompleteScope);
    }

    return timeline;
};

module.exports = TimelineBuilder;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var renderWebGL = require('../../../utils/NOOP');
var renderCanvas = require('../../../utils/NOOP');

if (typeof WEBGL_RENDERER)
{
    renderWebGL = require('./TriangleWebGLRenderer');
}

if (typeof CANVAS_RENDERER)
{
    renderCanvas = require('./TriangleCanvasRenderer');
}

module.exports = {

    renderWebGL: renderWebGL,
    renderCanvas: renderCanvas

};


/**
 * @typedef {object} Phaser.Types.Curves.JSONEllipseCurve
 * @since 3.0.0
 *
 * @property {string} type - The of the curve.
 * @property {number} x - The x coordinate of the ellipse.
 * @property {number} y - The y coordinate of the ellipse.
 * @property {number} xRadius - The horizontal radius of ellipse.
 * @property {number} yRadius - The vertical radius of ellipse.
 * @property {integer} startAngle - The start angle of the ellipse, in degrees.
 * @property {integer} endAngle - The end angle of the ellipse, in degrees.
 * @property {boolean} clockwise - Sets if the the ellipse rotation is clockwise (true) or anti-clockwise (false)
 * @property {integer} rotation - The rotation of ellipse, in degrees.
 */


}
};
module.exports = TextCanvasRenderer;

renderer.batchSprite(src, src.frame, camera, parentMatrix);


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * @namespace Phaser.GameObjects.Events
 */

module.exports = { DESTROY: require('./DESTROY_EVENT') };


/**
 * The position and size of the Bitmap Text in global space, taking into account the Game Object's scale and world position.
 *
 * @typedef {object} Phaser.Types.GameObjects.BitmapText.GlobalBitmapTextSize
 * @since 3.0.0
 *
 * @property {number} x - The x position of the BitmapText, taking into account the x position and scale of the Game Object.
 * @property {number} y - The y position of the BitmapText, taking into account the y position and scale of the Game Object.
 * @property {number} width - The width of the BitmapText, taking into account the x scale of the Game Object.
 * @property {number} height - The height of the BitmapText, taking into account the y scale of the Game Object.
 */


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * The Pointer Up Input Event.
 *
 * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is released anywhere.
 *
 * Listen to this event from within a Scene using: `this.input.on('pointerup', listener)`.
 *
 * The event hierarchy is as follows:
 *
 * 1. [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP}
 * 2. [GAMEOBJECT_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_UP}
 * 3. [POINTER_UP]{@linkcode Phaser.Input.Events#event:POINTER_UP} or [POINTER_UP_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_UP_OUTSIDE}
 *
 * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop
 * the propagation of this event.
 *
 * @event Phaser.Input.Events#POINTER_UP
 * @since 3.0.0
 *
 * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event.
 * @param {Phaser.GameObjects.GameObject[]} currentlyOver - An array containing all interactive Game Objects that the pointer was over when the event was created.
 */
module.exports = 'pointerup';


keep keep keep keep replace keep keep keep keep

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Utils = require('../../../renderer/webgl/Utils');

/**
 * Renders this Game Object with the WebGL Renderer to the given Camera.
 * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
 * This method should not be called directly. It is a utility function of the Render module.
 *
 * @method Phaser.GameObjects.Text#renderWebGL
 * @since 3.0.0
 * @private
 *
 * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
 * @param {Phaser.GameObjects.Text} src - The Game Object being rendered in this call.
 * @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
 */
var TextWebGLRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
    if (src.text === '')
    {
        return;
    }

    var frame = src.frame;
    var width = frame.width;
    var height = frame.height;
    var getTint = Utils.getTintAppendFloatAlpha;

    this.pipeline.batchTexture(
        src,
        frame.glTexture,
        width, height,
        src.x, src.y,
        width / src.style.resolution, height / src.style.resolution,
        src.scaleX, src.scaleY,
        src.rotation,
        src.flipX, src.flipY,
        src.scrollFactorX, src.scrollFactorY,
        src.displayOriginX, src.displayOriginY,
        0, 0, width, height,
        getTint(src._tintTL, camera.alpha * src._alphaTL),
        getTint(src._tintTR, camera.alpha * src._alphaTR),
        getTint(src._tintBL, camera.alpha * src._alphaBL),
        getTint(src._tintBR, camera.alpha * src._alphaBR),
        (src._isTinted && src.tintFill),
        0, 0,
        camera,
        parentMatrix
    );
};

module.exports = TextWebGLRenderer;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Body = require('../lib/body/Body');

/**
 * A component to apply force to Matter.js bodies.
 *
 * @namespace Phaser.Physics.Matter.Components.Force
 * @since 3.0.0
 */
var Force = {

    //  force = vec2 / point

    /**
     * Applies a force to a body.
     *
     * @method Phaser.Physics.Matter.Components.Force#applyForce
     * @since 3.0.0
     *
     * @param {Phaser.Math.Vector2} force - A Vector that specifies the force to apply.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    applyForce: function (force)
    {
        this._tempVec2.set(this.body.position.x, this.body.position.y);

        Body.applyForce(this.body, this._tempVec2, force);

        return this;
    },

    /**
     * Applies a force to a body from a given position.
     *
     * @method Phaser.Physics.Matter.Components.Force#applyForceFrom
     * @since 3.0.0
     *
     * @param {Phaser.Math.Vector2} position - The position in which the force comes from.
     * @param {Phaser.Math.Vector2} force - A Vector that specifies the force to apply.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    applyForceFrom: function (position, force)
    {
        Body.applyForce(this.body, position, force);

        return this;
    },

    /**
     * Apply thrust to the forward position of the body.
     *
     * @method Phaser.Physics.Matter.Components.Force#thrust
     * @since 3.0.0
     *
     * @param {number} speed - A speed value to be applied to a directional force.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    thrust: function (speed)
    {
        var angle = this.body.angle;

        this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle));

        Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2);

        return this;
    },

    /**
     * Apply thrust to the left position of the body.
     *
     * @method Phaser.Physics.Matter.Components.Force#thrustLeft
     * @since 3.0.0
     *
     * @param {number} speed - A speed value to be applied to a directional force.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    thrustLeft: function (speed)
    {
        var angle = this.body.angle - Math.PI / 2;

        this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle));

        Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2);

        return this;
    },

    /**
     * Apply thrust to the right position of the body.
     *
     * @method Phaser.Physics.Matter.Components.Force#thrustRight
     * @since 3.0.0
     *
     * @param {number} speed - A speed value to be applied to a directional force.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    thrustRight: function (speed)
    {
        var angle = this.body.angle + Math.PI / 2;

        this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle));

        Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2);

        return this;
    },

    /**
     * Apply thrust to the back position of the body.
     *
     * @method Phaser.Physics.Matter.Components.Force#thrustBack
     * @since 3.0.0
     *
     * @param {number} speed - A speed value to be applied to a directional force.
     *
     * @return {Phaser.GameObjects.GameObject} This Game Object.
     */
    thrustBack: function (speed)
    {
        var angle = this.body.angle - Math.PI;

        this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle));

        Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2);

        return this;
    }

};

module.exports = Force;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|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    2019 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * Force a value within the boundaries by clamping it to the range `min`, `max`.
 *
 * @function Phaser.Math.Clamp
 * @since 3.0.0
 *
 * @param {number} value - The value to be clamped.
 * @param {number} min - The minimum bounds.
 * @param {number} max - The maximum bounds.
 *
 * @return {number} The clamped value.
 */
var Clamp = function (value, min, max)
{
    return Math.max(min, Math.min(max, value));
};

module.exports = Clamp;


//  Used to create IDs for various Pixi objects.

keep keep keep replace replace replace replace keep keep

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

/**
* New version of PIXI.DefaultShader which was PIXI.PixiShader
*
* @class Phaser.Renderer.Canvas
* @constructor
* @param {Phaser.Game} game - Game reference to the currently running game.
*/
Phaser.Renderer.WebGL.Shaders.Sprite = function (renderer)
{
    this.renderer = renderer;

    //  WebGLContext
    this.gl = renderer.gl;

    /**
     * @property _UID
     * @type Number
     * @private
     */
    this._UID = Phaser._UID++;

    /**
     * The WebGL program.
     * @property program
     * @type Any
     */
    this.program = null;

    /**
    * The Default Vertex shader source.
    *
    * @property defaultVertexSrc
    * @type String
    */
    this.vertexSrc = [
        'attribute vec2 aVertexPosition;',
        'attribute vec2 aTextureCoord;',
        'attribute vec4 aColor;',
        'attribute float aTextureIndex;',

        'uniform vec2 projectionVector;',
        'uniform vec2 offsetVector;',

        'varying vec2 vTextureCoord;',
        'varying vec4 vColor;',
        'varying float vTextureIndex;',

        'const vec2 center = vec2(-1.0, 1.0);',

        'void main(void) {',
        '   if (aTextureIndex > 0.0) gl_Position = vec4(0.0);',
        '   gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center, 0.0, 1.0);',
        '   vTextureCoord = aTextureCoord;',
        '   vColor = vec4(aColor.rgb * aColor.a, aColor.a);',
        '   vTextureIndex = aTextureIndex;',
        '}'
    ];

    /**
     * The fragment shader.
     * @property fragmentSrc
     * @type Array
     */
    this.fragmentSrc = null;

    /**
     * Uniform attributes cache.
     * @property attributes
     * @type Array
     * @private
     */
    this.attributes = [];

    /**
     * A local texture counter for multi-texture shaders.
     * @property textureCount
     * @type Number
     */
    this.textureCount = 0;

    //  @type {WebGLUniformLocation }
    this.uSampler;

    //  @type {WebGLUniformLocation }
    this.projectionVector;

    //  @type {WebGLUniformLocation }
    this.offsetVector;

    //  @type {GLint}
    this.colorAttribute;

    //  @type {GLint}
    this.aTextureIndex;

    //  @type {GLint}
    this.aVertexPosition;

    //  @type {GLint}
    this.aTextureCoord;

    //  @type {WebGLUniformLocation }
    this.translationMatrix;

    //  @type {WebGLUniformLocation }
    this.alpha;

    this.init();
};

Phaser.Renderer.WebGL.Shaders.Sprite.prototype.constructor = Phaser.Renderer.WebGL.Shaders.Sprite;

Phaser.Renderer.WebGL.Shaders.Sprite.prototype = {

    init: function (usingFilter)
    {
        if (this.renderer.enableMultiTextureToggle && !usingFilter)
        {
            this.initMultitexShader();
        }
        else
        {
            this.initDefaultShader();
        }
    },

    initDefaultShader: function ()
    {
        if (this.fragmentSrc === null)
        {
            this.fragmentSrc = [
                'precision lowp float;',
                'varying vec2 vTextureCoord;',
                'varying vec4 vColor;',
                'varying float vTextureIndex;',
                'uniform sampler2D uSampler;',
                'void main(void) {',
                '   gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
                '}'
            ];
        }

        var gl = this.gl;

        var program = this.renderer.compileProgram(this.vertexSrc, this.fragmentSrc);

        gl.useProgram(program);

        // get and store the uniforms for the shader
        this.uSampler = gl.getUniformLocation(program, 'uSampler');
        this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
        this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
        this.dimensions = gl.getUniformLocation(program, 'dimensions');

        // get and store the attributes
        this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
        this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
        this.colorAttribute = gl.getAttribLocation(program, 'aColor');
        this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');

        this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute, this.aTextureIndex];

        // add those custom shaders!
        for (var key in this.uniforms)
        {
            // get the uniform locations..
            this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key);
        }

        this.initUniforms();

        this.program = program;
    },

    initMultitexShader: function ()
    {
        var gl = this.gl;
        var max = this.renderer.getMaxTextureUnits();

        var dynamicIfs = '\tif (vTextureIndex == 0.0) gl_FragColor = texture2D(uSamplerArray[0], vTextureCoord) * vColor;\n';

        for (var index = 1; index < max; ++index)
        {
            dynamicIfs += '\telse if (vTextureIndex == ' +
                        index + '.0) gl_FragColor = texture2D(uSamplerArray[' +
                        index + '], vTextureCoord) * vColor;\n'
        }

        this.fragmentSrc = [
            'precision lowp float;',
            'varying vec2 vTextureCoord;',
            'varying vec4 vColor;',
            'varying float vTextureIndex;',
            'uniform sampler2D uSamplerArray[' + max + '];',
            'const vec4 PINK = vec4(1.0, 0.0, 1.0, 1.0);',
            'const vec4 GREEN = vec4(0.0, 1.0, 0.0, 1.0);',
            'void main(void) {',
            dynamicIfs,
            'else gl_FragColor = PINK;',
            '}'
        ];

        var program = this.renderer.compileProgram(this.vertexSrc, this.fragmentSrc);

        gl.useProgram(program);

        // get and store the uniforms for the shader
        this.uSamplerArray = gl.getUniformLocation(program, 'uSamplerArray[0]');
        this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
        this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
        this.dimensions = gl.getUniformLocation(program, 'dimensions');

        // get and store the attributes
        this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
        this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
        this.colorAttribute = gl.getAttribLocation(program, 'aColor');
        this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');

        var indices = [];

        //  Bind an empty texture to avoid WebGL console warning spam
        var tempTexture = gl.createTexture();

        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, tempTexture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);

        for (var i = 0; i < max; ++i)
        {
            gl.activeTexture(gl.TEXTURE0 + i);
            gl.bindTexture(gl.TEXTURE_2D, tempTexture);
            indices.push(i);
        }

        gl.activeTexture(gl.TEXTURE0);
        gl.uniform1iv(this.uSamplerArray, indices);

        this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute, this.aTextureIndex];

        //  Add those custom shaders!
        for (var key in this.uniforms)
        {
            this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key);
        }

        this.initUniforms();

        this.program = program;
    },

    initUniforms: function ()
    {
        this.textureCount = 1;
        var gl = this.gl;
        var uniform;

        for (var key in this.uniforms)
        {
            uniform = this.uniforms[key];

            switch (uniform.type)
            {
                case 'sampler2D':

                    uniform._init = false;

                    if (uniform.value !== null)
                    {
                        this.initSampler2D(uniform);
                    }

                    break;

                case 'mat2':

                    uniform.glMatrix = true;
                    uniform.glValueLength = 1;
                    uniform.glFunc = gl.uniformMatrix2fv;
                    break;

                case 'mat3':

                    uniform.glMatrix = true;
                    uniform.glValueLength = 1;
                    uniform.glFunc = gl.uniformMatrix3fv;
                    break;

                case 'mat4':

                    uniform.glMatrix = true;
                    uniform.glValueLength = 1;
                    uniform.glFunc = gl.uniformMatrix4fv;
                    break;

                default:

                    //  GL function reference
                    uniform.glFunc = gl['uniform' + uniform.type];

                    if (uniform.type === '2f' || uniform.type === '2i')
                    {
                        uniform.glValueLength = 2;
                    }
                    else if (uniform.type === '3f' || uniform.type === '3i')
                    {
                        uniform.glValueLength = 3;
                    }
                    else if (uniform.type === '4f' || uniform.type === '4i')
                    {
                        uniform.glValueLength = 4;
                    }
                    else
                    {
                        uniform.glValueLength = 1;
                    }
            }
        }

    },

    /**
    * Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded)
    *
    * @method initSampler2D
    */
    initSampler2D: function (uniform)
    {
        if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded)
        {
            return;
        }

        var gl = this.gl;

        // No need to do string manipulation for this.
        gl.activeTexture(gl.TEXTURE0 + this.textureCount);
        gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures);

        //  Extended texture data
        if (uniform.textureData)
        {
            var data = uniform.textureData;

            // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D);
            // GLTextureLinear = mag/min linear, wrap clamp
            // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat
            // GLTextureNearest = mag/min nearest, wrap clamp
            // AudioTexture = whatever + luminance + width 512, height 2, border 0
            // KeyTexture = whatever + luminance + width 256, height 2, border 0

            //  magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST
            //  wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT

            var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR;
            var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR;
            var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE;
            var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE;
            var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA;

            if (data.repeat)
            {
                wrapS = gl.REPEAT;
                wrapT = gl.REPEAT;
            }

            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY);

            if (data.width)
            {
                var width = (data.width) ? data.width : 512;
                var height = (data.height) ? data.height : 2;
                var border = (data.border) ? data.border : 0;

                // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
                gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null);
            }
            else
            {
                //  void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels);
                gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source);
            }

            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
        }

        gl.uniform1i(uniform.uniformLocation, this.textureCount);

        uniform._init = true;

        this.textureCount++;
    },

    /**
    * Updates the shader uniform values.
    *
    * @method syncUniforms
    */
    syncUniforms: function ()
    {
        this.textureCount = 1;

        var uniform;

        var gl = this.gl;

        //  This would probably be faster in an array and it would guarantee key order
        for (var key in this.uniforms)
        {
            uniform = this.uniforms[key];

            if (uniform.glValueLength === 1)
            {
                if (uniform.glMatrix === true)
                {
                    uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value);
                }
                else
                {
                    uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value);
                }
            }
            else if (uniform.glValueLength === 2)
            {
                uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y);
            }
            else if (uniform.glValueLength === 3)
            {
                uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z);
            }
            else if (uniform.glValueLength === 4)
            {
                uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w);
            }
            else if (uniform.type === 'sampler2D')
            {
                if (uniform._init)
                {
                    gl.activeTexture(gl['TEXTURE' + this.textureCount]);

                    if (uniform.value.baseTexture._dirty)
                    {
                        this.renderer.updateTexture(uniform.value.baseTexture);
                    }
                    else
                    {
                        gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures);
                    }

                    gl.uniform1i(uniform.uniformLocation, this.textureCount);

                    this.textureCount++;
                }
                else
                {
                    this.initSampler2D(uniform);
                }
            }
        }

    },

    destroy: function ()
    {
        this.gl.deleteProgram(this.program);
        this.uniforms = null;
        this.gl = null;
        this.renderer = null;
        this.attributes = null;
    }

};


/**
 * Sunlight line number/line highlighting plugin
 *
 * This creates the line number gutter in addition to creating the line highlighting
 * overlay (if applicable). It is bundled in sunlight-min.js.
 *
 * Options:
 * 	- lineNumbers: true/false/"automatic" (default is "automatic")
 * 	- lineNumberStart: <number> (line number to start from, default is 1)
 *	- lineHighlight: <array> (array of line numbers to highlight)
 */
(function(sunlight, document, undefined){
	if (sunlight === undefined) {
		throw "Include sunlight.js before including plugin files";
	}

	function getLineCount(node) {
		//browsers don't render the last trailing newline, so we make sure that the line numbers reflect that
		//by disregarding the last trailing newline

		//get the last text node
		var lastTextNode = function getLastNode(node) {
			if (!node.lastChild) {
				return null;
			}

			if (node.lastChild.nodeType === 3) {
				return node.lastChild;
			}

			return getLastNode(node.lastChild);
		}(node) || { lastChild: "" };

		return node.innerHTML.replace(/[^\n]/g, "").length - /\n$/.test(lastTextNode.nodeValue);
	}

	sunlight.bind("afterHighlightNode", function(context) {
		var lineContainer,
			lineCount,
			lineHighlightOverlay,
			currentLineOverlay,
			lineHighlightingEnabled,
			i,
			eol,
			link,
			name;

		if (!this.options.lineNumbers) {
			return;
		}

		if (this.options.lineNumbers === "automatic" && sunlight.util.getComputedStyle(context.node, "display") !== "block") {
			//if it's not a block level element or the lineNumbers option is not set to "automatic"
			return;
		}

		lineContainer = document.createElement("pre");
		lineCount = getLineCount(context.node);

		lineHighlightingEnabled = this.options.lineHighlight.length > 0;
		if (lineHighlightingEnabled) {
			lineHighlightOverlay = document.createElement("div");
			lineHighlightOverlay.className = this.options.classPrefix + "line-highlight-overlay";
		}

		lineContainer.className = this.options.classPrefix + "line-number-margin";

		eol = document.createTextNode(sunlight.util.eol)
		for (i = this.options.lineNumberStart; i <= this.options.lineNumberStart + lineCount; i++) {
			link = document.createElement("a");
			name = (context.node.id ? context.node.id : this.options.classPrefix + context.count) + "-line-" + i;

			link.setAttribute("name", name);
			link.setAttribute("href", "#" + name);

			link.appendChild(document.createTextNode(i));
			lineContainer.appendChild(link);
			lineContainer.appendChild(eol.cloneNode(false));

			if (lineHighlightingEnabled) {
				currentLineOverlay = document.createElement("div");
				if (sunlight.util.contains(this.options.lineHighlight, i)) {
					currentLineOverlay.className = this.options.classPrefix + "line-highlight-active";
				}
				lineHighlightOverlay.appendChild(currentLineOverlay);
			}
		}

		context.codeContainer.insertBefore(lineContainer, context.codeContainer.firstChild);

		if (lineHighlightingEnabled) {
			context.codeContainer.appendChild(lineHighlightOverlay);
		}

		//enable the border on the code container
		context.codeContainer.style.borderWidth = "1px";
		context.codeContainer.style.borderStyle = "solid";
	});

	sunlight.globalOptions.lineNumbers = "automatic";
	sunlight.globalOptions.lineNumberStart = 1;
	sunlight.globalOptions.lineHighlight = [];

}(this["Sunlight"], document));


Phaser.QuadTree

x

The top left coordinate of the quadtree.

maxLevels

The maximum number of levels to iterate to.

A QuadTree implementation. The original code was a conversion of the Java code posted to GameDevTuts.\nHowever I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.\nOriginal version at https://github.com/timohausmann/quadtree-js/

getIndex

index - Index of the subnode (0-3), or -1 if rect cannot completely fit within a subnode and is part of the parent node.

Determine which node the object belongs to.

insert

Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.

body

The Body object to insert into the quadtree. Can be any object so long as it exposes x, y, right and bottom properties.

populate

Populates this quadtree with the children of the given Group. In order to be added the child must exist and have a body property.

retrieve

Return all objects that could collide with the given Sprite or Rectangle.

source

The source object to check the QuadTree against. Either a Sprite or Rectangle.

bounds

Object that contains the quadtree bounds.

maxLevels

The maximum number of levels to break down to.


PIXI.SpriteSheetLoader

crossorigin

Whether requests should be treated as crossorigin

The sprite sheet loader is used to load in JSON sprite sheet data\nTo generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format\nThere is a free version so thats nice, although the paid version is great value for money.\nIt is highly recommended to use Sprite sheets (also know as a 'texture atlas') as it means sprites can be batched and drawn together for highly increased rendering speed.\nOnce the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFrameId()\nThis loader will load the image file that the Spritesheet points to as well as the data.\nWhen loaded this class will dispatch a 'loaded' event

onLoaded

Invoke when all files are loaded (json and texture)

baseUrl

[read-only] The base url of the bitmap font data

crossorigin

Whether the requests should be treated as cross origin


* This sets if the CanvasRenderer will clear the canvas or not before the new render pass.

* If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color.

* If the Stage is transparent Pixi will use clearRect to clear the canvas every frame.

* Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set.

keep keep keep keep add keep keep keep keep keep

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

/**
* @namespace Phaser
*/
var Phaser = Phaser || {    // jshint ignore:line

    /**
    * The Phaser version number.
    * @constant
    * @type {string}
    */
    VERSION: '3.0.0.r4',

    /**
    * An array of Phaser game instances.
    * @constant
    * @type {array}
    */
    GAMES: [],

    /**
    * AUTO renderer - picks between WebGL or Canvas based on device.
    * @constant
    * @type {integer}
    */
    AUTO: 0,

    /**
    * Canvas Renderer.
    * @constant
    * @type {integer}
    */
    CANVAS: 1,

    /**
    * WebGL Renderer.
    * @constant
    * @type {integer}
    */
    WEBGL: 2,

    /**
    * Headless renderer (not visual output)
    * @constant
    * @type {integer}
    */
    HEADLESS: 3,

    /**
    * WebGL Renderer with MultiTexture support enabled.
    * @constant
    * @type {integer}
    */
    WEBGL_MULTI: 4,

    /**
    * Direction constant.
    * @constant
    * @type {integer}
    */
    NONE: 0,

    /**
    * Direction constant.
    * @constant
    * @type {integer}
    */
    LEFT: 1,

    /**
    * Direction constant.
    * @constant
    * @type {integer}
    */
    RIGHT: 2,

    /**
    * Direction constant.
    * @constant
    * @type {integer}
    */
    UP: 3,

    /**
    * Direction constant.
    * @constant
    * @type {integer}
    */
    DOWN: 4,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    SPRITE: 0,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    BUTTON: 1,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    IMAGE: 2,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    GRAPHICS: 3,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    TEXT: 4,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    TILESPRITE: 5,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    BITMAPTEXT: 6,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    GROUP: 7,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    RENDERTEXTURE: 8,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    TILEMAP: 9,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    TILEMAPLAYER: 10,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    EMITTER: 11,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    POLYGON: 12,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    BITMAPDATA: 13,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    CANVAS_FILTER: 14,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    WEBGL_FILTER: 15,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    ELLIPSE: 16,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    SPRITEBATCH: 17,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    RETROFONT: 18,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    POINTER: 19,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    ROPE: 20,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    CIRCLE: 21,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    RECTANGLE: 22,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    LINE: 23,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    MATRIX: 24,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    POINT: 25,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    ROUNDEDRECTANGLE: 26,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    CREATURE: 27,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    VIDEO: 28,

    /**
    * Game Object type.
    * @constant
    * @type {integer}
    */
    PENDING_ATLAS: -1,

    /**
    * A horizontal orientation
    * @constant
    * @type {integer}
    */
    HORIZONTAL: 0,

    /**
    * A vertical orientation
    * @constant
    * @type {integer}
    */
    VERTICAL: 1,

    /**
    * A landscape orientation
    * @constant
    * @type {integer}
    */
    LANDSCAPE: 0,

    /**
    * A portrait orientation
    * @constant
    * @type {integer}
    */
    PORTRAIT: 1,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face up.
    * @constant
    * @type {integer}
    */
    ANGLE_UP: 270,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face down.
    * @constant
    * @type {integer}
    */
    ANGLE_DOWN: 90,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face left.
    * @constant
    * @type {integer}
    */
    ANGLE_LEFT: 180,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face right.
    * @constant
    * @type {integer}
    */
    ANGLE_RIGHT: 0,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face north east.
    * @constant
    * @type {integer}
    */
    ANGLE_NORTH_EAST: 315,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face north west.
    * @constant
    * @type {integer}
    */
    ANGLE_NORTH_WEST: 225,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face south east.
    * @constant
    * @type {integer}
    */
    ANGLE_SOUTH_EAST: 45,

    /**
    * The Angle (in degrees) a Game Object needs to be set to in order to face south west.
    * @constant
    * @type {integer}
    */
    ANGLE_SOUTH_WEST: 135,

    /**
    * A constant representing a top-left alignment or position.
    * @constant
    * @type {integer}
    */
    TOP_LEFT: 0,

    /**
    * A constant representing a top-center alignment or position.
    * @constant
    * @type {integer}
    */
    TOP_CENTER: 1,

    /**
    * A constant representing a top-right alignment or position.
    * @constant
    * @type {integer}
    */
    TOP_RIGHT: 2,

    /**
    * A constant representing a left-top alignment or position.
    * @constant
    * @type {integer}
    */
    LEFT_TOP: 3,

    /**
    * A constant representing a left-center alignment or position.
    * @constant
    * @type {integer}
    */
    LEFT_CENTER: 4,

    /**
    * A constant representing a left-bottom alignment or position.
    * @constant
    * @type {integer}
    */
    LEFT_BOTTOM: 5,

    /**
    * A constant representing a center alignment or position.
    * @constant
    * @type {integer}
    */
    CENTER: 6,

    /**
    * A constant representing a right-top alignment or position.
    * @constant
    * @type {integer}
    */
    RIGHT_TOP: 7,

    /**
    * A constant representing a right-center alignment or position.
    * @constant
    * @type {integer}
    */
    RIGHT_CENTER: 8,

    /**
    * A constant representing a right-bottom alignment or position.
    * @constant
    * @type {integer}
    */
    RIGHT_BOTTOM: 9,

    /**
    * A constant representing a bottom-left alignment or position.
    * @constant
    * @type {integer}
    */
    BOTTOM_LEFT: 10,

    /**
    * A constant representing a bottom-center alignment or position.
    * @constant
    * @type {integer}
    */
    BOTTOM_CENTER: 11,

    /**
    * A constant representing a bottom-right alignment or position.
    * @constant
    * @type {integer}
    */
    BOTTOM_RIGHT: 12,

    /**
    * Various blend modes supported by Pixi.
    *
    * IMPORTANT: The WebGL renderer only supports the NORMAL, ADD, MULTIPLY and SCREEN blend modes.
    *
    * @constant
    * @property {Number} blendModes.NORMAL
    * @property {Number} blendModes.ADD
    * @property {Number} blendModes.MULTIPLY
    * @property {Number} blendModes.SCREEN
    * @property {Number} blendModes.OVERLAY
    * @property {Number} blendModes.DARKEN
    * @property {Number} blendModes.LIGHTEN
    * @property {Number} blendModes.COLOR_DODGE
    * @property {Number} blendModes.COLOR_BURN
    * @property {Number} blendModes.HARD_LIGHT
    * @property {Number} blendModes.SOFT_LIGHT
    * @property {Number} blendModes.DIFFERENCE
    * @property {Number} blendModes.EXCLUSION
    * @property {Number} blendModes.HUE
    * @property {Number} blendModes.SATURATION
    * @property {Number} blendModes.COLOR
    * @property {Number} blendModes.LUMINOSITY
    * @static
    */
    blendModes: {
        NORMAL: 0,
        ADD: 1,
        MULTIPLY: 2,
        SCREEN: 3,
        OVERLAY: 4,
        DARKEN: 5,
        LIGHTEN: 6,
        COLOR_DODGE: 7,
        COLOR_BURN: 8,
        HARD_LIGHT: 9,
        SOFT_LIGHT: 10,
        DIFFERENCE: 11,
        EXCLUSION: 12,
        HUE: 13,
        SATURATION: 14,
        COLOR: 15,
        LUMINOSITY: 16
    },

    /**
    * The scale modes that are supported by Pixi.
    *
    * The DEFAULT scale mode affects the default scaling mode of future operations.
    * It can be re-assigned to either LINEAR or NEAREST, depending upon suitability.
    *
    * @constant
    * @property {Object} Phaser.scaleModes
    * @property {Number} scaleModes.DEFAULT=LINEAR
    * @property {Number} scaleModes.LINEAR Smooth scaling
    * @property {Number} scaleModes.NEAREST Pixelating scaling
    * @static
    */
    scaleModes: {
        DEFAULT: 0,
        LINEAR: 0,
        NEAREST: 1
    },

    Renderer: {

    },

    PIXI: PIXI || {

    },

    //  Used to create IDs for various Pixi objects.
    _UID: 0

};


Phaser.Key

keycode

The key code this Key is responsible for.

If you need more fine-grained control over the handling of specific keys you can create and use Phaser.Key objects.

justPressed

True if the key is just pressed otherwise false.

Returns the "just pressed" state of the Key. Just pressed is considered true if the key was pressed down within the duration given.

duration

The duration below which the key is considered as being just pressed.

justReleased

True if the key is just released otherwise false.

Returns the "just released" state of the Key. Just released is considered as being true if the key was released within the duration given.

duration

The duration below which the key is considered as being just released.

reset

Resets the state of this Key. This sets isDown to false, isUp to true, resets the time to be the current time and clears any callbacks\nassociated with the onDown and onUp events and nulls the onHoldCallback if set.

hard

A soft reset won't reset any events or callbacks that are bound to this Key. A hard reset will.

processKeyDown

Called automatically by Phaser.Keyboard.

altKey

The down state of the ALT key, if pressed at the same time as this key.

ctrlKey

The down state of the CTRL key, if pressed at the same time as this key.

duration

If the key is down this value holds the duration of that key press and is constantly updated.\nIf the key is up it holds the duration of the previous down session.

The number of milliseconds this key has been held down for.

enabled

An enabled key processes its update and dispatches events. You can toggle this at run-time to disable a key without deleting it.

game

A reference to the currently running game.

onDown

This Signal is dispatched every time this Key is pressed down. It is only dispatched once (until the key is released again).

onHoldCallback

A callback that is called while this Key is held down. Warning: Depending on refresh rate that could be 60+ times per second.

onHoldContext

The context under which the onHoldCallback will be called.

repeats

If a key is held down this holds down the number of times the key has 'repeated'.

shiftKey

The down state of the SHIFT key, if pressed at the same time as this key.

timeDown

The timestamp when the key was last pressed down. This is based on Game.time.now.

timeUp

The timestamp when the key was last released. This is based on Game.time.now.


BasicGame.Preloader = function (game) {

	this.background = null;
	this.preloadBar = null;

	this.ready = false;

};

BasicGame.Preloader.prototype = {

	preload: function () {

		//	These are the assets we loaded in Boot.js
		//	A nice sparkly background and a loading progress bar
		this.background = this.add.sprite(0, 0, 'preloaderBackground');
		this.preloadBar = this.add.sprite(300, 400, 'preloaderBar');

		//	This sets the preloadBar sprite as a loader sprite.
		//	What that does is automatically crop the sprite from 0 to full-width
		//	as the files below are loaded in.
		this.load.setPreloadSprite(this.preloadBar);

		//	Here we load the rest of the assets our game needs.
		//	As this is just a Project Template I've not provided these assets, swap them for your own.
		this.load.image('titlepage', 'images/title.jpg');
		this.load.atlas('playButton', 'images/play_button.png', 'images/play_button.json');
		this.load.audio('titleMusic', ['audio/main_menu.mp3']);
		this.load.bitmapFont('caslon', 'fonts/caslon.png', 'fonts/caslon.xml');
		//	+ lots of other required assets here

	},

	create: function () {

		//	Once the load has finished we disable the crop because we're going to sit in the update loop for a short while as the music decodes
		this.preloadBar.cropEnabled = false;

	},

	update: function () {

		//	You don't actually need to do this, but I find it gives a much smoother game experience.
		//	Basically it will wait for our audio file to be decoded before proceeding to the MainMenu.
		//	You can jump right into the menu if you want and still play the music, but you'll have a few
		//	seconds of delay while the mp3 decodes - so if you need your music to be in-sync with your menu
		//	it's best to wait for it to decode here first, then carry on.

		//	If you don't have any music in your game then put the game.state.start line into the create function and delete
		//	the update function completely.

		if (this.cache.isSoundDecoded('titleMusic') && this.ready == false)
		{
			this.ready = true;
			this.state.start('MainMenu');
		}

	}

};


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

/**
* A RenderTexture is a special texture that allows any displayObject to be rendered to it. It allows you to take many complex objects and
* render them down into a single quad (on WebGL) which can then be used to texture other display objects with. A way of generating textures at run-time.
*
* @class Phaser.RenderTexture
* @constructor
* @extends PIXI.Texture
* @param {Phaser.Game} game - Current game instance.
* @param {number} [width=100] - The width of the render texture.
* @param {number} [height=100] - The height of the render texture.
* @param {string} [key=''] - The key of the RenderTexture in the Cache, if stored there.
* @param {number} [scaleMode=Phaser.scaleModes.DEFAULT] - One of the Phaser.scaleModes consts.
* @param {number} [resolution=1] - The resolution of the texture being generated.
*/
Phaser.RenderTexture = function (game, width, height, key, scaleMode, resolution, renderer, textureUnit) {

    if (width === undefined) { width = 100; }
    if (height === undefined) { height = 100; }
    if (key === undefined) { key = ''; }
    if (scaleMode === undefined) { scaleMode = Phaser.scaleModes.DEFAULT; }
    if (resolution === undefined) { resolution = 1; }
    if (renderer === undefined) { renderer = PIXI.defaultRenderer; }
    if (textureUnit === undefined) { textureUnit = 0; }

    /**
    * @property {Phaser.Game} game - A reference to the currently running game.
    */
    this.game = game;

    /**
    * @property {string} key - The key of the RenderTexture in the Cache, if stored there.
    */
    this.key = key;

    /**
    * @property {number} type - Base Phaser object type.
    */
    this.type = Phaser.RENDERTEXTURE;

    /**
    * @property {Phaser.Matrix} _tempMatrix - The matrix that is applied when display objects are rendered to this RenderTexture.
    * @private
    */
    this._tempMatrix = new Phaser.Matrix();

    this.width = width;
    this.height = height;
    this.resolution = resolution;

    this.frame = new Phaser.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution);

    this.crop = this.frame.clone();

    /**
     * The base texture object that this texture uses
     *
     * @property baseTexture
     * @type BaseTexture
     */
    this.baseTexture = new PIXI.BaseTexture();
    this.baseTexture.width = this.width * this.resolution;
    this.baseTexture.height = this.height * this.resolution;
    this.baseTexture._glTextures = null;
    this.baseTexture.resolution = this.resolution;

    this.baseTexture.scaleMode = scaleMode;

    this.baseTexture.hasLoaded = true;

    PIXI.Texture.call(this, this.baseTexture, this.frame.clone());

    /**
     * The renderer this RenderTexture uses. A RenderTexture can only belong to one renderer at the moment if its webGL.
     *
     * @property renderer
     * @type CanvasRenderer|WebGLRenderer
     */
    this.renderer = renderer;

    if (this.renderer.type === Phaser.WEBGL)
    {
        var gl = this.renderer.gl;
        this.baseTexture.textureIndex = textureUnit;
        this.baseTexture._dirty[gl.id] = false;

        this.textureBuffer = new PIXI.FilterTexture(gl, this.width, this.height, this.baseTexture.scaleMode, textureUnit);
        this.baseTexture._glTextures = this.textureBuffer.texture;

        this.projection = new Phaser.Point(this.width * 0.5, -this.height * 0.5);
    }
    else
    {
        this.textureBuffer = new PIXI.CanvasBuffer(this.width * this.resolution, this.height * this.resolution);
        this.baseTexture.source = this.textureBuffer.canvas;
    }

    /**
     * @property valid
     * @type Boolean
     */
    this.valid = true;

    this.tempMatrix = new Phaser.Matrix();

    this._updateUvs();

};

Phaser.RenderTexture.prototype = Object.create(PIXI.Texture.prototype);
Phaser.RenderTexture.prototype.constructor = Phaser.RenderTexture;

/**
* This function will draw the display object to the RenderTexture at the given coordinates.
*
* When the display object is drawn it takes into account scale and rotation.
*
* If you don't want those then use RenderTexture.renderRawXY instead.
*
* @method Phaser.RenderTexture.prototype.renderXY
* @param {Phaser.Sprite|Phaser.Image|Phaser.Text|Phaser.BitmapText|Phaser.Group} displayObject - The display object to render to this texture.
* @param {number} x - The x position to render the object at.
* @param {number} y - The y position to render the object at.
* @param {boolean} [clear=false] - If true the texture will be cleared before the display object is drawn.
*/
Phaser.RenderTexture.prototype.renderXY = function (displayObject, x, y, clear) {

    displayObject.updateTransform();

    this._tempMatrix.copyFrom(displayObject.worldTransform);
    this._tempMatrix.tx = x;
    this._tempMatrix.ty = y;

    if (this.renderer.type === Phaser.WEBGL)
    {
        this._renderWebGL(displayObject, this._tempMatrix, clear);
    }
    else
    {
        this._renderCanvas(displayObject, this._tempMatrix, clear);
    }

};

/**
* This function will draw the display object to the RenderTexture at the given coordinates.
*
* When the display object is drawn it doesn't take into account scale, rotation or translation.
*
* If you need those then use RenderTexture.renderXY instead.
*
* @method Phaser.RenderTexture.prototype.renderRawXY
* @param {Phaser.Sprite|Phaser.Image|Phaser.Text|Phaser.BitmapText|Phaser.Group} displayObject - The display object to render to this texture.
* @param {number} x - The x position to render the object at.
* @param {number} y - The y position to render the object at.
* @param {boolean} [clear=false] - If true the texture will be cleared before the display object is drawn.
*/
Phaser.RenderTexture.prototype.renderRawXY = function (displayObject, x, y, clear) {

    this._tempMatrix.identity().translate(x, y);

    if (this.renderer.type === Phaser.WEBGL)
    {
        this._renderWebGL(displayObject, this._tempMatrix, clear);
    }
    else
    {
        this._renderCanvas(displayObject, this._tempMatrix, clear);
    }

};

/**
* This function will draw the display object to the RenderTexture.
*
* In versions of Phaser prior to 2.4.0 the second parameter was a Phaser.Point object.
* This is now a Matrix allowing you much more control over how the Display Object is rendered.
* If you need to replicate the earlier behavior please use Phaser.RenderTexture.renderXY instead.
*
* If you wish for the displayObject to be rendered taking its current scale, rotation and translation into account then either
* pass `null`, leave it undefined or pass `displayObject.worldTransform` as the matrix value.
*
* @method Phaser.RenderTexture.prototype.render
* @param {Phaser.Sprite|Phaser.Image|Phaser.Text|Phaser.BitmapText|Phaser.Group} displayObject - The display object to render to this texture.
* @param {Phaser.Matrix} [matrix] - Optional matrix to apply to the display object before rendering. If null or undefined it will use the worldTransform matrix of the given display object.
* @param {boolean} [clear=false] - If true the texture will be cleared before the display object is drawn.
*/
Phaser.RenderTexture.prototype.render = function (displayObject, matrix, clear) {

    if (matrix === undefined || matrix === null)
    {
        this._tempMatrix.copyFrom(displayObject.worldTransform);
    }
    else
    {
        this._tempMatrix.copyFrom(matrix);
    }

    if (this.renderer.type === Phaser.WEBGL)
    {
        this._renderWebGL(displayObject, this._tempMatrix, clear);
    }
    else
    {
        this._renderCanvas(displayObject, this._tempMatrix, clear);
    }

};

/**
* Resizes the RenderTexture.
*
* @method Phaser.RenderTexture.prototype.resize
* @param {number} width - The width to resize to.
* @param {number} height - The height to resize to.
* @param {boolean} updateBase - Should the baseTexture.width and height values be resized as well?
*/
Phaser.RenderTexture.prototype.resize = function (width, height, updateBase) {

    if (width === this.width && height === this.height)
    {
        return;
    }

    this.valid = (width > 0 && height > 0);

    this.width = width;
    this.height = height;
    this.frame.width = this.crop.width = width * this.resolution;
    this.frame.height = this.crop.height = height * this.resolution;

    if (updateBase)
    {
        this.baseTexture.width = this.width * this.resolution;
        this.baseTexture.height = this.height * this.resolution;
    }

    if (this.renderer.type === Phaser.WEBGL)
    {
        this.projection.x = this.width / 2;
        this.projection.y = -this.height / 2;
    }

    if (!this.valid)
    {
        return;
    }

    this.textureBuffer.resize(this.width, this.height);

};

/**
* Clears the RenderTexture.
*
* @method Phaser.RenderTexture.prototype.clear
*/
Phaser.RenderTexture.prototype.clear = function () {

    if (!this.valid)
    {
        return;
    }

    if (this.renderer.type === Phaser.WEBGL)
    {
        this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
    }

    this.textureBuffer.clear();

};

/**
* This function will draw the display object to the texture.
*
* @private
* @method Phaser.RenderTexture.prototype._renderWebGL
* @param displayObject {DisplayObject} The display object to render this texture on
* @param [matrix] {Matrix} Optional matrix to apply to the display object before rendering.
* @param [clear] {Boolean} If true the texture will be cleared before the displayObject is drawn
* @private
*/
Phaser.RenderTexture.prototype._renderWebGL = function (displayObject, matrix, clear) {

    if (!this.valid || displayObject.alpha === 0)
    {
        return;
    }

    //  Let's create a nice matrix to apply to our display object.
    //  Frame buffers come in upside down so we need to flip the matrix.
    var wt = displayObject.worldTransform;
    wt.identity();
    wt.translate(0, this.projection.y * 2);

    if (matrix)
    {
        wt.append(matrix);
    }

    wt.scale(1, -1);

    //  Time to update all the children of the displayObject with the new matrix.
    for (var i = 0; i < displayObject.children.length; i++)
    {
        displayObject.children[i].updateTransform();
    }

    //  Time for the webGL fun stuff!
    var gl = this.renderer.gl;

    gl.viewport(0, 0, this.width * this.resolution, this.height * this.resolution);

    gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);

    if (clear)
    {
        this.textureBuffer.clear();
    }

    this.renderer.spriteBatch.dirty = true;

    this.renderer.renderDisplayObject(displayObject, this.projection, this.textureBuffer.frameBuffer, matrix);

    this.renderer.spriteBatch.dirty = true;

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

};

/**
* This function will draw the display object to the texture.
*
* @private
* @method Phaser.RenderTexture.prototype._renderCanvas
* @param displayObject {DisplayObject} The display object to render this texture on
* @param [matrix] {Matrix} Optional matrix to apply to the display object before rendering.
* @param [clear] {Boolean} If true the texture will be cleared before the displayObject is drawn
*/
Phaser.RenderTexture.prototype._renderCanvas = function (displayObject, matrix, clear) {

    if (!this.valid || displayObject.alpha === 0)
    {
        return;
    }

    //  Let's create a nice matrix to apply to our display object.
    //  Frame buffers come in upside down so we need to flip the matrix.
    var wt = displayObject.worldTransform;
    wt.identity();

    if (matrix)
    {
        wt.append(matrix);
    }

    // Time to update all the children of the displayObject with the new matrix (what new matrix? there isn't one!)
    for (var i = 0; i < displayObject.children.length; i++)
    {
        displayObject.children[i].updateTransform();
    }

    if (clear)
    {
        this.textureBuffer.clear();
    }

    var realResolution = this.renderer.resolution;

    this.renderer.resolution = this.resolution;

    this.renderer.renderDisplayObject(displayObject, this.textureBuffer.context, matrix);

    this.renderer.resolution = realResolution;

};

/**
* Will return a HTML Image of the texture
*
* @method Phaser.RenderTexture.prototype.getImage
* @return {Image}
*/
Phaser.RenderTexture.prototype.getImage = function () {

    var image = new Image();
    image.src = this.getBase64();

    return image;

};

/**
* Will return a base64 encoded string of this texture. It works by calling RenderTexture.getCanvas and then running toDataURL on that.
*
* @method Phaser.RenderTexture.prototype.getBase64
* @return {String} A base64 encoded string of the texture.
*/
Phaser.RenderTexture.prototype.getBase64 = function () {

    return this.getCanvas().toDataURL();

};

/**
* Creates a Canvas element, renders this RenderTexture to it and then returns it.
*
* @method Phaser.RenderTexture.prototype.getCanvas
* @return {HTMLCanvasElement} A Canvas element with the texture rendered on.
*/
Phaser.RenderTexture.prototype.getCanvas = function () {

    if (this.renderer.type === Phaser.WEBGL)
    {
        var gl = this.renderer.gl;
        var width = this.textureBuffer.width;
        var height = this.textureBuffer.height;

        var webGLPixels = new Uint8Array(4 * width * height);

        gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer);
        gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);

        var tempCanvas = new PIXI.CanvasBuffer(width, height);
        var canvasData = tempCanvas.context.getImageData(0, 0, width, height);
        canvasData.data.set(webGLPixels);

        tempCanvas.context.putImageData(canvasData, 0, 0);

        return tempCanvas.canvas;
    }
    else
    {
        return this.textureBuffer.canvas;
    }

};


this.projection.y = -(this.height / 2) / this.game.resolution;

* If Multi Texture support has been enabled, then calling this method will enable batching on the given

* textures. The texture collection is an array of keys, that map to Phaser.Cache image entries.

* The number of textures that can be batched is dependent on hardware. If you provide more textures

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

/**
* New version of PIXI.StripShader
*
* @class Phaser.Renderer.Canvas
* @constructor
* @param {Phaser.Game} game - Game reference to the currently running game.
*/
Phaser.Renderer.WebGL.Shaders.Strip = function (renderer)
{
    this.renderer = renderer;

    //  WebGLContext
    this.gl = renderer.gl;

    /**
     * @property _UID
     * @type Number
     * @private
     */
    this._UID = Phaser._UID++;

    /**
     * The WebGL program.
     * @property program
     * @type Any
     */
    this.program = null;

    /**
    * The vertex shader.
    * @property vertexSrc
    * @type Array
    */
    this.fragmentSrc = [];

    this.vertexSrc = [];

    this.attributes = [];

    //  @type {WebGLUniformLocation }
    this.uSampler;

    //  @type {WebGLUniformLocation }
    this.projectionVector;

    //  @type {WebGLUniformLocation }
    this.offsetVector;

    //  @type {GLint}
    this.colorAttribute;

    //  @type {GLint}
    this.aTextureIndex;

    //  @type {GLint}
    this.aVertexPosition;

    //  @type {GLint}
    this.aTextureCoord;

    //  @type {WebGLUniformLocation }
    this.translationMatrix;

    //  @type {WebGLUniformLocation }
    this.alpha;

    this.init();
};

Phaser.Renderer.WebGL.Shaders.Strip.prototype.constructor = Phaser.Renderer.WebGL.Shaders.Strip;

Phaser.Renderer.WebGL.Shaders.Strip.prototype = {

    init: function ()
    {
        if (this.renderer.enableMultiTextureToggle)
        {
            var dynamicIfs = '\tif (vTextureIndex == 0.0) gl_FragColor = texture2D(uSamplerArray[0], vTextureCoord);\n'

            for (var index = 1; index < this.renderer.getMaxTextureUnits(); ++index)
            {
                dynamicIfs += '\telse if (vTextureIndex == ' +
                            index + '.0) gl_FragColor = texture2D(uSamplerArray[' +
                            index + '], vTextureCoord) ;\n'
            }

            this.fragmentSrc = [
                'precision mediump float;',
                'varying vec2 vTextureCoord;',
                'varying float vTextureIndex;',
                'uniform float alpha;',
                'uniform sampler2D uSamplerArray[' + this.renderer.getMaxTextureUnits() + '];',
                'const vec4 PINK = vec4(1.0, 0.0, 1.0, 1.0);',
                'const vec4 GREEN = vec4(0.0, 1.0, 0.0, 1.0);',
                'void main(void) {',
                dynamicIfs,
                'else gl_FragColor = PINK;',
                '}'
            ];
        }
        else
        {
            this.fragmentSrc = [
                'precision mediump float;',
                'varying vec2 vTextureCoord;',
                'varying float vTextureIndex;',
                'uniform float alpha;',
                'uniform sampler2D uSampler;',
                'void main(void) {',
                '   gl_FragColor = texture2D(uSampler, vTextureCoord);',
                '}'
            ];
        }

        this.vertexSrc  = [
            'attribute vec2 aVertexPosition;',
            'attribute vec2 aTextureCoord;',
            'attribute float aTextureIndex;',
            'uniform mat3 translationMatrix;',
            'uniform vec2 projectionVector;',
            'uniform vec2 offsetVector;',
            'varying vec2 vTextureCoord;',
            'varying float vTextureIndex;',

            'void main(void) {',
            '   vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);',
            '   v -= offsetVector.xyx;',
            '   gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);',
            '   vTextureCoord = aTextureCoord;',
            '   vTextureIndex = aTextureIndex;',
            '}'
        ];

        var program = this.renderer.compileProgram(this.vertexSrc, this.fragmentSrc);

        var gl = this.gl;

        gl.useProgram(program);

        // get and store the uniforms for the shader
        this.uSampler = (this.renderer.enableMultiTextureToggle) ? gl.getUniformLocation(program, 'uSamplerArray[0]') : gl.getUniformLocation(program, 'uSampler');

        if (this.renderer.enableMultiTextureToggle)
        {
            var indices = [];

            // HACK: we bind an empty texture to avoid WebGL warning spam.
            var tempTexture = gl.createTexture();
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D, tempTexture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, null);

            for (var i = 0; i < this.renderer.getMaxTextureUnits(); ++i)
            {
                gl.activeTexture(gl.TEXTURE0 + i);
                gl.bindTexture(gl.TEXTURE_2D, tempTexture);
                indices.push(i);
            }

            gl.activeTexture(gl.TEXTURE0);
            gl.uniform1iv(this.uSampler, indices);
        }

        this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
        this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
        this.colorAttribute = gl.getAttribLocation(program, 'aColor');
        this.aTextureIndex = gl.getAttribLocation(program, 'aTextureIndex');

        // get and store the attributes
        this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
        this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');

        this.attributes = [this.aVertexPosition, this.aTextureCoord, this.aTextureIndex];

        this.translationMatrix = gl.getUniformLocation(program, 'translationMatrix');
        this.alpha = gl.getUniformLocation(program, 'alpha');

        this.program = program;
    },

    destroy: function ()
    {
        this.gl.deleteProgram(this.program);
        this.gl = null;
        this.renderer = null;
        this.attributes = null;
    }

};