@esotericsoftware/spine-webgl
Version:
The official Spine Runtimes for the web.
280 lines (274 loc) • 32.8 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 { 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