{"version":3,"file":"SpinePipe.mjs","sources":["../src/SpinePipe.ts"],"sourcesContent":["/** ****************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport {\n    collectAllRenderables,\n    extensions, ExtensionType,\n    InstructionSet,\n    type Renderer,\n    type RenderPipe,\n} from 'pixi.js';\nimport { BatchableSpineSlot } from './BatchableSpineSlot';\nimport { Spine } from './Spine';\nimport { MeshAttachment, RegionAttachment, SkeletonClipping } from '@esotericsoftware/spine-core';\n\nconst clipper = new SkeletonClipping();\n\nconst spineBlendModeMap = {\n    0: 'normal',\n    1: 'add',\n    2: 'multiply',\n    3: 'screen'\n};\n\n// eslint-disable-next-line max-len\nexport class SpinePipe implements RenderPipe<Spine>\n{\n    /** @ignore */\n    static extension = {\n        type: [\n            ExtensionType.WebGLPipes,\n            ExtensionType.WebGPUPipes,\n            ExtensionType.CanvasPipes,\n        ],\n        name: 'spine',\n    } as const;\n\n    renderer: Renderer;\n\n    private gpuSpineData:Record<string, any> = {};\n\n    constructor(renderer: Renderer)\n    {\n        this.renderer = renderer;\n    }\n\n    validateRenderable(spine: Spine): boolean\n    {\n        spine._applyState();\n\n        // if pine attachments have changed, we need to rebuild the batch!\n        if (spine.spineAttachmentsDirty)\n        {\n            return true;\n        }\n        // if the textures have changed, we need to rebuild the batch, but only if the texture is not already in the batch\n        else if (spine.spineTexturesDirty)\n        {\n            // loop through and see if the textures have changed..\n            const drawOrder = spine.skeleton.drawOrder;\n            const gpuSpine = this.gpuSpineData[spine.uid];\n\n            for (let i = 0, n = drawOrder.length; i < n; i++)\n            {\n                const slot = drawOrder[i];\n                const attachment = slot.getAttachment();\n\n                if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment)\n                {\n                    const cacheData = spine._getCachedData(slot, attachment);\n                    const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id];\n\n                    const texture = cacheData.texture;\n\n                    if (texture !== batchableSpineSlot.texture)\n                    {\n                        if (!batchableSpineSlot._batcher.checkAndUpdateTexture(batchableSpineSlot, texture))\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    addRenderable(spine: Spine, instructionSet:InstructionSet)\n    {\n        const gpuSpine = this.gpuSpineData[spine.uid] ||= { slotBatches: {} };\n\n        const batcher = this.renderer.renderPipes.batch;\n\n        const drawOrder = spine.skeleton.drawOrder;\n\n        const roundPixels = (this.renderer._roundPixels | spine._roundPixels) as 0 | 1;\n\n        spine._applyState();\n\n        for (let i = 0, n = drawOrder.length; i < n; i++)\n        {\n            const slot = drawOrder[i];\n            const attachment = slot.getAttachment();\n            const blendMode = spineBlendModeMap[slot.data.blendMode];\n\n            if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment)\n            {\n                const cacheData = spine._getCachedData(slot, attachment);\n                const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id] ||= new BatchableSpineSlot();\n\n                batchableSpineSlot.setData(\n                    spine,\n                    cacheData,\n                    blendMode,\n                    roundPixels\n                );\n\n                if (!cacheData.skipRender)\n                {\n                    batcher.addToBatch(batchableSpineSlot, instructionSet);\n                }\n            }\n\n            const containerAttachment = spine._slotsObject[slot.data.name];\n\n            if (containerAttachment)\n            {\n                const container = containerAttachment.container;\n\n                container.includeInBuild = true;\n                collectAllRenderables(container, instructionSet, this.renderer);\n                container.includeInBuild = false;\n            }\n        }\n\n        clipper.clipEnd();\n    }\n\n    updateRenderable(spine: Spine)\n    {\n        // we assume that spine will always change its verts size..\n        const gpuSpine = this.gpuSpineData[spine.uid];\n\n        spine._applyState();\n\n        const drawOrder = spine.skeleton.drawOrder;\n\n        for (let i = 0, n = drawOrder.length; i < n; i++)\n        {\n            const slot = drawOrder[i];\n            const attachment = slot.getAttachment();\n\n            if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment)\n            {\n                const cacheData = spine._getCachedData(slot, attachment);\n\n                if (!cacheData.skipRender)\n                {\n                    const batchableSpineSlot = gpuSpine.slotBatches[spine._getCachedData(slot, attachment).id];\n\n                    batchableSpineSlot._batcher?.updateElement(batchableSpineSlot);\n                }\n            }\n        }\n    }\n\n    destroyRenderable(spine: Spine)\n    {\n        // TODO remove the renderable from the batcher\n        this.gpuSpineData[spine.uid] = null as any;\n    }\n\n    destroy()\n    {\n        this.gpuSpineData = null as any;\n        this.renderer = null as any;\n    }\n}\n\nextensions.add(SpinePipe);\n"],"names":[],"mappings":"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"}