Ai_Assistant/client/node_modules/@pixiv/three-vrm-materials-v0compat/lib/three-vrm-materials-v0compat.module.js

359 lines
50 KiB
JavaScript
Raw Normal View History

2026-05-24 13:31:30 +02:00
/*!
* @pixiv/three-vrm-materials-v0compat v3.4.1
* VRM0.0 materials compatibility layer plugin for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-materials-v0compat is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/VRMMaterialsV0CompatPlugin.ts
import * as THREE from "three";
// src/utils/gammaEOTF.ts
function gammaEOTF(e) {
return Math.pow(e, 2.2);
}
// src/VRMMaterialsV0CompatPlugin.ts
var VRMMaterialsV0CompatPlugin = class {
get name() {
return "VRMMaterialsV0CompatPlugin";
}
constructor(parser) {
var _a;
this.parser = parser;
this._renderQueueMapTransparent = /* @__PURE__ */ new Map();
this._renderQueueMapTransparentZWrite = /* @__PURE__ */ new Map();
const json = this.parser.json;
json.extensionsUsed = (_a = json.extensionsUsed) != null ? _a : [];
if (json.extensionsUsed.indexOf("KHR_texture_transform") === -1) {
json.extensionsUsed.push("KHR_texture_transform");
}
}
beforeRoot() {
return __async(this, null, function* () {
var _a;
const json = this.parser.json;
const v0VRMExtension = (_a = json.extensions) == null ? void 0 : _a["VRM"];
const v0MaterialProperties = v0VRMExtension == null ? void 0 : v0VRMExtension.materialProperties;
if (!v0MaterialProperties) {
return;
}
this._populateRenderQueueMap(v0MaterialProperties);
v0MaterialProperties.forEach((materialProperties, materialIndex) => {
var _a2, _b;
const materialDef = (_a2 = json.materials) == null ? void 0 : _a2[materialIndex];
if (materialDef == null) {
console.warn(
`VRMMaterialsV0CompatPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
);
return;
}
if (materialProperties.shader === "VRM/MToon") {
const material = this._parseV0MToonProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if ((_b = materialProperties.shader) == null ? void 0 : _b.startsWith("VRM/Unlit")) {
const material = this._parseV0UnlitProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if (materialProperties.shader === "VRM_USE_GLTFSHADER") {
} else {
console.warn(`VRMMaterialsV0CompatPlugin: Unknown shader: ${materialProperties.shader}`);
}
});
});
}
_parseV0MToonProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa;
const isTransparent = (_b = (_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != null ? _b : false;
const enabledZWrite = ((_c = materialProperties.floatProperties) == null ? void 0 : _c["_ZWrite"]) === 1;
const transparentWithZWrite = enabledZWrite && isTransparent;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = (_e = (_d = materialProperties.keywordMap) == null ? void 0 : _d["_ALPHATEST_ON"]) != null ? _e : false;
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_g = (_f = materialProperties.floatProperties) == null ? void 0 : _f["_Cutoff"]) != null ? _g : 0.5 : void 0;
const cullMode = (_i = (_h = materialProperties.floatProperties) == null ? void 0 : _h["_CullMode"]) != null ? _i : 2;
const doubleSided = cullMode === 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_k = (_j = materialProperties.vectorProperties) == null ? void 0 : _j["_Color"]) != null ? _k : [1, 1, 1, 1]).map(
(v, i) => i === 3 ? v : gammaEOTF(v)
// alpha channel is stored in linear
);
const baseColorTextureIndex = (_l = materialProperties.textureProperties) == null ? void 0 : _l["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const normalTextureScale = (_n = (_m = materialProperties.floatProperties) == null ? void 0 : _m["_BumpScale"]) != null ? _n : 1;
const normalTextureIndex = (_o = materialProperties.textureProperties) == null ? void 0 : _o["_BumpMap"];
const normalTexture = normalTextureIndex != null ? {
index: normalTextureIndex,
scale: normalTextureScale,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const emissiveFactor = ((_q = (_p = materialProperties.vectorProperties) == null ? void 0 : _p["_EmissionColor"]) != null ? _q : [0, 0, 0, 1]).map(
gammaEOTF
);
const emissiveTextureIndex = (_r = materialProperties.textureProperties) == null ? void 0 : _r["_EmissionMap"];
const emissiveTexture = emissiveTextureIndex != null ? {
index: emissiveTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const shadeColorFactor = ((_t = (_s = materialProperties.vectorProperties) == null ? void 0 : _s["_ShadeColor"]) != null ? _t : [0.97, 0.81, 0.86, 1]).map(
gammaEOTF
);
const shadeMultiplyTextureIndex = (_u = materialProperties.textureProperties) == null ? void 0 : _u["_ShadeTexture"];
const shadeMultiplyTexture = shadeMultiplyTextureIndex != null ? {
index: shadeMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
let shadingShiftFactor = (_w = (_v = materialProperties.floatProperties) == null ? void 0 : _v["_ShadeShift"]) != null ? _w : 0;
let shadingToonyFactor = (_y = (_x = materialProperties.floatProperties) == null ? void 0 : _x["_ShadeToony"]) != null ? _y : 0.9;
shadingToonyFactor = THREE.MathUtils.lerp(shadingToonyFactor, 1, 0.5 + 0.5 * shadingShiftFactor);
shadingShiftFactor = -shadingShiftFactor - (1 - shadingToonyFactor);
const giIntensityFactor = (_A = (_z = materialProperties.floatProperties) == null ? void 0 : _z["_IndirectLightIntensity"]) != null ? _A : 0.1;
const giEqualizationFactor = giIntensityFactor ? 1 - giIntensityFactor : void 0;
const matcapTextureIndex = (_B = materialProperties.textureProperties) == null ? void 0 : _B["_SphereAdd"];
const matcapFactor = matcapTextureIndex != null ? [1, 1, 1] : void 0;
const matcapTexture = matcapTextureIndex != null ? {
index: matcapTextureIndex
} : void 0;
const rimLightingMixFactor = (_D = (_C = materialProperties.floatProperties) == null ? void 0 : _C["_RimLightingMix"]) != null ? _D : 0;
const rimMultiplyTextureIndex = (_E = materialProperties.textureProperties) == null ? void 0 : _E["_RimTexture"];
const rimMultiplyTexture = rimMultiplyTextureIndex != null ? {
index: rimMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const parametricRimColorFactor = ((_G = (_F = materialProperties.vectorProperties) == null ? void 0 : _F["_RimColor"]) != null ? _G : [0, 0, 0, 1]).map(
gammaEOTF
);
const parametricRimFresnelPowerFactor = (_I = (_H = materialProperties.floatProperties) == null ? void 0 : _H["_RimFresnelPower"]) != null ? _I : 1;
const parametricRimLiftFactor = (_K = (_J = materialProperties.floatProperties) == null ? void 0 : _J["_RimLift"]) != null ? _K : 0;
const outlineWidthMode = ["none", "worldCoordinates", "screenCoordinates"][(_M = (_L = materialProperties.floatProperties) == null ? void 0 : _L["_OutlineWidthMode"]) != null ? _M : 0];
let outlineWidthFactor = (_O = (_N = materialProperties.floatProperties) == null ? void 0 : _N["_OutlineWidth"]) != null ? _O : 0;
outlineWidthFactor = 0.01 * outlineWidthFactor;
const outlineWidthMultiplyTextureIndex = (_P = materialProperties.textureProperties) == null ? void 0 : _P["_OutlineWidthTexture"];
const outlineWidthMultiplyTexture = outlineWidthMultiplyTextureIndex != null ? {
index: outlineWidthMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const outlineColorFactor = ((_R = (_Q = materialProperties.vectorProperties) == null ? void 0 : _Q["_OutlineColor"]) != null ? _R : [0, 0, 0]).map(
gammaEOTF
);
const outlineColorMode = (_T = (_S = materialProperties.floatProperties) == null ? void 0 : _S["_OutlineColorMode"]) != null ? _T : 0;
const outlineLightingMixFactor = outlineColorMode === 1 ? (_V = (_U = materialProperties.floatProperties) == null ? void 0 : _U["_OutlineLightingMix"]) != null ? _V : 1 : 0;
const uvAnimationMaskTextureIndex = (_W = materialProperties.textureProperties) == null ? void 0 : _W["_UvAnimMaskTexture"];
const uvAnimationMaskTexture = uvAnimationMaskTextureIndex != null ? {
index: uvAnimationMaskTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const uvAnimationScrollXSpeedFactor = (_Y = (_X = materialProperties.floatProperties) == null ? void 0 : _X["_UvAnimScrollX"]) != null ? _Y : 0;
let uvAnimationScrollYSpeedFactor = (__ = (_Z = materialProperties.floatProperties) == null ? void 0 : _Z["_UvAnimScrollY"]) != null ? __ : 0;
if (uvAnimationScrollYSpeedFactor != null) {
uvAnimationScrollYSpeedFactor = -uvAnimationScrollYSpeedFactor;
}
const uvAnimationRotationSpeedFactor = (_aa = (_$ = materialProperties.floatProperties) == null ? void 0 : _$["_UvAnimRotation"]) != null ? _aa : 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite,
renderQueueOffsetNumber,
shadeColorFactor,
shadeMultiplyTexture,
shadingShiftFactor,
shadingToonyFactor,
giEqualizationFactor,
matcapFactor,
matcapTexture,
rimLightingMixFactor,
rimMultiplyTexture,
parametricRimColorFactor,
parametricRimFresnelPowerFactor,
parametricRimLiftFactor,
outlineWidthMode,
outlineWidthFactor,
outlineWidthMultiplyTexture,
outlineColorFactor,
outlineLightingMixFactor,
uvAnimationMaskTexture,
uvAnimationScrollXSpeedFactor,
uvAnimationScrollYSpeedFactor,
uvAnimationRotationSpeedFactor
};
return __spreadProps(__spreadValues({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
normalTexture,
emissiveTexture,
emissiveFactor,
alphaMode,
alphaCutoff,
doubleSided,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
_parseV0UnlitProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = materialProperties.shader === "VRM/UnlitCutout";
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_b = (_a = materialProperties.floatProperties) == null ? void 0 : _a["_Cutoff"]) != null ? _b : 0.5 : void 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_d = (_c = materialProperties.vectorProperties) == null ? void 0 : _c["_Color"]) != null ? _d : [1, 1, 1, 1]).map(gammaEOTF);
const baseColorTextureIndex = (_e = materialProperties.textureProperties) == null ? void 0 : _e["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite: isTransparentZWrite,
renderQueueOffsetNumber,
shadeColorFactor: baseColorFactor,
shadeMultiplyTexture: baseColorTexture
};
return __spreadProps(__spreadValues({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
alphaMode,
alphaCutoff,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
/**
* Create a glTF `KHR_texture_transform` extension from v0 texture transform info.
*/
_portTextureTransform(materialProperties) {
var _a, _b, _c, _d, _e;
const textureTransform = (_a = materialProperties.vectorProperties) == null ? void 0 : _a["_MainTex"];
if (textureTransform == null) {
return {};
}
const offset = [(_b = textureTransform == null ? void 0 : textureTransform[0]) != null ? _b : 0, (_c = textureTransform == null ? void 0 : textureTransform[1]) != null ? _c : 0];
const scale = [(_d = textureTransform == null ? void 0 : textureTransform[2]) != null ? _d : 1, (_e = textureTransform == null ? void 0 : textureTransform[3]) != null ? _e : 1];
offset[1] = 1 - scale[1] - offset[1];
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
KHR_texture_transform: { offset, scale }
};
}
/**
* Convert v0 render order into v1 render order.
* This uses a map from v0 render queue to v1 compliant render queue offset which is generated in {@link _populateRenderQueueMap}.
*/
_v0ParseRenderQueue(materialProperties) {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
let offset = 0;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
offset = this._renderQueueMapTransparentZWrite.get(v0Queue);
} else {
offset = this._renderQueueMapTransparent.get(v0Queue);
}
}
}
return offset;
}
/**
* Create a map which maps v0 render queue to v1 compliant render queue offset.
* This lists up all render queues the model use and creates a map to new render queue offsets in the same order.
*/
_populateRenderQueueMap(materialPropertiesList) {
const renderQueuesTransparent = /* @__PURE__ */ new Set();
const renderQueuesTransparentZWrite = /* @__PURE__ */ new Set();
materialPropertiesList.forEach((materialProperties) => {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
renderQueuesTransparentZWrite.add(v0Queue);
} else {
renderQueuesTransparent.add(v0Queue);
}
}
}
});
if (renderQueuesTransparent.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparent.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
if (renderQueuesTransparentZWrite.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparentZWrite.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
Array.from(renderQueuesTransparent).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i - renderQueuesTransparent.size + 1, -9), 0);
this._renderQueueMapTransparent.set(queue, newQueueOffset);
});
Array.from(renderQueuesTransparentZWrite).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i, 0), 9);
this._renderQueueMapTransparentZWrite.set(queue, newQueueOffset);
});
}
};
export {
VRMMaterialsV0CompatPlugin
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL1ZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luLnRzIiwgIi4uL3NyYy91dGlscy9nYW1tYUVPVEYudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IFZSTSBhcyBWMFZSTSwgTWF0ZXJpYWwgYXMgVjBNYXRlcmlhbCB9IGZyb20gJ0BwaXhpdi90eXBlcy12cm0tMC4wJztcbmltcG9ydCAqIGFzIFYxTVRvb25TY2hlbWEgZnJvbSAnQHBpeGl2L3R5cGVzLXZybWMtbWF0ZXJpYWxzLW10b29uLTEuMCc7XG5pbXBvcnQgdHlwZSB7IEdMVEZMb2FkZXJQbHVnaW4sIEdMVEZQYXJzZXIgfSBmcm9tICd0aHJlZS9leGFtcGxlcy9qc20vbG9hZGVycy9HTFRGTG9hZGVyLmpzJztcbmltcG9ydCB7IGdhbW1hRU9URiB9IGZyb20gJy4vdXRpbHMvZ2FtbWFFT1RGJztcbmltcG9ydCB7IEdMVEYgYXMgR0xURlNjaGVtYSB9IGZyb20gJ0BnbHRmLXRyYW5zZm9ybS9jb3JlJztcblxuZXhwb3J0IGNsYXNzIFZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luIGltcGxlbWVudHMgR0xURkxvYWRlclBsdWdpbiB7XG4gIHB1YmxpYyByZWFkb25seSBwYXJzZXI6IEdMVEZQYXJzZXI7XG5cbiAgLyoqXG4gICAqIEEgbWFwIGZyb20gdjAgcmVuZGVyIHF1ZXVlIHRvIHYxIHJlbmRlciBxdWV1ZSBvZmZzZXQsIGZvciBUcmFuc3BhcmVudCBtYXRlcmlhbHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJRdWV1ZU1hcFRyYW5zcGFyZW50OiBNYXA8bnVtYmVyLCBudW1iZXI+O1xuXG4gIC8qKlxuICAgKiBBIG1hcCBmcm9tIHYwIHJlbmRlciBxdWV1ZSB0byB2MSByZW5kZXIgcXVldWUgb2Zmc2V0LCBmb3IgVHJhbnNwYXJlbnRaV3JpdGUgbWF0ZXJpYWxzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfcmVuZGVyUXVldWVNYXBUcmFuc3BhcmVudFpXcml0ZTogTWFwPG51bWJlciwgbnVtYmVyPjtcblxuICBwdWJsaWMgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ1ZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luJztcbiAgfVxuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJzZXI6IEdMVEZQYXJzZXIpIHtcbiAgICB0aGlzLnBhcnNlciA9IHBhcnNlcjtcblxuICAgIHRoaXMuX3JlbmRlclF1ZXVlTWFwVHJhbnNwYXJlbnQgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5fcmVuZGVyUXVldWVNYXBUcmFuc3BhcmVudFpXcml0ZSA9IG5ldyBNYXAoKTtcblxuICAgIC8vIFdPUktBUk9VTkQ6IEFkZCBLSFJfdGV4dHVyZV90cmFuc2Zvcm0gdG8gZXh0ZW5zaW9uc1VzZWRcbiAgICAvLyBJdCBpcyB0b28gbGF0ZSB0byBhZGQgdGhpcyBpbiBiZWZvcmVSb290XG4gICAgY29uc3QganNvbiA9IHRoaXMucGFyc2VyLmpzb24gYXMgR0xURlNjaGVtYS5JR0xURjtcblxuICAgIGpzb24uZXh0ZW5zaW9uc1VzZWQgPSBqc29uLmV4dGVuc2lvbnNVc2VkID8/IFtdO1xuICAgIGlmIChqc29uLmV4dGVuc2lvbnNVc2VkLmluZGV4T2YoJ0tIUl90ZXh0dXJlX3RyYW5zZm9ybScpID09PSAtMSkge1xuICAgICAganNvbi5leHRlbnNpb25zVXNlZC5wdXNoKCdLSFJfdGV4dHVyZV90cmFuc2Zvcm0nKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYmVmb3JlUm9vdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBqc29uID0gdGhpcy5wYXJzZXIuanNvbiBhcyBHTFRGU2NoZW1hLklHTFRGO1xuXG4gICAgLy8gZWFybHkgYWJvcnQgaWYgaXQgZG9lc24ndCB1c2UgVjBWUk1cbiAgICBjb25zdCB2MFZSTUV4dGVuc2lvbiA9IGpzb24uZXh0ZW5zaW9ucz8uWydWUk0nXSBhcyBWMFZSTSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCB2ME1hdGVyaWFsUHJvcGVydGllcyA9IHYwVlJNRXh0ZW5zaW9uPy5tYXRlcmlhbFByb3BlcnRpZXM7XG4gICAgaWYgKCF2ME1hdGVyaWFsUHJvcGVydGllcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIHBvcHVsYXRlIHJlbmRlciBxdWV1ZSBtYXBcbiAgICB0aGlzLl9wb3B1bGF0ZVJlbmRlclF1ZXVlTWFwKHYwTWF0ZXJpYWxQcm9wZXJ0aWVzKTtcblxuICAgIC8vIGNvbnZlcnQgVjAgbWF0ZXJpYWwgcHJvcGVydGllcyBpbnRvIFYxIGNvbXBhdGlibGUgZm9ybWF0XG4gICAgdjBNYXRlcmlhbFByb3BlcnRpZXMuZm9yRWFjaCgobWF0ZXJpYWxQcm9wZXJ0aWVzLCBtYXRlcmlhbEluZGV4KSA9PiB7XG4gICAgICBjb25zdCBtYXRlcmlhbERlZiA9IGpzb24ubWF0ZXJpYWxzPy5bbWF0ZXJpYWxJbmRleF07XG5cbiAgICAgIGlmIChtYXRlcmlhbERlZiA9PSBudWxsKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgVlJNTWF0ZXJpYWxzVjBDb21wYXRQbHVnaW46IEF0dGVtcHQgdG8gdXNlIG1hdGVyaWFsc1ske21hdGVyaWFsSW5kZXh9XSBvZiBnbFRGIGJ1dCB0aGUgbWF0ZXJpYWwgZG9lc24ndCBleGlzdGAsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXIgPT09ICdWUk0vTVRvb24nKSB7XG4gICAgICAgIGNvbnN0IG1hdGVyaWFsID0gdGhpcy5fcGFyc2VWME1Ub29uUHJvcGVydGllcyhtYXRlcmlhbFByb3BlcnRpZXMsIG1hdGVyaWFsRGVmKTtcbiAgICAgICAganNvbi5tYXRlcmlhbHMhW21hdGVyaWFsSW5kZXhdID0gbWF0ZXJpYWw7XG4gICAgICB9IGVsc2UgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXI/LnN0YXJ0c1dpdGgoJ1ZSTS9VbmxpdCcpKSB7XG4gICAgICAgIGNvbnN0IG1hdGVyaWFsID0gdGhpcy5fcGFyc2VWMFVubGl0UHJvcGVydGllcyhtYXRlcmlhbFByb3BlcnRpZXMsIG1hdGVyaWFsRGVmKTtcbiAgICAgICAganNvbi5tYXRlcmlhbHMhW21hdGVyaWFsSW5kZXhdID0gbWF0ZXJpYWw7XG4gICAgICB9IGVsc2UgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXIgPT09ICdWUk1fVVNFX0dMVEZTSEFERVInKSB7XG4gICAgICAgIC8vIGBqc29uLm1hdGVyaWFsc1ttYXRlcmlhbEluZGV4XWAgc2hvdWxkIGJlIGFscmVhZHkgdmFsaWRcbiAgICAgI