UNPKG

@esotericsoftware/spine-webgl

Version:
280 lines (274 loc) 32.8 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 { ManagedWebGLRenderingContext } from "./WebGL.js"; export class Shader { vertexShader; fragmentShader; static MVP_MATRIX = "u_projTrans"; static POSITION = "a_position"; static COLOR = "a_color"; static COLOR2 = "a_color2"; static TEXCOORDS = "a_texCoords"; static SAMPLER = "u_texture"; context; vs = null; vsSource; fs = null; fsSource; program = null; tmp2x2 = new Float32Array(2 * 2); tmp3x3 = new Float32Array(3 * 3); tmp4x4 = new Float32Array(4 * 4); getProgram() { return this.program; } getVertexShader() { return this.vertexShader; } getFragmentShader() { return this.fragmentShader; } getVertexShaderSource() { return this.vsSource; } getFragmentSource() { return this.fsSource; } constructor(context, vertexShader, fragmentShader) { this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.vsSource = vertexShader; this.fsSource = fragmentShader; this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); this.context.addRestorable(this); this.compile(); } compile() { let gl = this.context.gl; try { this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); if (!this.vs) throw new Error("Couldn't compile vertex shader."); this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); if (!this.fs) throw new Error("Couldn#t compile fragment shader."); this.program = this.compileProgram(this.vs, this.fs); } catch (e) { this.dispose(); throw e; } } compileShader(type, source) { let gl = this.context.gl; let shader = gl.createShader(type); if (!shader) throw new Error("Couldn't create shader."); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); gl.deleteShader(shader); if (!gl.isContextLost()) throw new Error(error); } return shader; } compileProgram(vs, fs) { let gl = this.context.gl; let program = gl.createProgram(); if (!program) throw new Error("Couldn't compile program."); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); gl.deleteProgram(program); if (!gl.isContextLost()) throw new Error(error); } return program; } restore() { this.compile(); } bind() { this.context.gl.useProgram(this.program); } unbind() { this.context.gl.useProgram(null); } setUniformi(uniform, value) { this.context.gl.uniform1i(this.getUniformLocation(uniform), value); } setUniformf(uniform, value) { this.context.gl.uniform1f(this.getUniformLocation(uniform), value); } setUniform2f(uniform, value, value2) { this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); } setUniform3f(uniform, value, value2, value3) { this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); } setUniform4f(uniform, value, value2, value3, value4) { this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); } setUniform2x2f(uniform, value) { let gl = this.context.gl; this.tmp2x2.set(value); gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); } setUniform3x3f(uniform, value) { let gl = this.context.gl; this.tmp3x3.set(value); gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); } setUniform4x4f(uniform, value) { let gl = this.context.gl; this.tmp4x4.set(value); gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); } getUniformLocation(uniform) { let gl = this.context.gl; if (!this.program) throw new Error("Shader not compiled."); let location = gl.getUniformLocation(this.program, uniform); if (!location && !gl.isContextLost()) throw new Error(`Couldn't find location for uniform ${uniform}`); return location; } getAttributeLocation(attribute) { let gl = this.context.gl; if (!this.program) throw new Error("Shader not compiled."); let location = gl.getAttribLocation(this.program, attribute); if (location == -1 && !gl.isContextLost()) throw new Error(`Couldn't find location for attribute ${attribute}`); return location; } dispose() { this.context.removeRestorable(this); let gl = this.context.gl; if (this.vs) { gl.deleteShader(this.vs); this.vs = null; } if (this.fs) { gl.deleteShader(this.fs); this.fs = null; } if (this.program) { gl.deleteProgram(this.program); this.program = null; } } static newColoredTextured(context) { let vs = ` attribute vec4 ${Shader.POSITION}; attribute vec4 ${Shader.COLOR}; attribute vec2 ${Shader.TEXCOORDS}; uniform mat4 ${Shader.MVP_MATRIX}; varying vec4 v_color; varying vec2 v_texCoords; void main () { v_color = ${Shader.COLOR}; v_texCoords = ${Shader.TEXCOORDS}; gl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION}; } `; let fs = ` #ifdef GL_ES #define LOWP lowp precision mediump float; #else #define LOWP #endif varying LOWP vec4 v_color; varying vec2 v_texCoords; uniform sampler2D u_texture; void main () { gl_FragColor = v_color * texture2D(u_texture, v_texCoords); } `; return new Shader(context, vs, fs); } static newTwoColoredTextured(context) { let vs = ` attribute vec4 ${Shader.POSITION}; attribute vec4 ${Shader.COLOR}; attribute vec4 ${Shader.COLOR2}; attribute vec2 ${Shader.TEXCOORDS}; uniform mat4 ${Shader.MVP_MATRIX}; varying vec4 v_light; varying vec4 v_dark; varying vec2 v_texCoords; void main () { v_light = ${Shader.COLOR}; v_dark = ${Shader.COLOR2}; v_texCoords = ${Shader.TEXCOORDS}; gl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION}; } `; let fs = ` #ifdef GL_ES #define LOWP lowp precision mediump float; #else #define LOWP #endif varying LOWP vec4 v_light; varying LOWP vec4 v_dark; varying vec2 v_texCoords; uniform sampler2D u_texture; void main () { vec4 texColor = texture2D(u_texture, v_texCoords); gl_FragColor.a = texColor.a * v_light.a; gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; } `; return new Shader(context, vs, fs); } static newColored(context) { let vs = ` attribute vec4 ${Shader.POSITION}; attribute vec4 ${Shader.COLOR}; uniform mat4 ${Shader.MVP_MATRIX}; varying vec4 v_color; void main () { v_color = ${Shader.COLOR}; gl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION}; } `; let fs = ` #ifdef GL_ES #define LOWP lowp precision mediump float; #else #define LOWP #endif varying LOWP vec4 v_color; void main () { gl_FragColor = v_color; } `; return new Shader(context, vs, fs); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2hhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NoYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFHL0UsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTFELE1BQU0sT0FBTyxNQUFNO0lBd0JrRTtJQUE4QjtJQXZCM0csTUFBTSxDQUFDLFVBQVUsR0FBRyxhQUFhLENBQUM7SUFDbEMsTUFBTSxDQUFDLFFBQVEsR0FBRyxZQUFZLENBQUM7SUFDL0IsTUFBTSxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUM7SUFDekIsTUFBTSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUM7SUFDM0IsTUFBTSxDQUFDLFNBQVMsR0FBRyxhQUFhLENBQUM7SUFDakMsTUFBTSxDQUFDLE9BQU8sR0FBRyxXQUFXLENBQUM7SUFFNUIsT0FBTyxDQUErQjtJQUN0QyxFQUFFLEdBQXVCLElBQUksQ0FBQztJQUM5QixRQUFRLENBQVM7SUFDakIsRUFBRSxHQUF1QixJQUFJLENBQUM7SUFDOUIsUUFBUSxDQUFTO0lBQ2pCLE9BQU8sR0FBd0IsSUFBSSxDQUFDO0lBQ3BDLE1BQU0sR0FBaUIsSUFBSSxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBaUIsSUFBSSxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBaUIsSUFBSSxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRWhELFVBQVUsS0FBTSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLGVBQWUsS0FBTSxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO0lBQ2hELGlCQUFpQixLQUFNLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDcEQscUJB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WVYsQ0FBQztRQUVBLE9BQU8sSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNwQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgeyBEaXNwb3NhYmxlLCBSZXN0b3JhYmxlIH0gZnJvbSBcIkBlc290ZXJpY3NvZnR3YXJlL3NwaW5lLWNvcmVcIjtcbmltcG9ydCB7IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfSBmcm9tIFwiLi9XZWJHTC5qc1wiO1xuXG5leHBvcnQgY2xhc3MgU2hhZGVyIGltcGxlbWVudHMgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB7XG5cdHB1YmxpYyBzdGF0aWMgTVZQX01BVFJJWCA9IFwidV9wcm9qVHJhbnNcIjtcblx0cHVibGljIHN0YXRpYyBQT1NJVElPTiA9IFwiYV9wb3NpdGlvblwiO1xuXHRwdWJsaWMgc3RhdGljIENPTE9SID0gXCJhX2NvbG9yXCI7XG5cdHB1YmxpYyBzdGF0aWMgQ09MT1IyID0gXCJhX2NvbG9yMlwiO1xuXHRwdWJsaWMgc3RhdGljIFRFWENPT1JEUyA9IFwiYV90ZXhDb29yZHNcIjtcblx0cHVibGljIHN0YXRpYyBTQU1QTEVSID0gXCJ1X3RleHR1cmVcIjtcblxuXHRwcml2YXRlIGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cdHByaXZhdGUgdnM6IFdlYkdMU2hhZGVyIHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgdnNTb3VyY2U6IHN0cmluZztcblx0cHJpdmF0ZSBmczogV2ViR0xTaGFkZXIgfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBmc1NvdXJjZTogc3RyaW5nO1xuXHRwcml2YXRlIHByb2dyYW06IFdlYkdMUHJvZ3JhbSB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHRtcDJ4MjogRmxvYXQzMkFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSgyICogMik7XG5cdHByaXZhdGUgdG1wM3gzOiBGbG9hdDMyQXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KDMgKiAzKTtcblx0cHJpdmF0ZSB0bXA0eDQ6IEZsb2F0MzJBcnJheSA9IG5ldyBGbG9hdDMyQXJyYXkoNCAqIDQpO1xuXG5cdHB1YmxpYyBnZXRQcm9ncmFtICgpIHsgcmV0dXJuIHRoaXMucHJvZ3JhbTsgfVxuXHRwdWJsaWMgZ2V0VmVydGV4U2hhZGVyICgpIHsgcmV0dXJuIHRoaXMudmVydGV4U2hhZGVyOyB9XG5cdHB1YmxpYyBnZXRGcmFnbWVudFNoYWRlciAoKSB7IHJldHVybiB0aGlzLmZyYWdtZW50U2hhZGVyOyB9XG5cdHB1YmxpYyBnZXRWZXJ0ZXhTaGFkZXJTb3VyY2UgKCkgeyByZXR1cm4gdGhpcy52c1NvdXJjZTsgfVxuXHRwdWJsaWMgZ2V0RnJhZ21lbnRTb3VyY2UgKCkgeyByZXR1cm4gdGhpcy5mc1NvdXJjZTsgfVxuXG5cdGNvbnN0cnVjdG9yIChjb250ZXh0OiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0IHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBwcml2YXRlIHZlcnRleFNoYWRlcjogc3RyaW5nLCBwcml2YXRlIGZyYWdtZW50U2hhZGVyOiBzdHJpbmcpIHtcblx0XHR0aGlzLnZzU291cmNlID0gdmVydGV4U2hhZGVyO1xuXHRcdHRoaXMuZnNTb3VyY2UgPSBmcmFnbWVudFNoYWRlcjtcblx0XHR0aGlzLmNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCA/IGNvbnRleHQgOiBuZXcgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dChjb250ZXh0KTtcblx0XHR0aGlzLmNvbnRleHQuYWRkUmVzdG9yYWJsZSh0aGlzKTtcblx0XHR0aGlzLmNvbXBpbGUoKTtcblx0fVxuXG5cdHByaXZhdGUgY29tcGlsZSAoKSB7XG5cdFx0bGV0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLnZzID0gdGhpcy5jb21waWxlU2hhZGVyKGdsLlZFUlRFWF9TSEFERVIsIHRoaXMudmVydGV4U2hhZGVyKTtcblx0XHRcdGlmICghdGhpcy52cykgdGhyb3cgbmV3IEVycm9yKFwiQ291bGRuJ3QgY29tcGlsZSB2ZXJ0ZXggc2hhZGVyLlwiKTtcblx0XHRcdHRoaXMuZnMgPSB0aGlzLmNvbXBpbGVTaGFkZXIoZ2wuRlJBR01FTlRfU0hBREVSLCB0aGlzLmZyYWdtZW50U2hhZGVyKTtcblx0XHRcdGlmICghdGhpcy5mcykgdGhyb3cgbmV3IEVycm9yKFwiQ291bGRuI3QgY29tcGlsZSBmcmFnbWVudCBzaGFkZXIuXCIpO1xuXHRcdFx0dGhpcy5wcm9ncmFtID0gdGhpcy5jb21waWxlUHJvZ3JhbSh0aGlzLnZzLCB0aGlzLmZzKTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHR0aGlzLmRpc3Bvc2UoKTtcblx0XHRcdHRocm93IGU7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBjb21waWxlU2hhZGVyICh0eXBlOiBudW1iZXIsIHNvdXJjZTogc3RyaW5nKSB7XG5cdFx0bGV0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdGxldCBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIodHlwZSk7XG5cdFx0aWYgKCFzaGFkZXIpIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGNyZWF0ZSBzaGFkZXIuXCIpO1xuXHRcdGdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNvdXJjZSk7XG5cdFx0Z2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuXHRcdGlmICghZ2wuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgZ2wuQ09NUElMRV9TVEFUVVMpKSB7XG5cdFx0XHRsZXQgZXJyb3IgPSBcIkNvdWxkbid0IGNvbXBpbGUgc2hhZGVyOiBcIiArIGdsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKTtcblx0XHRcdGdsLmRlbGV0ZVNoYWRlcihzaGFkZXIpO1xuXHRcdFx0aWYgKCFnbC5pc0NvbnRleHRMb3N0KCkpIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdFx0fVxuXHRcdHJldHVybiBzaGFkZXI7XG5cdH1cblxuXHRwcml2YXRlIGNvbXBpbGVQcm9ncmFtICh2czogV2ViR0xTaGFkZXIsIGZzOiBXZWJHTFNoYWRlcikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRsZXQgcHJvZ3JhbSA9IGdsLmNyZWF0ZVByb2dyYW0oKTtcblx0XHRpZiAoIXByb2dyYW0pIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGNvbXBpbGUgcHJvZ3JhbS5cIik7XG5cdFx0Z2wuYXR0YWNoU2hhZGVyKHByb2dyYW0sIHZzKTtcblx0XHRnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnMpO1xuXHRcdGdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuXG5cdFx0aWYgKCFnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkxJTktfU1RBVFVTKSkge1xuXHRcdFx0bGV0IGVycm9yID0gXCJDb3VsZG4ndCBjb21waWxlIHNoYWRlciBwcm9ncmFtOiBcIiArIGdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pO1xuXHRcdFx0Z2wuZGVsZXRlUHJvZ3JhbShwcm9ncmFtKTtcblx0XHRcdGlmICghZ2wuaXNDb250ZXh0TG9zdCgpKSB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHRcdH1cblx0XHRyZXR1cm4gcHJvZ3JhbTtcblx0fVxuXG5cdHJlc3RvcmUgKCkge1xuXHRcdHRoaXMuY29tcGlsZSgpO1xuXHR9XG5cblx0cHVibGljIGJpbmQgKCkge1xuXHRcdHRoaXMuY29udGV4dC5nbC51c2VQcm9ncmFtKHRoaXMucHJvZ3JhbSk7XG5cdH1cblxuXHRwdWJsaWMgdW5iaW5kICgpIHtcblx0XHR0aGlzLmNvbnRleHQuZ2wudXNlUHJvZ3JhbShudWxsKTtcblx0fVxuXG5cdHB1YmxpYyBzZXRVbmlmb3JtaSAodW5pZm9ybTogc3RyaW5nLCB2YWx1ZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5jb250ZXh0LmdsLnVuaWZvcm0xaSh0aGlzLmdldFVuaWZvcm1Mb2NhdGlvbih1bmlmb3JtKSwgdmFsdWUpO1xuXHR9XG5cblx0cHVibGljIHNldFVuaWZvcm1mICh1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLmNvbnRleHQuZ2wudW5pZm9ybTFmKHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHVuaWZvcm0pLCB2YWx1ZSk7XG5cdH1cblxuXHRwdWJsaWMgc2V0VW5pZm9ybTJmICh1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIsIHZhbHVlMjogbnVtYmVyKSB7XG5cdFx0dGhpcy5jb250ZXh0LmdsLnVuaWZvcm0yZih0aGlzLmdldFVuaWZvcm1Mb2NhdGlvbih1bmlmb3JtKSwgdmFsdWUsIHZhbHVlMik7XG5cdH1cblxuXHRwdWJsaWMgc2V0VW5pZm9ybTNmICh1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIsIHZhbHVlMjogbnVtYmVyLCB2YWx1ZTM6IG51bWJlcikge1xuXHRcdHRoaXMuY29udGV4dC5nbC51bmlmb3JtM2YodGhpcy5nZXRVbmlmb3JtTG9jYXRpb24odW5pZm9ybSksIHZhbHVlLCB2YWx1ZTIsIHZhbHVlMyk7XG5cdH1cblxuXHRwdWJsaWMgc2V0VW5pZm9ybTRmICh1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIsIHZhbHVlMjogbnVtYmVyLCB2YWx1ZTM6IG51bWJlciwgdmFsdWU0OiBudW1iZXIpIHtcblx0XHR0aGlzLmNvbnRleHQuZ2wudW5pZm9ybTRmKHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHVuaWZvcm0pLCB2YWx1ZSwgdmFsdWUyLCB2YWx1ZTMsIHZhbHVlNCk7XG5cdH1cblxuXHRwdWJsaWMgc2V0VW5pZm9ybTJ4MmYgKHVuaWZvcm06IHN0cmluZywgdmFsdWU6IEFycmF5TGlrZTxudW1iZXI+KSB7XG5cdFx0bGV0IGdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdHRoaXMudG1wMngyLnNldCh2YWx1ZSk7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDJmdih0aGlzLmdldFVuaWZvcm1Mb2NhdGlvbih1bmlmb3JtKSwgZmFsc2UsIHRoaXMudG1wMngyKTtcblx0fVxuXG5cdHB1YmxpYyBzZXRVbmlmb3JtM3gzZiAodW5pZm9ybTogc3RyaW5nLCB2YWx1ZTogQXJyYXlMaWtlPG51bWJlcj4pIHtcblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0dGhpcy50bXAzeDMuc2V0KHZhbHVlKTtcblx0XHRnbC51bmlmb3JtTWF0cml4M2Z2KHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHVuaWZvcm0pLCBmYWxzZSwgdGhpcy50bXAzeDMpO1xuXHR9XG5cblx0cHVibGljIHNldFVuaWZvcm00eDRmICh1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBBcnJheUxpa2U8bnVtYmVyPikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHR0aGlzLnRtcDR4NC5zZXQodmFsdWUpO1xuXHRcdGdsLnVuaWZvcm1NYXRyaXg0ZnYodGhpcy5nZXRVbmlmb3JtTG9jYXRpb24odW5pZm9ybSksIGZhbHNlLCB0aGlzLnRtcDR4NCk7XG5cdH1cblxuXHRwdWJsaWMgZ2V0VW5pZm9ybUxvY2F0aW9uICh1bmlmb3JtOiBzdHJpbmcpOiBXZWJHTFVuaWZvcm1Mb2NhdGlvbiB8IG51bGwge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRpZiAoIXRoaXMucHJvZ3JhbSkgdGhyb3cgbmV3IEVycm9yKFwiU2hhZGVyIG5vdCBjb21waWxlZC5cIik7XG5cdFx0bGV0IGxvY2F0aW9uID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHRoaXMucHJvZ3JhbSwgdW5pZm9ybSk7XG5cdFx0aWYgKCFsb2NhdGlvbiAmJiAhZ2wuaXNDb250ZXh0TG9zdCgpKSB0aHJvdyBuZXcgRXJyb3IoYENvdWxkbid0IGZpbmQgbG9jYXRpb24gZm9yIHVuaWZvcm0gJHt1bmlmb3JtfWApO1xuXHRcdHJldHVybiBsb2NhdGlvbjtcblx0fVxuXG5cdHB1YmxpYyBnZXRBdHRyaWJ1dGVMb2NhdGlvbiAoYXR0cmlidXRlOiBzdHJpbmcpOiBudW1iZXIge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRpZiAoIXRoaXMucHJvZ3JhbSkgdGhyb3cgbmV3IEVycm9yKFwiU2hhZGVyIG5vdCBjb21waWxlZC5cIik7XG5cdFx0bGV0IGxvY2F0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24odGhpcy5wcm9ncmFtLCBhdHRyaWJ1dGUpO1xuXHRcdGlmIChsb2NhdGlvbiA9PSAtMSAmJiAhZ2wuaXNDb250ZXh0TG9zdCgpKSB0aHJvdyBuZXcgRXJyb3IoYENvdWxkbid0IGZpbmQgbG9jYXRpb24gZm9yIGF0dHJpYnV0ZSAke2F0dHJpYnV0ZX1gKTtcblx0XHRyZXR1cm4gbG9jYXRpb247XG5cdH1cblxuXHRwdWJsaWMgZGlzcG9zZSAoKSB7XG5cdFx0dGhpcy5jb250ZXh0LnJlbW92ZVJlc3RvcmFibGUodGhpcyk7XG5cblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0aWYgKHRoaXMudnMpIHtcblx0XHRcdGdsLmRlbGV0ZVNoYWRlcih0aGlzLnZzKTtcblx0XHRcdHRoaXMudnMgPSBudWxsO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLmZzKSB7XG5cdFx0XHRnbC5kZWxldGVTaGFkZXIodGhpcy5mcyk7XG5cdFx0XHR0aGlzLmZzID0gbnVsbDtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5wcm9ncmFtKSB7XG5cdFx0XHRnbC5kZWxldGVQcm9ncmFtKHRoaXMucHJvZ3JhbSk7XG5cdFx0XHR0aGlzLnByb2dyYW0gPSBudWxsO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBzdGF0aWMgbmV3Q29sb3JlZFRleHR1cmVkIChjb250ZXh0OiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0IHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogU2hhZGVyIHtcblx0XHRsZXQgdnMgPSBgXG5hdHRyaWJ1dGUgdmVjNCAke1NoYWRlci5QT1NJVElPTn07XG5hdHRyaWJ1dGUgdmVjNCAke1NoYWRlci5DT0xPUn07XG5hdHRyaWJ1dGUgdmVjMiAke1NoYWRlci5URVhDT09SRFN9O1xudW5pZm9ybSBtYXQ0ICR7U2hhZGVyLk1WUF9NQVRSSVh9O1xudmFyeWluZyB2ZWM0IHZfY29sb3I7XG52YXJ5aW5nIHZlYzIgdl90ZXhDb29yZHM7XG5cbnZvaWQgbWFpbiAoKSB7XG5cdHZfY29sb3IgPSAke1NoYWRlci5DT0xPUn07XG5cdHZfdGV4Q29vcmRzID0gJHtTaGFkZXIuVEVYQ09PUkRTfTtcblx0Z2xfUG9zaXRpb24gPSAke1NoYWRlci5NVlBfTUFUUklYfSAqICR7U2hhZGVyLlBPU0lUSU9OfTtcbn1cbmA7XG5cblx0XHRsZXQgZnMgPSBgXG4jaWZkZWYgR0xfRVNcblx0I2RlZmluZSBMT1dQIGxvd3Bcblx0cHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XG4jZWxzZVxuXHQjZGVmaW5lIExPV1BcbiNlbmRpZlxudmFyeWluZyBMT1dQIHZlYzQgdl9jb2xvcjtcbnZhcnlpbmcgdmVjMiB2X3RleENvb3JkcztcbnVuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTtcblxudm9pZCBtYWluICgpIHtcblx0Z2xfRnJhZ0NvbG9yID0gdl9jb2xvciAqIHRleHR1cmUyRCh1X3RleHR1cmUsIHZfdGV4Q29vcmRzKTtcbn1cbmA7XG5cblx0XHRyZXR1cm4gbmV3IFNoYWRlcihjb250ZXh0LCB2cywgZnMpO1xuXHR9XG5cblx0cHVibGljIHN0YXRpYyBuZXdUd29Db2xvcmVkVGV4dHVyZWQgKGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfCBXZWJHTFJlbmRlcmluZ0NvbnRleHQpOiBTaGFkZXIge1xuXHRcdGxldCB2cyA9IGBcbmF0dHJpYnV0ZSB2ZWM0ICR7U2hhZGVyLlBPU0lUSU9OfTtcbmF0dHJpYnV0ZSB2ZWM0ICR7U2hhZGVyLkNPTE9SfTtcbmF0dHJpYnV0ZSB2ZWM0ICR7U2hhZGVyLkNPTE9SMn07XG5hdHRyaWJ1dGUgdmVjMiAke1NoYWRlci5URVhDT09SRFN9O1xudW5pZm9ybSBtYXQ0ICR7U2hhZGVyLk1WUF9NQVRSSVh9O1xudmFyeWluZyB2ZWM0IHZfbGlnaHQ7XG52YXJ5aW5nIHZlYzQgdl9kYXJrO1xudmFyeWluZyB2ZWMyIHZfdGV4Q29vcmRzO1xuXG52b2lkIG1haW4gKCkge1xuXHR2X2xpZ2h0ID0gJHtTaGFkZXIuQ09MT1J9O1xuXHR2X2RhcmsgPSAke1NoYWRlci5DT0xPUjJ9O1xuXHR2X3RleENvb3JkcyA9ICR7U2hhZGVyLlRFWENPT1JEU307XG5cdGdsX1Bvc2l0aW9uID0gJHtTaGFkZXIuTVZQX01BVFJJWH0gKiAke1NoYWRlci5QT1NJVElPTn07XG59XG5gO1xuXG5cdFx0bGV0IGZzID0gYFxuI2lmZGVmIEdMX0VTXG5cdCNkZWZpbmUgTE9XUCBsb3dwXG5cdHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xuI2Vsc2Vcblx0I2RlZmluZSBMT1dQXG4jZW5kaWZcbnZhcnlpbmcgTE9XUCB2ZWM0IHZfbGlnaHQ7XG52YXJ5aW5nIExPV1AgdmVjNCB2X2Rhcms7XG52YXJ5aW5nIHZlYzIgdl90ZXhDb29yZHM7XG51bmlmb3JtIHNhbXBsZXIyRCB1X3RleHR1cmU7XG5cbnZvaWQgbWFpbiAoKSB7XG5cdHZlYzQgdGV4Q29sb3IgPSB0ZXh0dXJlMkQodV90ZXh0dXJlLCB2X3RleENvb3Jkcyk7XG5cdGdsX0ZyYWdDb2xvci5hID0gdGV4Q29sb3IuYSAqIHZfbGlnaHQuYTtcblx0Z2xfRnJhZ0NvbG9yLnJnYiA9ICgodGV4Q29sb3IuYSAtIDEuMCkgKiB2X2RhcmsuYSArIDEuMCAtIHRleENvbG9yLnJnYikgKiB2X2RhcmsucmdiICsgdGV4Q29sb3IucmdiICogdl9saWdodC5yZ2I7XG59XG5gO1xuXG5cdFx0cmV0dXJuIG5ldyBTaGFkZXIoY29udGV4dCwgdnMsIGZzKTtcblx0fVxuXG5cdHB1YmxpYyBzdGF0aWMgbmV3Q29sb3JlZCAoY29udGV4dDogTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCB8IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IFNoYWRlciB7XG5cdFx0bGV0IHZzID0gYFxuYXR0cmlidXRlIHZlYzQgJHtTaGFkZXIuUE9TSVRJT059O1xuYXR0cmlidXRlIHZlYzQgJHtTaGFkZXIuQ09MT1J9O1xudW5pZm9ybSBtYXQ0ICR7U2hhZGVyLk1WUF9NQVRSSVh9O1xudmFyeWluZyB2ZWM0IHZfY29sb3I7XG5cbnZvaWQgbWFpbiAoKSB7XG5cdHZfY29sb3IgPSAke1NoYWRlci5DT0xPUn07XG5cdGdsX1Bvc2l0aW9uID0gJHtTaGFkZXIuTVZQX01BVFJJWH0gKiAke1NoYWRlci5QT1NJVElPTn07XG59XG5gO1xuXG5cdFx0bGV0IGZzID0gYFxuI2lmZGVmIEdMX0VTXG5cdCNkZWZpbmUgTE9XUCBsb3dwXG5cdHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xuI2Vsc2Vcblx0I2RlZmluZSBMT1dQXG4jZW5kaWZcbnZhcnlpbmcgTE9XUCB2ZWM0IHZfY29sb3I7XG5cbnZvaWQgbWFpbiAoKSB7XG5cdGdsX0ZyYWdDb2xvciA9IHZfY29sb3I7XG59XG5gO1xuXG5cdFx0cmV0dXJuIG5ldyBTaGFkZXIoY29udGV4dCwgdnMsIGZzKTtcblx0fVxufVxuIl19