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