ng-cw-v12
Version:
Angular UI Component Library
230 lines (225 loc) • 30.4 kB
JavaScript
import { Component, ViewChild, Input, HostListener } from '@angular/core';
import * as THREE from 'three';
import * as i0 from "@angular/core";
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
precision highp float;
uniform float uTime;
uniform vec3 uResolution;
uniform vec3 uBaseColor;
uniform float uAmplitude;
uniform float uFrequencyX;
uniform float uFrequencyY;
uniform vec2 uMouse;
varying vec2 vUv;
vec4 renderImage(vec2 uvCoord) {
vec2 fragCoord = uvCoord * uResolution.xy;
vec2 uv = (2.0 * fragCoord - uResolution.xy) / min(uResolution.x, uResolution.y);
for (float i = 1.0; i < 10.0; i++){
uv.x += uAmplitude / i * cos(i * uFrequencyX * uv.y + uTime + uMouse.x * 3.14159);
uv.y += uAmplitude / i * cos(i * uFrequencyY * uv.x + uTime + uMouse.y * 3.14159);
}
vec2 diff = (uvCoord - uMouse);
float dist = length(diff);
float falloff = exp(-dist * 20.0);
float ripple = sin(10.0 * dist - uTime * 2.0) * 0.03;
uv += (diff / (dist + 0.0001)) * ripple * falloff;
vec3 color = uBaseColor / abs(sin(uTime - uv.y - uv.x));
return vec4(color, 1.0);
}
void main() {
vec4 col = vec4(0.0);
int samples = 0;
for (int i = -1; i <= 1; i++){
for (int j = -1; j <= 1; j++){
vec2 offset = vec2(float(i), float(j)) * (1.0 / min(uResolution.x, uResolution.y));
col += renderImage(vUv + offset);
samples++;
}
}
gl_FragColor = col / float(samples);
}
`;
export class LiquidChromeBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 基础颜色数组 [r, g, b](0-1) */
this.ncBaseColor = [0.1, 0.1, 0.1];
/** 动画运行速度(0-5) */
this.ncSpeed = 0.2;
/** 波动幅度(0.1-1) */
this.ncAmplitude = 0.3;
/** X轴波频 */
this.ncFrequencyX = 3;
/** Y轴波频 */
this.ncFrequencyY = 3;
/** 是否允许鼠标/触屏交互 */
this._interactive = true;
this.animationId = null;
this.mouse = new THREE.Vector2(0, 0);
this.update = (t) => {
this.animationId = requestAnimationFrame(this.update);
if (this.material) {
this.material.uniforms['uTime'].value = t * 0.001 * this.ncSpeed;
}
this.renderer.render(this.scene, this.camera);
};
}
set ncInteractive(value) {
this._interactive = value !== null && value !== undefined && value !== false && value !== 'false';
}
get ncInteractive() {
return this._interactive;
}
ngOnInit() { }
ngAfterViewInit() {
this.initWebGL();
}
ngOnDestroy() {
this.cleanup();
}
ngOnChanges(changes) {
if (!this.material)
return;
if (changes['ncBaseColor'] && changes['ncBaseColor'].currentValue) {
this.material.uniforms['uBaseColor'].value.fromArray(this.ncBaseColor);
}
if (changes['ncAmplitude'] !== undefined) {
this.material.uniforms['uAmplitude'].value = this.ncAmplitude;
}
if (changes['ncFrequencyX'] !== undefined) {
this.material.uniforms['uFrequencyX'].value = this.ncFrequencyX;
}
if (changes['ncFrequencyY'] !== undefined) {
this.material.uniforms['uFrequencyY'].value = this.ncFrequencyY;
}
// ncInteractive handled via HostListener check
}
initWebGL() {
const container = this.containerRef.nativeElement;
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
// 原版 jsx 清除颜色为白色
this.renderer.setClearColor(0xffffff, 1);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
container.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
// 正交相机渲染全屏 Plane
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
this.camera.position.z = 1;
const geometry = new THREE.PlaneGeometry(2, 2);
this.material = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms: {
uTime: { value: 0 },
uResolution: { value: new THREE.Vector3() },
uBaseColor: { value: new THREE.Vector3().fromArray(this.ncBaseColor) },
uAmplitude: { value: this.ncAmplitude },
uFrequencyX: { value: this.ncFrequencyX },
uFrequencyY: { value: this.ncFrequencyY },
uMouse: { value: this.mouse }
}
});
this.mesh = new THREE.Mesh(geometry, this.material);
this.scene.add(this.mesh);
this.resizeObserver = new ResizeObserver(() => this.resize());
this.resizeObserver.observe(container);
this.resize();
// Interaction handled via HostListener
// 提升性能,不让 requestAnimationFrame 触发 Angular 变更检测
this.ngZone.runOutsideAngular(() => {
this.update(0);
});
}
resize() {
if (!this.containerRef || !this.renderer)
return;
const container = this.containerRef.nativeElement;
const width = container.offsetWidth;
const height = container.offsetHeight;
this.renderer.setSize(width, height);
this.material.uniforms['uResolution'].value.set(width, height, width / height);
}
onMouseMove(event) {
if (!this.ncInteractive || !this.containerRef)
return;
const container = this.containerRef.nativeElement;
const rect = container.getBoundingClientRect();
const x = (event.clientX - rect.left) / rect.width;
const y = 1 - (event.clientY - rect.top) / rect.height;
this.mouse.set(x, y);
}
onTouchMove(event) {
if (!this.ncInteractive || !this.containerRef)
return;
if (event.touches.length > 0) {
const touch = event.touches[0];
const container = this.containerRef.nativeElement;
const rect = container.getBoundingClientRect();
const x = (touch.clientX - rect.left) / rect.width;
const y = 1 - (touch.clientY - rect.top) / rect.height;
this.mouse.set(x, y);
}
}
cleanup() {
var _a, _b;
if (this.animationId !== null) {
cancelAnimationFrame(this.animationId);
this.animationId = null;
}
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}
if (this.mesh) {
this.mesh.geometry.dispose();
this.mesh.material.dispose();
this.scene.remove(this.mesh);
}
if (this.renderer) {
this.renderer.dispose();
const dom = this.renderer.domElement;
if (dom && dom.parentElement) {
dom.parentElement.removeChild(dom);
}
(_b = (_a = this.renderer.getContext()) === null || _a === void 0 ? void 0 : _a.getExtension('WEBGL_lose_context')) === null || _b === void 0 ? void 0 : _b.loseContext();
}
}
}
LiquidChromeBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LiquidChromeBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
LiquidChromeBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: LiquidChromeBackgroundComponent, selector: "nc-liquid-chrome-background", inputs: { ncBaseColor: "ncBaseColor", ncSpeed: "ncSpeed", ncAmplitude: "ncAmplitude", ncFrequencyX: "ncFrequencyX", ncFrequencyY: "ncFrequencyY", ncInteractive: "ncInteractive" }, host: { listeners: { "mousemove": "onMouseMove($event)", "touchmove": "onTouchMove($event)" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-liquid-chrome-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-liquid-chrome-canvas-container{position:absolute;inset:0;z-index:0}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LiquidChromeBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-liquid-chrome-background',
templateUrl: './liquid-chrome-background.component.html',
styleUrls: ['./liquid-chrome-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncBaseColor: [{
type: Input
}], ncSpeed: [{
type: Input
}], ncAmplitude: [{
type: Input
}], ncFrequencyX: [{
type: Input
}], ncFrequencyY: [{
type: Input
}], ncInteractive: [{
type: Input
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], onTouchMove: [{
type: HostListener,
args: ['touchmove', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlxdWlkLWNocm9tZS1iYWNrZ3JvdW5kLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvbGlxdWlkLWNocm9tZS1iYWNrZ3JvdW5kL2xpcXVpZC1jaHJvbWUtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2xpcXVpZC1jaHJvbWUtYmFja2dyb3VuZC9saXF1aWQtY2hyb21lLWJhY2tncm91bmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFJVCxTQUFTLEVBRVQsS0FBSyxFQUlMLFlBQVksRUFDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQzs7QUFFL0IsTUFBTSxZQUFZLEdBQUc7Ozs7OztDQU1wQixDQUFDO0FBRUYsTUFBTSxjQUFjLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTBDdEIsQ0FBQztBQU9GLE1BQU0sT0FBTywrQkFBK0I7SUFnQzFDLFlBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBN0JsQyw0QkFBNEI7UUFDbkIsZ0JBQVcsR0FBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDakQsa0JBQWtCO1FBQ1QsWUFBTyxHQUFXLEdBQUcsQ0FBQztRQUMvQixrQkFBa0I7UUFDVCxnQkFBVyxHQUFXLEdBQUcsQ0FBQztRQUNuQyxXQUFXO1FBQ0YsaUJBQVksR0FBVyxDQUFDLENBQUM7UUFDbEMsV0FBVztRQUNGLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBQ2xDLGtCQUFrQjtRQUNWLGlCQUFZLEdBQVksSUFBSSxDQUFDO1FBYzdCLGdCQUFXLEdBQWtCLElBQUksQ0FBQztRQUVsQyxVQUFLLEdBQUcsSUFBSSxL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QVk7c0JBQXJELFNBQVM7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFHL0IsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxPQUFPO3NCQUFmLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR08sYUFBYTtzQkFBekIsS0FBSztnQkEwR04sV0FBVztzQkFEVixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFZckMsV0FBVztzQkFEVixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uSW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxuICBOZ1pvbmUsXHJcbiAgSG9zdExpc3RlbmVyXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcclxuXHJcbmNvbnN0IHZlcnRleFNoYWRlciA9IGBcclxuICB2YXJ5aW5nIHZlYzIgdlV2O1xyXG4gIHZvaWQgbWFpbigpIHtcclxuICAgIHZVdiA9IHV2O1xyXG4gICAgZ2xfUG9zaXRpb24gPSBwcm9qZWN0aW9uTWF0cml4ICogbW9kZWxWaWV3TWF0cml4ICogdmVjNChwb3NpdGlvbiwgMS4wKTtcclxuICB9XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnbWVudFNoYWRlciA9IGBcclxuICBwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XHJcbiAgdW5pZm9ybSBmbG9hdCB1VGltZTtcclxuICB1bmlmb3JtIHZlYzMgdVJlc29sdXRpb247XHJcbiAgdW5pZm9ybSB2ZWMzIHVCYXNlQ29sb3I7XHJcbiAgdW5pZm9ybSBmbG9hdCB1QW1wbGl0dWRlO1xyXG4gIHVuaWZvcm0gZmxvYXQgdUZyZXF1ZW5jeVg7XHJcbiAgdW5pZm9ybSBmbG9hdCB1RnJlcXVlbmN5WTtcclxuICB1bmlmb3JtIHZlYzIgdU1vdXNlO1xyXG4gIHZhcnlpbmcgdmVjMiB2VXY7XHJcblxyXG4gIHZlYzQgcmVuZGVySW1hZ2UodmVjMiB1dkNvb3JkKSB7XHJcbiAgICAgIHZlYzIgZnJhZ0Nvb3JkID0gdXZDb29yZCAqIHVSZXNvbHV0aW9uLnh5O1xyXG4gICAgICB2ZWMyIHV2ID0gKDIuMCAqIGZyYWdDb29yZCAtIHVSZXNvbHV0aW9uLnh5KSAvIG1pbih1UmVzb2x1dGlvbi54LCB1UmVzb2x1dGlvbi55KTtcclxuXHJcbiAgICAgIGZvciAoZmxvYXQgaSA9IDEuMDsgaSA8IDEwLjA7IGkrKyl7XHJcbiAgICAgICAgICB1di54ICs9IHVBbXBsaXR1ZGUgLyBpICogY29zKGkgKiB1RnJlcXVlbmN5WCAqIHV2LnkgKyB1VGltZSArIHVNb3VzZS54ICogMy4xNDE1OSk7XHJcbiAgICAgICAgICB1di55ICs9IHVBbXBsaXR1ZGUgLyBpICogY29zKGkgKiB1RnJlcXVlbmN5WSAqIHV2LnggKyB1VGltZSArIHVNb3VzZS55ICogMy4xNDE1OSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHZlYzIgZGlmZiA9ICh1dkNvb3JkIC0gdU1vdXNlKTtcclxuICAgICAgZmxvYXQgZGlzdCA9IGxlbmd0aChkaWZmKTtcclxuICAgICAgZmxvYXQgZmFsbG9mZiA9IGV4cCgtZGlzdCAqIDIwLjApO1xyXG4gICAgICBmbG9hdCByaXBwbGUgPSBzaW4oMTAuMCAqIGRpc3QgLSB1VGltZSAqIDIuMCkgKiAwLjAzO1xyXG4gICAgICB1diArPSAoZGlmZiAvIChkaXN0ICsgMC4wMDAxKSkgKiByaXBwbGUgKiBmYWxsb2ZmO1xyXG5cclxuICAgICAgdmVjMyBjb2xvciA9IHVCYXNlQ29sb3IgLyBhYnMoc2luKHVUaW1lIC0gdXYueSAtIHV2LngpKTtcclxuICAgICAgcmV0dXJuIHZlYzQoY29sb3IsIDEuMCk7XHJcbiAgfVxyXG5cclxuICB2b2lkIG1haW4oKSB7XHJcbiAgICAgIHZlYzQgY29sID0gdmVjNCgwLjApO1xyXG4gICAgICBpbnQgc2FtcGxlcyA9IDA7XHJcbiAgICAgIGZvciAoaW50IGkgPSAtMTsgaSA8PSAxOyBpKyspe1xyXG4gICAgICAgICAgZm9yIChpbnQgaiA9IC0xOyBqIDw9IDE7IGorKyl7XHJcbiAgICAgICAgICAgICAgdmVjMiBvZmZzZXQgPSB2ZWMyKGZsb2F0KGkpLCBmbG9hdChqKSkgKiAoMS4wIC8gbWluKHVSZXNvbHV0aW9uLngsIHVSZXNvbHV0aW9uLnkpKTtcclxuICAgICAgICAgICAgICBjb2wgKz0gcmVuZGVySW1hZ2UodlV2ICsgb2Zmc2V0KTtcclxuICAgICAgICAgICAgICBzYW1wbGVzKys7XHJcbiAgICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgZ2xfRnJhZ0NvbG9yID0gY29sIC8gZmxvYXQoc2FtcGxlcyk7XHJcbiAgfVxyXG5gO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYy1saXF1aWQtY2hyb21lLWJhY2tncm91bmQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9saXF1aWQtY2hyb21lLWJhY2tncm91bmQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2xpcXVpZC1jaHJvbWUtYmFja2dyb3VuZC5jb21wb25lbnQubGVzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBMaXF1aWRDaHJvbWVCYWNrZ3JvdW5kQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XHJcbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyBzdGF0aWM6IHRydWUgfSkgY29udGFpbmVyUmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XHJcblxyXG4gIC8qKiDln7rnoYDpopzoibLmlbDnu4QgW3IsIGcsIGJd77yIMC0x77yJICovXHJcbiAgQElucHV0KCkgbmNCYXNlQ29sb3I6IG51bWJlcltdID0gWzAuMSwgMC4xLCAwLjFdO1xyXG4gIC8qKiDliqjnlLvov5DooYzpgJ/luqbvvIgwLTXvvIkgKi9cclxuICBASW5wdXQoKSBuY1NwZWVkOiBudW1iZXIgPSAwLjI7XHJcbiAgLyoqIOazouWKqOW5heW6pu+8iDAuMS0x77yJICovXHJcbiAgQElucHV0KCkgbmNBbXBsaXR1ZGU6IG51bWJlciA9IDAuMztcclxuICAvKiogWOi9tOazoumikSAqL1xyXG4gIEBJbnB1dCgpIG5jRnJlcXVlbmN5WDogbnVtYmVyID0gMztcclxuICAvKiogWei9tOazoumikSAqL1xyXG4gIEBJbnB1dCgpIG5jRnJlcXVlbmN5WTogbnVtYmVyID0gMztcclxuICAvKiog5piv5ZCm5YWB6K646byg5qCHL+inpuWxj+S6pOS6kiAqL1xyXG4gIHByaXZhdGUgX2ludGVyYWN0aXZlOiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKSBzZXQgbmNJbnRlcmFjdGl2ZSh2YWx1ZTogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5faW50ZXJhY3RpdmUgPSB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBmYWxzZSAmJiB2YWx1ZSAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jSW50ZXJhY3RpdmUoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5faW50ZXJhY3RpdmU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlbmRlcmVyITogVEhSRUUuV2ViR0xSZW5kZXJlcjtcclxuICBwcml2YXRlIHNjZW5lITogVEhSRUUuU2NlbmU7XHJcbiAgcHJpdmF0ZSBjYW1lcmEhOiBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmE7XHJcbiAgcHJpdmF0ZSBtYXRlcmlhbCE6IFRIUkVFLlNoYWRlck1hdGVyaWFsO1xyXG4gIHByaXZhdGUgbWVzaCE6IFRIUkVFLk1lc2g7XHJcblxyXG4gIHByaXZhdGUgYW5pbWF0aW9uSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplT2JzZXJ2ZXIhOiBSZXNpemVPYnNlcnZlcjtcclxuICBwcml2YXRlIG1vdXNlID0gbmV3IFRIUkVFLlZlY3RvcjIoMCwgMCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbmdab25lOiBOZ1pvbmUpIHsgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHsgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmluaXRXZWJHTCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmNsZWFudXAoKTtcclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5tYXRlcmlhbCkgcmV0dXJuO1xyXG5cclxuICAgIGlmIChjaGFuZ2VzWyduY0Jhc2VDb2xvciddICYmIGNoYW5nZXNbJ25jQmFzZUNvbG9yJ10uY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VCYXNlQ29sb3InXS52YWx1ZS5mcm9tQXJyYXkodGhpcy5uY0Jhc2VDb2xvcik7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snbmNBbXBsaXR1ZGUnXSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VBbXBsaXR1ZGUnXS52YWx1ZSA9IHRoaXMubmNBbXBsaXR1ZGU7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snbmNGcmVxdWVuY3lYJ10gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1RnJlcXVlbmN5WCddLnZhbHVlID0gdGhpcy5uY0ZyZXF1ZW5jeVg7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snbmNGcmVxdWVuY3lZJ10gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1RnJlcXVlbmN5WSddLnZhbHVlID0gdGhpcy5uY0ZyZXF1ZW5jeVk7XHJcbiAgICB9XHJcbiAgICAvLyBuY0ludGVyYWN0aXZlIGhhbmRsZWQgdmlhIEhvc3RMaXN0ZW5lciBjaGVja1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbml0V2ViR0woKTogdm9pZCB7XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG5cclxuICAgIHRoaXMucmVuZGVyZXIgPSBuZXcgVEhSRUUuV2ViR0xSZW5kZXJlcih7IGFudGlhbGlhczogdHJ1ZSwgYWxwaGE6IHRydWUgfSk7XHJcbiAgICAvLyDljp/niYgganN4IOa4hemZpOminOiJsuS4uueZveiJslxyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRDbGVhckNvbG9yKDB4ZmZmZmZmLCAxKTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxLCAyKSk7XHJcblxyXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG5cclxuICAgIC8vIOato+S6pOebuOacuua4suafk+WFqOWxjyBQbGFuZVxyXG4gICAgdGhpcy5jYW1lcmEgPSBuZXcgVEhSRUUuT3J0aG9ncmFwaGljQ2FtZXJhKC0xLCAxLCAxLCAtMSwgMC4xLCAxMCk7XHJcbiAgICB0aGlzLmNhbWVyYS5wb3NpdGlvbi56ID0gMTtcclxuXHJcbiAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5KDIsIDIpO1xyXG5cclxuICAgIHRoaXMubWF0ZXJpYWwgPSBuZXcgVEhSRUUuU2hhZGVyTWF0ZXJpYWwoe1xyXG4gICAgICB2ZXJ0ZXhTaGFkZXIsXHJcbiAgICAgIGZyYWdtZW50U2hhZGVyLFxyXG4gICAgICB1bmlmb3Jtczoge1xyXG4gICAgICAgIHVUaW1lOiB7IHZhbHVlOiAwIH0sXHJcbiAgICAgICAgdVJlc29sdXRpb246IHsgdmFsdWU6IG5ldyBUSFJFRS5WZWN0b3IzKCkgfSxcclxuICAgICAgICB1QmFzZUNvbG9yOiB7IHZhbHVlOiBuZXcgVEhSRUUuVmVjdG9yMygpLmZyb21BcnJheSh0aGlzLm5jQmFzZUNvbG9yKSB9LFxyXG4gICAgICAgIHVBbXBsaXR1ZGU6IHsgdmFsdWU6IHRoaXMubmNBbXBsaXR1ZGUgfSxcclxuICAgICAgICB1RnJlcXVlbmN5WDogeyB2YWx1ZTogdGhpcy5uY0ZyZXF1ZW5jeVggfSxcclxuICAgICAgICB1RnJlcXVlbmN5WTogeyB2YWx1ZTogdGhpcy5uY0ZyZXF1ZW5jeVkgfSxcclxuICAgICAgICB1TW91c2U6IHsgdmFsdWU6IHRoaXMubW91c2UgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLm1lc2ggPSBuZXcgVEhSRUUuTWVzaChnZW9tZXRyeSwgdGhpcy5tYXRlcmlhbCk7XHJcbiAgICB0aGlzLnNjZW5lLmFkZCh0aGlzLm1lc2gpO1xyXG5cclxuICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5yZXNpemUoKSk7XHJcbiAgICB0aGlzLnJlc2l6ZU9ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKTtcclxuXHJcbiAgICB0aGlzLnJlc2l6ZSgpO1xyXG5cclxuICAgIC8vIEludGVyYWN0aW9uIGhhbmRsZWQgdmlhIEhvc3RMaXN0ZW5lclxyXG5cclxuICAgIC8vIOaPkOWNh+aAp+iDve+8jOS4jeiuqSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUg6Kem5Y+RIEFuZ3VsYXIg5Y+Y5pu05qOA5rWLXHJcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgIHRoaXMudXBkYXRlKDApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2l6ZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5jb250YWluZXJSZWYgfHwgIXRoaXMucmVuZGVyZXIpIHJldHVybjtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCB3aWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aDtcclxuICAgIGNvbnN0IGhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVJlc29sdXRpb24nXS52YWx1ZS5zZXQod2lkdGgsIGhlaWdodCwgd2lkdGggLyBoZWlnaHQpO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignbW91c2Vtb3ZlJywgWyckZXZlbnQnXSlcclxuICBvbk1vdXNlTW92ZShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm5jSW50ZXJhY3RpdmUgfHwgIXRoaXMuY29udGFpbmVyUmVmKSByZXR1cm47XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgY29uc3QgcmVjdCA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGNvbnN0IHggPSAoZXZlbnQuY2xpZW50WCAtIHJlY3QubGVmdCkgLyByZWN0LndpZHRoO1xyXG4gICAgY29uc3QgeSA9IDEgLSAoZXZlbnQuY2xpZW50WSAtIHJlY3QudG9wKSAvIHJlY3QuaGVpZ2h0O1xyXG5cclxuICAgIHRoaXMubW91c2Uuc2V0KHgsIHkpO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcigndG91Y2htb3ZlJywgWyckZXZlbnQnXSlcclxuICBvblRvdWNoTW92ZShldmVudDogVG91Y2hFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm5jSW50ZXJhY3RpdmUgfHwgIXRoaXMuY29udGFpbmVyUmVmKSByZXR1cm47XHJcbiAgICBpZiAoZXZlbnQudG91Y2hlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IHRvdWNoID0gZXZlbnQudG91Y2hlc1swXTtcclxuICAgICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICAgY29uc3QgcmVjdCA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgICAgY29uc3QgeCA9ICh0b3VjaC5jbGllbnRYIC0gcmVjdC5sZWZ0KSAvIHJlY3Qud2lkdGg7XHJcbiAgICAgIGNvbnN0IHkgPSAxIC0gKHRvdWNoLmNsaWVudFkgLSByZWN0LnRvcCkgLyByZWN0LmhlaWdodDtcclxuICAgICAgdGhpcy5tb3VzZS5zZXQoeCwgeSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuXHJcblxyXG4gIHByaXZhdGUgdXBkYXRlID0gKHQ6IG51bWJlcikgPT4ge1xyXG4gICAgdGhpcy5hbmltYXRpb25JZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnVwZGF0ZSk7XHJcblxyXG4gICAgaWYgKHRoaXMubWF0ZXJpYWwpIHtcclxuICAgICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVRpbWUnXS52YWx1ZSA9IHQgKiAwLjAwMSAqIHRoaXMubmNTcGVlZDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcih0aGlzLnNjZW5lLCB0aGlzLmNhbWVyYSk7XHJcbiAgfTtcclxuXHJcbiAgcHJpdmF0ZSBjbGVhbnVwKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYW5pbWF0aW9uSWQgIT09IG51bGwpIHtcclxuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRpb25JZCk7XHJcbiAgICAgIHRoaXMuYW5pbWF0aW9uSWQgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnJlc2l6ZU9ic2VydmVyKSB7XHJcbiAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xyXG4gICAgfVxyXG5cclxuXHJcblxyXG4gICAgaWYgKHRoaXMubWVzaCkge1xyXG4gICAgICB0aGlzLm1lc2guZ2VvbWV0cnkuZGlzcG9zZSgpO1xyXG4gICAgICAodGhpcy5tZXNoLm1hdGVyaWFsIGFzIFRIUkVFLk1hdGVyaWFsKS5kaXNwb3NlKCk7XHJcbiAgICAgIHRoaXMuc2NlbmUucmVtb3ZlKHRoaXMubWVzaCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMucmVuZGVyZXIpIHtcclxuICAgICAgdGhpcy5yZW5kZXJlci5kaXNwb3NlKCk7XHJcbiAgICAgIGNvbnN0IGRvbSA9IHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudDtcclxuICAgICAgaWYgKGRvbSAmJiBkb20ucGFyZW50RWxlbWVudCkge1xyXG4gICAgICAgIGRvbS5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKGRvbSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5yZW5kZXJlci5nZXRDb250ZXh0KCk/LmdldEV4dGVuc2lvbignV0VCR0xfbG9zZV9jb250ZXh0Jyk/Lmxvc2VDb250ZXh0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4iLCI8ZGl2ICNjb250YWluZXIgY2xhc3M9XCJuYy1saXF1aWQtY2hyb21lLWNhbnZhcy1jb250YWluZXJcIj48L2Rpdj5cclxuPGRpdiBjbGFzcz1cIm5jLWNvbnRlbnQtd3JhcHBlclwiPlxyXG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG48L2Rpdj4iXX0=