pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
1 lines • 35.4 kB
Source Map (JSON)
{"version":3,"file":"GifSprite.mjs","sources":["../../src/gif/GifSprite.ts"],"sourcesContent":["import { Texture } from '../rendering/renderers/shared/texture/Texture';\nimport { Sprite, type SpriteOptions } from '../scene/sprite/Sprite';\nimport { UPDATE_PRIORITY } from '../ticker/const';\nimport { Ticker } from '../ticker/Ticker';\nimport { GifSource } from './GifSource';\n\nimport type { SCALE_MODE } from '../rendering/renderers/shared/texture/const';\n\n/**\n * Configuration options for creating a GifSprite instance.\n *\n * These options control both the visual appearance and playback behavior\n * of animated GIFs.\n * @example\n * ```ts\n * import { GifSprite, Assets } from 'pixi.js';\n *\n * // Create with options\n * const source = await Assets.load('animation.gif');\n * const options: GifSpriteOptions = {\n * source, // GIF data source\n * animationSpeed: 1.5, // 50% faster than normal\n * loop: true, // Loop the animation\n * autoPlay: true, // Start playing immediately\n * scaleMode: 'nearest', // Pixel art style scaling\n * onComplete: () => { // Called when non-looping animation ends\n * console.log('Animation complete!');\n * }\n * };\n *\n * const animation = new GifSprite(options);\n * ```\n * @category gif\n * @standard\n */\ninterface GifSpriteOptions extends Omit<SpriteOptions, 'texture'>\n{\n /**\n * Source containing the GIF frame and animation data\n * @see {@link GifSource}\n * @example\n * ```ts\n * const source = await Assets.load('animation.gif');\n * const animation = new GifSprite({ source });\n * ```\n */\n source: GifSource;\n /**\n * Whether to start playing right away when created.\n * If `false`, you must call {@link GifSprite.play} to start playback.\n * @default true\n * @example\n * ```ts\n * const animation = new GifSprite({ source, autoPlay: true });\n * ```\n * @see {@link GifSprite.play}\n */\n autoPlay?: boolean;\n /**\n * Scale Mode to use for the texture\n * @type {SCALE_MODE}\n * @default 'linear'\n * @example\n * ```ts\n * const animation = new GifSprite({ source, scaleMode: 'nearest' });\n * ```\n * @see {@link SCALE_MODE}\n */\n scaleMode?: SCALE_MODE;\n /**\n * Whether to loop the animation.\n * If `false`, the animation will stop after the last frame.\n * @default true\n * @example\n * ```ts\n * const animation = new GifSprite({ source, loop: false });\n * ```\n */\n loop?: boolean;\n /**\n * Animation playback speed multiplier.\n * Higher values speed up the animation, lower values slow it down.\n * @default 1\n * @example\n * ```ts\n * const animation = new GifSprite({ source, animationSpeed: 2 }); // 2x speed\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n animationSpeed?: number;\n /**\n * Whether to auto-update animation via shared ticker.\n * Set to `false` to manage updates yourself.\n * @default true\n * @example\n * ```ts\n * const animation = new GifSprite({ source, autoUpdate: false });\n * // Manage updates manually:\n * app.ticker.add((ticker) => {\n * animation.update(ticker);\n * });\n * ```\n */\n autoUpdate?: boolean;\n /**\n * Callback when non-looping animation completes.\n * This is only called if `loop` is set to `false`.\n * If `loop` is `true`, use {@link GifSprite.onLoop} instead.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onComplete: () => {\n * console.log('Animation finished!');\n * }\n * });\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n onComplete?: null | (() => void);\n /**\n * Callback when looping animation completes a loop.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onLoop: () => {\n * console.log('Animation looped!');\n * }\n * });\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n onLoop?: null | (() => void);\n /**\n * Callback when animation frame changes.\n * This is called every time the current frame changes,\n * allowing you to respond to frame changes in real-time.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onFrameChange: (currentFrame) => {\n * console.log(`Current frame: ${currentFrame}`);\n * }\n * });\n * ```\n * @see {@link GifSprite.currentFrame}\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n onFrameChange?: null | ((currentFrame: number) => void);\n /**\n * Fallback FPS if GIF contains no timing information\n * @default 30\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * fps: 24 // Use 24 FPS if GIF timing is missing\n * });\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n * @see {@link GifSprite.update}\n */\n fps?: number;\n}\n\n/**\n * Runtime object for playing animated GIFs with advanced playback control.\n *\n * Features:\n * - Play, pause, and seek controls\n * - Adjustable animation speed\n * - Loop control\n * - Frame change callbacks\n * - Auto-updating via shared ticker\n *\n * This class extends Sprite and provides similar functionality to AnimatedSprite,\n * but specifically optimized for GIF playback.\n * @example\n * ```ts\n * import { GifSprite, Assets } from 'pixi.js';\n *\n * // Load and create a GIF sprite\n * const source = await Assets.load('animation.gif');\n * const animation = new GifSprite({\n * source,\n * animationSpeed: 1,\n * loop: true,\n * autoPlay: true\n * });\n *\n * // Add to stage\n * app.stage.addChild(animation);\n *\n * // Control playback\n * animation.play();\n * animation.stop();\n * animation.currentFrame = 5; // Jump to frame\n * ```\n * @category gif\n * @see Thanks to {@link https://github.com/matt-way/gifuct-js/ gifuct-js}\n * @standard\n */\nclass GifSprite extends Sprite\n{\n /**\n * Default configuration options for GifSprite instances.\n *\n * These values are used when specific options are not provided to the constructor.\n * Each property can be overridden by passing it in the options object.\n * @example\n * ```ts\n * GifSprite.defaultOptions.fps = 24; // Change default FPS to 24\n * GifSprite.defaultOptions.loop = false; // Disable looping by default\n *\n * const animation = new GifSprite(); // Will use these defaults\n * ```\n */\n public static defaultOptions: Omit<GifSpriteOptions, 'source'> = {\n scaleMode: 'linear',\n fps: 30,\n loop: true,\n animationSpeed: 1,\n autoPlay: true,\n autoUpdate: true,\n onComplete: null,\n onFrameChange: null,\n onLoop: null,\n };\n\n /**\n * Animation playback speed multiplier.\n * Higher values speed up the animation, lower values slow it down.\n * @default 1\n * @example\n * ```ts\n * const animation = new GifSprite({ source });\n * animation.animationSpeed = 2; // 2x speed\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n public animationSpeed = 1;\n\n /**\n * Whether to loop the animation.\n * If `false`, the animation will stop after the last frame.\n * @default true\n * @example\n * ```ts\n * const animation = new GifSprite({ source, loop: false });\n * ```\n */\n public loop = true;\n\n /**\n * Callback when non-looping animation completes.\n * This is only called if `loop` is set to `false`.\n * If `loop` is `true`, use {@link GifSprite.onLoop} instead.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onComplete: () => {\n * console.log('Animation finished!');\n * }\n * });\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n public onComplete?: () => void;\n\n /**\n * Callback when animation frame changes.\n * This is called every time the current frame changes,\n * allowing you to respond to frame changes in real-time.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onFrameChange: (currentFrame) => {\n * console.log(`Current frame: ${currentFrame}`);\n * }\n * });\n * ```\n * @see {@link GifSprite.currentFrame}\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n public onFrameChange?: (currentFrame: number) => void;\n\n /**\n * Callback when looping animation completes a loop.\n * If `loop` is `false`, this will not be called.\n * @default null\n * @example\n * ```ts\n * const animation = new GifSprite({\n * source,\n * onLoop: () => {\n * console.log('Animation looped!');\n * }\n * });\n * ```\n * @see {@link GifSprite.play}\n * @see {@link GifSprite.stop}\n */\n public onLoop?: () => void;\n\n /**\n * The total duration of animation in milliseconds.\n * This represents the length of one complete animation cycle.\n * @example\n * ```ts\n * // Get animation duration\n * const animation = new GifSprite({ source });\n * console.log('Duration:', animation.duration); // e.g. 1000 for 1 second\n * ```\n * @readonly\n * @default 0\n * @remarks\n * - Set during initialization from last frame's end time\n * - Used for progress calculation and loop timing\n * - Value is in milliseconds\n * - Cannot be modified after creation\n * @see {@link GifSprite.progress} For animation progress\n * @see {@link GifSprite.currentFrame} For current frame number\n */\n public readonly duration: number = 0;\n\n /**\n * Whether to start playing right away when created.\n * If `false`, you must call {@link GifSprite.play} to start playback.\n * @default true\n * @example\n * ```ts\n * const animation = new GifSprite({ source, autoPlay: true });\n * ```\n * @see {@link GifSprite.play}\n */\n public readonly autoPlay: boolean = true;\n\n /** Collection of frame to render. */\n private _source: GifSource;\n\n /**\n * Dirty means the image needs to be redrawn. Set to `true` to force redraw.\n * @advanced\n */\n public dirty = false;\n\n /** The current frame number (zero-based index). */\n private _currentFrame = 0;\n\n /** `true` uses {@link Ticker.shared} to auto update animation time.*/\n private _autoUpdate = false;\n\n /** `true` if the instance is currently connected to {@link Ticker.shared} to auto update animation time. */\n private _isConnectedToTicker = false;\n\n /** If animation is currently playing. */\n private _playing = false;\n\n /** Current playback position in milliseconds. */\n private _currentTime = 0;\n\n /**\n * @param source - Source, default options will be used.\n */\n constructor(source: GifSource);\n\n /**\n * @param options - Options for the GifSprite\n */\n constructor(options: GifSpriteOptions);\n\n /** @ignore */\n constructor(...args: [GifSource] | [GifSpriteOptions])\n {\n const options = args[0] instanceof GifSource ? { source: args[0] } : args[0];\n\n // Get the options, apply defaults\n const {\n scaleMode,\n source,\n fps,\n loop,\n animationSpeed,\n autoPlay,\n autoUpdate,\n onComplete,\n onFrameChange,\n onLoop,\n ...rest\n } = Object.assign({},\n GifSprite.defaultOptions,\n options\n );\n\n super({ texture: Texture.EMPTY, ...rest });\n\n // Handle rerenders\n this.onRender = () => this._updateFrame();\n\n this.texture = source.textures[0];\n\n this.duration = source.frames[source.frames.length - 1].end;\n this._source = source;\n this._playing = false;\n this._currentTime = 0;\n this._isConnectedToTicker = false;\n Object.assign(this, {\n fps,\n loop,\n animationSpeed,\n autoPlay,\n autoUpdate,\n onComplete,\n onFrameChange,\n onLoop,\n });\n\n // Draw the first frame\n this.currentFrame = 0;\n if (autoPlay)\n {\n this.play();\n }\n }\n\n /**\n * Stops the animation playback.\n * Halts at the current frame and disconnects from the ticker if auto-updating.\n * @example\n * ```ts\n * // Basic stop\n * const animation = new GifSprite({ source });\n * animation.stop();\n *\n * // Stop at specific frame\n * animation.currentFrame = 5;\n * animation.stop();\n *\n * // Stop and reset\n * animation.currentFrame = 0;\n * animation.stop();\n * ```\n * @remarks\n * - Does nothing if animation is already stopped\n * - Maintains current frame position\n * - Disconnects from shared ticker if auto-updating\n * - Can be resumed with play()\n * @see {@link GifSprite.play} For resuming playback\n * @see {@link GifSprite.currentFrame} For frame control\n */\n public stop(): void\n {\n if (!this._playing)\n {\n return;\n }\n\n this._playing = false;\n if (this._autoUpdate && this._isConnectedToTicker)\n {\n Ticker.shared.remove(this.update, this);\n this._isConnectedToTicker = false;\n }\n }\n\n /**\n * Starts or resumes animation playback.\n * If animation is at the last frame and not looping, playback will restart from the beginning.\n * @example\n * ```ts\n * // Basic playback\n * const animation = new GifSprite({ source, autoPlay: false });\n * animation.play();\n *\n * // Play after stopping\n * animation.stop();\n * animation.play(); // Resumes from current frame\n *\n * // Play with auto-updating disabled\n * const animation = new GifSprite({\n * source,\n * autoPlay: false,\n * autoUpdate: false\n * });\n * animation.play();\n * app.ticker.add((ticker) => {\n * animation.update(ticker);\n * });\n * ```\n * @remarks\n * - Does nothing if animation is already playing\n * - Connects to shared ticker if autoUpdate is true\n * - Restarts from beginning if at last frame of non-looping animation\n * - Maintains current frame position otherwise\n * @see {@link GifSprite.stop} For stopping playback\n * @see {@link GifSprite.playing} For checking playback status\n * @see {@link GifSprite.autoUpdate} For controlling automatic updates\n */\n public play(): void\n {\n if (this._playing)\n {\n return;\n }\n\n this._playing = true;\n if (this._autoUpdate && !this._isConnectedToTicker)\n {\n Ticker.shared.add(this.update, this, UPDATE_PRIORITY.HIGH);\n this._isConnectedToTicker = true;\n }\n\n // If were on the last frame and stopped, play should resume from beginning\n if (!this.loop && this.currentFrame === this._source.frames.length - 1)\n {\n this._currentTime = 0;\n }\n }\n\n /**\n * Gets the current progress of the animation as a value between 0 and 1.\n * Useful for tracking animation completion and implementing progress bars.\n * @example\n * ```ts\n * // Basic progress tracking\n * const animation = new GifSprite({ source });\n * console.log('Progress:', Math.round(animation.progress * 100) + '%');\n *\n * // Update progress bar\n * app.ticker.add(() => {\n * progressBar.width = animation.progress * 200; // 200px total width\n * });\n *\n * // Check if animation is near end\n * if (animation.progress > 0.9) {\n * console.log('Animation almost complete!');\n * }\n * ```\n * @remarks\n * - Returns 0 at start\n * - Returns 1 when complete\n * - Updates continuously during playback\n * - Based on currentTime and total duration\n * @readonly\n * @see {@link GifSprite.duration} For total animation length\n */\n public get progress(): number\n {\n return this._currentTime / this.duration;\n }\n\n /** `true` if the current animation is playing */\n public get playing(): boolean\n {\n return this._playing;\n }\n\n /**\n * Updates the object transform for rendering.\n * This method is called automatically by the ticker if `autoUpdate` is enabled.\n * Only updates if the animation is currently playing.\n * > [!IMPORTANT] Call this manually when `autoUpdate` is set to `false` to control animation timing.\n * @param ticker - Ticker instance used to calculate frame timing\n * @example\n * ```ts\n * // Manual update with app ticker\n * const animation = new GifSprite({\n * source,\n * autoUpdate: false\n * });\n *\n * // Add to custom ticker\n * app.ticker.add(() => {\n * animation.update(app.ticker);\n * });\n *\n * // Update with custom timing\n * const customTicker = new Ticker();\n * customTicker.add(() => {\n * animation.update(customTicker);\n * });\n * ```\n * @see {@link GifSprite.autoUpdate} For automatic update control\n * @see {@link GifSprite.playing} For playback state\n * @see {@link Ticker} For timing system details\n */\n public update(ticker: Ticker): void\n {\n if (!this._playing)\n {\n return;\n }\n\n const elapsed = this.animationSpeed * ticker.deltaTime / Ticker.targetFPMS;\n const currentTime = this._currentTime + elapsed;\n const localTime = currentTime % this.duration;\n\n const localFrame = this._source.frames.findIndex((frame) =>\n frame.start <= localTime && frame.end > localTime);\n\n if (currentTime >= this.duration)\n {\n if (this.loop)\n {\n this._currentTime = localTime;\n this._updateFrameIndex(localFrame);\n this.onLoop?.();\n }\n else\n {\n this._currentTime = this.duration;\n this._updateFrameIndex(this.totalFrames - 1);\n this.onComplete?.();\n this.stop();\n }\n }\n else\n {\n this._currentTime = localTime;\n this._updateFrameIndex(localFrame);\n }\n }\n\n /** Redraw the current frame, is necessary for the animation to work when */\n private _updateFrame(): void\n {\n if (!this.dirty)\n {\n return;\n }\n\n // Update the current frame\n this.texture = this._source.frames[this._currentFrame].texture;\n\n // Mark as clean\n this.dirty = false;\n }\n\n /**\n * Whether to use {@link Ticker.shared} to auto update animation time.\n * Controls if the animation updates automatically using the shared ticker.\n * @example\n * ```ts\n * // Using auto-update (default)\n * const animation = new GifSprite({\n * source,\n * autoUpdate: true\n * });\n *\n * // Manual updates\n * const animation = new GifSprite({\n * source,\n * autoUpdate: false\n * });\n *\n * // Custom update loop\n * app.ticker.add(() => {\n * animation.update(app.ticker);\n * });\n *\n * // Switch update modes at runtime\n * animation.autoUpdate = false; // Disconnect from shared ticker\n * animation.autoUpdate = true; // Reconnect if playing\n * ```\n * @default true\n * @see {@link GifSprite.update} For manual updating\n * @see {@link Ticker.shared} For the shared ticker instance\n */\n get autoUpdate(): boolean\n {\n return this._autoUpdate;\n }\n\n set autoUpdate(value: boolean)\n {\n if (value !== this._autoUpdate)\n {\n this._autoUpdate = value;\n\n if (!this._autoUpdate && this._isConnectedToTicker)\n {\n Ticker.shared.remove(this.update, this);\n this._isConnectedToTicker = false;\n }\n else if (this._autoUpdate && !this._isConnectedToTicker && this._playing)\n {\n Ticker.shared.add(this.update, this);\n this._isConnectedToTicker = true;\n }\n }\n }\n\n /**\n * Gets or sets the current frame number.\n * Controls which frame of the GIF animation is currently displayed.\n * @example\n * ```ts\n * // Get current frame\n * const animation = new GifSprite({ source });\n * console.log('Current frame:', animation.currentFrame);\n *\n * // Jump to specific frame\n * animation.currentFrame = 5;\n *\n * // Reset to first frame\n * animation.currentFrame = 0;\n *\n * // Get frame at specific progress\n * const frameAtProgress = Math.floor(animation.totalFrames * 0.5); // 50%\n * animation.currentFrame = frameAtProgress;\n * ```\n * @throws {Error} If frame index is out of range\n * @remarks\n * - Zero-based index (0 to totalFrames-1)\n * - Updates animation time to frame start\n * - Triggers frame change callback\n * - Marks sprite as dirty for redraw\n * @see {@link GifSprite.totalFrames} For frame count\n * @see {@link GifSprite.onFrameChange} For frame change events\n */\n get currentFrame(): number\n {\n return this._currentFrame;\n }\n set currentFrame(value: number)\n {\n this._updateFrameIndex(value);\n this._currentTime = this._source.frames[value].start;\n }\n\n /**\n * The source GIF data containing frame textures and timing information.\n * This represents the underlying animation data used by the sprite.\n * @example\n * ```ts\n * // Access source data\n * const animation = new GifSprite({ source });\n * const frameCount = animation.source.totalFrames;\n * const frameTexture = animation.source.textures[0];\n *\n * // Share source between sprites\n * const clone = new GifSprite({\n * source: animation.source,\n * autoPlay: false\n * });\n *\n * // Check source properties\n * console.log('Total frames:', animation.source.totalFrames);\n * console.log('Frame timing:', animation.source.frames);\n * ```\n * @remarks\n * - Contains all frame textures\n * - Manages frame timing data\n * - Can be shared between sprites\n * - Destroyed with sprite if destroyData=true\n * @readonly\n * @see {@link GifSource} For source data implementation\n * @see {@link GifSprite.clone} For creating independent instances\n */\n get source(): GifSource\n {\n return this._source;\n }\n\n /**\n * Internally handle updating the frame index\n * @param value\n */\n private _updateFrameIndex(value: number): void\n {\n if (value < 0 || value >= this.totalFrames)\n {\n throw new Error(`Frame index out of range, expecting 0 to ${this.totalFrames}, got ${value}`);\n }\n if (this._currentFrame !== value)\n {\n this._currentFrame = value;\n this.dirty = true;\n this.onFrameChange?.(value);\n }\n }\n\n /**\n * Gets the total number of frames in the GIF animation.\n * @example\n * ```ts\n * // Get total frames\n * const animation = new GifSprite({ source });\n * console.log('Total frames:', animation.totalFrames);\n * ```\n * @readonly\n * @see {@link GifSprite.currentFrame} For current frame index\n * @see {@link GifSource.totalFrames} For source frame count\n */\n get totalFrames(): number\n {\n return this._source.totalFrames;\n }\n\n /**\n * Destroy and don't use after this.\n * @param destroyData - Destroy the data, cannot be used again.\n * @example\n * ```ts\n * const animation = new GifSprite({ source });\n * // Do something with animation...\n * animation.destroy(true); // Destroy the animation and its source data\n *\n * // If you want to keep the source data for reuse, use:\n * animation.destroy(false); // Destroy the animation but keep source data\n * ```\n */\n public destroy(destroyData: boolean = false): void\n {\n this.stop();\n super.destroy();\n\n if (destroyData)\n {\n this._source.destroy();\n }\n\n const forceClear = null as any;\n\n this._source = forceClear;\n this.onComplete = forceClear;\n this.onFrameChange = forceClear;\n this.onLoop = forceClear;\n }\n\n /**\n * Creates an independent copy of this GifSprite instance.\n * Useful for creating multiple animations that share the same source data\n * but can be controlled independently.\n * > [!IMPORTANT]\n * > The cloned sprite will have its own playback state, so you can play,\n * > pause, or seek it without affecting the original sprite.\n * @example\n * ```ts\n * // Create original animation\n * const animation = new GifSprite({ source });\n *\n * // Create independent clone\n * const clone = animation.clone();\n * clone.play(); // Plays independently\n * animation.stop(); // Original stops, clone continues\n *\n * // Clone with modified properties\n * const halfSpeed = animation.clone();\n * halfSpeed.animationSpeed = 0.5;\n * ```\n * @returns {GifSprite} A new GifSprite instance with the same properties\n * @see {@link GifSprite.source} For shared source data\n * @see {@link GifSprite.destroy} For cleanup\n */\n public clone(): GifSprite\n {\n const clone = new GifSprite({\n source: this._source,\n autoUpdate: this._autoUpdate,\n loop: this.loop,\n autoPlay: this.autoPlay,\n scaleMode: this.texture.source.scaleMode,\n animationSpeed: this.animationSpeed,\n onComplete: this.onComplete,\n onFrameChange: this.onFrameChange,\n onLoop: this.onLoop,\n });\n\n clone.dirty = true;\n\n return clone;\n }\n}\n\nexport { GifSprite };\nexport type { GifSpriteOptions };\n"],"names":[],"mappings":";;;;;;;AAoNA,MAAM,UAAA,GAAN,MAAM,UAAA,SAAkB,MACxB,CAAA;AAAA;AAAA,EAgLI,eAAe,IACf,EAAA;AACI,IAAA,MAAM,OAAU,GAAA,IAAA,CAAK,CAAC,CAAA,YAAa,SAAY,GAAA,EAAE,MAAQ,EAAA,IAAA,CAAK,CAAC,CAAA,EAAM,GAAA,IAAA,CAAK,CAAC,CAAA,CAAA;AAG3E,IAAM,MAAA;AAAA,MACF,SAAA;AAAA,MACA,MAAA;AAAA,MACA,GAAA;AAAA,MACA,IAAA;AAAA,MACA,cAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,MAAA;AAAA,MACA,GAAG,IAAA;AAAA,QACH,MAAO,CAAA,MAAA;AAAA,MAAO,EAAC;AAAA,MACf,UAAU,CAAA,cAAA;AAAA,MACV,OAAA;AAAA,KACJ,CAAA;AAEA,IAAA,KAAA,CAAM,EAAE,OAAS,EAAA,OAAA,CAAQ,KAAO,EAAA,GAAG,MAAM,CAAA,CAAA;AAhK7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,cAAiB,GAAA,CAAA,CAAA;AAWxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,IAAO,GAAA,IAAA,CAAA;AA8Ed;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAgB,QAAmB,GAAA,CAAA,CAAA;AAYnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAgB,QAAoB,GAAA,IAAA,CAAA;AASpC;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,KAAQ,GAAA,KAAA,CAAA;AAGf;AAAA,IAAA,IAAA,CAAQ,aAAgB,GAAA,CAAA,CAAA;AAGxB;AAAA,IAAA,IAAA,CAAQ,WAAc,GAAA,KAAA,CAAA;AAGtB;AAAA,IAAA,IAAA,CAAQ,oBAAuB,GAAA,KAAA,CAAA;AAG/B;AAAA,IAAA,IAAA,CAAQ,QAAW,GAAA,KAAA,CAAA;AAGnB;AAAA,IAAA,IAAA,CAAQ,YAAe,GAAA,CAAA,CAAA;AAsCnB,IAAK,IAAA,CAAA,QAAA,GAAW,MAAM,IAAA,CAAK,YAAa,EAAA,CAAA;AAExC,IAAK,IAAA,CAAA,OAAA,GAAU,MAAO,CAAA,QAAA,CAAS,CAAC,CAAA,CAAA;AAEhC,IAAA,IAAA,CAAK,WAAW,MAAO,CAAA,MAAA,CAAO,OAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAE,CAAA,GAAA,CAAA;AACxD,IAAA,IAAA,CAAK,OAAU,GAAA,MAAA,CAAA;AACf,IAAA,IAAA,CAAK,QAAW,GAAA,KAAA,CAAA;AAChB,IAAA,IAAA,CAAK,YAAe,GAAA,CAAA,CAAA;AACpB,IAAA,IAAA,CAAK,oBAAuB,GAAA,KAAA,CAAA;AAC5B,IAAA,MAAA,CAAO,OAAO,IAAM,EAAA;AAAA,MAChB,GAAA;AAAA,MACA,IAAA;AAAA,MACA,cAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,MAAA;AAAA,KACH,CAAA,CAAA;AAGD,IAAA,IAAA,CAAK,YAAe,GAAA,CAAA,CAAA;AACpB,IAAA,IAAI,QACJ,EAAA;AACI,MAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AAAA,KACd;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BO,IACP,GAAA;AACI,IAAI,IAAA,CAAC,KAAK,QACV,EAAA;AACI,MAAA,OAAA;AAAA,KACJ;AAEA,IAAA,IAAA,CAAK,QAAW,GAAA,KAAA,CAAA;AAChB,IAAI,IAAA,IAAA,CAAK,WAAe,IAAA,IAAA,CAAK,oBAC7B,EAAA;AACI,MAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,EAAQ,IAAI,CAAA,CAAA;AACtC,MAAA,IAAA,CAAK,oBAAuB,GAAA,KAAA,CAAA;AAAA,KAChC;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCO,IACP,GAAA;AACI,IAAA,IAAI,KAAK,QACT,EAAA;AACI,MAAA,OAAA;AAAA,KACJ;AAEA,IAAA,IAAA,CAAK,QAAW,GAAA,IAAA,CAAA;AAChB,IAAA,IAAI,IAAK,CAAA,WAAA,IAAe,CAAC,IAAA,CAAK,oBAC9B,EAAA;AACI,MAAA,MAAA,CAAO,OAAO,GAAI,CAAA,IAAA,CAAK,MAAQ,EAAA,IAAA,EAAM,gBAAgB,IAAI,CAAA,CAAA;AACzD,MAAA,IAAA,CAAK,oBAAuB,GAAA,IAAA,CAAA;AAAA,KAChC;AAGA,IAAI,IAAA,CAAC,KAAK,IAAQ,IAAA,IAAA,CAAK,iBAAiB,IAAK,CAAA,OAAA,CAAQ,MAAO,CAAA,MAAA,GAAS,CACrE,EAAA;AACI,MAAA,IAAA,CAAK,YAAe,GAAA,CAAA,CAAA;AAAA,KACxB;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,IAAW,QACX,GAAA;AACI,IAAO,OAAA,IAAA,CAAK,eAAe,IAAK,CAAA,QAAA,CAAA;AAAA,GACpC;AAAA;AAAA,EAGA,IAAW,OACX,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,QAAA,CAAA;AAAA,GAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BO,OAAO,MACd,EAAA;AACI,IAAI,IAAA,CAAC,KAAK,QACV,EAAA;AACI,MAAA,OAAA;AAAA,KACJ;AAEA,IAAA,MAAM,OAAU,GAAA,IAAA,CAAK,cAAiB,GAAA,MAAA,CAAO,YAAY,MAAO,CAAA,UAAA,CAAA;AAChE,IAAM,MAAA,WAAA,GAAc,KAAK,YAAe,GAAA,OAAA,CAAA;AACxC,IAAM,MAAA,SAAA,GAAY,cAAc,IAAK,CAAA,QAAA,CAAA;AAErC,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,OAAQ,CAAA,MAAA,CAAO,SAAU,CAAA,CAAC,KAC9C,KAAA,KAAA,CAAM,KAAS,IAAA,SAAA,IAAa,KAAM,CAAA,GAAA,GAAM,SAAS,CAAA,CAAA;AAErD,IAAI,IAAA,WAAA,IAAe,KAAK,QACxB,EAAA;AACI,MAAA,IAAI,KAAK,IACT,EAAA;AACI,QAAA,IAAA,CAAK,YAAe,GAAA,SAAA,CAAA;AACpB,QAAA,IAAA,CAAK,kBAAkB,UAAU,CAAA,CAAA;AACjC,QAAA,IAAA,CAAK,MAAS,IAAA,CAAA;AAAA,OAGlB,MAAA;AACI,QAAA,IAAA,CAAK,eAAe,IAAK,CAAA,QAAA,CAAA;AACzB,QAAK,IAAA,CAAA,iBAAA,CAAkB,IAAK,CAAA,WAAA,GAAc,CAAC,CAAA,CAAA;AAC3C,QAAA,IAAA,CAAK,UAAa,IAAA,CAAA;AAClB,QAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AAAA,OACd;AAAA,KAGJ,MAAA;AACI,MAAA,IAAA,CAAK,YAAe,GAAA,SAAA,CAAA;AACpB,MAAA,IAAA,CAAK,kBAAkB,UAAU,CAAA,CAAA;AAAA,KACrC;AAAA,GACJ;AAAA;AAAA,EAGQ,YACR,GAAA;AACI,IAAI,IAAA,CAAC,KAAK,KACV,EAAA;AACI,MAAA,OAAA;AAAA,KACJ;AAGA,IAAA,IAAA,CAAK,UAAU,IAAK,CAAA,OAAA,CAAQ,MAAO,CAAA,IAAA,CAAK,aAAa,CAAE,CAAA,OAAA,CAAA;AAGvD,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AAAA,GACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,IAAI,UACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,WAAA,CAAA;AAAA,GAChB;AAAA,EAEA,IAAI,WAAW,KACf,EAAA;AACI,IAAI,IAAA,KAAA,KAAU,KAAK,WACnB,EAAA;AACI,MAAA,IAAA,CAAK,WAAc,GAAA,KAAA,CAAA;AAEnB,MAAA,IAAI,CAAC,IAAA,CAAK,WAAe,IAAA,IAAA,CAAK,oBAC9B,EAAA;AACI,QAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,EAAQ,IAAI,CAAA,CAAA;AACtC,QAAA,IAAA,CAAK,oBAAuB,GAAA,KAAA,CAAA;AAAA,iBAEvB,IAAK,CAAA,WAAA,IAAe,CAAC,IAAK,CAAA,oBAAA,IAAwB,KAAK,QAChE,EAAA;AACI,QAAA,MAAA,CAAO,MAAO,CAAA,GAAA,CAAI,IAAK,CAAA,MAAA,EAAQ,IAAI,CAAA,CAAA;AACnC,QAAA,IAAA,CAAK,oBAAuB,GAAA,IAAA,CAAA;AAAA,OAChC;AAAA,KACJ;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,IAAI,YACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,aAAA,CAAA;AAAA,GAChB;AAAA,EACA,IAAI,aAAa,KACjB,EAAA;AACI,IAAA,IAAA,CAAK,kBAAkB,KAAK,CAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,YAAe,GAAA,IAAA,CAAK,OAAQ,CAAA,MAAA,CAAO,KAAK,CAAE,CAAA,KAAA,CAAA;AAAA,GACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,IAAI,MACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,OAAA,CAAA;AAAA,GAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAAkB,KAC1B,EAAA;AACI,IAAA,IAAI,KAAQ,GAAA,CAAA,IAAK,KAAS,IAAA,IAAA,CAAK,WAC/B,EAAA;AACI,MAAA,MAAM,IAAI,KAAM,CAAA,CAAA,yCAAA,EAA4C,KAAK,WAAW,CAAA,MAAA,EAAS,KAAK,CAAE,CAAA,CAAA,CAAA;AAAA,KAChG;AACA,IAAI,IAAA,IAAA,CAAK,kBAAkB,KAC3B,EAAA;AACI,MAAA,IAAA,CAAK,aAAgB,GAAA,KAAA,CAAA;AACrB,MAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AACb,MAAA,IAAA,CAAK,gBAAgB,KAAK,CAAA,CAAA;AAAA,KAC9B;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,IAAI,WACJ,GAAA;AACI,IAAA,OAAO,KAAK,OAAQ,CAAA,WAAA,CAAA;AAAA,GACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeO,OAAA,CAAQ,cAAuB,KACtC,EAAA;AACI,IAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,IAAA,KAAA,CAAM,OAAQ,EAAA,CAAA;AAEd,IAAA,IAAI,WACJ,EAAA;AACI,MAAA,IAAA,CAAK,QAAQ,OAAQ,EAAA,CAAA;AAAA,KACzB;AAEA,IAAA,MAAM,UAAa,GAAA,IAAA,CAAA;AAEnB,IAAA,IAAA,CAAK,OAAU,GAAA,UAAA,CAAA;AACf,IAAA,IAAA,CAAK,UAAa,GAAA,UAAA,CAAA;AAClB,IAAA,IAAA,CAAK,aAAgB,GAAA,UAAA,CAAA;AACrB,IAAA,IAAA,CAAK,MAAS,GAAA,UAAA,CAAA;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BO,KACP,GAAA;AACI,IAAM,MAAA,KAAA,GAAQ,IAAI,UAAU,CAAA;AAAA,MACxB,QAAQ,IAAK,CAAA,OAAA;AAAA,MACb,YAAY,IAAK,CAAA,WAAA;AAAA,MACjB,MAAM,IAAK,CAAA,IAAA;AAAA,MACX,UAAU,IAAK,CAAA,QAAA;AAAA,MACf,SAAA,EAAW,IAAK,CAAA,OAAA,CAAQ,MAAO,CAAA,SAAA;AAAA,MAC/B,gBAAgB,IAAK,CAAA,cAAA;AAAA,MACrB,YAAY,IAAK,CAAA,UAAA;AAAA,MACjB,eAAe,IAAK,CAAA,aAAA;AAAA,MACpB,QAAQ,IAAK,CAAA,MAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAA,KAAA,CAAM,KAAQ,GAAA,IAAA,CAAA;AAEd,IAAO,OAAA,KAAA,CAAA;AAAA,GACX;AACJ,CAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAtqBM,UAAA,CAeY,cAAmD,GAAA;AAAA,EAC7D,SAAW,EAAA,QAAA;AAAA,EACX,GAAK,EAAA,EAAA;AAAA,EACL,IAAM,EAAA,IAAA;AAAA,EACN,cAAgB,EAAA,CAAA;AAAA,EAChB,QAAU,EAAA,IAAA;AAAA,EACV,UAAY,EAAA,IAAA;AAAA,EACZ,UAAY,EAAA,IAAA;AAAA,EACZ,aAAe,EAAA,IAAA;AAAA,EACf,MAAQ,EAAA,IAAA;AACZ,CAAA,CAAA;AAzBJ,IAAM,SAAN,GAAA;;;;"}