angular-three-soba 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/abstractions/lib/catmull-rom-line.d.ts +148 -148
  2. package/abstractions/lib/edges.d.ts +166 -166
  3. package/abstractions/lib/grid.d.ts +30 -30
  4. package/abstractions/lib/line.d.ts +2 -2
  5. package/abstractions/lib/prism-geometry.d.ts +4 -4
  6. package/abstractions/lib/rounded-box.d.ts +1 -1
  7. package/abstractions/lib/text-3d.d.ts +37 -37
  8. package/abstractions/lib/text.d.ts +2 -2
  9. package/cameras/lib/cube-camera.d.ts +1 -1
  10. package/cameras/lib/orthographic-camera.d.ts +1 -1
  11. package/cameras/lib/perspective-camera.d.ts +1 -1
  12. package/controls/index.d.ts +9 -1
  13. package/controls/lib/camera-controls.d.ts +1 -1
  14. package/controls/lib/orbit-controls.d.ts +1 -1
  15. package/esm2022/controls/index.mjs +6 -2
  16. package/esm2022/gizmos/angular-three-soba-gizmos.mjs +5 -0
  17. package/esm2022/gizmos/index.mjs +6 -0
  18. package/esm2022/gizmos/lib/gizmo-helper/gizmo-helper.mjs +187 -0
  19. package/esm2022/gizmos/lib/gizmo-helper/gizmo-viewcube.mjs +304 -0
  20. package/esm2022/gizmos/lib/gizmo-helper/gizmo-viewport.mjs +332 -0
  21. package/esm2022/gizmos/lib/pivot-controls/axis-arrow.mjs +263 -0
  22. package/esm2022/gizmos/lib/pivot-controls/axis-rotator.mjs +264 -0
  23. package/esm2022/gizmos/lib/pivot-controls/pivot-controls.mjs +340 -0
  24. package/esm2022/gizmos/lib/pivot-controls/plane-slider.mjs +266 -0
  25. package/esm2022/gizmos/lib/pivot-controls/scaling-sphere.mjs +232 -0
  26. package/esm2022/gizmos/lib/transform-controls.mjs +177 -0
  27. package/esm2022/staging/index.mjs +2 -1
  28. package/esm2022/staging/lib/mask.mjs +78 -0
  29. package/fesm2022/angular-three-soba-controls.mjs +14 -1337
  30. package/fesm2022/angular-three-soba-controls.mjs.map +1 -1
  31. package/fesm2022/angular-three-soba-gizmos.mjs +2319 -0
  32. package/fesm2022/angular-three-soba-gizmos.mjs.map +1 -0
  33. package/fesm2022/angular-three-soba-staging.mjs +92 -21
  34. package/fesm2022/angular-three-soba-staging.mjs.map +1 -1
  35. package/gizmos/README.md +3 -0
  36. package/gizmos/index.d.ts +5 -0
  37. package/gizmos/lib/gizmo-helper/gizmo-helper.d.ts +45 -0
  38. package/gizmos/lib/gizmo-helper/gizmo-viewcube.d.ts +74 -0
  39. package/gizmos/lib/gizmo-helper/gizmo-viewport.d.ts +64 -0
  40. package/{controls → gizmos}/lib/pivot-controls/pivot-controls.d.ts +1 -1
  41. package/gizmos/lib/transform-controls.d.ts +50 -0
  42. package/materials/lib/custom-shader-material.d.ts +3 -3
  43. package/materials/lib/mesh-refraction-material.d.ts +3 -3
  44. package/materials/lib/mesh-transmission-material.d.ts +1 -1
  45. package/misc/lib/computed-attribute.d.ts +5 -5
  46. package/misc/lib/decal.d.ts +1 -1
  47. package/misc/lib/html/html.d.ts +1 -1
  48. package/misc/lib/sampler.d.ts +1 -1
  49. package/package.json +18 -12
  50. package/performances/lib/instances/instances.d.ts +9 -9
  51. package/performances/lib/points/points.d.ts +20 -20
  52. package/performances/lib/segments/segments.d.ts +4 -4
  53. package/shaders/lib/mesh-refraction-material.d.ts +2 -2
  54. package/staging/index.d.ts +1 -0
  55. package/staging/lib/caustics.d.ts +1 -1
  56. package/staging/lib/center.d.ts +2 -2
  57. package/staging/lib/contact-shadows.d.ts +1 -1
  58. package/staging/lib/lightformer.d.ts +1 -1
  59. package/staging/lib/mask.d.ts +30 -0
  60. package/staging/lib/render-texture.d.ts +1 -1
  61. package/staging/lib/sky.d.ts +1 -1
  62. package/staging/lib/spot-light.d.ts +2 -2
  63. package/staging/lib/stage.d.ts +6 -6
  64. package/esm2022/controls/lib/pivot-controls/axis-arrow.mjs +0 -263
  65. package/esm2022/controls/lib/pivot-controls/axis-rotator.mjs +0 -264
  66. package/esm2022/controls/lib/pivot-controls/pivot-controls.mjs +0 -340
  67. package/esm2022/controls/lib/pivot-controls/plane-slider.mjs +0 -266
  68. package/esm2022/controls/lib/pivot-controls/scaling-sphere.mjs +0 -232
  69. /package/{controls → gizmos}/lib/pivot-controls/axis-arrow.d.ts +0 -0
  70. /package/{controls → gizmos}/lib/pivot-controls/axis-rotator.d.ts +0 -0
  71. /package/{controls → gizmos}/lib/pivot-controls/plane-slider.d.ts +0 -0
  72. /package/{controls → gizmos}/lib/pivot-controls/scaling-sphere.d.ts +0 -0
