@esotericsoftware/spine-webgl
Version:
The official Spine Runtimes for the web.
163 lines • 24.3 kB
JavaScript
/******************************************************************************
* 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 { Color2Attribute, ColorAttribute, Mesh, Position2Attribute, TexCoordAttribute } from "./Mesh.js";
import { ManagedWebGLRenderingContext } from "./WebGL.js";
const GL_ONE = 1;
const GL_ONE_MINUS_SRC_COLOR = 0x0301;
const GL_ONE_MINUS_SRC_ALPHA = 0x0303;
const GL_DST_COLOR = 0x0306;
export class PolygonBatcher {
static disableCulling = false;
context;
drawCalls = 0;
static globalDrawCalls = 0;
isDrawing = false;
mesh;
shader = null;
lastTexture = null;
verticesLength = 0;
indicesLength = 0;
srcColorBlend;
srcAlphaBlend;
dstBlend;
cullWasEnabled = false;
constructor(context, twoColorTint = true, maxVertices = 10920) {
if (maxVertices > 10920)
throw new Error(`Can't have more than 10920 triangles per batch: ${maxVertices}`);
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
const attributes = twoColorTint ?
[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] :
[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()];
this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3);
const gl = this.context.gl;
this.srcColorBlend = gl.SRC_ALPHA;
this.srcAlphaBlend = gl.ONE;
this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
}
begin(shader) {
if (this.isDrawing)
throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()");
this.drawCalls = 0;
this.shader = shader;
this.lastTexture = null;
this.isDrawing = true;
const gl = this.context.gl;
gl.enable(gl.BLEND);
gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
if (PolygonBatcher.disableCulling) {
this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);
if (this.cullWasEnabled)
gl.disable(gl.CULL_FACE);
}
}
static blendModesGL = [
{ srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },
{ srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE },
{ srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },
{ srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE }
];
setBlendMode(blendMode) {
const blendModeGL = PolygonBatcher.blendModesGL[blendMode];
const srcColorBlend = blendModeGL.srcRgbPma;
const srcAlphaBlend = blendModeGL.srcAlpha;
const dstBlend = blendModeGL.dstRgb;
if (this.srcColorBlend === srcColorBlend && this.srcAlphaBlend === srcAlphaBlend && this.dstBlend === dstBlend)
return;
this.srcColorBlend = srcColorBlend;
this.srcAlphaBlend = srcAlphaBlend;
this.dstBlend = dstBlend;
if (this.isDrawing) {
this.flush();
}
const gl = this.context.gl;
gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
}
draw(texture, vertices, indices) {
if (texture !== this.lastTexture) {
this.flush();
this.lastTexture = texture;
}
else if (this.verticesLength + vertices.length > this.mesh.getVertices().length ||
this.indicesLength + indices.length > this.mesh.getIndices().length) {
this.flush();
}
const indexStart = this.mesh.numVertices();
this.mesh.getVertices().set(vertices, this.verticesLength);
this.verticesLength += vertices.length;
this.mesh.setVerticesLength(this.verticesLength);
const indicesArray = this.mesh.getIndices();
for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++)
indicesArray[i] = indices[j] + indexStart;
this.indicesLength += indices.length;
this.mesh.setIndicesLength(this.indicesLength);
}
flush() {
if (this.verticesLength === 0)
return;
if (!this.lastTexture)
throw new Error("No texture set.");
if (!this.shader)
throw new Error("No shader set.");
this.lastTexture.bind();
this.mesh.draw(this.shader, this.context.gl.TRIANGLES);
this.verticesLength = 0;
this.indicesLength = 0;
this.mesh.setVerticesLength(0);
this.mesh.setIndicesLength(0);
this.drawCalls++;
PolygonBatcher.globalDrawCalls++;
}
end() {
if (!this.isDrawing)
throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()");
if (this.verticesLength > 0 || this.indicesLength > 0)
this.flush();
this.shader = null;
this.lastTexture = null;
this.isDrawing = false;
const gl = this.context.gl;
gl.disable(gl.BLEND);
if (PolygonBatcher.disableCulling) {
if (this.cullWasEnabled)
gl.enable(gl.CULL_FACE);
}
}
getDrawCalls() {
return this.drawCalls;
}
static getAndResetGlobalDrawCalls() {
const result = PolygonBatcher.globalDrawCalls;
PolygonBatcher.globalDrawCalls = 0;
return result;
}
dispose() {
this.mesh.dispose();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUG9seWdvbkJhdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvUG9seWdvbkJhdGNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBSS9FLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV6RyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFMUQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBQ2pCLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSxDQUFDO0FBQ3RDLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSxDQUFDO0FBQ3RDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQztBQUU1QixNQUFNLE9BQU8sY0FBYztJQUNuQixNQUFNLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztJQUU3QixPQUFPLENBQStCO0lBQ3RDLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFDZCxNQUFNLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQztJQUNuQyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ1YsSUFBSSxDQUFPO0lBQ1gsTUFBTSxHQUFrQixJQUFJLENBQUM7SUFDN0IsV0FBVyxHQUFxQixJQUFJLENBQUM7SUFDckMsY0FBYyxHQUFHLENBQUMsQ0FBQztJQUNuQixhQUFhLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLGFBQWEsQ0FBUztJQUN0QixhQUFhLENBQVM7SUFDdEIsUUFBUSxDQUFTO0lBQ2pCLGNBQWMsR0FBRyxLQUFLLENBQUM7SUFFL0IsWUFBYSxPQUE2RCxFQUFFLGVBQXdCLElBQUksRUFBRSxjQUFzQixLQUFLO1FBQ3BJLElBQUksV0FBVyxHQUFHLEtBQUs7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzNH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UUFDbkMsT0FBTyxNQUFNLENBQUM7SUFDZixDQUFDO0lBRUQsT0FBTztRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDckIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgQXByaWwgNSwgMjAyNS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDI1LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0ZcbiAqIFRIRSBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHR5cGUgeyBCbGVuZE1vZGUsIERpc3Bvc2FibGUgfSBmcm9tIFwiQGVzb3Rlcmljc29mdHdhcmUvc3BpbmUtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBHTFRleHR1cmUgfSBmcm9tIFwiLi9HTFRleHR1cmUuanNcIjtcbmltcG9ydCB7IENvbG9yMkF0dHJpYnV0ZSwgQ29sb3JBdHRyaWJ1dGUsIE1lc2gsIFBvc2l0aW9uMkF0dHJpYnV0ZSwgVGV4Q29vcmRBdHRyaWJ1dGUgfSBmcm9tIFwiLi9NZXNoLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFNoYWRlciB9IGZyb20gXCIuL1NoYWRlci5qc1wiO1xuaW1wb3J0IHsgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCB9IGZyb20gXCIuL1dlYkdMLmpzXCI7XG5cbmNvbnN0IEdMX09ORSA9IDE7XG5jb25zdCBHTF9PTkVfTUlOVVNfU1JDX0NPTE9SID0gMHgwMzAxO1xuY29uc3QgR0xfT05FX01JTlVTX1NSQ19BTFBIQSA9IDB4MDMwMztcbmNvbnN0IEdMX0RTVF9DT0xPUiA9IDB4MDMwNjtcblxuZXhwb3J0IGNsYXNzIFBvbHlnb25CYXRjaGVyIGltcGxlbWVudHMgRGlzcG9zYWJsZSB7XG5cdHB1YmxpYyBzdGF0aWMgZGlzYWJsZUN1bGxpbmcgPSBmYWxzZTtcblxuXHRwcml2YXRlIGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cdHByaXZhdGUgZHJhd0NhbGxzID0gMDtcblx0cHJpdmF0ZSBzdGF0aWMgZ2xvYmFsRHJhd0NhbGxzID0gMDtcblx0aXNEcmF3aW5nID0gZmFsc2U7XG5cdHByaXZhdGUgbWVzaDogTWVzaDtcblx0cHJpdmF0ZSBzaGFkZXI6IFNoYWRlciB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIGxhc3RUZXh0dXJlOiBHTFRleHR1cmUgfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSB2ZXJ0aWNlc0xlbmd0aCA9IDA7XG5cdHByaXZhdGUgaW5kaWNlc0xlbmd0aCA9IDA7XG5cdHByaXZhdGUgc3JjQ29sb3JCbGVuZDogbnVtYmVyO1xuXHRwcml2YXRlIHNyY0FscGhhQmxlbmQ6IG51bWJlcjtcblx0cHJpdmF0ZSBkc3RCbGVuZDogbnVtYmVyO1xuXHRwcml2YXRlIGN1bGxXYXNFbmFibGVkID0gZmFsc2U7XG5cblx0Y29uc3RydWN0b3IgKGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfCBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHR3b0NvbG9yVGludDogYm9vbGVhbiA9IHRydWUsIG1heFZlcnRpY2VzOiBudW1iZXIgPSAxMDkyMCkge1xuXHRcdGlmIChtYXhWZXJ0aWNlcyA+IDEwOTIwKSB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGhhdmUgbW9yZSB0aGFuIDEwOTIwIHRyaWFuZ2xlcyBwZXIgYmF0Y2g6ICR7bWF4VmVydGljZXN9YCk7XG5cdFx0dGhpcy5jb250ZXh0ID0gY29udGV4dCBpbnN0YW5jZW9mIE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgPyBjb250ZXh0IDogbmV3IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQoY29udGV4dCk7XG5cdFx0Y29uc3QgYXR0cmlidXRlcyA9IHR3b0NvbG9yVGludCA/XG5cdFx0XHRbbmV3IFBvc2l0aW9uMkF0dHJpYnV0ZSgpLCBuZXcgQ29sb3JBdHRyaWJ1dGUoKSwgbmV3IFRleENvb3JkQXR0cmlidXRlKCksIG5ldyBDb2xvcjJBdHRyaWJ1dGUoKV0gOlxuXHRcdFx0W25ldyBQb3NpdGlvbjJBdHRyaWJ1dGUoKSwgbmV3IENvbG9yQXR0cmlidXRlKCksIG5ldyBUZXhDb29yZEF0dHJpYnV0ZSgpXTtcblx0XHR0aGlzLm1lc2ggPSBuZXcgTWVzaChjb250ZXh0LCBhdHRyaWJ1dGVzLCBtYXhWZXJ0aWNlcywgbWF4VmVydGljZXMgKiAzKTtcblx0XHRjb25zdCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHR0aGlzLnNyY0NvbG9yQmxlbmQgPSBnbC5TUkNfQUxQSEE7XG5cdFx0dGhpcy5zcmNBbHBoYUJsZW5kID0gZ2wuT05FO1xuXHRcdHRoaXMuZHN0QmxlbmQgPSBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBO1xuXHR9XG5cblx0YmVnaW4gKHNoYWRlcjogU2hhZGVyKSB7XG5cdFx0aWYgKHRoaXMuaXNEcmF3aW5nKSB0aHJvdyBuZXcgRXJyb3IoXCJQb2x5Z29uQmF0Y2ggaXMgYWxyZWFkeSBkcmF3aW5nLiBDYWxsIFBvbHlnb25CYXRjaC5lbmQoKSBiZWZvcmUgY2FsbGluZyBQb2x5Z29uQmF0Y2guYmVnaW4oKVwiKTtcblx0XHR0aGlzLmRyYXdDYWxscyA9IDA7XG5cdFx0dGhpcy5zaGFkZXIgPSBzaGFkZXI7XG5cdFx0dGhpcy5sYXN0VGV4dHVyZSA9IG51bGw7XG5cdFx0dGhpcy5pc0RyYXdpbmcgPSB0cnVlO1xuXG5cdFx0Y29uc3QgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0Z2wuZW5hYmxlKGdsLkJMRU5EKTtcblx0XHRnbC5ibGVuZEZ1bmNTZXBhcmF0ZSh0aGlzLnNyY0NvbG9yQmxlbmQsIHRoaXMuZHN0QmxlbmQsIHRoaXMuc3JjQWxwaGFCbGVuZCwgdGhpcy5kc3RCbGVuZCk7XG5cblx0XHRpZiAoUG9seWdvbkJhdGNoZXIuZGlzYWJsZUN1bGxpbmcpIHtcblx0XHRcdHRoaXMuY3VsbFdhc0VuYWJsZWQgPSBnbC5pc0VuYWJsZWQoZ2wuQ1VMTF9GQUNFKTtcblx0XHRcdGlmICh0aGlzLmN1bGxXYXNFbmFibGVkKSBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBzdGF0aWMgYmxlbmRNb2Rlc0dMOiB7IHNyY1JnYlBtYTogbnVtYmVyLCBkc3RSZ2I6IG51bWJlciwgc3JjQWxwaGE6IG51bWJlciB9W10gPSBbXG5cdFx0eyBzcmNSZ2JQbWE6IEdMX09ORSwgZHN0UmdiOiBHTF9PTkVfTUlOVVNfU1JDX0FMUEhBLCBzcmNBbHBoYTogR0xfT05FIH0sXG5cdFx0eyBzcmNSZ2JQbWE6IEdMX09ORSwgZHN0UmdiOiBHTF9PTkUsIHNyY0FscGhhOiBHTF9PTkUgfSxcblx0XHR7IHNyY1JnYlBtYTogR0xfRFNUX0NPTE9SLCBkc3RSZ2I6IEdMX09ORV9NSU5VU19TUkNfQUxQSEEsIHNyY0FscGhhOiBHTF9PTkUgfSxcblx0XHR7IHNyY1JnYlBtYTogR0xfT05FLCBkc3RSZ2I6IEdMX09ORV9NSU5VU19TUkNfQ09MT1IsIHNyY0FscGhhOiBHTF9PTkUgfVxuXHRdXG5cblx0c2V0QmxlbmRNb2RlIChibGVuZE1vZGU6IEJsZW5kTW9kZSkge1xuXHRcdGNvbnN0IGJsZW5kTW9kZUdMID0gUG9seWdvbkJhdGNoZXIuYmxlbmRNb2Rlc0dMW2JsZW5kTW9kZV07XG5cdFx0Y29uc3Qgc3JjQ29sb3JCbGVuZCA9IGJsZW5kTW9kZUdMLnNyY1JnYlBtYTtcblx0XHRjb25zdCBzcmNBbHBoYUJsZW5kID0gYmxlbmRNb2RlR0wuc3JjQWxwaGE7XG5cdFx0Y29uc3QgZHN0QmxlbmQgPSBibGVuZE1vZGVHTC5kc3RSZ2I7XG5cblx0XHRpZiAodGhpcy5zcmNDb2xvckJsZW5kID09PSBzcmNDb2xvckJsZW5kICYmIHRoaXMuc3JjQWxwaGFCbGVuZCA9PT0gc3JjQWxwaGFCbGVuZCAmJiB0aGlzLmRzdEJsZW5kID09PSBkc3RCbGVuZCkgcmV0dXJuO1xuXHRcdHRoaXMuc3JjQ29sb3JCbGVuZCA9IHNyY0NvbG9yQmxlbmQ7XG5cdFx0dGhpcy5zcmNBbHBoYUJsZW5kID0gc3JjQWxwaGFCbGVuZDtcblx0XHR0aGlzLmRzdEJsZW5kID0gZHN0QmxlbmQ7XG5cdFx0aWYgKHRoaXMuaXNEcmF3aW5nKSB7XG5cdFx0XHR0aGlzLmZsdXNoKCk7XG5cdFx0fVxuXHRcdGNvbnN0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdGdsLmJsZW5kRnVuY1NlcGFyYXRlKHNyY0NvbG9yQmxlbmQsIGRzdEJsZW5kLCBzcmNBbHBoYUJsZW5kLCBkc3RCbGVuZCk7XG5cdH1cblxuXHRkcmF3ICh0ZXh0dXJlOiBHTFRleHR1cmUsIHZlcnRpY2VzOiBBcnJheUxpa2U8bnVtYmVyPiwgaW5kaWNlczogQXJyYXk8bnVtYmVyPikge1xuXHRcdGlmICh0ZXh0dXJlICE9PSB0aGlzLmxhc3RUZXh0dXJlKSB7XG5cdFx0XHR0aGlzLmZsdXNoKCk7XG5cdFx0XHR0aGlzLmxhc3RUZXh0dXJlID0gdGV4dHVyZTtcblx0XHR9IGVsc2UgaWYgKHRoaXMudmVydGljZXNMZW5ndGggKyB2ZXJ0aWNlcy5sZW5ndGggPiB0aGlzLm1lc2guZ2V0VmVydGljZXMoKS5sZW5ndGggfHxcblx0XHRcdHRoaXMuaW5kaWNlc0xlbmd0aCArIGluZGljZXMubGVuZ3RoID4gdGhpcy5tZXNoLmdldEluZGljZXMoKS5sZW5ndGgpIHtcblx0XHRcdHRoaXMuZmx1c2goKTtcblx0XHR9XG5cblx0XHRjb25zdCBpbmRleFN0YXJ0ID0gdGhpcy5tZXNoLm51bVZlcnRpY2VzKCk7XG5cdFx0dGhpcy5tZXNoLmdldFZlcnRpY2VzKCkuc2V0KHZlcnRpY2VzLCB0aGlzLnZlcnRpY2VzTGVuZ3RoKTtcblx0XHR0aGlzLnZlcnRpY2VzTGVuZ3RoICs9IHZlcnRpY2VzLmxlbmd0aDtcblx0XHR0aGlzLm1lc2guc2V0VmVydGljZXNMZW5ndGgodGhpcy52ZXJ0aWNlc0xlbmd0aClcblxuXHRcdGNvbnN0IGluZGljZXNBcnJheSA9IHRoaXMubWVzaC5nZXRJbmRpY2VzKCk7XG5cdFx0Zm9yIChsZXQgaSA9IHRoaXMuaW5kaWNlc0xlbmd0aCwgaiA9IDA7IGogPCBpbmRpY2VzLmxlbmd0aDsgaSsrLCBqKyspXG5cdFx0XHRpbmRpY2VzQXJyYXlbaV0gPSBpbmRpY2VzW2pdICsgaW5kZXhTdGFydDtcblx0XHR0aGlzLmluZGljZXNMZW5ndGggKz0gaW5kaWNlcy5sZW5ndGg7XG5cdFx0dGhpcy5tZXNoLnNldEluZGljZXNMZW5ndGgodGhpcy5pbmRpY2VzTGVuZ3RoKTtcblx0fVxuXG5cdGZsdXNoICgpIHtcblx0XHRpZiAodGhpcy52ZXJ0aWNlc0xlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXHRcdGlmICghdGhpcy5sYXN0VGV4dHVyZSkgdGhyb3cgbmV3IEVycm9yKFwiTm8gdGV4dHVyZSBzZXQuXCIpO1xuXHRcdGlmICghdGhpcy5zaGFkZXIpIHRocm93IG5ldyBFcnJvcihcIk5vIHNoYWRlciBzZXQuXCIpO1xuXHRcdHRoaXMubGFzdFRleHR1cmUuYmluZCgpO1xuXHRcdHRoaXMubWVzaC5kcmF3KHRoaXMuc2hhZGVyLCB0aGlzLmNvbnRleHQuZ2wuVFJJQU5HTEVTKTtcblxuXHRcdHRoaXMudmVydGljZXNMZW5ndGggPSAwO1xuXHRcdHRoaXMuaW5kaWNlc0xlbmd0aCA9IDA7XG5cdFx0dGhpcy5tZXNoLnNldFZlcnRpY2VzTGVuZ3RoKDApO1xuXHRcdHRoaXMubWVzaC5zZXRJbmRpY2VzTGVuZ3RoKDApO1xuXHRcdHRoaXMuZHJhd0NhbGxzKys7XG5cdFx0UG9seWdvbkJhdGNoZXIuZ2xvYmFsRHJhd0NhbGxzKys7XG5cdH1cblxuXHRlbmQgKCkge1xuXHRcdGlmICghdGhpcy5pc0RyYXdpbmcpIHRocm93IG5ldyBFcnJvcihcIlBvbHlnb25CYXRjaCBpcyBub3QgZHJhd2luZy4gQ2FsbCBQb2x5Z29uQmF0Y2guYmVnaW4oKSBiZWZvcmUgY2FsbGluZyBQb2x5Z29uQmF0Y2guZW5kKClcIik7XG5cdFx0aWYgKHRoaXMudmVydGljZXNMZW5ndGggPiAwIHx8IHRoaXMuaW5kaWNlc0xlbmd0aCA+IDApIHRoaXMuZmx1c2goKTtcblx0XHR0aGlzLnNoYWRlciA9IG51bGw7XG5cdFx0dGhpcy5sYXN0VGV4dHVyZSA9IG51bGw7XG5cdFx0dGhpcy5pc0RyYXdpbmcgPSBmYWxzZTtcblxuXHRcdGNvbnN0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdGdsLmRpc2FibGUoZ2wuQkxFTkQpO1xuXHRcdGlmIChQb2x5Z29uQmF0Y2hlci5kaXNhYmxlQ3VsbGluZykge1xuXHRcdFx0aWYgKHRoaXMuY3VsbFdhc0VuYWJsZWQpIGdsLmVuYWJsZShnbC5DVUxMX0ZBQ0UpO1xuXHRcdH1cblx0fVxuXG5cdGdldERyYXdDYWxscyAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZHJhd0NhbGxzO1xuXHR9XG5cblx0c3RhdGljIGdldEFuZFJlc2V0R2xvYmFsRHJhd0NhbGxzICgpIHtcblx0XHRjb25zdCByZXN1bHQgPSBQb2x5Z29uQmF0Y2hlci5nbG9iYWxEcmF3Q2FsbHM7XG5cdFx0UG9seWdvbkJhdGNoZXIuZ2xvYmFsRHJhd0NhbGxzID0gMDtcblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0ZGlzcG9zZSAoKSB7XG5cdFx0dGhpcy5tZXNoLmRpc3Bvc2UoKTtcblx0fVxufVxuIl19