* @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} object - [description]

* @param {integer} [bodyType] - The type of Body to create. Either `DYNAMIC_BODY` or `STATIC_BODY`.

if (bodyType === undefined) { bodyType = CONST.DYNAMIC_BODY; }

keep keep keep replace keep keep keep keep keep

* @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]|Phaser.GameObjects.Group|Phaser.GameObjects.Group[])} object - [description]

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

var ArcadeImage = require('./ArcadeImage');
var ArcadeSprite = require('./ArcadeSprite');
var Class = require('../../utils/Class');
var CONST = require('./const');
var PhysicsGroup = require('./PhysicsGroup');
var StaticPhysicsGroup = require('./StaticPhysicsGroup');

/**
 * @classdesc
 * The Arcade Physics Factory allows you to easily create Arcade Physics enabled Game Objects.
 * Objects that are created by this Factory are automatically added to the physics world.
 *
 * @class Factory
 * @memberOf Phaser.Physics.Arcade
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Physics.Arcade.World} world - The Arcade Physics World instance.
 */
var Factory = new Class({

    initialize:

    function Factory (world)
    {
        /**
         * A reference to the Arcade Physics World.
         *
         * @name Phaser.Physics.Arcade.Factory#world
         * @type {Phaser.Physics.Arcade.World}
         * @since 3.0.0
         */
        this.world = world;

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

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

    /**
     * Create a new Arcade Physics Collider object.
     *
     * @method Phaser.Physics.Arcade.Factory#collider
     * @since 3.0.0
     *
     * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} object1 - The first object to check for collision.
     * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} object2 - The second object to check for collision.
     * @param {ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects collide.
     * @param {ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects collide. Must return a boolean.
     * @param {*} [callbackContext] - The scope in which to call the callbacks.
     *
     * @return {Phaser.Physics.Arcade.Collider} The Collider that was created.
     */
    collider: function (object1, object2, collideCallback, processCallback, callbackContext)
    {
        return this.world.addCollider(object1, object2, collideCallback, processCallback, callbackContext);
    },

    /**
     * Create a new Arcade Physics Collider Overlap object.
     *
     * @method Phaser.Physics.Arcade.Factory#overlap
     * @since 3.0.0
     *
     * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} object1 - The first object to check for overlap.
     * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} object2 - The second object to check for overlap.
     * @param {ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects collide.
     * @param {ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects collide. Must return a boolean.
     * @param {*} [callbackContext] - The scope in which to call the callbacks.
     *
     * @return {Phaser.Physics.Arcade.Collider} The Collider that was created.
     */
    overlap: function (object1, object2, collideCallback, processCallback, callbackContext)
    {
        return this.world.addOverlap(object1, object2, collideCallback, processCallback, callbackContext);
    },

    /**
     * Adds an Arcade Physics Body to the given Game Object.
     *
     * @method Phaser.Physics.Arcade.Factory#existing
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.GameObject} gameObject - [description]
     * @param {boolean} [isStatic=false] - Set to true to create a Static body, otherwise it will create a Dynamic body.
     *
     * @return {Phaser.GameObjects.GameObject} The Game Object.
     */
    existing: function (gameObject, isStatic)
    {
        var type = (isStatic) ? CONST.STATIC_BODY : CONST.DYNAMIC_BODY;

        this.world.enableBody(gameObject, type);

        return gameObject;
    },

    /**
     * Creates a new Arcade Image object with a Static body.
     *
     * @method Phaser.Physics.Arcade.Factory#staticImage
     * @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} 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.
     *
     * @return {Phaser.Physics.Arcade.Image} The Image object that was created.
     */
    staticImage: function (x, y, key, frame)
    {
        var image = new ArcadeImage(this.scene, x, y, key, frame);

        this.sys.displayList.add(image);

        this.world.enableBody(image, CONST.STATIC_BODY);

        return image;
    },

    /**
     * Creates a new Arcade Image object with a Dynamic body.
     *
     * @method Phaser.Physics.Arcade.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} 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.
     *
     * @return {Phaser.Physics.Arcade.Image} The Image object that was created.
     */
    image: function (x, y, key, frame)
    {
        var image = new ArcadeImage(this.scene, x, y, key, frame);

        this.sys.displayList.add(image);

        this.world.enableBody(image, CONST.DYNAMIC_BODY);

        return image;
    },

    /**
     * Creates a new Arcade Sprite object with a Static body.
     *
     * @method Phaser.Physics.Arcade.Factory#staticSprite
     * @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} 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.
     *
     * @return {Phaser.Physics.Arcade.Sprite} The Sprite object that was created.
     */
    staticSprite: function (x, y, key, frame)
    {
        var sprite = new ArcadeSprite(this.scene, x, y, key, frame);

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

        this.world.enableBody(sprite, CONST.STATIC_BODY);

        return sprite;
    },

    /**
     * Creates a new Arcade Sprite object with a Dynamic body.
     *
     * @method Phaser.Physics.Arcade.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.
     *
     * @return {Phaser.Physics.Arcade.Sprite} The Sprite object that was created.
     */
    sprite: function (x, y, key, frame)
    {
        var sprite = new ArcadeSprite(this.scene, x, y, key, frame);

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

        this.world.enableBody(sprite, CONST.DYNAMIC_BODY);

        return sprite;
    },

    /**
     * Creates a Static Physics Group object.
     * All Game Objects created by this Group will automatically be static Arcade Physics objects.
     *
     * @method Phaser.Physics.Arcade.Factory#staticGroup
     * @since 3.0.0
     *
     * @param {array} [children] - [description]
     * @param {GroupConfig} [config] - [description]
     *
     * @return {Phaser.Physics.Arcade.StaticGroup} The Static Group object that was created.
     */
    staticGroup: function (children, config)
    {
        return this.sys.updateList.add(new StaticPhysicsGroup(this.world, this.world.scene, children, config));
    },

    /**
     * Creates a Physics Group object.
     * All Game Objects created by this Group will automatically be dynamic Arcade Physics objects.
     *
     * @method Phaser.Physics.Arcade.Factory#group
     * @since 3.0.0
     *
     * @param {array} [children] - [description]
     * @param {PhysicsGroupConfig} [config] - [description]
     *
     * @return {Phaser.Physics.Arcade.Group} The Group object that was created.
     */
    group: function (children, config)
    {
        return this.sys.updateList.add(new PhysicsGroup(this.world, this.world.scene, children, config));
    },

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

});

module.exports = Factory;


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

var Class = require('../../utils/Class');
var CONST = require('../const');
var File = require('../File');
var FileTypesManager = require('../FileTypesManager');
var GetFastValue = require('../../utils/object/GetFastValue');
var IsPlainObject = require('../../utils/object/IsPlainObject');

/**
 * @typedef {object} Phaser.Loader.FileTypes.ScenePluginFileConfig
 *
 * @property {string} key - The key of the file. Must be unique within the Loader.
 * @property {(string|function)} [url] - The absolute or relative URL to load the file from. Or, a Scene Plugin.
 * @property {string} [extension='js'] - The default file extension to use if no url is provided.
 * @property {string} [systemKey] - If this plugin is to be added to Scene.Systems, this is the property key for it.
 * @property {string} [sceneKey] - If this plugin is to be added to the Scene, this is the property key for it.
 * @property {XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
 */

/**
 * @classdesc
 * A single Scene Plugin Script File suitable for loading by the Loader.
 *
 * These are created when you use the Phaser.Loader.LoaderPlugin#scenePlugin method and are not typically created directly.
 *
 * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#scenePlugin.
 *
 * @class ScenePluginFile
 * @extends Phaser.Loader.File
 * @memberOf Phaser.Loader.FileTypes
 * @constructor
 * @since 3.8.0
 *
 * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
 * @param {(string|Phaser.Loader.FileTypes.ScenePluginFileConfig)} key - The key to use for this file, or a file configuration object.
 * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.js`, i.e. if `key` was "alien" then the URL will be "alien.js".
 * @param {string} [systemKey] - If this plugin is to be added to Scene.Systems, this is the property key for it.
 * @param {string} [sceneKey] - If this plugin is to be added to the Scene, this is the property key for it.
 * @param {XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
 */
var ScenePluginFile = new Class({

    Extends: File,

    initialize:

    function ScenePluginFile (loader, key, url, systemKey, sceneKey, xhrSettings)
    {
        var extension = 'js';

        if (IsPlainObject(key))
        {
            var config = key;

            key = GetFastValue(config, 'key');
            url = GetFastValue(config, 'url');
            xhrSettings = GetFastValue(config, 'xhrSettings');
            extension = GetFastValue(config, 'extension', extension);
            systemKey = GetFastValue(config, 'systemKey');
            sceneKey = GetFastValue(config, 'sceneKey');
        }

        var fileConfig = {
            type: 'scenePlugin',
            cache: false,
            extension: extension,
            responseType: 'text',
            key: key,
            url: url,
            xhrSettings: xhrSettings,
            config: {
                systemKey: systemKey,
                sceneKey: sceneKey
            }
        };

        File.call(this, loader, fileConfig);

        // If the url variable refers to a class, add the plugin directly
        if (typeof url === 'function')
        {
            this.data = url;

            this.state = CONST.FILE_POPULATED;
        }
    },

    /**
     * Called automatically by Loader.nextFile.
     * This method controls what extra work this File does with its loaded data.
     *
     * @method Phaser.Loader.FileTypes.ScenePluginFile#onProcess
     * @since 3.8.0
     */
    onProcess: function ()
    {
        var pluginManager = this.loader.systems.plugins;
        var config = this.config;

        var key = this.key;
        var systemKey = GetFastValue(config, 'systemKey', key);
        var sceneKey = GetFastValue(config, 'sceneKey', key);

        if (this.state === CONST.FILE_POPULATED)
        {
            pluginManager.installScenePlugin(systemKey, this.data, sceneKey, this.loader.scene);
        }
        else
        {
            //  Plugin added via a js file
            this.state = CONST.FILE_PROCESSING;

            this.data = document.createElement('script');
            this.data.language = 'javascript';
            this.data.type = 'text/javascript';
            this.data.defer = false;
            this.data.text = this.xhrLoader.responseText;

            document.head.appendChild(this.data);

            pluginManager.installScenePlugin(systemKey, window[this.key], sceneKey, this.loader.scene);
        }

        this.onProcessComplete();
    }

});

/**
 * Adds a Scene Plugin Script file, or array of plugin files, to the current load queue.
 *
 * You can call this method from within your Scene's `preload`, along with any other files you wish to load:
 *
 * ```javascript
 * function preload ()
 * {
 *     this.load.scenePlugin('ModPlayer', 'plugins/ModPlayer.js', 'modPlayer', 'mods');
 * }
 * ```
 *
 * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
 * or if it's already running, when the next free load slot becomes available. This happens automatically if you
 * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
 * it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
 * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
 * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
 * loaded.
 *
 * The key must be a unique String and not already in-use by another file in the Loader.
 *
 * Instead of passing arguments you can pass a configuration object, such as:
 *
 * ```javascript
 * this.load.scenePlugin({
 *     key: 'modplayer',
 *     url: 'plugins/ModPlayer.js'
 * });
 * ```
 *
 * See the documentation for `Phaser.Loader.FileTypes.ScenePluginFileConfig` for more details.
 *
 * Once the file has finished loading it will automatically be converted into a script element
 * via `document.createElement('script')`. It will have its language set to JavaScript, `defer` set to
 * false and then the resulting element will be appended to `document.head`. Any code then in the
 * script will be executed. It will then be passed to the Phaser PluginCache.register method.
 *
 * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
 *
 * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien"
 * and no URL is given then the Loader will set the URL to be "alien.js". It will always add `.js` as the extension, although
 * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
 *
 * Note: The ability to load this type of file will only be available if the Script File type has been built into Phaser.
 * It is available in the default build but can be excluded from custom builds.
 *
 * @method Phaser.Loader.LoaderPlugin#scenePlugin
 * @fires Phaser.Loader.LoaderPlugin#addFileEvent
 * @since 3.8.0
 *
 * @param {(string|Phaser.Loader.FileTypes.ScenePluginFileConfig|Phaser.Loader.FileTypes.ScenePluginFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
 * @param {(string|function)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.js`, i.e. if `key` was "alien" then the URL will be "alien.js". Or, set to a plugin function.
 * @param {string} [systemKey] - If this plugin is to be added to Scene.Systems, this is the property key for it.
 * @param {string} [sceneKey] - If this plugin is to be added to the Scene, this is the property key for it.
 * @param {XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings.
 *
 * @return {Phaser.Loader.LoaderPlugin} The Loader instance.
 */
FileTypesManager.register('scenePlugin', function (key, url, systemKey, sceneKey, xhrSettings)
{
    if (Array.isArray(key))
    {
        for (var i = 0; i < key.length; i++)
        {
            //  If it's an array it has to be an array of Objects, so we get everything out of the 'key' object
            this.addFile(new ScenePluginFile(this, key[i]));
        }
    }
    else
    {
        this.addFile(new ScenePluginFile(this, key, url, systemKey, sceneKey, xhrSettings));
    }

    return this;
});

module.exports = ScenePluginFile;


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

var Class = require('../../../utils/Class');
var ShaderSourceFS = require('../shaders/ForwardDiffuse-frag.js');
var TextureTintPipeline = require('./TextureTintPipeline');

var LIGHT_COUNT = 10;

/**
 * @classdesc
 * ForwardDiffuseLightPipeline implements a forward rendering approach for 2D lights.
 * This pipeline extends TextureTintPipeline so it implements all it's rendering functions
 * and batching system.
 *
 * @class ForwardDiffuseLightPipeline
 * @extends Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline
 * @memberOf Phaser.Renderer.WebGL.Pipelines
 * @constructor
 * @since 3.0.0
 *
 * @param {object} config - [description]
 */
var ForwardDiffuseLightPipeline = new Class({

    Extends: TextureTintPipeline,

    initialize:

    function ForwardDiffuseLightPipeline (config)
    {
        config.fragShader = ShaderSourceFS.replace('%LIGHT_COUNT%', LIGHT_COUNT.toString());

        TextureTintPipeline.call(this, config);
    },

    /**
     * This function binds it's base class resources and this lights 2D resources.
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#onBind
     * @override
     * @since 3.0.0
     *
     * @return {Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline} [description]
     */
    onBind: function ()
    {
        TextureTintPipeline.prototype.onBind.call(this);

        var renderer = this.renderer;
        var program = this.program;

        this.mvpUpdate();

        renderer.setInt1(program, 'uNormSampler', 1);
        renderer.setFloat2(program, 'uResolution', this.width, this.height);

        return this;
    },

    /**
     * This function sets all the needed resources for each camera pass.
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#onRender
     * @since 3.0.0
     *
     * @param {Phaser.Scene} scene - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     *
     * @return {Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline} [description]
     */
    onRender: function (scene, camera)
    {
        var lightManager = scene.sys.lights;

        if (!lightManager)
        {
            return this;
        }

        lightManager.culledLights.length = 0;

        if (lightManager.lights.length <= 0 || !lightManager.active)
        {
            return this; // If not visible lights just passthrough
        }

        var renderer = this.renderer;
        var program = this.program;
        var lights = lightManager.cull(camera);
        var lightCount = Math.min(lights.length, LIGHT_COUNT);
        var cameraMatrix = camera.matrix;
        var point = {x: 0, y: 0};
        var height = renderer.height;
        var index;

        for (index = 0; index < LIGHT_COUNT; ++index)
        {
            renderer.setFloat1(program, 'uLights[' + index + '].radius', 0); // reset lights
        }

        if (lightCount <= 0) { return this; }

        renderer.setFloat4(program, 'uCamera', camera.x, camera.y, camera.rotation, camera.zoom);
        renderer.setFloat3(program, 'uAmbientLightColor', lightManager.ambientColor.r, lightManager.ambientColor.g, lightManager.ambientColor.b);

        for (index = 0; index < lightCount; ++index)
        {
            var light = lights[index];
            var lightName = 'uLights[' + index + '].';
            cameraMatrix.transformPoint(light.x, light.y, point);
            renderer.setFloat2(program, lightName + 'position', point.x - (camera.scrollX * light.scrollFactorX * camera.zoom), height - (point.y - (camera.scrollY * light.scrollFactorY) * camera.zoom));
            renderer.setFloat3(program, lightName + 'color', light.r, light.g, light.b);
            renderer.setFloat1(program, lightName + 'intensity', light.intensity);
            renderer.setFloat1(program, lightName + 'radius', light.radius);
        }

        return this;
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#drawStaticTilemapLayer
     * @override
     * @since 3.0.0
     *
     * @param {Phaser.Tilemaps.StaticTilemapLayer} tilemap - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     */
    drawStaticTilemapLayer: function (tilemap, camera, parentTransformMatrix)
    {
        var normalTexture = tilemap.tileset.image.dataSource[0];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.drawStaticTilemapLayer.call(this, tilemap, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. StaticTilemapLayer rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.drawStaticTilemapLayer(tilemap, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#drawEmitterManager
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Particles.ParticleEmitterManager} emitterManager - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    drawEmitterManager: function (emitterManager, camera, parentTransformMatrix)
    {
        var normalTexture = emitterManager.texture.dataSource[emitterManager.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.drawEmitterManager.call(this, emitterManager, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. EmitterManager rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.drawEmitterManager(emitterManager, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#drawBlitter
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Blitter} blitter - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    drawBlitter: function (blitter, camera, parentTransformMatrix)
    {
        var normalTexture = blitter.texture.dataSource[blitter.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.drawBlitter.call(this, blitter, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. Blitter rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.drawBlitter(blitter, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchSprite
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Sprite} sprite - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchSprite: function (sprite, camera, parentTransformMatrix)
    {
        var normalTexture = sprite.texture.dataSource[sprite.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchSprite.call(this, sprite, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. Sprite rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchSprite(sprite, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchMesh
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Mesh} mesh - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchMesh: function (mesh, camera, parentTransformMatrix)
    {
        var normalTexture = mesh.texture.dataSource[mesh.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchMesh.call(this, mesh, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. Mesh rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchMesh(mesh, camera, parentTransformMatrix);

        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchBitmapText
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.BitmapText} bitmapText - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchBitmapText: function (bitmapText, camera, parentTransformMatrix)
    {
        var normalTexture = bitmapText.texture.dataSource[bitmapText.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchBitmapText.call(this, bitmapText, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. BitmapText rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchBitmapText(bitmapText, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchDynamicBitmapText
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.DynamicBitmapText} bitmapText - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchDynamicBitmapText: function (bitmapText, camera, parentTransformMatrix)
    {
        var normalTexture = bitmapText.texture.dataSource[bitmapText.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchDynamicBitmapText.call(this, bitmapText, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. DynamicBitmapText rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchDynamicBitmapText(bitmapText, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchText
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Text} text - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchText: function (text, camera, parentTransformMatrix)
    {
        var normalTexture = text.texture.dataSource[text.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchText.call(this, text, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. Text rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchText(text, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchDynamicTilemapLayer
     * @since 3.0.0
     *
     * @param {Phaser.Tilemaps.DynamicTilemapLayer} tilemapLayer - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchDynamicTilemapLayer: function (tilemapLayer, camera, parentTransformMatrix)
    {
        var normalTexture = tilemapLayer.tileset.image.dataSource[0];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchDynamicTilemapLayer.call(this, tilemapLayer, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. DynamicTilemapLayer rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchDynamicTilemapLayer(tilemapLayer, camera, parentTransformMatrix);
        }
    },

    /**
     * [description]
     *
     * @method Phaser.Renderer.WebGL.Pipelines.ForwardDiffuseLightPipeline#batchTileSprite
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.TileSprite} tileSprite - [description]
     * @param {Phaser.Cameras.Scene2D.Camera} camera - [description]
     * @param {Phaser.GameObjects.Components.TransformMatrix} parentTransformMatrix - [description]
     *
     */
    batchTileSprite: function (tileSprite, camera, parentTransformMatrix)
    {
        var normalTexture = tileSprite.texture.dataSource[tileSprite.frame.sourceIndex];

        if (normalTexture)
        {
            this.renderer.setPipeline(this);
            this.setTexture2D(normalTexture.glTexture, 1);
            TextureTintPipeline.prototype.batchTileSprite.call(this, tileSprite, camera, parentTransformMatrix);
        }
        else
        {
            console.warn('Normal map texture missing for using Light2D pipeline. TileSprite rendered with default pipeline.');
            this.renderer.pipelines.TextureTintPipeline.batchTileSprite(tileSprite, camera, parentTransformMatrix);
        }
    }

});

ForwardDiffuseLightPipeline.LIGHT_COUNT = LIGHT_COUNT;

module.exports = ForwardDiffuseLightPipeline;


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

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

/**
 * @classdesc
 * Defines a Point in 2D space, with an x and y component.
 *
 * @class Point
 * @memberOf Phaser.Geom
 * @constructor
 * @since 3.0.0
 *
 * @param {number} [x=0] - The x coordinate of this Point.
 * @param {number} [y=x] - The y coordinate of this Point.
 */
var Point = new Class({

    initialize:

    function Point (x, y)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = x; }

        /**
         * The x coordinate of this Point.
         *
         * @name Phaser.Geom.Point#x
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.x = x;

        /**
         * The y coordinate of this Point.
         *
         * @name Phaser.Geom.Point#y
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.y = y;
    },

    /**
     * Set the x and y coordinates of the point to the given values.
     *
     * @method Phaser.Geom.Point#setTo
     * @since 3.0.0
     *
     * @param {number} [x=0] - The x coordinate of this Point.
     * @param {number} [y=x] - The y coordinate of this Point.
     *
     * @return {Phaser.Geom.Point} This Point object.
     */
    setTo: function (x, y)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = x; }

        this.x = x;
        this.y = y;

        return this;
    }

});

module.exports = Point;


* Disables the Body of a Game Object, or the Bodies of several Game Objects.

keep keep keep keep keep replace keep keep keep


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

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

/**
 * Renders this Game Object with the Canvas Renderer to the given Camera.
 * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
 * This method should not be called directly. It is a utility function of the Render module.
 *
 * @method Phaser.GameObjects.BitmapText#renderCanvas
 * @since 3.0.0
 * @private
 *
 * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
 * @param {Phaser.GameObjects.BitmapText} src - The Game Object being rendered in this call.
 * @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
 * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
 * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
 */
var BitmapTextCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
    var text = src.text;
    var textLength = text.length;

    if (GameObject.RENDER_MASK !== src.renderFlags || textLength === 0 || (src.cameraFilter > 0 && (src.cameraFilter & camera._id)))
    {
        return;
    }

    var textureFrame = src.frame;

    var chars = src.fontData.chars;
    var lineHeight = src.fontData.lineHeight;
    var letterSpacing = src.letterSpacing;

    var xAdvance = 0;
    var yAdvance = 0;

    var indexCount = 0;
    var charCode = 0;

    var glyph = null;
    var glyphX = 0;
    var glyphY = 0;
    var glyphW = 0;
    var glyphH = 0;

    var x = 0;
    var y = 0;

    var lastGlyph = null;
    var lastCharCode = 0;

    var ctx = renderer.currentContext;
    var image = src.frame.source.image;

    var textureX = textureFrame.cutX;
    var textureY = textureFrame.cutY;

    var scale = (src.fontSize / src.fontData.size);

    //  Blend Mode
    if (renderer.currentBlendMode !== src.blendMode)
    {
        renderer.currentBlendMode = src.blendMode;
        ctx.globalCompositeOperation = renderer.blendModes[src.blendMode];
    }

    //  Alpha
    if (renderer.currentAlpha !== src.alpha)
    {
        renderer.currentAlpha = src.alpha;
        ctx.globalAlpha = src.alpha;
    }

    //  Smoothing
    if (renderer.currentScaleMode !== src.scaleMode)
    {
        renderer.currentScaleMode = src.scaleMode;
    }

    var roundPixels = renderer.config.roundPixels;

    var tx = (src.x - camera.scrollX * src.scrollFactorX) + src.frame.x;
    var ty = (src.y - camera.scrollY * src.scrollFactorY) + src.frame.y;

    if (roundPixels)
    {
        tx |= 0;
        ty |= 0;
    }

    ctx.save();

    if (parentMatrix !== undefined)
    {
        var matrix = parentMatrix.matrix;
        ctx.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
    }

    ctx.translate(tx, ty);

    ctx.rotate(src.rotation);

    ctx.translate(-src.displayOriginX, -src.displayOriginY);

    ctx.scale(src.scaleX, src.scaleY);

    for (var index = 0; index < textLength; ++index)
    {
        charCode = text.charCodeAt(index);

        if (charCode === 10)
        {
            xAdvance = 0;
            indexCount = 0;
            yAdvance += lineHeight;
            lastGlyph = null;
            continue;
        }

        glyph = chars[charCode];

        if (!glyph)
        {
            continue;
        }

        glyphX = textureX + glyph.x;
        glyphY = textureY + glyph.y;

        glyphW = glyph.width;
        glyphH = glyph.height;

        x = indexCount + glyph.xOffset + xAdvance;
        y = glyph.yOffset + yAdvance;

        if (lastGlyph !== null)
        {
            var kerningOffset = glyph.kerning[lastCharCode];
            x += (kerningOffset !== undefined) ? kerningOffset : 0;
        }

        x *= scale;
        y *= scale;

        xAdvance += glyph.xAdvance + letterSpacing;
        indexCount += 1;
        lastGlyph = glyph;
        lastCharCode = charCode;

        //  Nothing to render or a space? Then skip to the next glyph
        if (glyphW === 0 || glyphH === 0 || charCode === 32)
        {
            continue;
        }

        if (roundPixels)
        {
            x |= 0;
            y |= 0;
        }

        ctx.save();

        ctx.translate(x, y);

        ctx.scale(scale, scale);

        ctx.drawImage(image, glyphX, glyphY, glyphW, glyphH, 0, 0, glyphW, glyphH);

        ctx.restore();
    }

    ctx.restore();
};

module.exports = BitmapTextCanvasRenderer;


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

/**
 * Gets the shortest angle between `angle1` and `angle2`.
 * Both angles must be in the range -180 to 180, which is the same clamped
 * range that `sprite.angle` uses, so you can pass in two sprite angles to
 * this method and get the shortest angle back between the two of them.
 *
 * The angle returned will be in the same range. If the returned angle is
 * greater than 0 then it's a counter-clockwise rotation, if < 0 then it's
 * a clockwise rotation.
 *
 * @function Phaser.Math.Angle.ShortestBetween
 * @since 3.0.0
 *
 * @param {number} angle1 - The first angle in the range -180 to 180.
 * @param {number} angle2 - The second angle in the range -180 to 180.
 *
 * @return {number} The shortest angle, in degrees. If greater than zero it's a counter-clockwise rotation.
 */
var ShortestBetween = function (angle1, angle2)
{
    var difference = angle2 - angle1;

    if (difference === 0)
    {
        return 0;
    }

    var times = Math.floor((difference - (-180)) / 360);

    return difference - (times * 360);

};

module.exports = ShortestBetween;


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

/**
 * Returns the circumference of the given Circle.
 *
 * @function Phaser.Geom.Circle.Circumference
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Circle} circle - The Circle to get the circumference of.
 *
 * @return {number} The circumference of the Circle.
 */
var Circumference = function (circle)
{
    return 2 * (Math.PI * circle.radius);
};

module.exports = Circumference;