if (knockout === undefined) { knockout = false; }

* This must be an integer and can be between 0 and 128 inclusive.

* The higher the value, the more iterations the shader takes

* The strength of the glow outward from the edge of the Sprite.

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

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

var Class = require('../../utils/Class');
var Effects = require('../../fx/');
var SpliceOne = require('../../utils/array/SpliceOne');

/**
 * @classdesc
 *
 * @class FX
 * @memberof Phaser.GameObjects.Components
 * @constructor
 * @since 3.60.0
 * @webglOnly
 *
 * @param {Phaser.GameObjects.GameObject} gameObject - A reference to the Game Object that owns this FX Component.
 * @param {boolean} isPost - Is this a Pre or Post FX Component?
+- *
 */
var FX = new Class({

    initialize:

    function FX (gameObject, isPost)
    {
        /**
         * A reference to the Game Object that owns this FX Component.
         *
         * @name Phaser.GameObjects.Components.FX#gameObject
         * @type {Phaser.GameObjects.GameObject}
         * @since 3.60.0
         */
        this.gameObject = gameObject;

        /**
         * Is this a Post FX Controller? or a Pre FX Controller?
         *
         * @name Phaser.GameObjects.Components.FX#isPost
         * @type {boolean}
         * @since 3.60.0
         */
        this.isPost = isPost;

        /**
         * Has this FX Component been enabled?
         *
         * You should treat this property as read-only.
         *
         * @name Phaser.GameObjects.Components.FX#enabled
         * @type {boolean}
         * @since 3.60.0
         */
        this.enabled = false;

        /**
         * An array containing all of the FX Controllers that
         * have been added to this FX Component.
         *
         * @name Phaser.GameObjects.Components.FX#list
         * @type {Phaser.FX.Controller[]}
         * @since 3.60.0
         */
        this.list = [];

        /**
         * The amount of extra padding to be applied to this Game Object
         * when it is being rendered by a PreFX or SpriteFX Pipeline.
         *
         * Lots of FX require additional spacing added to the texture the
         * Game Object uses, for example a glow or shadow effect, and this
         * method allows you to control how much extra padding is included
         * in addition to the texture size.
         *
         * @name Phaser.GameObjects.Components.FX#padding
         * @type {number}
         * @default 0
         * @since 3.60.0
         */
        this.padding = 0;
    },

    /**
     * Sets the amount of extra padding to be applied to this Game Object
     * when it is being rendered by a PreFX Pipeline.
     *
     * Lots of FX require additional spacing added to the texture the
     * Game Object uses, for example a glow or shadow effect, and this
     * method allows you to control how much extra padding is included
     * in addition to the texture size.
     *
     * @method Phaser.GameObjects.Components.FX#setPadding
     * @webglOnly
     * @since 3.60.0
     *
     * @param {number} [padding=0] - The amount of padding to add to this Game Object.
     *
     * @return {this} This Game Object instance.
     */
    setPadding: function (padding)
    {
        if (padding === undefined) { padding = 0; }

        this.padding = padding;

        return this.gameObject;
    },

    /**
     * This callback is invoked when this Game Object is copied by a PreFX Pipeline.
     *
     * This happens when the pipeline uses its `copySprite` method.
     *
     * It's invoked prior to the copy, allowing you to set shader uniforms, etc on the pipeline.
     *
     * @method Phaser.GameObjects.Components.FX#onFXCopy
     * @since 3.60.0
     *
     * @param {Phaser.Renderer.WebGL.Pipelines.PreFXPipeline} pipeline - The PreFX Pipeline that invoked this callback.
     */
    onFXCopy: function ()
    {
    },

    /**
     * This callback is invoked when this Game Object is rendered by a PreFX Pipeline.
     *
     * This happens when the pipeline uses its `drawSprite` method.
     *
     * It's invoked prior to the draw, allowing you to set shader uniforms, etc on the pipeline.
     *
     * @method Phaser.GameObjects.Components.FX#onFX
     * @since 3.60.0
     *
     * @param {Phaser.Renderer.WebGL.Pipelines.PreFXPipeline} pipeline - The PreFX Pipeline that invoked this callback.
     */
    onFX: function ()
    {
    },

    /**
     * Enables this FX Component and applies the FXPipeline to the parent Game Object.
     *
     * This is called automatically whenever you call a method such as `addBloom`, etc.
     *
     * You can check the `enabled` property to see if the Game Object is already enabled, or not.
     *
     * @method Phaser.GameObjects.Components.FX#enable
     * @since 3.60.0
     *
     * @param {number} [padding=0] - The amount of padding to add to this Game Object.
     */
    enable: function (padding)
    {
        var renderer = this.gameObject.scene.sys.renderer;

        if (renderer && renderer.pipelines)
        {
            this.gameObject.pipeline = renderer.pipelines.FX_PIPELINE;

            if (padding !== undefined)
            {
                this.padding = padding;
            }

            this.enabled = true;
        }
        else
        {
            this.enabled = false;
        }
    },

    /**
     * Destroys and removes all FX Controllers that are part of this FX Component,
     * then disables it.
     *
     * @method Phaser.GameObjects.Components.FX#clear
     * @since 3.60.0
     */
    clear: function ()
    {
        var list = this.list;

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

        this.list = [];

        this.enabled = false;
    },

    /**
     * Searches for the given FX Controler within this FX Component.
     *
     * If found, the controller is removed from this compoent and then destroyed.
     *
     * @method Phaser.GameObjects.Components.FX#remove
     * @since 3.60.0
     *
     * @param {Phaser.FX.Controller} fx - The FX Controller to remove from this FX Component.
     */
    remove: function (fx)
    {
        var list = this.list;

        for (var i = 0; i < list.length; i++)
        {
            if (list[i] === fx)
            {
                SpliceOne(list, i);

                fx.destroy();
            }
        }
    },

    /**
     * Disables this FX Component.
     *
     * This will reset the pipeline on the Game Object that owns this component back to its
     * default and flag this component as disabled.
     *
     * You can re-enable it again by calling `enable`.
     *
     * Optionally, set `clear` to destroy all current FX Controllers.
     *
     * @method Phaser.GameObjects.Components.FX#disable
     * @since 3.60.0
     *
     * @param {boolean} [clear=false] - Destroy and remove all FX Controllers that are part of this FX Component.
     */
    disable: function (clear)
    {
        if (clear === undefined) { clear = false; }

        this.gameObject.resetPipeline();

        this.enabled = false;

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

    /**
     * Adds the given FX Controler to this FX Component.
     *
     * Note that adding an FX Controller does not remove any existing FX. They all stack-up
     * on-top of each other. If you don't want this, make sure to call either `remove` or
     * `clear` first.
     *
     * @method Phaser.GameObjects.Components.FX#add
     * @since 3.60.0
     *
     * @param {Phaser.FX.Controller} fx - The FX Controller to add to this FX Component.
     *
     * @return {Phaser.FX.Controller} The FX Controller.
     */
    add: function (fx)
    {
        if (this.isPost)
        {
            var type = String(fx.type);

            this.gameObject.setPostPipeline(type);

            var pipeline = this.gameObject.getPostPipeline(type);

            if (pipeline)
            {
                if (Array.isArray(pipeline))
                {
                    pipeline = pipeline.pop();
                }

                pipeline.controller = fx;

                return fx;
            }
        }
        else
        {
            if (!this.enabled)
            {
                this.enable();
            }

            this.list.push(fx);

            return fx;
        }
    },

    /**
     * Adds a Glow effect.
     *
     * @method Phaser.GameObjects.Components.FX#addGlow
     * @since 3.60.0
     *
     * @param {number} [color=0xffffff] - The color of the glow effect as a number value.
     * @param {number} [outerStrength=4] - The strength of the glow outward from the edge of the Sprite.
     * @param {number} [innerStrength=0] - The strength of the glow inward from the edge of the Sprite.
     * @param {boolean} [knockout=false] - If `true` only the glow is drawn, not the texture itself.
     *
     * @return {Phaser.FX.Glow} The Glow FX Controller.
     */
    addGlow: function (color, outerStrength, innerStrength, knockout)
    {
        return this.add(new Effects.Glow(this.gameObject, color, outerStrength, innerStrength, knockout));
    },

    /**
     * Adds a Shadow effect.
     *
     * @method Phaser.GameObjects.Components.FX#addShadow
     * @since 3.60.0
     *
     * @param {number} [x=0] - The horizontal offset of the shadow effect.
     * @param {number} [y=0] - The vertical offset of the shadow effect.
     * @param {number} [decay=0.1] - The amount of decay for shadow effect.
     * @param {number} [power=1] - The power of the shadow effect.
     * @param {number} [color=0x000000] - The color of the shadow.
     * @param {number} [samples=6] - The number of samples that the shadow effect will run for. An integer between 1 and 12.
     * @param {number} [intensity=1] - The intensity of the shadow effect.
     *
     * @return {Phaser.FX.Shadow} The Shadow FX Controller.
     */
    addShadow: function (x, y, decay, power, color, samples, intensity)
    {
        return this.add(new Effects.Shadow(this.gameObject, x, y, decay, power, color, samples, intensity));
    },

    /**
     * Adds a Pixelate effect.
     *
     * @method Phaser.GameObjects.Components.FX#addPixelate
     * @since 3.60.0
     *
     * @param {number} [amount=1] - The amount of pixelation to apply.
     *
     * @return {Phaser.FX.Pixelate} The Pixelate FX Controller.
     */
    addPixelate: function (amount)
    {
        return this.add(new Effects.Pixelate(this.gameObject, amount));
    },

    /**
     * Adds a Vignette effect.
     *
     * @method Phaser.GameObjects.Components.FX#addVignette
     * @since 3.60.0
     *
     * @param {number} [x=0.5] - The horizontal offset of the vignette effect. This value is normalized to the range 0 to 1.
     * @param {number} [y=0.5] - The vertical offset of the vignette effect. This value is normalized to the range 0 to 1.
     * @param {number} [radius=0.5] - The radius of the vignette effect. This value is normalized to the range 0 to 1.
     * @param {number} [strength=0.5] - The strength of the vignette effect.
     *
     * @return {Phaser.FX.Vignette} The Vignette FX Controller.
     */
    addVignette: function (x, y, radius, strength)
    {
        return this.add(new Effects.Vignette(this.gameObject, x, y, radius, strength));
    },

    /**
     * Adds a Shine effect.
     *
     * @method Phaser.GameObjects.Components.FX#addShine
     * @since 3.60.0
     *
     * @param {number} [speed=0.5] - The speed of the Shine effect.
     * @param {number} [lineWidth=0.5] - The line width of the Shine effect.
     * @param {number} [gradient=3] - The gradient of the Shine effect.
     * @param {boolean} [reveal=false] - Does this Shine effect reveal or get added to its target?
     *
     * @return {Phaser.FX.Shine} The Shine FX Controller.
     */
    addShine: function (speed, lineWidth, gradient, reveal)
    {
        return this.add(new Effects.Shine(this.gameObject, speed, lineWidth, gradient, reveal));
    },

    /**
     * Adds a Blur effect.
     *
     * @method Phaser.GameObjects.Components.FX#addBlur
     * @since 3.60.0
     *
     * @param {number} [quality=0] - The quality of the blur effect. Can be either 0 for Low Quality, 1 for Medium Quality or 2 for High Quality.
     * @param {number} [x=2] - The horizontal offset of the blur effect.
     * @param {number} [y=2] - The vertical offset of the blur effect.
     * @param {number} [strength=1] - The strength of the blur effect.
     * @param {number} [color=0xffffff] - The color of the blur, as a hex value.
     * @param {number} [steps=4] - The number of steps to run the blur effect for. This value should always be an integer.
     *
     * @return {Phaser.FX.Blur} The Blur FX Controller.
     */
    addBlur: function (quality, x, y, strength, color, steps)
    {
        return this.add(new Effects.Blur(this.gameObject, quality, x, y, strength, color, steps));
    },

    /**
     * Adds a Gradient effect.
     *
     * @method Phaser.GameObjects.Components.FX#addGradient
     * @since 3.60.0
     *
     * @param {number} [color1=0xff0000] - The first gradient color, given as a number value.
     * @param {number} [color2=0x00ff00] - The second gradient color, given as a number value.
     * @param {number} [alpha=0.2] - The alpha value of the gradient effect.
     * @param {number} [fromX=0] - The horizontal position the gradient will start from. This value is noralized, between 0 and 1 and is not in pixels.
     * @param {number} [fromY=0] - The vertical position the gradient will start from. This value is noralized, between 0 and 1 and is not in pixels.
     * @param {number} [toX=0] - The horizontal position the gradient will end at. This value is noralized, between 0 and 1 and is not in pixels.
     * @param {number} [toY=1] - The vertical position the gradient will end at. This value is noralized, between 0 and 1 and is not in pixels.
     * @param {number} [size=0] - How many 'chunks' the gradient is divided in to, as spread over the entire height of the texture. Leave this at zero for a smooth gradient, or set higher for a more retro chunky effect.
     *
     * @return {Phaser.FX.Gradient} The Gradient FX Controller.
     */
    addGradient: function (color1, color2, alpha, fromX, fromY, toX, toY, size)
    {
        return this.add(new Effects.Gradient(this.gameObject, color1, color2, alpha, fromX, fromY, toX, toY, size));
    },

    /**
     * Adds a Bloom effect.
     *
     * @method Phaser.GameObjects.Components.FX#addBloom
     * @since 3.60.0
     *
     * @param {number} [color] - The color of the Bloom, as a hex value.
     * @param {number} [offsetX=1] - The horizontal offset of the bloom effect.
     * @param {number} [offsetY=1] - The vertical offset of the bloom effect.
     * @param {number} [blurStrength=1] - The strength of the blur process of the bloom effect.
     * @param {number} [strength=1] - The strength of the blend process of the bloom effect.
     * @param {number} [steps=4] - The number of steps to run the Bloom effect for. This value should always be an integer.
     *
     * @return {Phaser.FX.Bloom} The Bloom FX Controller.
     */
    addBloom: function (color, offsetX, offsetY, blurStrength, strength, steps)
    {
        return this.add(new Effects.Bloom(this.gameObject, color, offsetX, offsetY, blurStrength, strength, steps));
    },

    /**
     * Adds a ColorMatrix effect.
     *
     * @method Phaser.GameObjects.Components.FX#addColorMatrix
     * @since 3.60.0
     *
     * @return {Phaser.FX.ColorMatrix} The ColorMatrix FX Controller.
     */
    addColorMatrix: function ()
    {
        return this.add(new Effects.ColorMatrix(this.gameObject));
    },

    /**
     * Adds a Circle effect.
     *
     * @method Phaser.GameObjects.Components.FX#addCircle
     * @since 3.60.0
     *
     * @param {number} [thickness=8] - The width of the circle around the texture, in pixels.
     * @param {number} [color=16724914] - The color of the circular ring, given as a number value.
     * @param {number} [backgroundColor=0xff0000] - The color of the background, behind the texture, given as a number value.
     * @param {number} [scale=1] - The scale of the circle. The default scale is 1, which is a circle the full size of the underlying texture.
     * @param {number} [feather=0.005] - The amount of feathering to apply to the circle from the ring.
     *
     * @return {Phaser.FX.Circle} The Circle FX Controller.
     */
    addCircle: function (thickness, color, backgroundColor, scale, feather)
    {
        return this.add(new Effects.Circle(this.gameObject, thickness, color, backgroundColor, scale, feather));
    },

    /**
     * Adds a Barrel effect.
     *
     * @method Phaser.GameObjects.Components.FX#addBarrel
     * @since 3.60.0
     *
     * @param {number} [amount=1] - The amount of distortion applied to the barrel effect. A value of 1 is no distortion. Typically keep this within +- 1.
     *
     * @return {Phaser.FX.Barrel} The Barrel FX Controller.
     */
    addBarrel: function (amount)
    {
        return this.add(new Effects.Barrel(this.gameObject, amount));
    },

    /**
     * Adds a Displacement effect.
     *
     * @method Phaser.GameObjects.Components.FX#addDisplacement
     * @since 3.60.0
     *
     * @param {string} [key='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager.
     * @param {number} [x=0.005] - The amount of horizontal displacement to apply.
     * @param {number} [y=0.005] - The amount of vertical displacement to apply.
     *
     * @return {Phaser.FX.Displacement} The Displacement FX Controller.
     */
    addDisplacement: function (displacementTexture, x, y)
    {
        return this.add(new Effects.Displacement(this.gameObject, displacementTexture, x, y));
    },

    /**
     * Adds a Wipe effect.
     *
     * @method Phaser.GameObjects.Components.FX#addWipe
     * @since 3.60.0
     *
     * @param {number} [wipeWidth=0.1] - The width of the wipe effect. This value is normalized in the range 0 to 1.
     * @param {number} [direction=0] - The direction of the wipe effect. Either 0 or 1. Set in conjunction with the axis property.
     * @param {number} [axis=0] - The axis of the wipe effect. Either 0 or 1. Set in conjunction with the direction property.
     *
     * @return {Phaser.FX.Wipe} The Wipe FX Controller.
     */
    addWipe: function (wipeWidth, direction, axis)
    {
        return this.add(new Effects.Wipe(this.gameObject, wipeWidth, direction, axis));
    },

    /**
     * Adds a Reveal Wipe effect.
     *
     * @method Phaser.GameObjects.Components.FX#addReveal
     * @since 3.60.0
     *
     * @param {number} [wipeWidth=0.1] - The width of the wipe effect. This value is normalized in the range 0 to 1.
     * @param {number} [direction=0] - The direction of the wipe effect. Either 0 or 1. Set in conjunction with the axis property.
     * @param {number} [axis=0] - The axis of the wipe effect. Either 0 or 1. Set in conjunction with the direction property.
     *
     * @return {Phaser.FX.Wipe} The Wipe FX Controller.
     */
    addReveal: function (wipeWidth, direction, axis)
    {
        return this.add(new Effects.Wipe(this.gameObject, wipeWidth, direction, axis, true));
    },

    /**
     * Adds a Bokeh effect.
     *
     * @method Phaser.GameObjects.Components.FX#addBokeh
     * @since 3.60.0
     *
     * @param {number} [radius=0.5] - The radius of the bokeh effect.
     * @param {number} [amount=1] - The amount of the bokeh effect.
     * @param {number} [contrast=0.2] - The color contrast of the bokeh effect.
     *
     * @return {Phaser.FX.Bokeh} The Bokeh FX Controller.
     */
    addBokeh: function (radius, amount, contrast)
    {
        return this.add(new Effects.Bokeh(this.gameObject, radius, amount, contrast));
    },

    /**
     * Adds a TiltShift effect.
     *
     * @method Phaser.GameObjects.Components.FX#addTiltShift
     * @since 3.60.0
     *
     * @param {number} [radius=0.5] - The radius of the bokeh effect.
     * @param {number} [amount=1] - The amount of the bokeh effect.
     * @param {number} [contrast=0.2] - The color contrast of the bokeh effect.
     * @param {number} [blurX=1] - If Tilt Shift, the amount of horizontal blur.
     * @param {number} [blurY=1] - If Tilt Shift, the amount of vertical blur.
     * @param {number} [strength=1] - If Tilt Shift, the strength of the blur.
     *
     * @return {Phaser.FX.Bokeh} The Bokeh TiltShift FX Controller.
     */
    addTiltShift: function (radius, amount, contrast, blurX, blurY, strength)
    {
        return this.add(new Effects.Bokeh(this.gameObject, radius, amount, contrast, true, blurX, blurY, strength));
    },

    /**
     * Destroys this FX Component.
     *
     * Called automatically when Game Objects are destroyed.
     *
     * @method Phaser.GameObjects.Components.FX#destroy
     * @since 3.60.0
     */
    destroy: function ()
    {
        this.clear();

        this.gameObject = null;
    }

});

module.exports = FX;


/**
 * @author       Florian Vazelle
 * @author       Geoffrey Glaive
 * @copyright    2013-2023 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var GetLineToRectangle = require('./GetLineToRectangle');
var RectangleToRectangle = require('./RectangleToRectangle');

/**
 * Checks if two Rectangles intersect and returns the intersection points as a Point object array.
 *
 * A Rectangle intersects another Rectangle if any part of its bounds is within the other Rectangle's bounds. As such, the two Rectangles are considered "solid". A Rectangle with no width or no height will never intersect another Rectangle.
 *
 * @function Phaser.Geom.Intersects.GetRectangleToRectangle
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection.
 * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection.
 * @param {array} [out] - An optional array in which to store the points of intersection.
 *
 * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array.
 */
var GetRectangleToRectangle = function (rectA, rectB, out)
{
    if (out === undefined) { out = []; }

    if (RectangleToRectangle(rectA, rectB))
    {
        var lineA = rectA.getLineA();
        var lineB = rectA.getLineB();
        var lineC = rectA.getLineC();
        var lineD = rectA.getLineD();

        GetLineToRectangle(lineA, rectB, out);
        GetLineToRectangle(lineB, rectB, out);
        GetLineToRectangle(lineC, rectB, out);
        GetLineToRectangle(lineD, rectB, out);
    }

    return out;
};

module.exports = GetRectangleToRectangle;


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

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

/**
 * @callback EachMapCallback<E>
 *
 * @param {string} key - The key of the Map entry.
 * @param {E} entry - The value of the Map entry.
 *
 * @return {?boolean} The callback result.
 */

/**
 * @classdesc
 * The keys of a Map can be arbitrary values.
 *
 * ```javascript
 * var map = new Map([
 *    [ 1, 'one' ],
 *    [ 2, 'two' ],
 *    [ 3, 'three' ]
 * ]);
 * ```
 *
 * @class Map
 * @memberof Phaser.Structs
 * @constructor
 * @since 3.0.0
 *
 * @generic K
 * @generic V
 * @genericUse {V[]} - [elements]
 *
 * @param {Array.<*>} elements - An optional array of key-value pairs to populate this Map with.
 */
var Map = new Class({

    initialize:

    function Map (elements)
    {
        /**
         * The entries in this Map.
         *
         * @genericUse {Object.<string, V>} - [$type]
         *
         * @name Phaser.Structs.Map#entries
         * @type {Object.<string, *>}
         * @default {}
         * @since 3.0.0
         */
        this.entries = {};

        /**
         * The number of key / value pairs in this Map.
         *
         * @name Phaser.Structs.Map#size
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.size = 0;

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

    /**
     * Adds an element with a specified `key` and `value` to this Map.
     * If the `key` already exists, the value will be replaced.
     *
     * @method Phaser.Structs.Map#set
     * @since 3.0.0
     *
     * @genericUse {K} - [key]
     * @genericUse {V} - [value]
     * @genericUse {Phaser.Structs.Map.<K, V>} - [$return]
     *
     * @param {string} key - The key of the element to be added to this Map.
     * @param {*} value - The value of the element to be added to this Map.
     *
     * @return {Phaser.Structs.Map} This Map object.
     */
    set: function (key, value)
    {
        if (!this.has(key))
        {
            this.size++;
        }

        this.entries[key] = value;

        return this;
    },

    /**
     * Returns the value associated to the `key`, or `undefined` if there is none.
     *
     * @method Phaser.Structs.Map#get
     * @since 3.0.0
     *
     * @genericUse {K} - [key]
     * @genericUse {V} - [$return]
     *
     * @param {string} key - The key of the element to return from the `Map` object.
     *
     * @return {*} The element associated with the specified key or `undefined` if the key can't be found in this Map object.
     */
    get: function (key)
    {
        if (this.has(key))
        {
            return this.entries[key];
        }
    },

    /**
     * Returns an `Array` of all the values stored in this Map.
     *
     * @method Phaser.Structs.Map#getArray
     * @since 3.0.0
     *
     * @genericUse {V[]} - [$return]
     *
     * @return {Array.<*>} An array of the values stored in this Map.
     */
    getArray: function ()
    {
        var output = [];
        var entries = this.entries;

        for (var key in entries)
        {
            output.push(entries[key]);
        }

        return output;
    },

    /**
     * Returns a boolean indicating whether an element with the specified key exists or not.
     *
     * @method Phaser.Structs.Map#has
     * @since 3.0.0
     *
     * @genericUse {K} - [key]
     *
     * @param {string} key - The key of the element to test for presence of in this Map.
     *
     * @return {boolean} Returns `true` if an element with the specified key exists in this Map, otherwise `false`.
     */
    has: function (key)
    {
        return (this.entries.hasOwnProperty(key));
    },

    /**
     * Delete the specified element from this Map.
     *
     * @method Phaser.Structs.Map#delete
     * @since 3.0.0
     *
     * @genericUse {K} - [key]
     * @genericUse {Phaser.Structs.Map.<K, V>} - [$return]
     *
     * @param {string} key - The key of the element to delete from this Map.
     *
     * @return {Phaser.Structs.Map} This Map object.
     */
    delete: function (key)
    {
        if (this.has(key))
        {
            delete this.entries[key];
            this.size--;
        }

        return this;
    },

    /**
     * Delete all entries from this Map.
     *
     * @method Phaser.Structs.Map#clear
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Map.<K, V>} - [$return]
     *
     * @return {Phaser.Structs.Map} This Map object.
     */
    clear: function ()
    {
        Object.keys(this.entries).forEach(function (prop)
        {
            delete this.entries[prop];

        }, this);

        this.size = 0;

        return this;
    },

    /**
     * Returns all entries keys in this Map.
     *
     * @method Phaser.Structs.Map#keys
     * @since 3.0.0
     *
     * @genericUse {K[]} - [$return]
     *
     * @return {string[]} Array containing entries' keys.
     */
    keys: function ()
    {
        return Object.keys(this.entries);
    },

    /**
     * Returns an `Array` of all entries.
     *
     * @method Phaser.Structs.Map#values
     * @since 3.0.0
     *
     * @genericUse {V[]} - [$return]
     *
     * @return {Array.<*>} An `Array` of entries.
     */
    values: function ()
    {
        var output = [];
        var entries = this.entries;

        for (var key in entries)
        {
            output.push(entries[key]);
        }

        return output;
    },

    /**
     * Dumps the contents of this Map to the console via `console.group`.
     *
     * @method Phaser.Structs.Map#dump
     * @since 3.0.0
     */
    dump: function ()
    {
        var entries = this.entries;

        // eslint-disable-next-line no-console
        console.group('Map');

        for (var key in entries)
        {
            console.log(key, entries[key]);
        }

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

    /**
     * Iterates through all entries in this Map, passing each one to the given callback.
     *
     * If the callback returns `false`, the iteration will break.
     *
     * @method Phaser.Structs.Map#each
     * @since 3.0.0
     *
     * @genericUse {EachMapCallback.<V>} - [callback]
     * @genericUse {Phaser.Structs.Map.<K, V>} - [$return]
     *
     * @param {EachMapCallback} callback - The callback which will receive the keys and entries held in this Map.
     *
     * @return {Phaser.Structs.Map} This Map object.
     */
    each: function (callback)
    {
        var entries = this.entries;

        for (var key in entries)
        {
            if (callback(key, entries[key]) === false)
            {
                break;
            }
        }

        return this;
    },

    /**
     * Returns `true` if the value exists within this Map. Otherwise, returns `false`.
     *
     * @method Phaser.Structs.Map#contains
     * @since 3.0.0
     *
     * @genericUse {V} - [value]
     *
     * @param {*} value - The value to search for.
     *
     * @return {boolean} `true` if the value is found, otherwise `false`.
     */
    contains: function (value)
    {
        var entries = this.entries;

        for (var key in entries)
        {
            if (entries[key] === value)
            {
                return true;
            }
        }

        return false;
    },

    /**
     * Merges all new keys from the given Map into this one.
     * If it encounters a key that already exists it will be skipped unless override is set to `true`.
     *
     * @method Phaser.Structs.Map#merge
     * @since 3.0.0
     *
     * @genericUse {Phaser.Structs.Map.<K, V>} - [map,$return]
     *
     * @param {Phaser.Structs.Map} map - The Map to merge in to this Map.
     * @param {boolean} [override=false] - Set to `true` to replace values in this Map with those from the source map, or `false` to skip them.
     *
     * @return {Phaser.Structs.Map} This Map object.
     */
    merge: function (map, override)
    {
        if (override === undefined) { override = false; }

        var local = this.entries;
        var source = map.entries;

        for (var key in source)
        {
            if (local.hasOwnProperty(key) && override)
            {
                local[key] = source[key];
            }
            else
            {
                this.set(key, source[key]);
            }
        }

        return this;
    }

});

module.exports = Map;


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

var Point = require('../point/Point');

/**
 * Returns a uniformly distributed random point from anywhere within the given Circle.
 *
 * @function Phaser.Geom.Circle.Random
 * @since 3.0.0
 *
 * @generic {Phaser.Geom.Point} O - [out,$return]
 *
 * @param {Phaser.Geom.Circle} circle - The Circle to get a random point from.
 * @param {(Phaser.Geom.Point|object)} [out] - A Point or point-like object to set the random `x` and `y` values in.
 *
 * @return {(Phaser.Geom.Point|object)} A Point object with the random values set in the `x` and `y` properties.
 */
var Random = function (circle, out)
{
    if (out === undefined) { out = new Point(); }

    var t = 2 * Math.PI * Math.random();
    var u = Math.random() + Math.random();
    var r = (u > 1) ? 2 - u : u;
    var x = r * Math.cos(t);
    var y = r * Math.sin(t);

    out.x = circle.x + (x * circle.radius);
    out.y = circle.y + (y * circle.radius);

    return out;
};

module.exports = Random;


* @param {Phaser.FX.Controller} fx - The FX Controller to add to this FX Component.

* @return {Phaser.FX.Controller} The FX Controller.

* @param {object} [config] - Optional configuration object that is passed to the pipeline during instantiation.


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

//  This singleton is instantiated as soon as Phaser loads,
//  before a Phaser.Game instance has even been created.
//  Which means all instances of Phaser Games can share it,
//  without having to re-poll the device all over again

/**
 * @namespace Phaser.Device
 * @since 3.0.0
 */

/**
 * @typedef {object} Phaser.DeviceConf
 *
 * @property {Phaser.Device.OS} os - The OS Device functions.
 * @property {Phaser.Device.Browser} browser - The Browser Device functions.
 * @property {Phaser.Device.Features} features - The Features Device functions.
 * @property {Phaser.Device.Input} input - The Input Device functions.
 * @property {Phaser.Device.Audio} audio - The Audio Device functions.
 * @property {Phaser.Device.Video} video - The Video Device functions.
 * @property {Phaser.Device.Fullscreen} fullscreen - The Fullscreen Device functions.
 * @property {Phaser.Device.CanvasFeatures} canvasFeatures - The Canvas Device functions.
 */

module.exports = {

    os: require('./OS'),
    browser: require('./Browser'),
    features: require('./Features'),
    input: require('./Input'),
    audio: require('./Audio'),
    video: require('./Video'),
    fullscreen: require('./Fullscreen'),
    canvasFeatures: require('./CanvasFeatures')

};


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

var DeepCopy = require('../../utils/object/DeepCopy');
var FX = require('../components/FX');
var SpliceOne = require('../../utils/array/SpliceOne');

/**
 * Provides methods used for setting the WebGL rendering post pipeline of a Game Object.
 *
 * @namespace Phaser.GameObjects.Components.PostPipeline
 * @webglOnly
 * @since 3.60.0
 */

var PostPipeline = {

    /**
     * Does this Game Object have any Post Pipelines set?
     *
     * @name Phaser.GameObjects.Components.PostPipeline#hasPostPipeline
     * @type {boolean}
     * @webglOnly
     * @since 3.60.0
     */
    hasPostPipeline: false,

    /**
     * The WebGL Post FX Pipelines this Game Object uses for post-render effects.
     *
     * The pipelines are processed in the order in which they appear in this array.
     *
     * If you modify this array directly, be sure to set the
     * `hasPostPipeline` property accordingly.
     *
     * @name Phaser.GameObjects.Components.PostPipeline#postPipelines
     * @type {Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[]}
     * @webglOnly
     * @since 3.60.0
     */
    postPipelines: null,

    /**
     * An object to store pipeline specific data in, to be read by the pipelines this Game Object uses.
     *
     * @name Phaser.GameObjects.Components.PostPipeline#postPipelineData
     * @type {object}
     * @webglOnly
     * @since 3.60.0
     */
    postPipelineData: null,

    /**
     * The Pre FX component of this Game Object.
     *
     * This component allows you to apply a variety of built-in effects to this Game Object, such
     * as glow, blur, bloom, displacements, vignettes and more. You access them via this property,
     * for example:
     *
     * ```js
     * const player = this.add.sprite();
     * player.preFX.addBloom();
     * ```
     *
     * Only the following Game Objects support Pre FX:
     *
     * * Image
     * * Sprite
     * * TileSprite
     * * Text
     * * RenderTexture
     * * Video
     *
     * All FX are WebGL only and do not have Canvas counterparts.
     *
     * Please see the FX Class for more details and available methods.
     *
     * @name Phaser.GameObjects.Components.PostPipeline#preFX
     * @type {Phaser.GameObjects.Components.FX}
     * @webglOnly
     * @since 3.60.0
     */
    preFX: null,

    /**
     * The Post FX component of this Game Object.
     *
     * This component allows you to apply a variety of built-in effects to this Game Object, such
     * as glow, blur, bloom, displacements, vignettes and more. You access them via this property,
     * for example:
     *
     * ```js
     * const player = this.add.sprite();
     * player.postFX.addBloom();
     * ```
     *
     * All FX are WebGL only and do not have Canvas counterparts.
     *
     * Please see the FX Class for more details and available methods.
     *
     * @name Phaser.GameObjects.Components.PostPipeline#postFX
     * @type {Phaser.GameObjects.Components.FX}
     * @webglOnly
     * @since 3.60.0
     */
    postFX: null,

    /**
     * This should only be called during the instantiation of the Game Object.
     *
     * It is called by default by all core Game Objects and doesn't need
     * calling again.
     *
     * After that, use `setPostPipeline`.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#initPostPipeline
     * @webglOnly
     * @since 3.60.0
     *
     * @param {boolean} [preFX=false] - Does this Game Object support Pre FX?
     */
    initPostPipeline: function (preFX)
    {
        this.postPipelines = [];
        this.postPipelineData = {};

        this.postFX = new FX(this, true);

        if (preFX)
        {
            this.preFX = new FX(this, false);
        }
    },

    /**
     * Sets one, or more, Post Pipelines on this Game Object.
     *
     * Post Pipelines are invoked after this Game Object has rendered to its target and
     * are commonly used for post-fx.
     *
     * The post pipelines are appended to the `postPipelines` array belonging to this
     * Game Object. When the renderer processes this Game Object, it iterates through the post
     * pipelines in the order in which they appear in the array. If you are stacking together
     * multiple effects, be aware that the order is important.
     *
     * If you call this method multiple times, the new pipelines will be appended to any existing
     * post pipelines already set. Use the `resetPostPipeline` method to clear them first, if required.
     *
     * You can optionally also set the `postPipelineData` property, if the parameter is given.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#setPostPipeline
     * @webglOnly
     * @since 3.60.0
     *
     * @param {(string|string[]|function|function[]|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[])} pipelines - Either the string-based name of the pipeline, or a pipeline instance, or class, or an array of them.
     * @param {object} [pipelineData] - Optional pipeline data object that is set in to the `postPipelineData` property of this Game Object.
     * @param {boolean} [copyData=true] - Should the pipeline data object be _deep copied_ into the `postPipelineData` property of this Game Object? If `false` it will be set by reference instead.
     *
     * @return {this} This Game Object instance.
     */
    setPostPipeline: function (pipelines, pipelineData, copyData)
    {
        var renderer = this.scene.sys.renderer;

        if (!renderer)
        {
            return this;
        }

        var pipelineManager = renderer.pipelines;

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

            for (var i = 0; i < pipelines.length; i++)
            {
                var instance = pipelineManager.getPostPipeline(pipelines[i], this);

                if (instance)
                {
                    this.postPipelines.push(instance);
                }
            }

            if (pipelineData)
            {
                this.postPipelineData = (copyData) ? DeepCopy(pipelineData) : pipelineData;
            }
        }

        this.hasPostPipeline = (this.postPipelines.length > 0);

        return this;
    },

    /**
     * Adds an entry to the `postPipelineData` object belonging to this Game Object.
     *
     * If the 'key' already exists, its value is updated. If it doesn't exist, it is created.
     *
     * If `value` is undefined, and `key` exists, `key` is removed from the data object.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#setPostPipelineData
     * @webglOnly
     * @since 3.60.0
     *
     * @param {string} key - The key of the pipeline data to set, update, or delete.
     * @param {any} [value] - The value to be set with the key. If `undefined` then `key` will be deleted from the object.
     *
     * @return {this} This Game Object instance.
     */
    setPostPipelineData: function (key, value)
    {
        var data = this.postPipelineData;

        if (value === undefined)
        {
            delete data[key];
        }
        else
        {
            data[key] = value;
        }

        return this;
    },

    /**
     * Gets a Post Pipeline instance from this Game Object, based on the given name, and returns it.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#getPostPipeline
     * @webglOnly
     * @since 3.60.0
     *
     * @param {(string|function|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline)} pipeline - The string-based name of the pipeline, or a pipeline class.
     *
     * @return {(Phaser.Renderer.WebGL.Pipelines.PostFXPipeline|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[])} An array of all the Post Pipelines matching the name. This array will be empty if there was no match. If there was only one single match, that pipeline is returned directly, not in an array.
     */
    getPostPipeline: function (pipeline)
    {
        var isString = (typeof pipeline === 'string');

        var pipelines = this.postPipelines;

        var results = [];

        for (var i = 0; i < pipelines.length; i++)
        {
            var instance = pipelines[i];

            if ((isString && instance.name === pipeline) || (!isString && instance instanceof pipeline))
            {
                results.push(instance);
            }
        }

        return (results.length === 1) ? results[0] : results;
    },

    /**
     * Resets the WebGL Post Pipelines of this Game Object. It does this by calling
     * the `destroy` method on each post pipeline and then clearing the local array.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#resetPostPipeline
     * @webglOnly
     * @since 3.60.0
     *
     * @param {boolean} [resetData=false] - Reset the `postPipelineData` object to being an empty object?
     */
    resetPostPipeline: function (resetData)
    {
        if (resetData === undefined) { resetData = false; }

        var pipelines = this.postPipelines;

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

        this.postPipelines = [];
        this.hasPostPipeline = false;

        if (resetData)
        {
            this.postPipelineData = {};
        }
    },

    /**
     * Removes a type of Post Pipeline instances from this Game Object, based on the given name, and destroys them.
     *
     * If you wish to remove all Post Pipelines use the `resetPostPipeline` method instead.
     *
     * @method Phaser.GameObjects.Components.PostPipeline#removePostPipeline
     * @webglOnly
     * @since 3.60.0
     *
     * @param {string|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline} pipeline - The string-based name of the pipeline, or a pipeline class.
     *
     * @return {this} This Game Object.
     */
    removePostPipeline: function (pipeline)
    {
        var pipelines = this.postPipelines;

        for (var i = pipelines.length - 1; i >= 0; i--)
        {
            var instance = pipelines[i];

            if (
                (typeof pipeline === 'string' && instance.name === pipeline) ||
                (typeof pipeline !== 'string' && instance instanceof pipeline))
            {
                instance.destroy();

                SpliceOne(pipelines, i);
            }
        }

        this.hasPostPipeline = (this.postPipelines.length > 0);

        return this;
    }

};

module.exports = PostPipeline;


/**
 * @typedef {object} Phaser.Types.Loader.FileTypes.BitmapFontFileConfig
 *
 * @property {string} key - The key of the file. Must be unique within both the Loader and the Texture Manager.
 * @property {string} [textureURL] - The absolute or relative URL to load the texture image file from.
 * @property {string} [textureExtension='png'] - The default file extension to use for the image texture if no url is provided.
 * @property {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - Extra XHR Settings specifically for the texture image file.
 * @property {string} [normalMap] - The filename of an associated normal map. It uses the same path and url to load as the texture image.
 * @property {string} [fontDataURL] - The absolute or relative URL to load the font data xml file from.
 * @property {string} [fontDataExtension='xml'] - The default file extension to use for the font data xml if no url is provided.
 * @property {Phaser.Types.Loader.XHRSettingsObject} [fontDataXhrSettings] - Extra XHR Settings specifically for the font data xml file.
 */


keep keep keep replace keep keep keep keep keep


#define SHADER_NAME DISPLACEMENT_FS

precision mediump float;

uniform sampler2D uMainSampler;
uniform sampler2D uDisplacementSampler;

uniform vec2 amount;

varying vec2 outTexCoord;

void main ()
{
    vec2 disp = (-vec2(0.5, 0.5) + texture2D(uDisplacementSampler, outTexCoord).rr) * amount;

    gl_FragColor = texture2D(uMainSampler, outTexCoord + disp).rgba;
}


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

var AnimationState = require('../../animations/AnimationState');
var Clamp = require('../../math/Clamp');
var Class = require('../../utils/Class');
var DegToRad = require('../../math/DegToRad');
var Rectangle = require('../../geom/rectangle/Rectangle');
var RotateAround = require('../../math/RotateAround');
var Vector2 = require('../../math/Vector2');

/**
 * @classdesc
 * A Particle is a simple object owned and controlled by a Particle Emitter.
 *
 * It encapsulates all of the properties required to move and update according
 * to the Emitters operations.
 *
 * @class Particle
 * @memberof Phaser.GameObjects.Particles
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Emitter to which this Particle belongs.
 */
var Particle = new Class({

    initialize:

    function Particle (emitter)
    {
        /**
         * The Emitter to which this Particle belongs.
         *
         * A Particle can only belong to a single Emitter and is created, updated and destroyed by it.
         *
         * @name Phaser.GameObjects.Particles.Particle#emitter
         * @type {Phaser.GameObjects.Particles.ParticleEmitter}
         * @since 3.0.0
         */
        this.emitter = emitter;

        /**
         * The texture used by this Particle when it renders.
         *
         * @name Phaser.GameObjects.Particles.Particle#texture
         * @type {Phaser.Textures.Texture}
         * @default null
         * @since 3.60.0
         */
        this.texture = null;

        /**
         * The texture frame used by this Particle when it renders.
         *
         * @name Phaser.GameObjects.Particles.Particle#frame
         * @type {Phaser.Textures.Frame}
         * @default null
         * @since 3.0.0
         */
        this.frame = null;

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

        /**
         * The y coordinate of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#y
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.y = 0;

        /**
         * The coordinates of this Particle in world space.
         *
         * Updated as part of `computeVelocity`.
         *
         * @name Phaser.GameObjects.Particles.Particle#worldPosition
         * @type {Phaser.Math.Vector2}
         * @since 3.60.0
         */
        this.worldPosition = new Vector2();

        /**
         * The x velocity of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#velocityX
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.velocityX = 0;

        /**
         * The y velocity of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#velocityY
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.velocityY = 0;

        /**
         * The x acceleration of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#accelerationX
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.accelerationX = 0;

        /**
         * The y acceleration of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#accelerationY
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.accelerationY = 0;

        /**
         * The maximum horizontal velocity this Particle can travel at.
         *
         * @name Phaser.GameObjects.Particles.Particle#maxVelocityX
         * @type {number}
         * @default 10000
         * @since 3.0.0
         */
        this.maxVelocityX = 10000;

        /**
         * The maximum vertical velocity this Particle can travel at.
         *
         * @name Phaser.GameObjects.Particles.Particle#maxVelocityY
         * @type {number}
         * @default 10000
         * @since 3.0.0
         */
        this.maxVelocityY = 10000;

        /**
         * The bounciness, or restitution, of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#bounce
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.bounce = 0;

        /**
         * The horizontal scale of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#scaleX
         * @type {number}
         * @default 1
         * @since 3.0.0
         */
        this.scaleX = 1;

        /**
         * The vertical scale of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#scaleY
         * @type {number}
         * @default 1
         * @since 3.0.0
         */
        this.scaleY = 1;

        /**
         * The alpha value of this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#alpha
         * @type {number}
         * @default 1
         * @since 3.0.0
         */
        this.alpha = 1;

        /**
         * The angle of this Particle in degrees.
         *
         * @name Phaser.GameObjects.Particles.Particle#angle
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.angle = 0;

        /**
         * The angle of this Particle in radians.
         *
         * @name Phaser.GameObjects.Particles.Particle#rotation
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.rotation = 0;

        /**
         * The tint applied to this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#tint
         * @type {number}
         * @webglOnly
         * @since 3.0.0
         */
        this.tint = 0xffffff;

        /**
         * The lifespan of this Particle in ms.
         *
         * @name Phaser.GameObjects.Particles.Particle#life
         * @type {number}
         * @default 1000
         * @since 3.0.0
         */
        this.life = 1000;

        /**
         * The current life of this Particle in ms.
         *
         * @name Phaser.GameObjects.Particles.Particle#lifeCurrent
         * @type {number}
         * @default 1000
         * @since 3.0.0
         */
        this.lifeCurrent = 1000;

        /**
         * The delay applied to this Particle upon emission, in ms.
         *
         * @name Phaser.GameObjects.Particles.Particle#delayCurrent
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.delayCurrent = 0;

        /**
         * The hold applied to this Particle before it expires, in ms.
         *
         * @name Phaser.GameObjects.Particles.Particle#holdCurrent
         * @type {number}
         * @default 0
         * @since 3.60.0
         */
        this.holdCurrent = 0;

        /**
         * The normalized lifespan T value, where 0 is the start and 1 is the end.
         *
         * @name Phaser.GameObjects.Particles.Particle#lifeT
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.lifeT = 0;

        /**
         * The data used by the ease equation.
         *
         * @name Phaser.GameObjects.Particles.Particle#data
         * @type {object}
         * @since 3.0.0
         */
        this.data = {
            tint: { min: 0xffffff, max: 0xffffff },
            alpha: { min: 1, max: 1 },
            rotate: { min: 0, max: 0 },
            scaleX: { min: 1, max: 1 },
            scaleY: { min: 1, max: 1 },
            x: { min: 0, max: 0 },
            y: { min: 0, max: 0 },
            accelerationX: { min: 0, max: 0 },
            accelerationY: { min: 0, max: 0 },
            maxVelocityX: { min: 0, max: 0 },
            maxVelocityY: { min: 0, max: 0 },
            moveToX: { min: 0, max: 0 },
            moveToY: { min: 0, max: 0 },
            bounce: { min: 0, max: 0 }
        };

        /**
         * Interal private value.
         *
         * @name Phaser.GameObjects.Particles.Particle#isCropped
         * @type {boolean}
         * @private
         * @readonly
         * @since 3.60.0
         */
        this.isCropped = false;

        /**
         * A reference to the Scene to which this Game Object belongs.
         *
         * Game Objects can only belong to one Scene.
         *
         * You should consider this property as being read-only. You cannot move a
         * Game Object to another Scene by simply changing it.
         *
         * @name Phaser.GameObjects.Particles.Particle#scene
         * @type {Phaser.Scene}
         * @since 3.60.0
         */
        this.scene = emitter.scene;

        /**
         * The Animation State component of this Particle.
         *
         * This component provides features to apply animations to this Particle.
         * It is responsible for playing, loading, queuing animations for later playback,
         * mixing between animations and setting the current animation frame to this Particle.
         *
         * @name Phaser.GameObjects.Particles.Particle#anims
         * @type {Phaser.Animations.AnimationState}
         * @since 3.60.0
         */
        this.anims = new AnimationState(this);

        /**
         * A rectangle that holds the bounds of this Particle after a call to
         * the `Particle.getBounds` method has been made.
         *
         * @name Phaser.GameObjects.Particles.Particle#bounds
         * @type {Phaser.Geom.Rectangle}
         * @since 3.60.0
         */
        this.bounds = new Rectangle();
    },

    /**
     * The Event Emitter proxy.
     *
     * Passes on all parameters to the `ParticleEmitter` to emit directly.
     *
     * @method Phaser.GameObjects.Particles.Particle#emit
     * @since 3.60.0
     *
     * @param {(string|Symbol)} event - The event name.
     * @param {any} [a1] - Optional argument 1.
     * @param {any} [a2] - Optional argument 2.
     * @param {any} [a3] - Optional argument 3.
     * @param {any} [a4] - Optional argument 4.
     * @param {any} [a5] - Optional argument 5.
     *
     * @return {boolean} `true` if the event had listeners, else `false`.
     */
    emit: function (event, a1, a2, a3, a4, a5)
    {
        return this.emitter.emit(event, a1, a2, a3, a4, a5);
    },

    /**
     * Checks to see if this Particle is alive and updating.
     *
     * @method Phaser.GameObjects.Particles.Particle#isAlive
     * @since 3.0.0
     *
     * @return {boolean} `true` if this Particle is alive and updating, otherwise `false`.
     */
    isAlive: function ()
    {
        return (this.lifeCurrent > 0);
    },

    /**
     * Kills this particle. This sets the `lifeCurrent` value to 0, which forces
     * the Particle to be removed the next time its parent Emitter runs an update.
     *
     * @method Phaser.GameObjects.Particles.Particle#kill
     * @since 3.60.0
     */
    kill: function ()
    {
        this.lifeCurrent = 0;
    },

    /**
     * Sets the position of this particle to the given x/y coordinates.
     *
     * If the parameters are left undefined, it resets the particle back to 0x0.
     *
     * @method Phaser.GameObjects.Particles.Particle#setPosition
     * @since 3.60.0
     *
     * @param {number} [x=0] - The x coordinate to set this Particle to.
     * @param {number} [y=0] - The y coordinate to set this Particle to.
     */
    setPosition: function (x, y)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = 0; }

        this.x = x;
        this.y = y;
    },

    /**
     * Starts this Particle from the given coordinates.
     *
     * @method Phaser.GameObjects.Particles.Particle#fire
     * @since 3.0.0
     *
     * @param {number} [x] - The x coordinate to launch this Particle from.
     * @param {number} [y] - The y coordinate to launch this Particle from.
     *
     * @return {boolean} `true` if the Particle is alive, or `false` if it was spawned inside a DeathZone.
     */
    fire: function (x, y)
    {
        var emitter = this.emitter;
        var ops = emitter.ops;

        var anim = emitter.getAnim();

        if (anim)
        {
            this.anims.play(anim);
        }
        else
        {
            this.frame = emitter.getFrame();
            this.texture = this.frame.texture;
        }

        if (!this.frame)
        {
            throw new Error('Particle has no texture frame');
        }

        //  Updates particle.x and particle.y during this call
        emitter.getEmitZone(this);

        if (x === undefined)
        {
            this.x += ops.x.onEmit(this, 'x');
        }
        else if (ops.x.steps > 0)
        {
            //  EmitterOp is stepped but x was forced (follower?) so use it
            this.x += x + ops.x.onEmit(this, 'x');
        }
        else
        {
            this.x += x;
        }

        if (y === undefined)
        {
            this.y += ops.y.onEmit(this, 'y');
        }
        else if (ops.y.steps > 0)
        {
            //  EmitterOp is stepped but y was forced (follower?) so use it
            this.y += y + ops.y.onEmit(this, 'y');
        }
        else
        {
            this.y += y;
        }

        this.life = ops.lifespan.onEmit(this, 'lifespan');
        this.lifeCurrent = this.life;
        this.lifeT = 0;

        this.delayCurrent = ops.delay.onEmit(this, 'delay');
        this.holdCurrent = ops.hold.onEmit(this, 'hold');

        this.scaleX = ops.scaleX.onEmit(this, 'scaleX');
        this.scaleY = (ops.scaleY.active) ? ops.scaleY.onEmit(this, 'scaleY') : this.scaleX;

        this.angle = ops.rotate.onEmit(this, 'rotate');

        this.rotation = DegToRad(this.angle);

        emitter.worldMatrix.transformPoint(this.x, this.y, this.worldPosition);

        //  Check we didn't spawn in the middle of a DeathZone
        if (this.delayCurrent === 0 && emitter.getDeathZone(this))
        {
            this.lifeCurrent = 0;

            return false;
        }

        var sx = ops.speedX.onEmit(this, 'speedX');
        var sy = (ops.speedY.active) ? ops.speedY.onEmit(this, 'speedY') : sx;

        if (emitter.radial)
        {
            var rad = DegToRad(ops.angle.onEmit(this, 'angle'));

            this.velocityX = Math.cos(rad) * Math.abs(sx);
            this.velocityY = Math.sin(rad) * Math.abs(sy);
        }
        else if (emitter.moveTo)
        {
            var mx = ops.moveToX.onEmit(this, 'moveToX');
            var my = ops.moveToY.onEmit(this, 'moveToY');
            var lifeS = this.life / 1000;

            this.velocityX = (mx - this.x) / lifeS;
            this.velocityY = (my - this.y) / lifeS;
        }
        else
        {
            this.velocityX = sx;
            this.velocityY = sy;
        }

        if (emitter.acceleration)
        {
            this.accelerationX = ops.accelerationX.onEmit(this, 'accelerationX');
            this.accelerationY = ops.accelerationY.onEmit(this, 'accelerationY');
        }

        this.maxVelocityX = ops.maxVelocityX.onEmit(this, 'maxVelocityX');
        this.maxVelocityY = ops.maxVelocityY.onEmit(this, 'maxVelocityY');

        this.bounce = ops.bounce.onEmit(this, 'bounce');

        this.alpha = ops.alpha.onEmit(this, 'alpha');

        if (ops.color.active)
        {
            this.tint = ops.color.onEmit(this, 'tint');
        }
        else
        {
            this.tint = ops.tint.onEmit(this, 'tint');
        }

        return true;
    },

    /**
     * The main update method for this Particle.
     *
     * Updates its life values, computes the velocity and repositions the Particle.
     *
     * @method Phaser.GameObjects.Particles.Particle#update
     * @since 3.0.0
     *
     * @param {number} delta - The delta time in ms.
     * @param {number} step - The delta value divided by 1000.
     * @param {Phaser.GameObjects.Particles.ParticleProcessor[]} processors - An array of all active Particle Processors.
     *
     * @return {boolean} Returns `true` if this Particle has now expired and should be removed, otherwise `false` if still active.
     */
    update: function (delta, step, processors)
    {
        if (this.lifeCurrent <= 0)
        {
            //  Particle is dead via `Particle.kill` method, or being held
            if (this.holdCurrent > 0)
            {
                this.holdCurrent -= delta;

                return (this.holdCurrent <= 0);
            }
            else
            {
                return true;
            }
        }

        if (this.delayCurrent > 0)
        {
            this.delayCurrent -= delta;

            return false;
        }

        this.anims.update(0, delta);

        var emitter = this.emitter;
        var ops = emitter.ops;

        //  How far along in life is this particle? (t = 0 to 1)
        var t = 1 - (this.lifeCurrent / this.life);

        this.lifeT = t;

        this.x = ops.x.onUpdate(this, 'x', t, this.x);
        this.y = ops.y.onUpdate(this, 'y', t, this.y);

        if (emitter.moveTo)
        {
            var mx = ops.moveToX.onUpdate(this, 'moveToX', t, emitter.moveToX);
            var my = ops.moveToY.onUpdate(this, 'moveToY', t, emitter.moveToY);
            var lifeS = this.lifeCurrent / 1000;

            this.velocityX = (mx - this.x) / lifeS;
            this.velocityY = (my - this.y) / lifeS;
        }

        this.computeVelocity(emitter, delta, step, processors, t);

        this.scaleX = ops.scaleX.onUpdate(this, 'scaleX', t, this.scaleX);
        this.scaleY = this.scaleX;

        if (ops.scaleY.active)
        {
            this.scaleY = ops.scaleY.onUpdate(this, 'scaleY', t, this.scaleY);
        }

        this.angle = ops.rotate.onUpdate(this, 'rotate', t, this.angle);

        this.rotation = DegToRad(this.angle);

        if (emitter.getDeathZone(this))
        {
            this.lifeCurrent = 0;

            //  No need to go any further, particle has been killed
            return true;
        }

        this.alpha = ops.alpha.onUpdate(this, 'alpha', t, this.alpha);

        if (ops.color.active)
        {
            this.tint = ops.color.onUpdate(this, 'color', t, this.tint);
        }
        else
        {
            this.tint = ops.tint.onUpdate(this, 'tint', t, this.tint);
        }

        this.lifeCurrent -= delta;

        return (this.lifeCurrent <= 0 && this.holdCurrent <= 0);
    },

    /**
     * An internal method that calculates the velocity of the Particle and
     * its world position. It also runs it against any active Processors
     * that are set on the Emitter.
     *
     * @method Phaser.GameObjects.Particles.Particle#computeVelocity
     * @since 3.0.0
     *
     * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Emitter that is updating this Particle.
     * @param {number} delta - The delta time in ms.
     * @param {number} step - The delta value divided by 1000.
     * @param {Phaser.GameObjects.Particles.ParticleProcessor[]} processors - An array of all active Particle Processors.
     * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death).
     */
    computeVelocity: function (emitter, delta, step, processors, t)
    {
        var ops = emitter.ops;

        var vx = this.velocityX;
        var vy = this.velocityY;

        var ax = ops.accelerationX.onUpdate(this, 'accelerationX', t, this.accelerationX);
        var ay = ops.accelerationY.onUpdate(this, 'accelerationY', t, this.accelerationY);

        var mx = ops.maxVelocityX.onUpdate(this, 'maxVelocityX', t, this.maxVelocityX);
        var my = ops.maxVelocityY.onUpdate(this, 'maxVelocityY', t, this.maxVelocityY);

        this.bounce = ops.bounce.onUpdate(this, 'bounce', t, this.bounce);

        vx += (emitter.gravityX * step) + (ax * step);
        vy += (emitter.gravityY * step) + (ay * step);

        vx = Clamp(vx, -mx, mx);
        vy = Clamp(vy, -my, my);

        this.velocityX = vx;
        this.velocityY = vy;

        //  Integrate back in to the position
        this.x += vx * step;
        this.y += vy * step;

        emitter.worldMatrix.transformPoint(this.x, this.y, this.worldPosition);

        //  Apply any additional processors (these can update velocity and/or position)
        for (var i = 0; i < processors.length; i++)
        {
            var processor = processors[i];

            if (processor.active)
            {
                processor.update(this, delta, step, t);
            }
        }
    },

    /**
     * This is a NOOP method and does nothing when called.
     *
     * @method Phaser.GameObjects.Particles.Particle#setSizeToFrame
     * @since 3.60.0
     */
    setSizeToFrame: function ()
    {
        //  NOOP
    },

    /**
     * Gets the bounds of this particle as a Geometry Rectangle, factoring in any
     * transforms of the parent emitter and anything else above it in the display list.
     *
     * Once calculated the bounds can be accessed via the `Particle.bounds` property.
     *
     * @method Phaser.GameObjects.Particles.Particle#getBounds
     * @since 3.60.0
     *
     * @param {Phaser.GameObjects.Components.TransformMatrix} [matrix] - Optional transform matrix to apply to this particle.
     *
     * @return {Phaser.Geom.Rectangle} A Rectangle containing the transformed bounds of this particle.
     */
    getBounds: function (matrix)
    {
        if (matrix === undefined) { matrix = this.emitter.getWorldTransformMatrix(); }

        var sx = Math.abs(matrix.scaleX) * this.scaleX;
        var sy = Math.abs(matrix.scaleY) * this.scaleY;

        var x = this.x;
        var y = this.y;
        var rotation = this.rotation;
        var width = (this.frame.width * sx) / 2;
        var height = (this.frame.height * sy) / 2;

        var bounds = this.bounds;

        var topLeft = new Vector2(x - width, y - height);
        var topRight = new Vector2(x + width, y - height);
        var bottomLeft = new Vector2(x - width, y + height);
        var bottomRight = new Vector2(x + width, y + height);

        if (rotation !== 0)
        {
            RotateAround(topLeft, x, y, rotation);
            RotateAround(topRight, x, y, rotation);
            RotateAround(bottomLeft, x, y, rotation);
            RotateAround(bottomRight, x, y, rotation);
        }

        matrix.transformPoint(topLeft.x, topLeft.y, topLeft);
        matrix.transformPoint(topRight.x, topRight.y, topRight);
        matrix.transformPoint(bottomLeft.x, bottomLeft.y, bottomLeft);
        matrix.transformPoint(bottomRight.x, bottomRight.y, bottomRight);

        bounds.x = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
        bounds.y = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
        bounds.width = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x) - bounds.x;
        bounds.height = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y) - bounds.y;

        return bounds;
    },

    /**
     * Destroys this Particle.
     *
     * @method Phaser.GameObjects.Particles.Particle#destroy
     * @since 3.60.0
     */
    destroy: function ()
    {
        this.anims.destroy();

        this.anims = null;
        this.emitter = null;
        this.texture = null;
        this.frame = null;
        this.scene = null;
    }

});

