super-hero/extensions/shader-graph/dist/importer/shader-graph.js

234 lines
32 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ShaderGraph = void 0;
const path_1 = require("path");
const js_yaml_1 = require("js-yaml");
const fs_extra_1 = require("fs-extra");
module.paths.push((0, path_1.join)(Editor.App.path, 'node_modules'));
const { Asset } = require('@editor/asset-db');
const block_forge_1 = require("../block-forge");
const shader_graph_1 = require("../shader-graph");
const utils_3_8_1 = require("./utils-3.8");
const VectorDataType = [
'float',
'vec2',
'vec3',
'vec4',
'color',
'enum',
'boolean',
];
class ShaderGraph {
constructor() {
this.shaderNodeClassMap = new Map;
/**
* 用于存储每个 asset 对应的 source
* 导入前先换成,把 source 替换成 temp 路径下的 effect
* 导入后在替换成原本的 source
*/
this.cacheSourceMap = new Map();
this._initedGraph = false;
}
get assetType() {
return 'cc.EffectAsset';
}
get version() {
return '1.0.0';
}
get name() {
return 'shader-graph';
}
get migrations() {
return [];
}
async initGraph() {
if (this._initedGraph && this.shaderContext?.shaderTemplatesDir) {
return;
}
await Editor.Module.importProjectModule('db://shader-graph/operation/index.ts');
const { ShaderProperty } = await Editor.Module.importProjectModule('db://shader-graph/operation/property.ts');
this.ShaderProperty = ShaderProperty;
const { shaderNodeMap, shaderPropertyMap, shaderNodeClassMap } = await Editor.Module.importProjectModule('db://shader-graph/graph/index.ts');
const { shaderContext } = await Editor.Module.importProjectModule('db://shader-graph/operation/context.ts');
(0, shader_graph_1.declareShaderNodeBlock)(shaderNodeMap);
this.shaderNodeClassMap = shaderNodeClassMap;
this.shaderContext = shaderContext;
shaderContext.shaderTemplatesDir = await Editor.Message.request('asset-db', 'query-path', 'db://shader-graph/../compile-shader/shader-templates');
// shaderContext.shaderTemplatesDir = queryPath('db://shader-graph/../compile-shader/shader-templates');
this._initedGraph = true;
}
createShaderNodes(blockMap) {
const shaderNodeClassMap = this.shaderNodeClassMap;
const shaderContext = this.shaderContext;
for (const uuid in blockMap) {
const block = blockMap[uuid];
if (!block.desc)
continue;
const type = block.desc.type;
let shaderNode = block.shaderNode;
if (!shaderNode) {
const cls = shaderNodeClassMap.get(type);
if (!cls) {
console.error(`Can not find type for ${type}`);
}
shaderNode = new cls();
shaderNode.init();
shaderNode.block = block;
if (!shaderContext.allNodes.includes(shaderNode)) {
shaderContext.allNodes.push(shaderNode);
}
if (type === 'RegisterLocalVar') {
if (!shaderContext.localVars.includes(shaderNode)) {
shaderNode.name = block.getInputPinsList()[1].value.value;
shaderContext.localVars.push(shaderNode);
}
}
if (type === 'GetLocalVar') {
if (!shaderContext.getLocalVars.includes(shaderNode)) {
shaderNode.name = block.getInputPinsList()[0].value.value;
shaderContext.getLocalVars.push(shaderNode);
}
}
if (type === 'PropertyNode') {
shaderNode.name = block.block.details.title;
}
const inputPins = block.getInputPinsList();
for (let i = 0; i < inputPins.length; i++) {
const pin = inputPins[i];
const value = pin.value;
const input = shaderNode.inputs[i];
let slot = shaderNode.getSlotWithSlotName(pin.desc.name);
if (!slot) {
slot = shaderNode.getPropWithName(pin.desc.name);
}
if (VectorDataType.includes(value.dataType)) {
if (slot) {
if (typeof value.value === 'number' || typeof value.value === 'boolean') {
slot.value = value.value;
}
else if (value.dataType === 'color') {
// srgb to linear
slot.value.set(value.value.x * value.value.x, value.value.y * value.value.y, value.value.z * value.value.z, value.value.w);
}
else if (value.dataType === 'enum') {
slot.value = value.value;
}
else if (value.dataType === 'dynamicEnum') {
// TODO
}
else {
slot.value.set(value.value);
}
}
}
}
block.shaderNode = shaderNode;
}
}
}
searchInputs(block) {
const shaderNode = block.shaderNode;
const inputList = block.getInputPinsList();
for (let i = 0; i < inputList.length; i++) {
const pin = inputList[i];
if (!shaderNode.inputs[i]) {
continue;
}
const connectPin = pin.connectPins[0];
if (connectPin) {
const connectBlock = connectPin.block;
const connectShaderNode = connectBlock.shaderNode;
const connectOutIdx = connectPin.block.getOutputPinsList().indexOf(connectPin);
const connectSlot = connectShaderNode.outputs[connectOutIdx];
shaderNode.inputs[i].connectSlots[0] = connectSlot;
connectSlot.connectSlots.push(shaderNode.inputs[i]);
this.searchInputs(connectBlock);
}
else {
shaderNode.inputs[i].connectSlots.length = 0;
}
}
}
async generateMasterNode(graphData) {
await this.initGraph();
const forge = new block_forge_1.Forge(graphData);
const graph = forge.getGraph();
this.shaderContext.reset();
// TODO 这里还需要处理子图的 properties
const properties = graph.details.properties;
if (properties) {
properties.forEach((v) => {
const prop = new this.ShaderProperty(v.type);
prop.name = v.name;
prop.setValue(v.outputPins[0].value);
this.shaderContext.properties.push(prop);
});
}
const blockMap = graph.getBlockMap();
await this.createShaderNodes(blockMap);
let masterBlock;
for (const uuid in blockMap) {
const block = blockMap[uuid];
if (!block.desc)
continue;
const type = block.desc.type;
if (type.includes('MasterNode')) {
masterBlock = block;
}
}
if (!masterBlock) {
throw new Error('Can not find MasterBlock');
}
for (let i = 0; i < this.shaderContext.localVars.length; i++) {
const locVar = this.shaderContext.localVars[i];
await this.searchInputs(locVar.block);
}
await this.searchInputs(masterBlock);
const masterNode = masterBlock.shaderNode;
return masterNode;
}
async generateEffectByGraphData(graphData) {
const masterNode = await this.generateMasterNode(graphData);
return masterNode.generateCode();
}
// @ts-expect-error
async generateEffectByAsset(asset) {
const serializeYAML = await (0, fs_extra_1.readFile)(asset.source, 'utf8');
const graphData = (0, js_yaml_1.load)(serializeYAML);
const code = await this.generateEffectByGraphData(graphData);
(0, fs_extra_1.ensureDirSync)(this.tempEffectCodeDir);
await (0, fs_extra_1.writeFile)(this.getTempEffectCodePath(asset), code);
return code;
}
// @ts-expect-error
existsCacheEffect(asset) {
return (0, fs_extra_1.existsSync)(this.getTempEffectCodePath(asset));
}
/**
* 获取存储 effect code 文件夹
*/
// @ts-expect-error
getTempEffectCodePath(asset) {
return (0, path_1.join)(this.tempEffectCodeDir, `${asset.uuid}.effect`);
}
/**
* 获取存储 effect code 路径
*/
get tempEffectCodeDir() {
return (0, path_1.join)(Editor.Project.tmpDir, `shader-graph`);
}
/**
* 返回是否导入成功的标记
* 如果返回 false则 imported 标记不会变成 true
* 后续的一系列操作都不会执行
* @param asset
*/
// @ts-expect-error
async import(asset) {
await (0, utils_3_8_1.generateEffectAsset)(asset, await this.generateEffectByAsset(asset));
return true;
}
}
exports.ShaderGraph = ShaderGraph;
exports.default = new ShaderGraph();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhZGVyLWdyYXBoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ltcG9ydGVyL3NoYWRlci1ncmFwaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBNEI7QUFDNUIscUNBQStCO0FBQy9CLHVDQUEwRTtBQUUxRSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFBLFdBQUksRUFBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0FBRXpELE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUU5QyxnREFBOEM7QUFFOUMsa0RBQXlFO0FBQ3pFLDJDQUFrRDtBQUVsRCxNQUFNLGNBQWMsR0FBRztJQUNuQixPQUFPO0lBQ1AsTUFBTTtJQUNOLE1BQU07SUFDTixNQUFNO0lBQ04sT0FBTztJQUNQLE1BQU07SUFDTixTQUFTO0NBQ1osQ0FBQztBQUVGLE1BQWEsV0FBVztJQUF4QjtRQWtCSSx1QkFBa0IsR0FBcUIsSUFBSSxHQUFHLENBQUM7UUFJL0M7Ozs7V0FJRztRQUNJLG1CQUFjLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUM7UUFFdkQsaUJBQVksR0FBRyxLQUFLLENBQUM7SUF3T3pCLENBQUM7SUFuUUcsSUFBSSxTQUFTO1FBQ1QsT0FBTyxnQkFBZ0IsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBSSxPQUFPO1FBQ1AsT0FBTyxPQUFPLENBQUM7SUFDbkIsQ0FBQztJQUVELElBQUksSUFBSTtRQUNKLE9BQU8sY0FBYyxDQUFDO0lBQzFCLENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDVixPQUFPLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFjRCxLQUFLLENBQUMsU0FBUztRQUNYLElBQUksSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLGtCQUFrQixFQUFFO1lBQzdELE9BQU87U0FDVjtRQUVE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SSxFQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLFNBQVMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsaUJBQWlCO1FBQ3hCLE9BQU8sSUFBQSxXQUFJLEVBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsbUJBQW1CO0lBQ1osS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFZO1FBQzVCLE1BQU0sSUFBQSwrQkFBbUIsRUFBQyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUMxRSxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0NBQ0o7QUFyUUQsa0NBcVFDO0FBRUQsa0JBQWUsSUFBSSxXQUFXLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpvaW4gfSBmcm9tICdwYXRoJztcbmltcG9ydCB7IGxvYWQgfSBmcm9tICdqcy15YW1sJztcbmltcG9ydCB7IGVuc3VyZURpclN5bmMsIHJlYWRGaWxlLCB3cml0ZUZpbGUsIGV4aXN0c1N5bmMgfSBmcm9tICdmcy1leHRyYSc7XG5cbm1vZHVsZS5wYXRocy5wdXNoKGpvaW4oRWRpdG9yLkFwcC5wYXRoLCAnbm9kZV9tb2R1bGVzJykpO1xuXG5jb25zdCB7IEFzc2V0IH0gPSByZXF1aXJlKCdAZWRpdG9yL2Fzc2V0LWRiJyk7XG5cbmltcG9ydCB7IEJsb2NrLCBGb3JnZSB9IGZyb20gJy4uL2Jsb2NrLWZvcmdlJztcbmltcG9ydCB7IEdyYXBoRGF0YSB9IGZyb20gJy4uL2Jsb2NrLWZvcmdlL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBJTW9kdWxlT3B0aW9ucywgZGVjbGFyZVNoYWRlck5vZGVCbG9jayB9IGZyb20gJy4uL3NoYWRlci1ncmFwaCc7XG5pbXBvcnQgeyBnZW5lcmF0ZUVmZmVjdEFzc2V0IH0gZnJvbSAnLi91dGlscy0zLjgnO1xuXG5jb25zdCBWZWN0b3JEYXRhVHlwZSA9IFtcbiAgICAnZmxvYXQnLFxuICAgICd2ZWMyJyxcbiAgICAndmVjMycsXG4gICAgJ3ZlYzQnLFxuICAgICdjb2xvcicsXG4gICAgJ2VudW0nLFxuICAgICdib29sZWFuJyxcbl07XG5cbmV4cG9ydCBjbGFzcyBTaGFkZXJHcmFwaCB7XG5cbiAgICBnZXQgYXNzZXRUeXBlKCkge1xuICAgICAgICByZXR1cm4gJ2NjLkVmZmVjdEFzc2V0JztcbiAgICB9XG5cbiAgICBnZXQgdmVyc2lvbigpIHtcbiAgICAgICAgcmV0dXJuICcxLjAuMCc7XG4gICAgfVxuXG4gICAgZ2V0IG5hbWUoKSB7XG4gICAgICAgIHJldHVybiAnc2hhZGVyLWdyYXBoJztcbiAgICB9XG5cbiAgICBnZXQgbWlncmF0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHNoYWRlck5vZGVDbGFzc01hcDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXA7XG4gICAgc2hhZGVyQ29udGV4dDogYW55O1xuICAgIFNoYWRlclByb3BlcnR5OiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiDnlKjkuo7lrZjlgqjmr4/kuKogYXNzZXQg5a+55bqU55qEIHNvdXJjZVxuICAgICAqIOWvvOWFpeWJjeWFiOaNouaIkO+8jOaKiiBzb3VyY2Ug5pu/5o2i5oiQIHRlbXAg6Lev5b6E5LiL55qEIGVmZmVjdFxuICAgICAqIOWvvOWFpeWQjuWcqOabv+aNouaIkOWOn+acrOeahCBzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMgY2FjaGVTb3VyY2VNYXA6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XG5cbiAgICBfaW5pdGVkR3JhcGggPSBmYWxzZTtcbiAgICBhc3luYyBpbml0R3JhcGgoKSB7XG4gICAgICAgIGlmICh0aGlzLl9pbml0ZWRHcmFwaCAmJiB0aGlzLnNoYWRlckNvbnRleHQ/LnNoYWRlclRlbXBsYXRlc0Rpcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgRWRpdG9yLk1vZHVsZS5pbXBvcnRQcm9qZWN0TW9kdWxlKCdkYjovL3NoYWRlci1ncmFwaC9vcGVyYXRpb24vaW5kZXgudHMnKTtcblxuICAgICAgICBjb25zdCB7IFNoYWRlclByb3BlcnR5IH0gPSBhd2FpdCBFZGl0b3IuTW9kdWxlLmltcG9ydFByb2plY3RNb2R1bGUoJ2RiOi8vc2hhZGVyLWdyYXBoL29wZXJhdGlvbi9wcm9wZXJ0eS50cycpIGFzIGFueTtcbiAgICAgICAgdGhpcy5TaGFkZXJQcm9wZXJ0eSA9IFNoYWRlclByb3BlcnR5O1xuXG4gICAgICAgIGNvbnN0IHsgc2hhZGVyTm9kZU1hcCwgc2hhZGVyUHJvcGVydHlNYXAsIHNoYWRlck5vZGVDbGFzc01hcCB9ID0gYXdhaXQgRWRpdG9yLk1vZHVsZS5pbXBvcnRQcm9qZWN0TW9kdWxlKCdkYjovL3NoYWRlci1ncmFwaC9ncmFwaC9pbmRleC50cycpIGFzIElNb2R1bGVPcHRpb25zO1xuXG4gICAgICAgIGNvbnN0IHsgc2hhZGVyQ29udGV4dCB9ID0gYXdhaXQgRWRpdG9yLk1vZHVsZS5pbXBvcnRQcm9qZWN0TW9kdWxlKCdkYjovL3NoYWRlci1ncmFwaC9vcGVyYXRpb24vY29udGV4dC50cycpIGFzIGFueTtcbiAgICAgICAgZGVjbGFyZVNoYWRlck5vZGVCbG9jayhzaGFkZXJOb2RlTWFwKTtcblxuICAgICAgICB0aGlzLnNoYWRlck5vZGVDbGFzc01hcCA9IHNoYWRlck5vZGVDbGFzc01hcDtcbiAgICAgICAgdGhpcy5zaGFkZXJDb250ZXh0ID0gc2hhZGVyQ29udGV4dDtcblxuICAgICAgICBzaGFkZXJDb250ZXh0LnNoYWRlclRlbXBsYXRlc0RpciA9IGF3YWl0IEVkaXRvci5NZXNzYWdlLnJlcXVlc3QoJ2Fzc2V0LWRiJywgJ3F1ZXJ5LXBhdGgnLCAnZGI6Ly9zaGFkZXItZ3JhcGgvLi4vY29tcGlsZS1zaGFkZXIvc2hhZGVyLXRlbXBsYXRlcycpIGFzIHN0cmluZztcbiAgICAgICAgLy8gc2hhZGVyQ29udGV4dC5zaGFkZXJUZW1wbGF0ZXNEaXIgPSBxdWVyeVBhdGgoJ2RiOi8vc2hhZGVyLWdyYXBoLy4uL2NvbXBpbGUtc2hhZGVyL3NoYWRlci10ZW1wbGF0ZXMnKTtcbiAgICAgICAgdGhpcy5faW5pdGVkR3JhcGggPSB0cnVlO1xuICAgIH1cblxuICAgIGNyZWF0ZVNoYWRlck5vZGVzKGJsb2NrTWFwOiB7XG4gICAgICAgIFt1dWlkOiBzdHJpbmddOiBCbG9jaztcbiAgICB9KSB7XG4gICAgICAgIGNvbnN0IHNoYWRlck5vZGVDbGFzc01hcCA9IHRoaXMuc2hhZGVyTm9kZUNsYXNzTWFwO1xuICAgICAgICBjb25zdCBzaGFkZXJDb250ZXh0ID0gdGhpcy5zaGFkZXJDb250ZXh0O1xuXG4gICAgICAgIGZvciAoY29uc3QgdXVpZCBpbiBibG9ja01hcCkge1xuICAgICAgICAgICAgY29uc3QgYmxvY2sgPSBibG9ja01hcFt1dWlkXTtcbiAgICAgICAgICAgIGlmICghYmxvY2suZGVzYykgY29udGludWU7XG4gICAgICAgICAgICBjb25zdCB0eXBlID0gYmxvY2suZGVzYy50eXBlO1xuXG4gICAgICAgICAgICBsZXQgc2hhZGVyTm9kZSA9IChibG9jayBhcyBhbnkpLnNoYWRlck5vZGU7XG4gICAgICAgICAgICBpZiAoIXNoYWRlck5vZGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbHMgPSBzaGFkZXJOb2RlQ2xhc3NNYXAuZ2V0KHR5cGUpO1xuICAgICAgICAgICAgICAgIGlmICghY2xzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYENhbiBub3QgZmluZCB0eXBlIGZvciAke3R5cGV9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNoYWRlck5vZGUgPSBuZXcgY2xzKCk7XG4gICAgICAgICAgICAgICAgc2hhZGVyTm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgc2hhZGVyTm9kZS5ibG9jayA9IGJsb2NrO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFzaGFkZXJDb250ZXh0LmFsbE5vZGVzLmluY2x1ZGVzKHNoYWRlck5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNoYWRlckNvbnRleHQuYWxsTm9kZXMucHVzaChzaGFkZXJOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdSZWdpc3RlckxvY2FsVmFyJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNoYWRlckNvbnRleHQubG9jYWxWYXJzLmluY2x1ZGVzKHNoYWRlck5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGFkZXJOb2RlLm5hbWUgPSBibG9jay5nZXRJbnB1dFBpbnNMaXN0KClbMV0udmFsdWUudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGFkZXJDb250ZXh0LmxvY2FsVmFycy5wdXNoKHNoYWRlck5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnR2V0TG9jYWxWYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2hhZGVyQ29udGV4dC5nZXRMb2NhbFZhcnMuaW5jbHVkZXMoc2hhZGVyTm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoYWRlck5vZGUubmFtZSA9IGJsb2NrLmdldElucHV0UGluc0xpc3QoKVswXS52YWx1ZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoYWRlckNvbnRleHQuZ2V0TG9jYWxWYXJzLnB1c2goc2hhZGVyTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdQcm9wZXJ0eU5vZGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNoYWRlck5vZGUubmFtZSA9IGJsb2NrLmJsb2NrLmRldGFpbHMudGl0bGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgaW5wdXRQaW5zID0gYmxvY2suZ2V0SW5wdXRQaW5zTGlzdCgpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFBpbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGluID0gaW5wdXRQaW5zW2ldO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBpbi52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBzaGFkZXJOb2RlLmlucHV0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgc2xvdCA9IHNoYWRlck5vZGUuZ2V0U2xvdFdpdGhTbG90TmFtZShwaW4uZGVzYy5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzbG90KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gc2hhZGVyTm9kZS5nZXRQcm9wV2l0aE5hbWUocGluLmRlc2MubmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoVmVjdG9yRGF0YVR5cGUuaW5jbHVkZXModmFsdWUuZGF0YVR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2xvdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUudmFsdWUgPT09ICdudW1iZXInIHx8IHR5cGVvZiB2YWx1ZS52YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QudmFsdWUgPSB2YWx1ZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUuZGF0YVR5cGUgPT09ICdjb2xvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3JnYiB0byBsaW5lYXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdC52YWx1ZS5zZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS52YWx1ZS54ICogdmFsdWUudmFsdWUueCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLnZhbHVlLnkgKiB2YWx1ZS52YWx1ZS55LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUudmFsdWUueiAqIHZhbHVlLnZhbHVlLnosXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS52YWx1ZS53LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh2YWx1ZS5kYXRhVHlwZSA9PT0gJ2VudW0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QudmFsdWUgPSB2YWx1ZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUuZGF0YVR5cGUgPT09ICdkeW5hbWljRW51bScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ET1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdC52YWx1ZS5zZXQodmFsdWUudmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIChibG9jayBhcyBhbnkpLnNoYWRlck5vZGUgPSBzaGFkZXJOb2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2VhcmNoSW5wdXRzKGJsb2NrOiBCbG9jaykge1xuICAgICAgICBjb25zdCBzaGFkZXJOb2RlID0gKGJsb2NrIGFzIGFueSkuc2hhZGVyTm9kZTtcbiAgICAgICAgY29uc3QgaW5wdXRMaXN0ID0gYmxvY2suZ2V0SW5wdXRQaW5zTGlzdCgpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgcGluID0gaW5wdXRMaXN0W2ldO1xuICAgICAgICAgICAgaWYgKCFzaGFkZXJOb2RlLmlucHV0c1tpXSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBjb25uZWN0UGluID0gcGluLmNvbm5lY3RQaW5zWzBdO1xuICAgICAgICAgICAgaWYgKGNvbm5lY3RQaW4pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0QmxvY2sgPSBjb25uZWN0UGluLmJsb2NrO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3RTaGFkZXJOb2RlID0gKGNvbm5lY3RCbG9jayBhcyBhbnkpLnNoYWRlck5vZGU7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdE91dElkeCA9IGNvbm5lY3RQaW4uYmxvY2suZ2V0T3V0cHV0UGluc0xpc3QoKS5pbmRleE9mKGNvbm5lY3RQaW4pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3RTbG90ID0gY29ubmVjdFNoYWRlck5vZGUub3V0cHV0c1tjb25uZWN0T3V0SWR4XTtcblxuICAgICAgICAgICAgICAgIHNoYWRlck5vZGUuaW5wdXRzW2ldLmNvbm5lY3RTbG90c1swXSA9IGNvbm5lY3RTbG90O1xuICAgICAgICAgICAgICAgIGNvbm5lY3RTbG90LmNvbm5lY3RTbG90cy5wdXNoKHNoYWRlck5vZGUuaW5wdXRzW2ldKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2VhcmNoSW5wdXRzKGNvbm5lY3RCbG9jayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJOb2RlLmlucHV0c1tpXS5jb25uZWN0U2xvdHMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZW5lcmF0ZU1hc3Rlck5vZGUoZ3JhcGhEYXRhOiBHcmFwaERhdGEpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbml0R3JhcGgoKTtcblxuICAgICAgICBjb25zdCBmb3JnZSA9IG5ldyBGb3JnZShncmFwaERhdGEpO1xuXG4gICAgICAgIGNvbnN0IGdyYXBoID0gZm9yZ2UuZ2V0R3JhcGgoKTtcblxuICAgICAgICB0aGlzLnNoYWRlckNvbnRleHQucmVzZXQoKTtcblxuICAgICAgICAvLyBUT0RPIOi/memHjOi/mOmcgOimgeWkhOeQhuWtkOWbvueahCBwcm9wZXJ0aWVzXG4gICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBncmFwaC5kZXRhaWxzLnByb3BlcnRpZXM7XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzLmZvckVhY2goKHY6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHByb3AgPSBuZXcgdGhpcy5TaGFkZXJQcm9wZXJ0eSh2LnR5cGUpO1xuICAgICAgICAgICAgICAgIHByb3AubmFtZSA9IHYubmFtZTtcbiAgICAgICAgICAgICAgICBwcm9wLnNldFZhbHVlKHYub3V0cHV0UGluc1swXS52YWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaGFkZXJDb250ZXh0LnByb3BlcnRpZXMucHVzaChwcm9wKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmxvY2tNYXAgPSBncmFwaC5nZXRCbG9ja01hcCgpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlU2hhZGVyTm9kZXMoYmxvY2tNYXApO1xuXG4gICAgICAgIGxldCBtYXN0ZXJCbG9jaztcbiAgICAgICAgZm9yIChjb25zdCB1dWlkIGluIGJsb2NrTWFwKSB7XG4gICAgICAgICAgICBjb25zdCBibG9jayA9IGJsb2NrTWFwW3V1aWRdO1xuICAgICAgICAgICAgaWYgKCFibG9jay5kZXNjKSBjb250aW51ZTtcbiAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBibG9jay5kZXNjLnR5cGU7XG4gICAgICAgICAgICBpZiAodHlwZS5pbmNsdWRlcygnTWFzdGVyTm9kZScpKSB7XG4gICAgICAgICAgICAgICAgbWFzdGVyQmxvY2sgPSBibG9jaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghbWFzdGVyQmxvY2spIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBmaW5kIE1hc3RlckJsb2NrJyk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2hhZGVyQ29udGV4dC5sb2NhbFZhcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGxvY1ZhciA9IHRoaXMuc2hhZGVyQ29udGV4dC5sb2NhbFZhcnNbaV07XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNlYXJjaElucHV0cyhsb2NWYXIuYmxvY2spO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuc2VhcmNoSW5wdXRzKG1hc3RlckJsb2NrKTtcblxuICAgICAgICBjb25zdCBtYXN0ZXJOb2RlID0gKG1hc3RlckJsb2NrIGFzIGFueSkuc2hhZGVyTm9kZTtcbiAgICAgICAgcmV0dXJuIG1hc3Rlck5vZGU7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdlbmVyYXRlRWZmZWN0QnlHcmFwaERhdGEoZ3JhcGhEYXRhOiBHcmFwaERhdGEpIHtcbiAgICAgICAgY29uc3QgbWFzdGVyTm9kZSA9IGF3YWl0IHRoaXMuZ2VuZXJhdGVNYXN0ZXJOb2RlKGdyYXBoRGF0YSk7XG4gICAgICAgIHJldHVybiBtYXN0ZXJOb2RlLmdlbmVyYXRlQ29kZSgpO1xuICAgIH1cblxuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICBwdWJsaWMgYXN5bmMgZ2VuZXJhdGVFZmZlY3RCeUFzc2V0KGFzc2V0OiBBc3NldCkge1xuICAgICAgICBjb25zdCBzZXJpYWxpemVZQU1MID0gYXdhaXQgcmVhZEZpbGUoYXNzZXQuc291cmNlLCAndXRmOCcpO1xuXG4gICAgICAgIGNvbnN0IGdyYXBoRGF0YSA9IGxvYWQoc2VyaWFsaXplWUFNTCkgYXMgR3JhcGhEYXRhO1xuXG4gICAgICAgIGNvbnN0IGNvZGUgPSBhd2FpdCB0aGlzLmdlbmVyYXRlRWZmZWN0QnlHcmFwaERhdGEoZ3JhcGhEYXRhKTtcblxuICAgICAgICBlbnN1cmVEaXJTeW5jKHRoaXMudGVtcEVmZmVjdENvZGVEaXIpO1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUodGhpcy5nZXRUZW1wRWZmZWN0Q29kZVBhdGgoYXNzZXQpLCBjb2RlKTtcbiAgICAgICAgcmV0dXJuIGNvZGU7XG4gICAgfVxuXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHB1YmxpYyBleGlzdHNDYWNoZUVmZmVjdChhc3NldDogQXNzZXQpIHtcbiAgICAgICAgcmV0dXJuIGV4aXN0c1N5bmModGhpcy5nZXRUZW1wRWZmZWN0Q29kZVBhdGgoYXNzZXQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDojrflj5blrZjlgqggZWZmZWN0IGNvZGUg5paH5Lu25aS5XG4gICAgICovXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHB1YmxpYyBnZXRUZW1wRWZmZWN0Q29kZVBhdGgoYXNzZXQ6IEFzc2V0KTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGpvaW4odGhpcy50ZW1wRWZmZWN0Q29kZURpciwgYCR7YXNzZXQudXVpZH0uZWZmZWN0YCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog6I635Y+W5a2Y5YKoIGVmZmVjdCBjb2RlIOi3r+W+hFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgdGVtcEVmZmVjdENvZGVEaXIoKSB7XG4gICAgICAgIHJldHVybiBqb2luKEVkaXRvci5Qcm9qZWN0LnRtcERpciwgYHNoYWRlci1ncmFwaGApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOi/lOWbnuaYr+WQpuWvvOWFpeaIkOWKn+eahOagh+iusFxuICAgICAqIOWmguaenOi/lOWbniBmYWxzZe+8jOWImSBpbXBvcnRlZCDmoIforrDkuI3kvJrlj5jmiJAgdHJ1ZVxuICAgICAqIOWQjue7reeahOS4gOezu+WIl+aTjeS9nOmDveS4jeS8muaJp+ihjFxuICAgICAqIEBwYXJhbSBhc3NldFxuICAgICAqL1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICBwdWJsaWMgYXN5bmMgaW1wb3J0KGFzc2V0OiBBc3NldCkge1xuICAgICAgICBhd2FpdCBnZW5lcmF0ZUVmZmVjdEFzc2V0KGFzc2V0LCBhd2FpdCB0aGlzLmdlbmVyYXRlRWZmZWN0QnlBc3NldChhc3NldCkpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG5ldyBTaGFkZXJHcmFwaCgpO1xuIl19