var FacebookInstantGamesPlugin = require('../../plugins/fbinstant/src/FacebookInstantGamesPlugin');

var SoundManagerCreator = require('../sound/SoundManagerCreator');

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

require('./polyfills');

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

/**
 * @namespace Phaser
 */

var Phaser = {

    Actions: require('./actions'),
    Animations: require('./animations'),
    Cache: require('./cache'),
    Cameras: require('./cameras'),
    Core: require('./core'),
    Class: require('./utils/Class'),
    Create: require('./create'),
    Curves: require('./curves'),
    Data: require('./data'),
    Display: require('./display'),
    DOM: require('./dom'),
    Events: require('./events'),
    Game: require('./core/Game'),
    GameObjects: require('./gameobjects'),
    Geom: require('./geom'),
    Input: require('./input'),
    Loader: require('./loader'),
    Math: require('./math'),
    Physics: {
        Arcade: require('./physics/arcade')
    },
    Plugins: require('./plugins'),
    Scale: require('./scale'),
    Scene: require('./scene/Scene'),
    Scenes: require('./scene'),
    Sound: require('./sound'),
    Structs: require('./structs'),
    Textures: require('./textures'),
    Tilemaps: require('./tilemaps'),
    Time: require('./time'),
    Tweens: require('./tweens'),
    Utils: require('./utils')

};

//   Merge in the consts

Phaser = Extend(false, Phaser, CONST);

//  Export it

module.exports = Phaser;

global.Phaser = Phaser;

/*
 * "Documentation is like pizza: when it is good, it is very, very good;
 * and when it is bad, it is better than nothing."
 *  -- Dick Brandon
 */


var TextureManager = require('../textures/TextureManager');

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

keep keep keep add keep keep keep keep keep

/**
 * @typedef {object} Phaser.Cameras.Controls.Types.SmoothedKeyControlConfig
 * @since 3.0.0
 *
 * @property {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera that this Control will update.
 * @property {Phaser.Input.Keyboard.Key} [left] - The Key to be pressed that will move the Camera left.
 * @property {Phaser.Input.Keyboard.Key} [right] - The Key to be pressed that will move the Camera right.
 * @property {Phaser.Input.Keyboard.Key} [up] - The Key to be pressed that will move the Camera up.
 * @property {Phaser.Input.Keyboard.Key} [zoomIn] - The Key to be pressed that will zoom the Camera in.
 * @property {Phaser.Input.Keyboard.Key} [zoomOut] - The Key to be pressed that will zoom the Camera out.
 * @property {number} [zoomSpeed=0.01] - The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
 * @property {(number|{x:number,y:number})} [acceleration=0] - The horizontal and vertical acceleration the camera will move.
 * @property {(number|{x:number,y:number})} [drag=0] - The horizontal and vertical drag applied to the camera when it is moving.
 * @property {(number|{x:number,y:number})} [maxSpeed=0] - The maximum horizontal and vertical speed the camera will move.
 */


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

/**
 * Returns an object containing dimensions of the Text object.
 *
 * @function Phaser.GameObjects.Text.GetTextSize
 * @since 3.0.0
 *
 * @param {Phaser.GameObjects.Text} text - The Text object to calculate the size from.
 * @param {Phaser.GameObjects.Text.Types.TextMetrics} size - The Text metrics to use when calculating the size.
 * @param {array} lines - The lines of text to calculate the size from.
 *
 * @return {object} An object containing dimensions of the Text object.
 */
var GetTextSize = function (text, size, lines)
{
    var canvas = text.canvas;
    var context = text.context;
    var style = text.style;

    var lineWidths = [];
    var maxLineWidth = 0;
    var drawnLines = lines.length;

    if (style.maxLines > 0 && style.maxLines < lines.length)
    {
        drawnLines = style.maxLines;
    }

    style.syncFont(canvas, context);

    //  Text Width

    for (var i = 0; i < drawnLines; i++)
    {
        var lineWidth = style.strokeThickness;

        lineWidth += context.measureText(lines[i]).width;

        // Adjust for wrapped text
        if (style.wordWrap)
        {
            lineWidth -= context.measureText(' ').width;
        }

        lineWidths[i] = Math.ceil(lineWidth);
        maxLineWidth = Math.max(maxLineWidth, lineWidths[i]);
    }

    //  Text Height

    var lineHeight = size.fontSize + style.strokeThickness;
    var height = lineHeight * drawnLines;
    var lineSpacing = text.lineSpacing;

    //  Adjust for line spacing
    if (drawnLines > 1)
    {
        height += lineSpacing * (drawnLines - 1);
    }

    return {
        width: maxLineWidth,
        height: height,
        lines: drawnLines,
        lineWidths: lineWidths,
        lineSpacing: lineSpacing,
        lineHeight: lineHeight
    };
};

module.exports = GetTextSize;


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

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

/**
 * @classdesc
 * A base Phaser.Scene class which you could extend for your own use.
 *
 * @class Scene
 * @memberof Phaser
 * @constructor
 * @since 3.0.0
 *
 * @param {(string|Phaser.Scenes.Types.SettingsConfig)} config - Scene specific configuration settings.
 */
var Scene = new Class({

    initialize:

    function Scene (config)
    {
        /**
         * The Scene Systems. You must never overwrite this property, or all hell will break lose.
         *
         * @name Phaser.Scene#sys
         * @type {Phaser.Scenes.Systems}
         * @since 3.0.0
         */
        this.sys = new Systems(this, config);

        /**
         * A reference to the Phaser.Game instance.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#game
         * @type {Phaser.Game}
         * @since 3.0.0
         */
        this.game;

        /**
         * A reference to the global Animation Manager.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#anims
         * @type {Phaser.Animations.AnimationManager}
         * @since 3.0.0
         */
        this.anims;

        /**
         * A reference to the global Cache.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#cache
         * @type {Phaser.Cache.CacheManager}
         * @since 3.0.0
         */
        this.cache;

        /**
         * A reference to the game level Data Manager.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#registry
         * @type {Phaser.Data.DataManager}
         * @since 3.0.0
         */
        this.registry;

        /**
         * A reference to the Sound Manager.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#sound
         * @type {Phaser.Sound.BaseSoundManager}
         * @since 3.0.0
         */
        this.sound;

        /**
         * A reference to the Texture Manager.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#textures
         * @type {Phaser.Textures.TextureManager}
         * @since 3.0.0
         */
        this.textures;

        /**
         * A scene level Event Emitter.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#events
         * @type {Phaser.Events.EventEmitter}
         * @since 3.0.0
         */
        this.events;

        /**
         * A scene level Camera System.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#cameras
         * @type {Phaser.Cameras.Scene2D.CameraManager}
         * @since 3.0.0
         */
        this.cameras;

        /**
         * A scene level Game Object Factory.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#add
         * @type {Phaser.GameObjects.GameObjectFactory}
         * @since 3.0.0
         */
        this.add;

        /**
         * A scene level Game Object Creator.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#make
         * @type {Phaser.GameObjects.GameObjectCreator}
         * @since 3.0.0
         */
        this.make;

        /**
         * A reference to the Scene Manager Plugin.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#scene
         * @type {Phaser.Scenes.ScenePlugin}
         * @since 3.0.0
         */
        this.scene;

        /**
         * A scene level Game Object Display List.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#children
         * @type {Phaser.GameObjects.DisplayList}
         * @since 3.0.0
         */
        this.children;

        /**
         * A scene level Lights Manager Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#lights
         * @type {Phaser.GameObjects.LightsManager}
         * @since 3.0.0
         */
        this.lights;

        /**
         * A scene level Data Manager Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#data
         * @type {Phaser.Data.DataManager}
         * @since 3.0.0
         */
        this.data;

        /**
         * A scene level Input Manager Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#input
         * @type {Phaser.Input.InputPlugin}
         * @since 3.0.0
         */
        this.input;

        /**
         * A scene level Loader Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#load
         * @type {Phaser.Loader.LoaderPlugin}
         * @since 3.0.0
         */
        this.load;

        /**
         * A scene level Time and Clock Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#time
         * @type {Phaser.Time.Clock}
         * @since 3.0.0
         */
        this.time;

        /**
         * A scene level Tween Manager Plugin.
         * This property will only be available if defined in the Scene Injection Map and the plugin is installed.
         *
         * @name Phaser.Scene#tweens
         * @type {Phaser.Tweens.TweenManager}
         * @since 3.0.0
         */
        this.tweens;

        /**
         * A scene level Arcade Physics Plugin.
         * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured.
         *
         * @name Phaser.Scene#physics
         * @type {Phaser.Physics.Arcade.ArcadePhysics}
         * @since 3.0.0
         */
        this.physics;

        /**
         * A scene level Impact Physics Plugin.
         * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured.
         *
         * @name Phaser.Scene#impact
         * @type {Phaser.Physics.Impact.ImpactPhysics}
         * @since 3.0.0
         */
        this.impact;

        /**
         * A scene level Matter Physics Plugin.
         * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured.
         *
         * @name Phaser.Scene#matter
         * @type {Phaser.Physics.Matter.MatterPhysics}
         * @since 3.0.0
         */
        this.matter;

        if (typeof PLUGIN_FBINSTANT)
        {
            /**
             * A scene level Facebook Instant Games Plugin.
             * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured.
             *
             * @name Phaser.Scene#facebook
             * @type {Phaser.FacebookInstantGamesPlugin}
             * @since 3.12.0
             */
            this.facebook;
        }

        /**
         * A reference to the global Scale Manager.
         * This property will only be available if defined in the Scene Injection Map.
         *
         * @name Phaser.Scene#scale
         * @type {Phaser.Scale.ScaleManager}
         * @since 3.16.2
         */
        this.scale;
    },

    /**
     * Should be overridden by your own Scenes.
     * This method is called once per game step while the scene is running.
     *
     * @method Phaser.Scene#update
     * @since 3.0.0
     *
     * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     */
    update: function ()
    {
    }

    /**
     * Can be defined on your own Scenes.
     * This method is called by the Scene Manager when the scene starts, before `preload()` and `create()`.
     *
     * @method Phaser.Scene#init
     * @since 3.0.0
     *
     * @param {object} data - Any data passed via `ScenePlugin.add()` or `ScenePlugin.start()`. Same as Scene.settings.data.
     */

    /**
     * Can be defined on your own Scenes. Use it to load assets.
     * This method is called by the Scene Manager, after `init()` and before `create()`, only if the Scene has a LoaderPlugin.
     * After this method completes, if the LoaderPlugin's queue isn't empty, the LoaderPlugin will start automatically.
     *
     * @method Phaser.Scene#preload
     * @since 3.0.0
     */

    /**
     * Can be defined on your own Scenes. Use it to create your game objects.
     * This method is called by the Scene Manager when the scene starts, after `init()` and `preload()`.
     * If the LoaderPlugin started after `preload()`, then this method is called only after loading is complete.
     *
     * @method Phaser.Scene#create
     * @since 3.0.0
     *
     * @param {object} data - Any data passed via `ScenePlugin.add()` or `ScenePlugin.start()`. Same as Scene.settings.data.
     */

});