module.exports = Particle;


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

//  This is based off an explanation and expanded math presented by Paul Bourke:
//  See http://paulbourke.net/geometry/pointlineplane/

/**
 * Checks if two Lines intersect. If the Lines are identical, they will be treated as parallel and thus non-intersecting.
 *
 * @function Phaser.Geom.Intersects.LineToLine
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Line} line1 - The first Line to check.
 * @param {Phaser.Geom.Line} line2 - The second Line to check.
 * @param {Phaser.Types.Math.Vector2Like} [out] - An optional point-like object in which to store the coordinates of intersection, if needed.
 *
 * @return {boolean} `true` if the two Lines intersect, and the `out` object will be populated, if given. Otherwise, `false`.
 */
var LineToLine = function (line1, line2, out)
{
    var x1 = line1.x1;
    var y1 = line1.y1;
    var x2 = line1.x2;
    var y2 = line1.y2;

    var x3 = line2.x1;
    var y3 = line2.y1;
    var x4 = line2.x2;
    var y4 = line2.y2;

    //  Check that none of the lines are length zero
    if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4))
    {
        return false;
    }

    var denom = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));

    //  Make sure there is not a division by zero - this also indicates that the lines are parallel.
    //  If numA and numB were both equal to zero the lines would be on top of each other (coincidental).
    //  This check is not done because it is not necessary for this implementation (the parallel check accounts for this).

    if (denom === 0)
    {
        //  Lines are parallel
        return false;
    }

    //  Calculate the intermediate fractional point that the lines potentially intersect.

    var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
    var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;

    //  The fractional point will be between 0 and 1 inclusive if the lines intersect.
    //  If the fractional calculation is larger than 1 or smaller than 0 the lines would need to be longer to intersect.

    if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
    {
        return false;
    }
    else
    {
        if (out)
        {
            out.x = x1 + ua * (x2 - x1);
            out.y = y1 + ua * (y2 - y1);
        }

        return true;
    }
};

