UNPKG

@esotericsoftware/spine-pixi-v8

Version:
195 lines 30.3 kB
/****************************************************************************** * Spine Runtimes License Agreement * Last updated April 5, 2025. Replaces all prior versions. * * Copyright (c) 2013-2025, Esoteric Software LLC * * Integration of the Spine Runtimes into software or otherwise creating * derivative works of the Spine Runtimes is permitted under the terms and * conditions of Section 2 of the Spine Editor License Agreement: * http://esotericsoftware.com/spine-editor-license * * Otherwise, it is permitted to integrate the Spine Runtimes into software * or otherwise create derivative works of the Spine Runtimes (collectively, * "Products"), provided that each user of the Products must obtain their own * Spine Editor license and redistribution of the Products in any form must * include this license and copyright notice. * * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ import { SkeletonRenderer as CanvasSkeletonRenderer, MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-canvas'; import { ExtensionType, extensions, RendererType, } from 'pixi.js'; import { BatchableSpineSlot } from './BatchableSpineSlot.js'; const spineBlendModeMap = { 0: 'normal', 1: 'add', 2: 'multiply', 3: 'screen' }; // eslint-disable-next-line max-len export class SpinePipe { /** @ignore */ static extension = { type: [ ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes, ], name: 'spine', }; renderer; canvasSkeletonRenderer; gpuSpineData = {}; _destroyRenderableBound = this.destroyRenderable.bind(this); constructor(renderer) { this.renderer = renderer; } validateRenderable(spine) { if (this.renderer.type === RendererType.CANVAS) { return true; } spine._validateAndTransformAttachments(); // if spine attachments have changed or destroyed, we need to rebuild the batch! if (spine.spineAttachmentsDirty) { return true; } // if the textures have changed, we need to rebuild the batch, but only if the texture is not already in the batch else if (spine.spineTexturesDirty) { // loop through and see if the textures have changed.. const drawOrder = spine.skeleton.drawOrder.appliedPose; const gpuSpine = this.gpuSpineData[spine.uid]; if (!gpuSpine) return false; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; if (!slot.bone.active) continue; const attachment = slot.appliedPose.attachment; if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) { const cacheData = spine._getCachedData(slot, attachment); const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id]; const texture = cacheData.texture; if (texture !== batchableSpineSlot?.texture) { if (!batchableSpineSlot?._batcher.checkAndUpdateTexture(batchableSpineSlot, texture)) { return true; } } } } } return false; } execute(spine) { if (this.renderer.type === RendererType.CANVAS) { const renderer = this.renderer; const groupAlpha = ((spine.groupColorAlpha >>> 24) & 0xFF) / 255; const contextSystem = renderer.canvasContext; const context = contextSystem.activeContext; context.save(); if (!this.canvasSkeletonRenderer) { this.canvasSkeletonRenderer = new CanvasSkeletonRenderer(context); this.canvasSkeletonRenderer.triangleRendering = true; } contextSystem.setContextTransform(spine.groupTransform, (renderer._roundPixels | spine._roundPixels) === 1); const oldAlpha = spine.skeleton.color.a; spine.skeleton.color.a *= groupAlpha; this.canvasSkeletonRenderer.draw(spine.skeleton); spine.skeleton.color.a = oldAlpha; context.restore(); } } addRenderable(spine, instructionSet) { if (this.renderer.type === RendererType.CANVAS) { this.renderer.renderPipes.batch.break(instructionSet); instructionSet.add(spine); return; } const gpuSpine = this._getSpineData(spine); const batcher = this.renderer.renderPipes.batch; const drawOrder = spine.skeleton.drawOrder.appliedPose; const roundPixels = (this.renderer._roundPixels | spine._roundPixels); spine._validateAndTransformAttachments(); spine.spineAttachmentsDirty = false; spine.spineTexturesDirty = false; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; if (!slot.bone.active) continue; const attachment = slot.appliedPose.attachment; const blendMode = spineBlendModeMap[slot.data.blendMode]; let skipRender = false; if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) { const cacheData = spine._getCachedData(slot, attachment); const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id] ||= new BatchableSpineSlot(); batchableSpineSlot.setData(spine, cacheData, blendMode, roundPixels); skipRender = cacheData.skipRender; if (!skipRender) { batcher.addToBatch(batchableSpineSlot, instructionSet); } } const containerAttachment = spine._slotsObject[slot.data.name]; if (containerAttachment?.wasRenderable) { const container = containerAttachment.container; container.includeInBuild = true; // See https://github.com/pixijs/pixijs/blob/b4c050a791fe65e979e467c9cba2bda0c01a1c35/src/scene/container/utils/collectAllRenderables.ts#L28 // biome-ignore lint/style/noNonNullAssertion: it was in pixi code container.collectRenderables(instructionSet, this.renderer, null); container.includeInBuild = false; } } } updateRenderable(spine) { const gpuSpine = this.gpuSpineData[spine.uid]; if (!gpuSpine) return; spine._validateAndTransformAttachments(); spine.spineAttachmentsDirty = false; spine.spineTexturesDirty = false; const drawOrder = spine.skeleton.drawOrder.appliedPose; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; if (!slot.bone.active) continue; const attachment = slot.appliedPose.attachment; if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) { const cacheData = spine._getCachedData(slot, attachment); if (!cacheData.skipRender) { const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id]; if (batchableSpineSlot) { // biome-ignore lint/style/noNonNullAssertion: if clipped is true, clippedData exists batchableSpineSlot.uvs = cacheData.clipped ? cacheData.clippedData.uvs : cacheData.uvs; batchableSpineSlot._batcher?.updateElement(batchableSpineSlot); } } } } } destroyRenderable(spine) { this.gpuSpineData[spine.uid] = null; spine.off('destroyed', this._destroyRenderableBound); } destroy() { this.gpuSpineData = null; this.renderer = null; this.canvasSkeletonRenderer = null; } _getSpineData(spine) { return this.gpuSpineData[spine.uid] || this._initMeshData(spine); } _initMeshData(spine) { this.gpuSpineData[spine.uid] = { slotBatches: {} }; spine.on('destroyed', this._destroyRenderableBound); return this.gpuSpineData[spine.uid]; } } extensions.add(SpinePipe); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVQaXBlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NwaW5lUGlwZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFFL0UsT0FBTyxFQUFFLGdCQUFnQixJQUFJLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzlILE9BQU8sRUFHVSxhQUFhLEVBQzdCLFVBQVUsRUFHVixZQUFZLEdBRVosTUFBTSxTQUFTLENBQUM7QUFDakIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHN0QsTUFBTSxpQkFBaUIsR0FBZ0M7SUFDdEQsQ0FBQyxFQUFFLFFBQVE7SUFDWCxDQUFDLEVBQUUsS0FBSztJQUNSLENBQUMsRUFBRSxVQUFVO0lBQ2IsQ0FBQyxFQUFFLFFBQVE7Q0FDWCxDQUFDO0FBSUYsbUNBQW1DO0FBQ25DLE1BQU0sT0FBTyxTQUFTO0lBQ3JCLGNBQWM7SUFDZCxNQUFNLENBQUMsU0FBUyxHQUFHO1FBQ2xCLElBQUksRUFBRTtZQUNMLGFBQWEsQ0FBQyxVQUFVO1lBQ3hCLGFBQWEsQ0FBQyxXQUFXO1lBQ3pCLGFBQWEsQ0FBQyxXQUFXO1NBQ3pCO1FBQ0QsSUFBSSxFQUFFLE9BQU87S0FDSixDQUFDO0lBRVgsUUFBUSxDQUFXO0lBQ1gsc0JBQXNCLENBQTBCO0lBRWhELFlBQVksR0FBd0MsRUFBRSxDQUFDO0lBQzlDLHVCQUF1QixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFvQyxDQUFDO0lBRWhILFlBQWEsUUFBa0I7UUFDOUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDMUIsQ0FBQztJQUVELGtCQUFrQixDQUFFLEtBQVk7UUFDL0IsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxZQUFZLENBQUMsTUFBTSxF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T0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxDQUFDOztBQUdGLFVBQVUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEFwcmlsIDUsIDIwMjUuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyNSwgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxuICogb3Igb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB7IFNrZWxldG9uUmVuZGVyZXIgYXMgQ2FudmFzU2tlbGV0b25SZW5kZXJlciwgTWVzaEF0dGFjaG1lbnQsIFJlZ2lvbkF0dGFjaG1lbnQgfSBmcm9tICdAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jYW52YXMnO1xuaW1wb3J0IHtcblx0dHlwZSBCTEVORF9NT0RFUyxcblx0dHlwZSBDYW52YXNSZW5kZXJlcixcblx0dHlwZSBDb250YWluZXIsIEV4dGVuc2lvblR5cGUsXG5cdGV4dGVuc2lvbnMsXG5cdHR5cGUgSW5zdHJ1Y3Rpb25TZXQsXG5cdHR5cGUgUmVuZGVyZXIsXG5cdFJlbmRlcmVyVHlwZSxcblx0dHlwZSBSZW5kZXJQaXBlLFxufSBmcm9tICdwaXhpLmpzJztcbmltcG9ydCB7IEJhdGNoYWJsZVNwaW5lU2xvdCB9IGZyb20gJy4vQmF0Y2hhYmxlU3BpbmVTbG90LmpzJztcbmltcG9ydCB0eXBlIHsgU3BpbmUgfSBmcm9tICcuL1NwaW5lLmpzJztcblxuY29uc3Qgc3BpbmVCbGVuZE1vZGVNYXA6IFJlY29yZDxudW1iZXIsIEJMRU5EX01PREVTPiA9IHtcblx0MDogJ25vcm1hbCcsXG5cdDE6ICdhZGQnLFxuXHQyOiAnbXVsdGlwbHknLFxuXHQzOiAnc2NyZWVuJ1xufTtcblxudHlwZSBHcHVTcGluZURhdGFFbGVtZW50ID0geyBzbG90QmF0Y2hlczogUmVjb3JkPHN0cmluZywgQmF0Y2hhYmxlU3BpbmVTbG90IHwgdW5kZWZpbmVkPiB9O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuZXhwb3J0IGNsYXNzIFNwaW5lUGlwZSBpbXBsZW1lbnRzIFJlbmRlclBpcGU8U3BpbmU+IHtcblx0LyoqIEBpZ25vcmUgKi9cblx0c3RhdGljIGV4dGVuc2lvbiA9IHtcblx0XHR0eXBlOiBbXG5cdFx0XHRFeHRlbnNpb25UeXBlLldlYkdMUGlwZXMsXG5cdFx0XHRFeHRlbnNpb25UeXBlLldlYkdQVVBpcGVzLFxuXHRcdFx0RXh0ZW5zaW9uVHlwZS5DYW52YXNQaXBlcyxcblx0XHRdLFxuXHRcdG5hbWU6ICdzcGluZScsXG5cdH0gYXMgY29uc3Q7XG5cblx0cmVuZGVyZXI6IFJlbmRlcmVyO1xuXHRwcml2YXRlIGNhbnZhc1NrZWxldG9uUmVuZGVyZXIhOiBDYW52YXNTa2VsZXRvblJlbmRlcmVyO1xuXG5cdHByaXZhdGUgZ3B1U3BpbmVEYXRhOiBSZWNvcmQ8c3RyaW5nLCBHcHVTcGluZURhdGFFbGVtZW50PiA9IHt9O1xuXHRwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95UmVuZGVyYWJsZUJvdW5kID0gdGhpcy5kZXN0cm95UmVuZGVyYWJsZS5iaW5kKHRoaXMpIGFzIChyZW5kZXJhYmxlOiBDb250YWluZXIpID0+IHZvaWQ7XG5cblx0Y29uc3RydWN0b3IgKHJlbmRlcmVyOiBSZW5kZXJlcikge1xuXHRcdHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcblx0fVxuXG5cdHZhbGlkYXRlUmVuZGVyYWJsZSAoc3BpbmU6IFNwaW5lKTogYm9vbGVhbiB7XG5cdFx0aWYgKHRoaXMucmVuZGVyZXIudHlwZSA9PT0gUmVuZGVyZXJUeXBlLkNBTlZBUykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0c3BpbmUuX3ZhbGlkYXRlQW5kVHJhbnNmb3JtQXR0YWNobWVudHMoKTtcblxuXHRcdC8vIGlmIHNwaW5lIGF0dGFjaG1lbnRzIGhhdmUgY2hhbmdlZCBvciBkZXN0cm95ZWQsIHdlIG5lZWQgdG8gcmVidWlsZCB0aGUgYmF0Y2ghXG5cdFx0aWYgKHNwaW5lLnNwaW5lQXR0YWNobWVudHNEaXJ0eSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gaWYgdGhlIHRleHR1cmVzIGhhdmUgY2hhbmdlZCwgd2UgbmVlZCB0byByZWJ1aWxkIHRoZSBiYXRjaCwgYnV0IG9ubHkgaWYgdGhlIHRleHR1cmUgaXMgbm90IGFscmVhZHkgaW4gdGhlIGJhdGNoXG5cdFx0ZWxzZSBpZiAoc3BpbmUuc3BpbmVUZXh0dXJlc0RpcnR5KSB7XG5cdFx0XHQvLyBsb29wIHRocm91Z2ggYW5kIHNlZSBpZiB0aGUgdGV4dHVyZXMgaGF2ZSBjaGFuZ2VkLi5cblx0XHRcdGNvbnN0IGRyYXdPcmRlciA9IHNwaW5lLnNrZWxldG9uLmRyYXdPcmRlci5hcHBsaWVkUG9zZTtcblx0XHRcdGNvbnN0IGdwdVNwaW5lID0gdGhpcy5ncHVTcGluZURhdGFbc3BpbmUudWlkXTtcblxuXHRcdFx0aWYgKCFncHVTcGluZSkgcmV0dXJuIGZhbHNlO1xuXG5cdFx0XHRmb3IgKGxldCBpID0gMCwgbiA9IGRyYXdPcmRlci5sZW5ndGg7IGkgPCBuOyBpKyspIHtcblx0XHRcdFx0Y29uc3Qgc2xvdCA9IGRyYXdPcmRlcltpXTtcblx0XHRcdFx0aWYgKCFzbG90LmJvbmUuYWN0aXZlKSBjb250aW51ZTtcblxuXHRcdFx0XHRjb25zdCBhdHRhY2htZW50ID0gc2xvdC5hcHBsaWVkUG9zZS5hdHRhY2htZW50O1xuXG5cdFx0XHRcdGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgUmVnaW9uQXR0YWNobWVudCB8fCBhdHRhY2htZW50IGluc3RhbmNlb2YgTWVzaEF0dGFjaG1lbnQpIHtcblx0XHRcdFx0XHRjb25zdCBjYWNoZURhdGEgPSBzcGluZS5fZ2V0Q2FjaGVkRGF0YShzbG90LCBhdHRhY2htZW50KTtcblx0XHRcdFx0XHRjb25zdCBiYXRjaGFibGVTcGluZVNsb3QgPSBncHVTcGluZS5zbG90QmF0Y2hlc1tjYWNoZURhdGEuaWRdO1xuXG5cdFx0XHRcdFx0Y29uc3QgdGV4dHVyZSA9IGNhY2hlRGF0YS50ZXh0dXJlO1xuXG5cdFx0XHRcdFx0aWYgKHRleHR1cmUgIT09IGJhdGNoYWJsZVNwaW5lU2xvdD8udGV4dHVyZSkge1xuXHRcdFx0XHRcdFx0aWYgKCFiYXRjaGFibGVTcGluZVNsb3Q/Ll9iYXRjaGVyLmNoZWNrQW5kVXBkYXRlVGV4dHVyZShiYXRjaGFibGVTcGluZVNsb3QsIHRleHR1cmUpKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGV4ZWN1dGUgKHNwaW5lOiBTcGluZSkge1xuXHRcdGlmICh0aGlzLnJlbmRlcmVyLnR5cGUgPT09IFJlbmRlcmVyVHlwZS5DQU5WQVMpIHtcblx0XHRcdGNvbnN0IHJlbmRlcmVyID0gdGhpcy5yZW5kZXJlciBhcyBDYW52YXNSZW5kZXJlcjtcblx0XHRcdGNvbnN0IGdyb3VwQWxwaGEgPSAoKHNwaW5lLmdyb3VwQ29sb3JBbHBoYSA+Pj4gMjQpICYgMHhGRikgLyAyNTU7XG5cdFx0XHRjb25zdCBjb250ZXh0U3lzdGVtID0gcmVuZGVyZXIuY2FudmFzQ29udGV4dDtcblx0XHRcdGNvbnN0IGNvbnRleHQgPSBjb250ZXh0U3lzdGVtLmFjdGl2ZUNvbnRleHQ7XG5cblx0XHRcdGNvbnRleHQuc2F2ZSgpO1xuXG5cdFx0XHRpZiAoIXRoaXMuY2FudmFzU2tlbGV0b25SZW5kZXJlcikge1xuXHRcdFx0XHR0aGlzLmNhbnZhc1NrZWxldG9uUmVuZGVyZXIgPSBuZXcgQ2FudmFzU2tlbGV0b25SZW5kZXJlcihjb250ZXh0IGFzIHVua25vd24gYXMgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTtcblx0XHRcdFx0dGhpcy5jYW52YXNTa2VsZXRvblJlbmRlcmVyLnRyaWFuZ2xlUmVuZGVyaW5nID0gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29udGV4dFN5c3RlbS5zZXRDb250ZXh0VHJhbnNmb3JtKHNwaW5lLmdyb3VwVHJhbnNmb3JtLCAocmVuZGVyZXIuX3JvdW5kUGl4ZWxzIHwgc3BpbmUuX3JvdW5kUGl4ZWxzKSA9PT0gMSk7XG5cblx0XHRcdGNvbnN0IG9sZEFscGhhID0gc3BpbmUuc2tlbGV0b24uY29sb3IuYTtcblx0XHRcdHNwaW5lLnNrZWxldG9uLmNvbG9yLmEgKj0gZ3JvdXBBbHBoYTtcblx0XHRcdHRoaXMuY2FudmFzU2tlbGV0b25SZW5kZXJlci5kcmF3KHNwaW5lLnNrZWxldG9uKTtcblx0XHRcdHNwaW5lLnNrZWxldG9uLmNvbG9yLmEgPSBvbGRBbHBoYTtcblxuXHRcdFx0Y29udGV4dC5yZXN0b3JlKCk7XG5cdFx0fVxuXHR9XG5cblx0YWRkUmVuZGVyYWJsZSAoc3BpbmU6IFNwaW5lLCBpbnN0cnVjdGlvblNldDogSW5zdHJ1Y3Rpb25TZXQpIHtcblx0XHRpZiAodGhpcy5yZW5kZXJlci50eXBlID09PSBSZW5kZXJlclR5cGUuQ0FOVkFTKSB7XG5cdFx0XHR0aGlzLnJlbmRlcmVyLnJlbmRlclBpcGVzLmJhdGNoLmJyZWFrKGluc3RydWN0aW9uU2V0KTtcblx0XHRcdGluc3RydWN0aW9uU2V0LmFkZChzcGluZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgZ3B1U3BpbmUgPSB0aGlzLl9nZXRTcGluZURhdGEoc3BpbmUpO1xuXG5cdFx0Y29uc3QgYmF0Y2hlciA9IHRoaXMucmVuZGVyZXIucmVuZGVyUGlwZXMuYmF0Y2g7XG5cblx0XHRjb25zdCBkcmF3T3JkZXIgPSBzcGluZS5za2VsZXRvbi5kcmF3T3JkZXIuYXBwbGllZFBvc2U7XG5cblx0XHRjb25zdCByb3VuZFBpeGVscyA9ICh0aGlzLnJlbmRlcmVyLl9yb3VuZFBpeGVscyB8IHNwaW5lLl9yb3VuZFBpeGVscykgYXMgMCB8IDE7XG5cblx0XHRzcGluZS5fdmFsaWRhdGVBbmRUcmFuc2Zvcm1BdHRhY2htZW50cygpO1xuXG5cdFx0c3BpbmUuc3BpbmVBdHRhY2htZW50c0RpcnR5ID0gZmFsc2U7XG5cdFx0c3BpbmUuc3BpbmVUZXh0dXJlc0RpcnR5ID0gZmFsc2U7XG5cblx0XHRmb3IgKGxldCBpID0gMCwgbiA9IGRyYXdPcmRlci5sZW5ndGg7IGkgPCBuOyBpKyspIHtcblx0XHRcdGNvbnN0IHNsb3QgPSBkcmF3T3JkZXJbaV07XG5cdFx0XHRpZiAoIXNsb3QuYm9uZS5hY3RpdmUpIGNvbnRpbnVlO1xuXG5cdFx0XHRjb25zdCBhdHRhY2htZW50ID0gc2xvdC5hcHBsaWVkUG9zZS5hdHRhY2htZW50O1xuXHRcdFx0Y29uc3QgYmxlbmRNb2RlID0gc3BpbmVCbGVuZE1vZGVNYXBbc2xvdC5kYXRhLmJsZW5kTW9kZV07XG5cdFx0XHRsZXQgc2tpcFJlbmRlciA9IGZhbHNlO1xuXG5cdFx0XHRpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIFJlZ2lvbkF0dGFjaG1lbnQgfHwgYXR0YWNobWVudCBpbnN0YW5jZW9mIE1lc2hBdHRhY2htZW50KSB7XG5cdFx0XHRcdGNvbnN0IGNhY2hlRGF0YSA9IHNwaW5lLl9nZXRDYWNoZWREYXRhKHNsb3QsIGF0dGFjaG1lbnQpO1xuXHRcdFx0XHRjb25zdCBiYXRjaGFibGVTcGluZVNsb3QgPSBncHVTcGluZS5zbG90QmF0Y2hlc1tjYWNoZURhdGEuaWRdIHx8PSBuZXcgQmF0Y2hhYmxlU3BpbmVTbG90KCk7XG5cblx0XHRcdFx0YmF0Y2hhYmxlU3BpbmVTbG90LnNldERhdGEoXG5cdFx0XHRcdFx0c3BpbmUsXG5cdFx0XHRcdFx0Y2FjaGVEYXRhLFxuXHRcdFx0XHRcdGJsZW5kTW9kZSxcblx0XHRcdFx0XHRyb3VuZFBpeGVsc1xuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdHNraXBSZW5kZXIgPSBjYWNoZURhdGEuc2tpcFJlbmRlcjtcblx0XHRcdFx0aWYgKCFza2lwUmVuZGVyKSB7XG5cdFx0XHRcdFx0YmF0Y2hlci5hZGRUb0JhdGNoKGJhdGNoYWJsZVNwaW5lU2xvdCwgaW5zdHJ1Y3Rpb25TZXQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGNvbnRhaW5lckF0dGFjaG1lbnQgPSBzcGluZS5fc2xvdHNPYmplY3Rbc2xvdC5kYXRhLm5hbWVdO1xuXG5cdFx0XHRpZiAoY29udGFpbmVyQXR0YWNobWVudD8ud2FzUmVuZGVyYWJsZSkge1xuXHRcdFx0XHRjb25zdCBjb250YWluZXIgPSBjb250YWluZXJBdHRhY2htZW50LmNvbnRhaW5lcjtcblxuXHRcdFx0XHRjb250YWluZXIuaW5jbHVkZUluQnVpbGQgPSB0cnVlO1xuXHRcdFx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3BpeGlqcy9waXhpanMvYmxvYi9iNGMwNTBhNzkxZmU2NWU5NzllNDY3YzljYmEyYmRhMGMwMWExYzM1L3NyYy9zY2VuZS9jb250YWluZXIvdXRpbHMvY29sbGVjdEFsbFJlbmRlcmFibGVzLnRzI0wyOFxuXHRcdFx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IGl0IHdhcyBpbiBwaXhpIGNvZGVcblx0XHRcdFx0Y29udGFpbmVyLmNvbGxlY3RSZW5kZXJhYmxlcyhpbnN0cnVjdGlvblNldCwgdGhpcy5yZW5kZXJlciwgbnVsbCEpO1xuXG5cdFx0XHRcdGNvbnRhaW5lci5pbmNsdWRlSW5CdWlsZCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHVwZGF0ZVJlbmRlcmFibGUgKHNwaW5lOiBTcGluZSkge1xuXHRcdGNvbnN0IGdwdVNwaW5lID0gdGhpcy5ncHVTcGluZURhdGFbc3BpbmUudWlkXTtcblxuXHRcdGlmICghZ3B1U3BpbmUpIHJldHVybjtcblxuXHRcdHNwaW5lLl92YWxpZGF0ZUFuZFRyYW5zZm9ybUF0dGFjaG1lbnRzKCk7XG5cblx0XHRzcGluZS5zcGluZUF0dGFjaG1lbnRzRGlydHkgPSBmYWxzZTtcblx0XHRzcGluZS5zcGluZVRleHR1cmVzRGlydHkgPSBmYWxzZTtcblxuXHRcdGNvbnN0IGRyYXdPcmRlciA9IHNwaW5lLnNrZWxldG9uLmRyYXdPcmRlci5hcHBsaWVkUG9zZTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBuID0gZHJhd09yZGVyLmxlbmd0aDsgaSA8IG47IGkrKykge1xuXHRcdFx0Y29uc3Qgc2xvdCA9IGRyYXdPcmRlcltpXTtcblx0XHRcdGlmICghc2xvdC5ib25lLmFjdGl2ZSkgY29udGludWU7XG5cblx0XHRcdGNvbnN0IGF0dGFjaG1lbnQgPSBzbG90LmFwcGxpZWRQb3NlLmF0dGFjaG1lbnQ7XG5cblx0XHRcdGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgUmVnaW9uQXR0YWNobWVudCB8fCBhdHRhY2htZW50IGluc3RhbmNlb2YgTWVzaEF0dGFjaG1lbnQpIHtcblx0XHRcdFx0Y29uc3QgY2FjaGVEYXRhID0gc3BpbmUuX2dldENhY2hlZERhdGEoc2xvdCwgYXR0YWNobWVudCk7XG5cblx0XHRcdFx0aWYgKCFjYWNoZURhdGEuc2tpcFJlbmRlcikge1xuXHRcdFx0XHRcdGNvbnN0IGJhdGNoYWJsZVNwaW5lU2xvdCA9IGdwdVNwaW5lLnNsb3RCYXRjaGVzW2NhY2hlRGF0YS5pZF07XG5cdFx0XHRcdFx0aWYgKGJhdGNoYWJsZVNwaW5lU2xvdCkge1xuXHRcdFx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBpZiBjbGlwcGVkIGlzIHRydWUsIGNsaXBwZWREYXRhIGV4aXN0c1xuXHRcdFx0XHRcdFx0YmF0Y2hhYmxlU3BpbmVTbG90LnV2cyA9IGNhY2hlRGF0YS5jbGlwcGVkID8gY2FjaGVEYXRhLmNsaXBwZWREYXRhIS51dnMgOiBjYWNoZURhdGEudXZzO1xuXHRcdFx0XHRcdFx0YmF0Y2hhYmxlU3BpbmVTbG90Ll9iYXRjaGVyPy51cGRhdGVFbGVtZW50KGJhdGNoYWJsZVNwaW5lU2xvdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0ZGVzdHJveVJlbmRlcmFibGUgKHNwaW5lOiBTcGluZSkge1xuXHRcdCh0aGlzLmdwdVNwaW5lRGF0YVtzcGluZS51aWRdIGFzIHVua25vd24pID0gbnVsbDtcblx0XHRzcGluZS5vZmYoJ2Rlc3Ryb3llZCcsIHRoaXMuX2Rlc3Ryb3lSZW5kZXJhYmxlQm91bmQpO1xuXHR9XG5cblx0ZGVzdHJveSAoKSB7XG5cdFx0KHRoaXMuZ3B1U3BpbmVEYXRhIGFzIHVua25vd24pID0gbnVsbDtcblx0XHQodGhpcy5yZW5kZXJlciBhcyB1bmtub3duKSA9IG51bGw7XG5cdFx0KHRoaXMuY2FudmFzU2tlbGV0b25SZW5kZXJlciBhcyB1bmtub3duKSA9IG51bGw7XG5cdH1cblxuXHRwcml2YXRlIF9nZXRTcGluZURhdGEgKHNwaW5lOiBTcGluZSk6IEdwdVNwaW5lRGF0YUVsZW1lbnQge1xuXHRcdHJldHVybiB0aGlzLmdwdVNwaW5lRGF0YVtzcGluZS51aWRdIHx8IHRoaXMuX2luaXRNZXNoRGF0YShzcGluZSk7XG5cdH1cblxuXHRwcml2YXRlIF9pbml0TWVzaERhdGEgKHNwaW5lOiBTcGluZSk6IEdwdVNwaW5lRGF0YUVsZW1lbnQge1xuXHRcdHRoaXMuZ3B1U3BpbmVEYXRhW3NwaW5lLnVpZF0gPSB7IHNsb3RCYXRjaGVzOiB7fSB9O1xuXHRcdHNwaW5lLm9uKCdkZXN0cm95ZWQnLCB0aGlzLl9kZXN0cm95UmVuZGVyYWJsZUJvdW5kKTtcblx0XHRyZXR1cm4gdGhpcy5ncHVTcGluZURhdGFbc3BpbmUudWlkXTtcblx0fVxufVxuXG5leHRlbnNpb25zLmFkZChTcGluZVBpcGUpO1xuIl19