module.exports = Scene;


this.scale = new ScaleManager(this, this.config);

* An instance of the base Sound Manager.

* The Sound Manager is a global system responsible for the playback and updating of all audio in your game.

* The Time Step is a global system responsible for setting-up and responding to the browser frame events, processing

keep keep keep keep replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep


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

/**
 * @namespace Phaser.GameObjects
 */

var GameObjects = {

    Events: require('./events'),

    DisplayList: require('./DisplayList'),
    GameObjectCreator: require('./GameObjectCreator'),
    GameObjectFactory: require('./GameObjectFactory'),
    UpdateList: require('./UpdateList'),

    Components: require('./components'),

    BuildGameObject: require('./BuildGameObject'),
    BuildGameObjectAnimation: require('./BuildGameObjectAnimation'),
    GameObject: require('./GameObject'),
    BitmapText: require('./bitmaptext/static/BitmapText'),
    Blitter: require('./blitter/Blitter'),
    Container: require('./container/Container'),
    DOMElement: require('./domelement/DOMElement'),
    DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapText'),
    Extern: require('./extern/Extern.js'),
    Graphics: require('./graphics/Graphics.js'),
    Group: require('./group/Group'),
    Image: require('./image/Image'),
    Particles: require('./particles'),
    PathFollower: require('./pathfollower/PathFollower'),
    RenderTexture: require('./rendertexture/RenderTexture'),
    RetroFont: require('./bitmaptext/RetroFont'),
    Sprite: require('./sprite/Sprite'),
    Text: require('./text/static/Text'),
    TileSprite: require('./tilesprite/TileSprite'),
    Zone: require('./zone/Zone'),

    //  Shapes

    Shape: require('./shape/Shape'),
    Arc: require('./shape/arc/Arc'),
    Curve: require('./shape/curve/Curve'),
    Ellipse: require('./shape/ellipse/Ellipse'),
    Grid: require('./shape/grid/Grid'),
    IsoBox: require('./shape/isobox/IsoBox'),
    IsoTriangle: require('./shape/isotriangle/IsoTriangle'),
    Line: require('./shape/line/Line'),
    Polygon: require('./shape/polygon/Polygon'),
    Rectangle: require('./shape/rectangle/Rectangle'),
    Star: require('./shape/star/Star'),
    Triangle: require('./shape/triangle/Triangle'),

    //  Game Object Factories

    Factories: {
        Blitter: require('./blitter/BlitterFactory'),
        Container: require('./container/ContainerFactory'),
        DOMElement: require('./domelement/DOMElementFactory'),
        DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextFactory'),
        Extern: require('./extern/ExternFactory'),
        Graphics: require('./graphics/GraphicsFactory'),
        Group: require('./group/GroupFactory'),
        Image: require('./image/ImageFactory'),
        Particles: require('./particles/ParticleManagerFactory'),
        PathFollower: require('./pathfollower/PathFollowerFactory'),
        RenderTexture: require('./rendertexture/RenderTextureFactory'),
        Sprite: require('./sprite/SpriteFactory'),
        StaticBitmapText: require('./bitmaptext/static/BitmapTextFactory'),
        Text: require('./text/static/TextFactory'),
        TileSprite: require('./tilesprite/TileSpriteFactory'),
        Zone: require('./zone/ZoneFactory'),

        //  Shapes
        Arc: require('./shape/arc/ArcFactory'),
        Curve: require('./shape/curve/CurveFactory'),
        Ellipse: require('./shape/ellipse/EllipseFactory'),
        Grid: require('./shape/grid/GridFactory'),
        IsoBox: require('./shape/isobox/IsoBoxFactory'),
        IsoTriangle: require('./shape/isotriangle/IsoTriangleFactory'),
        Line: require('./shape/line/LineFactory'),
        Polygon: require('./shape/polygon/PolygonFactory'),
        Rectangle: require('./shape/rectangle/RectangleFactory'),
        Star: require('./shape/star/StarFactory'),
        Triangle: require('./shape/triangle/TriangleFactory')
    },

    Creators: {
        Blitter: require('./blitter/BlitterCreator'),
        Container: require('./container/ContainerCreator'),
        DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextCreator'),
        Graphics: require('./graphics/GraphicsCreator'),
        Group: require('./group/GroupCreator'),
        Image: require('./image/ImageCreator'),
        Particles: require('./particles/ParticleManagerCreator'),
        RenderTexture: require('./rendertexture/RenderTextureCreator'),
        Sprite: require('./sprite/SpriteCreator'),
        StaticBitmapText: require('./bitmaptext/static/BitmapTextCreator'),
        Text: require('./text/static/TextCreator'),
        TileSprite: require('./tilesprite/TileSpriteCreator'),
        Zone: require('./zone/ZoneCreator')
    }

};

if (typeof WEBGL_RENDERER)
{
    //  WebGL only Game Objects
    GameObjects.Mesh = require('./mesh/Mesh');
    GameObjects.Quad = require('./quad/Quad');

    GameObjects.Factories.Mesh = require('./mesh/MeshFactory');
    GameObjects.Factories.Quad = require('./quad/QuadFactory');

    GameObjects.Creators.Mesh = require('./mesh/MeshCreator');
    GameObjects.Creators.Quad = require('./quad/QuadCreator');

    GameObjects.Light = require('./lights/Light');

    require('./lights/LightsManager');
    require('./lights/LightsPlugin');
}

module.exports = GameObjects;


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

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

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

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

module.exports = {

    renderWebGL: renderWebGL,
    renderCanvas: renderCanvas

};


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

var Clamp = require('../../math/Clamp');

/**
 * [description]
 *
 * @function Phaser.Physics.Impact.GetVelocity
 * @since 3.0.0
 *
 * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
 * @param {number} vel - [description]
 * @param {number} accel - [description]
 * @param {number} friction - [description]
 * @param {number} max - [description]
 *
 * @return {number} [description]
 */
var GetVelocity = function (delta, vel, accel, friction, max)
{
    if (accel)
    {
        return Clamp(vel + accel * delta, -max, max);
    }
    else if (friction)
    {
        var frictionDelta = friction * delta;

        if (vel - frictionDelta > 0)
        {
            return vel - frictionDelta;
        }
        else if (vel + frictionDelta < 0)
        {
            return vel + frictionDelta;
        }
        else
        {
            return 0;
        }
    }

    return Clamp(vel, -max, max);
};

module.exports = GetVelocity;


Plugins: require('./plugins'),
Scale: require('./scale'),
Scene: require('./scene/Scene'),
Scenes: require('./scene'),
Sound: require('./sound'),
Structs: require('./structs'),
Textures: require('./textures'),
Tilemaps: require('./tilemaps'),
Time: require('./time'),

keep keep keep keep replace keep keep keep keep

'use strict';

const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    mode: 'production',

    context: `${__dirname}/src/`,

    entry: {
        phaser: './phaser.js',
        'phaser.min': './phaser.js',
        'phaser-arcade-physics': './phaser-arcade-physics.js',
        'phaser-arcade-physics.min': './phaser-arcade-physics.js'
    },

    output: {
        path: `${__dirname}/dist/`,
        filename: '[name].js',
        library: 'Phaser',
        libraryTarget: 'umd',
        umdNamedDefine: true
    },

    performance: { hints: false },

    optimization: {
        minimizer: [
            new UglifyJSPlugin({
                include: /\.min\.js$/,
                parallel: true,
                sourceMap: false,
                uglifyOptions: {
                    compress: true,
                    ie8: false,
                    ecma: 5,
                    output: {comments: false},
                    warnings: false
                },
                warningsFilter: () => false
            })
        ]
    },

    plugins: [
        new webpack.DefinePlugin({
            "typeof CANVAS_RENDERER": JSON.stringify(true),
            "typeof WEBGL_RENDERER": JSON.stringify(true),
            "typeof EXPERIMENTAL": JSON.stringify(false),
            "typeof PLUGIN_CAMERA3D": JSON.stringify(false),
            "typeof PLUGIN_FBINSTANT": JSON.stringify(false)
        }),

        new CleanWebpackPlugin([ 'dist' ])
    ]
};


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

var quickselect = require('../utils/array/QuickSelect');

/**
 * @classdesc
 * RBush is a high-performance JavaScript library for 2D spatial indexing of points and rectangles.
 * It's based on an optimized R-tree data structure with bulk insertion support.
 *
 * Spatial index is a special data structure for points and rectangles that allows you to perform queries like
 * "all items within this bounding box" very efficiently (e.g. hundreds of times faster than looping over all items).
 *
 * This version of RBush uses a fixed min/max accessor structure of `[ '.left', '.top', '.right', '.bottom' ]`.
 * This is to avoid the eval like function creation that the original library used, which caused CSP policy violations.
 *
 * rbush is forked from https://github.com/mourner/rbush by Vladimir Agafonkin
 *
 * @class RTree
 * @memberof Phaser.Structs
 * @constructor
 * @since 3.0.0
 */