module.exports = LineToLine;


var pipeline = this.gameObject.getPostPipeline(type);

keep keep keep replace keep keep keep keep

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

var Class = require('../utils/Class');
var Controller = require('./Controller');
var FX_CONST = require('./const');

/**
 * @classdesc
 *
 * @class Glow
 * @extends Phaser.FX.Controller
 * @memberof Phaser.FX
 * @constructor
 * @since 3.60.0
 *
 * @param {Phaser.GameObjects.GameObject} gameObject - A reference to the Game Object that has this fx.
 * @param {number} [color=0xffffff] - The color of the glow effect as a number value.
 * @param {number} [outerStrength=4] - The strength of the glow outward from the edge of the Sprite.
 * @param {number} [innerStrength=0] - The strength of the glow inward from the edge of the Sprite.
 * @param {boolean} [knockout=false] - If `true` only the glow is drawn, not the texture itself.
 */
var Glow = new Class({

    Extends: Controller,

    initialize:

    function Glow (gameObject, color, outerStrength, innerStrength, knockout)
    {
        if (outerStrength === undefined) { outerStrength = 4; }
        if (innerStrength === undefined) { innerStrength = 0; }
        if (knockout === undefined) { knockout = false; }

        Controller.call(this, FX_CONST.GLOW, gameObject);

        /**
         * The distance of the glow.
         *
         * This must be an integer and can be between 0 and 128 inclusive.
         *
         * The higher the value, the more iterations the shader takes
         * when drawing the glow.
         *
         * @name Phaser.FX.Glow#distance
         * @type {number}
         * @since 3.60.0
         */
        // this.distance = distance;

        /**
         * The strength of the glow outward from the edge of the Sprite.
         *
         * @name Phaser.FX.Glow#outerStrength
         * @type {number}
         * @since 3.60.0
         */
        this.outerStrength = outerStrength;

        /**
         * The strength of the glow inward from the edge of the Sprite.
         *
         * @name Phaser.FX.Glow#innerStrength
         * @type {number}
         * @since 3.60.0
         */
        this.innerStrength = innerStrength;

        /**
         * If `true` only the glow is drawn, not the texture itself.
         *
         * @name Phaser.FX.Glow#knockout
         * @type {number}
         * @since 3.60.0
         */
        this.knockout = knockout;

        /**
         * A 4 element array of gl color values.
         *
         * @name Phaser.FX.Glow#glcolor
         * @type {number[]}
         * @since 3.60.0
         */
        this.glcolor = [ 1, 1, 1, 1 ];

        if (color !== undefined)
        {
            this.color = color;
        }
    },

    /**
     * The color of the glow as a number value.
     *
     * @name Phaser.FX.Glow#color
     * @type {number}
     * @since 3.60.0
     */
    color: {

        get: function ()
        {
            var color = this.glcolor;

            return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0));
        },

        set: function (value)
        {
            var color = this.glcolor;

            color[0] = ((value >> 16) & 0xFF) / 255;
            color[1] = ((value >> 8) & 0xFF) / 255;
            color[2] = (value & 0xFF) / 255;
        }

    }

});

