{"version":3,"file":"PrepareBase.mjs","sources":["../../src/prepare/PrepareBase.ts"],"sourcesContent":["import { Container } from '../scene/container/Container';\nimport { UPDATE_PRIORITY } from '../ticker/const';\nimport { Ticker } from '../ticker/Ticker';\n\nimport type { TextureSource } from '../rendering/renderers/shared/texture/sources/TextureSource';\nimport type { Texture } from '../rendering/renderers/shared/texture/Texture';\nimport type { Renderer } from '../rendering/renderers/types';\nimport type { GraphicsContext } from '../scene/graphics/shared/GraphicsContext';\nimport type { Text } from '../scene/text/Text';\n\n/** The accepted types to pass to the prepare system */\nexport type PrepareSourceItem = Container | TextureSource | Texture | GraphicsContext;\n\n/** The valid types resolved to the queue ready for upload */\nexport type PrepareQueueItem = TextureSource | Text | GraphicsContext;\n\n/**\n * Part of the prepare system. Responsible for uploading all the items to the GPU.\n * This class provides the base functionality and handles processing the queue asynchronously.\n * @memberof rendering\n */\nexport abstract class PrepareBase\n{\n    /** The number of uploads to process per frame */\n    public static uploadsPerFrame = 4;\n\n    /** Reference to the renderer */\n    protected renderer: Renderer;\n\n    /** The queue to process over a async timer */\n    protected queue: PrepareQueueItem[];\n\n    /** Collection of callbacks to call when the uploads are finished */\n    protected resolves: ((value: void | PromiseLike<void>) => void)[];\n\n    /** Timeout id for next processing call */\n    protected timeout?: number;\n\n    /**\n     * @param {rendering.Renderer} renderer - A reference to the current renderer\n     */\n    constructor(renderer: Renderer)\n    {\n        this.renderer = renderer;\n        this.queue = [];\n        this.resolves = [];\n    }\n\n    /** Resolve the given resource type and return an item for the queue */\n    protected abstract resolveQueueItem(source: PrepareSourceItem, queue: PrepareQueueItem[]): void;\n    protected abstract uploadQueueItem(item: PrepareQueueItem): void;\n\n    /**\n     * Return a copy of the queue\n     * @returns {PrepareQueueItem[]} The queue\n     */\n    public getQueue(): PrepareQueueItem[]\n    {\n        return [...this.queue];\n    }\n\n    /**\n     * Add a textures or graphics resource to the queue\n     * @param {PrepareSourceItem | PrepareSourceItem[]} resource\n     */\n    public add(resource: PrepareSourceItem | PrepareSourceItem[]): this\n    {\n        const resourceArray = Array.isArray(resource) ? resource : [resource];\n\n        for (const resourceItem of resourceArray)\n        {\n            // handle containers and their children\n            if (resourceItem instanceof Container)\n            {\n                this._addContainer(resourceItem);\n            }\n            else\n            {\n                this.resolveQueueItem(resourceItem, this.queue);\n            }\n        }\n\n        return this;\n    }\n\n    /**\n     * Recursively add a container and its children to the queue\n     * @param {Container} container - The container to add to the queue\n     */\n    private _addContainer(container: Container): void\n    {\n        this.resolveQueueItem(container, this.queue);\n\n        // recursively add children\n        for (const child of container.children)\n        {\n            this._addContainer(child);\n        }\n    }\n\n    /**\n     * Upload all the textures and graphics to the GPU (optionally add more resources to the queue first)\n     * @param {PrepareSourceItem | PrepareSourceItem[] | undefined} resource\n     */\n    public upload(resource?: PrepareSourceItem | PrepareSourceItem[]): Promise<void>\n    {\n        if (resource)\n        {\n            this.add(resource);\n        }\n\n        return new Promise((resolve) =>\n        {\n            if (this.queue.length)\n            {\n                // add resolve callback to the collection\n                this.resolves.push(resolve);\n\n                // eliminate duplicates first\n                this.dedupeQueue();\n\n                // launch first tick\n                Ticker.system.addOnce(this._tick, this, UPDATE_PRIORITY.UTILITY);\n            }\n            else\n            {\n                // queue is empty, resolve immediately\n                resolve();\n            }\n        });\n    }\n\n    /** eliminate duplicates before processing */\n    public dedupeQueue(): void\n    {\n        const hash = Object.create(null);\n        let nextUnique = 0;\n\n        for (let i = 0; i < this.queue.length; i++)\n        {\n            const current = this.queue[i];\n\n            if (!hash[current.uid])\n            {\n                hash[current.uid] = true;\n                this.queue[nextUnique++] = current;\n            }\n        }\n\n        this.queue.length = nextUnique;\n    }\n\n    /** called per frame by the ticker, defer processing to next tick */\n    private readonly _tick = () =>\n    {\n        this.timeout = setTimeout(this._processQueue, 0) as unknown as number;\n    };\n\n    /** process the queue up to max item limit per frame */\n    private readonly _processQueue = () =>\n    {\n        const { queue } = this;\n        let itemsProcessed = 0;\n\n        // process the maximum number of items per frame\n        while (queue.length && itemsProcessed < PrepareBase.uploadsPerFrame)\n        {\n            const queueItem = queue.shift();\n\n            this.uploadQueueItem(queueItem);\n\n            itemsProcessed++;\n        }\n\n        if (queue.length)\n        {\n            // queue is not empty, continue processing on next frame\n            Ticker.system.addOnce(this._tick, this, UPDATE_PRIORITY.UTILITY);\n        }\n        else\n        {\n            // queue is empty, resolve immediately\n            this._resolve();\n        }\n    };\n\n    /** Call all the resolve callbacks */\n    private _resolve(): void\n    {\n        const { resolves } = this;\n\n        // call all resolve callbacks\n        const array = resolves.slice(0);\n\n        resolves.length = 0;\n\n        for (const resolve of array)\n        {\n            resolve();\n        }\n    }\n}\n"],"names":[],"mappings":"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"}