function rbush (maxEntries)
{
    var format = [ '.left', '.top', '.right', '.bottom' ];

    if (!(this instanceof rbush)) return new rbush(maxEntries, format);

    // max entries in a node is 9 by default; min node fill is 40% for best performance
    this._maxEntries = Math.max(4, maxEntries || 9);
    this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));

    this.clear();
}

rbush.prototype = {

    all: function ()
    {
        return this._all(this.data, []);
    },

    search: function (bbox)
    {
        var node = this.data,
            result = [],
            toBBox = this.toBBox;

        if (!intersects(bbox, node)) return result;

        var nodesToSearch = [],
            i, len, child, childBBox;

        while (node) {
            for (i = 0, len = node.children.length; i < len; i++) {

                child = node.children[i];
                childBBox = node.leaf ? toBBox(child) : child;

                if (intersects(bbox, childBBox)) {
                    if (node.leaf) result.push(child);
                    else if (contains(bbox, childBBox)) this._all(child, result);
                    else nodesToSearch.push(child);
                }
            }
            node = nodesToSearch.pop();
        }

        return result;
    },

    collides: function (bbox)
    {
        var node = this.data,
            toBBox = this.toBBox;

        if (!intersects(bbox, node)) return false;

        var nodesToSearch = [],
            i, len, child, childBBox;

        while (node) {
            for (i = 0, len = node.children.length; i < len; i++) {

                child = node.children[i];
                childBBox = node.leaf ? toBBox(child) : child;

                if (intersects(bbox, childBBox)) {
                    if (node.leaf || contains(bbox, childBBox)) return true;
                    nodesToSearch.push(child);
                }
            }
            node = nodesToSearch.pop();
        }

        return false;
    },

    load: function (data)
    {
        if (!(data && data.length)) return this;

        if (data.length < this._minEntries) {
            for (var i = 0, len = data.length; i < len; i++) {
                this.insert(data[i]);
            }
            return this;
        }

        // recursively build the tree with the given data from scratch using OMT algorithm
        var node = this._build(data.slice(), 0, data.length - 1, 0);

        if (!this.data.children.length) {
            // save as is if tree is empty
            this.data = node;

        } else if (this.data.height === node.height) {
            // split root if trees have the same height
            this._splitRoot(this.data, node);

        } else {
            if (this.data.height < node.height) {
                // swap trees if inserted one is bigger
                var tmpNode = this.data;
                this.data = node;
                node = tmpNode;
            }

            // insert the small tree into the large tree at appropriate level
            this._insert(node, this.data.height - node.height - 1, true);
        }

        return this;
    },

    insert: function (item)
    {
        if (item) this._insert(item, this.data.height - 1);
        return this;
    },

    clear: function ()
    {
        this.data = createNode([]);
        return this;
    },

    remove: function (item, equalsFn)
    {
        if (!item) return this;

        var node = this.data,
            bbox = this.toBBox(item),
            path = [],
            indexes = [],
            i, parent, index, goingUp;

        // depth-first iterative tree traversal
        while (node || path.length) {

            if (!node) { // go up
                node = path.pop();
                parent = path[path.length - 1];
                i = indexes.pop();
                goingUp = true;
            }

            if (node.leaf) { // check current node
                index = findItem(item, node.children, equalsFn);

                if (index !== -1) {
                    // item found, remove the item and condense tree upwards
                    node.children.splice(index, 1);
                    path.push(node);
                    this._condense(path);
                    return this;
                }
            }

            if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
                path.push(node);
                indexes.push(i);
                i = 0;
                parent = node;
                node = node.children[0];

            } else if (parent) { // go right
                i++;
                node = parent.children[i];
                goingUp = false;

            } else node = null; // nothing found
        }

        return this;
    },

    toBBox: function (item) { return item; },

    compareMinX: compareNodeMinX,
    compareMinY: compareNodeMinY,

    toJSON: function () { return this.data; },

    fromJSON: function (data)
    {
        this.data = data;
        return this;
    },

    _all: function (node, result)
    {
        var nodesToSearch = [];
        while (node) {
            if (node.leaf) result.push.apply(result, node.children);
            else nodesToSearch.push.apply(nodesToSearch, node.children);

            node = nodesToSearch.pop();
        }
        return result;
    },

    _build: function (items, left, right, height)
    {
        var N = right - left + 1,
            M = this._maxEntries,
            node;

        if (N <= M) {
            // reached leaf level; return leaf
            node = createNode(items.slice(left, right + 1));
            calcBBox(node, this.toBBox);
            return node;
        }

        if (!height) {
            // target height of the bulk-loaded tree
            height = Math.ceil(Math.log(N) / Math.log(M));

            // target number of root entries to maximize storage utilization
            M = Math.ceil(N / Math.pow(M, height - 1));
        }

        node = createNode([]);
        node.leaf = false;
        node.height = height;

        // split the items into M mostly square tiles

        var N2 = Math.ceil(N / M),
            N1 = N2 * Math.ceil(Math.sqrt(M)),
            i, j, right2, right3;

        multiSelect(items, left, right, N1, this.compareMinX);

        for (i = left; i <= right; i += N1) {

            right2 = Math.min(i + N1 - 1, right);

            multiSelect(items, i, right2, N2, this.compareMinY);

            for (j = i; j <= right2; j += N2) {

                right3 = Math.min(j + N2 - 1, right2);

                // pack each entry recursively
                node.children.push(this._build(items, j, right3, height - 1));
            }
        }

        calcBBox(node, this.toBBox);

        return node;
    },

    _chooseSubtree: function (bbox, node, level, path)
    {
        var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;

        while (true) {
            path.push(node);

            if (node.leaf || path.length - 1 === level) break;

            minArea = minEnlargement = Infinity;

            for (i = 0, len = node.children.length; i < len; i++) {
                child = node.children[i];
                area = bboxArea(child);
                enlargement = enlargedArea(bbox, child) - area;

                // choose entry with the least area enlargement
                if (enlargement < minEnlargement) {
                    minEnlargement = enlargement;
                    minArea = area < minArea ? area : minArea;
                    targetNode = child;

                } else if (enlargement === minEnlargement) {
                    // otherwise choose one with the smallest area
                    if (area < minArea) {
                        minArea = area;
                        targetNode = child;
                    }
                }
            }

            node = targetNode || node.children[0];
        }

        return node;
    },

    _insert: function (item, level, isNode)
    {
        var toBBox = this.toBBox,
            bbox = isNode ? item : toBBox(item),
            insertPath = [];

        // find the best node for accommodating the item, saving all nodes along the path too
        var node = this._chooseSubtree(bbox, this.data, level, insertPath);

        // put the item into the node
        node.children.push(item);
        extend(node, bbox);

        // split on node overflow; propagate upwards if necessary
        while (level >= 0) {
            if (insertPath[level].children.length > this._maxEntries) {
                this._split(insertPath, level);
                level--;
            } else break;
        }

        // adjust bboxes along the insertion path
        this._adjustParentBBoxes(bbox, insertPath, level);
    },

    // split overflowed node into two
    _split: function (insertPath, level)
    {
        var node = insertPath[level],
            M = node.children.length,
            m = this._minEntries;

        this._chooseSplitAxis(node, m, M);

        var splitIndex = this._chooseSplitIndex(node, m, M);

        var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
        newNode.height = node.height;
        newNode.leaf = node.leaf;

        calcBBox(node, this.toBBox);
        calcBBox(newNode, this.toBBox);

        if (level) insertPath[level - 1].children.push(newNode);
        else this._splitRoot(node, newNode);
    },

    _splitRoot: function (node, newNode)
    {
        // split root node
        this.data = createNode([node, newNode]);
        this.data.height = node.height + 1;
        this.data.leaf = false;
        calcBBox(this.data, this.toBBox);
    },

    _chooseSplitIndex: function (node, m, M)
    {
        var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;

        minOverlap = minArea = Infinity;

        for (i = m; i <= M - m; i++) {
            bbox1 = distBBox(node, 0, i, this.toBBox);
            bbox2 = distBBox(node, i, M, this.toBBox);

            overlap = intersectionArea(bbox1, bbox2);
            area = bboxArea(bbox1) + bboxArea(bbox2);

            // choose distribution with minimum overlap
            if (overlap < minOverlap) {
                minOverlap = overlap;
                index = i;

                minArea = area < minArea ? area : minArea;

            } else if (overlap === minOverlap) {
                // otherwise choose distribution with minimum area
                if (area < minArea) {
                    minArea = area;
                    index = i;
                }
            }
        }

        return index;
    },

    // sorts node children by the best axis for split
    _chooseSplitAxis: function (node, m, M)
    {
        var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
            compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
            xMargin = this._allDistMargin(node, m, M, compareMinX),
            yMargin = this._allDistMargin(node, m, M, compareMinY);

        // if total distributions margin value is minimal for x, sort by minX,
        // otherwise it's already sorted by minY
        if (xMargin < yMargin) node.children.sort(compareMinX);
    },

    // total margin of all possible split distributions where each node is at least m full
    _allDistMargin: function (node, m, M, compare)
    {
        node.children.sort(compare);

        var toBBox = this.toBBox,
            leftBBox = distBBox(node, 0, m, toBBox),
            rightBBox = distBBox(node, M - m, M, toBBox),
            margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
            i, child;

        for (i = m; i < M - m; i++) {
            child = node.children[i];
            extend(leftBBox, node.leaf ? toBBox(child) : child);
            margin += bboxMargin(leftBBox);
        }

        for (i = M - m - 1; i >= m; i--) {
            child = node.children[i];
            extend(rightBBox, node.leaf ? toBBox(child) : child);
            margin += bboxMargin(rightBBox);
        }

        return margin;
    },

    _adjustParentBBoxes: function (bbox, path, level)
    {
        // adjust bboxes along the given tree path
        for (var i = level; i >= 0; i--) {
            extend(path[i], bbox);
        }
    },

    _condense: function (path)
    {
        // go through the path, removing empty nodes and updating bboxes
        for (var i = path.length - 1, siblings; i >= 0; i--) {
            if (path[i].children.length === 0) {
                if (i > 0) {
                    siblings = path[i - 1].children;
                    siblings.splice(siblings.indexOf(path[i]), 1);

                } else this.clear();

            } else calcBBox(path[i], this.toBBox);
        }
    },

    compareMinX: function (a, b)
    {
        return a.left - b.left;
    },

    compareMinY: function (a, b)
    {
        return a.top - b.top;
    },

    toBBox: function (a)
    {
        return {
            minX: a.left,
            minY: a.top,
            maxX: a.right,
            maxY: a.bottom
        };
    }
};

