/*!
 * @pixi/ticker - v6.5.0-rc
 * Compiled Thu, 14 Jul 2022 18:30:46 UTC
 *
 * @pixi/ticker is licensed under the MIT License.
 * http://www.opensource.org/licenses/mit-license
 */
this.PIXI = this.PIXI || {};
var _pixi_ticker = (function (exports, settings, core) {
    'use strict';

    /**
     * Target frames per millisecond.
     * @static
     * @name TARGET_FPMS
     * @memberof PIXI.settings
     * @type {number}
     * @default 0.06
     */
    settings.settings.TARGET_FPMS = 0.06;

    /**
     * Represents the update priorities used by internal PIXI classes when registered with
     * the {@link PIXI.Ticker} object. Higher priority items are updated first and lower
     * priority items, such as render, should go later.
     * @static
     * @constant
     * @name UPDATE_PRIORITY
     * @memberof PIXI
     * @enum {number}
     * @property {number} [INTERACTION=50] Highest priority, used for {@link PIXI.InteractionManager}
     * @property {number} [HIGH=25] High priority updating, {@link PIXI.VideoBaseTexture} and {@link PIXI.AnimatedSprite}
     * @property {number} [NORMAL=0] Default priority for ticker events, see {@link PIXI.Ticker#add}.
     * @property {number} [LOW=-25] Low priority used for {@link PIXI.Application} rendering.
     * @property {number} [UTILITY=-50] Lowest priority used for {@link PIXI.BasePrepare} utility.
     */
    exports.UPDATE_PRIORITY = void 0;
    (function (UPDATE_PRIORITY) {
        UPDATE_PRIORITY[UPDATE_PRIORITY["INTERACTION"] = 50] = "INTERACTION";
        UPDATE_PRIORITY[UPDATE_PRIORITY["HIGH"] = 25] = "HIGH";
        UPDATE_PRIORITY[UPDATE_PRIORITY["NORMAL"] = 0] = "NORMAL";
        UPDATE_PRIORITY[UPDATE_PRIORITY["LOW"] = -25] = "LOW";
        UPDATE_PRIORITY[UPDATE_PRIORITY["UTILITY"] = -50] = "UTILITY";
    })(exports.UPDATE_PRIORITY || (exports.UPDATE_PRIORITY = {}));

    /**
     * Internal class for handling the priority sorting of ticker handlers.
     * @private
     * @class
     * @memberof PIXI
     */
    var TickerListener = /** @class */ (function () {
        /**
         * Constructor
         * @private
         * @param fn - The listener function to be added for one update
         * @param context - The listener context
         * @param priority - The priority for emitting
         * @param once - If the handler should fire once
         */
        function TickerListener(fn, context, priority, once) {
            if (context === void 0) { context = null; }
            if (priority === void 0) { priority = 0; }
            if (once === void 0) { once = false; }
            /** The next item in chain. */
            this.next = null;
            /** The previous item in chain. */
            this.previous = null;
            /** `true` if this listener has been destroyed already. */
            this._destroyed = false;
            this.fn = fn;
            this.context = context;
            this.priority = priority;
            this.once = once;
        }
        /**
         * Simple compare function to figure out if a function and context match.
         * @private
         * @param fn - The listener function to be added for one update
         * @param context - The listener context
         * @returns `true` if the listener match the arguments
         */
        TickerListener.prototype.match = function (fn, context) {
            if (context === void 0) { context = null; }
            return this.fn === fn && this.context === context;
        };
        /**
         * Emit by calling the current function.
         * @private
         * @param deltaTime - time since the last emit.
         * @returns Next ticker
         */
        TickerListener.prototype.emit = function (deltaTime) {
            if (this.fn) {
                if (this.context) {
                    this.fn.call(this.context, deltaTime);
                }
                else {
                    this.fn(deltaTime);
                }
            }
            var redirect = this.next;
            if (this.once) {
                this.destroy(true);
            }
            // Soft-destroying should remove
            // the next reference
            if (this._destroyed) {
                this.next = null;
            }
            return redirect;
        };
        /**
         * Connect to the list.
         * @private
         * @param previous - Input node, previous listener
         */
        TickerListener.prototype.connect = function (previous) {
            this.previous = previous;
            if (previous.next) {
                previous.next.previous = this;
            }
            this.next = previous.next;
            previous.next = this;
        };
        /**
         * Destroy and don't use after this.
         * @private
         * @param hard - `true` to remove the `next` reference, this
         *        is considered a hard destroy. Soft destroy maintains the next reference.
         * @returns The listener to redirect while emitting or removing.
         */
        TickerListener.prototype.destroy = function (hard) {
            if (hard === void 0) { hard = false; }
            this._destroyed = true;
            this.fn = null;
            this.context = null;
            // Disconnect, hook up next and previous
            if (this.previous) {
                this.previous.next = this.next;
            }
            if (this.next) {
                this.next.previous = this.previous;
            }
            // Redirect to the next item
            var redirect = this.next;
            // Remove references
            this.next = hard ? null : redirect;
            this.previous = null;
            return redirect;
        };
        return TickerListener;
    }());

    /**
     * A Ticker class that runs an update loop that other objects listen to.
     *
     * This class is composed around listeners meant for execution on the next requested animation frame.
     * Animation frames are requested only when necessary, e.g. When the ticker is started and the emitter has listeners.
     * @class
     * @memberof PIXI
     */
    var Ticker = /** @class */ (function () {
        function Ticker() {
            var _this = this;
            /**
             * Whether or not this ticker should invoke the method
             * {@link PIXI.Ticker#start} automatically
             * when a listener is added.
             */
            this.autoStart = false;
            /**
             * Scalar time value from last frame to this frame.
             * This value is capped by setting {@link PIXI.Ticker#minFPS}
             * and is scaled with {@link PIXI.Ticker#speed}.
             * **Note:** The cap may be exceeded by scaling.
             */
            this.deltaTime = 1;
            /**
             * The last time {@link PIXI.Ticker#update} was invoked.
             * This value is also reset internally outside of invoking
             * update, but only when a new animation frame is requested.
             * If the platform supports DOMHighResTimeStamp,
             * this value will have a precision of 1 µs.
             */
            this.lastTime = -1;
            /**
             * Factor of current {@link PIXI.Ticker#deltaTime}.
             * @example
             * // Scales ticker.deltaTime to what would be
             * // the equivalent of approximately 120 FPS
             * ticker.speed = 2;
             */
            this.speed = 1;
            /**
             * Whether or not this ticker has been started.
             * `true` if {@link PIXI.Ticker#start} has been called.
             * `false` if {@link PIXI.Ticker#stop} has been called.
             * While `false`, this value may change to `true` in the
             * event of {@link PIXI.Ticker#autoStart} being `true`
             * and a listener is added.
             */
            this.started = false;
            /** Internal current frame request ID */
            this._requestId = null;
            /**
             * Internal value managed by minFPS property setter and getter.
             * This is the maximum allowed milliseconds between updates.
             */
            this._maxElapsedMS = 100;
            /**
             * Internal value managed by minFPS property setter and getter.
             * This is the minimum allowed milliseconds between updates.
             */
            this._minElapsedMS = 0;
            /** If enabled, deleting is disabled.*/
            this._protected = false;
            /** The last time keyframe was executed. Maintains a relatively fixed interval with the previous value. */
            this._lastFrame = -1;
            this._head = new TickerListener(null, null, Infinity);
            this.deltaMS = 1 / settings.settings.TARGET_FPMS;
            this.elapsedMS = 1 / settings.settings.TARGET_FPMS;
            this._tick = function (time) {
                _this._requestId = null;
                if (_this.started) {
                    // Invoke listeners now
                    _this.update(time);
                    // Listener side effects may have modified ticker state.
                    if (_this.started && _this._requestId === null && _this._head.next) {
                        _this._requestId = requestAnimationFrame(_this._tick);
                    }
                }
            };
        }
        /**
         * Conditionally requests a new animation frame.
         * If a frame has not already been requested, and if the internal
         * emitter has listeners, a new frame is requested.
         * @private
         */
        Ticker.prototype._requestIfNeeded = function () {
            if (this._requestId === null && this._head.next) {
                // ensure callbacks get correct delta
                this.lastTime = performance.now();
                this._lastFrame = this.lastTime;
                this._requestId = requestAnimationFrame(this._tick);
            }
        };
        /**
         * Conditionally cancels a pending animation frame.
         * @private
         */
        Ticker.prototype._cancelIfNeeded = function () {
            if (this._requestId !== null) {
                cancelAnimationFrame(this._requestId);
                this._requestId = null;
            }
        };
        /**
         * Conditionally requests a new animation frame.
         * If the ticker has been started it checks if a frame has not already
         * been requested, and if the internal emitter has listeners. If these
         * conditions are met, a new frame is requested. If the ticker has not
         * been started, but autoStart is `true`, then the ticker starts now,
         * and continues with the previous conditions to request a new frame.
         * @private
         */
        Ticker.prototype._startIfPossible = function () {
            if (this.started) {
                this._requestIfNeeded();
            }
            else if (this.autoStart) {
                this.start();
            }
        };
        /**
         * Register a handler for tick events. Calls continuously unless
         * it is removed or the ticker is stopped.
         * @param fn - The listener function to be added for updates
         * @param context - The listener context
         * @param {number} [priority=PIXI.UPDATE_PRIORITY.NORMAL] - The priority for emitting
         * @returns This instance of a ticker
         */
        Ticker.prototype.add = function (fn, context, priority) {
            if (priority === void 0) { priority = exports.UPDATE_PRIORITY.NORMAL; }
            return this._addListener(new TickerListener(fn, context, priority));
        };
        /**
         * Add a handler for the tick event which is only execute once.
         * @param fn - The listener function to be added for one update
         * @param context - The listener context
         * @param {number} [priority=PIXI.UPDATE_PRIORITY.NORMAL] - The priority for emitting
         * @returns This instance of a ticker
         */
        Ticker.prototype.addOnce = function (fn, context, priority) {
            if (priority === void 0) { priority = exports.UPDATE_PRIORITY.NORMAL; }
            return this._addListener(new TickerListener(fn, context, priority, true));
        };
        /**
         * Internally adds the event handler so that it can be sorted by priority.
         * Priority allows certain handler (user, AnimatedSprite, Interaction) to be run
         * before the rendering.
         * @private
         * @param listener - Current listener being added.
         * @returns This instance of a ticker
         */
        Ticker.prototype._addListener = function (listener) {
            // For attaching to head
            var current = this._head.next;
            var previous = this._head;
            // Add the first item
            if (!current) {
                listener.connect(previous);
            }
            else {
                // Go from highest to lowest priority
                while (current) {
                    if (listener.priority > current.priority) {
                        listener.connect(previous);
                        break;
                    }
                    previous = current;
                    current = current.next;
                }
                // Not yet connected
                if (!listener.previous) {
                    listener.connect(previous);
                }
            }
            this._startIfPossible();
            return this;
        };
        /**
         * Removes any handlers matching the function and context parameters.
         * If no handlers are left after removing, then it cancels the animation frame.
         * @param fn - The listener function to be removed
         * @param context - The listener context to be removed
         * @returns This instance of a ticker
         */
        Ticker.prototype.remove = function (fn, context) {
            var listener = this._head.next;
            while (listener) {
                // We found a match, lets remove it
                // no break to delete all possible matches
                // incase a listener was added 2+ times
                if (listener.match(fn, context)) {
                    listener = listener.destroy();
                }
                else {
                    listener = listener.next;
                }
            }
            if (!this._head.next) {
                this._cancelIfNeeded();
            }
            return this;
        };
        Object.defineProperty(Ticker.prototype, "count", {
            /**
             * The number of listeners on this ticker, calculated by walking through linked list
             * @readonly
             * @member {number}
             */
            get: function () {
                if (!this._head) {
                    return 0;
                }
                var count = 0;
                var current = this._head;
                while ((current = current.next)) {
                    count++;
                }
                return count;
            },
            enumerable: false,
            configurable: true
        });
        /** Starts the ticker. If the ticker has listeners a new animation frame is requested at this point. */
        Ticker.prototype.start = function () {
            if (!this.started) {
                this.started = true;
                this._requestIfNeeded();
            }
        };
        /** Stops the ticker. If the ticker has requested an animation frame it is canceled at this point. */
        Ticker.prototype.stop = function () {
            if (this.started) {
                this.started = false;
                this._cancelIfNeeded();
            }
        };
        /** Destroy the ticker and don't use after this. Calling this method removes all references to internal events. */
        Ticker.prototype.destroy = function () {
            if (!this._protected) {
                this.stop();
                var listener = this._head.next;
                while (listener) {
                    listener = listener.destroy(true);
                }
                this._head.destroy();
                this._head = null;
            }
        };
        /**
         * Triggers an update. An update entails setting the
         * current {@link PIXI.Ticker#elapsedMS},
         * the current {@link PIXI.Ticker#deltaTime},
         * invoking all listeners with current deltaTime,
         * and then finally setting {@link PIXI.Ticker#lastTime}
         * with the value of currentTime that was provided.
         * This method will be called automatically by animation
         * frame callbacks if the ticker instance has been started
         * and listeners are added.
         * @param {number} [currentTime=performance.now()] - the current time of execution
         */
        Ticker.prototype.update = function (currentTime) {
            if (currentTime === void 0) { currentTime = performance.now(); }
            var elapsedMS;
            // If the difference in time is zero or negative, we ignore most of the work done here.
            // If there is no valid difference, then should be no reason to let anyone know about it.
            // A zero delta, is exactly that, nothing should update.
            //
            // The difference in time can be negative, and no this does not mean time traveling.
            // This can be the result of a race condition between when an animation frame is requested
            // on the current JavaScript engine event loop, and when the ticker's start method is invoked
            // (which invokes the internal _requestIfNeeded method). If a frame is requested before
            // _requestIfNeeded is invoked, then the callback for the animation frame the ticker requests,
            // can receive a time argument that can be less than the lastTime value that was set within
            // _requestIfNeeded. This difference is in microseconds, but this is enough to cause problems.
            //
            // This check covers this browser engine timing issue, as well as if consumers pass an invalid
            // currentTime value. This may happen if consumers opt-out of the autoStart, and update themselves.
            if (currentTime > this.lastTime) {
                // Save uncapped elapsedMS for measurement
                elapsedMS = this.elapsedMS = currentTime - this.lastTime;
                // cap the milliseconds elapsed used for deltaTime
                if (elapsedMS > this._maxElapsedMS) {
                    elapsedMS = this._maxElapsedMS;
                }
                elapsedMS *= this.speed;
                // If not enough time has passed, exit the function.
                // Get ready for next frame by setting _lastFrame, but based on _minElapsedMS
                // adjustment to ensure a relatively stable interval.
                if (this._minElapsedMS) {
                    var delta = currentTime - this._lastFrame | 0;
                    if (delta < this._minElapsedMS) {
                        return;
                    }
                    this._lastFrame = currentTime - (delta % this._minElapsedMS);
                }
                this.deltaMS = elapsedMS;
                this.deltaTime = this.deltaMS * settings.settings.TARGET_FPMS;
                // Cache a local reference, in-case ticker is destroyed
                // during the emit, we can still check for head.next
                var head = this._head;
                // Invoke listeners added to internal emitter
                var listener = head.next;
                while (listener) {
                    listener = listener.emit(this.deltaTime);
                }
                if (!head.next) {
                    this._cancelIfNeeded();
                }
            }
            else {
                this.deltaTime = this.deltaMS = this.elapsedMS = 0;
            }
            this.lastTime = currentTime;
        };
        Object.defineProperty(Ticker.prototype, "FPS", {
            /**
             * The frames per second at which this ticker is running.
             * The default is approximately 60 in most modern browsers.
             * **Note:** This does not factor in the value of
             * {@link PIXI.Ticker#speed}, which is specific
             * to scaling {@link PIXI.Ticker#deltaTime}.
             * @member {number}
             * @readonly
             */
            get: function () {
                return 1000 / this.elapsedMS;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Ticker.prototype, "minFPS", {
            /**
             * Manages the maximum amount of milliseconds allowed to
             * elapse between invoking {@link PIXI.Ticker#update}.
             * This value is used to cap {@link PIXI.Ticker#deltaTime},
             * but does not effect the measured value of {@link PIXI.Ticker#FPS}.
             * When setting this property it is clamped to a value between
             * `0` and `PIXI.settings.TARGET_FPMS * 1000`.
             * @member {number}
             * @default 10
             */
            get: function () {
                return 1000 / this._maxElapsedMS;
            },
            set: function (fps) {
                // Minimum must be below the maxFPS
                var minFPS = Math.min(this.maxFPS, fps);
                // Must be at least 0, but below 1 / settings.TARGET_FPMS
                var minFPMS = Math.min(Math.max(0, minFPS) / 1000, settings.settings.TARGET_FPMS);
                this._maxElapsedMS = 1 / minFPMS;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Ticker.prototype, "maxFPS", {
            /**
             * Manages the minimum amount of milliseconds required to
             * elapse between invoking {@link PIXI.Ticker#update}.
             * This will effect the measured value of {@link PIXI.Ticker#FPS}.
             * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.
             * Otherwise it will be at least `minFPS`
             * @member {number}
             * @default 0
             */
            get: function () {
                if (this._minElapsedMS) {
                    return Math.round(1000 / this._minElapsedMS);
                }
                return 0;
            },
            set: function (fps) {
                if (fps === 0) {
                    this._minElapsedMS = 0;
                }
                else {
                    // Max must be at least the minFPS
                    var maxFPS = Math.max(this.minFPS, fps);
                    this._minElapsedMS = 1 / (maxFPS / 1000);
                }
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Ticker, "shared", {
            /**
             * The shared ticker instance used by {@link PIXI.AnimatedSprite} and by
             * {@link PIXI.VideoResource} to update animation frames / video textures.
             *
             * It may also be used by {@link PIXI.Application} if created with the `sharedTicker` option property set to true.
             *
             * The property {@link PIXI.Ticker#autoStart} is set to `true` for this instance.
             * Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker.
             * @example
             * let ticker = PIXI.Ticker.shared;
             * // Set this to prevent starting this ticker when listeners are added.
             * // By default this is true only for the PIXI.Ticker.shared instance.
             * ticker.autoStart = false;
             * // FYI, call this to ensure the ticker is stopped. It should be stopped
             * // if you have not attempted to render anything yet.
             * ticker.stop();
             * // Call this when you are ready for a running shared ticker.
             * ticker.start();
             * @example
             * // You may use the shared ticker to render...
             * let renderer = PIXI.autoDetectRenderer();
             * let stage = new PIXI.Container();
             * document.body.appendChild(renderer.view);
             * ticker.add(function (time) {
             *     renderer.render(stage);
             * });
             * @example
             * // Or you can just update it manually.
             * ticker.autoStart = false;
             * ticker.stop();
             * function animate(time) {
             *     ticker.update(time);
             *     renderer.render(stage);
             *     requestAnimationFrame(animate);
             * }
             * animate(performance.now());
             * @member {PIXI.Ticker}
             * @static
             */
            get: function () {
                if (!Ticker._shared) {
                    var shared = Ticker._shared = new Ticker();
                    shared.autoStart = true;
                    shared._protected = true;
                }
                return Ticker._shared;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Ticker, "system", {
            /**
             * The system ticker instance used by {@link PIXI.InteractionManager} and by
             * {@link PIXI.BasePrepare} for core timing functionality that shouldn't usually need to be paused,
             * unlike the `shared` ticker which drives visual animations and rendering which may want to be paused.
             *
             * The property {@link PIXI.Ticker#autoStart} is set to `true` for this instance.
             * @member {PIXI.Ticker}
             * @static
             */
            get: function () {
                if (!Ticker._system) {
                    var system = Ticker._system = new Ticker();
                    system.autoStart = true;
                    system._protected = true;
                }
                return Ticker._system;
            },
            enumerable: false,
            configurable: true
        });
        return Ticker;
    }());

    /**
     * Middleware for for Application Ticker.
     * @example
     * import {TickerPlugin} from '@pixi/ticker';
     * import {Application} from '@pixi/app';
     * import {extensions} from '@pixi/core';
     * extensions.add(TickerPlugin);
     * @class
     * @memberof PIXI
     */
    var TickerPlugin = /** @class */ (function () {
        function TickerPlugin() {
        }
        /**
         * Initialize the plugin with scope of application instance
         * @static
         * @private
         * @param {object} [options] - See application options
         */
        TickerPlugin.init = function (options) {
            var _this = this;
            // Set default
            options = Object.assign({
                autoStart: true,
                sharedTicker: false,
            }, options);
            // Create ticker setter
            Object.defineProperty(this, 'ticker', {
                set: function (ticker) {
                    if (this._ticker) {
                        this._ticker.remove(this.render, this);
                    }
                    this._ticker = ticker;
                    if (ticker) {
                        ticker.add(this.render, this, exports.UPDATE_PRIORITY.LOW);
                    }
                },
                get: function () {
                    return this._ticker;
                },
            });
            /**
             * Convenience method for stopping the render.
             * @method
             * @memberof PIXI.Application
             * @instance
             */
            this.stop = function () {
                _this._ticker.stop();
            };
            /**
             * Convenience method for starting the render.
             * @method
             * @memberof PIXI.Application
             * @instance
             */
            this.start = function () {
                _this._ticker.start();
            };
            /**
             * Internal reference to the ticker.
             * @type {PIXI.Ticker}
             * @name _ticker
             * @memberof PIXI.Application#
             * @private
             */
            this._ticker = null;
            /**
             * Ticker for doing render updates.
             * @type {PIXI.Ticker}
             * @name ticker
             * @memberof PIXI.Application#
             * @default PIXI.Ticker.shared
             */
            this.ticker = options.sharedTicker ? Ticker.shared : new Ticker();
            // Start the rendering
            if (options.autoStart) {
                this.start();
            }
        };
        /**
         * Clean up the ticker, scoped to application.
         * @static
         * @private
         */
        TickerPlugin.destroy = function () {
            if (this._ticker) {
                var oldTicker = this._ticker;
                this.ticker = null;
                oldTicker.destroy();
            }
        };
        /** @ignore */
        TickerPlugin.extension = core.ExtensionType.Application;
        return TickerPlugin;
    }());

    exports.Ticker = Ticker;
    exports.TickerPlugin = TickerPlugin;

    Object.defineProperty(exports, '__esModule', { value: true });

    return exports;

})({}, PIXI, PIXI);
Object.assign(this.PIXI, _pixi_ticker);
//# sourceMappingURL=ticker.js.map
