{"version":3,"file":"Ticker.mjs","sources":["../../src/ticker/Ticker.ts"],"sourcesContent":["import { UPDATE_PRIORITY } from './const';\nimport { TickerListener } from './TickerListener';\n\n/**\n * A callback which can be added to a ticker.\n * The callback receives the Ticker instance as its parameter, providing access to timing properties.\n * @example\n * ```ts\n * ticker.add((ticker) => {\n *    // Access deltaTime (dimensionless scalar ~1.0 at 60fps)\n *    sprite.rotation += 0.1 * ticker.deltaTime;\n *\n *    // Access deltaMS (milliseconds elapsed)\n *    const progress = ticker.deltaMS / animationDuration;\n * });\n * ```\n * @category ticker\n * @standard\n */\nexport type TickerCallback<T> = (this: T, ticker: Ticker) => any;\n\n/**\n * A Ticker class that runs an update loop that other objects listen to.\n * Used for managing animation frames and timing in a PixiJS application.\n *\n * It provides a way to add listeners that will be called on each frame,\n * allowing for smooth animations and updates.\n *\n * ## Time Units\n * - `deltaTime`: Dimensionless scalar (typically ~1.0 at 60 FPS) for frame-independent animations\n * - `deltaMS`: Milliseconds elapsed (capped and speed-scaled) for time-based calculations\n * - `elapsedMS`: Raw milliseconds elapsed (uncapped, unscaled) for measurements\n * - `lastTime`: Timestamp in milliseconds since epoch (performance.now() format)\n *\n * Animation frames are requested\n * only when necessary, e.g., when the ticker is started and the emitter has listeners.\n * @example\n * ```ts\n * // Basic ticker usage with different time units\n * const ticker = new Ticker();\n * ticker.add((ticker) => {\n *     // Frame-independent animation using dimensionless deltaTime\n *     sprite.rotation += 0.1 * ticker.deltaTime;\n *\n *     // Time-based animation using deltaMS (milliseconds)\n *     sprite.x += (100 / 1000) * ticker.deltaMS; // 100 pixels per second\n * });\n * ticker.start();\n *\n * // Control update priority\n * ticker.add(\n *     (ticker) => {\n *         // High priority updates run first\n *         physics.update(ticker.deltaTime);\n *     },\n *     undefined,\n *     UPDATE_PRIORITY.HIGH\n * );\n *\n * // One-time updates\n * ticker.addOnce(() => {\n *     console.log('Runs on next frame only');\n * });\n * ```\n * @see {@link TickerPlugin} For use with Application\n * @see {@link UPDATE_PRIORITY} For priority constants\n * @see {@link TickerCallback} For listener function type\n * @category ticker\n * @standard\n */\nexport class Ticker\n{\n    /**\n     * Target frame rate in frames per millisecond.\n     * Used for converting deltaTime to a scalar time delta.\n     * @example\n     * ```ts\n     * // Default is 0.06 (60 FPS)\n     * console.log(Ticker.targetFPMS); // 0.06\n     *\n     * // Calculate target frame duration\n     * const frameDuration = 1 / Ticker.targetFPMS; // ≈ 16.67ms\n     *\n     * // Use in custom timing calculations\n     * const deltaTime = elapsedMS * Ticker.targetFPMS;\n     * ```\n     * @remarks\n     * - Default is 0.06 (equivalent to 60 FPS)\n     * - Used in deltaTime calculations\n     * - Affects all ticker instances\n     * @default 0.06\n     * @see {@link Ticker#deltaTime} For time scaling\n     * @see {@link Ticker#FPS} For actual frame rate\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 {@link Ticker#start|start}\n     * automatically when a listener is added.\n     * @example\n     * ```ts\n     * // Default behavior (manual start)\n     * const ticker = new Ticker();\n     * ticker.autoStart = false;\n     * ticker.add(() => {\n     *     // Won't run until ticker.start() is called\n     * });\n     *\n     * // Auto-start behavior\n     * const autoTicker = new Ticker();\n     * autoTicker.autoStart = true;\n     * autoTicker.add(() => {\n     *     // Runs immediately when added\n     * });\n     * ```\n     * @default false\n     * @see {@link Ticker#start} For manually starting the ticker\n     * @see {@link Ticker#stop} For manually stopping the ticker\n     */\n    public autoStart = false;\n    /**\n     * Scalar representing the delta time factor.\n     * This is a dimensionless value representing the fraction of a frame at the target framerate.\n     * At 60 FPS, this value is typically around 1.0.\n     *\n     * This is NOT in milliseconds - it's a scalar multiplier for frame-independent animations.\n     * For actual milliseconds, use {@link Ticker#deltaMS}.\n     * @example\n     * ```ts\n     * // Frame-independent animation using deltaTime scalar\n     * ticker.add((ticker) => {\n     *     // Rotate sprite by 0.1 radians per frame, scaled by deltaTime\n     *     sprite.rotation += 0.1 * ticker.deltaTime;\n     * });\n     * ```\n     */\n    public deltaTime: number = 1;\n    /**\n     * Scalar time elapsed in milliseconds from last frame to this frame.\n     * Provides precise timing for animations and updates.\n     *\n     * This value is capped by setting {@link Ticker#minFPS|minFPS}\n     * and is scaled with {@link Ticker#speed|speed}.\n     *\n     * If the platform supports DOMHighResTimeStamp,\n     * this value will have a precision of 1 µs.\n     *\n     * Defaults to target frame time\n     *\n     * > [!NOTE] The cap may be exceeded by scaling.\n     * @example\n     * ```ts\n     * // Animation timing\n     * ticker.add((ticker) => {\n     *     // Use millisecond timing for precise animations\n     *     const progress = (ticker.deltaMS / animationDuration);\n     *     sprite.alpha = Math.min(1, progress);\n     * });\n     * ```\n     * @default 16.66\n     */\n    public deltaMS: number;\n    /**\n     * Time elapsed in milliseconds from the last frame to this frame.\n     * This value is not capped or scaled and provides raw timing information.\n     *\n     * Unlike {@link Ticker#deltaMS}, this value is unmodified by speed scaling or FPS capping.\n     * @example\n     * ```ts\n     * ticker.add((ticker) => {\n     *     console.log(`Raw frame time: ${ticker.elapsedMS}ms`);\n     * });\n     * ```\n     */\n    public elapsedMS: number;\n    /**\n     * The last time update was invoked, in milliseconds since epoch.\n     * Similar to performance.now() timestamp format.\n     *\n     * Used internally for calculating time deltas between frames.\n     * @example\n     * ```ts\n     * ticker.add((ticker) => {\n     *     const currentTime = performance.now();\n     *     const timeSinceLastFrame = currentTime - ticker.lastTime;\n     *     console.log(`Time since last frame: ${timeSinceLastFrame}ms`);\n     * });\n     * ```\n     */\n    public lastTime: number = -1;\n    /**\n     * Factor of current {@link Ticker#deltaTime|deltaTime}.\n     * Used to scale time for slow motion or fast-forward effects.\n     * @example\n     * ```ts\n     * // Basic speed adjustment\n     * ticker.speed = 0.5; // Half speed (slow motion)\n     * ticker.speed = 2.0; // Double speed (fast forward)\n     *\n     * // Temporary speed changes\n     * function slowMotion() {\n     *     const normalSpeed = ticker.speed;\n     *     ticker.speed = 0.2;\n     *     setTimeout(() => {\n     *         ticker.speed = normalSpeed;\n     *     }, 1000);\n     * }\n     * ```\n     */\n    public speed = 1;\n    /**\n     * Whether or not this ticker has been started.\n     *\n     * `true` if {@link Ticker#start|start} has been called.\n     * `false` if {@link Ticker#stop|Stop} has been called.\n     *\n     * While `false`, this value may change to `true` in the\n     * event of {@link Ticker#autoStart|autoStart} being `true`\n     * and a listener is added.\n     * @example\n     * ```ts\n     * // Check ticker state\n     * const ticker = new Ticker();\n     * console.log(ticker.started); // false\n     *\n     * // Start and verify\n     * ticker.start();\n     * console.log(ticker.started); // true\n     * ```\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 maxFPS 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 readonly _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     */\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    /** Conditionally cancels a pending animation frame. */\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     */\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.\n     * @param fn - The listener function to add. Receives the Ticker instance as parameter\n     * @param context - The context for the listener\n     * @param priority - The priority of the listener\n     * @example\n     * ```ts\n     * // Access time properties through the ticker parameter\n     * ticker.add((ticker) => {\n     *     // Use deltaTime (dimensionless scalar) for frame-independent animations\n     *     sprite.rotation += 0.1 * ticker.deltaTime;\n     *\n     *     // Use deltaMS (milliseconds) for time-based calculations\n     *     const progress = ticker.deltaMS / animationDuration;\n     *\n     *     // Use elapsedMS for raw timing measurements\n     *     console.log(`Raw frame time: ${ticker.elapsedMS}ms`);\n     * });\n     * ```\n     */\n    public add<T = any>(fn: TickerCallback<T>, context?: T, priority: number = 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 executed once on the next frame.\n     * @example\n     * ```ts\n     * // Basic one-time update\n     * ticker.addOnce(() => {\n     *     console.log('Runs next frame only');\n     * });\n     *\n     * // With specific context\n     * const game = {\n     *     init(ticker) {\n     *         this.loadResources();\n     *         console.log('Game initialized');\n     *     }\n     * };\n     * ticker.addOnce(game.init, game);\n     *\n     * // With priority\n     * ticker.addOnce(\n     *     () => {\n     *         // High priority one-time setup\n     *         physics.init();\n     *     },\n     *     undefined,\n     *     UPDATE_PRIORITY.HIGH\n     * );\n     * ```\n     * @param fn - The listener function to be added for one update\n     * @param context - The listener context\n     * @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)\n     * @returns This instance of a ticker\n     * @see {@link Ticker#add} For continuous updates\n     * @see {@link Ticker#remove} For removing handlers\n     */\n    public addOnce<T = any>(fn: TickerCallback<T>, context?: T, priority: number = 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     * @example\n     * ```ts\n     * // Basic removal\n     * const onTick = () => {\n     *     sprite.rotation += 0.1;\n     * };\n     * ticker.add(onTick);\n     * ticker.remove(onTick);\n     *\n     * // Remove with context\n     * const game = {\n     *     update(ticker) {\n     *         this.physics.update(ticker.deltaTime);\n     *     }\n     * };\n     * ticker.add(game.update, game);\n     * ticker.remove(game.update, game);\n     *\n     * // Remove all matching handlers\n     * // (if same function was added multiple times)\n     * ticker.add(onTick);\n     * ticker.add(onTick);\n     * ticker.remove(onTick); // Removes all instances\n     * ```\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     * @see {@link Ticker#add} For adding handlers\n     * @see {@link Ticker#addOnce} For one-time handlers\n     */\n    public 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     * @example\n     * ```ts\n     * // Check number of active listeners\n     * const ticker = new Ticker();\n     * console.log(ticker.count); // 0\n     *\n     * // Add some listeners\n     * ticker.add(() => {});\n     * ticker.add(() => {});\n     * console.log(ticker.count); // 2\n     *\n     * // Check after cleanup\n     * ticker.destroy();\n     * console.log(ticker.count); // 0\n     * ```\n     * @readonly\n     * @see {@link Ticker#add} For adding listeners\n     * @see {@link Ticker#remove} For removing listeners\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    /**\n     * Starts the ticker. If the ticker has listeners a new animation frame is requested at this point.\n     * @example\n     * ```ts\n     * // Basic manual start\n     * const ticker = new Ticker();\n     * ticker.add(() => {\n     *     // Animation code here\n     * });\n     * ticker.start();\n     * ```\n     * @see {@link Ticker#stop} For stopping the ticker\n     * @see {@link Ticker#autoStart} For automatic starting\n     * @see {@link Ticker#started} For checking ticker state\n     */\n    public start(): void\n    {\n        if (!this.started)\n        {\n            this.started = true;\n            this._requestIfNeeded();\n        }\n    }\n\n    /**\n     * Stops the ticker. If the ticker has requested an animation frame it is canceled at this point.\n     * @example\n     * ```ts\n     * // Basic stop\n     * const ticker = new Ticker();\n     * ticker.stop();\n     * ```\n     * @see {@link Ticker#start} For starting the ticker\n     * @see {@link Ticker#started} For checking ticker state\n     * @see {@link Ticker#destroy} For cleaning up the ticker\n     */\n    public stop(): void\n    {\n        if (this.started)\n        {\n            this.started = false;\n            this._cancelIfNeeded();\n        }\n    }\n\n    /**\n     * Destroy the ticker and don't use after this. Calling this method removes all references to internal events.\n     * @example\n     * ```ts\n     * // Clean up with active listeners\n     * const ticker = new Ticker();\n     * ticker.add(() => {});\n     * ticker.destroy(); // Removes all listeners\n     * ```\n     * @see {@link Ticker#stop} For stopping without destroying\n     * @see {@link Ticker#remove} For removing specific listeners\n     */\n    public 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.\n     *\n     * An update entails setting the\n     * current {@link Ticker#elapsedMS|elapsedMS},\n     * the current {@link Ticker#deltaTime|deltaTime},\n     * invoking all listeners with current deltaTime,\n     * and then finally setting {@link Ticker#lastTime|lastTime}\n     * with the value of currentTime that was provided.\n     *\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     * @example\n     * ```ts\n     * // Basic manual update\n     * const ticker = new Ticker();\n     * ticker.update(performance.now());\n     * ```\n     * @param currentTime - The current time of execution (defaults to performance.now())\n     * @see {@link Ticker#deltaTime} For frame delta value\n     * @see {@link Ticker#elapsedMS} For raw elapsed time\n     */\n    public update(currentTime: number = 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);\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 Ticker#speed|speed}, which is specific\n     * > to scaling {@link Ticker#deltaTime|deltaTime}.\n     * @example\n     * ```ts\n     * // Basic FPS monitoring\n     * ticker.add(() => {\n     *     console.log(`Current FPS: ${Math.round(ticker.FPS)}`);\n     * });\n     * ```\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 Ticker#update|update}.\n     *\n     * This value is used to cap {@link Ticker#deltaTime|deltaTime},\n     * but does not effect the measured value of {@link Ticker#FPS|FPS}.\n     *\n     * When setting this property it is clamped to a value between\n     * `0` and `Ticker.targetFPMS * 1000` (typically 60).\n     *\n     * If `maxFPS` is currently set (non-zero) and `minFPS` is set above it,\n     * `maxFPS` is automatically raised to match. This keeps the two limits consistent.\n     * @example\n     * ```ts\n     * // Set minimum acceptable frame rate\n     * const ticker = new Ticker();\n     * ticker.minFPS = 30; // Never go below 30 FPS\n     *\n     * // Use with maxFPS for frame rate clamping\n     * ticker.minFPS = 30;\n     * ticker.maxFPS = 60;\n     *\n     * // minFPS above maxFPS pushes maxFPS up\n     * ticker.minFPS = 50; // maxFPS is raised to 50\n     * ```\n     * @default 10\n     */\n    get minFPS(): number\n    {\n        return 1000 / this._maxElapsedMS;\n    }\n\n    set minFPS(fps: number)\n    {\n        // Must be at least 0, but below 1 / Ticker.targetFPMS\n        const minFPMS = Math.min(Math.max(0, fps) / 1000, Ticker.targetFPMS);\n\n        this._maxElapsedMS = 1 / minFPMS;\n\n        // If maxFPS is set (non-zero) and now lower than minFPS, push it up\n        if (this._minElapsedMS && fps > this.maxFPS)\n        {\n            this.maxFPS = fps;\n        }\n    }\n\n    /**\n     * Manages the minimum amount of milliseconds required to\n     * elapse between invoking {@link Ticker#update|update}.\n     *\n     * This will effect the measured value of {@link Ticker#FPS|FPS}.\n     *\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     *\n     * If `maxFPS` is set below the current `minFPS`, `minFPS` is automatically lowered to match.\n     * This keeps the two limits consistent.\n     * @example\n     * ```ts\n     * // Cap the frame rate\n     * const ticker = new Ticker();\n     * ticker.maxFPS = 60; // Never go above 60 FPS\n     *\n     * // Use with minFPS for frame rate clamping\n     * ticker.minFPS = 30;\n     * ticker.maxFPS = 60;\n     *\n     * // maxFPS below minFPS pushes minFPS down\n     * ticker.maxFPS = 20; // minFPS is now also 20\n     * ```\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            if (fps < this.minFPS)\n            {\n                this.minFPS = fps;\n            }\n\n            this._minElapsedMS = 1 / (fps / 1000);\n        }\n    }\n\n    /**\n     * The shared ticker instance used by {@link AnimatedSprite} and by\n     * {@link VideoSource} to update animation frames / video textures.\n     *\n     * It may also be used by {@link Application} if created with the `sharedTicker` option property set to true.\n     *\n     * The property {@link Ticker#autoStart|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 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     * @type {Ticker}\n     * @readonly\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 PrepareBase} 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 Ticker#autoStart|autoStart} is set to `true` for this instance.\n     * @type {Ticker}\n     * @readonly\n     * @advanced\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":[],"mappings":"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"}