UNPKG

ng-cw-v12

Version:

Angular UI Component Library

517 lines (480 loc) 68.4 kB
import { Component, ViewChild, Input, HostListener } from '@angular/core'; import { Scene, OrthographicCamera, WebGLRenderer, PlaneGeometry, Mesh, ShaderMaterial, Vector3, Vector2, Clock } from 'three'; import * as i0 from "@angular/core"; const vertexShader = ` precision highp float; void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const fragmentShader = ` precision highp float; uniform float iTime; uniform vec3 iResolution; uniform float animationSpeed; uniform bool enableTop; uniform bool enableMiddle; uniform bool enableBottom; uniform int topLineCount; uniform int middleLineCount; uniform int bottomLineCount; uniform float topLineDistance; uniform float middleLineDistance; uniform float bottomLineDistance; uniform vec3 topWavePosition; uniform vec3 middleWavePosition; uniform vec3 bottomWavePosition; uniform vec2 iMouse; uniform bool interactive; uniform float bendRadius; uniform float bendStrength; uniform float bendInfluence; uniform bool parallax; uniform float parallaxStrength; uniform vec2 parallaxOffset; uniform vec3 lineGradient[8]; uniform int lineGradientCount; const vec3 BLACK = vec3(0.0); const vec3 PINK = vec3(233.0, 71.0, 245.0) / 255.0; const vec3 BLUE = vec3(47.0, 75.0, 162.0) / 255.0; mat2 rotate(float r) { return mat2(cos(r), sin(r), -sin(r), cos(r)); } vec3 background_color(vec2 uv) { vec3 col = vec3(0.0); float y = sin(uv.x - 0.2) * 0.3 - 0.1; float m = uv.y - y; col += mix(BLUE, BLACK, smoothstep(0.0, 1.0, abs(m))); col += mix(PINK, BLACK, smoothstep(0.0, 1.0, abs(m - 0.8))); return col * 0.5; } vec3 getLineColor(float t, vec3 baseColor) { if (lineGradientCount <= 0) { return baseColor; } vec3 gradientColor; if (lineGradientCount == 1) { gradientColor = lineGradient[0]; } else { float clampedT = clamp(t, 0.0, 0.9999); float scaled = clampedT * float(lineGradientCount - 1); int idx = int(floor(scaled)); float f = fract(scaled); int idx2 = min(idx + 1, lineGradientCount - 1); vec3 c1 = lineGradient[idx]; vec3 c2 = lineGradient[idx2]; gradientColor = mix(c1, c2, f); } return gradientColor * 0.5; } float wave(vec2 uv, float offset, vec2 screenUv, vec2 mouseUv, bool shouldBend) { float time = iTime * animationSpeed; float x_offset = offset; float x_movement = time * 0.1; float amp = sin(offset + time * 0.2) * 0.3; float y = sin(uv.x + x_offset + x_movement) * amp; if (shouldBend) { vec2 d = screenUv - mouseUv; float influence = exp(-dot(d, d) * bendRadius); // radial falloff around cursor float bendOffset = (mouseUv.y - screenUv.y) * influence * bendStrength * bendInfluence; y += bendOffset; } float m = uv.y - y; return 0.0175 / max(abs(m) + 0.01, 1e-3) + 0.01; } void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 baseUv = (2.0 * fragCoord - iResolution.xy) / iResolution.y; baseUv.y *= -1.0; if (parallax) { baseUv += parallaxOffset; } vec3 col = vec3(0.0); vec3 b = lineGradientCount > 0 ? vec3(0.0) : background_color(baseUv); vec2 mouseUv = vec2(0.0); if (interactive) { mouseUv = (2.0 * iMouse - iResolution.xy) / iResolution.y; mouseUv.y *= -1.0; } if (enableBottom) { for (int i = 0; i < 20; ++i) { // Fixed limit for Loop if(i >= bottomLineCount) break; float fi = float(i); float t = fi / max(float(bottomLineCount - 1), 1.0); vec3 lineCol = getLineColor(t, b); float angle = bottomWavePosition.z * log(length(baseUv) + 1.0); vec2 ruv = baseUv * rotate(angle); col += lineCol * wave( ruv + vec2(bottomLineDistance * fi + bottomWavePosition.x, bottomWavePosition.y), 1.5 + 0.2 * fi, baseUv, mouseUv, interactive ) * 0.2; } } if (enableMiddle) { for (int i = 0; i < 20; ++i) { if(i >= middleLineCount) break; float fi = float(i); float t = fi / max(float(middleLineCount - 1), 1.0); vec3 lineCol = getLineColor(t, b); float angle = middleWavePosition.z * log(length(baseUv) + 1.0); vec2 ruv = baseUv * rotate(angle); col += lineCol * wave( ruv + vec2(middleLineDistance * fi + middleWavePosition.x, middleWavePosition.y), 2.0 + 0.15 * fi, baseUv, mouseUv, interactive ); } } if (enableTop) { for (int i = 0; i < 20; ++i) { if(i >= topLineCount) break; float fi = float(i); float t = fi / max(float(topLineCount - 1), 1.0); vec3 lineCol = getLineColor(t, b); float angle = topWavePosition.z * log(length(baseUv) + 1.0); vec2 ruv = baseUv * rotate(angle); ruv.x *= -1.0; col += lineCol * wave( ruv + vec2(topLineDistance * fi + topWavePosition.x, topWavePosition.y), 1.0 + 0.2 * fi, baseUv, mouseUv, interactive ) * 0.1; } } fragColor = vec4(col, 1.0); } void main() { vec4 color = vec4(0.0); mainImage(color, gl_FragCoord.xy); gl_FragColor = color; } `; const MAX_GRADIENT_STOPS = 8; function hexToVec3(hex) { let value = hex.trim(); if (value.startsWith('#')) { value = value.slice(1); } let r = 255; let g = 255; let b = 255; if (value.length === 3) { r = parseInt(value[0] + value[0], 16); g = parseInt(value[1] + value[1], 16); b = parseInt(value[2] + value[2], 16); } else if (value.length === 6) { r = parseInt(value.slice(0, 2), 16); g = parseInt(value.slice(2, 4), 16); b = parseInt(value.slice(4, 6), 16); } return new Vector3(r / 255, g / 255, b / 255); } export class FloatingLinesBackgroundComponent { constructor(ngZone) { this.ngZone = ngZone; /** 用于线条渐变着色的十六进制颜色字符串数组(最多 8 种颜色) */ this.ncLinesGradient = []; /** 显示哪些波形层。可以单独切换显示/隐藏各个波形 */ this.ncEnabledWaves = ['top', 'middle', 'bottom']; /** 每波形的线条数。单个数值适用于所有波形,也可以使用数组进行逐波形控制(1-20) */ this.ncLineCount = 6; /** 行间距。单个数值适用于所有波形,或使用数组进行逐个波形的控制(1-100) */ this.ncLineDistance = 5; /** 顶部波浪的位置和旋转参数 { x, y, rotate } */ this.ncTopWavePosition = { x: 10.0, y: 0.5, rotate: -0.4 }; /** 中部波浪的位置和旋转参数 { x, y, rotate } */ this.ncMiddleWavePosition = { x: 5.0, y: 0.0, rotate: 0.2 }; /** 底部波浪的位置和旋转参数 { x, y, rotate } */ this.ncBottomWavePosition = { x: 2.0, y: -0.7, rotate: -1 }; /** 波浪动画的速度倍增器 */ this.ncAnimationSpeed = 1; /** 线条是否会对鼠标/指针移动做出反应 */ this._interactive = true; /** 受鼠标交互影响区域的半径(1-30) */ this.ncBendRadius = 5.0; /** 与鼠标交互时弯曲效应的强度(-15-15) */ this.ncBendStrength = -0.5; /** 鼠标移动跟踪的平滑因子(0-1) */ this.ncMouseDamping = 0.05; /** 启用鼠标移动时的视差效果 */ this._parallax = true; /** 视差效应的强度 */ this.ncParallaxStrength = 0.2; /** CSS mix-blend-mode 应用于canvas元素 */ this.ncMixBlendMode = 'unset'; this.clock = new Clock(); this.rafId = 0; this.targetMouse = new Vector2(-1000, -1000); this.currentMouse = new Vector2(-1000, -1000); this.targetInfluence = 0; this.currentInfluence = 0; this.targetParallax = new Vector2(0, 0); this.currentParallax = new Vector2(0, 0); this.uniforms = {}; } set ncInteractive(val) { this._interactive = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncInteractive() { return this._interactive; } set ncParallax(val) { this._parallax = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncParallax() { return this._parallax; } ngOnInit() { } ngAfterViewInit() { this.initThree(); this.setupResizeObserver(); this.ngZone.runOutsideAngular(() => { this.animate(); }); } ngOnDestroy() { if (this.rafId) cancelAnimationFrame(this.rafId); if (this.resizeObserver) this.resizeObserver.disconnect(); this.cleanupThree(); } ngOnChanges(changes) { if (this.material) { this.updateUniforms(); } } initThree() { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; const el = this.containerRef.nativeElement; this.scene = new Scene(); this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1); this.camera.position.z = 1; this.renderer = new WebGLRenderer({ antialias: true, alpha: false }); this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); this.renderer.setSize(el.clientWidth || 1, el.clientHeight || 1, false); el.appendChild(this.renderer.domElement); this.uniforms = { iTime: { value: 0 }, iResolution: { value: new Vector3(el.clientWidth, el.clientHeight, 1) }, animationSpeed: { value: this.ncAnimationSpeed }, enableTop: { value: this.ncEnabledWaves.includes('top') }, enableMiddle: { value: this.ncEnabledWaves.includes('middle') }, enableBottom: { value: this.ncEnabledWaves.includes('bottom') }, topLineCount: { value: this.getLineCount('top') }, middleLineCount: { value: this.getLineCount('middle') }, bottomLineCount: { value: this.getLineCount('bottom') }, topLineDistance: { value: this.getLineDistance('top') * 0.01 }, middleLineDistance: { value: this.getLineDistance('middle') * 0.01 }, bottomLineDistance: { value: this.getLineDistance('bottom') * 0.01 }, topWavePosition: { value: new Vector3((_b = (_a = this.ncTopWavePosition) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 10.0, (_d = (_c = this.ncTopWavePosition) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0.5, (_f = (_e = this.ncTopWavePosition) === null || _e === void 0 ? void 0 : _e.rotate) !== null && _f !== void 0 ? _f : -0.4) }, middleWavePosition: { value: new Vector3((_h = (_g = this.ncMiddleWavePosition) === null || _g === void 0 ? void 0 : _g.x) !== null && _h !== void 0 ? _h : 5.0, (_k = (_j = this.ncMiddleWavePosition) === null || _j === void 0 ? void 0 : _j.y) !== null && _k !== void 0 ? _k : 0.0, (_m = (_l = this.ncMiddleWavePosition) === null || _l === void 0 ? void 0 : _l.rotate) !== null && _m !== void 0 ? _m : 0.2) }, bottomWavePosition: { value: new Vector3((_p = (_o = this.ncBottomWavePosition) === null || _o === void 0 ? void 0 : _o.x) !== null && _p !== void 0 ? _p : 2.0, (_r = (_q = this.ncBottomWavePosition) === null || _q === void 0 ? void 0 : _q.y) !== null && _r !== void 0 ? _r : -0.7, (_t = (_s = this.ncBottomWavePosition) === null || _s === void 0 ? void 0 : _s.rotate) !== null && _t !== void 0 ? _t : -1) }, iMouse: { value: new Vector2(-1000, -1000) }, interactive: { value: this.ncInteractive }, bendRadius: { value: this.ncBendRadius }, bendStrength: { value: this.ncBendStrength }, bendInfluence: { value: 0 }, parallax: { value: this.ncParallax }, parallaxStrength: { value: this.ncParallaxStrength }, parallaxOffset: { value: new Vector2(0, 0) }, lineGradient: { value: Array.from({ length: MAX_GRADIENT_STOPS }, () => new Vector3(1, 1, 1)) }, lineGradientCount: { value: 0 } }; if (this.ncLinesGradient && this.ncLinesGradient.length > 0) { const stops = this.ncLinesGradient.slice(0, MAX_GRADIENT_STOPS); this.uniforms.lineGradientCount.value = stops.length; stops.forEach((hex, i) => { const color = hexToVec3(hex); this.uniforms.lineGradient.value[i].copy(color); }); } this.material = new ShaderMaterial({ uniforms: this.uniforms, vertexShader, fragmentShader }); this.geometry = new PlaneGeometry(2, 2); this.mesh = new Mesh(this.geometry, this.material); this.scene.add(this.mesh); } updateUniforms() { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; this.uniforms.animationSpeed.value = this.ncAnimationSpeed; this.uniforms.enableTop.value = this.ncEnabledWaves.includes('top'); this.uniforms.enableMiddle.value = this.ncEnabledWaves.includes('middle'); this.uniforms.enableBottom.value = this.ncEnabledWaves.includes('bottom'); this.uniforms.topLineCount.value = this.getLineCount('top'); this.uniforms.middleLineCount.value = this.getLineCount('middle'); this.uniforms.bottomLineCount.value = this.getLineCount('bottom'); this.uniforms.topLineDistance.value = this.getLineDistance('top') * 0.01; this.uniforms.middleLineDistance.value = this.getLineDistance('middle') * 0.01; this.uniforms.bottomLineDistance.value = this.getLineDistance('bottom') * 0.01; this.uniforms.topWavePosition.value.set((_b = (_a = this.ncTopWavePosition) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 10.0, (_d = (_c = this.ncTopWavePosition) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0.5, (_f = (_e = this.ncTopWavePosition) === null || _e === void 0 ? void 0 : _e.rotate) !== null && _f !== void 0 ? _f : -0.4); this.uniforms.middleWavePosition.value.set((_h = (_g = this.ncMiddleWavePosition) === null || _g === void 0 ? void 0 : _g.x) !== null && _h !== void 0 ? _h : 5.0, (_k = (_j = this.ncMiddleWavePosition) === null || _j === void 0 ? void 0 : _j.y) !== null && _k !== void 0 ? _k : 0.0, (_m = (_l = this.ncMiddleWavePosition) === null || _l === void 0 ? void 0 : _l.rotate) !== null && _m !== void 0 ? _m : 0.2); this.uniforms.bottomWavePosition.value.set((_p = (_o = this.ncBottomWavePosition) === null || _o === void 0 ? void 0 : _o.x) !== null && _p !== void 0 ? _p : 2.0, (_r = (_q = this.ncBottomWavePosition) === null || _q === void 0 ? void 0 : _q.y) !== null && _r !== void 0 ? _r : -0.7, (_t = (_s = this.ncBottomWavePosition) === null || _s === void 0 ? void 0 : _s.rotate) !== null && _t !== void 0 ? _t : -1); this.uniforms.interactive.value = this.ncInteractive; this.uniforms.bendRadius.value = this.ncBendRadius; this.uniforms.bendStrength.value = this.ncBendStrength; this.uniforms.parallax.value = this.ncParallax; this.uniforms.parallaxStrength.value = this.ncParallaxStrength; if (this.ncLinesGradient && this.ncLinesGradient.length > 0) { const stops = this.ncLinesGradient.slice(0, MAX_GRADIENT_STOPS); this.uniforms.lineGradientCount.value = stops.length; stops.forEach((hex, i) => { const color = hexToVec3(hex); this.uniforms.lineGradient.value[i].copy(color); }); } else { this.uniforms.lineGradientCount.value = 0; } } getLineCount(waveType) { var _a; if (typeof this.ncLineCount === 'number') return this.ncLineCount; if (!this.ncEnabledWaves.includes(waveType)) return 0; const index = this.ncEnabledWaves.indexOf(waveType); return (_a = this.ncLineCount[index]) !== null && _a !== void 0 ? _a : 0; } getLineDistance(waveType) { var _a; if (typeof this.ncLineDistance === 'number') return this.ncLineDistance; if (!this.ncEnabledWaves.includes(waveType)) return 0.1; const index = this.ncEnabledWaves.indexOf(waveType); return (_a = this.ncLineDistance[index]) !== null && _a !== void 0 ? _a : 0.1; } setupResizeObserver() { this.resizeObserver = new ResizeObserver(() => { const el = this.containerRef.nativeElement; const width = el.clientWidth || 1; const height = el.clientHeight || 1; this.ngZone.runOutsideAngular(() => { this.renderer.setSize(width, height, false); const canvasWidth = this.renderer.domElement.width; const canvasHeight = this.renderer.domElement.height; this.uniforms.iResolution.value.set(canvasWidth, canvasHeight, 1); }); }); this.resizeObserver.observe(this.containerRef.nativeElement); } onPointerMove(event) { if (!this.ncInteractive && !this.ncParallax) return; const rect = this.renderer.domElement.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; const dpr = this.renderer.getPixelRatio(); if (this.ncInteractive) { this.targetMouse.set(x * dpr, (rect.height - y) * dpr); this.targetInfluence = 1.0; } if (this.ncParallax) { const centerX = rect.width / 2; const centerY = rect.height / 2; const offsetX = (x - centerX) / rect.width; const offsetY = -(y - centerY) / rect.height; this.targetParallax.set(offsetX * this.ncParallaxStrength, offsetY * this.ncParallaxStrength); } } onPointerLeave() { this.targetInfluence = 0.0; } animate() { this.rafId = requestAnimationFrame(() => this.animate()); this.render(); } render() { this.uniforms.iTime.value = this.clock.getElapsedTime(); if (this.ncInteractive) { this.currentMouse.lerp(this.targetMouse, this.ncMouseDamping); this.uniforms.iMouse.value.copy(this.currentMouse); this.currentInfluence += (this.targetInfluence - this.currentInfluence) * this.ncMouseDamping; this.uniforms.bendInfluence.value = this.currentInfluence; } if (this.ncParallax) { this.currentParallax.lerp(this.targetParallax, this.ncMouseDamping); this.uniforms.parallaxOffset.value.copy(this.currentParallax); } this.renderer.render(this.scene, this.camera); } cleanupThree() { if (this.geometry) this.geometry.dispose(); if (this.material) this.material.dispose(); if (this.renderer) { this.renderer.dispose(); this.renderer.domElement.remove(); } } } FloatingLinesBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: FloatingLinesBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); FloatingLinesBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: FloatingLinesBackgroundComponent, selector: "nc-floating-lines-background", inputs: { ncLinesGradient: "ncLinesGradient", ncEnabledWaves: "ncEnabledWaves", ncLineCount: "ncLineCount", ncLineDistance: "ncLineDistance", ncTopWavePosition: "ncTopWavePosition", ncMiddleWavePosition: "ncMiddleWavePosition", ncBottomWavePosition: "ncBottomWavePosition", ncAnimationSpeed: "ncAnimationSpeed", ncInteractive: "ncInteractive", ncBendRadius: "ncBendRadius", ncBendStrength: "ncBendStrength", ncMouseDamping: "ncMouseDamping", ncParallax: "ncParallax", ncParallaxStrength: "ncParallaxStrength", ncMixBlendMode: "ncMixBlendMode" }, host: { listeners: { "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-floating-lines-canvas-container\" [style.mix-blend-mode]=\"ncMixBlendMode\"></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-floating-lines-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: FloatingLinesBackgroundComponent, decorators: [{ type: Component, args: [{ selector: 'nc-floating-lines-background', templateUrl: './floating-lines-background.component.html', styleUrls: ['./floating-lines-background.component.less'] }] }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{ type: ViewChild, args: ['container', { static: true }] }], ncLinesGradient: [{ type: Input }], ncEnabledWaves: [{ type: Input }], ncLineCount: [{ type: Input }], ncLineDistance: [{ type: Input }], ncTopWavePosition: [{ type: Input }], ncMiddleWavePosition: [{ type: Input }], ncBottomWavePosition: [{ type: Input }], ncAnimationSpeed: [{ type: Input }], ncInteractive: [{ type: Input }], ncBendRadius: [{ type: Input }], ncBendStrength: [{ type: Input }], ncMouseDamping: [{ type: Input }], ncParallax: [{ type: Input }], ncParallaxStrength: [{ type: Input }], ncMixBlendMode: [{ type: Input }], onPointerMove: [{ type: HostListener, args: ['pointermove', ['$event']] }], onPointerLeave: [{ type: HostListener, args: ['pointerleave'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2Zsb2F0aW5nLWxpbmVzLWJhY2tncm91bmQvZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2Zsb2F0aW5nLWxpbmVzLWJhY2tncm91bmQvZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUlULFNBQVMsRUFFVCxLQUFLLEVBR0wsWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxLQUFLLEVBQ0wsa0JBQWtCLEVBQ2xCLGFBQWEsRUFDYixhQUFhLEVBQ2IsSUFBSSxFQUNKLGNBQWMsRUFDZCxPQUFPLEVBQ1AsT0FBTyxFQUNQLEtBQUssRUFDTixNQUFNLE9BQU8sQ0FBQzs7QUFTZixNQUFNLFlBQVksR0FBRzs7Ozs7O0NBTXBCLENBQUM7QUFFRixNQUFNLGNBQWMsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBdUx0QixDQUFDO0FBRUYsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUM7QUFFN0IsU0FBUyxTQUFTLENBQUMsR0FBVztJQUM1QixJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FB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LFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDhCQUE4QjtvQkFDeEMsV0FBVyxFQUFFLDRDQUE0QztvQkFDekQsU0FBUyxFQUFFLENBQUMsNENBQTRDLENBQUM7aUJBQzFEOzZGQUUyQyxZQUFZO3NCQUFyRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRy9CLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsY0FBYztzQkFBdEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFFRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUlGLGFBQWE7c0JBRGhCLEtBQUs7Z0JBUUcsWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBSUYsVUFBVTtzQkFEYixLQUFLO2dCQVFHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQTRNTixhQUFhO3NCQURaLFlBQVk7dUJBQUMsYUFBYSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQXdCdkMsY0FBYztzQkFEYixZQUFZO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBPbkluaXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgVmlld0NoaWxkLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgSW5wdXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIFNpbXBsZUNoYW5nZXMsXHJcbiAgSG9zdExpc3RlbmVyLFxyXG4gIE5nWm9uZVxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIFNjZW5lLFxyXG4gIE9ydGhvZ3JhcGhpY0NhbWVyYSxcclxuICBXZWJHTFJlbmRlcmVyLFxyXG4gIFBsYW5lR2VvbWV0cnksXHJcbiAgTWVzaCxcclxuICBTaGFkZXJNYXRlcmlhbCxcclxuICBWZWN0b3IzLFxyXG4gIFZlY3RvcjIsXHJcbiAgQ2xvY2tcclxufSBmcm9tICd0aHJlZSc7XHJcblxyXG5leHBvcnQgdHlwZSBOY1dhdmVUeXBlID0gJ3RvcCcgfCAnbWlkZGxlJyB8ICdib3R0b20nO1xyXG5leHBvcnQgaW50ZXJmYWNlIE5jV2F2ZVBvc2l0aW9uIHtcclxuICB4PzogbnVtYmVyO1xyXG4gIHk/OiBudW1iZXI7XHJcbiAgcm90YXRlPzogbnVtYmVyO1xyXG59XHJcblxyXG5jb25zdCB2ZXJ0ZXhTaGFkZXIgPSBgXHJcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcbnZvaWQgbWFpbigpIHtcclxuICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb25NYXRyaXggKiBtb2RlbFZpZXdNYXRyaXggKiB2ZWM0KHBvc2l0aW9uLCAxLjApO1xyXG59XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnbWVudFNoYWRlciA9IGBcclxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xyXG5cclxudW5pZm9ybSBmbG9hdCBpVGltZTtcclxudW5pZm9ybSB2ZWMzICBpUmVzb2x1dGlvbjtcclxudW5pZm9ybSBmbG9hdCBhbmltYXRpb25TcGVlZDtcclxuXHJcbnVuaWZvcm0gYm9vbCBlbmFibGVUb3A7XHJcbnVuaWZvcm0gYm9vbCBlbmFibGVNaWRkbGU7XHJcbnVuaWZvcm0gYm9vbCBlbmFibGVCb3R0b207XHJcblxyXG51bmlmb3JtIGludCB0b3BMaW5lQ291bnQ7XHJcbnVuaWZvcm0gaW50IG1pZGRsZUxpbmVDb3VudDtcclxudW5pZm9ybSBpbnQgYm90dG9tTGluZUNvdW50O1xyXG5cclxudW5pZm9ybSBmbG9hdCB0b3BMaW5lRGlzdGFuY2U7XHJcbnVuaWZvcm0gZmxvYXQgbWlkZGxlTGluZURpc3RhbmNlO1xyXG51bmlmb3JtIGZsb2F0IGJvdHRvbUxpbmVEaXN0YW5jZTtcclxuXHJcbnVuaWZvcm0gdmVjMyB0b3BXYXZlUG9zaXRpb247XHJcbnVuaWZvcm0gdmVjMyBtaWRkbGVXYXZlUG9zaXRpb247XHJcbnVuaWZvcm0gdmVjMyBib3R0b21XYXZlUG9zaXRpb247XHJcblxyXG51bmlmb3JtIHZlYzIgaU1vdXNlO1xyXG51bmlmb3JtIGJvb2wgaW50ZXJhY3RpdmU7XHJcbnVuaWZvcm0gZmxvYXQgYmVuZFJhZGl1cztcclxudW5pZm9ybSBmbG9hdCBiZW5kU3RyZW5ndGg7XHJcbnVuaWZvcm0gZmxvYXQgYmVuZEluZmx1ZW5jZTtcclxuXHJcbnVuaWZvcm0gYm9vbCBwYXJhbGxheDtcclxudW5pZm9ybSBmbG9hdCBwYXJhbGxheFN0cmVuZ3RoO1xyXG51bmlmb3JtIHZlYzIgcGFyYWxsYXhPZmZzZXQ7XHJcblxyXG51bmlmb3JtIHZlYzMgbGluZUdyYWRpZW50WzhdO1xyXG51bmlmb3JtIGludCBsaW5lR3JhZGllbnRDb3VudDtcclxuXHJcbmNvbnN0IHZlYzMgQkxBQ0sgPSB2ZWMzKDAuMCk7XHJcbmNvbnN0IHZlYzMgUElOSyAgPSB2ZWMzKDIzMy4wLCA3MS4wLCAyNDUuMCkgLyAyNTUuMDtcclxuY29uc3QgdmVjMyBCTFVFICA9IHZlYzMoNDcuMCwgIDc1LjAsIDE2Mi4wKSAvIDI1NS4wO1xyXG5cclxubWF0MiByb3RhdGUoZmxvYXQgcikge1xyXG4gIHJldHVybiBtYXQyKGNvcyhyKSwgc2luKHIpLCAtc2luKHIpLCBjb3MocikpO1xyXG59XHJcblxyXG52ZWMzIGJhY2tncm91bmRfY29sb3IodmVjMiB1dikge1xyXG4gIHZlYzMgY29sID0gdmVjMygwLjApO1xyXG5cclxuICBmbG9hdCB5ID0gc2luKHV2LnggLSAwLjIpICogMC4zIC0gMC4xO1xyXG4gIGZsb2F0IG0gPSB1di55IC0geTtcclxuXHJcbiAgY29sICs9IG1peChCTFVFLCBCTEFDSywgc21vb3Roc3RlcCgwLjAsIDEuMCwgYWJzKG0pKSk7XHJcbiAgY29sICs9IG1peChQSU5LLCBCTEFDSywgc21vb3Roc3RlcCgwLjAsIDEuMCwgYWJzKG0gLSAwLjgpKSk7XHJcbiAgcmV0dXJuIGNvbCAqIDAuNTtcclxufVxyXG5cclxudmVjMyBnZXRMaW5lQ29sb3IoZmxvYXQgdCwgdmVjMyBiYXNlQ29sb3IpIHtcclxuICBpZiAobGluZUdyYWRpZW50Q291bnQgPD0gMCkge1xyXG4gICAgcmV0dXJuIGJhc2VDb2xvcjtcclxuICB9XHJcblxyXG4gIHZlYzMgZ3JhZGllbnRDb2xvcjtcclxuICBcclxuICBpZiAobGluZUdyYWRpZW50Q291bnQgPT0gMSkge1xyXG4gICAgZ3JhZGllbnRDb2xvciA9IGxpbmVHcmFkaWVudFswXTtcclxuICB9IGVsc2Uge1xyXG4gICAgZmxvYXQgY2xhbXBlZFQgPSBjbGFtcCh0LCAwLjAsIDAuOTk5OSk7XHJcbiAgICBmbG9hdCBzY2FsZWQgPSBjbGFtcGVkVCAqIGZsb2F0KGxpbmVHcmFkaWVudENvdW50IC0gMSk7XHJcbiAgICBpbnQgaWR4ID0gaW50KGZsb29yKHNjYWxlZCkpO1xyXG4gICAgZmxvYXQgZiA9IGZyYWN0KHNjYWxlZCk7XHJcbiAgICBpbnQgaWR4MiA9IG1pbihpZHggKyAxLCBsaW5lR3JhZGllbnRDb3VudCAtIDEpO1xyXG5cclxuICAgIHZlYzMgYzEgPSBsaW5lR3JhZGllbnRbaWR4XTtcclxuICAgIHZlYzMgYzIgPSBsaW5lR3JhZGllbnRbaWR4Ml07XHJcbiAgICBcclxuICAgIGdyYWRpZW50Q29sb3IgPSBtaXgoYzEsIGMyLCBmKTtcclxuICB9XHJcbiAgXHJcbiAgcmV0dXJuIGdyYWRpZW50Q29sb3IgKiAwLjU7XHJcbn1cclxuXHJcbmZsb2F0IHdhdmUodmVjMiB1diwgZmxvYXQgb2Zmc2V0LCB2ZWMyIHNjcmVlblV2LCB2ZWMyIG1vdXNlVXYsIGJvb2wgc2hvdWxkQmVuZCkge1xyXG4gIGZsb2F0IHRpbWUgPSBpVGltZSAqIGFuaW1hdGlvblNwZWVkO1xyXG5cclxuICBmbG9hdCB4X29mZnNldCAgID0gb2Zmc2V0O1xyXG4gIGZsb2F0IHhfbW92ZW1lbnQgPSB0aW1lICogMC4xO1xyXG4gIGZsb2F0IGFtcCAgICAgICAgPSBzaW4ob2Zmc2V0ICsgdGltZSAqIDAuMikgKiAwLjM7XHJcbiAgZmxvYXQgeSAgICAgICAgICA9IHNpbih1di54ICsgeF9vZmZzZXQgKyB4X21vdmVtZW50KSAqIGFtcDtcclxuXHJcbiAgaWYgKHNob3VsZEJlbmQpIHtcclxuICAgIHZlYzIgZCA9IHNjcmVlblV2IC0gbW91c2VVdjtcclxuICAgIGZsb2F0IGluZmx1ZW5jZSA9IGV4cCgtZG90KGQsIGQpICogYmVuZFJhZGl1cyk7IC8vIHJhZGlhbCBmYWxsb2ZmIGFyb3VuZCBjdXJzb3JcclxuICAgIGZsb2F0IGJlbmRPZmZzZXQgPSAobW91c2VVdi55IC0gc2NyZWVuVXYueSkgKiBpbmZsdWVuY2UgKiBiZW5kU3RyZW5ndGggKiBiZW5kSW5mbHVlbmNlO1xyXG4gICAgeSArPSBiZW5kT2Zmc2V0O1xyXG4gIH1cclxuXHJcbiAgZmxvYXQgbSA9IHV2LnkgLSB5O1xyXG4gIHJldHVybiAwLjAxNzUgLyBtYXgoYWJzKG0pICsgMC4wMSwgMWUtMykgKyAwLjAxO1xyXG59XHJcblxyXG52b2lkIG1haW5JbWFnZShvdXQgdmVjNCBmcmFnQ29sb3IsIGluIHZlYzIgZnJhZ0Nvb3JkKSB7XHJcbiAgdmVjMiBiYXNlVXYgPSAoMi4wICogZnJhZ0Nvb3JkIC0gaVJlc29sdXRpb24ueHkpIC8gaVJlc29sdXRpb24ueTtcclxuICBiYXNlVXYueSAqPSAtMS4wO1xyXG4gIFxyXG4gIGlmIChwYXJhbGxheCkge1xyXG4gICAgYmFzZVV2ICs9IHBhcmFsbGF4T2Zmc2V0O1xyXG4gIH1cclxuXHJcbiAgdmVjMyBjb2wgPSB2ZWMzKDAuMCk7XHJcblxyXG4gIHZlYzMgYiA9IGxpbmVHcmFkaWVudENvdW50ID4gMCA/IHZlYzMoMC4wKSA6IGJhY2tncm91bmRfY29sb3IoYmFzZVV2KTtcclxuXHJcbiAgdmVjMiBtb3VzZVV2ID0gdmVjMigwLjApO1xyXG4gIGlmIChpbnRlcmFjdGl2ZSkge1xyXG4gICAgbW91c2VVdiA9ICgyLjAgKiBpTW91c2UgLSBpUmVzb2x1dGlvbi54eSkgLyBpUmVzb2x1dGlvbi55O1xyXG4gICAgbW91c2VVdi55ICo9IC0xLjA7XHJcbiAgfVxyXG4gIFxyXG4gIGlmIChlbmFibGVCb3R0b20pIHtcclxuICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMjA7ICsraSkgeyAvLyBGaXhlZCBsaW1pdCBmb3IgTG9vcFxyXG4gICAgICBpZihpID49IGJvdHRvbUxpbmVDb3VudCkgYnJlYWs7XHJcbiAgICAgIGZsb2F0IGZpID0gZmxvYXQoaSk7XHJcbiAgICAgIGZsb2F0IHQgPSBmaSAvIG1heChmbG9hdChib3R0b21MaW5lQ291bnQgLSAxKSwgMS4wKTtcclxuICAgICAgdmVjMyBsaW5lQ29sID0gZ2V0TGluZUNvbG9yKHQsIGIpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgYW5nbGUgPSBib3R0b21XYXZlUG9zaXRpb24ueiAqIGxvZyhsZW5ndGgoYmFzZVV2KSArIDEuMCk7XHJcbiAgICAgIHZlYzIgcnV2ID0gYmFzZVV2ICogcm90YXRlKGFuZ2xlKTtcclxuICAgICAgY29sICs9IGxpbmVDb2wgKiB3YXZlKFxyXG4gICAgICAgIHJ1diArIHZlYzIoYm90dG9tTGluZURpc3RhbmNlICogZmkgKyBib3R0b21XYXZlUG9zaXRpb24ueCwgYm90dG9tV2F2ZVBvc2l0aW9uLnkpLFxyXG4gICAgICAgIDEuNSArIDAuMiAqIGZpLFxyXG4gICAgICAgIGJhc2VVdixcclxuICAgICAgICBtb3VzZVV2LFxyXG4gICAgICAgIGludGVyYWN0aXZlXHJcbiAgICAgICkgKiAwLjI7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpZiAoZW5hYmxlTWlkZGxlKSB7XHJcbiAgICBmb3IgKGludCBpID0gMDsgaSA8IDIwOyArK2kpIHtcclxuICAgICAgaWYoaSA+PSBtaWRkbGVMaW5lQ291bnQpIGJyZWFrO1xyXG4gICAgICBmbG9hdCBmaSA9IGZsb2F0KGkpO1xyXG4gICAgICBmbG9hdCB0ID0gZmkgLyBtYXgoZmxvYXQobWlkZGxlTGluZUNvdW50IC0gMSksIDEuMCk7XHJcbiAgICAgIHZlYzMgbGluZUNvbCA9IGdldExpbmVDb2xvcih0LCBiKTtcclxuICAgICAgXHJcbiAgICAgIGZsb2F0IGFuZ2xlID0gbWlkZGxlV2F2ZVBvc2l0aW9uLnogKiBsb2cobGVuZ3RoKGJhc2VVdikgKyAxLjApO1xyXG4gICAgICB2ZWMyIHJ1diA9IGJhc2VVdiAqIHJvdGF0ZShhbmdsZSk7XHJcbiAgICAgIGNvbCArPSBsaW5lQ29sICogd2F2ZShcclxuICAgICAgICBydXYgKyB2ZWMyKG1pZGRsZUxpbmVEaXN0YW5jZSAqIGZpICsgbWlkZGxlV2F2ZVBvc2l0aW9uLngsIG1pZGRsZVdhdmVQb3NpdGlvbi55KSxcclxuICAgICAgICAyLjAgKyAwLjE1ICogZmksXHJcbiAgICAgICAgYmFzZVV2LFxyXG4gICAgICAgIG1vdXNlVXYsXHJcbiAgICAgICAgaW50ZXJhY3RpdmVcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmIChlbmFibGVUb3ApIHtcclxuICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMjA7ICsraSkge1xyXG4gICAgICBpZihpID49IHRvcExpbmVDb3VudCkgYnJlYWs7XHJcbiAgICAgIGZsb2F0IGZpID0gZmxvYXQoaSk7XHJcbiAgICAgIGZsb2F0IHQgPSBmaSAvIG1heChmbG9hdCh0b3BMaW5lQ291bnQgLSAxKSwgMS4wKTtcclxuICAgICAgdmVjMyBsaW5lQ29sID0gZ2V0TGluZUNvbG9yKHQsIGIpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgYW5nbGUgPSB0b3BXYXZlUG9zaXRpb24ueiAqIGxvZyhsZW5ndGgoYmFzZVV2KSArIDEuMCk7XHJcbiAgICAgIHZlYzIgcnV2ID0gYmFzZVV2ICogcm90YXRlKGFuZ2xlKTtcclxuICAgICAgcnV2LnggKj0gLTEuMDtcclxuICAgICAgY29sICs9IGxpbmVDb2wgKiB3YXZlKFxyXG4gICAgICAgIHJ1diArIHZlYzIodG9wTGluZURpc3RhbmNlICogZmkgKyB0b3BXYXZlUG9zaXRpb24ueCwgdG9wV2F2ZVBvc2l0aW9uLnkpLFxyXG4gICAgICAgIDEuMCArIDAuMiAqIGZpLFxyXG4gICAgICAgIGJhc2VVdixcclxuICAgICAgICBtb3VzZVV2LFxyXG4gICAgICAgIGludGVyYWN0aXZlXHJcbiAgICAgICkgKiAwLjE7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBmcmFnQ29sb3IgPSB2ZWM0KGNvbCwgMS4wKTtcclxufVxyXG5cclxudm9pZCBtYWluKCkge1xyXG4gIHZlYzQgY29sb3IgPSB2ZWM0KDAuMCk7XHJcbiAgbWFpbkltYWdlKGNvbG9yLCBnbF9GcmFnQ29vcmQueHkpO1xyXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xyXG59XHJcbmA7XHJcblxyXG5jb25zdCBNQVhfR1JBRElFTlRfU1RPUFMgPSA4O1xyXG5cclxuZnVuY3Rpb24gaGV4VG9WZWMzKGhleDogc3RyaW5nKSB7XHJcbiAgbGV0IHZhbHVlID0gaGV4LnRyaW0oKTtcclxuICBpZiAodmFsdWUuc3RhcnRzV2l0aCgnIycpKSB7XHJcbiAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDEpO1xyXG4gIH1cclxuICBsZXQgciA9IDI1NTtcclxuICBsZXQgZyA9IDI1NTtcclxuICBsZXQgYiA9IDI1NTtcclxuICBpZiAodmFsdWUubGVuZ3RoID09P