module.exports = Glow;


module.exports = [
    '#define SHADER_NAME SHINE_FS',
    'precision mediump float;',
    'uniform sampler2D uMainSampler;',
    'uniform vec2 resolution;',
    'uniform bool reveal;',
    'uniform float speed;',
    'uniform float time;',
    'uniform float lineWidth;',
    'uniform float gradient;',
    'varying vec2 outTexCoord;',
    'void main ()',
    '{',
    '	vec2 uv = gl_FragCoord.xy / resolution.xy;',
    '    vec4 tex = texture2D(uMainSampler, outTexCoord);',
    '    vec4 col1 = vec4(0.3, 0.0, 0.0, 1.0);',
    '    vec4 col2 = vec4(0.85, 0.85, 0.85, 1.0);',
    '    uv.x = uv.x - mod(time * speed, 2.0) + 0.5;',
    '    float y = uv.x * gradient;',
    '    float s = smoothstep(y - lineWidth, y, uv.y) - smoothstep(y, y + lineWidth, uv.y);',
    '    gl_FragColor = (((s * col1) + (s * col2)) * tex);',
    '    if (!reveal)',
    '    {',
    '        gl_FragColor += tex;',
    '    }',
    '}',
].join('\n');


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

/**
 * The Gamepad Button Up Event.
 *
 * This event is dispatched by a Gamepad instance when a button has been released on it.
 *
 * Listen to this event from a Gamepad instance. Once way to get this is from the `pad1`, `pad2`, etc properties on the Gamepad Plugin:
 * `this.input.gamepad.pad1.on('up', listener)`.
 *
 * Note that you will not receive any Gamepad button events until the browser considers the Gamepad as being 'connected'.
 *
 * You can also listen for an UP event from the Gamepad Plugin. See the [BUTTON_UP]{@linkcode Phaser.Input.Gamepad.Events#event:BUTTON_UP} event for details.
 *
 * @event Phaser.Input.Gamepad.Events#GAMEPAD_BUTTON_UP
 * @type {string}
 * @since 3.10.0
 *
 * @param {number} index - The index of the button that was released.
 * @param {number} value - The value of the button at the time it was released. Between 0 and 1. Some Gamepads have pressure-sensitive buttons.
 * @param {Phaser.Input.Gamepad.Button} button - A reference to the Button which was released.
 */