@@ -0,0 +1,266 @@
1
+ import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, input, signal, viewChild, } from '@angular/core';
2
+ import { extend, injectStore } from 'angular-three';
3
+ import { NgtsLine } from 'angular-three-soba/abstractions';
4
+ import { NgtsHTML, NgtsHTMLContent } from 'angular-three-soba/misc';
5
+ import { DoubleSide, Group, Matrix4, Mesh, MeshBasicMaterial, Plane, PlaneGeometry, Ray, Vector3 } from 'three';
6
+ import { NgtsPivotControls } from './pivot-controls';
7
+ import * as i0 from "@angular/core";
8
+ function decomposeIntoBasis(e1, e2, offset) {
9
+ const i1 = Math.abs(e1.x) >= Math.abs(e1.y) && Math.abs(e1.x) >= Math.abs(e1.z)
10
+ ? 0
11
+ : Math.abs(e1.y) >= Math.abs(e1.x) && Math.abs(e1.y) >= Math.abs(e1.z)
12
+ ? 1
13
+ : 2;
14
+ const e2DegrowthOrder = [0, 1, 2].sort((a, b) => Math.abs(e2.getComponent(b)) - Math.abs(e2.getComponent(a)));
15
+ const i2 = i1 === e2DegrowthOrder[0] ? e2DegrowthOrder[1] : e2DegrowthOrder[0];
16
+ const a1 = e1.getComponent(i1);
17
+ const a2 = e1.getComponent(i2);
18
+ const b1 = e2.getComponent(i1);
19
+ const b2 = e2.getComponent(i2);
20
+ const c1 = offset.getComponent(i1);
21
+ const c2 = offset.getComponent(i2);
22
+ const y = (c2 - c1 * (a2 / a1)) / (b2 - b1 * (a2 / a1));
23
+ const x = (c1 - y * b1) / a1;
24
+ return [x, y];
25
+ }
26
+ const ray = new Ray();
27
+ const intersection = new Vector3();
28
+ const offsetMatrix = new Matrix4();
29
+ export class NgtsPlaneSlider {
30
+ constructor() {
31
+ this.DoubleSide = DoubleSide;
32
+ this.dir1 = input.required();
33
+ this.dir2 = input.required();
34
+ this.axis = input.required();
35
+ this.groupRef = viewChild.required('group');
36
+ this.annotationRef = viewChild('annotation', { read: ElementRef });
37
+ this.pivotControls = inject(NgtsPivotControls);
38
+ this.store = injectStore();
39
+ this.controls = this.store.select('controls');
40
+ this.hovered = signal(false);
41
+ this.clickInfo = null;
42
+ this.offsetX0 = 0;
43
+ this.offsetY0 = 0;
44
+ this.matrixL = computed(() => {
45
+ const dir1N = this.dir1().clone().normalize();
46
+ const dir2N = this.dir2().clone().normalize();
47
+ return new Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
48
+ });
49
+ this.pos1 = computed(() => (this.pivotControls.fixed() ? 1 / 7 : this.pivotControls.scale() / 7));
50
+ this.length = computed(() => (this.pivotControls.fixed() ? 0.225 : this.pivotControls.scale() * 0.225));
51
+ this.color = computed(() => this.hovered() ? this.pivotControls.hoveredColor() : this.pivotControls.axisColors()[this.axis()]);
52
+ this.points = computed(() => {
53
+ const length = this.length();
54
+ return [
55
+ new Vector3(0, 0, 0),
56
+ new Vector3(0, length, 0),
57
+ new Vector3(length, length, 0),
58
+ new Vector3(length, 0, 0),
59
+ new Vector3(0, 0, 0),
60
+ ];
61
+ });
62
+ extend({ Group, Mesh, PlaneGeometry, MeshBasicMaterial });
63
+ }
64
+ onPointerDown(event) {
65
+ const [annotation, axis, group, controls] = [
66
+ this.annotationRef()?.nativeElement,
67
+ this.axis(),
68
+ this.groupRef().nativeElement,
69
+ this.controls(),
70
+ ];
71
+ if (annotation) {
72
+ annotation.innerText = `${this.pivotControls.translation[(axis + 1) % 3].toFixed(2)}, ${this.pivotControls.translation[(axis + 2) % 3].toFixed(2)}`;
73
+ annotation.style.display = 'block';
74
+ }
75
+ event.stopPropagation();
76
+ const clickPoint = event.point.clone();
77
+ const origin = new Vector3().setFromMatrixPosition(group.matrixWorld);
78
+ const e1 = new Vector3().setFromMatrixColumn(group.matrixWorld, 0).normalize();
79
+ const e2 = new Vector3().setFromMatrixColumn(group.matrixWorld, 1).normalize();
80
+ const normal = new Vector3().setFromMatrixColumn(group.matrixWorld, 2).normalize();
81
+ const plane = new Plane().setFromNormalAndCoplanarPoint(normal, origin);
82
+ this.clickInfo = { clickPoint, e1, e2, plane };
83
+ this.offsetX0 = this.pivotControls.translation[(axis + 1) % 3];
84
+ this.offsetY0 = this.pivotControls.translation[(axis + 2) % 3];
85
+ this.pivotControls.onDragStart({ component: 'Slider', axis, origin, directions: [e1, e2, normal] });
86
+ if (controls) {
87
+ controls.enabled = false;
88
+ }
89
+ // @ts-expect-error - setPointerCapture is not defined on ThreeEvent
90
+ event.target.setPointerCapture(event.pointerId);
91
+ }
92
+ onPointerMove(event) {
93
+ event.stopPropagation();
94
+ if (!this.hovered())
95
+ this.hovered.set(true);
96
+ if (this.clickInfo) {
97
+ const { clickPoint, e1, e2, plane } = this.clickInfo;
98
+ const [translationLimits, axis, annotation] = [
99
+ this.pivotControls.translationLimits(),
100
+ this.axis(),
101
+ this.annotationRef()?.nativeElement,
102
+ ];
103
+ const [minX, maxX] = translationLimits?.[(axis + 1) % 3] || [undefined, undefined];
104
+ const [minY, maxY] = translationLimits?.[(axis + 2) % 3] || [undefined, undefined];
105
+ ray.copy(event.ray);
106
+ ray.intersectPlane(plane, intersection);
107
+ ray.direction.negate();
108
+ ray.intersectPlane(plane, intersection);
109
+ intersection.sub(clickPoint);
110
+ let [offsetX, offsetY] = decomposeIntoBasis(e1, e2, intersection);
111
+ /* let offsetY = (intersection.y - (intersection.x * e1.y) / e1.x) / (e2.y - (e2.x * e1.y) / e1.x)
112
+ let offsetX = (intersection.x - offsetY * e2.x) / e1.x */
113
+ if (minX !== undefined) {
114
+ offsetX = Math.max(offsetX, minX - this.offsetX0);
115
+ }
116
+ if (maxX !== undefined) {
117
+ offsetX = Math.min(offsetX, maxX - this.offsetX0);
118
+ }
119
+ if (minY !== undefined) {
120
+ offsetY = Math.max(offsetY, minY - this.offsetY0);
121
+ }
122
+ if (maxY !== undefined) {
123
+ offsetY = Math.min(offsetY, maxY - this.offsetY0);
124
+ }
125
+ this.pivotControls.translation[(axis + 1) % 3] = this.offsetX0 + offsetX;
126
+ this.pivotControls.translation[(axis + 2) % 3] = this.offsetY0 + offsetY;
127
+ if (annotation) {
128
+ annotation.innerText = `${this.pivotControls.translation[(axis + 1) % 3].toFixed(2)}, ${this.pivotControls.translation[(axis + 2) % 3].toFixed(2)}`;
129
+ }
130
+ offsetMatrix.makeTranslation(offsetX * e1.x + offsetY * e2.x, offsetX * e1.y + offsetY * e2.y, offsetX * e1.z + offsetY * e2.z);
131
+ this.pivotControls.onDrag(offsetMatrix);
132
+ }
133
+ }
134
+ onPointerUp(event) {
135
+ const [annotation, controls] = [this.annotationRef()?.nativeElement, this.controls()];
136
+ if (annotation) {
137
+ annotation.style.display = 'none';
138
+ }
139
+ event.stopPropagation();
140
+ this.clickInfo = null;
141
+ this.pivotControls.onDragEnd();
142
+ if (controls) {
143
+ controls.enabled = true;
144
+ }
145
+ // @ts-expect-error - releasePointerCapture is not defined on ThreeEvent
146
+ event.target.releasePointerCapture(event.pointerId);
147
+ }
148
+ onPointerOut(event) {
149
+ event.stopPropagation();
150
+ this.hovered.set(false);
151
+ }
152
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtsPlaneSlider, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
153
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: NgtsPlaneSlider, isStandalone: true, selector: "ngts-plane-slider", inputs: { dir1: { classPropertyName: "dir1", publicName: "dir1", isSignal: true, isRequired: true, transformFunction: null }, dir2: { classPropertyName: "dir2", publicName: "dir2", isSignal: true, isRequired: true, transformFunction: null }, axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "groupRef", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "annotationRef", first: true, predicate: ["annotation"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: `
154
+ <ngt-group #group [matrix]="matrixL()" [matrixAutoUpdate]="false">
155
+ @if (pivotControls.annotations()) {
156
+ <ngts-html [options]="{ position: [0, 0, 0] }">
157
+ <div
158
+ #annotation
159
+ ngtsHTMLContent
160
+ style="display: none; background: #151520; color: white; padding: 6px 8px; border-radius: 7px; white-space: nowrap"
161
+ [class]="pivotControls.annotationsClass()"
162
+ ></div>
163
+ </ngts-html>
164
+ }
165
+ <ngt-group [position]="[pos1() * 1.7, pos1() * 1.7, 0]">
166
+ <ngt-mesh
167
+ [visible]="true"
168
+ [scale]="length()"
169
+ [userData]="pivotControls.userData()"
170
+ (pointerdown)="onPointerDown($any($event))"
171
+ (pointermove)="onPointerMove($any($event))"
172
+ (pointerup)="onPointerUp($any($event))"
173
+ (pointerout)="onPointerOut($any($event))"
174
+ >
175
+ <ngt-plane-geometry />
176
+ <ngt-mesh-basic-material
177
+ [transparent]="true"
178
+ [depthTest]="pivotControls.depthTest()"
179
+ [color]="color()"
180
+ [polygonOffset]="true"
181
+ [polygonOffsetFactor]="-10"
182
+ [side]="DoubleSide"
183
+ [fog]="false"
184
+ />
185
+ </ngt-mesh>
186
+ <ngts-line
187
+ [points]="points()"
188
+ [options]="{
189
+ position: [-length() / 2, -length() / 2, 0],
190
+ transparent: true,
191
+ depthTest: pivotControls.depthTest(),
192
+ lineWidth: pivotControls.lineWidth(),
193
+ color: color(),
194
+ opacity: pivotControls.opacity(),
195
+ polygonOffset: true,
196
+ polygonOffsetFactor: -10,
197
+ userData: pivotControls.userData(),
198
+ fog: false,
199
+ }"
200
+ />
201
+ </ngt-group>
202
+ </ngt-group>
203
+ `, isInline: true, dependencies: [{ kind: "component", type: NgtsHTML, selector: "ngts-html", inputs: ["options"] }, { kind: "component", type: NgtsHTMLContent, selector: "[ngtsHTMLContent]", inputs: ["ngtsHTMLContent"], outputs: ["occluded"] }, { kind: "component", type: NgtsLine, selector: "ngts-line", inputs: ["points", "options"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
204
+ }
205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtsPlaneSlider, decorators: [{
206
+ type: Component,
207
+ args: [{
208
+ selector: 'ngts-plane-slider',
209
+ standalone: true,
210
+ template: `
211
+ <ngt-group #group [matrix]="matrixL()" [matrixAutoUpdate]="false">
212
+ @if (pivotControls.annotations()) {
213
+ <ngts-html [options]="{ position: [0, 0, 0] }">
214
+ <div
215
+ #annotation
216
+ ngtsHTMLContent
217
+ style="display: none; background: #151520; color: white; padding: 6px 8px; border-radius: 7px; white-space: nowrap"
218
+ [class]="pivotControls.annotationsClass()"
219
+ ></div>
220
+ </ngts-html>
221
+ }
222
+ <ngt-group [position]="[pos1() * 1.7, pos1() * 1.7, 0]">
223
+ <ngt-mesh
224
+ [visible]="true"
225
+ [scale]="length()"
226
+ [userData]="pivotControls.userData()"
227
+ (pointerdown)="onPointerDown($any($event))"
228
+ (pointermove)="onPointerMove($any($event))"
229
+ (pointerup)="onPointerUp($any($event))"
230
+ (pointerout)="onPointerOut($any($event))"
231
+ >
232
+ <ngt-plane-geometry />
233
+ <ngt-mesh-basic-material
234
+ [transparent]="true"
235
+ [depthTest]="pivotControls.depthTest()"
236
+ [color]="color()"
237
+ [polygonOffset]="true"
238
+ [polygonOffsetFactor]="-10"
239
+ [side]="DoubleSide"
240
+ [fog]="false"
241
+ />
242
+ </ngt-mesh>
243
+ <ngts-line
244
+ [points]="points()"
245
+ [options]="{
246
+ position: [-length() / 2, -length() / 2, 0],
247
+ transparent: true,
248
+ depthTest: pivotControls.depthTest(),
249
+ lineWidth: pivotControls.lineWidth(),
250
+ color: color(),
251
+ opacity: pivotControls.opacity(),
252
+ polygonOffset: true,
253
+ polygonOffsetFactor: -10,
254
+ userData: pivotControls.userData(),
255
+ fog: false,
256
+ }"
257
+ />
258
+ </ngt-group>
259
+ </ngt-group>
260
+ `,
261
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
262
+ changeDetection: ChangeDetectionStrategy.OnPush,
263
+ imports: [NgtsHTML, NgtsHTMLContent, NgtsLine],
264
+ }]
265
+ }], ctorParameters: () => [] });
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbmUtc2xpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9zb2JhL2dpem1vcy9zcmMvbGliL3Bpdm90LWNvbnRyb2xzL3BsYW5lLXNsaWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1Isc0JBQXNCLEVBQ3RCLFVBQVUsRUFDVixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sRUFFTixTQUFTLEdBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQWlCLE1BQU0sZUFBZSxDQUFDO0FBQ25FLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMzRCxPQUFPLEVBQUUsUUFBUSxFQUFFLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ2hILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDOztBQUVyRCxTQUFTLGtCQUFrQixDQUFDLEVBQVcsRUFBRSxFQUFXLEVBQUUsTUFBZTtJQUNwRSxNQUFNLEVBQUUsR0FDUCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbkUsQ0FBQyxDQUFDLENBQUM7UUFDSCxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3JFLENBQUMsQ0FBQyxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNQLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlHLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9FLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0IsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvQixNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0IsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQyxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxD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QU8sRUFBRSxDQUFDLFFBQVEsRUFBRSxlQUFlLEVBQUUsUUFBUSxDQUFDO2lCQUM5QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuXHRDb21wb25lbnQsXG5cdGNvbXB1dGVkLFxuXHRDVVNUT01fRUxFTUVOVFNfU0NIRU1BLFxuXHRFbGVtZW50UmVmLFxuXHRpbmplY3QsXG5cdGlucHV0LFxuXHRzaWduYWwsXG5cdFNpZ25hbCxcblx0dmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGV4dGVuZCwgaW5qZWN0U3RvcmUsIE5ndFRocmVlRXZlbnQgfSBmcm9tICdhbmd1bGFyLXRocmVlJztcbmltcG9ydCB7IE5ndHNMaW5lIH0gZnJvbSAnYW5ndWxhci10aHJlZS1zb2JhL2Fic3RyYWN0aW9ucyc7XG5pbXBvcnQgeyBOZ3RzSFRNTCwgTmd0c0hUTUxDb250ZW50IH0gZnJvbSAnYW5ndWxhci10aHJlZS1zb2JhL21pc2MnO1xuaW1wb3J0IHsgRG91YmxlU2lkZSwgR3JvdXAsIE1hdHJpeDQsIE1lc2gsIE1lc2hCYXNpY01hdGVyaWFsLCBQbGFuZSwgUGxhbmVHZW9tZXRyeSwgUmF5LCBWZWN0b3IzIH0gZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgTmd0c1Bpdm90Q29udHJvbHMgfSBmcm9tICcuL3Bpdm90LWNvbnRyb2xzJztcblxuZnVuY3Rpb24gZGVjb21wb3NlSW50b0Jhc2lzKGUxOiBWZWN0b3IzLCBlMjogVmVjdG9yMywgb2Zmc2V0OiBWZWN0b3IzKSB7XG5cdGNvbnN0IGkxID1cblx0XHRNYXRoLmFicyhlMS54KSA+PSBNYXRoLmFicyhlMS55KSAmJiBNYXRoLmFicyhlMS54KSA+PSBNYXRoLmFicyhlMS56KVxuXHRcdFx0PyAwXG5cdFx0XHQ6IE1hdGguYWJzKGUxLnkpID49IE1hdGguYWJzKGUxLngpICYmIE1hdGguYWJzKGUxLnkpID49IE1hdGguYWJzKGUxLnopXG5cdFx0XHRcdD8gMVxuXHRcdFx0XHQ6IDI7XG5cdGNvbnN0IGUyRGVncm93dGhPcmRlciA9IFswLCAxLCAyXS5zb3J0KChhLCBiKSA9PiBNYXRoLmFicyhlMi5nZXRDb21wb25lbnQoYikpIC0gTWF0aC5hYnMoZTIuZ2V0Q29tcG9uZW50KGEpKSk7XG5cdGNvbnN0IGkyID0gaTEgPT09IGUyRGVncm93dGhPcmRlclswXSA/IGUyRGVncm93dGhPcmRlclsxXSA6IGUyRGVncm93dGhPcmRlclswXTtcblx0Y29uc3QgYTEgPSBlMS5nZXRDb21wb25lbnQoaTEpO1xuXHRjb25zdCBhMiA9IGUxLmdldENvbXBvbmVudChpMik7XG5cdGNvbnN0IGIxID0gZTIuZ2V0Q29tcG9uZW50KGkxKTtcblx0Y29uc3QgYjIgPSBlMi5nZXRDb21wb25lbnQoaTIpO1xuXHRjb25zdCBjMSA9IG9mZnNldC5nZXRDb21wb25lbnQoaTEpO1xuXHRjb25zdCBjMiA9IG9mZnNldC5nZXRDb21wb25lbnQoaTIpO1xuXG5cdGNvbnN0IHkgPSAoYzIgLSBjMSAqIChhMiAvIGExKSkgLyAoYjIgLSBiMSAqIChhMiAvIGExKSk7XG5cdGNvbnN0IHggPSAoYzEgLSB5ICogYjEpIC8gYTE7XG5cblx0cmV0dXJuIFt4LCB5XTtcbn1cblxuY29uc3QgcmF5ID0gbmV3IFJheSgpO1xuY29uc3QgaW50ZXJzZWN0aW9uID0gbmV3IFZlY3RvcjMoKTtcbmNvbnN0IG9mZnNldE1hdHJpeCA9IG5ldyBNYXRyaXg0KCk7XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ25ndHMtcGxhbmUtc2xpZGVyJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0dGVtcGxhdGU6IGBcblx0XHQ8bmd0LWdyb3VwICNncm91cCBbbWF0cml4XT1cIm1hdHJpeEwoKVwiIFttYXRyaXhBdXRvVXBkYXRlXT1cImZhbHNlXCI+XG5cdFx0XHRAaWYgKHBpdm90Q29udHJvbHMuYW5ub3RhdGlvbnMoKSkge1xuXHRcdFx0XHQ8bmd0cy1odG1sIFtvcHRpb25zXT1cInsgcG9zaXRpb246IFswLCAwLCAwXSB9XCI+XG5cdFx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdFx0I2Fubm90YXRpb25cblx0XHRcdFx0XHRcdG5ndHNIVE1MQ29udGVudFxuXHRcdFx0XHRcdFx0c3R5bGU9XCJkaXNwbGF5OiBub25lOyBiYWNrZ3JvdW5kOiAjMTUxNTIwOyBjb2xvcjogd2hpdGU7IHBhZGRpbmc6IDZweCA4cHg7IGJvcmRlci1yYWRpdXM6IDdweDsgd2hpdGUtc3BhY2U6IG5vd3JhcFwiXG5cdFx0XHRcdFx0XHRbY2xhc3NdPVwicGl2b3RDb250cm9scy5hbm5vdGF0aW9uc0NsYXNzKClcIlxuXHRcdFx0XHRcdD48L2Rpdj5cblx0XHRcdFx0PC9uZ3RzLWh0bWw+XG5cdFx0XHR9XG5cdFx0XHQ8bmd0LWdyb3VwIFtwb3NpdGlvbl09XCJbcG9zMSgpICogMS43LCBwb3MxKCkgKiAxLjcsIDBdXCI+XG5cdFx0XHRcdDxuZ3QtbWVzaFxuXHRcdFx0XHRcdFt2aXNpYmxlXT1cInRydWVcIlxuXHRcdFx0XHRcdFtzY2FsZV09XCJsZW5ndGgoKVwiXG5cdFx0XHRcdFx0W3VzZXJEYXRhXT1cInBpdm90Q29udHJvbHMudXNlckRhdGEoKVwiXG5cdFx0XHRcdFx0KHBvaW50ZXJkb3duKT1cIm9uUG9pbnRlckRvd24oJGFueSgkZXZlbnQpKVwiXG5cdFx0XHRcdFx0KHBvaW50ZXJtb3ZlKT1cIm9uUG9pbnRlck1vdmUoJGFueSgkZXZlbnQpKVwiXG5cdFx0XHRcdFx0KHBvaW50ZXJ1cCk9XCJvblBvaW50ZXJVcCgkYW55KCRldmVudCkpXCJcblx0XHRcdFx0XHQocG9pbnRlcm91dCk9XCJvblBvaW50ZXJPdXQoJGFueSgkZXZlbnQpKVwiXG5cdFx0XHRcdD5cblx0XHRcdFx0XHQ8bmd0LXBsYW5lLWdlb21ldHJ5IC8+XG5cdFx0XHRcdFx0PG5ndC1tZXNoLWJhc2ljLW1hdGVyaWFsXG5cdFx0XHRcdFx0XHRbdHJhbnNwYXJlbnRdPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHRbZGVwdGhUZXN0XT1cInBpdm90Q29udHJvbHMuZGVwdGhUZXN0KClcIlxuXHRcdFx0XHRcdFx0W2NvbG9yXT1cImNvbG9yKClcIlxuXHRcdFx0XHRcdFx0W3BvbHlnb25PZmZzZXRdPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHRbcG9seWdvbk9mZnNldEZhY3Rvcl09XCItMTBcIlxuXHRcdFx0XHRcdFx0W3NpZGVdPVwiRG91YmxlU2lkZVwiXG5cdFx0XHRcdFx0XHRbZm9nXT1cImZhbHNlXCJcblx0XHRcdFx0XHQvPlxuXHRcdFx0XHQ8L25ndC1tZXNoPlxuXHRcdFx0XHQ8bmd0cy1saW5lXG5cdFx0XHRcdFx0W3BvaW50c109XCJwb2ludHMoKVwiXG5cdFx0XHRcdFx0W29wdGlvbnNdPVwie1xuXHRcdFx0XHRcdFx0cG9zaXRpb246IFstbGVuZ3RoKCkgLyAyLCAtbGVuZ3RoKCkgLyAyLCAwXSxcblx0XHRcdFx0XHRcdHRyYW5zcGFyZW50OiB0cnVlLFxuXHRcdFx0XHRcdFx0ZGVwdGhUZXN0OiBwaXZvdENvbnRyb2xzLmRlcHRoVGVzdCgpLFxuXHRcdFx0XHRcdFx0bGluZVdpZHRoOiBwaXZvdENvbnRyb2xzLmxpbmVXaWR0aCgpLFxuXHRcdFx0XHRcdFx0Y29sb3I6IGNvbG9yKCksXG5cdFx0XHRcdFx0XHRvcGFjaXR5OiBwaXZvdENvbnRyb2xzLm9wYWNpdHkoKSxcblx0XHRcdFx0XHRcdHBvbHlnb25PZmZzZXQ6IHRydWUsXG5cdFx0XHRcdFx0XHRwb2x5Z29uT2Zmc2V0RmFjdG9yOiAtMTAsXG5cdFx0XHRcdFx0XHR1c2VyRGF0YTogcGl2b3RDb250cm9scy51c2VyRGF0YSgpLFxuXHRcdFx0XHRcdFx0Zm9nOiBmYWxzZSxcblx0XHRcdFx0XHR9XCJcblx0XHRcdFx0Lz5cblx0XHRcdDwvbmd0LWdyb3VwPlxuXHRcdDwvbmd0LWdyb3VwPlxuXHRgLFxuXHRzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXG5cdGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuXHRpbXBvcnRzOiBbTmd0c0hUTUwsIE5ndHNIVE1MQ29udGVudCwgTmd0c0xpbmVdLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3RzUGxhbmVTbGlkZXIge1xuXHRwcm90ZWN0ZWQgcmVhZG9ubHkgRG91YmxlU2lkZSA9IERvdWJsZVNpZGU7XG5cblx0ZGlyMSA9IGlucHV0LnJlcXVpcmVkPFZlY3RvcjM+KCk7XG5cdGRpcjIgPSBpbnB1dC5yZXF1aXJlZDxWZWN0b3IzPigpO1xuXHRheGlzID0gaW5wdXQucmVxdWlyZWQ8MCB8IDEgfCAyPigpO1xuXG5cdGdyb3VwUmVmID0gdmlld0NoaWxkLnJlcXVpcmVkPEVsZW1lbnRSZWY8R3JvdXA+PignZ3JvdXAnKTtcblx0YW5ub3RhdGlvblJlZiA9IHZpZXdDaGlsZDx1bmtub3duLCBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50Pj4oJ2Fubm90YXRpb24nLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSk7XG5cblx0cGl2b3RDb250cm9scyA9IGluamVjdChOZ3RzUGl2b3RDb250cm9scyk7XG5cdHByaXZhdGUgc3RvcmUgPSBpbmplY3RTdG9yZSgpO1xuXHRwcml2YXRlIGNvbnRyb2xzID0gdGhpcy5zdG9yZS5zZWxlY3QoJ2NvbnRyb2xzJykgYXMgdW5rbm93biBhcyBTaWduYWw8eyBlbmFibGVkOiBib29sZWFuIH0+O1xuXG5cdHByaXZhdGUgaG92ZXJlZCA9IHNpZ25hbChmYWxzZSk7XG5cdHByaXZhdGUgY2xpY2tJbmZvOiB7IGNsaWNrUG9pbnQ6IFZlY3RvcjM7IGUxOiBWZWN0b3IzOyBlMjogVmVjdG9yMzsgcGxhbmU6IFBsYW5lIH0gfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBvZmZzZXRYMCA9IDA7XG5cdHByaXZhdGUgb2Zmc2V0WTAgPSAwO1xuXG5cdG1hdHJpeEwgPSBjb21wdXRlZCgoKSA9PiB7XG5cdFx0Y29uc3QgZGlyMU4gPSB0aGlzLmRpcjEoKS5jbG9uZSgpLm5vcm1hbGl6ZSgpO1xuXHRcdGNvbnN0IGRpcjJOID0gdGhpcy5kaXIyKCkuY2xvbmUoKS5ub3JtYWxpemUoKTtcblx0XHRyZXR1cm4gbmV3IE1hdHJpeDQoKS5tYWtlQmFzaXMoZGlyMU4sIGRpcjJOLCBkaXIxTi5jbG9uZSgpLmNyb3NzKGRpcjJOKSk7XG5cdH0pO1xuXG5cdHBvczEgPSBjb21wdXRlZCgoKSA9PiAodGhpcy5waXZvdENvbnRyb2xzLmZpeGVkKCkgPyAxIC8gNyA6IHRoaXMucGl2b3RDb250cm9scy5zY2FsZSgpIC8gNykpO1xuXHRsZW5ndGggPSBjb21wdXRlZCgoKSA9PiAodGhpcy5waXZvdENvbnRyb2xzLmZpeGVkKCkgPyAwLjIyNSA6IHRoaXMucGl2b3RDb250cm9scy5zY2FsZSgpICogMC4yMjUpKTtcblx0Y29sb3IgPSBjb21wdXRlZCgoKSA9PlxuXHRcdHRoaXMuaG92ZXJlZCgpID8gdGhpcy5waXZvdENvbnRyb2xzLmhvdmVyZWRDb2xvcigpIDogdGhpcy5waXZvdENvbnRyb2xzLmF4aXNDb2xvcnMoKVt0aGlzLmF4aXMoKV0sXG5cdCk7XG5cdHBvaW50cyA9IGNvbXB1dGVkKCgpID0+IHtcblx0XHRjb25zdCBsZW5ndGggPSB0aGlzLmxlbmd0aCgpO1xuXHRcdHJldHVybiBbXG5cdFx0XHRuZXcgVmVjdG9yMygwLCAwLCAwKSxcblx0XHRcdG5ldyBWZWN0b3IzKDAsIGxlbmd0aCwgMCksXG5cdFx0XHRuZXcgVmVjdG9yMyhsZW5ndGgsIGxlbmd0aCwgMCksXG5cdFx0XHRuZXcgVmVjdG9yMyhsZW5ndGgsIDAsIDApLFxuXHRcdFx0bmV3IFZlY3RvcjMoMCwgMCwgMCksXG5cdFx0XTtcblx0fSk7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0ZXh0ZW5kKHsgR3JvdXAsIE1lc2gsIFBsYW5lR2VvbWV0cnksIE1lc2hCYXNpY01hdGVyaWFsIH0pO1xuXHR9XG5cblx0b25Qb2ludGVyRG93bihldmVudDogTmd0VGhyZWVFdmVudDxQb2ludGVyRXZlbnQ+KSB7XG5cdFx0Y29uc3QgW2Fubm90YXRpb24sIGF4aXMsIGdyb3VwLCBjb250cm9sc10gPSBbXG5cdFx0XHR0aGlzLmFubm90YXRpb25SZWYoKT8ubmF0aXZlRWxlbWVudCxcblx0XHRcdHRoaXMuYXhpcygpLFxuXHRcdFx0dGhpcy5ncm91cFJlZigpLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHR0aGlzLmNvbnRyb2xzKCksXG5cdFx0XTtcblxuXHRcdGlmIChhbm5vdGF0aW9uKSB7XG5cdFx0XHRhbm5vdGF0aW9uLmlubmVyVGV4dCA9IGAke3RoaXMucGl2b3RDb250cm9scy50cmFuc2xhdGlvblsoYXhpcyArIDEpICUgM10udG9GaXhlZCgyKX0sICR7dGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMikgJSAzXS50b0ZpeGVkKDIpfWA7XG5cdFx0XHRhbm5vdGF0aW9uLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuXHRcdH1cblxuXHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdGNvbnN0IGNsaWNrUG9pbnQgPSBldmVudC5wb2ludC5jbG9uZSgpO1xuXHRcdGNvbnN0IG9yaWdpbiA9IG5ldyBWZWN0b3IzKCkuc2V0RnJvbU1hdHJpeFBvc2l0aW9uKGdyb3VwLm1hdHJpeFdvcmxkKTtcblx0XHRjb25zdCBlMSA9IG5ldyBWZWN0b3IzKCkuc2V0RnJvbU1hdHJpeENvbHVtbihncm91cC5tYXRyaXhXb3JsZCwgMCkubm9ybWFsaXplKCk7XG5cdFx0Y29uc3QgZTIgPSBuZXcgVmVjdG9yMygpLnNldEZyb21NYXRyaXhDb2x1bW4oZ3JvdXAubWF0cml4V29ybGQsIDEpLm5vcm1hbGl6ZSgpO1xuXHRcdGNvbnN0IG5vcm1hbCA9IG5ldyBWZWN0b3IzKCkuc2V0RnJvbU1hdHJpeENvbHVtbihncm91cC5tYXRyaXhXb3JsZCwgMikubm9ybWFsaXplKCk7XG5cdFx0Y29uc3QgcGxhbmUgPSBuZXcgUGxhbmUoKS5zZXRGcm9tTm9ybWFsQW5kQ29wbGFuYXJQb2ludChub3JtYWwsIG9yaWdpbik7XG5cdFx0dGhpcy5jbGlja0luZm8gPSB7IGNsaWNrUG9pbnQsIGUxLCBlMiwgcGxhbmUgfTtcblx0XHR0aGlzLm9mZnNldFgwID0gdGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMSkgJSAzXTtcblx0XHR0aGlzLm9mZnNldFkwID0gdGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMikgJSAzXTtcblx0XHR0aGlzLnBpdm90Q29udHJvbHMub25EcmFnU3RhcnQoeyBjb21wb25lbnQ6ICdTbGlkZXInLCBheGlzLCBvcmlnaW4sIGRpcmVjdGlvbnM6IFtlMSwgZTIsIG5vcm1hbF0gfSk7XG5cdFx0aWYgKGNvbnRyb2xzKSB7XG5cdFx0XHRjb250cm9scy5lbmFibGVkID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQHRzLWV4cGVjdC1lcnJvciAtIHNldFBvaW50ZXJDYXB0dXJlIGlzIG5vdCBkZWZpbmVkIG9uIFRocmVlRXZlbnRcblx0XHRldmVudC50YXJnZXQuc2V0UG9pbnRlckNhcHR1cmUoZXZlbnQucG9pbnRlcklkKTtcblx0fVxuXG5cdG9uUG9pbnRlck1vdmUoZXZlbnQ6IE5ndFRocmVlRXZlbnQ8UG9pbnRlckV2ZW50Pikge1xuXHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdGlmICghdGhpcy5ob3ZlcmVkKCkpIHRoaXMuaG92ZXJlZC5zZXQodHJ1ZSk7XG5cblx0XHRpZiAodGhpcy5jbGlja0luZm8pIHtcblx0XHRcdGNvbnN0IHsgY2xpY2tQb2ludCwgZTEsIGUyLCBwbGFuZSB9ID0gdGhpcy5jbGlja0luZm87XG5cdFx0XHRjb25zdCBbdHJhbnNsYXRpb25MaW1pdHMsIGF4aXMsIGFubm90YXRpb25dID0gW1xuXHRcdFx0XHR0aGlzLnBpdm90Q29udHJvbHMudHJhbnNsYXRpb25MaW1pdHMoKSxcblx0XHRcdFx0dGhpcy5heGlzKCksXG5cdFx0XHRcdHRoaXMuYW5ub3RhdGlvblJlZigpPy5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XTtcblxuXHRcdFx0Y29uc3QgW21pblgsIG1heFhdID0gdHJhbnNsYXRpb25MaW1pdHM/LlsoYXhpcyArIDEpICUgM10gfHwgW3VuZGVmaW5lZCwgdW5kZWZpbmVkXTtcblx0XHRcdGNvbnN0IFttaW5ZLCBtYXhZXSA9IHRyYW5zbGF0aW9uTGltaXRzPy5bKGF4aXMgKyAyKSAlIDNdIHx8IFt1bmRlZmluZWQsIHVuZGVmaW5lZF07XG5cblx0XHRcdHJheS5jb3B5KGV2ZW50LnJheSk7XG5cdFx0XHRyYXkuaW50ZXJzZWN0UGxhbmUocGxhbmUsIGludGVyc2VjdGlvbik7XG5cdFx0XHRyYXkuZGlyZWN0aW9uLm5lZ2F0ZSgpO1xuXHRcdFx0cmF5LmludGVyc2VjdFBsYW5lKHBsYW5lLCBpbnRlcnNlY3Rpb24pO1xuXHRcdFx0aW50ZXJzZWN0aW9uLnN1YihjbGlja1BvaW50KTtcblx0XHRcdGxldCBbb2Zmc2V0WCwgb2Zmc2V0WV0gPSBkZWNvbXBvc2VJbnRvQmFzaXMoZTEsIGUyLCBpbnRlcnNlY3Rpb24pO1xuXHRcdFx0LyogbGV0IG9mZnNldFkgPSAoaW50ZXJzZWN0aW9uLnkgLSAoaW50ZXJzZWN0aW9uLnggKiBlMS55KSAvIGUxLngpIC8gKGUyLnkgLSAoZTIueCAqIGUxLnkpIC8gZTEueClcbiAgICAgIGxldCBvZmZzZXRYID0gKGludGVyc2VjdGlvbi54IC0gb2Zmc2V0WSAqIGUyLngpIC8gZTEueCAqL1xuXHRcdFx0aWYgKG1pblggIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRvZmZzZXRYID0gTWF0aC5tYXgob2Zmc2V0WCwgbWluWCAtIHRoaXMub2Zmc2V0WDApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG1heFggIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRvZmZzZXRYID0gTWF0aC5taW4ob2Zmc2V0WCwgbWF4WCAtIHRoaXMub2Zmc2V0WDApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG1pblkgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRvZmZzZXRZID0gTWF0aC5tYXgob2Zmc2V0WSwgbWluWSAtIHRoaXMub2Zmc2V0WTApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG1heFkgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRvZmZzZXRZID0gTWF0aC5taW4ob2Zmc2V0WSwgbWF4WSAtIHRoaXMub2Zmc2V0WTApO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMSkgJSAzXSA9IHRoaXMub2Zmc2V0WDAgKyBvZmZzZXRYO1xuXHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMikgJSAzXSA9IHRoaXMub2Zmc2V0WTAgKyBvZmZzZXRZO1xuXG5cdFx0XHRpZiAoYW5ub3RhdGlvbikge1xuXHRcdFx0XHRhbm5vdGF0aW9uLmlubmVyVGV4dCA9IGAke3RoaXMucGl2b3RDb250cm9scy50cmFuc2xhdGlvblsoYXhpcyArIDEpICUgM10udG9GaXhlZCgyKX0sICR7dGhpcy5waXZvdENvbnRyb2xzLnRyYW5zbGF0aW9uWyhheGlzICsgMikgJSAzXS50b0ZpeGVkKDIpfWA7XG5cdFx0XHR9XG5cblx0XHRcdG9mZnNldE1hdHJpeC5tYWtlVHJhbnNsYXRpb24oXG5cdFx0XHRcdG9mZnNldFggKiBlMS54ICsgb2Zmc2V0WSAqIGUyLngsXG5cdFx0XHRcdG9mZnNldFggKiBlMS55ICsgb2Zmc2V0WSAqIGUyLnksXG5cdFx0XHRcdG9mZnNldFggKiBlMS56ICsgb2Zmc2V0WSAqIGUyLnosXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLm9uRHJhZyhvZmZzZXRNYXRyaXgpO1xuXHRcdH1cblx0fVxuXG5cdG9uUG9pbnRlclVwKGV2ZW50OiBOZ3RUaHJlZUV2ZW50PFBvaW50ZXJFdmVudD4pIHtcblx0XHRjb25zdCBbYW5ub3RhdGlvbiwgY29udHJvbHNdID0gW3RoaXMuYW5ub3RhdGlvblJlZigpPy5uYXRpdmVFbGVtZW50LCB0aGlzLmNvbnRyb2xzKCldO1xuXHRcdGlmIChhbm5vdGF0aW9uKSB7XG5cdFx0XHRhbm5vdGF0aW9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0fVxuXHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdHRoaXMuY2xpY2tJbmZvID0gbnVsbDtcblx0XHR0aGlzLnBpdm90Q29udHJvbHMub25EcmFnRW5kKCk7XG5cdFx0aWYgKGNvbnRyb2xzKSB7XG5cdFx0XHRjb250cm9scy5lbmFibGVkID0gdHJ1ZTtcblx0XHR9XG5cdFx0Ly8gQHRzLWV4cGVjdC1lcnJvciAtIHJlbGVhc2VQb2ludGVyQ2FwdHVyZSBpcyBub3QgZGVmaW5lZCBvbiBUaHJlZUV2ZW50XG5cdFx0ZXZlbnQudGFyZ2V0LnJlbGVhc2VQb2ludGVyQ2FwdHVyZShldmVudC5wb2ludGVySWQpO1xuXHR9XG5cblx0b25Qb2ludGVyT3V0KGV2ZW50OiBOZ3RUaHJlZUV2ZW50PFBvaW50ZXJFdmVudD4pIHtcblx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHR0aGlzLmhvdmVyZWQuc2V0KGZhbHNlKTtcblx0fVxufVxuIl19
@@ -0,0 +1,232 @@
1
+ import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, input, signal, viewChild, } from '@angular/core';
2
+ import { extend, injectStore, NgtArgs } from 'angular-three';
3
+ import { calculateScaleFactor, NgtsHTML, NgtsHTMLContent } from 'angular-three-soba/misc';
4
+ import { Group, Matrix4, Mesh, MeshBasicMaterial, Quaternion, SphereGeometry, Vector3 } from 'three';
5
+ import { NgtsPivotControls } from './pivot-controls';
6
+ import * as i0 from "@angular/core";
7
+ const vec1 = new Vector3();
8
+ const vec2 = new Vector3();
9
+ export function calculateOffset(clickPoint, normal, rayStart, rayDir) {
10
+ const e1 = normal.dot(normal);
11
+ const e2 = normal.dot(clickPoint) - normal.dot(rayStart);
12
+ const e3 = normal.dot(rayDir);
13
+ if (e3 === 0) {
14
+ return -e2 / e1;
15
+ }
16
+ vec1
17
+ .copy(rayDir)
18
+ .multiplyScalar(e1 / e3)
19
+ .sub(normal);
20
+ vec2
21
+ .copy(rayDir)
22
+ .multiplyScalar(e2 / e3)
23
+ .add(rayStart)
24
+ .sub(clickPoint);
25
+ return -vec1.dot(vec2) / vec1.dot(vec1);
26
+ }
27
+ const upV = new Vector3(0, 1, 0);
28
+ const scaleV = new Vector3();
29
+ const scaleMatrix = new Matrix4();
30
+ export class NgtsScalingSphere {
31
+ constructor() {
32
+ this.direction = input.required();
33
+ this.axis = input.required();
34
+ this.groupRef = viewChild.required('group');
35
+ this.annotationRef = viewChild('annotation', { read: ElementRef });
36
+ this.meshRef = viewChild.required('mesh');
37
+ this.pivotControls = inject(NgtsPivotControls);
38
+ this.store = injectStore();
39
+ this.controls = this.store.select('controls');
40
+ this.size = this.store.select('size');
41
+ this.hovered = signal(false);
42
+ this.scale0 = 1;
43
+ this.scaleCurrent = 1;
44
+ this.clickInfo = null;
45
+ this.position = computed(() => (this.pivotControls.fixed() ? 1.2 : 1.2 * this.pivotControls.scale()));
46
+ this.radius = computed(() => this.pivotControls.fixed()
47
+ ? (this.pivotControls.lineWidth() / this.pivotControls.scale()) * 1.8
48
+ : this.pivotControls.scale() / 22.5);
49
+ this.matrixL = computed(() => {
50
+ const quaternion = new Quaternion().setFromUnitVectors(upV, this.direction().clone().normalize());
51
+ return new Matrix4().makeRotationFromQuaternion(quaternion);
52
+ });
53
+ this.color = computed(() => this.hovered() ? this.pivotControls.hoveredColor() : this.pivotControls.axisColors()[this.axis()]);
54
+ extend({ Group, Mesh, SphereGeometry, MeshBasicMaterial });
55
+ }
56
+ onPointerDown(event) {
57
+ const [annotation, controls, fixed, scale, direction, axis, size, group] = [
58
+ this.annotationRef()?.nativeElement,
59
+ this.controls(),
60
+ this.pivotControls.fixed(),
61
+ this.pivotControls.scale(),
62
+ this.direction(),
63
+ this.axis(),
64
+ this.size(),
65
+ this.groupRef().nativeElement,
66
+ ];
67
+ if (annotation) {
68
+ annotation.innerText = `${scale.toFixed(2)}`;
69
+ annotation.style.display = 'block';
70
+ }
71
+ event.stopPropagation();
72
+ const rotation = new Matrix4().extractRotation(group.matrixWorld);
73
+ const clickPoint = event.point.clone();
74
+ const origin = new Vector3().setFromMatrixPosition(group.matrixWorld);
75
+ const dir = direction.clone().applyMatrix4(rotation).normalize();
76
+ const mPLG = group.matrixWorld.clone();
77
+ const mPLGInv = mPLG.clone().invert();
78
+ const offsetMultiplier = fixed
79
+ ? 1 / calculateScaleFactor(group.getWorldPosition(vec1), scale, event.camera, size)
80
+ : 1;
81
+ this.clickInfo = { clickPoint, dir, mPLG, mPLGInv, offsetMultiplier };
82
+ this.pivotControls.onDragStart({ component: 'Sphere', axis, origin, directions: [dir] });
83
+ if (controls) {
84
+ controls.enabled = false;
85
+ }
86
+ // @ts-expect-error - setPointerCapture is not in the type definition
87
+ event.target.setPointerCapture(event.pointerId);
88
+ }
89
+ onPointerMove(event) {
90
+ event.stopPropagation();
91
+ if (!this.hovered())
92
+ this.hovered.set(true);
93
+ if (this.clickInfo) {
94
+ const { clickPoint, dir, mPLG, mPLGInv, offsetMultiplier } = this.clickInfo;
95
+ const [scaleLimits, axis, position, annotation, fixed, scale, mesh] = [
96
+ this.pivotControls.scaleLimits(),
97
+ this.axis(),
98
+ this.position(),
99
+ this.annotationRef()?.nativeElement,
100
+ this.pivotControls.fixed(),
101
+ this.pivotControls.scale(),
102
+ this.meshRef().nativeElement,
103
+ ];
104
+ const [min, max] = scaleLimits?.[axis] || [1e-5, undefined]; // always limit the minimal value, since setting it very low might break the transform
105
+ const offsetW = calculateOffset(clickPoint, dir, event.ray.origin, event.ray.direction);
106
+ const offsetL = offsetW * offsetMultiplier;
107
+ const offsetH = fixed ? offsetL : offsetL / scale;
108
+ let upscale = Math.pow(2, offsetH * 0.2);
109
+ if (event.shiftKey) {
110
+ upscale = Math.round(upscale * 10) / 10;
111
+ }
112
+ upscale = Math.max(upscale, min / this.scale0);
113
+ if (max !== undefined) {
114
+ upscale = Math.min(upscale, max / this.scale0);
115
+ }
116
+ this.scaleCurrent = this.scale0 * upscale;
117
+ mesh.position.set(0, position + offsetL, 0);
118
+ if (annotation) {
119
+ annotation.innerText = `${this.scaleCurrent.toFixed(2)}`;
120
+ }
121
+ scaleV.set(1, 1, 1);
122
+ scaleV.setComponent(axis, upscale);
123
+ scaleMatrix.makeScale(scaleV.x, scaleV.y, scaleV.z).premultiply(mPLG).multiply(mPLGInv);
124
+ this.pivotControls.onDrag(scaleMatrix);
125
+ }
126
+ }
127
+ onPointerUp(event) {
128
+ const [annotation, controls, position, mesh] = [
129
+ this.annotationRef()?.nativeElement,
130
+ this.controls(),
131
+ this.position(),
132
+ this.meshRef().nativeElement,
133
+ ];
134
+ if (annotation) {
135
+ annotation.style.display = 'none';
136
+ }
137
+ event.stopPropagation();
138
+ this.scale0 = this.scaleCurrent;
139
+ this.clickInfo = null;
140
+ mesh.position.set(0, position, 0);
141
+ this.pivotControls.onDragEnd();
142
+ if (controls) {
143
+ controls.enabled = true;
144
+ }
145
+ // @ts-expect-error - releasePointerCapture is not in the type definition
146
+ event.target.releasePointerCapture(event.pointerId);
147
+ }
148
+ onPointerOut(event) {
149
+ event.stopPropagation();
150
+ this.hovered.set(false);
151
+ }
152
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtsScalingSphere, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
153
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: NgtsScalingSphere, isStandalone: true, selector: "ngts-scaling-sphere", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: true, transformFunction: null }, axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "groupRef", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "annotationRef", first: true, predicate: ["annotation"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "meshRef", first: true, predicate: ["mesh"], descendants: true, isSignal: true }], ngImport: i0, template: `
154
+ <ngt-group #group>
155
+ <ngt-group
156
+ [matrix]="matrixL()"
157
+ [matrixAutoUpdate]="false"
158
+ (pointerdown)="onPointerDown($any($event))"
159
+ (pointermove)="onPointerMove($any($event))"
160
+ (pointerup)="onPointerUp($any($event))"
161
+ (pointerout)="onPointerOut($any($event))"
162
+ >
163
+ @if (pivotControls.annotations()) {
164
+ <ngts-html [options]="{ position: [0, position() / 2, 0] }">
165
+ <div
166
+ #annotation
167
+ ngtsHTMLContent
168
+ style="display: none; background: #151520; color: white; padding: 6px 8px; border-radius: 7px; white-space: nowrap;"
169
+ [class]="pivotControls.annotationsClass()"
170
+ ></div>
171
+ </ngts-html>
172
+ }
173
+ <ngt-mesh #mesh [position]="[0, position(), 0]" [renderOrder]="500" [userData]="pivotControls.userData()">
174
+ <ngt-sphere-geometry *args="[radius(), 12, 12]" />
175
+ <ngt-mesh-basic-material
176
+ [transparent]="true"
177
+ [depthTest]="pivotControls.depthTest()"
178
+ [color]="color()"
179
+ [opacity]="pivotControls.opacity()"
180
+ [polygonOffset]="true"
181
+ [polygonOffsetFactor]="-10"
182
+ />
183
+ </ngt-mesh>
184
+ </ngt-group>
185
+ </ngt-group>
186
+ `, isInline: true, dependencies: [{ kind: "component", type: NgtsHTML, selector: "ngts-html", inputs: ["options"] }, { kind: "component", type: NgtsHTMLContent, selector: "[ngtsHTMLContent]", inputs: ["ngtsHTMLContent"], outputs: ["occluded"] }, { kind: "directive", type: NgtArgs, selector: "ng-template[args]", inputs: ["args"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
187
+ }
188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtsScalingSphere, decorators: [{
189
+ type: Component,
190
+ args: [{
191
+ selector: 'ngts-scaling-sphere',
192
+ standalone: true,
193
+ template: `
194
+ <ngt-group #group>
195
+ <ngt-group
196
+ [matrix]="matrixL()"
197
+ [matrixAutoUpdate]="false"
198
+ (pointerdown)="onPointerDown($any($event))"
199
+ (pointermove)="onPointerMove($any($event))"
200
+ (pointerup)="onPointerUp($any($event))"
201
+ (pointerout)="onPointerOut($any($event))"
202
+ >
203
+ @if (pivotControls.annotations()) {
204
+ <ngts-html [options]="{ position: [0, position() / 2, 0] }">
205
+ <div
206
+ #annotation
207
+ ngtsHTMLContent
208
+ style="display: none; background: #151520; color: white; padding: 6px 8px; border-radius: 7px; white-space: nowrap;"
209
+ [class]="pivotControls.annotationsClass()"
210
+ ></div>
211
+ </ngts-html>
212
+ }
213
+ <ngt-mesh #mesh [position]="[0, position(), 0]" [renderOrder]="500" [userData]="pivotControls.userData()">
214
+ <ngt-sphere-geometry *args="[radius(), 12, 12]" />
215
+ <ngt-mesh-basic-material
216
+ [transparent]="true"
217
+ [depthTest]="pivotControls.depthTest()"
218
+ [color]="color()"
219
+ [opacity]="pivotControls.opacity()"
220
+ [polygonOffset]="true"
221
+ [polygonOffsetFactor]="-10"
222
+ />
223
+ </ngt-mesh>
224
+ </ngt-group>
225
+ </ngt-group>
226
+ `,
227
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
228
+ changeDetection: ChangeDetectionStrategy.OnPush,
229
+ imports: [NgtsHTML, NgtsHTMLContent, NgtArgs],
230
+ }]
231
+ }], ctorParameters: () => [] });
232
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NhbGluZy1zcGhlcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL3NvYmEvZ2l6bW9zL3NyYy9saWIvcGl2b3QtY29udHJvbHMvc2NhbGluZy1zcGhlcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNOLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsUUFBUSxFQUNSLHNCQUFzQixFQUN0QixVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBRU4sU0FBUyxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDNUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMxRixPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxPQUFPLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDckcsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7O0FBRXJELE1BQU0sSUFBSSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7QUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztBQUUzQixNQUFNLFVBQVUsZUFBZSxDQUFDLFVBQW1CLEVBQUUsTUFBZSxFQUFFLFFBQWlCLEVBQUUsTUFBZTtJQUN2RyxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlCLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6RCxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FB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QyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pCLENBQUM7OEdBeEpXLGlCQUFpQjtrR0FBakIsaUJBQWlCLDhnQkFLd0QsVUFBVSwrSUEzQ3JGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFpQ1QsNERBR1MsUUFBUSwyRUFBRSxlQUFlLGtIQUFFLE9BQU87OzJGQUVoQyxpQkFBaUI7a0JBekM3QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxxQkFBcUI7b0JBQy9CLFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWlDVDtvQkFDRCxPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDakMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07b0JBQy9DLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRSxlQUFlLEVBQUUsT0FBTyxDQUFDO2lCQUM3QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuXHRDb21wb25lbnQsXG5cdGNvbXB1dGVkLFxuXHRDVVNUT01fRUxFTUVOVFNfU0NIRU1BLFxuXHRFbGVtZW50UmVmLFxuXHRpbmplY3QsXG5cdGlucHV0LFxuXHRzaWduYWwsXG5cdFNpZ25hbCxcblx0dmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGV4dGVuZCwgaW5qZWN0U3RvcmUsIE5ndEFyZ3MsIE5ndFRocmVlRXZlbnQgfSBmcm9tICdhbmd1bGFyLXRocmVlJztcbmltcG9ydCB7IGNhbGN1bGF0ZVNjYWxlRmFjdG9yLCBOZ3RzSFRNTCwgTmd0c0hUTUxDb250ZW50IH0gZnJvbSAnYW5ndWxhci10aHJlZS1zb2JhL21pc2MnO1xuaW1wb3J0IHsgR3JvdXAsIE1hdHJpeDQsIE1lc2gsIE1lc2hCYXNpY01hdGVyaWFsLCBRdWF0ZXJuaW9uLCBTcGhlcmVHZW9tZXRyeSwgVmVjdG9yMyB9IGZyb20gJ3RocmVlJztcbmltcG9ydCB7IE5ndHNQaXZvdENvbnRyb2xzIH0gZnJvbSAnLi9waXZvdC1jb250cm9scyc7XG5cbmNvbnN0IHZlYzEgPSBuZXcgVmVjdG9yMygpO1xuY29uc3QgdmVjMiA9IG5ldyBWZWN0b3IzKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVPZmZzZXQoY2xpY2tQb2ludDogVmVjdG9yMywgbm9ybWFsOiBWZWN0b3IzLCByYXlTdGFydDogVmVjdG9yMywgcmF5RGlyOiBWZWN0b3IzKSB7XG5cdGNvbnN0IGUxID0gbm9ybWFsLmRvdChub3JtYWwpO1xuXHRjb25zdCBlMiA9IG5vcm1hbC5kb3QoY2xpY2tQb2ludCkgLSBub3JtYWwuZG90KHJheVN0YXJ0KTtcblx0Y29uc3QgZTMgPSBub3JtYWwuZG90KHJheURpcik7XG5cblx0aWYgKGUzID09PSAwKSB7XG5cdFx0cmV0dXJuIC1lMiAvIGUxO1xuXHR9XG5cblx0dmVjMVxuXHRcdC5jb3B5KHJheURpcilcblx0XHQubXVsdGlwbHlTY2FsYXIoZTEgLyBlMylcblx0XHQuc3ViKG5vcm1hbCk7XG5cdHZlYzJcblx0XHQuY29weShyYXlEaXIpXG5cdFx0Lm11bHRpcGx5U2NhbGFyKGUyIC8gZTMpXG5cdFx0LmFkZChyYXlTdGFydClcblx0XHQuc3ViKGNsaWNrUG9pbnQpO1xuXG5cdHJldHVybiAtdmVjMS5kb3QodmVjMikgLyB2ZWMxLmRvdCh2ZWMxKTtcbn1cblxuY29uc3QgdXBWID0gbmV3IFZlY3RvcjMoMCwgMSwgMCk7XG5jb25zdCBzY2FsZVYgPSBuZXcgVmVjdG9yMygpO1xuY29uc3Qgc2NhbGVNYXRyaXggPSBuZXcgTWF0cml4NCgpO1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICduZ3RzLXNjYWxpbmctc3BoZXJlJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0dGVtcGxhdGU6IGBcblx0XHQ8bmd0LWdyb3VwICNncm91cD5cblx0XHRcdDxuZ3QtZ3JvdXBcblx0XHRcdFx0W21hdHJpeF09XCJtYXRyaXhMKClcIlxuXHRcdFx0XHRbbWF0cml4QXV0b1VwZGF0ZV09XCJmYWxzZVwiXG5cdFx0XHRcdChwb2ludGVyZG93bik9XCJvblBvaW50ZXJEb3duKCRhbnkoJGV2ZW50KSlcIlxuXHRcdFx0XHQocG9pbnRlcm1vdmUpPVwib25Qb2ludGVyTW92ZSgkYW55KCRldmVudCkpXCJcblx0XHRcdFx0KHBvaW50ZXJ1cCk9XCJvblBvaW50ZXJVcCgkYW55KCRldmVudCkpXCJcblx0XHRcdFx0KHBvaW50ZXJvdXQpPVwib25Qb2ludGVyT3V0KCRhbnkoJGV2ZW50KSlcIlxuXHRcdFx0PlxuXHRcdFx0XHRAaWYgKHBpdm90Q29udHJvbHMuYW5ub3RhdGlvbnMoKSkge1xuXHRcdFx0XHRcdDxuZ3RzLWh0bWwgW29wdGlvbnNdPVwieyBwb3NpdGlvbjogWzAsIHBvc2l0aW9uKCkgLyAyLCAwXSB9XCI+XG5cdFx0XHRcdFx0XHQ8ZGl2XG5cdFx0XHRcdFx0XHRcdCNhbm5vdGF0aW9uXG5cdFx0XHRcdFx0XHRcdG5ndHNIVE1MQ29udGVudFxuXHRcdFx0XHRcdFx0XHRzdHlsZT1cImRpc3BsYXk6IG5vbmU7IGJhY2tncm91bmQ6ICMxNTE1MjA7IGNvbG9yOiB3aGl0ZTsgcGFkZGluZzogNnB4IDhweDsgYm9yZGVyLXJhZGl1czogN3B4OyB3aGl0ZS1zcGFjZTogbm93cmFwO1wiXG5cdFx0XHRcdFx0XHRcdFtjbGFzc109XCJwaXZvdENvbnRyb2xzLmFubm90YXRpb25zQ2xhc3MoKVwiXG5cdFx0XHRcdFx0XHQ+PC9kaXY+XG5cdFx0XHRcdFx0PC9uZ3RzLWh0bWw+XG5cdFx0XHRcdH1cblx0XHRcdFx0PG5ndC1tZXNoICNtZXNoIFtwb3NpdGlvbl09XCJbMCwgcG9zaXRpb24oKSwgMF1cIiBbcmVuZGVyT3JkZXJdPVwiNTAwXCIgW3VzZXJEYXRhXT1cInBpdm90Q29udHJvbHMudXNlckRhdGEoKVwiPlxuXHRcdFx0XHRcdDxuZ3Qtc3BoZXJlLWdlb21ldHJ5ICphcmdzPVwiW3JhZGl1cygpLCAxMiwgMTJdXCIgLz5cblx0XHRcdFx0XHQ8bmd0LW1lc2gtYmFzaWMtbWF0ZXJpYWxcblx0XHRcdFx0XHRcdFt0cmFuc3BhcmVudF09XCJ0cnVlXCJcblx0XHRcdFx0XHRcdFtkZXB0aFRlc3RdPVwicGl2b3RDb250cm9scy5kZXB0aFRlc3QoKVwiXG5cdFx0XHRcdFx0XHRbY29sb3JdPVwiY29sb3IoKVwiXG5cdFx0XHRcdFx0XHRbb3BhY2l0eV09XCJwaXZvdENvbnRyb2xzLm9wYWNpdHkoKVwiXG5cdFx0XHRcdFx0XHRbcG9seWdvbk9mZnNldF09XCJ0cnVlXCJcblx0XHRcdFx0XHRcdFtwb2x5Z29uT2Zmc2V0RmFjdG9yXT1cIi0xMFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0PC9uZ3QtbWVzaD5cblx0XHRcdDwvbmd0LWdyb3VwPlxuXHRcdDwvbmd0LWdyb3VwPlxuXHRgLFxuXHRzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXG5cdGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuXHRpbXBvcnRzOiBbTmd0c0hUTUwsIE5ndHNIVE1MQ29udGVudCwgTmd0QXJnc10sXG59KVxuZXhwb3J0IGNsYXNzIE5ndHNTY2FsaW5nU3BoZXJlIHtcblx0ZGlyZWN0aW9uID0gaW5wdXQucmVxdWlyZWQ8VmVjdG9yMz4oKTtcblx0YXhpcyA9IGlucHV0LnJlcXVpcmVkPDAgfCAxIHwgMj4oKTtcblxuXHRncm91cFJlZiA9IHZpZXdDaGlsZC5yZXF1aXJlZDxFbGVtZW50UmVmPEdyb3VwPj4oJ2dyb3VwJyk7XG5cdGFubm90YXRpb25SZWYgPSB2aWV3Q2hpbGQ8dW5rbm93biwgRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD4+KCdhbm5vdGF0aW9uJywgeyByZWFkOiBFbGVtZW50UmVmIH0pO1xuXHRtZXNoUmVmID0gdmlld0NoaWxkLnJlcXVpcmVkPEVsZW1lbnRSZWY8TWVzaD4+KCdtZXNoJyk7XG5cblx0cGl2b3RDb250cm9scyA9IGluamVjdChOZ3RzUGl2b3RDb250cm9scyk7XG5cdHByaXZhdGUgc3RvcmUgPSBpbmplY3RTdG9yZSgpO1xuXHRwcml2YXRlIGNvbnRyb2xzID0gdGhpcy5zdG9yZS5zZWxlY3QoJ2NvbnRyb2xzJykgYXMgdW5rbm93biBhcyBTaWduYWw8eyBlbmFibGVkOiBib29sZWFuIH0+O1xuXHRwcml2YXRlIHNpemUgPSB0aGlzLnN0b3JlLnNlbGVjdCgnc2l6ZScpO1xuXG5cdHByaXZhdGUgaG92ZXJlZCA9IHNpZ25hbChmYWxzZSk7XG5cdHByaXZhdGUgc2NhbGUwID0gMTtcblx0cHJpdmF0ZSBzY2FsZUN1cnJlbnQgPSAxO1xuXHRwcml2YXRlIGNsaWNrSW5mbzoge1xuXHRcdGNsaWNrUG9pbnQ6IFZlY3RvcjM7XG5cdFx0ZGlyOiBWZWN0b3IzO1xuXHRcdG1QTEc6IE1hdHJpeDQ7XG5cdFx0bVBMR0ludjogTWF0cml4NDtcblx0XHRvZmZzZXRNdWx0aXBsaWVyOiBudW1iZXI7XG5cdH0gfCBudWxsID0gbnVsbDtcblxuXHRwb3NpdGlvbiA9IGNvbXB1dGVkKCgpID0+ICh0aGlzLnBpdm90Q29udHJvbHMuZml4ZWQoKSA/IDEuMiA6IDEuMiAqIHRoaXMucGl2b3RDb250cm9scy5zY2FsZSgpKSk7XG5cdHJhZGl1cyA9IGNvbXB1dGVkKCgpID0+XG5cdFx0dGhpcy5waXZvdENvbnRyb2xzLmZpeGVkKClcblx0XHRcdD8gKHRoaXMucGl2b3RDb250cm9scy5saW5lV2lkdGgoKSAvIHRoaXMucGl2b3RDb250cm9scy5zY2FsZSgpKSAqIDEuOFxuXHRcdFx0OiB0aGlzLnBpdm90Q29udHJvbHMuc2NhbGUoKSAvIDIyLjUsXG5cdCk7XG5cdG1hdHJpeEwgPSBjb21wdXRlZCgoKSA9PiB7XG5cdFx0Y29uc3QgcXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCkuc2V0RnJvbVVuaXRWZWN0b3JzKHVwViwgdGhpcy5kaXJlY3Rpb24oKS5jbG9uZSgpLm5vcm1hbGl6ZSgpKTtcblx0XHRyZXR1cm4gbmV3IE1hdHJpeDQoKS5tYWtlUm90YXRpb25Gcm9tUXVhdGVybmlvbihxdWF0ZXJuaW9uKTtcblx0fSk7XG5cdGNvbG9yID0gY29tcHV0ZWQoKCkgPT5cblx0XHR0aGlzLmhvdmVyZWQoKSA/IHRoaXMucGl2b3RDb250cm9scy5ob3ZlcmVkQ29sb3IoKSA6IHRoaXMucGl2b3RDb250cm9scy5heGlzQ29sb3JzKClbdGhpcy5heGlzKCldLFxuXHQpO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdGV4dGVuZCh7IEdyb3VwLCBNZXNoLCBTcGhlcmVHZW9tZXRyeSwgTWVzaEJhc2ljTWF0ZXJpYWwgfSk7XG5cdH1cblxuXHRvblBvaW50ZXJEb3duKGV2ZW50OiBOZ3RUaHJlZUV2ZW50PFBvaW50ZXJFdmVudD4pIHtcblx0XHRjb25zdCBbYW5ub3RhdGlvbiwgY29udHJvbHMsIGZpeGVkLCBzY2FsZSwgZGlyZWN0aW9uLCBheGlzLCBzaXplLCBncm91cF0gPSBbXG5cdFx0XHR0aGlzLmFubm90YXRpb25SZWYoKT8ubmF0aXZlRWxlbWVudCxcblx0XHRcdHRoaXMuY29udHJvbHMoKSxcblx0XHRcdHRoaXMucGl2b3RDb250cm9scy5maXhlZCgpLFxuXHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLnNjYWxlKCksXG5cdFx0XHR0aGlzLmRpcmVjdGlvbigpLFxuXHRcdFx0dGhpcy5heGlzKCksXG5cdFx0XHR0aGlzLnNpemUoKSxcblx0XHRcdHRoaXMuZ3JvdXBSZWYoKS5uYXRpdmVFbGVtZW50LFxuXHRcdF07XG5cblx0XHRpZiAoYW5ub3RhdGlvbikge1xuXHRcdFx0YW5ub3RhdGlvbi5pbm5lclRleHQgPSBgJHtzY2FsZS50b0ZpeGVkKDIpfWA7XG5cdFx0XHRhbm5vdGF0aW9uLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuXHRcdH1cblxuXHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdGNvbnN0IHJvdGF0aW9uID0gbmV3IE1hdHJpeDQoKS5leHRyYWN0Um90YXRpb24oZ3JvdXAubWF0cml4V29ybGQpO1xuXHRcdGNvbnN0IGNsaWNrUG9pbnQgPSBldmVudC5wb2ludC5jbG9uZSgpO1xuXHRcdGNvbnN0IG9yaWdpbiA9IG5ldyBWZWN0b3IzKCkuc2V0RnJvbU1hdHJpeFBvc2l0aW9uKGdyb3VwLm1hdHJpeFdvcmxkKTtcblx0XHRjb25zdCBkaXIgPSBkaXJlY3Rpb24uY2xvbmUoKS5hcHBseU1hdHJpeDQocm90YXRpb24pLm5vcm1hbGl6ZSgpO1xuXHRcdGNvbnN0IG1QTEcgPSBncm91cC5tYXRyaXhXb3JsZC5jbG9uZSgpO1xuXHRcdGNvbnN0IG1QTEdJbnYgPSBtUExHLmNsb25lKCkuaW52ZXJ0KCk7XG5cdFx0Y29uc3Qgb2Zmc2V0TXVsdGlwbGllciA9IGZpeGVkXG5cdFx0XHQ/IDEgLyBjYWxjdWxhdGVTY2FsZUZhY3Rvcihncm91cC5nZXRXb3JsZFBvc2l0aW9uKHZlYzEpLCBzY2FsZSwgZXZlbnQuY2FtZXJhLCBzaXplKVxuXHRcdFx0OiAxO1xuXHRcdHRoaXMuY2xpY2tJbmZvID0geyBjbGlja1BvaW50LCBkaXIsIG1QTEcsIG1QTEdJbnYsIG9mZnNldE11bHRpcGxpZXIgfTtcblx0XHR0aGlzLnBpdm90Q29udHJvbHMub25EcmFnU3RhcnQoeyBjb21wb25lbnQ6ICdTcGhlcmUnLCBheGlzLCBvcmlnaW4sIGRpcmVjdGlvbnM6IFtkaXJdIH0pO1xuXG5cdFx0aWYgKGNvbnRyb2xzKSB7XG5cdFx0XHRjb250cm9scy5lbmFibGVkID0gZmFsc2U7XG5cdFx0fVxuXHRcdC8vIEB0cy1leHBlY3QtZXJyb3IgLSBzZXRQb2ludGVyQ2FwdHVyZSBpcyBub3QgaW4gdGhlIHR5cGUgZGVmaW5pdGlvblxuXHRcdGV2ZW50LnRhcmdldC5zZXRQb2ludGVyQ2FwdHVyZShldmVudC5wb2ludGVySWQpO1xuXHR9XG5cblx0b25Qb2ludGVyTW92ZShldmVudDogTmd0VGhyZWVFdmVudDxQb2ludGVyRXZlbnQ+KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0aWYgKCF0aGlzLmhvdmVyZWQoKSkgdGhpcy5ob3ZlcmVkLnNldCh0cnVlKTtcblxuXHRcdGlmICh0aGlzLmNsaWNrSW5mbykge1xuXHRcdFx0Y29uc3QgeyBjbGlja1BvaW50LCBkaXIsIG1QTEcsIG1QTEdJbnYsIG9mZnNldE11bHRpcGxpZXIgfSA9IHRoaXMuY2xpY2tJbmZvO1xuXHRcdFx0Y29uc3QgW3NjYWxlTGltaXRzLCBheGlzLCBwb3NpdGlvbiwgYW5ub3RhdGlvbiwgZml4ZWQsIHNjYWxlLCBtZXNoXSA9IFtcblx0XHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLnNjYWxlTGltaXRzKCksXG5cdFx0XHRcdHRoaXMuYXhpcygpLFxuXHRcdFx0XHR0aGlzLnBvc2l0aW9uKCksXG5cdFx0XHRcdHRoaXMuYW5ub3RhdGlvblJlZigpPy5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XHR0aGlzLnBpdm90Q29udHJvbHMuZml4ZWQoKSxcblx0XHRcdFx0dGhpcy5waXZvdENvbnRyb2xzLnNjYWxlKCksXG5cdFx0XHRcdHRoaXMubWVzaFJlZigpLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHRdO1xuXG5cdFx0XHRjb25zdCBbbWluLCBtYXhdID0gc2NhbGVMaW1pdHM/LltheGlzXSB8fCBbMWUtNSwgdW5kZWZpbmVkXTsgLy8gYWx3YXlzIGxpbWl0IHRoZSBtaW5pbWFsIHZhbHVlLCBzaW5jZSBzZXR0aW5nIGl0IHZlcnkgbG93IG1pZ2h0IGJyZWFrIHRoZSB0cmFuc2Zvcm1cblx0XHRcdGNvbnN0IG9mZnNldFcgPSBjYWxjdWxhdGVPZmZzZXQoY2xpY2tQb2ludCwgZGlyLCBldmVudC5yYXkub3JpZ2luLCBldmVudC5yYXkuZGlyZWN0aW9uKTtcblx0XHRcdGNvbnN0IG9mZnNldEwgPSBvZmZzZXRXICogb2Zmc2V0TXVsdGlwbGllcjtcblx0XHRcdGNvbnN0IG9mZnNldEggPSBmaXhlZCA/IG9mZnNldEwgOiBvZmZzZXRMIC8gc2NhbGU7XG5cdFx0XHRsZXQgdXBzY2FsZSA9IE1hdGgucG93KDIsIG9mZnNldEggKiAwLjIpO1xuXG5cdFx0XHRpZiAoZXZlbnQuc2hpZnRLZXkpIHtcblx0XHRcdFx0dXBzY2FsZSA9IE1hdGgucm91bmQodXBzY2FsZSAqIDEwKSAvIDEwO1xuXHRcdFx0fVxuXG5cdFx0XHR1cHNjYWxlID0gTWF0aC5tYXgodXBzY2FsZSwgbWluIC8gdGhpcy5zY2FsZTApO1xuXG5cdFx0XHRpZiAobWF4ICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0dXBzY2FsZSA9IE1hdGgubWluKHVwc2NhbGUsIG1heCAvIHRoaXMuc2NhbGUwKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zY2FsZUN1cnJlbnQgPSB0aGlzLnNjYWxlMCAqIHVwc2NhbGU7XG5cdFx0XHRtZXNoLnBvc2l0aW9uLnNldCgwLCBwb3NpdGlvbiArIG9mZnNldEwsIDApO1xuXG5cdFx0XHRpZiAoYW5ub3RhdGlvbikge1xuXHRcdFx0XHRhbm5vdGF0aW9uLmlubmVyVGV4dCA9IGAke3RoaXMuc2NhbGVDdXJyZW50LnRvRml4ZWQoMil9YDtcblx0XHRcdH1cblxuXHRcdFx0c2NhbGVWLnNldCgxLCAxLCAxKTtcblx0XHRcdHNjYWxlVi5zZXRDb21wb25lbnQoYXhpcywgdXBzY2FsZSk7XG5cdFx0XHRzY2FsZU1hdHJpeC5tYWtlU2NhbGUoc2NhbGVWLngsIHNjYWxlVi55LCBzY2FsZVYueikucHJlbXVsdGlwbHkobVBMRykubXVsdGlwbHkobVBMR0ludik7XG5cdFx0XHR0aGlzLnBpdm90Q29udHJvbHMub25EcmFnKHNjYWxlTWF0cml4KTtcblx0XHR9XG5cdH1cblxuXHRvblBvaW50ZXJVcChldmVudDogTmd0VGhyZWVFdmVudDxQb2ludGVyRXZlbnQ+KSB7XG5cdFx0Y29uc3QgW2Fubm90YXRpb24sIGNvbnRyb2xzLCBwb3NpdGlvbiwgbWVzaF0gPSBbXG5cdFx0XHR0aGlzLmFubm90YXRpb25SZWYoKT8ubmF0aXZlRWxlbWVudCxcblx0XHRcdHRoaXMuY29udHJvbHMoKSxcblx0XHRcdHRoaXMucG9zaXRpb24oKSxcblx0XHRcdHRoaXMubWVzaFJlZigpLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XTtcblxuXHRcdGlmIChhbm5vdGF0aW9uKSB7XG5cdFx0XHRhbm5vdGF0aW9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0fVxuXG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0dGhpcy5zY2FsZTAgPSB0aGlzLnNjYWxlQ3VycmVudDtcblx0XHR0aGlzLmNsaWNrSW5mbyA9IG51bGw7XG5cdFx0bWVzaC5wb3NpdGlvbi5zZXQoMCwgcG9zaXRpb24sIDApO1xuXHRcdHRoaXMucGl2b3RDb250cm9scy5vbkRyYWdFbmQoKTtcblx0XHRpZiAoY29udHJvbHMpIHtcblx0XHRcdGNvbnRyb2xzLmVuYWJsZWQgPSB0cnVlO1xuXHRcdH1cblx0XHQvLyBAdHMtZXhwZWN0LWVycm9yIC0gcmVsZWFzZVBvaW50ZXJDYXB0dXJlIGlzIG5vdCBpbiB0aGUgdHlwZSBkZWZpbml0aW9uXG5cdFx0ZXZlbnQudGFyZ2V0LnJlbGVhc2VQb2ludGVyQ2FwdHVyZShldmVudC5wb2ludGVySWQpO1xuXHR9XG5cblx0b25Qb2ludGVyT3V0KGV2ZW50OiBOZ3RUaHJlZUV2ZW50PFBvaW50ZXJFdmVudD4pIHtcblx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHR0aGlzLmhvdmVyZWQuc2V0KGZhbHNlKTtcblx0fVxufVxuIl19