@esotericsoftware/spine-webgl
Version:
The official Spine Runtimes for the web.
203 lines • 27.9 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 { Shader } from "./Shader.js";
import { ManagedWebGLRenderingContext } from "./WebGL.js";
export class Mesh {
attributes;
context;
vertices;
verticesBuffer = null;
verticesLength = 0;
dirtyVertices = false;
indices;
indicesBuffer = null;
indicesLength = 0;
dirtyIndices = false;
elementsPerVertex = 0;
getAttributes() { return this.attributes; }
maxVertices() { return this.vertices.length / this.elementsPerVertex; }
numVertices() { return this.verticesLength / this.elementsPerVertex; }
setVerticesLength(length) {
this.dirtyVertices = true;
this.verticesLength = length;
}
getVertices() { return this.vertices; }
maxIndices() { return this.indices.length; }
numIndices() { return this.indicesLength; }
setIndicesLength(length) {
this.dirtyIndices = true;
this.indicesLength = length;
}
getIndices() { return this.indices; }
;
getVertexSizeInFloats() {
let size = 0;
for (let i = 0; i < this.attributes.length; i++) {
const attribute = this.attributes[i];
size += attribute.numElements;
}
return size;
}
constructor(context, attributes, maxVertices, maxIndices) {
this.attributes = attributes;
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
this.elementsPerVertex = 0;
for (let i = 0; i < attributes.length; i++) {
this.elementsPerVertex += attributes[i].numElements;
}
this.vertices = new Float32Array(maxVertices * this.elementsPerVertex);
this.indices = new Uint16Array(maxIndices);
this.context.addRestorable(this);
}
setVertices(vertices) {
this.dirtyVertices = true;
if (vertices.length > this.vertices.length)
throw Error(`Mesh can't store more than ${this.maxVertices()} vertices`);
this.vertices.set(vertices, 0);
this.verticesLength = vertices.length;
}
setIndices(indices) {
this.dirtyIndices = true;
if (indices.length > this.indices.length)
throw Error(`Mesh can't store more than ${this.maxIndices()} indices`);
this.indices.set(indices, 0);
this.indicesLength = indices.length;
}
draw(shader, primitiveType) {
this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex);
}
drawWithOffset(shader, primitiveType, offset, count) {
const gl = this.context.gl;
if (this.dirtyVertices || this.dirtyIndices)
this.update();
this.bind(shader);
if (this.indicesLength > 0) {
gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2);
}
else {
gl.drawArrays(primitiveType, offset, count);
}
this.unbind(shader);
}
bind(shader) {
const gl = this.context.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
let offset = 0;
for (let i = 0; i < this.attributes.length; i++) {
const attrib = this.attributes[i];
const location = shader.getAttributeLocation(attrib.name);
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4);
offset += attrib.numElements;
}
if (this.indicesLength > 0)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
}
unbind(shader) {
const gl = this.context.gl;
for (let i = 0; i < this.attributes.length; i++) {
const attrib = this.attributes[i];
const location = shader.getAttributeLocation(attrib.name);
gl.disableVertexAttribArray(location);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
if (this.indicesLength > 0)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
update() {
const gl = this.context.gl;
if (this.dirtyVertices) {
if (!this.verticesBuffer) {
this.verticesBuffer = gl.createBuffer();
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
this.dirtyVertices = false;
}
if (this.dirtyIndices) {
if (!this.indicesBuffer) {
this.indicesBuffer = gl.createBuffer();
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
this.dirtyIndices = false;
}
}
restore() {
this.verticesBuffer = null;
this.indicesBuffer = null;
this.update();
}
dispose() {
this.context.removeRestorable(this);
const gl = this.context.gl;
gl.deleteBuffer(this.verticesBuffer);
gl.deleteBuffer(this.indicesBuffer);
}
}
export class VertexAttribute {
name;
type;
numElements;
constructor(name, type, numElements) {
this.name = name;
this.type = type;
this.numElements = numElements;
}
}
export class Position2Attribute extends VertexAttribute {
constructor() {
super(Shader.POSITION, VertexAttributeType.Float, 2);
}
}
export class Position3Attribute extends VertexAttribute {
constructor() {
super(Shader.POSITION, VertexAttributeType.Float, 3);
}
}
export class TexCoordAttribute extends VertexAttribute {
constructor(unit = 0) {
super(Shader.TEXCOORDS + (unit === 0 ? "" : unit), VertexAttributeType.Float, 2);
}
}
export class ColorAttribute extends VertexAttribute {
constructor() {
super(Shader.COLOR, VertexAttributeType.Float, 4);
}
}
export class Color2Attribute extends VertexAttribute {
constructor() {
super(Shader.COLOR2, VertexAttributeType.Float, 4);
}
}
export var VertexAttributeType;
(function (VertexAttributeType) {
VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float";
})(VertexAttributeType || (VertexAttributeType = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9NZXNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUcvRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUcxRCxNQUFNLE9BQU8sSUFBSTtJQXVDb0U7SUF0QzVFLE9BQU8sQ0FBK0I7SUFDdEMsUUFBUSxDQUFlO0lBQ3ZCLGNBQWMsR0FBdUIsSUFBSSxDQUFDO0lBQzFDLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUN0QixPQUFPLENBQWM7SUFDckIsYUFBYSxHQUF1QixJQUFJLENBQUM7SUFDekMsYUFBYSxHQUFHLENBQUMsQ0FBQztJQUNsQixZQUFZLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLGlCQUFpQixHQUFHLENBQUMsQ0FBQztJQUU5QixhQUFhLEtBQXlCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFFL0QsV0FBVyxLQUFjLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUNoRixXQUFXLEtBQWMsT0FBTyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDL0UsaUJBQWlCLENBQUUsTUFBYztRQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQztJQUM5QixDQUFDO0lBQ0QsV0FBVyxLQUFvQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXRELFVBQVUsS0FBYyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFD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RSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEYsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGNBQWUsU0FBUSxlQUFlO0lBQ2xEO1FBQ0MsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELENBQUM7Q0FDRDtBQUVELE1BQU0sT0FBTyxlQUFnQixTQUFRLGVBQWU7SUFDbkQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDcEQsQ0FBQztDQUNEO0FBRUQsTUFBTSxDQUFOLElBQVksbUJBRVg7QUFGRCxXQUFZLG1CQUFtQjtJQUM5QiwrREFBSyxDQUFBO0FBQ04sQ0FBQyxFQUZXLG1CQUFtQixLQUFuQixtQkFBbUIsUUFFOUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEFwcmlsIDUsIDIwMjUuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyNSwgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxuICogb3Igb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB0eXBlIHsgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jb3JlXCI7XG5pbXBvcnQgeyBTaGFkZXIgfSBmcm9tIFwiLi9TaGFkZXIuanNcIjtcbmltcG9ydCB7IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfSBmcm9tIFwiLi9XZWJHTC5qc1wiO1xuXG5cbmV4cG9ydCBjbGFzcyBNZXNoIGltcGxlbWVudHMgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB7XG5cdHByaXZhdGUgY29udGV4dDogTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcblx0cHJpdmF0ZSB2ZXJ0aWNlczogRmxvYXQzMkFycmF5O1xuXHRwcml2YXRlIHZlcnRpY2VzQnVmZmVyOiBXZWJHTEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHZlcnRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eVZlcnRpY2VzID0gZmFsc2U7XG5cdHByaXZhdGUgaW5kaWNlczogVWludDE2QXJyYXk7XG5cdHByaXZhdGUgaW5kaWNlc0J1ZmZlcjogV2ViR0xCdWZmZXIgfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBpbmRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0cHJpdmF0ZSBlbGVtZW50c1BlclZlcnRleCA9IDA7XG5cblx0Z2V0QXR0cmlidXRlcyAoKTogVmVydGV4QXR0cmlidXRlW10geyByZXR1cm4gdGhpcy5hdHRyaWJ1dGVzOyB9XG5cblx0bWF4VmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzLmxlbmd0aCAvIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXg7IH1cblx0bnVtVmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzTGVuZ3RoIC8gdGhpcy5lbGVtZW50c1BlclZlcnRleDsgfVxuXHRzZXRWZXJ0aWNlc0xlbmd0aCAobGVuZ3RoOiBudW1iZXIpIHtcblx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSB0cnVlO1xuXHRcdHRoaXMudmVydGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0VmVydGljZXMgKCk6IEZsb2F0MzJBcnJheSB7IHJldHVybiB0aGlzLnZlcnRpY2VzOyB9XG5cblx0bWF4SW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlcy5sZW5ndGg7IH1cblx0bnVtSW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlc0xlbmd0aDsgfVxuXHRzZXRJbmRpY2VzTGVuZ3RoIChsZW5ndGg6IG51bWJlcikge1xuXHRcdHRoaXMuZGlydHlJbmRpY2VzID0gdHJ1ZTtcblx0XHR0aGlzLmluZGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0SW5kaWNlcyAoKTogVWludDE2QXJyYXkgeyByZXR1cm4gdGhpcy5pbmRpY2VzIH07XG5cblx0Z2V0VmVydGV4U2l6ZUluRmxvYXRzICgpOiBudW1iZXIge1xuXHRcdGxldCBzaXplID0gMDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgYXR0cmlidXRlID0gdGhpcy5hdHRyaWJ1dGVzW2ldO1xuXHRcdFx0c2l6ZSArPSBhdHRyaWJ1dGUubnVtRWxlbWVudHM7XG5cdFx0fVxuXHRcdHJldHVybiBzaXplO1xuXHR9XG5cblx0Y29uc3RydWN0b3IgKGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfCBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHByaXZhdGUgYXR0cmlidXRlczogVmVydGV4QXR0cmlidXRlW10sIG1heFZlcnRpY2VzOiBudW1iZXIsIG1heEluZGljZXM6IG51bWJlcikge1xuXHRcdHRoaXMuY29udGV4dCA9IGNvbnRleHQgaW5zdGFuY2VvZiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0ID8gY29udGV4dCA6IG5ldyBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0KGNvbnRleHQpO1xuXHRcdHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXggPSAwO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dGhpcy5lbGVtZW50c1BlclZlcnRleCArPSBhdHRyaWJ1dGVzW2ldLm51bUVsZW1lbnRzO1xuXHRcdH1cblx0XHR0aGlzLnZlcnRpY2VzID0gbmV3IEZsb2F0MzJBcnJheShtYXhWZXJ0aWNlcyAqIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXgpO1xuXHRcdHRoaXMuaW5kaWNlcyA9IG5ldyBVaW50MTZBcnJheShtYXhJbmRpY2VzKTtcblx0XHR0aGlzLmNvbnRleHQuYWRkUmVzdG9yYWJsZSh0aGlzKTtcblx0fVxuXG5cdHNldFZlcnRpY2VzICh2ZXJ0aWNlczogQXJyYXk8bnVtYmVyPikge1xuXHRcdHRoaXMuZGlydHlWZXJ0aWNlcyA9IHRydWU7XG5cdFx0aWYgKHZlcnRpY2VzLmxlbmd0aCA+IHRoaXMudmVydGljZXMubGVuZ3RoKSB0aHJvdyBFcnJvcihgTWVzaCBjYW4ndCBzdG9yZSBtb3JlIHRoYW4gJHt0aGlzLm1heFZlcnRpY2VzKCl9IHZlcnRpY2VzYCk7XG5cdFx0dGhpcy52ZXJ0aWNlcy5zZXQodmVydGljZXMsIDApO1xuXHRcdHRoaXMudmVydGljZXNMZW5ndGggPSB2ZXJ0aWNlcy5sZW5ndGg7XG5cdH1cblxuXHRzZXRJbmRpY2VzIChpbmRpY2VzOiBBcnJheTxudW1iZXI+KSB7XG5cdFx0dGhpcy5kaXJ0eUluZGljZXMgPSB0cnVlO1xuXHRcdGlmIChpbmRpY2VzLmxlbmd0aCA+IHRoaXMuaW5kaWNlcy5sZW5ndGgpIHRocm93IEVycm9yKGBNZXNoIGNhbid0IHN0b3JlIG1vcmUgdGhhbiAke3RoaXMubWF4SW5kaWNlcygpfSBpbmRpY2VzYCk7XG5cdFx0dGhpcy5pbmRpY2VzLnNldChpbmRpY2VzLCAwKTtcblx0XHR0aGlzLmluZGljZXNMZW5ndGggPSBpbmRpY2VzLmxlbmd0aDtcblx0fVxuXG5cdGRyYXcgKHNoYWRlcjogU2hhZGVyLCBwcmltaXRpdmVUeXBlOiBudW1iZXIpIHtcblx0XHR0aGlzLmRyYXdXaXRoT2Zmc2V0KHNoYWRlciwgcHJpbWl0aXZlVHlwZSwgMCwgdGhpcy5pbmRpY2VzTGVuZ3RoID4gMCA/IHRoaXMuaW5kaWNlc0xlbmd0aCA6IHRoaXMudmVydGljZXNMZW5ndGggLyB0aGlzLmVsZW1lbnRzUGVyVmVydGV4KTtcblx0fVxuXG5cdGRyYXdXaXRoT2Zmc2V0IChzaGFkZXI6IFNoYWRlciwgcHJpbWl0aXZlVHlwZTogbnVtYmVyLCBvZmZzZXQ6IG51bWJlciwgY291bnQ6IG51bWJlcikge1xuXHRcdGNvbnN0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdGlmICh0aGlzLmRpcnR5VmVydGljZXMgfHwgdGhpcy5kaXJ0eUluZGljZXMpIHRoaXMudXBkYXRlKCk7XG5cdFx0dGhpcy5iaW5kKHNoYWRlcik7XG5cdFx0aWYgKHRoaXMuaW5kaWNlc0xlbmd0aCA+IDApIHtcblx0XHRcdGdsLmRyYXdFbGVtZW50cyhwcmltaXRpdmVUeXBlLCBjb3VudCwgZ2wuVU5TSUdORURfU0hPUlQsIG9mZnNldCAqIDIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRnbC5kcmF3QXJyYXlzKHByaW1pdGl2ZVR5cGUsIG9mZnNldCwgY291bnQpO1xuXHRcdH1cblx0XHR0aGlzLnVuYmluZChzaGFkZXIpO1xuXHR9XG5cblx0YmluZCAoc2hhZGVyOiBTaGFkZXIpIHtcblx0XHRjb25zdCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGhpcy52ZXJ0aWNlc0J1ZmZlcik7XG5cdFx0bGV0IG9mZnNldCA9IDA7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGF0dHJpYiA9IHRoaXMuYXR0cmlidXRlc1tpXTtcblx0XHRcdGNvbnN0IGxvY2F0aW9uID0gc2hhZGVyLmdldEF0dHJpYnV0ZUxvY2F0aW9uKGF0dHJpYi5uYW1lKTtcblx0XHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGxvY2F0aW9uKTtcblx0XHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIobG9jYXRpb24sIGF0dHJpYi5udW1FbGVtZW50cywgZ2wuRkxPQVQsIGZhbHNlLCB0aGlzLmVsZW1lbnRzUGVyVmVydGV4ICogNCwgb2Zmc2V0ICogNCk7XG5cdFx0XHRvZmZzZXQgKz0gYXR0cmliLm51bUVsZW1lbnRzO1xuXHRcdH1cblx0XHRpZiAodGhpcy5pbmRpY2VzTGVuZ3RoID4gMCkgZ2wuYmluZEJ1ZmZlcihnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgdGhpcy5pbmRpY2VzQnVmZmVyKTtcblx0fVxuXG5cdHVuYmluZCAoc2hhZGVyOiBTaGFkZXIpIHtcblx0XHRjb25zdCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgYXR0cmliID0gdGhpcy5hdHRyaWJ1dGVzW2ldO1xuXHRcdFx0Y29uc3QgbG9jYXRpb24gPSBzaGFkZXIuZ2V0QXR0cmlidXRlTG9jYXRpb24oYXR0cmliLm5hbWUpO1xuXHRcdFx0Z2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGxvY2F0aW9uKTtcblx0XHR9XG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIG51bGwpO1xuXHRcdGlmICh0aGlzLmluZGljZXNMZW5ndGggPiAwKSBnbC5iaW5kQnVmZmVyKGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSLCBudWxsKTtcblx0fVxuXG5cdHByaXZhdGUgdXBkYXRlICgpIHtcblx0XHRjb25zdCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRpZiAodGhpcy5kaXJ0eVZlcnRpY2VzKSB7XG5cdFx0XHRpZiAoIXRoaXMudmVydGljZXNCdWZmZXIpIHtcblx0XHRcdFx0dGhpcy52ZXJ0aWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXNCdWZmZXIpO1xuXHRcdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXMuc3ViYXJyYXkoMCwgdGhpcy52ZXJ0aWNlc0xlbmd0aCksIGdsLkRZTkFNSUNfRFJBVyk7XG5cdFx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kaXJ0eUluZGljZXMpIHtcblx0XHRcdGlmICghdGhpcy5pbmRpY2VzQnVmZmVyKSB7XG5cdFx0XHRcdHRoaXMuaW5kaWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgdGhpcy5pbmRpY2VzQnVmZmVyKTtcblx0XHRcdGdsLmJ1ZmZlckRhdGEoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIHRoaXMuaW5kaWNlcy5zdWJhcnJheSgwLCB0aGlzLmluZGljZXNMZW5ndGgpLCBnbC5EWU5BTUlDX0RSQVcpO1xuXHRcdFx0dGhpcy5kaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRyZXN0b3JlICgpIHtcblx0XHR0aGlzLnZlcnRpY2VzQnVmZmVyID0gbnVsbDtcblx0XHR0aGlzLmluZGljZXNCdWZmZXIgPSBudWxsO1xuXHRcdHRoaXMudXBkYXRlKCk7XG5cdH1cblxuXHRkaXNwb3NlICgpIHtcblx0XHR0aGlzLmNvbnRleHQucmVtb3ZlUmVzdG9yYWJsZSh0aGlzKTtcblx0XHRjb25zdCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRnbC5kZWxldGVCdWZmZXIodGhpcy52ZXJ0aWNlc0J1ZmZlcik7XG5cdFx0Z2wuZGVsZXRlQnVmZmVyKHRoaXMuaW5kaWNlc0J1ZmZlcik7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFZlcnRleEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yIChwdWJsaWMgbmFtZTogc3RyaW5nLCBwdWJsaWMgdHlwZTogVmVydGV4QXR0cmlidXRlVHlwZSwgcHVibGljIG51bUVsZW1lbnRzOiBudW1iZXIpIHsgfVxufVxuXG5leHBvcnQgY2xhc3MgUG9zaXRpb24yQXR0cmlidXRlIGV4dGVuZHMgVmVydGV4QXR0cmlidXRlIHtcblx0Y29uc3RydWN0b3IgKCkge1xuXHRcdHN1cGVyKFNoYWRlci5QT1NJVElPTiwgVmVydGV4QXR0cmlidXRlVHlwZS5GbG9hdCwgMik7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvc2l0aW9uM0F0dHJpYnV0ZSBleHRlbmRzIFZlcnRleEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yICgpIHtcblx0XHRzdXBlcihTaGFkZXIuUE9TSVRJT04sIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDMpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBUZXhDb29yZEF0dHJpYnV0ZSBleHRlbmRzIFZlcnRleEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yICh1bml0OiBudW1iZXIgPSAwKSB7XG5cdFx0c3VwZXIoU2hhZGVyLlRFWENPT1JEUyArICh1bml0ID09PSAwID8gXCJcIiA6IHVuaXQpLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCAyKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3JBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAoKSB7XG5cdFx0c3VwZXIoU2hhZGVyLkNPTE9SLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCA0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3IyQXR0cmlidXRlIGV4dGVuZHMgVmVydGV4QXR0cmlidXRlIHtcblx0Y29uc3RydWN0b3IgKCkge1xuXHRcdHN1cGVyKFNoYWRlci5DT0xPUjIsIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDQpO1xuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFZlcnRleEF0dHJpYnV0ZVR5cGUge1xuXHRGbG9hdFxufVxuIl19