module.exports = 'up';


/**
 * @typedef {object} Phaser.Types.GameObjects.Particles.ParticleEmitterDeathZoneConfig
 * @since 3.0.0
 *
 * @property {Phaser.Types.GameObjects.Particles.DeathZoneSource} source - A shape representing the zone. See {@link Phaser.GameObjects.Particles.Zones.DeathZone#source}.
 * @property {string} [type='onEnter'] - 'onEnter' or 'onLeave'.
 */


* @param {number} [color=0xffffff] - The color of the glow effect as a number value.

* @param {number} [outerStrength=4] - The strength of the glow outward from the edge of the Sprite.

* @param {number} [innerStrength=0] - The strength of the glow inward from the edge of the Sprite.

* @param {boolean} [knockout=false] - If `true` only the glow is drawn, not the texture itself.

* @return {Phaser.FX.Glow} The Glow FX Controller.

* @param {number} [quality=0.1] - Only available for PostFX. Sets the quality of this Glow effect. Default is 0.1. Cannot be changed post-creation.

* @param {number} [distance=10] - Only available for PostFX. Sets the distance of this Glow effect. Default is 10. Cannot be changed post-creation.

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

var Class = require('../../../../utils/Class');
var GlowFrag = require('../../shaders/FXGlow-frag.js');
var PostFXPipeline = require('../PostFXPipeline');
var Utils = require('../../Utils');

