kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
246 lines (241 loc) • 32.9 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DeckSurfaceFogEffect = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _engine = require("@luma.gl/engine");
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var SURFACE_FOG_UNIFORM_BLOCK = /* glsl */"uniform surfaceFogUniforms {\n float density;\n float fogHeight;\n float fogThickness;\n vec3 fogColor;\n vec4 invCol0;\n vec4 invCol1;\n vec4 invCol2;\n vec4 invCol3;\n float viewportWidth;\n float viewportHeight;\n} surfaceFog;\n";
var SURFACE_FOG_FS = /* glsl */"#version 300 es\nprecision highp float;\n\nuniform sampler2D texSrc;\nuniform sampler2D texDepth;\n\nin vec2 position;\nin vec2 coordinate;\nin vec2 uv;\n\nout vec4 fragColor;\n\nvoid main() {\n vec4 color = texture(texSrc, coordinate);\n float depth = texture(texDepth, coordinate).r;\n\n if (depth >= 0.999) {\n fragColor = color;\n return;\n }\n\n // pixelUnprojectionMatrix maps (pixelX, pixelY, clipZ) \u2192 common space.\n // coordinate is 0..1 UV; convert to CSS pixel coords matching deck.gl convention\n // (origin top-left, y-down).\n // Depth buffer stores [0,1]; convert to clip-space Z [-1,1] (WebGL NDC).\n // Must use viewport CSS dimensions (not texture device-pixel size) because\n // pixelUnprojectionMatrix is built from CSS-pixel width/height.\n vec3 pixelPos = vec3(\n coordinate.x * surfaceFog.viewportWidth,\n (1.0 - coordinate.y) * surfaceFog.viewportHeight,\n depth * 2.0 - 1.0\n );\n\n mat4 invMat = mat4(\n surfaceFog.invCol0,\n surfaceFog.invCol1,\n surfaceFog.invCol2,\n surfaceFog.invCol3\n );\n\n vec4 commonPos = invMat * vec4(pixelPos, 1.0);\n commonPos /= commonPos.w;\n\n // commonPos.z is elevation in common-space units.\n // fogHeight and fogThickness are pre-converted to the same units on CPU.\n // Below fogHeight: full fog.\n // fogHeight \u2192 fogHeight + fogThickness: smooth transition.\n // Above fogHeight + fogThickness: no fog.\n float fogFactor = (1.0 - smoothstep(surfaceFog.fogHeight, surfaceFog.fogHeight + surfaceFog.fogThickness, commonPos.z))\n * surfaceFog.density;\n\n vec3 fogColorNorm = surfaceFog.fogColor / 255.0;\n fragColor = vec4(mix(color.rgb, fogColorNorm, clamp(fogFactor, 0.0, 1.0)), color.a);\n}\n";
var screenModule = {
name: 'screen',
fs: /* glsl */"uniform screenUniforms {\n vec2 texSize;\n} screen;\n",
uniformTypes: {
texSize: 'vec2<f32>'
}
};
var surfaceFogModule = {
name: 'surfaceFog',
fs: SURFACE_FOG_UNIFORM_BLOCK,
uniformTypes: {
density: 'f32',
fogHeight: 'f32',
fogThickness: 'f32',
fogColor: 'vec3<f32>',
invCol0: 'vec4<f32>',
invCol1: 'vec4<f32>',
invCol2: 'vec4<f32>',
invCol3: 'vec4<f32>',
viewportWidth: 'f32',
viewportHeight: 'f32'
},
defaultUniforms: {
density: 0.6,
fogHeight: 0,
fogThickness: 0,
fogColor: [230, 235, 242],
invCol0: [1, 0, 0, 0],
invCol1: [0, 1, 0, 0],
invCol2: [0, 0, 1, 0],
invCol3: [0, 0, 0, 1],
viewportWidth: 1,
viewportHeight: 1
},
propTypes: {
density: {
value: 0.6,
min: 0,
max: 1
},
height: {
value: 100,
min: 0,
max: 3000
},
thickness: {
value: 200,
min: 0,
max: 1000
},
fogColor: {
value: [230, 235, 242]
},
fogHeight: {
value: 0,
"private": true
},
fogThickness: {
value: 0,
"private": true
},
invCol0: {
value: [1, 0, 0, 0],
"private": true
},
invCol1: {
value: [0, 1, 0, 0],
"private": true
},
invCol2: {
value: [0, 0, 1, 0],
"private": true
},
invCol3: {
value: [0, 0, 0, 1],
"private": true
},
viewportWidth: {
value: 1,
"private": true
},
viewportHeight: {
value: 1,
"private": true
}
}
};
/**
* Surface Fog Effect — elevation-based ground-level fog.
*
* Uses deck.gl's pixelUnprojectionMatrix to reconstruct the common-space
* position of each fragment from the depth buffer. The Z component of
* that position corresponds to the fragment's real-world elevation
* (scaled by distanceScales.unitsPerMeter). Fog is applied to all
* fragments whose elevation is below the user-configured height (meters),
* with a smooth transition zone controlled by thickness (meters).
*/
var DeckSurfaceFogEffect = exports.DeckSurfaceFogEffect = /*#__PURE__*/function () {
function DeckSurfaceFogEffect() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _classCallCheck2["default"])(this, DeckSurfaceFogEffect);
(0, _defineProperty2["default"])(this, "id", 'surface-fog-effect');
(0, _defineProperty2["default"])(this, "props", void 0);
(0, _defineProperty2["default"])(this, "module", surfaceFogModule);
(0, _defineProperty2["default"])(this, "model", null);
this.props = _objectSpread({
density: 0.6,
height: 100,
thickness: 200,
fogColor: [230, 235, 242]
}, props);
}
return (0, _createClass2["default"])(DeckSurfaceFogEffect, [{
key: "setup",
value: function setup(_ref) {
var device = _ref.device;
this.model = new _engine.ClipSpace(device, {
id: 'surface-fog-pass',
fs: SURFACE_FOG_FS,
modules: [surfaceFogModule, screenModule],
parameters: {
depthWriteEnabled: false,
depthCompare: 'always',
blend: true,
blendColorSrcFactor: 'one',
blendColorDstFactor: 'one-minus-src-alpha',
blendAlphaSrcFactor: 'one',
blendAlphaDstFactor: 'one-minus-src-alpha',
blendColorOperation: 'add',
blendAlphaOperation: 'add'
}
});
}
}, {
key: "setProps",
value: function setProps(props) {
Object.assign(this.props, props);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
}, {
key: "preRender",
value: function preRender() {}
}, {
key: "postRender",
value: function postRender(params) {
var _params$viewports;
var inputBuffer = params.inputBuffer,
swapBuffer = params.swapBuffer,
target = params.target;
var outputBuffer = target !== undefined ? target : swapBuffer;
if (!this.model) return inputBuffer;
var depthAttachment = inputBuffer.depthStencilAttachment;
if (!depthAttachment) return inputBuffer;
var invCol0 = [1, 0, 0, 0];
var invCol1 = [0, 1, 0, 0];
var invCol2 = [0, 0, 1, 0];
var invCol3 = [0, 0, 0, 1];
var unitsPerMeterZ = 1;
var viewportWidth = 1;
var viewportHeight = 1;
if (((_params$viewports = params.viewports) === null || _params$viewports === void 0 ? void 0 : _params$viewports.length) > 0) {
var viewport = params.viewports[0];
viewportWidth = viewport.width;
viewportHeight = viewport.height;
// pixelUnprojectionMatrix maps (pixelX, pixelY, depth) → common space
var pum = viewport.pixelUnprojectionMatrix;
if (pum) {
invCol0 = [pum[0], pum[1], pum[2], pum[3]];
invCol1 = [pum[4], pum[5], pum[6], pum[7]];
invCol2 = [pum[8], pum[9], pum[10], pum[11]];
invCol3 = [pum[12], pum[13], pum[14], pum[15]];
}
var ds = viewport.distanceScales;
if (ds !== null && ds !== void 0 && ds.unitsPerMeter) {
var z = Array.isArray(ds.unitsPerMeter) ? ds.unitsPerMeter[2] : ds.unitsPerMeter;
if (Number.isFinite(z) && z > 0) {
unitsPerMeterZ = z;
}
}
}
// Convert user-facing meters to common-space units for the shader
var fogHeightCommon = this.props.height * unitsPerMeterZ;
var fogThicknessCommon = this.props.thickness * unitsPerMeterZ;
var texSize = [inputBuffer.width, inputBuffer.height];
this.model.shaderInputs.setProps({
screen: {
texSrc: inputBuffer.colorAttachments[0],
texSize: texSize
},
surfaceFog: {
texDepth: depthAttachment,
density: this.props.density,
fogHeight: fogHeightCommon,
fogThickness: fogThicknessCommon,
fogColor: this.props.fogColor,
invCol0: invCol0,
invCol1: invCol1,
invCol2: invCol2,
invCol3: invCol3,
viewportWidth: viewportWidth,
viewportHeight: viewportHeight
}
});
var renderPass = this.model.device.beginRenderPass({
framebuffer: outputBuffer,
parameters: {
viewport: [0, 0].concat(texSize)
},
clearColor: [0, 0, 0, 0],
clearDepth: 1
});
this.model.draw(renderPass);
renderPass.end();
return outputBuffer || inputBuffer;
}
}, {
key: "cleanup",
value: function cleanup() {
if (this.model) {
this.model.destroy();
this.model = null;
}
}
}]);
}();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZW5naW5lIiwicmVxdWlyZSIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiU1VSRkFDRV9GT0dfVU5JRk9STV9CTE9DSyIsIlNVUkZBQ0VfRk9HX0ZTIiwic2NyZWVuTW9kdWxlIiwibmFtZSIsImZzIiwidW5pZm9ybVR5cGVzIiwidGV4U2l6ZSIsInN1cmZhY2VGb2dNb2R1bGUiLCJkZW5zaXR5IiwiZm9nSGVpZ2h0IiwiZm9nVGhpY2tuZXNzIiwiZm9nQ29sb3IiLCJpbnZDb2wwIiwiaW52Q29sMSIsImludkNvbDIiLCJpbnZDb2wzIiwidmlld3BvcnRXaWR0aCIsInZpZXdwb3J0SGVpZ2h0IiwiZGVmYXVsdFVuaWZvcm1zIiwicHJvcFR5cGVzIiwidmFsdWUiLCJtaW4iLCJtYXgiLCJoZWlnaHQiLCJ0aGlja25lc3MiLCJEZWNrU3VyZmFjZUZvZ0VmZmVjdCIsImV4cG9ydHMiLCJwcm9wcyIsInVuZGVmaW5lZCIsIl9jbGFzc0NhbGxDaGVjazIiLCJfY3JlYXRlQ2xhc3MyIiwia2V5Iiwic2V0dXAiLCJfcmVmIiwiZGV2aWNlIiwibW9kZWwiLCJDbGlwU3BhY2UiLCJpZCIsIm1vZHVsZXMiLCJwYXJhbWV0ZXJzIiwiZGVwdGhXcml0ZUVuYWJsZWQiLCJkZXB0aENvbXBhcmUiLCJibGVuZCIsImJsZW5kQ29sb3JTcmNGYWN0b3IiLCJibGVuZENvbG9yRHN0RmFjdG9yIiwiYmxlbmRBbHBoYVNyY0ZhY3RvciIsImJsZW5kQWxwaGFEc3RGYWN0b3IiLCJibGVuZENvbG9yT3BlcmF0aW9uIiwiYmxlbmRBbHBoYU9wZXJhdGlvbiIsInNldFByb3BzIiwiYXNzaWduIiwicHJlUmVuZGVyIiwicG9zdFJlbmRlciIsInBhcmFtcyIsIl9wYXJhbXMkdmlld3BvcnRzIiwiaW5wdXRCdWZmZXIiLCJzd2FwQnVmZmVyIiwidGFyZ2V0Iiwib3V0cHV0QnVmZmVyIiwiZGVwdGhBdHRhY2htZW50IiwiZGVwdGhTdGVuY2lsQXR0YWNobWVudCIsInVuaXRzUGVyTWV0ZXJaIiwidmlld3BvcnRzIiwidmlld3BvcnQiLCJ3aWR0aCIsInB1bSIsInBpeGVsVW5wcm9qZWN0aW9uTWF0cml4IiwiZHMiLCJkaXN0YW5jZVNjYWxlcyIsInVuaXRzUGVyTWV0ZXIiLCJ6IiwiQXJyYXkiLCJpc0FycmF5IiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJmb2dIZWlnaHRDb21tb24iLCJmb2dUaGlja25lc3NDb21tb24iLCJzaGFkZXJJbnB1dHMiLCJzY3JlZW4iLCJ0ZXhTcmMiLCJjb2xvckF0dGFjaG1lbnRzIiwic3VyZmFjZUZvZyIsInRleERlcHRoIiwicmVuZGVyUGFzcyIsImJlZ2luUmVuZGVyUGFzcyIsImZyYW1lYnVmZmVyIiwiY29uY2F0IiwiY2xlYXJDb2xvciIsImNsZWFyRGVwdGgiLCJkcmF3IiwiZW5kIiwiY2xlYW51cCIsImRlc3Ryb3kiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2hhZGVyLXBhc3Nlcy9zdXJmYWNlLWZvZy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge0NsaXBTcGFjZX0gZnJvbSAnQGx1bWEuZ2wvZW5naW5lJztcbmltcG9ydCB0eXBlIHtTaGFkZXJNb2R1bGV9IGZyb20gJ0BsdW1hLmdsL3NoYWRlcnRvb2xzJztcblxuZXhwb3J0IHR5cGUgU3VyZmFjZUZvZ1Byb3BzID0ge1xuICBkZW5zaXR5OiBudW1iZXI7XG4gIC8qKiBGb2cgY2VpbGluZyBlbGV2YXRpb24gaW4gbWV0ZXJzLiBHZW9tZXRyeSBiZWxvdyB0aGlzIGdldHMgZm9nLiAqL1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgLyoqIFZlcnRpY2FsIHRyYW5zaXRpb24gem9uZSBpbiBtZXRlcnMgYWJvdmUgdGhlIGNlaWxpbmcuICovXG4gIHRoaWNrbmVzczogbnVtYmVyO1xuICBmb2dDb2xvcjogW251bWJlciwgbnVtYmVyLCBudW1iZXJdO1xufTtcblxuY29uc3QgU1VSRkFDRV9GT0dfVU5JRk9STV9CTE9DSyA9IC8qIGdsc2wgKi8gYFxcXG51bmlmb3JtIHN1cmZhY2VGb2dVbmlmb3JtcyB7XG4gIGZsb2F0IGRlbnNpdHk7XG4gIGZsb2F0IGZvZ0hlaWdodDtcbiAgZmxvYXQgZm9nVGhpY2tuZXNzO1xuICB2ZWMzIGZvZ0NvbG9yO1xuICB2ZWM0IGludkNvbDA7XG4gIHZlYzQgaW52Q29sMTtcbiAgdmVjNCBpbnZDb2wyO1xuICB2ZWM0IGludkNvbDM7XG4gIGZsb2F0IHZpZXdwb3J0V2lkdGg7XG4gIGZsb2F0IHZpZXdwb3J0SGVpZ2h0O1xufSBzdXJmYWNlRm9nO1xuYDtcblxuY29uc3QgU1VSRkFDRV9GT0dfRlMgPSAvKiBnbHNsICovIGBcXFxuI3ZlcnNpb24gMzAwIGVzXG5wcmVjaXNpb24gaGlnaHAgZmxvYXQ7XG5cbnVuaWZvcm0gc2FtcGxlcjJEIHRleFNyYztcbnVuaWZvcm0gc2FtcGxlcjJEIHRleERlcHRoO1xuXG5pbiB2ZWMyIHBvc2l0aW9uO1xuaW4gdmVjMiBjb29yZGluYXRlO1xuaW4gdmVjMiB1djtcblxub3V0IHZlYzQgZnJhZ0NvbG9yO1xuXG52b2lkIG1haW4oKSB7XG4gIHZlYzQgY29sb3IgPSB0ZXh0dXJlKHRleFNyYywgY29vcmRpbmF0ZSk7XG4gIGZsb2F0IGRlcHRoID0gdGV4dHVyZSh0ZXhEZXB0aCwgY29vcmRpbmF0ZSkucjtcblxuICBpZiAoZGVwdGggPj0gMC45OTkpIHtcbiAgICBmcmFnQ29sb3IgPSBjb2xvcjtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBwaXhlbFVucHJvamVjdGlvbk1hdHJpeCBtYXBzIChwaXhlbFgsIHBpeGVsWSwgY2xpcFopIOKGkiBjb21tb24gc3BhY2UuXG4gIC8vIGNvb3JkaW5hdGUgaXMgMC4uMSBVVjsgY29udmVydCB0byBDU1MgcGl4ZWwgY29vcmRzIG1hdGNoaW5nIGRlY2suZ2wgY29udmVudGlvblxuICAvLyAob3JpZ2luIHRvcC1sZWZ0LCB5LWRvd24pLlxuICAvLyBEZXB0aCBidWZmZXIgc3RvcmVzIFswLDFdOyBjb252ZXJ0IHRvIGNsaXAtc3BhY2UgWiBbLTEsMV0gKFdlYkdMIE5EQykuXG4gIC8vIE11c3QgdXNlIHZpZXdwb3J0IENTUyBkaW1lbnNpb25zIChub3QgdGV4dHVyZSBkZXZpY2UtcGl4ZWwgc2l6ZSkgYmVjYXVzZVxuICAvLyBwaXhlbFVucHJvamVjdGlvbk1hdHJpeCBpcyBidWlsdCBmcm9tIENTUy1waXhlbCB3aWR0aC9oZWlnaHQuXG4gIHZlYzMgcGl4ZWxQb3MgPSB2ZWMzKFxuICAgIGNvb3JkaW5hdGUueCAqIHN1cmZhY2VGb2cudmlld3BvcnRXaWR0aCxcbiAgICAoMS4wIC0gY29vcmRpbmF0ZS55KSAqIHN1cmZhY2VGb2cudmlld3BvcnRIZWlnaHQsXG4gICAgZGVwdGggKiAyLjAgLSAxLjBcbiAgKTtcblxuICBtYXQ0IGludk1hdCA9IG1hdDQoXG4gICAgc3VyZmFjZUZvZy5pbnZDb2wwLFxuICAgIHN1cmZhY2VGb2cuaW52Q29sMSxcbiAgICBzdXJmYWNlRm9nLmludkNvbDIsXG4gICAgc3VyZmFjZUZvZy5pbnZDb2wzXG4gICk7XG5cbiAgdmVjNCBjb21tb25Qb3MgPSBpbnZNYXQgKiB2ZWM0KHBpeGVsUG9zLCAxLjApO1xuICBjb21tb25Qb3MgLz0gY29tbW9uUG9zLnc7XG5cbiAgLy8gY29tbW9uUG9zLnogaXMgZWxldmF0aW9uIGluIGNvbW1vbi1zcGFjZSB1bml0cy5cbiAgLy8gZm9nSGVpZ2h0IGFuZCBmb2dUaGlja25lc3MgYXJlIHByZS1jb252ZXJ0ZWQgdG8gdGhlIHNhbWUgdW5pdHMgb24gQ1BVLlxuICAvLyBCZWxvdyBmb2dIZWlnaHQ6IGZ1bGwgZm9nLlxuICAvLyBmb2dIZWlnaHQg4oaSIGZvZ0hlaWdodCArIGZvZ1RoaWNrbmVzczogc21vb3RoIHRyYW5zaXRpb24uXG4gIC8vIEFib3ZlIGZvZ0hlaWdodCArIGZvZ1RoaWNrbmVzczogbm8gZm9nLlxuICBmbG9hdCBmb2dGYWN0b3IgPSAoMS4wIC0gc21vb3Roc3RlcChzdXJmYWNlRm9nLmZvZ0hlaWdodCwgc3VyZmFjZUZvZy5mb2dIZWlnaHQgKyBzdXJmYWNlRm9nLmZvZ1RoaWNrbmVzcywgY29tbW9uUG9zLnopKVxuICAgICAgICAgICAgICAgICAgICAqIHN1cmZhY2VGb2cuZGVuc2l0eTtcblxuICB2ZWMzIGZvZ0NvbG9yTm9ybSA9IHN1cmZhY2VGb2cuZm9nQ29sb3IgLyAyNTUuMDtcbiAgZnJhZ0NvbG9yID0gdmVjNChtaXgoY29sb3IucmdiLCBmb2dDb2xvck5vcm0sIGNsYW1wKGZvZ0ZhY3RvciwgMC4wLCAxLjApKSwgY29sb3IuYSk7XG59XG5gO1xuXG5jb25zdCBzY3JlZW5Nb2R1bGUgPSB7XG4gIG5hbWU6ICdzY3JlZW4nLFxuICBmczogLyogZ2xzbCAqLyBgXFxcbnVuaWZvcm0gc2NyZWVuVW5pZm9ybXMge1xuICB2ZWMyIHRleFNpemU7XG59IHNjcmVlbjtcbmAsXG4gIHVuaWZvcm1UeXBlczoge1xuICAgIHRleFNpemU6ICd2ZWMyPGYzMj4nXG4gIH1cbn0gYXMgY29uc3Qgc2F0aXNmaWVzIFNoYWRlck1vZHVsZTtcblxuY29uc3Qgc3VyZmFjZUZvZ01vZHVsZSA9IHtcbiAgbmFtZTogJ3N1cmZhY2VGb2cnLFxuICBmczogU1VSRkFDRV9GT0dfVU5JRk9STV9CTE9DSyxcbiAgdW5pZm9ybVR5cGVzOiB7XG4gICAgZGVuc2l0eTogJ2YzMicsXG4gICAgZm9nSGVpZ2h0OiAnZjMyJyxcbiAgICBmb2dUaGlja25lc3M6ICdmMzInLFxuICAgIGZvZ0NvbG9yOiAndmVjMzxmMzI+JyxcbiAgICBpbnZDb2wwOiAndmVjNDxmMzI+JyxcbiAgICBpbnZDb2wxOiAndmVjNDxmMzI+JyxcbiAgICBpbnZDb2wyOiAndmVjNDxmMzI+JyxcbiAgICBpbnZDb2wzOiAndmVjNDxmMzI+JyxcbiAgICB2aWV3cG9ydFdpZHRoOiAnZjMyJyxcbiAgICB2aWV3cG9ydEhlaWdodDogJ2YzMidcbiAgfSxcbiAgZGVmYXVsdFVuaWZvcm1zOiB7XG4gICAgZGVuc2l0eTogMC42LFxuICAgIGZvZ0hlaWdodDogMCxcbiAgICBmb2dUaGlja25lc3M6IDAsXG4gICAgZm9nQ29sb3I6IFsyMzAsIDIzNSwgMjQyXSxcbiAgICBpbnZDb2wwOiBbMSwgMCwgMCwgMF0sXG4gICAgaW52Q29sMTogWzAsIDEsIDAsIDBdLFxuICAgIGludkNvbDI6IFswLCAwLCAxLCAwXSxcbiAgICBpbnZDb2wzOiBbMCwgMCwgMCwgMV0sXG4gICAgdmlld3BvcnRXaWR0aDogMSxcbiAgICB2aWV3cG9ydEhlaWdodDogMVxuICB9LFxuICBwcm9wVHlwZXM6IHtcbiAgICBkZW5zaXR5OiB7dmFsdWU6IDAuNiwgbWluOiAwLCBtYXg6IDF9LFxuICAgIGhlaWdodDoge3ZhbHVlOiAxMDAsIG1pbjogMCwgbWF4OiAzMDAwfSxcbiAgICB0aGlja25lc3M6IHt2YWx1ZTogMjAwLCBtaW46IDAsIG1heDogMTAwMH0sXG4gICAgZm9nQ29sb3I6IHt2YWx1ZTogWzIzMCwgMjM1LCAyNDJdfSxcbiAgICBmb2dIZWlnaHQ6IHt2YWx1ZTogMCwgcHJpdmF0ZTogdHJ1ZX0sXG4gICAgZm9nVGhpY2tuZXNzOiB7dmFsdWU6IDAsIHByaXZhdGU6IHRydWV9LFxuICAgIGludkNvbDA6IHt2YWx1ZTogWzEsIDAsIDAsIDBdLCBwcml2YXRlOiB0cnVlfSxcbiAgICBpbnZDb2wxOiB7dmFsdWU6IFswLCAxLCAwLCAwXSwgcHJpdmF0ZTogdHJ1ZX0sXG4gICAgaW52Q29sMjoge3ZhbHVlOiBbMCwgMCwgMSwgMF0sIHByaXZhdGU6IHRydWV9LFxuICAgIGludkNvbDM6IHt2YWx1ZTogWzAsIDAsIDAsIDFdLCBwcml2YXRlOiB0cnVlfSxcbiAgICB2aWV3cG9ydFdpZHRoOiB7dmFsdWU6IDEsIHByaXZhdGU6IHRydWV9LFxuICAgIHZpZXdwb3J0SGVpZ2h0OiB7dmFsdWU6IDEsIHByaXZhdGU6IHRydWV9XG4gIH1cbn0gYXMgY29uc3Qgc2F0aXNmaWVzIFNoYWRlck1vZHVsZTtcblxuLyoqXG4gKiBTdXJmYWNlIEZvZyBFZmZlY3Qg4oCUIGVsZXZhdGlvbi1iYXNlZCBncm91bmQtbGV2ZWwgZm9nLlxuICpcbiAqIFVzZXMgZGVjay5nbCdzIHBpeGVsVW5wcm9qZWN0aW9uTWF0cml4IHRvIHJlY29uc3RydWN0IHRoZSBjb21tb24tc3BhY2VcbiAqIHBvc2l0aW9uIG9mIGVhY2ggZnJhZ21lbnQgZnJvbSB0aGUgZGVwdGggYnVmZmVyLiAgVGhlIFogY29tcG9uZW50IG9mXG4gKiB0aGF0IHBvc2l0aW9uIGNvcnJlc3BvbmRzIHRvIHRoZSBmcmFnbWVudCdzIHJlYWwtd29ybGQgZWxldmF0aW9uXG4gKiAoc2NhbGVkIGJ5IGRpc3RhbmNlU2NhbGVzLnVuaXRzUGVyTWV0ZXIpLiAgRm9nIGlzIGFwcGxpZWQgdG8gYWxsXG4gKiBmcmFnbWVudHMgd2hvc2UgZWxldmF0aW9uIGlzIGJlbG93IHRoZSB1c2VyLWNvbmZpZ3VyZWQgaGVpZ2h0IChtZXRlcnMpLFxuICogd2l0aCBhIHNtb290aCB0cmFuc2l0aW9uIHpvbmUgY29udHJvbGxlZCBieSB0aGlja25lc3MgKG1ldGVycykuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZWNrU3VyZmFjZUZvZ0VmZmVjdCB7XG4gIGlkID0gJ3N1cmZhY2UtZm9nLWVmZmVjdCc7XG4gIHByb3BzOiBTdXJmYWNlRm9nUHJvcHM7XG4gIG1vZHVsZSA9IHN1cmZhY2VGb2dNb2R1bGU7XG4gIHByaXZhdGUgbW9kZWw6IEluc3RhbmNlVHlwZTx0eXBlb2YgQ2xpcFNwYWNlPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBQYXJ0aWFsPFN1cmZhY2VGb2dQcm9wcz4gPSB7fSkge1xuICAgIHRoaXMucHJvcHMgPSB7XG4gICAgICBkZW5zaXR5OiAwLjYsXG4gICAgICBoZWlnaHQ6IDEwMCxcbiAgICAgIHRoaWNrbmVzczogMjAwLFxuICAgICAgZm9nQ29sb3I6IFsyMzAsIDIzNSwgMjQyXSxcbiAgICAgIC4uLnByb3BzXG4gICAgfTtcbiAgfVxuXG4gIHNldHVwKHtkZXZpY2V9KSB7XG4gICAgdGhpcy5tb2RlbCA9IG5ldyBDbGlwU3BhY2UoZGV2aWNlLCB7XG4gICAgICBpZDogJ3N1cmZhY2UtZm9nLXBhc3MnLFxuICAgICAgZnM6IFNVUkZBQ0VfRk9HX0ZTLFxuICAgICAgbW9kdWxlczogW3N1cmZhY2VGb2dNb2R1bGUsIHNjcmVlbk1vZHVsZV0sXG4gICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgIGRlcHRoV3JpdGVFbmFibGVkOiBmYWxzZSxcbiAgICAgICAgZGVwdGhDb21wYXJlOiAnYWx3YXlzJyBhcyBjb25zdCxcbiAgICAgICAgYmxlbmQ6IHRydWUsXG4gICAgICAgIGJsZW5kQ29sb3JTcmNGYWN0b3I6ICdvbmUnIGFzIGNvbnN0LFxuICAgICAgICBibGVuZENvbG9yRHN0RmFjdG9yOiAnb25lLW1pbnVzLXNyYy1hbHBoYScgYXMgY29uc3QsXG4gICAgICAgIGJsZW5kQWxwaGFTcmNGYWN0b3I6ICdvbmUnIGFzIGNvbnN0LFxuICAgICAgICBibGVuZEFscGhhRHN0RmFjdG9yOiAnb25lLW1pbnVzLXNyYy1hbHBoYScgYXMgY29uc3QsXG4gICAgICAgIGJsZW5kQ29sb3JPcGVyYXRpb246ICdhZGQnIGFzIGNvbnN0LFxuICAgICAgICBibGVuZEFscGhhT3BlcmF0aW9uOiAnYWRkJyBhcyBjb25zdFxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc2V0UHJvcHMocHJvcHM6IFBhcnRpYWw8U3VyZmFjZUZvZ1Byb3BzPikge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcy5wcm9wcywgcHJvcHMpO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICBwcmVSZW5kZXIoKTogdm9pZCB7fVxuXG4gIHBvc3RSZW5kZXIocGFyYW1zOiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHtpbnB1dEJ1ZmZlciwgc3dhcEJ1ZmZlciwgdGFyZ2V0fSA9IHBhcmFtcztcbiAgICBjb25zdCBvdXRwdXRCdWZmZXIgPSB0YXJnZXQgIT09IHVuZGVmaW5lZCA/IHRhcmdldCA6IHN3YXBCdWZmZXI7XG5cbiAgICBpZiAoIXRoaXMubW9kZWwpIHJldHVybiBpbnB1dEJ1ZmZlcjtcblxuICAgIGNvbnN0IGRlcHRoQXR0YWNobWVudCA9IGlucHV0QnVmZmVyLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQ7XG4gICAgaWYgKCFkZXB0aEF0dGFjaG1lbnQpIHJldHVybiBpbnB1dEJ1ZmZlcjtcblxuICAgIGxldCBpbnZDb2wwID0gWzEsIDAsIDAsIDBdO1xuICAgIGxldCBpbnZDb2wxID0gWzAsIDEsIDAsIDBdO1xuICAgIGxldCBpbnZDb2wyID0gWzAsIDAsIDEsIDBdO1xuICAgIGxldCBpbnZDb2wzID0gWzAsIDAsIDAsIDFdO1xuICAgIGxldCB1bml0c1Blck1ldGVyWiA9IDE7XG4gICAgbGV0IHZpZXdwb3J0V2lkdGggPSAxO1xuICAgIGxldCB2aWV3cG9ydEhlaWdodCA9IDE7XG5cbiAgICBpZiAocGFyYW1zLnZpZXdwb3J0cz8ubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgdmlld3BvcnQgPSBwYXJhbXMudmlld3BvcnRzWzBdO1xuXG4gICAgICB2aWV3cG9ydFdpZHRoID0gdmlld3BvcnQud2lkdGg7XG4gICAgICB2aWV3cG9ydEhlaWdodCA9IHZpZXdwb3J0LmhlaWdodDtcblxuICAgICAgLy8gcGl4ZWxVbnByb2plY3Rpb25NYXRyaXggbWFwcyAocGl4ZWxYLCBwaXhlbFksIGRlcHRoKSDihpIgY29tbW9uIHNwYWNlXG4gICAgICBjb25zdCBwdW0gPSB2aWV3cG9ydC5waXhlbFVucHJvamVjdGlvbk1hdHJpeDtcbiAgICAgIGlmIChwdW0pIHtcbiAgICAgICAgaW52Q29sMCA9IFtwdW1bMF0sIHB1bVsxXSwgcHVtWzJdLCBwdW1bM11dO1xuICAgICAgICBpbnZDb2wxID0gW3B1bVs0XSwgcHVtWzVdLCBwdW1bNl0sIHB1bVs3XV07XG4gICAgICAgIGludkNvbDIgPSBbcHVtWzhdLCBwdW1bOV0sIHB1bVsxMF0sIHB1bVsxMV1dO1xuICAgICAgICBpbnZDb2wzID0gW3B1bVsxMl0sIHB1bVsxM10sIHB1bVsxNF0sIHB1bVsxNV1dO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkcyA9IHZpZXdwb3J0LmRpc3RhbmNlU2NhbGVzO1xuICAgICAgaWYgKGRzPy51bml0c1Blck1ldGVyKSB7XG4gICAgICAgIGNvbnN0IHogPSBBcnJheS5pc0FycmF5KGRzLnVuaXRzUGVyTWV0ZXIpID8gZHMudW5pdHNQZXJNZXRlclsyXSA6IGRzLnVuaXRzUGVyTWV0ZXI7XG4gICAgICAgIGlmIChOdW1iZXIuaXNGaW5pdGUoeikgJiYgeiA+IDApIHtcbiAgICAgICAgICB1bml0c1Blck1ldGVyWiA9IHo7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0IHVzZXItZmFjaW5nIG1ldGVycyB0byBjb21tb24tc3BhY2UgdW5pdHMgZm9yIHRoZSBzaGFkZXJcbiAgICBjb25zdCBmb2dIZWlnaHRDb21tb24gPSB0aGlzLnByb3BzLmhlaWdodCAqIHVuaXRzUGVyTWV0ZXJaO1xuICAgIGNvbnN0IGZvZ1RoaWNrbmVzc0NvbW1vbiA9IHRoaXMucHJvcHMudGhpY2tuZXNzICogdW5pdHNQZXJNZXRlclo7XG5cbiAgICBjb25zdCB0ZXhTaXplOiBbbnVtYmVyLCBudW1iZXJdID0gW2lucHV0QnVmZmVyLndpZHRoLCBpbnB1dEJ1ZmZlci5oZWlnaHRdO1xuXG4gICAgdGhpcy5tb2RlbC5zaGFkZXJJbnB1dHMuc2V0UHJvcHMoe1xuICAgICAgc2NyZWVuOiB7XG4gICAgICAgIHRleFNyYzogaW5wdXRCdWZmZXIuY29sb3JBdHRhY2htZW50c1swXSxcbiAgICAgICAgdGV4U2l6ZVxuICAgICAgfSxcbiAgICAgIHN1cmZhY2VGb2c6IHtcbiAgICAgICAgdGV4RGVwdGg6IGRlcHRoQXR0YWNobWVudCxcbiAgICAgICAgZGVuc2l0eTogdGhpcy5wcm9wcy5kZW5zaXR5LFxuICAgICAgICBmb2dIZWlnaHQ6IGZvZ0hlaWdodENvbW1vbixcbiAgICAgICAgZm9nVGhpY2tuZXNzOiBmb2dUaGlja25lc3NDb21tb24sXG4gICAgICAgIGZvZ0NvbG9yOiB0aGlzLnByb3BzLmZvZ0NvbG9yLFxuICAgICAgICBpbnZDb2wwLFxuICAgICAgICBpbnZDb2wxLFxuICAgICAgICBpbnZDb2wyLFxuICAgICAgICBpbnZDb2wzLFxuICAgICAgICB2aWV3cG9ydFdpZHRoLFxuICAgICAgICB2aWV3cG9ydEhlaWdodFxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVuZGVyUGFzcyA9IHRoaXMubW9kZWwuZGV2aWNlLmJlZ2luUmVuZGVyUGFzcyh7XG4gICAgICBmcmFtZWJ1ZmZlcjogb3V0cHV0QnVmZmVyLFxuICAgICAgcGFyYW1ldGVyczoge3ZpZXdwb3J0OiBbMCwgMCwgLi4udGV4U2l6ZV19LFxuICAgICAgY2xlYXJDb2xvcjogWzAsIDAsIDAsIDBdLFxuICAgICAgY2xlYXJEZXB0aDogMVxuICAgIH0pO1xuICAgIHRoaXMubW9kZWwuZHJhdyhyZW5kZXJQYXNzKTtcbiAgICByZW5kZXJQYXNzLmVuZCgpO1xuXG4gICAgcmV0dXJuIG91dHB1dEJ1ZmZlciB8fCBpbnB1dEJ1ZmZlcjtcbiAgfVxuXG4gIGNsZWFudXAoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubW9kZWwpIHtcbiAgICAgIHRoaXMubW9kZWwuZGVzdHJveSgpO1xuICAgICAgdGhpcy5tb2RlbCA9IG51bGw7XG4gICAgfVxuICB9XG59XG4iXSwibWFwcGlu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