function findItem (item, items, equalsFn)
{
    if (!equalsFn) return items.indexOf(item);

    for (var i = 0; i < items.length; i++) {
        if (equalsFn(item, items[i])) return i;
    }
    return -1;
}

// calculate node's bbox from bboxes of its children
function calcBBox (node, toBBox)
{
    distBBox(node, 0, node.children.length, toBBox, node);
}

// min bounding rectangle of node children from k to p-1
function distBBox (node, k, p, toBBox, destNode)
{
    if (!destNode) destNode = createNode(null);
    destNode.minX = Infinity;
    destNode.minY = Infinity;
    destNode.maxX = -Infinity;
    destNode.maxY = -Infinity;

    for (var i = k, child; i < p; i++) {
        child = node.children[i];
        extend(destNode, node.leaf ? toBBox(child) : child);
    }

    return destNode;
}

function extend (a, b)
{
    a.minX = Math.min(a.minX, b.minX);
    a.minY = Math.min(a.minY, b.minY);
    a.maxX = Math.max(a.maxX, b.maxX);
    a.maxY = Math.max(a.maxY, b.maxY);
    return a;
}

function compareNodeMinX (a, b) { return a.minX - b.minX; }
function compareNodeMinY (a, b) { return a.minY - b.minY; }

function bboxArea (a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
function bboxMargin (a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }

function enlargedArea (a, b)
{
    return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
           (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
}

function intersectionArea (a, b)
{
    var minX = Math.max(a.minX, b.minX),
        minY = Math.max(a.minY, b.minY),
        maxX = Math.min(a.maxX, b.maxX),
        maxY = Math.min(a.maxY, b.maxY);

    return Math.max(0, maxX - minX) *
           Math.max(0, maxY - minY);
}

function contains (a, b)
{
    return a.minX <= b.minX &&
           a.minY <= b.minY &&
           b.maxX <= a.maxX &&
           b.maxY <= a.maxY;
}

function intersects (a, b)
{
    return b.minX <= a.maxX &&
           b.minY <= a.maxY &&
           b.maxX >= a.minX &&
           b.maxY >= a.minY;
}

function createNode (children)
{
    return {
        children: children,
        height: 1,
        leaf: true,
        minX: Infinity,
        minY: Infinity,
        maxX: -Infinity,
        maxY: -Infinity
    };
}

// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
// combines selection algorithm with binary divide & conquer approach

function multiSelect (arr, left, right, n, compare)
{
    var stack = [left, right],
        mid;

    while (stack.length)
    {
        right = stack.pop();
        left = stack.pop();

        if (right - left <= n) continue;

        mid = left + Math.ceil((right - left) / n / 2) * n;
        quickselect(arr, mid, left, right, compare);

        stack.push(left, mid, mid, right);
    }
}

module.exports = rbush;


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

var Class = require('../../utils/Class');
var Components = require('../components');
var GameObject = require('../GameObject');
var SpriteRender = require('./SpriteRender');

/**
 * @classdesc
 * A Sprite Game Object.
 *
 * A Sprite Game Object is used for the display of both static and animated images in your game.
 * Sprites can have input events and physics bodies. They can also be tweened, tinted, scrolled
 * and animated.
 *
 * The main difference between a Sprite and an Image Game Object is that you cannot animate Images.
 * As such, Sprites take a fraction longer to process and have a larger API footprint due to the Animation
 * Component. If you do not require animation then you can safely use Images to replace Sprites in all cases.
 *
 * @class Sprite
 * @extends Phaser.GameObjects.GameObject
 * @memberof Phaser.GameObjects
 * @constructor
 * @since 3.0.0
 *
 * @extends Phaser.GameObjects.Components.Alpha
 * @extends Phaser.GameObjects.Components.BlendMode
 * @extends Phaser.GameObjects.Components.Depth
 * @extends Phaser.GameObjects.Components.Flip
 * @extends Phaser.GameObjects.Components.GetBounds
 * @extends Phaser.GameObjects.Components.Mask
 * @extends Phaser.GameObjects.Components.Origin
 * @extends Phaser.GameObjects.Components.Pipeline
 * @extends Phaser.GameObjects.Components.ScrollFactor
 * @extends Phaser.GameObjects.Components.Size
 * @extends Phaser.GameObjects.Components.TextureCrop
 * @extends Phaser.GameObjects.Components.Tint
 * @extends Phaser.GameObjects.Components.Transform
 * @extends Phaser.GameObjects.Components.Visible
 *
 * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
 * @param {number} x - The horizontal position of this Game Object in the world.
 * @param {number} y - The vertical position of this Game Object in the world.
 * @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
 * @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
 */
var Sprite = new Class({

    Extends: GameObject,

    Mixins: [
        Components.Alpha,
        Components.BlendMode,
        Components.Depth,
        Components.Flip,
        Components.GetBounds,
        Components.Mask,
        Components.Origin,
        Components.Pipeline,
        Components.ScrollFactor,
        Components.Size,
        Components.TextureCrop,
        Components.Tint,
        Components.Transform,
        Components.Visible,
        SpriteRender
    ],

    initialize:

    function Sprite (scene, x, y, texture, frame)
    {
        GameObject.call(this, scene, 'Sprite');

        /**
         * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method.
         *
         * @name Phaser.GameObjects.Sprite#_crop
         * @type {object}
         * @private
         * @since 3.11.0
         */
        this._crop = this.resetCropObject();

        /**
         * The Animation Controller of this Sprite.
         *
         * @name Phaser.GameObjects.Sprite#anims
         * @type {Phaser.GameObjects.Components.Animation}
         * @since 3.0.0
         */
        this.anims = new Components.Animation(this);

        this.setTexture(texture, frame);
        this.setPosition(x, y);
        this.setSizeToFrame();
        this.setOriginFromFrame();
        this.initPipeline();
    },

    /**
     * Update this Sprite's animations.
     *
     * @method Phaser.GameObjects.Sprite#preUpdate
     * @protected
     * @since 3.0.0
     *
     * @param {number} time - The current timestamp.
     * @param {number} delta - The delta time, in ms, elapsed since the last frame.
     */
    preUpdate: function (time, delta)
    {
        this.anims.update(time, delta);
    },

    /**
     * Start playing the given animation.
     *
     * @method Phaser.GameObjects.Sprite#play
     * @since 3.0.0
     *
     * @param {string} key - The string-based key of the animation to play.
     * @param {boolean} [ignoreIfPlaying=false] - If an animation is already playing then ignore this call.
     * @param {integer} [startFrame=0] - Optionally start the animation playing from this frame index.
     *
     * @return {Phaser.GameObjects.Sprite} This Game Object.
     */
    play: function (key, ignoreIfPlaying, startFrame)
    {
        this.anims.play(key, ignoreIfPlaying, startFrame);

        return this;
    },

    /**
     * Build a JSON representation of this Sprite.
     *
     * @method Phaser.GameObjects.Sprite#toJSON
     * @since 3.0.0
     *
     * @return {Phaser.GameObjects.Types.JSONGameObject} A JSON representation of the Game Object.
     */
    toJSON: function ()
    {
        var data = Components.ToJSON(this);

        //  Extra Sprite data is added here

        return data;
    },

    /**
     * Handles the pre-destroy step for the Sprite, which removes the Animation component.
     *
     * @method Phaser.GameObjects.Sprite#preDestroy
     * @private
     * @since 3.14.0
     */
    preDestroy: function ()
    {
        this.anims.destroy();

        this.anims = undefined;
    }

});

module.exports = Sprite;


Phaser = Extend(false, Phaser, CONST);
//  Export it
module.exports = Phaser;

if (typeof FEATURE_SOUND)
{
Phaser.Sound = require('./sound');
}

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

var AddToDOM = require('../dom/AddToDOM');
var AnimationManager = require('../animations/AnimationManager');
var CacheManager = require('../cache/CacheManager');
var CanvasPool = require('../display/canvas/CanvasPool');
var Class = require('../utils/Class');
var Config = require('./Config');
var CreateDOMContainer = require('../dom/CreateDOMContainer');
var CreateRenderer = require('./CreateRenderer');
var DataManager = require('../data/DataManager');
var DebugHeader = require('./DebugHeader');
var Device = require('../device');
var DOMContentLoaded = require('../dom/DOMContentLoaded');
var EventEmitter = require('eventemitter3');
var Events = require('./events');
var InputManager = require('../input/InputManager');
var PluginCache = require('../plugins/PluginCache');
var PluginManager = require('../plugins/PluginManager');
var ScaleManager = require('../scale/ScaleManager');
var SceneManager = require('../scene/SceneManager');
var SoundManagerCreator = require('../sound/SoundManagerCreator');
var TextureEvents = require('../textures/events');
var TextureManager = require('../textures/TextureManager');
var TimeStep = require('./TimeStep');
var VisibilityHandler = require('./VisibilityHandler');

if (typeof PLUGIN_FBINSTANT)
{
    var FacebookInstantGamesPlugin = require('../../plugins/fbinstant/src/FacebookInstantGamesPlugin');
}

/**
 * @classdesc
 * The Phaser.Game instance is the main controller for the entire Phaser game. It is responsible
 * for handling the boot process, parsing the configuration values, creating the renderer,
 * and setting-up all of the global Phaser systems, such as sound and input.
 * Once that is complete it will start the Scene Manager and then begin the main game loop.
 *
 * You should generally avoid accessing any of the systems created by Game, and instead use those
 * made available to you via the Phaser.Scene Systems class instead.
 *
 * @class Game
 * @memberof Phaser
 * @constructor
 * @fires Phaser.Core.Events#BLUR
 * @fires Phaser.Core.Events#FOCUS
 * @fires Phaser.Core.Events#HIDDEN
 * @fires Phaser.Core.Events#VISIBLE
 * @since 3.0.0
 *
 * @param {Phaser.Core.Types.GameConfig} [GameConfig] - The configuration object for your Phaser Game instance.
 */
var Game = new Class({

    initialize:

    function Game (config)
    {
        /**
         * The parsed Game Configuration object.
         *
         * The values stored within this object are read-only and should not be changed at run-time.
         *
         * @name Phaser.Game#config
         * @type {Phaser.Core.Config}
         * @readonly
         * @since 3.0.0
         */
        this.config = new Config(config);

        /**
         * A reference to either the Canvas or WebGL Renderer that this Game is using.
         *
         * @name Phaser.Game#renderer
         * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)}
         * @since 3.0.0
         */
        this.renderer = null;

        /**
         * A reference to an HTML Div Element used as the DOM Element Container.
         *
         * Only set if `createDOMContainer` is `true` in the game config (by default it is `false`) and
         * if you provide a parent element to insert the Phaser Game inside.
         *
         * See the DOM Element Game Object for more details.
         *
         * @name Phaser.Game#domContainer
         * @type {HTMLDivElement}
         * @since 3.17.0
         */
        this.domContainer = null;

        /**
         * A reference to the HTML Canvas Element that Phaser uses to render the game.
         * This is created automatically by Phaser unless you provide a `canvas` property
         * in your Game Config.
         *
         * @name Phaser.Game#canvas
         * @type {HTMLCanvasElement}
         * @since 3.0.0
         */
        this.canvas = null;

        /**
         * A reference to the Rendering Context belonging to the Canvas Element this game is rendering to.
         * If the game is running under Canvas it will be a 2d Canvas Rendering Context.
         * If the game is running under WebGL it will be a WebGL Rendering Context.
         * This context is created automatically by Phaser unless you provide a `context` property
         * in your Game Config.
         *
         * @name Phaser.Game#context
         * @type {(CanvasRenderingContext2D|WebGLRenderingContext)}
         * @since 3.0.0
         */
        this.context = null;

        /**
         * A flag indicating when this Game instance has finished its boot process.
         *
         * @name Phaser.Game#isBooted
         * @type {boolean}
         * @readonly
         * @since 3.0.0
         */
        this.isBooted = false;

        /**
         * A flag indicating if this Game is currently running its game step or not.
         *
         * @name Phaser.Game#isRunning
         * @type {boolean}
         * @readonly
         * @since 3.0.0
         */
        this.isRunning = false;

        /**
         * An Event Emitter which is used to broadcast game-level events from the global systems.
         *
         * @name Phaser.Game#events
         * @type {Phaser.Events.EventEmitter}
         * @since 3.0.0
         */
        this.events = new EventEmitter();

        /**
         * An instance of the Animation Manager.
         *
         * The Animation Manager is a global system responsible for managing all animations used within your game.
         *
         * @name Phaser.Game#anims
         * @type {Phaser.Animations.AnimationManager}
         * @since 3.0.0
         */
        this.anims = new AnimationManager(this);

        /**
         * An instance of the Texture Manager.
         *
         * The Texture Manager is a global system responsible for managing all textures being used by your game.
         *
         * @name Phaser.Game#textures
         * @type {Phaser.Textures.TextureManager}
         * @since 3.0.0
         */
        this.textures = new TextureManager(this);

        /**
         * An instance of the Cache Manager.
         *
         * The Cache Manager is a global system responsible for caching, accessing and releasing external game assets.
         *
         * @name Phaser.Game#cache
         * @type {Phaser.Cache.CacheManager}
         * @since 3.0.0
         */
        this.cache = new CacheManager(this);

        /**
         * An instance of the Data Manager
         *
         * @name Phaser.Game#registry
         * @type {Phaser.Data.DataManager}
         * @since 3.0.0
         */
        this.registry = new DataManager(this);

        /**
         * An instance of the Input Manager.
         *
         * The Input Manager is a global system responsible for the capture of browser-level input events.
         *
         * @name Phaser.Game#input
         * @type {Phaser.Input.InputManager}
         * @since 3.0.0
         */
        this.input = new InputManager(this, this.config);

        /**
         * An instance of the Scene Manager.
         *
         * The Scene Manager is a global system responsible for creating, modifying and updating the Scenes in your game.
         *
         * @name Phaser.Game#scene
         * @type {Phaser.Scenes.SceneManager}
         * @since 3.0.0
         */
        this.scene = new SceneManager(this, this.config.sceneConfig);

        /**
         * A reference to the Device inspector.
         *
         * Contains information about the device running this game, such as OS, browser vendor and feature support.
         * Used by various systems to determine capabilities and code paths.
         *
         * @name Phaser.Game#device
         * @type {Phaser.DeviceConf}
         * @since 3.0.0
         */
        this.device = Device;

        /**
         * An instance of the Scale Manager.
         *
         * The Scale Manager is a global system responsible for handling scaling of the game canvas.
         *
         * @name Phaser.Game#scale
         * @type {Phaser.Scale.ScaleManager}
         * @since 3.16.0
         */
        this.scale = new ScaleManager(this, this.config);

        /**
         * An instance of the base Sound Manager.
         *
         * The Sound Manager is a global system responsible for the playback and updating of all audio in your game.
         *
         * @name Phaser.Game#sound
         * @type {Phaser.Sound.BaseSoundManager}
         * @since 3.0.0
         */
        this.sound = SoundManagerCreator.create(this);

        /**
         * An instance of the Time Step.
         *
         * The Time Step is a global system responsible for setting-up and responding to the browser frame events, processing
         * them and calculating delta values. It then automatically calls the game step.
         *
         * @name Phaser.Game#loop
         * @type {Phaser.Core.TimeStep}
         * @since 3.0.0
         */
        this.loop = new TimeStep(this, this.config.fps);

        /**
         * An instance of the Plugin Manager.
         *
         * The Plugin Manager is a global system that allows plugins to register themselves with it, and can then install
         * those plugins into Scenes as required.
         *
         * @name Phaser.Game#plugins
         * @type {Phaser.Plugins.PluginManager}
         * @since 3.0.0
         */
        this.plugins = new PluginManager(this, this.config);

        if (typeof PLUGIN_FBINSTANT)
        {
            /**
             * An instance of the Facebook Instant Games Plugin.
             *
             * This will only be available if the plugin has been built into Phaser,
             * or you're using the special Facebook Instant Games custom build.
             *
             * @name Phaser.Game#facebook
             * @type {Phaser.FacebookInstantGamesPlugin}
             * @since 3.13.0
             */
            this.facebook = new FacebookInstantGamesPlugin(this);
        }

        /**
         * Is this Game pending destruction at the start of the next frame?
         *
         * @name Phaser.Game#pendingDestroy
         * @type {boolean}
         * @private
         * @since 3.5.0
         */
        this.pendingDestroy = false;

        /**
         * Remove the Canvas once the destroy is over?
         *
         * @name Phaser.Game#removeCanvas
         * @type {boolean}
         * @private
         * @since 3.5.0
         */
        this.removeCanvas = false;

        /**
         * Remove everything when the game is destroyed.
         * You cannot create a new Phaser instance on the same web page after doing this.
         *
         * @name Phaser.Game#noReturn
         * @type {boolean}
         * @private
         * @since 3.12.0
         */
        this.noReturn = false;

        /**
         * Does the window the game is running in currently have focus or not?
         * This is modified by the VisibilityHandler.
         *
         * @name Phaser.Game#hasFocus
         * @type {boolean}
         * @readonly
         * @since 3.9.0
         */
        this.hasFocus = false;

        //  Wait for the DOM Ready event, then call boot.
        DOMContentLoaded(this.boot.bind(this));
    },

    /**
     * This method is called automatically when the DOM is ready. It is responsible for creating the renderer,
     * displaying the Debug Header, adding the game canvas to the DOM and emitting the 'boot' event.
     * It listens for a 'ready' event from the base systems and once received it will call `Game.start`.
     *
     * @method Phaser.Game#boot
     * @protected
     * @fires Phaser.Core.Events#BOOT
     * @listens Phaser.Textures.Events#READY
     * @since 3.0.0
     */
    boot: function ()
    {
        if (!PluginCache.hasCore('EventEmitter'))
        {
            console.warn('Aborting. Core Plugins missing.');
            return;
        }

        this.isBooted = true;

        this.config.preBoot(this);

        this.scale.preBoot();

        CreateRenderer(this);

        CreateDOMContainer(this);

        DebugHeader(this);

        AddToDOM(this.canvas, this.config.parent);

        //  The Texture Manager has to wait on a couple of non-blocking events before it's fully ready.
        //  So it will emit this internal event when done:
        this.textures.once(TextureEvents.READY, this.texturesReady, this);

        this.events.emit(Events.BOOT);
    },

    /**
     * Called automatically when the Texture Manager has finished setting up and preparing the
     * default textures.
     *
     * @method Phaser.Game#texturesReady
     * @private
     * @fires Phaser.Game#ready
     * @since 3.12.0
     */
    texturesReady: function ()
    {
        //  Start all the other systems
        this.events.emit(Events.READY);

        this.start();
    },

    /**
     * Called automatically by Game.boot once all of the global systems have finished setting themselves up.
     * By this point the Game is now ready to start the main loop running.
     * It will also enable the Visibility Handler.
     *
     * @method Phaser.Game#start
     * @protected
     * @since 3.0.0
     */
    start: function ()
    {
        this.isRunning = true;

        this.config.postBoot(this);

        if (this.renderer)
        {
            this.loop.start(this.step.bind(this));
        }
        else
        {
            this.loop.start(this.headlessStep.bind(this));
        }

        VisibilityHandler(this);

        var eventEmitter = this.events;

        eventEmitter.on(Events.HIDDEN, this.onHidden, this);
        eventEmitter.on(Events.VISIBLE, this.onVisible, this);
        eventEmitter.on(Events.BLUR, this.onBlur, this);
        eventEmitter.on(Events.FOCUS, this.onFocus, this);
    },

    /**
     * The main Game Step. Called automatically by the Time Step, once per browser frame (typically as a result of
     * Request Animation Frame, or Set Timeout on very old browsers.)
     *
     * The step will update the global managers first, then proceed to update each Scene in turn, via the Scene Manager.
     *
     * It will then render each Scene in turn, via the Renderer. This process emits `prerender` and `postrender` events.
     *
     * @method Phaser.Game#step
     * @fires Phaser.Core.Events#PRE_STEP_EVENT
     * @fires Phaser.Core.Events#STEP_EVENT
     * @fires Phaser.Core.Events#POST_STEP_EVENT
     * @fires Phaser.Core.Events#PRE_RENDER_EVENT
     * @fires Phaser.Core.Events#POST_RENDER_EVENT
     * @since 3.0.0
     *
     * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     */
    step: function (time, delta)
    {
        if (this.pendingDestroy)
        {
            return this.runDestroy();
        }

        var eventEmitter = this.events;

        //  Global Managers like Input and Sound update in the prestep

        eventEmitter.emit(Events.PRE_STEP, time, delta);

        //  This is mostly meant for user-land code and plugins

        eventEmitter.emit(Events.STEP, time, delta);

        //  Update the Scene Manager and all active Scenes

        this.scene.update(time, delta);

        //  Our final event before rendering starts

        eventEmitter.emit(Events.POST_STEP, time, delta);

        var renderer = this.renderer;

        //  Run the Pre-render (clearing the canvas, setting background colors, etc)

        renderer.preRender();

        eventEmitter.emit(Events.PRE_RENDER, renderer, time, delta);

        //  The main render loop. Iterates all Scenes and all Cameras in those scenes, rendering to the renderer instance.

        this.scene.render(renderer);

        //  The Post-Render call. Tidies up loose end, takes snapshots, etc.

        renderer.postRender();

        //  The final event before the step repeats. Your last chance to do anything to the canvas before it all starts again.

        eventEmitter.emit(Events.POST_RENDER, renderer, time, delta);
    },

    /**
     * A special version of the Game Step for the HEADLESS renderer only.
     *
     * The main Game Step. Called automatically by the Time Step, once per browser frame (typically as a result of
     * Request Animation Frame, or Set Timeout on very old browsers.)
     *
     * The step will update the global managers first, then proceed to update each Scene in turn, via the Scene Manager.
     *
     * This process emits `prerender` and `postrender` events, even though nothing actually displays.
     *
     * @method Phaser.Game#headlessStep
     * @fires Phaser.Game#prerenderEvent
     * @fires Phaser.Game#postrenderEvent
     * @since 3.2.0
     *
     * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
     * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
     */
    headlessStep: function (time, delta)
    {
        var eventEmitter = this.events;

        //  Global Managers

        eventEmitter.emit(Events.PRE_STEP, time, delta);

        eventEmitter.emit(Events.STEP, time, delta);

        //  Scenes

        this.scene.update(time, delta);

        eventEmitter.emit(Events.POST_STEP, time, delta);

        //  Render

        eventEmitter.emit(Events.PRE_RENDER);

        eventEmitter.emit(Events.POST_RENDER);
    },

    /**
     * Called automatically by the Visibility Handler.
     * This will pause the main loop and then emit a pause event.
     *
     * @method Phaser.Game#onHidden
     * @protected
     * @fires Phaser.Core.Events#PAUSE
     * @since 3.0.0
     */
    onHidden: function ()
    {
        this.loop.pause();

        this.events.emit(Events.PAUSE);
    },

    /**
     * Called automatically by the Visibility Handler.
     * This will resume the main loop and then emit a resume event.
     *
     * @method Phaser.Game#onVisible
     * @protected
     * @fires Phaser.Core.Events#RESUME
     * @since 3.0.0
     */
    onVisible: function ()
    {
        this.loop.resume();

        this.events.emit(Events.RESUME);
    },

    /**
     * Called automatically by the Visibility Handler.
     * This will set the main loop into a 'blurred' state, which pauses it.
     *
     * @method Phaser.Game#onBlur
     * @protected
     * @since 3.0.0
     */
    onBlur: function ()
    {
        this.hasFocus = false;

        this.loop.blur();
    },

    /**
     * Called automatically by the Visibility Handler.
     * This will set the main loop into a 'focused' state, which resumes it.
     *
     * @method Phaser.Game#onFocus
     * @protected
     * @since 3.0.0
     */
    onFocus: function ()
    {
        this.hasFocus = true;

        this.loop.focus();
    },

    /**
     * Returns the current game frame.
     * When the game starts running, the frame is incremented every time Request Animation Frame, or Set Timeout, fires.
     *
     * @method Phaser.Game#getFrame
     * @since 3.16.0
     *
     * @return {number} The current game frame.
     */
    getFrame: function ()
    {
        return this.loop.frame;
    },

    /**
     * Returns the current game timestamp.
     * When the game starts running, the frame is incremented every time Request Animation Frame, or Set Timeout, fires.
     *
     * @method Phaser.Game#getTime
     * @since 3.16.0
     *
     * @return {number} The current game timestamp.
     */
    getTime: function ()
    {
        return this.loop.frame.time;
    },

    /**
     * Flags this Game instance as needing to be destroyed on the next frame.
     * It will wait until the current frame has completed and then call `runDestroy` internally.
     *
     * If you **do not** need to run Phaser again on the same web page you can set the `noReturn` argument to `true` and it will free-up
     * memory being held by the core Phaser plugins. If you do need to create another game instance on the same page, leave this as `false`.
     *
     * @method Phaser.Game#destroy
     * @fires Phaser.Core.Events#DESTROY
     * @since 3.0.0
     *
     * @param {boolean} removeCanvas - Set to `true` if you would like the parent canvas element removed from the DOM, or `false` to leave it in place.
     * @param {boolean} [noReturn=false] - If `true` all the core Phaser plugins are destroyed. You cannot create another instance of Phaser on the same web page if you do this.
     */
    destroy: function (removeCanvas, noReturn)
    {
        if (noReturn === undefined) { noReturn = false; }

        this.pendingDestroy = true;

        this.removeCanvas = removeCanvas;
        this.noReturn = noReturn;
    },

    /**
     * Destroys this Phaser.Game instance, all global systems, all sub-systems and all Scenes.
     *
     * @method Phaser.Game#runDestroy
     * @private
     * @since 3.5.0
     */
    runDestroy: function ()
    {
        this.events.emit(Events.DESTROY);

        this.events.removeAllListeners();

        this.scene.destroy();

        if (this.renderer)
        {
            this.renderer.destroy();
        }

        if (this.removeCanvas && this.canvas)
        {
            CanvasPool.remove(this.canvas);

            if (this.canvas.parentNode)
            {
                this.canvas.parentNode.removeChild(this.canvas);
            }
        }

        if (this.domContainer)
        {
            this.domContainer.parentNode.removeChild(this.domContainer);
        }

        this.loop.destroy();

        this.pendingDestroy = false;
    }

});

module.exports = Game;

/**
 * "Computers are good at following instructions, but not at reading your mind." - Donald Knuth
 */


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

/**
 * @namespace Phaser.Display.Masks
 */

module.exports = {

    BitmapMask: require('./BitmapMask'),
    GeometryMask: require('./GeometryMask')

};


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

/**
 * @namespace Phaser.Math.Easing
 */

module.exports = {

    Back: require('./back'),
    Bounce: require('./bounce'),
    Circular: require('./circular'),
    Cubic: require('./cubic'),
    Elastic: require('./elastic'),
    Expo: require('./expo'),
    Linear: require('./linear'),
    Quadratic: require('./quadratic'),
    Quartic: require('./quartic'),
    Quintic: require('./quintic'),
    Sine: require('./sine'),
    Stepped: require('./stepped')

};


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

var Bodies = require('./lib/factory/Bodies');
var Class = require('../../utils/Class');
var Composites = require('./lib/factory/Composites');
var Constraint = require('./lib/constraint/Constraint');
var MatterGameObject = require('./MatterGameObject');
var MatterImage = require('./MatterImage');
var MatterSprite = require('./MatterSprite');
var MatterTileBody = require('./MatterTileBody');
var PointerConstraint = require('./PointerConstraint');

/**
 * @classdesc
 * The Matter Factory can create different types of bodies and them to a physics world.
 *
 * @class Factory
 * @memberof Phaser.Physics.Matter
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Physics.Matter.World} world - The Matter World which this Factory adds to.
 */
var Factory = new Class({

    initialize:

    function Factory (world)
    {
        /**
         * The Matter World which this Factory adds to.
         *
         * @name Phaser.Physics.Matter.Factory#world
         * @type {Phaser.Physics.Matter.World}
         * @since 3.0.0
         */
        this.world = world;

        /**
         * The Scene which this Factory's Matter World belongs to.
         *
         * @name Phaser.Physics.Matter.Factory#scene
         * @type {Phaser.Scene}
         * @since 3.0.0
         */
        this.scene = world.scene;

        /**
         * A reference to the Scene.Systems this Matter Physics instance belongs to.
         *
         * @name Phaser.Physics.Matter.Factory#sys
         * @type {Phaser.Scenes.Systems}
         * @since 3.0.0
         */
        this.sys = world.scene.sys;
    },

    /**
     * Creates a new rigid rectangular Body and adds it to the World.
     *
     * @method Phaser.Physics.Matter.Factory#rectangle
     * @since 3.0.0
     *
     * @param {number} x - The X coordinate of the center of the Body.
     * @param {number} y - The Y coordinate of the center of the Body.
     * @param {number} width - The width of the Body.
     * @param {number} height - The height of the Body.
     * @param {object} options - An object of properties to set on the Body. You can also specify a `chamfer` property to automatically adjust the body.
     *
     * @return {MatterJS.Body} A Matter JS Body.
     */
    rectangle: function (x, y, width, height, options)
    {
        var body = Bodies.rectangle(x, y, width, height, options);

        this.world.add(body);

        return body;
    },

    /**
     * Creates a new rigid trapezoidal Body and adds it to the World.
     *
     * @method Phaser.Physics.Matter.Factory#trapezoid
     * @since 3.0.0
     *
     * @param {number} x - The X coordinate of the center of the Body.
     * @param {number} y - The Y coordinate of the center of the Body.
     * @param {number} width - The width of the trapezoid of the Body.
     * @param {number} height - The height of the trapezoid of the Body.
     * @param {number} slope - The slope of the trapezoid. 0 creates a rectangle, while 1 creates a triangle. Positive values make the top side shorter, while negative values make the bottom side shorter.
     * @param {object} options - An object of properties to set on the Body. You can also specify a `chamfer` property to automatically adjust the body.
     *
     * @return {MatterJS.Body} A Matter JS Body.
     */
    trapezoid: function (x, y, width, height, slope, options)
    {
        var body = Bodies.trapezoid(x, y, width, height, slope, options);

        this.world.add(body);

        return body;
    },

    /**
     * Creates a new rigid circular Body and adds it to the World.
     *
     * @method Phaser.Physics.Matter.Factory#circle
     * @since 3.0.0
     *
     * @param {number} x - The X coordinate of the center of the Body.
     * @param {number} y - The Y coordinate of the center of the Body.
     * @param {number} radius - The radius of the circle.
     * @param {object} options - An object of properties to set on the Body. You can also specify a `chamfer` property to automatically adjust the body.
     * @param {number} maxSides - The maximum amount of sides to use for the polygon which will approximate this circle.
     *
     * @return {MatterJS.Body} A Matter JS Body.
     */
    circle: function (x, y, radius, options, maxSides)
    {
        var body = Bodies.circle(x, y, radius, options, maxSides);

        this.world.add(body);

        return body;
    },

    /**
     * Creates a new rigid polygonal Body and adds it to the World.
     *
     * @method Phaser.Physics.Matter.Factory#polygon
     * @since 3.0.0
     *
     * @param {number} x - The X coordinate of the center of the Body.
     * @param {number} y - The Y coordinate of the center of the Body.
     * @param {number} sides - The number of sides the polygon will have.
     * @param {number} radius - The "radius" of the polygon, i.e. the distance from its center to any vertex. This is also the radius of its circumcircle.
     * @param {object} options - An object of properties to set on the Body. You can also specify a `chamfer` property to automatically adjust the body.
     *
     * @return {MatterJS.Body} A Matter JS Body.
     */
    polygon: function (x, y, sides, radius, options)
    {
        var body = Bodies.polygon(x, y, sides, radius, options);

        this.world.add(body);

        return body;
    },

    /**
     * Creates a body using the supplied vertices (or an array containing multiple sets of vertices) and adds it to the World.
     * If the vertices are convex, they will pass through as supplied. Otherwise, if the vertices are concave, they will be decomposed. Note that this process is not guaranteed to support complex sets of vertices, e.g. ones with holes.
     *
     * @method Phaser.Physics.Matter.Factory#fromVertices
     * @since 3.0.0
     *
     * @param {number} x - The X coordinate of the center of the Body.
     * @param {number} y - The Y coordinate of the center of the Body.
     * @param {array} vertexSets - [description]
     * @param {object} options - [description]
     * @param {boolean} flagInternal - Flag internal edges (coincident part edges)
     * @param {boolean} removeCollinear - Whether Matter.js will discard collinear edges (to improve performance).
     * @param {number} minimumArea - During decomposition discard parts that have an area less than this
     *
     * @return {MatterJS.Body} A Matter JS Body.
     */
    fromVertices: function (x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea)
    {
        var body = Bodies.fromVertices(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea);

        this.world.add(body);

        return body;
    },

    /**
     * Create a new composite containing Matter Image objects created in a grid arrangement.
     * This function uses the body bounds to prevent overlaps.
     *
     * @method Phaser.Physics.Matter.Factory#imageStack
     * @since 3.0.0
     *
     * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
     * @param {(string|integer)} frame - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value.
     * @param {number} x - The horizontal position of this composite in the world.
     * @param {number} y - The vertical position of this composite in the world.
     * @param {number} columns - The number of columns in the grid.
     * @param {number} rows - The number of rows in the grid.
     * @param {number} [columnGap=0] - The distance between each column.
     * @param {number} [rowGap=0] - The distance between each row.
     * @param {object} [options] - [description]
     *
     * @return {MatterJS.Composite} A Matter JS Composite Stack.
     */
    imageStack: function (key, frame, x, y, columns, rows, columnGap, rowGap, options)
    {
        if (columnGap === undefined) { columnGap = 0; }
        if (rowGap === undefined) { rowGap = 0; }
        if (options === undefined) { options = {}; }

        var world = this.world;
        var displayList = this.sys.displayList;

        options.addToWorld = false;

        var stack = Composites.stack(x, y, columns, rows, columnGap, rowGap, function (x, y)
        {
            var image = new MatterImage(world, x, y, key, frame, options);

            displayList.add(image);

            return image.body;
        });

        world.add(stack);

        return stack;
    },

    /**
     * Create a new composite containing bodies created in the callback in a grid arrangement.
     * This function uses the body bounds to prevent overlaps.
     *
     * @method Phaser.Physics.Matter.Factory#stack
     * @since 3.0.0
     *
     * @param {number} x - The horizontal position of this composite in the world.
     * @param {number} y - The vertical position of this composite in the world.
     * @param {number} columns - The number of columns in the grid.
     * @param {number} rows - The number of rows in the grid.
     * @param {number} columnGap - The distance between each column.
     * @param {number} rowGap - The distance between each row.
     * @param {function} callback - The callback that creates the stack.
     *
     * @return {MatterJS.Composite} A new composite containing objects created in the callback.
     */
    stack: function (x, y, columns, rows, columnGap, rowGap, callback)
    {
        var stack = Composites.stack(x, y, columns, rows, columnGap, rowGap, callback);

        this.world.add(stack);

        return stack;
    },

    /**
     * Create a new composite containing bodies created in the callback in a pyramid arrangement.
     * This function uses the body bounds to prevent overlaps.
     *
     * @method Phaser.Physics.Matter.Factory#pyramid
     * @since 3.0.0
     *
     * @param {number} x - The horizontal position of this composite in the world.
     * @param {number} y - The vertical position of this composite in the world.
     * @param {number} columns - The number of columns in the pyramid.
     * @param {number} rows - The number of rows in the pyramid.
     * @param {number} columnGap - The distance between each column.
     * @param {number} rowGap - The distance between each row.
     * @param {function} callback - The callback function to be invoked.
     *
     * @return {MatterJS.Composite} A Matter JS Composite pyramid.
     */
    pyramid: function (x, y, columns, rows, columnGap, rowGap, callback)
    {
        var stack = Composites.pyramid(x, y, columns, rows, columnGap, rowGap, callback);

        this.world.add(stack);

        return stack;
    },

    /**
     * Chains all bodies in the given composite together using constraints.
     *
     * @method Phaser.Physics.Matter.Factory#chain
     * @since 3.0.0
     *
     * @param {MatterJS.Composite} composite - [description]
     * @param {number} xOffsetA - [description]
     * @param {number} yOffsetA - [description]
     * @param {number} xOffsetB - [description]
     * @param {number} yOffsetB - [description]
     * @param {object} options - [description]
     *
     * @return {MatterJS.Composite} A new composite containing objects chained together with constraints.
     */
    chain: function (composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options)
    {
        return Composites.chain(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options);
    },

    /**
     * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces.
     *
     * @method Phaser.Physics.Matter.Factory#mesh
     * @since 3.0.0
     *
     * @param {MatterJS.Composite} composite - [description]
     * @param {number} columns - [description]
     * @param {number} rows - [description]
     * @param {boolean} crossBrace - [description]
     * @param {object} options - [description]
     *
     * @return {MatterJS.Composite} The composite containing objects meshed together with constraints.
     */
    mesh: function (composite, columns, rows, crossBrace, options)
    {
        return Composites.mesh(composite, columns, rows, crossBrace, options);
    },

    /**
     * Creates a composite with a Newton's Cradle setup of bodies and constraints.
     *
     * @method Phaser.Physics.Matter.Factory#newtonsCradle
     * @since 3.0.0
     *
     * @param {number} x - [description]
     * @param {number} y - [description]
     * @param {number} number - [description]
     * @param {number} size - [description]
     * @param {number} length - [description]
     *
     * @return {MatterJS.Composite} A new composite newtonsCradle body.
     */
    newtonsCradle: function (x, y, number, size, length)
    {
        var composite = Composites.newtonsCradle(x, y, number, size, length);

        this.world.add(composite);

        return composite;
    },

    /**
     * Creates a composite with simple car setup of bodies and constraints.
     *
     * @method Phaser.Physics.Matter.Factory#car
     * @since 3.0.0
     *
     * @param {number} x - [description]
     * @param {number} y - [description]
     * @param {number} width - [description]
     * @param {number} height - [description]
     * @param {number} wheelSize - [description]
     *
     * @return {MatterJS.Composite} A new composite car body.
     */
    car: function (x, y, width, height, wheelSize)
    {
        var composite = Composites.car(x, y, width, height, wheelSize);

        this.world.add(composite);

        return composite;
    },

    /**
     * Creates a simple soft body like object.
     *
     * @method Phaser.Physics.Matter.Factory#softBody
     * @since 3.0.0
     *
     * @param {number} x - The horizontal position of this composite in the world.
     * @param {number} y - The vertical position of this composite in the world.
     * @param {number} columns - The number of columns in the Composite.
     * @param {number} rows - The number of rows in the Composite.
     * @param {number} columnGap - The distance between each column.
     * @param {number} rowGap - The distance between each row.
     * @param {boolean} crossBrace - [description]
     * @param {number} particleRadius - The radius of this circlular composite.
     * @param {object} particleOptions - [description]
     * @param {object} constraintOptions - [description]
     *
     * @return {MatterJS.Composite} A new composite simple soft body.
     */
    softBody: function (x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions)
    {
        var composite = Composites.softBody(x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions);

        this.world.add(composite);

        return composite;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#joint
     * @since 3.0.0
     *
     * @param {MatterJS.Body} bodyA - [description]
     * @param {MatterJS.Body} bodyB - [description]
     * @param {number} length - [description]
     * @param {number} [stiffness=1] - [description]
     * @param {object} [options={}] - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    joint: function (bodyA, bodyB, length, stiffness, options)
    {
        return this.constraint(bodyA, bodyB, length, stiffness, options);
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#spring
     * @since 3.0.0
     *
     * @param {MatterJS.Body} bodyA - The first possible `Body` that this constraint is attached to.
     * @param {MatterJS.Body} bodyB - The second possible `Body` that this constraint is attached to.
     * @param {number} length - A Number that specifies the target resting length of the constraint. It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`
     * @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring.
     * @param {object} [options={}] - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    spring: function (bodyA, bodyB, length, stiffness, options)
    {
        return this.constraint(bodyA, bodyB, length, stiffness, options);
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#constraint
     * @since 3.0.0
     *
     * @param {MatterJS.Body} bodyA - [description]
     * @param {MatterJS.Body} bodyB - [description]
     * @param {number} length - [description]
     * @param {number} [stiffness=1] - [description]
     * @param {object} [options={}] - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    constraint: function (bodyA, bodyB, length, stiffness, options)
    {
        if (stiffness === undefined) { stiffness = 1; }
        if (options === undefined) { options = {}; }

        options.bodyA = (bodyA.type === 'body') ? bodyA : bodyA.body;
        options.bodyB = (bodyB.type === 'body') ? bodyB : bodyB.body;
        options.length = length;
        options.stiffness = stiffness;

        var constraint = Constraint.create(options);

        this.world.add(constraint);

        return constraint;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#worldConstraint
     * @since 3.0.0
     *
     * @param {MatterJS.Body} bodyB - [description]
     * @param {number} length - [description]
     * @param {number} [stiffness=1] - [description]
     * @param {object} [options={}] - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    worldConstraint: function (bodyB, length, stiffness, options)
    {
        if (stiffness === undefined) { stiffness = 1; }
        if (options === undefined) { options = {}; }

        options.bodyB = (bodyB.type === 'body') ? bodyB : bodyB.body;
        options.length = length;
        options.stiffness = stiffness;

        var constraint = Constraint.create(options);

        this.world.add(constraint);

        return constraint;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#mouseSpring
     * @since 3.0.0
     *
     * @param {object} options - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    mouseSpring: function (options)
    {
        return this.pointerConstraint(options);
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#pointerConstraint
     * @since 3.0.0
     *
     * @param {object} options - [description]
     *
     * @return {MatterJS.Constraint} A Matter JS Constraint.
     */
    pointerConstraint: function (options)
    {
        if (options === undefined) { options = {}; }

        if (!options.hasOwnProperty('render'))
        {
            options.render = { visible: false };
        }

        var pointerConstraint = new PointerConstraint(this.scene, this.world, options);

        this.world.add(pointerConstraint.constraint);

        return pointerConstraint;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#image
     * @since 3.0.0
     *
     * @param {number} x - The horizontal position of this Game Object in the world.
     * @param {number} y - The vertical position of this Game Object in the world.
     * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
     * @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value.
     * @param {object} [options={}] - [description]
     *
     * @return {Phaser.Physics.Matter.Image} [description]
     */
    image: function (x, y, key, frame, options)
    {
        var image = new MatterImage(this.world, x, y, key, frame, options);

        this.sys.displayList.add(image);

        return image;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#tileBody
     * @since 3.0.0
     *
     * @param {Phaser.Tilemaps.Tile} tile - [description]
     * @param {object} options - [description]
     *
     * @return {Phaser.Physics.Matter.TileBody} [description]
     */
    tileBody: function (tile, options)
    {
        var tileBody = new MatterTileBody(this.world, tile, options);

        return tileBody;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#sprite
     * @since 3.0.0
     *
     * @param {number} x - The horizontal position of this Game Object in the world.
     * @param {number} y - The vertical position of this Game Object in the world.
     * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
     * @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value.
     * @param {object} [options={}] - [description]
     *
     * @return {Phaser.Physics.Matter.Sprite} [description]
     */
    sprite: function (x, y, key, frame, options)
    {
        var sprite = new MatterSprite(this.world, x, y, key, frame, options);

        this.sys.displayList.add(sprite);
        this.sys.updateList.add(sprite);

        return sprite;
    },

    /**
     * [description]
     *
     * @method Phaser.Physics.Matter.Factory#gameObject
     * @since 3.3.0
     *
     * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to inject the Matter Body in to.
     * @param {object} options - [description]
     *
     * @return {Phaser.GameObjects.GameObject} The Game Object that had the Matter Body injected into it.
     */
    gameObject: function (gameObject, options)
    {
        return MatterGameObject(this.world, gameObject, options);
    },

    /**
     * Destroys this Factory.
     *
     * @method Phaser.Physics.Matter.Factory#destroy
     * @since 3.5.0
     */
    destroy: function ()
    {
        this.world = null;
        this.scene = null;
        this.sys = null;
    }

});

module.exports = Factory;


Plugins: require('./plugins'),
Renderer: require('./renderer'),
Scale: require('./scale'),
Scene: require('./scene/Scene'),
Scenes: require('./scene'),
Sound: require('./sound'),
Structs: require('./structs'),
Textures: require('./textures'),
Time: require('./time'),
Tweens: require('./tweens')
};

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://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

require('./polyfills');

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

/**
 * @namespace Phaser
 */

var Phaser = {

    Actions: require('./actions'),
    Animations: require('./animations'),
    Cache: require('./cache'),
    Cameras: require('./cameras'),
    Core: require('./core'),
    Class: require('./utils/Class'),
    Create: require('./create'),
    Curves: require('./curves'),
    Data: require('./data'),
    Display: require('./display'),
    DOM: require('./dom'),
    Events: require('./events'),
    Game: require('./core/Game'),
    GameObjects: require('./gameobjects'),
    Geom: require('./geom'),
    Input: require('./input'),
    Loader: require('./loader'),
    Math: require('./math'),
    Physics: require('./physics'),
    Plugins: require('./plugins'),
    Renderer: require('./renderer'),
    Scale: require('./scale'),
    Scene: require('./scene/Scene'),
    Scenes: require('./scene'),
    Sound: require('./sound'),
    Structs: require('./structs'),
    Textures: require('./textures'),
    Tilemaps: require('./tilemaps'),
    Time: require('./time'),
    Tweens: require('./tweens'),
    Utils: require('./utils')

};

//  Merge in the optional plugins

if (typeof PLUGIN_CAMERA3D)
{
    Phaser.Cameras.Sprite3D = require('../plugins/camera3d/src');
    Phaser.GameObjects.Sprite3D = require('../plugins/camera3d/src/sprite3d/Sprite3D');
    Phaser.GameObjects.Factories.Sprite3D = require('../plugins/camera3d/src/sprite3d/Sprite3DFactory');
    Phaser.GameObjects.Creators.Sprite3D = require('../plugins/camera3d/src/sprite3d/Sprite3DCreator');
}

if (typeof PLUGIN_FBINSTANT)
{
    Phaser.FacebookInstantGamesPlugin = require('../plugins/fbinstant/src/FacebookInstantGamesPlugin');
}

//   Merge in the consts

Phaser = Extend(false, Phaser, CONST);

//  Export it

module.exports = Phaser;

global.Phaser = Phaser;

/*
 * "Documentation is like pizza: when it is good, it is very, very good;
 * and when it is bad, it is better than nothing."
 *  -- Dick Brandon
 */


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

/**
 * Nudges (translates) the top-left corner of a Rectangle by the coordinates of a point (translation vector).
 *
 * @function Phaser.Geom.Rectangle.OffsetPoint
 * @since 3.0.0
 *
 * @generic {Phaser.Geom.Rectangle} O - [rect,$return]
 *
 * @param {Phaser.Geom.Rectangle} rect - The Rectangle to adjust.
 * @param {(Phaser.Geom.Point|Phaser.Math.Vector2)} point - The point whose coordinates should be used as an offset.
 *
 * @return {Phaser.Geom.Rectangle} The adjusted Rectangle.
 */
var OffsetPoint = function (rect, point)
{
    rect.x += point.x;
    rect.y += point.y;

    return rect;
};

module.exports = OffsetPoint;


/**
 * @typedef {object} Phaser.Core.Types.PluginObjectItem
 * @since 3.8.0
 *
 * @property {string} [key] - A key to identify the plugin in the Plugin Manager.
 * @property {*} [plugin] - The plugin itself. Usually a class/constructor.
 * @property {boolean} [start] - Whether the plugin should be started automatically.
 * @property {string} [systemKey] - For a scene plugin, add the plugin to the scene's systems object under this key (`this.sys.KEY`, from the scene).
 * @property {string} [sceneKey] - For a scene plugin, add the plugin to the scene object under this key (`this.KEY`, from the scene).
 * @property {string} [mapping] - If this plugin is to be injected into the Scene Systems, this is the property key map used.
 * @property {*} [data] - Arbitrary data passed to the plugin's init() method.
 *
 * @example
 * // Global plugin
 * { key: 'BankPlugin', plugin: BankPluginV3, start: true, data: { gold: 5000 } }
 * @example
 * // Scene plugin
 * { key: 'WireFramePlugin', plugin: WireFramePlugin, systemKey: 'wireFramePlugin', sceneKey: 'wireframe' }
 */