var GlowFXPipeline = new Class({

    Extends: PostFXPipeline,

    initialize:

    function GlowFXPipeline (game, quality, distance)
    {
        if (quality === undefined) { quality = 0.1; }
        if (distance === undefined) { distance = 10; }

        PostFXPipeline.call(this, {
            game: game,
            fragShader: Utils.setGlowQuality(GlowFrag, game, quality, distance)
        });

        this.outerStrength = 4;
        this.innerStrength = 0;
        this.knockout = false;
        this.glcolor = [ 1, 1, 1, 1 ];
    },

    onPreRender: function (controller, shader, width, height)
    {
        controller = this.getController(controller);

        this.set1f('outerStrength', controller.outerStrength, shader);
        this.set1f('innerStrength', controller.innerStrength, shader);
        this.set4fv('glowColor', controller.glcolor, shader);
        this.setBoolean('knockout', controller.knockout, shader);

        if (width && height)
        {
            this.set2f('resolution', width, height, shader);
        }
    },

    onDraw: function (target)
    {
        this.set2f('resolution', target.width, target.height);

        this.bindAndDraw(target);
    }

});

module.exports = GlowFXPipeline;


#define SHADER_NAME BARREL_FS

precision mediump float;

uniform sampler2D uMainSampler;

uniform float amount;

