UNPKG

@esotericsoftware/spine-webgl

Version:
203 lines 33.1 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 { BlendMode, ClippingAttachment, Color, MeshAttachment, RegionAttachment, SkeletonClipping, Utils } from "@esotericsoftware/spine-core"; class Renderable { vertices; numVertices; numFloats; constructor(vertices, numVertices, numFloats) { this.vertices = vertices; this.numVertices = numVertices; this.numFloats = numFloats; } } ; export class SkeletonRenderer { static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; tempColor = new Color(); tempColor2 = new Color(); vertices; vertexSize = 2 + 2 + 4; twoColorTint = false; renderable = new Renderable([], 0, 0); clipper = new SkeletonClipping(); /** * Batches additive slots together with normal slots by rendering additive slots with premultiplied alpha RGB and zero alpha, * while using normal PMA blending. This reduces draw calls for normal/additive/normal sequences with the same texture. * Disable this if rendering to a transparent target and the accumulated destination alpha from additive blending must be preserved. */ pmaAdditiveBatching = true; constructor(context, twoColorTint = true) { this.twoColorTint = twoColorTint; if (twoColorTint) this.vertexSize += 4; this.vertices = Utils.newFloatArray(this.vertexSize * 1024); } draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1, transformer = null) { const clipper = this.clipper; const twoColorTint = this.twoColorTint; let blendMode = null; const renderable = this.renderable; let uvs; let triangles; const drawOrder = skeleton.drawOrder.appliedPose; let attachmentColor; const skeletonColor = skeleton.color; const vertexSize = twoColorTint ? 12 : 8; let inRange = false; if (slotRangeStart === -1) inRange = true; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; if (!slot.bone.active) { clipper.clipEnd(slot); continue; } if (slotRangeStart >= 0 && slotRangeStart === slot.data.index) { inRange = true; } if (!inRange) { clipper.clipEnd(slot); continue; } if (slotRangeEnd >= 0 && slotRangeEnd === slot.data.index) { inRange = false; } const pose = slot.appliedPose; const attachment = pose.attachment; let texture; if (attachment instanceof RegionAttachment) { renderable.vertices = this.vertices; renderable.numVertices = 4; renderable.numFloats = vertexSize << 2; const sequence = attachment.sequence; const sequenceIndex = sequence.resolveIndex(pose); attachment.computeWorldVertices(slot, attachment.getOffsets(pose), renderable.vertices, 0, vertexSize); triangles = SkeletonRenderer.QUAD_TRIANGLES; uvs = sequence.getUVs(sequenceIndex); texture = sequence.regions[sequenceIndex]?.texture; attachmentColor = attachment.color; } else if (attachment instanceof MeshAttachment) { renderable.vertices = this.vertices; renderable.numVertices = (attachment.worldVerticesLength >> 1); renderable.numFloats = renderable.numVertices * vertexSize; if (renderable.numFloats > renderable.vertices.length) { renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats); } attachment.computeWorldVertices(skeleton, slot, 0, attachment.worldVerticesLength, renderable.vertices, 0, vertexSize); triangles = attachment.triangles; const sequence = attachment.sequence; const sequenceIndex = sequence.resolveIndex(pose); texture = sequence.regions[sequenceIndex]?.texture; uvs = sequence.getUVs(sequenceIndex); attachmentColor = attachment.color; } else if (attachment instanceof ClippingAttachment) { clipper.clipEnd(slot); clipper.clipStart(skeleton, slot, attachment); continue; } else { clipper.clipEnd(slot); continue; } if (texture) { const slotColor = pose.color; const finalColor = this.tempColor; const alpha = skeletonColor.a * slotColor.a * attachmentColor.a; finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r * alpha; finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g * alpha; finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b * alpha; const slotBlendMode = slot.data.blendMode; const additiveBlend = this.pmaAdditiveBatching && slotBlendMode === BlendMode.Additive; finalColor.a = additiveBlend ? 0 : alpha; const darkColor = this.tempColor2; if (!pose.darkColor) darkColor.set(0, 0, 0, 1.0); else { darkColor.r = pose.darkColor.r * alpha; darkColor.g = pose.darkColor.g * alpha; darkColor.b = pose.darkColor.b * alpha; darkColor.a = 1; } const batchBlendMode = additiveBlend ? BlendMode.Normal : slotBlendMode; if (batchBlendMode !== blendMode) { blendMode = batchBlendMode; batcher.setBlendMode(blendMode); } if (clipper.isClipping() && clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint, vertexSize)) { const clippedVertices = new Float32Array(clipper.clippedVertices); const clippedTriangles = clipper.clippedTriangles; if (transformer) transformer(clippedVertices, clippedVertices.length, vertexSize); batcher.draw(texture, clippedVertices, clippedTriangles); } else { const verts = renderable.vertices; if (!twoColorTint) { for (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) { verts[v] = finalColor.r; verts[v + 1] = finalColor.g; verts[v + 2] = finalColor.b; verts[v + 3] = finalColor.a; verts[v + 4] = uvs[u]; verts[v + 5] = uvs[u + 1]; } } else { for (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) { verts[v] = finalColor.r; verts[v + 1] = finalColor.g; verts[v + 2] = finalColor.b; verts[v + 3] = finalColor.a; verts[v + 4] = uvs[u]; verts[v + 5] = uvs[u + 1]; verts[v + 6] = darkColor.r; verts[v + 7] = darkColor.g; verts[v + 8] = darkColor.b; verts[v + 9] = darkColor.a; } } const view = renderable.vertices.subarray(0, renderable.numFloats); if (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize); batcher.draw(texture, view, triangles); } } clipper.clipEnd(slot); } clipper.clipEnd(); } /** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/ getSkeletonClipping() { return this.clipper; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25SZW5kZXJlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9Ta2VsZXRvblJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUUvRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLEtBQUssRUFBRSxjQUFjLEVBQXdCLGdCQUFnQixFQUFpQixnQkFBZ0IsRUFBRSxLQUFLLEVBQVcsTUFBTSw4QkFBOEIsQ0FBQztBQU03TCxNQUFNLFVBQVU7SUFDSztJQUFrQztJQUE0QjtJQUFsRixZQUFvQixRQUF5QixFQUFTLFdBQW1CLEVBQVMsU0FBaUI7UUFBL0UsYUFBUSxHQUFSLFFBQVEsQ0FBaUI7UUFBUyxnQkFBVyxHQUFYLFdBQVcsQ0FBUTtRQUFTLGNBQVMsR0FBVCxTQUFTLENBQVE7SUFBSSxDQUFDO0NBQ3hHO0FBQUEsQ0FBQztBQUlGLE1BQU0sT0FBTyxnQkFBZ0I7SUFDNUIsTUFBTSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFbkMsU0FBUyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7SUFDeEIsVUFBVSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7SUFDekIsUUFBUSxDQUFrQjtJQUMxQixVQUFVLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkIsWUFBWSxHQUFHLEtBQUssQ0FBQztJQUNyQixVQUFVLEdBQWUsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRCxPQUFPLEdBQXFCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztJQUUzRDs7OztPQUlHO0lBQ0gsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0lBRTNCLFlBQWEsT0FBcUMsRUFBRSxlQUF3QixJQUFJO1FBQy9FLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksWUFBWTtZQUNmLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRCxJQUFJLENBQUUsT0FBdUIsRUFBRSxRQUFrQixFQUFFLGlCQUF5QixDQUFDLENBQUMsRUFBRSxlQUF1QixDQUFDLENBQUMsRUFBRSxjQUF3QyxJQUFJO1FBQ3RKLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUN2QyxJQUFJLFNBQVMsR0FBcUIsSUFBSSxDQUFDO1FBRXZDLE1BQU0sVUFBVSxHQUFlLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDL0MsSUFBSSxHQUFvQixDQUFDO1FBQ3pCLElBQUksU0FBd0IsQ0FBQztRQUM3QixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQztRQUNqRCxJQUFJLGVBQXNCLENBQUM7UUFDM0IsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUNyQyxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLGNBQWMsS0FBSyxDQUFDLENBQUM7WUFBRSxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQzFDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3ZCLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RCLFNBQVM7WUFDVixDQUFDO1lBRUQsSUFBSSxjQUFjLElBQUksQ0FBQyxJQUFJLGNBQWMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMvRCxPQUFPLEdBQUcsSUFBSSxDQUFDO1lBQ2hCLENBQUM7WUFFRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2QsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdEIsU0FBUztZQUNWLENBQUM7WUFFRCxJQUFJLFlBQVksSUFBSSxDQUFDLElBQUksWUFBWSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzNELE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDakIsQ0FBQztZQUVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDOUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztZQUNuQyxJQUFJLE9BQWtCLENBQUM7WUFDdkIsSUFBSSxVQUFVLFlBQVksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDNUMsVUFBVSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUNwQyxVQUFVLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztnQkFDM0IsVUFBVSxDQUFDLFNBQVMsR0FBRyxVQUFVLElBQUksQ0FBQyxDQUFDO2dCQUV2QyxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDO2dCQUNyQyxNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNsRCxVQUFVLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBRXZHLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUM7Z0JBQzVDLEdBQUcsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUNyQyxPQUFPLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxPQUFvQixDQUFDO2dCQUNoRSxlQUFlLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUNwQyxDQUFDO2lCQUFNLElBQUksVUFBVSxZQUFZLGNBQWMsRUFBRSxDQUFDO2dCQUNqRCxVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ3BDLFVBQVUsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQy9ELFVBQVUsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUM7Z0JBRTNELElBQUksVUFBVSxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUN2RCxVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2pGLENBQUM7Z0JBQ0QsVUFBVSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDdkgsU0FBUyxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUM7Z0JBRWpDLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUM7Z0JBQ3JDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRWxELE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFLE9BQW9CLENBQUM7Z0JBQ2hFLEdBQUcsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUNyQyxlQUFlLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUNwQyxDQUFDO2lCQUFNLElBQUksVUFBVSxZQUFZLGtCQUFrQixFQUFFLENBQUM7Z0JBQ3JELE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDOUMsU0FBUztZQUNWLENBQUM7aUJBQU0sQ0FBQztnQkFDUCxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN0QixTQUFTO1lBQ1YsQ0FBQztZQUVELElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztnQkFDN0IsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDbEMsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hFLFVBQVUsQ0FBQyxDQUFDLEdBQUcsYUFBYSxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO2dCQUN6RSxVQUFVLENBQUMsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztnQkFDekUsVUFBVSxDQUFDLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsZUFBZSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7Z0JBRXpFLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUMxQyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLElBQUksYUFBYSxLQUFLLFNBQVMsQ0FBQyxRQUFRLENBQUM7Z0JBQ3ZGLFVBQVUsQ0FBQyxDQUFDLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztnQkFFekMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTO29CQUNsQixTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO3FCQUN4QixDQUFDO29CQUNMLFNBQVMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO29CQUN2QyxTQUFTLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztvQkFDdkMsU0FBUyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7b0JBQ3ZDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNqQixDQUFDO2dCQUVELE1BQU0sY0FBYyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDO2dCQUN4RSxJQUFJLGNBQWMsS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDbEMsU0FBUyxHQUFHLGNBQWMsQ0FBQztvQkFDM0IsT0FBTyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDakMsQ0FBQztnQkFFRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsSUFBSSxPQUFPLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQzNKLE1BQU0sZUFBZSxHQUFHLElBQUksWUFBWSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztvQkFDbEUsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUM7b0JBQ2xELElBQUksV0FBVzt3QkFBRSxXQUFXLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQ2xGLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUMxRCxDQUFDO3FCQUFNLENBQUM7b0JBQ1AsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQztvQkFDbEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO3dCQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7NEJBQ2pGLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDOzRCQUN4QixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUM7NEJBQzVCLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQzs0QkFDNUIsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDOzRCQUM1QixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDdEIsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO3dCQUMzQixDQUFDO29CQUNGLENBQUM7eUJBQU0sQ0FBQzt3QkFDUCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7NEJBQ2pGLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDOzRCQUN4QixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUM7NEJBQzVCLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQzs0QkFDNUIsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDOzRCQUM1QixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDdEIsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDOzRCQUMxQixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7NEJBQzNCLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQzs0QkFDM0IsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDOzRCQUMzQixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7d0JBQzVCLENBQUM7b0JBQ0YsQ0FBQztvQkFDRCxNQUFNLElBQUksR0FBSSxVQUFVLENBQUMsUUFBeUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztvQkFDckYsSUFBSSxXQUFXO3dCQUFFLFdBQVcsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQ3BGLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDeEMsQ0FBQztZQUNGLENBQUM7WUFFRCxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7UUFDRCxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELCtHQUErRztJQUN4RyxtQkFBbUI7UUFDekIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3JCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEFwcmlsIDUsIDIwMjUuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyNSwgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxuICogb3Igb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB7IEJsZW5kTW9kZSwgQ2xpcHBpbmdBdHRhY2htZW50LCBDb2xvciwgTWVzaEF0dGFjaG1lbnQsIHR5cGUgTnVtYmVyQXJyYXlMaWtlLCBSZWdpb25BdHRhY2htZW50LCB0eXBlIFNrZWxldG9uLCBTa2VsZXRvbkNsaXBwaW5nLCBVdGlscywgVmVjdG9yMiB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IEdMVGV4dHVyZSB9IGZyb20gXCIuL0dMVGV4dHVyZS5qc1wiO1xuaW1wb3J0IHR5cGUgeyBQb2x5Z29uQmF0Y2hlciB9IGZyb20gXCIuL1BvbHlnb25CYXRjaGVyLmpzXCI7XG5pbXBvcnQgdHlwZSB7IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfSBmcm9tIFwiLi9XZWJHTC5qc1wiO1xuXG5cbmNsYXNzIFJlbmRlcmFibGUge1xuXHRjb25zdHJ1Y3RvciAocHVibGljIHZlcnRpY2VzOiBOdW1iZXJBcnJheUxpa2UsIHB1YmxpYyBudW1WZXJ0aWNlczogbnVtYmVyLCBwdWJsaWMgbnVtRmxvYXRzOiBudW1iZXIpIHsgfVxufTtcblxuZXhwb3J0IHR5cGUgVmVydGV4VHJhbnNmb3JtZXIgPSAodmVydGljZXM6IE51bWJlckFycmF5TGlrZSwgbnVtVmVydGljZXM6IG51bWJlciwgc3RyaWRlOiBudW1iZXIpID0+IHZvaWQ7XG5cbmV4cG9ydCBjbGFzcyBTa2VsZXRvblJlbmRlcmVyIHtcblx0c3RhdGljIFFVQURfVFJJQU5HTEVTID0gWzAsIDEsIDIsIDIsIDMsIDBdO1xuXG5cdHByaXZhdGUgdGVtcENvbG9yID0gbmV3IENvbG9yKCk7XG5cdHByaXZhdGUgdGVtcENvbG9yMiA9IG5ldyBDb2xvcigpO1xuXHRwcml2YXRlIHZlcnRpY2VzOiBOdW1iZXJBcnJheUxpa2U7XG5cdHByaXZhdGUgdmVydGV4U2l6ZSA9IDIgKyAyICsgNDtcblx0cHJpdmF0ZSB0d29Db2xvclRpbnQgPSBmYWxzZTtcblx0cHJpdmF0ZSByZW5kZXJhYmxlOiBSZW5kZXJhYmxlID0gbmV3IFJlbmRlcmFibGUoW10sIDAsIDApO1xuXHRwcml2YXRlIGNsaXBwZXI6IFNrZWxldG9uQ2xpcHBpbmcgPSBuZXcgU2tlbGV0b25DbGlwcGluZygpO1xuXG5cdC8qKlxuXHQgKiBCYXRjaGVzIGFkZGl0aXZlIHNsb3RzIHRvZ2V0aGVyIHdpdGggbm9ybWFsIHNsb3RzIGJ5IHJlbmRlcmluZyBhZGRpdGl2ZSBzbG90cyB3aXRoIHByZW11bHRpcGxpZWQgYWxwaGEgUkdCIGFuZCB6ZXJvIGFscGhhLFxuXHQgKiB3aGlsZSB1c2luZyBub3JtYWwgUE1BIGJsZW5kaW5nLiBUaGlzIHJlZHVjZXMgZHJhdyBjYWxscyBmb3Igbm9ybWFsL2FkZGl0aXZlL25vcm1hbCBzZXF1ZW5jZXMgd2l0aCB0aGUgc2FtZSB0ZXh0dXJlLlxuXHQgKiBEaXNhYmxlIHRoaXMgaWYgcmVuZGVyaW5nIHRvIGEgdHJhbnNwYXJlbnQgdGFyZ2V0IGFuZCB0aGUgYWNjdW11bGF0ZWQgZGVzdGluYXRpb24gYWxwaGEgZnJvbSBhZGRpdGl2ZSBibGVuZGluZyBtdXN0IGJlIHByZXNlcnZlZC5cblx0ICovXG5cdHBtYUFkZGl0aXZlQmF0Y2hpbmcgPSB0cnVlO1xuXG5cdGNvbnN0cnVjdG9yIChjb250ZXh0OiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB0d29Db2xvclRpbnQ6IGJvb2xlYW4gPSB0cnVlKSB7XG5cdFx0dGhpcy50d29Db2xvclRpbnQgPSB0d29Db2xvclRpbnQ7XG5cdFx0aWYgKHR3b0NvbG9yVGludClcblx0XHRcdHRoaXMudmVydGV4U2l6ZSArPSA0O1xuXHRcdHRoaXMudmVydGljZXMgPSBVdGlscy5uZXdGbG9hdEFycmF5KHRoaXMudmVydGV4U2l6ZSAqIDEwMjQpO1xuXHR9XG5cblx0ZHJhdyAoYmF0Y2hlcjogUG9seWdvbkJhdGNoZXIsIHNrZWxldG9uOiBTa2VsZXRvbiwgc2xvdFJhbmdlU3RhcnQ6IG51bWJlciA9IC0xLCBzbG90UmFuZ2VFbmQ6IG51bWJlciA9IC0xLCB0cmFuc2Zvcm1lcjogVmVydGV4VHJhbnNmb3JtZXIgfCBudWxsID0gbnVsbCkge1xuXHRcdGNvbnN0IGNsaXBwZXIgPSB0aGlzLmNsaXBwZXI7XG5cdFx0Y29uc3QgdHdvQ29sb3JUaW50ID0gdGhpcy50d29Db2xvclRpbnQ7XG5cdFx0bGV0IGJsZW5kTW9kZTogQmxlbmRNb2RlIHwgbnVsbCA9IG51bGw7XG5cblx0XHRjb25zdCByZW5kZXJhYmxlOiBSZW5kZXJhYmxlID0gdGhpcy5yZW5kZXJhYmxlO1xuXHRcdGxldCB1dnM6IE51bWJlckFycmF5TGlrZTtcblx0XHRsZXQgdHJpYW5nbGVzOiBBcnJheTxudW1iZXI+O1xuXHRcdGNvbnN0IGRyYXdPcmRlciA9IHNrZWxldG9uLmRyYXdPcmRlci5hcHBsaWVkUG9zZTtcblx0XHRsZXQgYXR0YWNobWVudENvbG9yOiBDb2xvcjtcblx0XHRjb25zdCBza2VsZXRvbkNvbG9yID0gc2tlbGV0b24uY29sb3I7XG5cdFx0Y29uc3QgdmVydGV4U2l6ZSA9IHR3b0NvbG9yVGludCA/IDEyIDogODtcblx0XHRsZXQgaW5SYW5nZSA9IGZhbHNlO1xuXHRcdGlmIChzbG90UmFuZ2VTdGFydCA9PT0gLTEpIGluUmFuZ2UgPSB0cnVlO1xuXHRcdGZvciAobGV0IGkgPSAwLCBuID0gZHJhd09yZGVyLmxlbmd0aDsgaSA8IG47IGkrKykge1xuXHRcdFx0Y29uc3Qgc2xvdCA9IGRyYXdPcmRlcltpXTtcblx0XHRcdGlmICghc2xvdC5ib25lLmFjdGl2ZSkge1xuXHRcdFx0XHRjbGlwcGVyLmNsaXBFbmQoc2xvdCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoc2xvdFJhbmdlU3RhcnQgPj0gMCAmJiBzbG90UmFuZ2VTdGFydCA9PT0gc2xvdC5kYXRhLmluZGV4KSB7XG5cdFx0XHRcdGluUmFuZ2UgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIWluUmFuZ2UpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHNsb3RSYW5nZUVuZCA+PSAwICYmIHNsb3RSYW5nZUVuZCA9PT0gc2xvdC5kYXRhLmluZGV4KSB7XG5cdFx0XHRcdGluUmFuZ2UgPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgcG9zZSA9IHNsb3QuYXBwbGllZFBvc2U7XG5cdFx0XHRjb25zdCBhdHRhY2htZW50ID0gcG9zZS5hdHRhY2htZW50O1xuXHRcdFx0bGV0IHRleHR1cmU6IEdMVGV4dHVyZTtcblx0XHRcdGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgUmVnaW9uQXR0YWNobWVudCkge1xuXHRcdFx0XHRyZW5kZXJhYmxlLnZlcnRpY2VzID0gdGhpcy52ZXJ0aWNlcztcblx0XHRcdFx0cmVuZGVyYWJsZS5udW1WZXJ0aWNlcyA9IDQ7XG5cdFx0XHRcdHJlbmRlcmFibGUubnVtRmxvYXRzID0gdmVydGV4U2l6ZSA8PCAyO1xuXG5cdFx0XHRcdGNvbnN0IHNlcXVlbmNlID0gYXR0YWNobWVudC5zZXF1ZW5jZTtcblx0XHRcdFx0Y29uc3Qgc2VxdWVuY2VJbmRleCA9IHNlcXVlbmNlLnJlc29sdmVJbmRleChwb3NlKTtcblx0XHRcdFx0YXR0YWNobWVudC5jb21wdXRlV29ybGRWZXJ0aWNlcyhzbG90LCBhdHRhY2htZW50LmdldE9mZnNldHMocG9zZSksIHJlbmRlcmFibGUudmVydGljZXMsIDAsIHZlcnRleFNpemUpO1xuXG5cdFx0XHRcdHRyaWFuZ2xlcyA9IFNrZWxldG9uUmVuZGVyZXIuUVVBRF9UUklBTkdMRVM7XG5cdFx0XHRcdHV2cyA9IHNlcXVlbmNlLmdldFVWcyhzZXF1ZW5jZUluZGV4KTtcblx0XHRcdFx0dGV4dHVyZSA9IHNlcXVlbmNlLnJlZ2lvbnNbc2VxdWVuY2VJbmRleF0/LnRleHR1cmUgYXMgR0xUZXh0dXJlO1xuXHRcdFx0XHRhdHRhY2htZW50Q29sb3IgPSBhdHRhY2htZW50LmNvbG9yO1xuXHRcdFx0fSBlbHNlIGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgTWVzaEF0dGFjaG1lbnQpIHtcblx0XHRcdFx0cmVuZGVyYWJsZS52ZXJ0aWNlcyA9IHRoaXMudmVydGljZXM7XG5cdFx0XHRcdHJlbmRlcmFibGUubnVtVmVydGljZXMgPSAoYXR0YWNobWVudC53b3JsZFZlcnRpY2VzTGVuZ3RoID4+IDEpO1xuXHRcdFx0XHRyZW5kZXJhYmxlLm51bUZsb2F0cyA9IHJlbmRlcmFibGUubnVtVmVydGljZXMgKiB2ZXJ0ZXhTaXplO1xuXG5cdFx0XHRcdGlmIChyZW5kZXJhYmxlLm51bUZsb2F0cyA+IHJlbmRlcmFibGUudmVydGljZXMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0cmVuZGVyYWJsZS52ZXJ0aWNlcyA9IHRoaXMudmVydGljZXMgPSBVdGlscy5uZXdGbG9hdEFycmF5KHJlbmRlcmFibGUubnVtRmxvYXRzKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRhdHRhY2htZW50LmNvbXB1dGVXb3JsZFZlcnRpY2VzKHNrZWxldG9uLCBzbG90LCAwLCBhdHRhY2htZW50LndvcmxkVmVydGljZXNMZW5ndGgsIHJlbmRlcmFibGUudmVydGljZXMsIDAsIHZlcnRleFNpemUpO1xuXHRcdFx0XHR0cmlhbmdsZXMgPSBhdHRhY2htZW50LnRyaWFuZ2xlcztcblxuXHRcdFx0XHRjb25zdCBzZXF1ZW5jZSA9IGF0dGFjaG1lbnQuc2VxdWVuY2U7XG5cdFx0XHRcdGNvbnN0IHNlcXVlbmNlSW5kZXggPSBzZXF1ZW5jZS5yZXNvbHZlSW5kZXgocG9zZSk7XG5cblx0XHRcdFx0dGV4dHVyZSA9IHNlcXVlbmNlLnJlZ2lvbnNbc2VxdWVuY2VJbmRleF0/LnRleHR1cmUgYXMgR0xUZXh0dXJlO1xuXHRcdFx0XHR1dnMgPSBzZXF1ZW5jZS5nZXRVVnMoc2VxdWVuY2VJbmRleCk7XG5cdFx0XHRcdGF0dGFjaG1lbnRDb2xvciA9IGF0dGFjaG1lbnQuY29sb3I7XG5cdFx0XHR9IGVsc2UgaWYgKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBDbGlwcGluZ0F0dGFjaG1lbnQpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRjbGlwcGVyLmNsaXBTdGFydChza2VsZXRvbiwgc2xvdCwgYXR0YWNobWVudCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHRleHR1cmUpIHtcblx0XHRcdFx0Y29uc3Qgc2xvdENvbG9yID0gcG9zZS5jb2xvcjtcblx0XHRcdFx0Y29uc3QgZmluYWxDb2xvciA9IHRoaXMudGVtcENvbG9yO1xuXHRcdFx0XHRjb25zdCBhbHBoYSA9IHNrZWxldG9uQ29sb3IuYSAqIHNsb3RDb2xvci5hICogYXR0YWNobWVudENvbG9yLmE7XG5cdFx0XHRcdGZpbmFsQ29sb3IuciA9IHNrZWxldG9uQ29sb3IuciAqIHNsb3RDb2xvci5yICogYXR0YWNobWVudENvbG9yLnIgKiBhbHBoYTtcblx0XHRcdFx0ZmluYWxDb2xvci5nID0gc2tlbGV0b25Db2xvci5nICogc2xvdENvbG9yLmcgKiBhdHRhY2htZW50Q29sb3IuZyAqIGFscGhhO1xuXHRcdFx0XHRmaW5hbENvbG9yLmIgPSBza2VsZXRvbkNvbG9yLmIgKiBzbG90Q29sb3IuYiAqIGF0dGFjaG1lbnRDb2xvci5iICogYWxwaGE7XG5cblx0XHRcdFx0Y29uc3Qgc2xvdEJsZW5kTW9kZSA9IHNsb3QuZGF0YS5ibGVuZE1vZGU7XG5cdFx0XHRcdGNvbnN0IGFkZGl0aXZlQmxlbmQgPSB0aGlzLnBtYUFkZGl0aXZlQmF0Y2hpbmcgJiYgc2xvdEJsZW5kTW9kZSA9PT0gQmxlbmRNb2RlLkFkZGl0aXZlO1xuXHRcdFx0XHRmaW5hbENvbG9yLmEgPSBhZGRpdGl2ZUJsZW5kID8gMCA6IGFscGhhO1xuXG5cdFx0XHRcdGNvbnN0IGRhcmtDb2xvciA9IHRoaXMudGVtcENvbG9yMjtcblx0XHRcdFx0aWYgKCFwb3NlLmRhcmtDb2xvcilcblx0XHRcdFx0XHRkYXJrQ29sb3Iuc2V0KDAsIDAsIDAsIDEuMCk7XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdGRhcmtDb2xvci5yID0gcG9zZS5kYXJrQ29sb3IuciAqIGFscGhhO1xuXHRcdFx0XHRcdGRhcmtDb2xvci5nID0gcG9zZS5kYXJrQ29sb3IuZyAqIGFscGhhO1xuXHRcdFx0XHRcdGRhcmtDb2xvci5iID0gcG9zZS5kYXJrQ29sb3IuYiAqIGFscGhhO1xuXHRcdFx0XHRcdGRhcmtDb2xvci5hID0gMTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbnN0IGJhdGNoQmxlbmRNb2RlID0gYWRkaXRpdmVCbGVuZCA/IEJsZW5kTW9kZS5Ob3JtYWwgOiBzbG90QmxlbmRNb2RlO1xuXHRcdFx0XHRpZiAoYmF0Y2hCbGVuZE1vZGUgIT09IGJsZW5kTW9kZSkge1xuXHRcdFx0XHRcdGJsZW5kTW9kZSA9IGJhdGNoQmxlbmRNb2RlO1xuXHRcdFx0XHRcdGJhdGNoZXIuc2V0QmxlbmRNb2RlKGJsZW5kTW9kZSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoY2xpcHBlci5pc0NsaXBwaW5nKCkgJiYgY2xpcHBlci5jbGlwVHJpYW5nbGVzKHJlbmRlcmFibGUudmVydGljZXMsIHRyaWFuZ2xlcywgdHJpYW5nbGVzLmxlbmd0aCwgdXZzLCBmaW5hbENvbG9yLCBkYXJrQ29sb3IsIHR3b0NvbG9yVGludCwgdmVydGV4U2l6ZSkpIHtcblx0XHRcdFx0XHRjb25zdCBjbGlwcGVkVmVydGljZXMgPSBuZXcgRmxvYXQzMkFycmF5KGNsaXBwZXIuY2xpcHBlZFZlcnRpY2VzKTtcblx0XHRcdFx0XHRjb25zdCBjbGlwcGVkVHJpYW5nbGVzID0gY2xpcHBlci5jbGlwcGVkVHJpYW5nbGVzO1xuXHRcdFx0XHRcdGlmICh0cmFuc2Zvcm1lcikgdHJhbnNmb3JtZXIoY2xpcHBlZFZlcnRpY2VzLCBjbGlwcGVkVmVydGljZXMubGVuZ3RoLCB2ZXJ0ZXhTaXplKTtcblx0XHRcdFx0XHRiYXRjaGVyLmRyYXcodGV4dHVyZSwgY2xpcHBlZFZlcnRpY2VzLCBjbGlwcGVkVHJpYW5nbGVzKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb25zdCB2ZXJ0cyA9IHJlbmRlcmFibGUudmVydGljZXM7XG5cdFx0XHRcdFx0aWYgKCF0d29Db2xvclRpbnQpIHtcblx0XHRcdFx0XHRcdGZvciAobGV0IHYgPSAyLCB1ID0gMCwgbiA9IHJlbmRlcmFibGUubnVtRmxvYXRzOyB2IDwgbjsgdiArPSB2ZXJ0ZXhTaXplLCB1ICs9IDIpIHtcblx0XHRcdFx0XHRcdFx0dmVydHNbdl0gPSBmaW5hbENvbG9yLnI7XG5cdFx0XHRcdFx0XHRcdHZlcnRzW3YgKyAxXSA9IGZpbmFsQ29sb3IuZztcblx0XHRcdFx0XHRcdFx0dmVydHNbdiArIDJdID0gZmluYWxDb2xvci5iO1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2ICsgM10gPSBmaW5hbENvbG9yLmE7XG5cdFx0XHRcdFx0XHRcdHZlcnRzW3YgKyA0XSA9IHV2c1t1XTtcblx0XHRcdFx0XHRcdFx0dmVydHNbdiArIDVdID0gdXZzW3UgKyAxXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Zm9yIChsZXQgdiA9IDIsIHUgPSAwLCBuID0gcmVuZGVyYWJsZS5udW1GbG9hdHM7IHYgPCBuOyB2ICs9IHZlcnRleFNpemUsIHUgKz0gMikge1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2XSA9IGZpbmFsQ29sb3Iucjtcblx0XHRcdFx0XHRcdFx0dmVydHNbdiArIDFdID0gZmluYWxDb2xvci5nO1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2ICsgMl0gPSBmaW5hbENvbG9yLmI7XG5cdFx0XHRcdFx0XHRcdHZlcnRzW3YgKyAzXSA9IGZpbmFsQ29sb3IuYTtcblx0XHRcdFx0XHRcdFx0dmVydHNbdiArIDRdID0gdXZzW3VdO1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2ICsgNV0gPSB1dnNbdSArIDFdO1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2ICsgNl0gPSBkYXJrQ29sb3Iucjtcblx0XHRcdFx0XHRcdFx0dmVydHNbdiArIDddID0gZGFya0NvbG9yLmc7XG5cdFx0XHRcdFx0XHRcdHZlcnRzW3YgKyA4XSA9IGRhcmtDb2xvci5iO1xuXHRcdFx0XHRcdFx0XHR2ZXJ0c1t2ICsgOV0gPSBkYXJrQ29sb3IuYTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Y29uc3QgdmlldyA9IChyZW5kZXJhYmxlLnZlcnRpY2VzIGFzIEZsb2F0MzJBcnJheSkuc3ViYXJyYXkoMCwgcmVuZGVyYWJsZS5udW1GbG9hdHMpO1xuXHRcdFx0XHRcdGlmICh0cmFuc2Zvcm1lcikgdHJhbnNmb3JtZXIocmVuZGVyYWJsZS52ZXJ0aWNlcywgcmVuZGVyYWJsZS5udW1GbG9hdHMsIHZlcnRleFNpemUpO1xuXHRcdFx0XHRcdGJhdGNoZXIuZHJhdyh0ZXh0dXJlLCB2aWV3LCB0cmlhbmdsZXMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHR9XG5cdFx0Y2xpcHBlci5jbGlwRW5kKCk7XG5cdH1cblxuXHQvKiogUmV0dXJucyB0aGUge0BsaW5rIFNrZWxldG9uQ2xpcHBpbmd9IHVzZWQgYnkgdGhpcyByZW5kZXJlciBmb3IgdXNlIHdpdGggZS5nLiB7QGxpbmsgU2tlbGV0b24uZ2V0Qm91bmRzfSAqKi9cblx0cHVibGljIGdldFNrZWxldG9uQ2xpcHBpbmcgKCk6IFNrZWxldG9uQ2xpcHBpbmcge1xuXHRcdHJldHVybiB0aGlzLmNsaXBwZXI7XG5cdH1cbn1cbiJdfQ==