varying vec2 outTexCoord;

vec2 Distort(vec2 p)
{
    float theta  = atan(p.y, p.x);
    float radius = length(p);
    radius = pow(radius, amount);
    p.x = radius * cos(theta);
    p.y = radius * sin(theta);
    return 0.5 * (p + 1.0);
}

void main()
{
    vec2 xy = 2.0 * outTexCoord - 1.0;
    vec2 texCoord = outTexCoord;

    if (length(xy) < 1.0)
    {
        texCoord = Distort(xy);
    }

    gl_FragColor = texture2D(uMainSampler, texCoord);
}


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

var GetLeft = require('../../bounds/GetLeft');
var GetTop = require('../../bounds/GetTop');
var SetBottom = require('../../bounds/SetBottom');
var SetLeft = require('../../bounds/SetLeft');

/**
 * Takes given Game Object and aligns it so that it is positioned next to the top left position of the other.
 *
 * @function Phaser.Display.Align.To.TopLeft
 * @since 3.0.0
 *
 * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return]
 *
 * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned.
 * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on.
 * @param {number} [offsetX=0] - Optional horizontal offset from the position.
 * @param {number} [offsetY=0] - Optional vertical offset from the position.
 *
 * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned.
 */
var TopLeft = function (gameObject, alignTo, offsetX, offsetY)
{
    if (offsetX === undefined) { offsetX = 0; }
    if (offsetY === undefined) { offsetY = 0; }

    SetLeft(gameObject, GetLeft(alignTo) - offsetX);
    SetBottom(gameObject, GetTop(alignTo) - offsetY);

    return gameObject;
};

module.exports = TopLeft;


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

/**
 * Quadratic ease-in/out.
 *
 * @function Phaser.Math.Easing.Quadratic.InOut
 * @since 3.0.0
 *
 * @param {number} v - The value to be tweened.
 *
 * @return {number} The tweened value.
 */
var InOut = function (v)
{
    if ((v *= 2) < 1)
    {
        return 0.5 * v * v;
    }
    else
    {
        return -0.5 * (--v * (v - 2) - 1);
    }
};

module.exports = InOut;