angular-three-soba 1.0.2 → 1.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.
- package/esm2020/controls/lib/orbit-controls/orbit-controls.mjs +3 -3
- package/esm2020/loaders/index.mjs +4 -1
- package/esm2020/loaders/lib/loader/loader.mjs +133 -0
- package/esm2020/loaders/lib/progress/progress.mjs +39 -0
- package/esm2020/loaders/lib/texture-loader/texture-loader.mjs +19 -0
- package/esm2020/misc/angular-three-soba-misc.mjs +5 -0
- package/esm2020/misc/index.mjs +2 -0
- package/esm2020/misc/lib/bake-shadows/bake-shadows.mjs +25 -0
- package/esm2020/performance/angular-three-soba-performance.mjs +5 -0
- package/esm2020/performance/index.mjs +5 -0
- package/esm2020/performance/lib/adaptive/adaptive-dpr.mjs +46 -0
- package/esm2020/performance/lib/adaptive/adaptive-events.mjs +36 -0
- package/esm2020/performance/lib/detailed/detailed.mjs +50 -0
- package/esm2020/performance/lib/stats/stats.mjs +63 -0
- package/esm2020/shaders/angular-three-soba-shaders.mjs +5 -0
- package/esm2020/shaders/index.mjs +2 -0
- package/esm2020/shaders/lib/shader-material/shader-material.mjs +34 -0
- package/esm2020/staging/angular-three-soba-staging.mjs +5 -0
- package/esm2020/staging/index.mjs +13 -0
- package/esm2020/staging/lib/accumulative-shadows/accumulative-shadows.mjs +276 -0
- package/esm2020/staging/lib/accumulative-shadows/progressive-light-map.mjs +109 -0
- package/esm2020/staging/lib/accumulative-shadows/randomized-lights.mjs +196 -0
- package/esm2020/staging/lib/bounds/bounds.mjs +283 -0
- package/esm2020/staging/lib/center/center.mjs +142 -0
- package/esm2020/staging/lib/contact-shadows/contact-shadows.mjs +227 -0
- package/esm2020/staging/lib/environment/assets.mjs +13 -0
- package/esm2020/staging/lib/environment/environment-cube.mjs +40 -0
- package/esm2020/staging/lib/environment/environment-ground.mjs +66 -0
- package/esm2020/staging/lib/environment/environment-inputs.mjs +86 -0
- package/esm2020/staging/lib/environment/environment-map.mjs +38 -0
- package/esm2020/staging/lib/environment/environment-portal.mjs +110 -0
- package/esm2020/staging/lib/environment/environment.mjs +163 -0
- package/esm2020/staging/lib/environment/utils.mjs +70 -0
- package/esm2020/staging/lib/float/float.mjs +76 -0
- package/esm2020/staging/lib/sky/sky.mjs +111 -0
- package/esm2020/staging/lib/sparkles/sparkles.mjs +209 -0
- package/esm2020/staging/lib/stage/stage.mjs +369 -0
- package/esm2020/staging/lib/stars/stars.mjs +171 -0
- package/fesm2015/angular-three-soba-controls.mjs +3 -3
- package/fesm2015/angular-three-soba-loaders.mjs +187 -3
- package/fesm2015/angular-three-soba-loaders.mjs.map +1 -1
- package/fesm2015/angular-three-soba-misc.mjs +32 -0
- package/fesm2015/angular-three-soba-misc.mjs.map +1 -0
- package/fesm2015/angular-three-soba-performance.mjs +191 -0
- package/fesm2015/angular-three-soba-performance.mjs.map +1 -0
- package/fesm2015/angular-three-soba-shaders.mjs +38 -0
- package/fesm2015/angular-three-soba-shaders.mjs.map +1 -0
- package/fesm2015/angular-three-soba-staging.mjs +2647 -0
- package/fesm2015/angular-three-soba-staging.mjs.map +1 -0
- package/fesm2020/angular-three-soba-controls.mjs +3 -3
- package/fesm2020/angular-three-soba-loaders.mjs +186 -3
- package/fesm2020/angular-three-soba-loaders.mjs.map +1 -1
- package/fesm2020/angular-three-soba-misc.mjs +32 -0
- package/fesm2020/angular-three-soba-misc.mjs.map +1 -0
- package/fesm2020/angular-three-soba-performance.mjs +191 -0
- package/fesm2020/angular-three-soba-performance.mjs.map +1 -0
- package/fesm2020/angular-three-soba-shaders.mjs +41 -0
- package/fesm2020/angular-three-soba-shaders.mjs.map +1 -0
- package/fesm2020/angular-three-soba-staging.mjs +2654 -0
- package/fesm2020/angular-three-soba-staging.mjs.map +1 -0
- package/loaders/index.d.ts +3 -0
- package/loaders/lib/loader/loader.d.ts +26 -0
- package/loaders/lib/progress/progress.d.ts +16 -0
- package/loaders/lib/texture-loader/texture-loader.d.ts +5 -0
- package/misc/README.md +3 -0
- package/misc/index.d.ts +1 -0
- package/misc/lib/bake-shadows/bake-shadows.d.ts +9 -0
- package/package.json +37 -2
- package/performance/README.md +3 -0
- package/performance/index.d.ts +4 -0
- package/performance/lib/adaptive/adaptive-dpr.d.ts +11 -0
- package/performance/lib/adaptive/adaptive-events.d.ts +10 -0
- package/performance/lib/detailed/detailed.d.ts +12 -0
- package/performance/lib/stats/stats.d.ts +14 -0
- package/plugin/package.json +1 -1
- package/plugin/src/generators/init/init.js +13 -17
- package/plugin/src/generators/init/init.js.map +1 -1
- package/shaders/README.md +3 -0
- package/shaders/index.d.ts +1 -0
- package/shaders/lib/shader-material/shader-material.d.ts +6 -0
- package/staging/README.md +3 -0
- package/staging/index.d.ts +12 -0
- package/staging/lib/accumulative-shadows/accumulative-shadows.d.ts +64 -0
- package/staging/lib/accumulative-shadows/progressive-light-map.d.ts +34 -0
- package/staging/lib/accumulative-shadows/randomized-lights.d.ts +42 -0
- package/staging/lib/bounds/bounds.d.ts +48 -0
- package/staging/lib/center/center.d.ts +40 -0
- package/staging/lib/contact-shadows/contact-shadows.d.ts +29 -0
- package/staging/lib/environment/assets.d.ts +13 -0
- package/staging/lib/environment/environment-cube.d.ts +11 -0
- package/staging/lib/environment/environment-ground.d.ts +9 -0
- package/staging/lib/environment/environment-inputs.d.ts +28 -0
- package/staging/lib/environment/environment-map.d.ts +10 -0
- package/staging/lib/environment/environment-portal.d.ts +15 -0
- package/staging/lib/environment/environment.d.ts +12 -0
- package/staging/lib/environment/utils.d.ts +8 -0
- package/staging/lib/float/float.d.ts +16 -0
- package/staging/lib/sky/sky.d.ts +21 -0
- package/staging/lib/sparkles/sparkles.d.ts +29 -0
- package/staging/lib/stage/stage.d.ts +87 -0
- package/staging/lib/stars/stars.d.ts +20 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, Directive, inject, InjectionToken, Input } from '@angular/core';
|
|
2
|
+
import { extend, injectNgtRef, NgtRxStore } from 'angular-three';
|
|
3
|
+
import { combineLatest } from 'rxjs';
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
import { DirectionalLight, Group, OrthographicCamera, Vector2 } from 'three';
|
|
6
|
+
import { NGTS_ACCUMULATIVE_SHADOWS_API } from './accumulative-shadows';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
extend({ Group, DirectionalLight, OrthographicCamera, Vector2 });
|
|
9
|
+
export const NGTS_RANDOMIZED_LIGHTS_API = new InjectionToken('NgtsRandomizedLights API');
|
|
10
|
+
function randomizedLightsApiFactory(randomizedLights) {
|
|
11
|
+
const accumulativeApi = inject(NGTS_ACCUMULATIVE_SHADOWS_API);
|
|
12
|
+
const update = () => {
|
|
13
|
+
let light;
|
|
14
|
+
if (randomizedLights.lightsRef.nativeElement) {
|
|
15
|
+
for (let l = 0; l < randomizedLights.lightsRef.nativeElement.children.length; l++) {
|
|
16
|
+
light = randomizedLights.lightsRef.nativeElement.children[l];
|
|
17
|
+
if (Math.random() > randomizedLights.get('ambient')) {
|
|
18
|
+
const position = randomizedLights.get('position');
|
|
19
|
+
const radius = randomizedLights.get('radius');
|
|
20
|
+
light.position.set(position[0] + THREE.MathUtils.randFloatSpread(radius), position[1] + THREE.MathUtils.randFloatSpread(radius), position[2] + THREE.MathUtils.randFloatSpread(radius));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const lambda = Math.acos(2 * Math.random() - 1) - Math.PI / 2.0;
|
|
24
|
+
const phi = 2 * Math.PI * Math.random();
|
|
25
|
+
const length = randomizedLights.get('length');
|
|
26
|
+
light.position.set(Math.cos(lambda) * Math.cos(phi) * length, Math.abs(Math.cos(lambda) * Math.sin(phi) * length), Math.sin(lambda) * length);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const api = { update };
|
|
32
|
+
randomizedLights.effect(combineLatest([
|
|
33
|
+
randomizedLights.lightsRef.$,
|
|
34
|
+
randomizedLights.select('position'),
|
|
35
|
+
randomizedLights.select('radius'),
|
|
36
|
+
randomizedLights.select('length'),
|
|
37
|
+
randomizedLights.select('ambient'),
|
|
38
|
+
]), ([group]) => {
|
|
39
|
+
if (accumulativeApi)
|
|
40
|
+
accumulativeApi.lights.set(group.uuid, api);
|
|
41
|
+
return () => accumulativeApi.lights.delete(group.uuid);
|
|
42
|
+
});
|
|
43
|
+
return api;
|
|
44
|
+
}
|
|
45
|
+
export class RandomizedLightsConsumer {
|
|
46
|
+
constructor() {
|
|
47
|
+
inject(NGTS_RANDOMIZED_LIGHTS_API);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
RandomizedLightsConsumer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: RandomizedLightsConsumer, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
51
|
+
RandomizedLightsConsumer.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.3", type: RandomizedLightsConsumer, isStandalone: true, selector: "ngts-randomized-lights-consumer", ngImport: i0 });
|
|
52
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: RandomizedLightsConsumer, decorators: [{
|
|
53
|
+
type: Directive,
|
|
54
|
+
args: [{ selector: 'ngts-randomized-lights-consumer', standalone: true }]
|
|
55
|
+
}], ctorParameters: function () { return []; } });
|
|
56
|
+
export class NgtsRandomizedLights extends NgtRxStore {
|
|
57
|
+
constructor() {
|
|
58
|
+
super(...arguments);
|
|
59
|
+
this.lightsRef = injectNgtRef();
|
|
60
|
+
}
|
|
61
|
+
/** How many frames it will jiggle the lights, 1.
|
|
62
|
+
* Frames is context aware, if a provider like AccumulativeShadows exists, frames will be taken from there! */
|
|
63
|
+
set frames(frames) {
|
|
64
|
+
this.set({ frames });
|
|
65
|
+
}
|
|
66
|
+
/** Light position, [0, 0, 0] */
|
|
67
|
+
set position(position) {
|
|
68
|
+
this.set({ position });
|
|
69
|
+
}
|
|
70
|
+
/** Radius of the jiggle, higher values make softer light, 5 */
|
|
71
|
+
set radius(radius) {
|
|
72
|
+
this.set({ radius });
|
|
73
|
+
}
|
|
74
|
+
/** Amount of lights, 8 */
|
|
75
|
+
set amount(amount) {
|
|
76
|
+
this.set({ amount });
|
|
77
|
+
}
|
|
78
|
+
/** Light intensity, 1 */
|
|
79
|
+
set intensity(intensity) {
|
|
80
|
+
this.set({ intensity });
|
|
81
|
+
}
|
|
82
|
+
/** Ambient occlusion, lower values mean less AO, hight more, you can mix AO and directional light, 0.5 */
|
|
83
|
+
set ambient(ambient) {
|
|
84
|
+
this.set({ ambient });
|
|
85
|
+
}
|
|
86
|
+
/** If the lights cast shadows, this is true by default */
|
|
87
|
+
set castShadow(castShadow) {
|
|
88
|
+
this.set({ castShadow });
|
|
89
|
+
}
|
|
90
|
+
/** Default shadow bias, 0 */
|
|
91
|
+
set bias(bias) {
|
|
92
|
+
this.set({ bias });
|
|
93
|
+
}
|
|
94
|
+
/** Default map size, 512 */
|
|
95
|
+
set mapSize(mapSize) {
|
|
96
|
+
this.set({ mapSize });
|
|
97
|
+
}
|
|
98
|
+
/** Default size of the shadow camera, 10 */
|
|
99
|
+
set size(size) {
|
|
100
|
+
this.set({ size });
|
|
101
|
+
}
|
|
102
|
+
/** Default shadow camera near, 0.5 */
|
|
103
|
+
set near(near) {
|
|
104
|
+
this.set({ near });
|
|
105
|
+
}
|
|
106
|
+
/** Default shadow camera far, 500 */
|
|
107
|
+
set far(far) {
|
|
108
|
+
this.set({ far });
|
|
109
|
+
}
|
|
110
|
+
initialize() {
|
|
111
|
+
super.initialize();
|
|
112
|
+
this.set({
|
|
113
|
+
castShadow: true,
|
|
114
|
+
bias: 0.001,
|
|
115
|
+
mapSize: 512,
|
|
116
|
+
size: 5,
|
|
117
|
+
near: 0.5,
|
|
118
|
+
far: 500,
|
|
119
|
+
frames: 1,
|
|
120
|
+
position: [0, 0, 0],
|
|
121
|
+
radius: 1,
|
|
122
|
+
amount: 8,
|
|
123
|
+
intensity: 1,
|
|
124
|
+
ambient: 0.5,
|
|
125
|
+
});
|
|
126
|
+
this.connect('cameraArgs', this.select(['size', 'near', 'far'], ({ size, near, far }) => [-size, size, size, -size, near, far]));
|
|
127
|
+
this.connect('length', this.select(['position'], ({ position }) => new THREE.Vector3(...position).length()));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
NgtsRandomizedLights.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: NgtsRandomizedLights, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
131
|
+
NgtsRandomizedLights.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.3", type: NgtsRandomizedLights, isStandalone: true, selector: "ngts-randomized-lights", inputs: { lightsRef: "lightsRef", frames: "frames", position: "position", radius: "radius", amount: "amount", intensity: "intensity", ambient: "ambient", castShadow: "castShadow", bias: "bias", mapSize: "mapSize", size: "size", near: "near", far: "far" }, providers: [
|
|
132
|
+
{ provide: NGTS_RANDOMIZED_LIGHTS_API, useFactory: randomizedLightsApiFactory, deps: [NgtsRandomizedLights] },
|
|
133
|
+
], usesInheritance: true, ngImport: i0, template: `
|
|
134
|
+
<ngt-group ngtCompound [ref]="lightsRef">
|
|
135
|
+
<ngt-directional-light
|
|
136
|
+
*ngFor="let i; repeat: get('amount')"
|
|
137
|
+
[castShadow]="get('castShadow')"
|
|
138
|
+
[intensity]="get('intensity') / get('amount')"
|
|
139
|
+
>
|
|
140
|
+
<ngt-value [rawValue]="get('bias')" attach="shadow.bias" />
|
|
141
|
+
<ngt-vector2 *args="[get('mapSize'), get('mapSize')]" attach="shadow.mapSize" />
|
|
142
|
+
<ngt-orthographic-camera *args="get('cameraArgs')" attach="shadow.camera" />
|
|
143
|
+
</ngt-directional-light>
|
|
144
|
+
</ngt-group>
|
|
145
|
+
`, isInline: true });
|
|
146
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: NgtsRandomizedLights, decorators: [{
|
|
147
|
+
type: Component,
|
|
148
|
+
args: [{
|
|
149
|
+
selector: 'ngts-randomized-lights',
|
|
150
|
+
standalone: true,
|
|
151
|
+
template: `
|
|
152
|
+
<ngt-group ngtCompound [ref]="lightsRef">
|
|
153
|
+
<ngt-directional-light
|
|
154
|
+
*ngFor="let i; repeat: get('amount')"
|
|
155
|
+
[castShadow]="get('castShadow')"
|
|
156
|
+
[intensity]="get('intensity') / get('amount')"
|
|
157
|
+
>
|
|
158
|
+
<ngt-value [rawValue]="get('bias')" attach="shadow.bias" />
|
|
159
|
+
<ngt-vector2 *args="[get('mapSize'), get('mapSize')]" attach="shadow.mapSize" />
|
|
160
|
+
<ngt-orthographic-camera *args="get('cameraArgs')" attach="shadow.camera" />
|
|
161
|
+
</ngt-directional-light>
|
|
162
|
+
</ngt-group>
|
|
163
|
+
`,
|
|
164
|
+
providers: [
|
|
165
|
+
{ provide: NGTS_RANDOMIZED_LIGHTS_API, useFactory: randomizedLightsApiFactory, deps: [NgtsRandomizedLights] },
|
|
166
|
+
],
|
|
167
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
168
|
+
}]
|
|
169
|
+
}], propDecorators: { lightsRef: [{
|
|
170
|
+
type: Input
|
|
171
|
+
}], frames: [{
|
|
172
|
+
type: Input
|
|
173
|
+
}], position: [{
|
|
174
|
+
type: Input
|
|
175
|
+
}], radius: [{
|
|
176
|
+
type: Input
|
|
177
|
+
}], amount: [{
|
|
178
|
+
type: Input
|
|
179
|
+
}], intensity: [{
|
|
180
|
+
type: Input
|
|
181
|
+
}], ambient: [{
|
|
182
|
+
type: Input
|
|
183
|
+
}], castShadow: [{
|
|
184
|
+
type: Input
|
|
185
|
+
}], bias: [{
|
|
186
|
+
type: Input
|
|
187
|
+
}], mapSize: [{
|
|
188
|
+
type: Input
|
|
189
|
+
}], size: [{
|
|
190
|
+
type: Input
|
|
191
|
+
}], near: [{
|
|
192
|
+
type: Input
|
|
193
|
+
}], far: [{
|
|
194
|
+
type: Input
|
|
195
|
+
}] } });
|
|
196
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFuZG9taXplZC1saWdodHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2FuZ3VsYXItdGhyZWUtc29iYS9zdGFnaW5nL3NyYy9saWIvYWNjdW11bGF0aXZlLXNoYWRvd3MvcmFuZG9taXplZC1saWdodHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxzQkFBc0IsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDNUcsT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckMsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDL0IsT0FBTyxFQUFFLGdCQUFnQixFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDN0UsT0FBTyxFQUFtQyw2QkFBNkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDOztBQUV4RyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztBQUVqRSxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLGNBQWMsQ0FDeEQsMEJBQTBCLENBQzdCLENBQUM7QUFFRixTQUFTLDBCQUEwQixDQUFDLGdCQUFzQztJQUN0RSxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUU5RCxNQUFNLE1BQU0sR0FBRyxHQUFHLEVBQUU7UUFDaEIsSUFBSSxLQUF5QyxDQUFDO1FBQzlDLElBQUksZ0JBQWdCLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRTtZQUMxQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFB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c0JBQW5CLEtBQUs7Z0JBS08sVUFBVTtzQkFBdEIsS0FBSztnQkFLTyxJQUFJO3NCQUFoQixLQUFLO2dCQUtPLE9BQU87c0JBQW5CLEtBQUs7Z0JBS08sSUFBSTtzQkFBaEIsS0FBSztnQkFLTyxJQUFJO3NCQUFoQixLQUFLO2dCQUtPLEdBQUc7c0JBQWYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQSwgRGlyZWN0aXZlLCBpbmplY3QsIEluamVjdGlvblRva2VuLCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZXh0ZW5kLCBpbmplY3ROZ3RSZWYsIE5ndFJ4U3RvcmUgfSBmcm9tICdhbmd1bGFyLXRocmVlJztcbmltcG9ydCB7IGNvbWJpbmVMYXRlc3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IERpcmVjdGlvbmFsTGlnaHQsIEdyb3VwLCBPcnRob2dyYXBoaWNDYW1lcmEsIFZlY3RvcjIgfSBmcm9tICd0aHJlZSc7XG5pbXBvcnQgeyBOZ3RzQWNjdW11bGF0aXZlU2hhZG93c0xpZ2h0QXBpLCBOR1RTX0FDQ1VNVUxBVElWRV9TSEFET1dTX0FQSSB9IGZyb20gJy4vYWNjdW11bGF0aXZlLXNoYWRvd3MnO1xuXG5leHRlbmQoeyBHcm91cCwgRGlyZWN0aW9uYWxMaWdodCwgT3J0aG9ncmFwaGljQ2FtZXJhLCBWZWN0b3IyIH0pO1xuXG5leHBvcnQgY29uc3QgTkdUU19SQU5ET01JWkVEX0xJR0hUU19BUEkgPSBuZXcgSW5qZWN0aW9uVG9rZW48Tmd0c0FjY3VtdWxhdGl2ZVNoYWRvd3NMaWdodEFwaT4oXG4gICAgJ05ndHNSYW5kb21pemVkTGlnaHRzIEFQSSdcbik7XG5cbmZ1bmN0aW9uIHJhbmRvbWl6ZWRMaWdodHNBcGlGYWN0b3J5KHJhbmRvbWl6ZWRMaWdodHM6IE5ndHNSYW5kb21pemVkTGlnaHRzKSB7XG4gICAgY29uc3QgYWNjdW11bGF0aXZlQXBpID0gaW5qZWN0KE5HVFNfQUNDVU1VTEFUSVZFX1NIQURPV1NfQVBJKTtcblxuICAgIGNvbnN0IHVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgbGV0IGxpZ2h0OiBUSFJFRS5EaXJlY3Rpb25hbExpZ2h0IHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAocmFuZG9taXplZExpZ2h0cy5saWdodHNSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgZm9yIChsZXQgbCA9IDA7IGwgPCByYW5kb21pemVkTGlnaHRzLmxpZ2h0c1JlZi5uYXRpdmVFbGVtZW50LmNoaWxkcmVuLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgICAgICAgICAgbGlnaHQgPSByYW5kb21pemVkTGlnaHRzLmxpZ2h0c1JlZi5uYXRpdmVFbGVtZW50LmNoaWxkcmVuW2xdIGFzIFRIUkVFLkRpcmVjdGlvbmFsTGlnaHQ7XG4gICAgICAgICAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPiByYW5kb21pemVkTGlnaHRzLmdldCgnYW1iaWVudCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gcmFuZG9taXplZExpZ2h0cy5nZXQoJ3Bvc2l0aW9uJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhZGl1cyA9IHJhbmRvbWl6ZWRMaWdodHMuZ2V0KCdyYWRpdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgbGlnaHQucG9zaXRpb24uc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25bMF0gKyBUSFJFRS5NYXRoVXRpbHMucmFuZEZsb2F0U3ByZWFkKHJhZGl1cyksXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvblsxXSArIFRIUkVFLk1hdGhVdGlscy5yYW5kRmxvYXRTcHJlYWQocmFkaXVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uWzJdICsgVEhSRUUuTWF0aFV0aWxzLnJhbmRGbG9hdFNwcmVhZChyYWRpdXMpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFtYmRhID0gTWF0aC5hY29zKDIgKiBNYXRoLnJhbmRvbSgpIC0gMSkgLSBNYXRoLlBJIC8gMi4wO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwaGkgPSAyICogTWF0aC5QSSAqIE1hdGgucmFuZG9tKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHJhbmRvbWl6ZWRMaWdodHMuZ2V0KCdsZW5ndGgnKTtcbiAgICAgICAgICAgICAgICAgICAgbGlnaHQucG9zaXRpb24uc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5jb3MobGFtYmRhKSAqIE1hdGguY29zKHBoaSkgKiBsZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmFicyhNYXRoLmNvcyhsYW1iZGEpICogTWF0aC5zaW4ocGhpKSAqIGxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLnNpbihsYW1iZGEpICogbGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGFwaSA9IHsgdXBkYXRlIH0gYXMgTmd0c0FjY3VtdWxhdGl2ZVNoYWRvd3NMaWdodEFwaTtcblxuICAgIHJhbmRvbWl6ZWRMaWdodHMuZWZmZWN0KFxuICAgICAgICBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgICAgIHJhbmRvbWl6ZWRMaWdodHMubGlnaHRzUmVmLiQsXG4gICAgICAgICAgICByYW5kb21pemVkTGlnaHRzLnNlbGVjdCgncG9zaXRpb24nKSxcbiAgICAgICAgICAgIHJhbmRvbWl6ZWRMaWdodHMuc2VsZWN0KCdyYWRpdXMnKSxcbiAgICAgICAgICAgIHJhbmRvbWl6ZWRMaWdodHMuc2VsZWN0KCdsZW5ndGgnKSxcbiAgICAgICAgICAgIHJhbmRvbWl6ZWRMaWdodHMuc2VsZWN0KCdhbWJpZW50JyksXG4gICAgICAgIF0pLFxuICAgICAgICAoW2dyb3VwXSkgPT4ge1xuICAgICAgICAgICAgaWYgKGFjY3VtdWxhdGl2ZUFwaSkgYWNjdW11bGF0aXZlQXBpLmxpZ2h0cy5zZXQoZ3JvdXAudXVpZCwgYXBpKTtcbiAgICAgICAgICAgIHJldHVybiAoKSA9PiBhY2N1bXVsYXRpdmVBcGkubGlnaHRzLmRlbGV0ZShncm91cC51dWlkKTtcbiAgICAgICAgfVxuICAgICk7XG5cbiAgICByZXR1cm4gYXBpO1xufVxuXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICduZ3RzLXJhbmRvbWl6ZWQtbGlnaHRzLWNvbnN1bWVyJywgc3RhbmRhbG9uZTogdHJ1ZSB9KVxuZXhwb3J0IGNsYXNzIFJhbmRvbWl6ZWRMaWdodHNDb25zdW1lciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGluamVjdChOR1RTX1JBTkRPTUlaRURfTElHSFRTX0FQSSk7XG4gICAgfVxufVxuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ndHMtcmFuZG9taXplZC1saWdodHMnLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgdGVtcGxhdGU6IGBcbiAgICAgICAgPG5ndC1ncm91cCBuZ3RDb21wb3VuZCBbcmVmXT1cImxpZ2h0c1JlZlwiPlxuICAgICAgICAgICAgPG5ndC1kaXJlY3Rpb25hbC1saWdodFxuICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpOyByZXBlYXQ6IGdldCgnYW1vdW50JylcIlxuICAgICAgICAgICAgICAgIFtjYXN0U2hhZG93XT1cImdldCgnY2FzdFNoYWRvdycpXCJcbiAgICAgICAgICAgICAgICBbaW50ZW5zaXR5XT1cImdldCgnaW50ZW5zaXR5JykgLyBnZXQoJ2Ftb3VudCcpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bmd0LXZhbHVlIFtyYXdWYWx1ZV09XCJnZXQoJ2JpYXMnKVwiIGF0dGFjaD1cInNoYWRvdy5iaWFzXCIgLz5cbiAgICAgICAgICAgICAgICA8bmd0LXZlY3RvcjIgKmFyZ3M9XCJbZ2V0KCdtYXBTaXplJyksIGdldCgnbWFwU2l6ZScpXVwiIGF0dGFjaD1cInNoYWRvdy5tYXBTaXplXCIgLz5cbiAgICAgICAgICAgICAgICA8bmd0LW9ydGhvZ3JhcGhpYy1jYW1lcmEgKmFyZ3M9XCJnZXQoJ2NhbWVyYUFyZ3MnKVwiIGF0dGFjaD1cInNoYWRvdy5jYW1lcmFcIiAvPlxuICAgICAgICAgICAgPC9uZ3QtZGlyZWN0aW9uYWwtbGlnaHQ+XG4gICAgICAgIDwvbmd0LWdyb3VwPlxuICAgIGAsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHsgcHJvdmlkZTogTkdUU19SQU5ET01JWkVEX0xJR0hUU19BUEksIHVzZUZhY3Rvcnk6IHJhbmRvbWl6ZWRMaWdodHNBcGlGYWN0b3J5LCBkZXBzOiBbTmd0c1JhbmRvbWl6ZWRMaWdodHNdIH0sXG4gICAgXSxcbiAgICBzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXG59KVxuZXhwb3J0IGNsYXNzIE5ndHNSYW5kb21pemVkTGlnaHRzIGV4dGVuZHMgTmd0UnhTdG9yZSB7XG4gICAgQElucHV0KCkgbGlnaHRzUmVmID0gaW5qZWN0Tmd0UmVmPFRIUkVFLkdyb3VwPigpO1xuICAgIC8qKiBIb3cgbWFueSBmcmFtZXMgaXQgd2lsbCBqaWdnbGUgdGhlIGxpZ2h0cywgMS5cbiAgICAgKiAgRnJhbWVzIGlzIGNvbnRleHQgYXdhcmUsIGlmIGEgcHJvdmlkZXIgbGlrZSBBY2N1bXVsYXRpdmVTaGFkb3dzIGV4aXN0cywgZnJhbWVzIHdpbGwgYmUgdGFrZW4gZnJvbSB0aGVyZSEgICovXG4gICAgQElucHV0KCkgc2V0IGZyYW1lcyhmcmFtZXM6IG51bWJlcikge1xuICAgICAgICB0aGlzLnNldCh7IGZyYW1lcyB9KTtcbiAgICB9XG5cbiAgICAvKiogTGlnaHQgcG9zaXRpb24sIFswLCAwLCAwXSAqL1xuICAgIEBJbnB1dCgpIHNldCBwb3NpdGlvbihwb3NpdGlvbjogW3g6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXJdKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgcG9zaXRpb24gfSk7XG4gICAgfVxuXG4gICAgLyoqIFJhZGl1cyBvZiB0aGUgamlnZ2xlLCBoaWdoZXIgdmFsdWVzIG1ha2Ugc29mdGVyIGxpZ2h0LCA1ICovXG4gICAgQElucHV0KCkgc2V0IHJhZGl1cyhyYWRpdXM6IG51bWJlcikge1xuICAgICAgICB0aGlzLnNldCh7IHJhZGl1cyB9KTtcbiAgICB9XG5cbiAgICAvKiogQW1vdW50IG9mIGxpZ2h0cywgOCAqL1xuICAgIEBJbnB1dCgpIHNldCBhbW91bnQoYW1vdW50OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5zZXQoeyBhbW91bnQgfSk7XG4gICAgfVxuXG4gICAgLyoqIExpZ2h0IGludGVuc2l0eSwgMSAqL1xuICAgIEBJbnB1dCgpIHNldCBpbnRlbnNpdHkoaW50ZW5zaXR5OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5zZXQoeyBpbnRlbnNpdHkgfSk7XG4gICAgfVxuXG4gICAgLyoqIEFtYmllbnQgb2NjbHVzaW9uLCBsb3dlciB2YWx1ZXMgbWVhbiBsZXNzIEFPLCBoaWdodCBtb3JlLCB5b3UgY2FuIG1peCBBTyBhbmQgZGlyZWN0aW9uYWwgbGlnaHQsIDAuNSAqL1xuICAgIEBJbnB1dCgpIHNldCBhbWJpZW50KGFtYmllbnQ6IG51bWJlcikge1xuICAgICAgICB0aGlzLnNldCh7IGFtYmllbnQgfSk7XG4gICAgfVxuXG4gICAgLyoqIElmIHRoZSBsaWdodHMgY2FzdCBzaGFkb3dzLCB0aGlzIGlzIHRydWUgYnkgZGVmYXVsdCAqL1xuICAgIEBJbnB1dCgpIHNldCBjYXN0U2hhZG93KGNhc3RTaGFkb3c6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5zZXQoeyBjYXN0U2hhZG93IH0pO1xuICAgIH1cblxuICAgIC8qKiBEZWZhdWx0IHNoYWRvdyBiaWFzLCAwICovXG4gICAgQElucHV0KCkgc2V0IGJpYXMoYmlhczogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgYmlhcyB9KTtcbiAgICB9XG5cbiAgICAvKiogRGVmYXVsdCBtYXAgc2l6ZSwgNTEyICovXG4gICAgQElucHV0KCkgc2V0IG1hcFNpemUobWFwU2l6ZTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgbWFwU2l6ZSB9KTtcbiAgICB9XG5cbiAgICAvKiogRGVmYXVsdCBzaXplIG9mIHRoZSBzaGFkb3cgY2FtZXJhLCAxMCAqL1xuICAgIEBJbnB1dCgpIHNldCBzaXplKHNpemU6IG51bWJlcikge1xuICAgICAgICB0aGlzLnNldCh7IHNpemUgfSk7XG4gICAgfVxuXG4gICAgLyoqIERlZmF1bHQgc2hhZG93IGNhbWVyYSBuZWFyLCAwLjUgKi9cbiAgICBASW5wdXQoKSBzZXQgbmVhcihuZWFyOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5zZXQoeyBuZWFyIH0pO1xuICAgIH1cblxuICAgIC8qKiBEZWZhdWx0IHNoYWRvdyBjYW1lcmEgZmFyLCA1MDAgKi9cbiAgICBASW5wdXQoKSBzZXQgZmFyKGZhcjogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgZmFyIH0pO1xuICAgIH1cblxuICAgIG92ZXJyaWRlIGluaXRpYWxpemUoKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLmluaXRpYWxpemUoKTtcbiAgICAgICAgdGhpcy5zZXQoe1xuICAgICAgICAgICAgY2FzdFNoYWRvdzogdHJ1ZSxcbiAgICAgICAgICAgIGJpYXM6IDAuMDAxLFxuICAgICAgICAgICAgbWFwU2l6ZTogNTEyLFxuICAgICAgICAgICAgc2l6ZTogNSxcbiAgICAgICAgICAgIG5lYXI6IDAuNSxcbiAgICAgICAgICAgIGZhcjogNTAwLFxuICAgICAgICAgICAgZnJhbWVzOiAxLFxuICAgICAgICAgICAgcG9zaXRpb246IFswLCAwLCAwXSxcbiAgICAgICAgICAgIHJhZGl1czogMSxcbiAgICAgICAgICAgIGFtb3VudDogOCxcbiAgICAgICAgICAgIGludGVuc2l0eTogMSxcbiAgICAgICAgICAgIGFtYmllbnQ6IDAuNSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY29ubmVjdChcbiAgICAgICAgICAgICdjYW1lcmFBcmdzJyxcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0KFsnc2l6ZScsICduZWFyJywgJ2ZhciddLCAoeyBzaXplLCBuZWFyLCBmYXIgfSkgPT4gWy1zaXplLCBzaXplLCBzaXplLCAtc2l6ZSwgbmVhciwgZmFyXSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5jb25uZWN0KFxuICAgICAgICAgICAgJ2xlbmd0aCcsXG4gICAgICAgICAgICB0aGlzLnNlbGVjdChbJ3Bvc2l0aW9uJ10sICh7IHBvc2l0aW9uIH0pID0+IG5ldyBUSFJFRS5WZWN0b3IzKC4uLnBvc2l0aW9uKS5sZW5ndGgoKSlcbiAgICAgICAgKTtcbiAgICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, inject, InjectionToken, Input, Output, } from '@angular/core';
|
|
2
|
+
import { extend, injectBeforeRender, injectNgtRef, is, NgtRxStore, NgtStore } from 'angular-three';
|
|
3
|
+
import { combineLatest, switchMap } from 'rxjs';
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
import { Group } from 'three';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
const isBox3 = (def) => !!def && def.isBox3;
|
|
8
|
+
function equals(a, b, eps) {
|
|
9
|
+
return Math.abs(a.x - b.x) < eps && Math.abs(a.y - b.y) < eps && Math.abs(a.z - b.z) < eps;
|
|
10
|
+
}
|
|
11
|
+
function damp(v, t, lambda, delta) {
|
|
12
|
+
v.x = THREE.MathUtils.damp(v.x, t.x, lambda, delta);
|
|
13
|
+
v.y = THREE.MathUtils.damp(v.y, t.y, lambda, delta);
|
|
14
|
+
v.z = THREE.MathUtils.damp(v.z, t.z, lambda, delta);
|
|
15
|
+
}
|
|
16
|
+
export const NGTS_BOUNDS_API = new InjectionToken('NgtsBounds API');
|
|
17
|
+
function boundsApiFactory(bounds) {
|
|
18
|
+
const store = inject(NgtStore);
|
|
19
|
+
const box = new THREE.Box3();
|
|
20
|
+
function getSize() {
|
|
21
|
+
const camera = store.get('camera');
|
|
22
|
+
const margin = bounds.get('margin');
|
|
23
|
+
const size = box.getSize(new THREE.Vector3());
|
|
24
|
+
const center = box.getCenter(new THREE.Vector3());
|
|
25
|
+
const maxSize = Math.max(size.x, size.y, size.z);
|
|
26
|
+
const fitHeightDistance = is.orthographicCamera(camera)
|
|
27
|
+
? maxSize * 4
|
|
28
|
+
: maxSize / (2 * Math.atan((Math.PI * camera.fov) / 360));
|
|
29
|
+
const fitWidthDistance = is.orthographicCamera(camera) ? maxSize * 4 : fitHeightDistance / camera.aspect;
|
|
30
|
+
const distance = margin * Math.max(fitHeightDistance, fitWidthDistance);
|
|
31
|
+
return { box, size, center, distance };
|
|
32
|
+
}
|
|
33
|
+
const api = {
|
|
34
|
+
getSize,
|
|
35
|
+
refresh(object) {
|
|
36
|
+
const { camera, controls: storeControls } = store.get();
|
|
37
|
+
const controls = storeControls;
|
|
38
|
+
if (isBox3(object))
|
|
39
|
+
box.copy(object);
|
|
40
|
+
else {
|
|
41
|
+
const target = object || bounds.boundsRef.nativeElement;
|
|
42
|
+
if (target) {
|
|
43
|
+
target.updateWorldMatrix(true, true);
|
|
44
|
+
box.setFromObject(target);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (box.isEmpty()) {
|
|
48
|
+
const max = camera.position.length() || 10;
|
|
49
|
+
box.setFromCenterAndSize(new THREE.Vector3(), new THREE.Vector3(max, max, max));
|
|
50
|
+
}
|
|
51
|
+
if (controls?.constructor.name === 'OrthographicTrackballControls') {
|
|
52
|
+
// put camera on a sphere along which it would move
|
|
53
|
+
const { distance } = getSize();
|
|
54
|
+
const direction = camera.position.clone().sub(controls.target).normalize().multiplyScalar(distance);
|
|
55
|
+
const newPos = controls.target.clone().add(direction);
|
|
56
|
+
camera.position.copy(newPos);
|
|
57
|
+
}
|
|
58
|
+
return this;
|
|
59
|
+
},
|
|
60
|
+
clip() {
|
|
61
|
+
const { distance } = getSize();
|
|
62
|
+
const { camera, controls: storeControls, invalidate } = store.get();
|
|
63
|
+
const controls = storeControls;
|
|
64
|
+
if (controls)
|
|
65
|
+
controls.maxDistance = distance * 10;
|
|
66
|
+
camera.near = distance / 100;
|
|
67
|
+
camera.far = distance * 100;
|
|
68
|
+
camera.updateProjectionMatrix();
|
|
69
|
+
if (controls)
|
|
70
|
+
controls.update();
|
|
71
|
+
invalidate();
|
|
72
|
+
return this;
|
|
73
|
+
},
|
|
74
|
+
to({ position, target }) {
|
|
75
|
+
const { camera } = store.get();
|
|
76
|
+
const { damping } = bounds.get();
|
|
77
|
+
bounds.current.camera.copy(camera.position);
|
|
78
|
+
const { center } = getSize();
|
|
79
|
+
bounds.goal.camera.set(...position);
|
|
80
|
+
if (target) {
|
|
81
|
+
bounds.goal.focus.set(...target);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
bounds.goal.focus.copy(center);
|
|
85
|
+
}
|
|
86
|
+
if (damping) {
|
|
87
|
+
bounds.current.animating = true;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
camera.position.set(...position);
|
|
91
|
+
}
|
|
92
|
+
return this;
|
|
93
|
+
},
|
|
94
|
+
fit() {
|
|
95
|
+
const { camera, controls: storeControls, invalidate } = store.get();
|
|
96
|
+
const controls = storeControls;
|
|
97
|
+
const { damping, margin } = bounds.get();
|
|
98
|
+
bounds.current.camera.copy(camera.position);
|
|
99
|
+
if (controls)
|
|
100
|
+
bounds.current.focus.copy(controls.target);
|
|
101
|
+
const { center, distance } = getSize();
|
|
102
|
+
const direction = center.clone().sub(camera.position).normalize().multiplyScalar(distance);
|
|
103
|
+
bounds.goal.camera.copy(center).sub(direction);
|
|
104
|
+
bounds.goal.focus.copy(center);
|
|
105
|
+
if (is.orthographicCamera(camera)) {
|
|
106
|
+
bounds.current.zoom = camera.zoom;
|
|
107
|
+
let maxHeight = 0, maxWidth = 0;
|
|
108
|
+
const vertices = [
|
|
109
|
+
new THREE.Vector3(box.min.x, box.min.y, box.min.z),
|
|
110
|
+
new THREE.Vector3(box.min.x, box.max.y, box.min.z),
|
|
111
|
+
new THREE.Vector3(box.min.x, box.min.y, box.max.z),
|
|
112
|
+
new THREE.Vector3(box.min.x, box.max.y, box.max.z),
|
|
113
|
+
new THREE.Vector3(box.max.x, box.max.y, box.max.z),
|
|
114
|
+
new THREE.Vector3(box.max.x, box.max.y, box.min.z),
|
|
115
|
+
new THREE.Vector3(box.max.x, box.min.y, box.max.z),
|
|
116
|
+
new THREE.Vector3(box.max.x, box.min.y, box.min.z),
|
|
117
|
+
];
|
|
118
|
+
// Transform the center and each corner to camera space
|
|
119
|
+
center.applyMatrix4(camera.matrixWorldInverse);
|
|
120
|
+
for (const v of vertices) {
|
|
121
|
+
v.applyMatrix4(camera.matrixWorldInverse);
|
|
122
|
+
maxHeight = Math.max(maxHeight, Math.abs(v.y - center.y));
|
|
123
|
+
maxWidth = Math.max(maxWidth, Math.abs(v.x - center.x));
|
|
124
|
+
}
|
|
125
|
+
maxHeight *= 2;
|
|
126
|
+
maxWidth *= 2;
|
|
127
|
+
const zoomForHeight = (camera.top - camera.bottom) / maxHeight;
|
|
128
|
+
const zoomForWidth = (camera.right - camera.left) / maxWidth;
|
|
129
|
+
bounds.goal.zoom = Math.min(zoomForHeight, zoomForWidth) / margin;
|
|
130
|
+
if (!damping) {
|
|
131
|
+
camera.zoom = bounds.goal.zoom;
|
|
132
|
+
camera.updateProjectionMatrix();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (damping) {
|
|
136
|
+
bounds.current.animating = true;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
camera.position.copy(bounds.goal.camera);
|
|
140
|
+
camera.lookAt(bounds.goal.focus);
|
|
141
|
+
if (controls) {
|
|
142
|
+
controls.target.copy(bounds.goal.focus);
|
|
143
|
+
controls.update();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (bounds.fitted.observed)
|
|
147
|
+
bounds.fitted.emit(this.getSize());
|
|
148
|
+
invalidate();
|
|
149
|
+
return this;
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
let count = 0;
|
|
153
|
+
bounds.hold(bounds.boundsRef.$.pipe(switchMap(() => combineLatest([
|
|
154
|
+
bounds.select('clip'),
|
|
155
|
+
bounds.select('fit'),
|
|
156
|
+
bounds.select('observe'),
|
|
157
|
+
store.select('camera'),
|
|
158
|
+
store.select('controls'),
|
|
159
|
+
store.select('size'),
|
|
160
|
+
bounds.boundsRef.children$(),
|
|
161
|
+
]))), ([clip, fit, observe]) => {
|
|
162
|
+
if (observe || count++ === 0) {
|
|
163
|
+
api.refresh();
|
|
164
|
+
if (fit)
|
|
165
|
+
api.fit();
|
|
166
|
+
if (clip)
|
|
167
|
+
api.clip();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
injectBeforeRender(({ delta }) => {
|
|
171
|
+
if (bounds.current.animating) {
|
|
172
|
+
const { damping, eps } = bounds.get();
|
|
173
|
+
const { camera, controls: storeControls, invalidate } = store.get();
|
|
174
|
+
const controls = storeControls;
|
|
175
|
+
damp(bounds.current.focus, bounds.goal.focus, damping, delta);
|
|
176
|
+
damp(bounds.current.camera, bounds.goal.camera, damping, delta);
|
|
177
|
+
bounds.current.zoom = THREE.MathUtils.damp(bounds.current.zoom, bounds.goal.zoom, damping, delta);
|
|
178
|
+
camera.position.copy(bounds.current.camera);
|
|
179
|
+
if (is.orthographicCamera(camera)) {
|
|
180
|
+
camera.zoom = bounds.current.zoom;
|
|
181
|
+
camera.updateProjectionMatrix();
|
|
182
|
+
}
|
|
183
|
+
if (!controls) {
|
|
184
|
+
camera.lookAt(bounds.current.focus);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
controls.target.copy(bounds.current.focus);
|
|
188
|
+
controls.update();
|
|
189
|
+
}
|
|
190
|
+
invalidate();
|
|
191
|
+
if (is.orthographicCamera(camera) && !(Math.abs(bounds.current.zoom - bounds.goal.zoom) < eps))
|
|
192
|
+
return;
|
|
193
|
+
if (!is.orthographicCamera(camera) && !equals(bounds.current.camera, bounds.goal.camera, eps))
|
|
194
|
+
return;
|
|
195
|
+
if (controls && !equals(bounds.current.focus, bounds.goal.focus, eps))
|
|
196
|
+
return;
|
|
197
|
+
bounds.current.animating = false;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return api;
|
|
201
|
+
}
|
|
202
|
+
extend({ Group });
|
|
203
|
+
export class NgtsBounds extends NgtRxStore {
|
|
204
|
+
constructor() {
|
|
205
|
+
super(...arguments);
|
|
206
|
+
this.boundsRef = injectNgtRef();
|
|
207
|
+
this.fitted = new EventEmitter();
|
|
208
|
+
this.store = inject(NgtStore);
|
|
209
|
+
this.current = { animating: false, focus: new THREE.Vector3(), camera: new THREE.Vector3(), zoom: 1 };
|
|
210
|
+
this.goal = { focus: new THREE.Vector3(), camera: new THREE.Vector3(), zoom: 1 };
|
|
211
|
+
}
|
|
212
|
+
set damping(damping) {
|
|
213
|
+
this.set({ damping });
|
|
214
|
+
}
|
|
215
|
+
set fit(fit) {
|
|
216
|
+
this.set({ fit });
|
|
217
|
+
}
|
|
218
|
+
set clip(clip) {
|
|
219
|
+
this.set({ clip });
|
|
220
|
+
}
|
|
221
|
+
set observe(observe) {
|
|
222
|
+
this.set({ observe });
|
|
223
|
+
}
|
|
224
|
+
set margin(margin) {
|
|
225
|
+
this.set({ margin });
|
|
226
|
+
}
|
|
227
|
+
set eps(eps) {
|
|
228
|
+
this.set({ eps });
|
|
229
|
+
}
|
|
230
|
+
initialize() {
|
|
231
|
+
super.initialize();
|
|
232
|
+
this.set({ damping: 6, fit: false, clip: false, observe: false, margin: 1.2, eps: 0.01 });
|
|
233
|
+
}
|
|
234
|
+
ngOnInit() {
|
|
235
|
+
this.preventDragHijacking();
|
|
236
|
+
}
|
|
237
|
+
preventDragHijacking() {
|
|
238
|
+
this.effect(this.store.select('controls'), (controls) => {
|
|
239
|
+
if (controls) {
|
|
240
|
+
const callback = () => (this.current.animating = false);
|
|
241
|
+
controls.addEventListener('start', callback);
|
|
242
|
+
return () => controls.removeEventListener('start', callback);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
NgtsBounds.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: NgtsBounds, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
248
|
+
NgtsBounds.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.3", type: NgtsBounds, isStandalone: true, selector: "ngts-bounds", inputs: { boundsRef: "boundsRef", damping: "damping", fit: "fit", clip: "clip", observe: "observe", margin: "margin", eps: "eps" }, outputs: { fitted: "fitted" }, providers: [{ provide: NGTS_BOUNDS_API, useFactory: boundsApiFactory, deps: [NgtsBounds] }], usesInheritance: true, ngImport: i0, template: `
|
|
249
|
+
<ngt-group ngtCompound [ref]="boundsRef">
|
|
250
|
+
<ng-content />
|
|
251
|
+
</ngt-group>
|
|
252
|
+
`, isInline: true });
|
|
253
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.3", ngImport: i0, type: NgtsBounds, decorators: [{
|
|
254
|
+
type: Component,
|
|
255
|
+
args: [{
|
|
256
|
+
selector: 'ngts-bounds',
|
|
257
|
+
standalone: true,
|
|
258
|
+
template: `
|
|
259
|
+
<ngt-group ngtCompound [ref]="boundsRef">
|
|
260
|
+
<ng-content />
|
|
261
|
+
</ngt-group>
|
|
262
|
+
`,
|
|
263
|
+
providers: [{ provide: NGTS_BOUNDS_API, useFactory: boundsApiFactory, deps: [NgtsBounds] }],
|
|
264
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
265
|
+
}]
|
|
266
|
+
}], propDecorators: { boundsRef: [{
|
|
267
|
+
type: Input
|
|
268
|
+
}], damping: [{
|
|
269
|
+
type: Input
|
|
270
|
+
}], fit: [{
|
|
271
|
+
type: Input
|
|
272
|
+
}], clip: [{
|
|
273
|
+
type: Input
|
|
274
|
+
}], observe: [{
|
|
275
|
+
type: Input
|
|
276
|
+
}], margin: [{
|
|
277
|
+
type: Input
|
|
278
|
+
}], eps: [{
|
|
279
|
+
type: Input
|
|
280
|
+
}], fitted: [{
|
|
281
|
+
type: Output
|
|
282
|
+
}] } });
|
|
283
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm91bmRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9hbmd1bGFyLXRocmVlLXNvYmEvc3RhZ2luZy9zcmMvbGliL2JvdW5kcy9ib3VuZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxzQkFBc0IsRUFDdEIsWUFBWSxFQUNaLE1BQU0sRUFDTixjQUFjLEVBQ2QsS0FBSyxFQUVMLE1BQU0sR0FDVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsTUFBTSxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRyxPQUFPLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoRCxPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMvQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDOztBQStCOUIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFZLEVBQXFCLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFLLEdBQWtCLENBQUMsTUFBTSxDQUFDO0FBRXhGLFNBQVMsTUFBTSxDQUFDLENBQWdCLEVBQUUsQ0FBZ0IsRUFBRSxHQUFXO0lBQzNELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDL0YsQ0FBQztBQUVELFNBQVMsSUFBSSxDQUFDLENBQWdCLEVB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LEdBQUcsQ0FBQyxDQUFDO2dCQUNqQixNQUFNLFFBQVEsR0FBRztvQkFDYixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQ2xELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztvQkFDbEQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUNsRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQ2xELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztvQkFDbEQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUNsRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQ2xELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztpQkFDckQsQ0FBQztnQkFDRix1REFBdUQ7Z0JBQ3ZELE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBQy9DLEtBQUssTUFBTSxDQUFDLElBQUksUUFBUSxFQUFFO29CQUN0QixDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO29CQUMxQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUMxRCxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUMzRDtnQkFDRCxTQUFTLElBQUksQ0FBQyxDQUFDO2dCQUNmLFFBQVEsSUFBSSxDQUFDLENBQUM7Z0JBQ2QsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUM7Z0JBQy9ELE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDO2dCQUM3RCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsR0FBRyxNQUFNLENBQUM7Z0JBQ2xFLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ1YsTUFBTSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztvQkFDL0IsTUFBTSxDQUFDLHNCQUFzQixFQUFFLENBQUM7aUJBQ25DO2FBQ0o7WUFFRCxJQUFJLE9BQU8sRUFBRTtnQkFDVCxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7YUFDbkM7aUJBQU07Z0JBQ0gsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDekMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQyxJQUFJLFFBQVEsRUFBRTtvQkFDVixRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN4QyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7aUJBQ3JCO2FBQ0o7WUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUTtnQkFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUMvRCxVQUFVLEVBQUUsQ0FBQztZQUNiLE9BQU8sSUFBSSxDQUFDO1FBQ2hCLENBQUM7S0FDYSxDQUFDO0lBRW5CLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLE1BQU0sQ0FBQyxJQUFJLENBQ1AsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUNuQixTQUFTLENBQUMsR0FBRyxFQUFFLENBQ1gsYUFBYSxDQUFDO1FBQ1YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDckIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDcEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7UUFDeEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7UUFDdEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDeEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDcEIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUU7S0FDL0IsQ0FBQyxDQUNMLENBQ0osRUFDRCxDQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFO1FBQ3JCLElBQUksT0FBTyxJQUFJLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRTtZQUMxQixHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDZCxJQUFJLEdBQUc7Z0JBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ25CLElBQUksSUFBSTtnQkFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDLENBQ0osQ0FBQztJQUVGLGtCQUFrQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1FBQzdCLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7WUFDMUIsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDdEMsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxHQUFHLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNwRSxNQUFNLFFBQVEsR0FBRyxhQUF5QyxDQUFDO1lBRTNELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDOUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNoRSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDbEcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUU1QyxJQUFJLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDL0IsTUFBTSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDbEMsTUFBTSxDQUFDLHNCQUFzQixFQUFFLENBQUM7YUFDbkM7WUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNYLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUN2QztpQkFBTTtnQkFDSCxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDckI7WUFFRCxVQUFVLEVBQUUsQ0FBQztZQUNiLElBQUksRUFBRSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDO2dCQUFFLE9BQU87WUFDdkcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7Z0JBQUUsT0FBTztZQUN0RyxJQUFJLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7Z0JBQUUsT0FBTztZQUM5RSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7U0FDcEM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sR0FBRyxDQUFDO0FBQ2YsQ0FBQztBQUVELE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7QUFhbEIsTUFBTSxPQUFPLFVBQVcsU0FBUSxVQUFVO0lBWDFDOztRQVlhLGNBQVMsR0FBRyxZQUFZLEVBQVMsQ0FBQztRQTBCakMsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFrQixDQUFDO1FBRXJDLFVBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFakMsWUFBTyxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNqRyxTQUFJLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztLQW9CeEY7SUFqREcsSUFBYSxPQUFPLENBQUMsT0FBZTtRQUNoQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsSUFBYSxHQUFHLENBQUMsR0FBWTtRQUN6QixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUN0QixDQUFDO0lBRUQsSUFBYSxJQUFJLENBQUMsSUFBYTtRQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFBYSxPQUFPLENBQUMsT0FBZ0I7UUFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVELElBQWEsTUFBTSxDQUFDLE1BQWM7UUFDOUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVELElBQWEsR0FBRyxDQUFDLEdBQVc7UUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQVNRLFVBQVU7UUFDZixLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRUQsUUFBUTtRQUNKLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFTyxvQkFBb0I7UUFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFO1lBQ3BELElBQUksUUFBUSxFQUFFO2dCQUNWLE1BQU0sUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUM7Z0JBQ3ZELFFBQXFDLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUMzRSxPQUFPLEdBQUcsRUFBRSxDQUFFLFFBQXFDLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQzlGO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDOzt1R0FuRFEsVUFBVTsyRkFBVixVQUFVLDZOQUhSLENBQUMsRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGlEQUxqRjs7OztLQUlUOzJGQUlRLFVBQVU7a0JBWHRCLFNBQVM7bUJBQUM7b0JBQ1AsUUFBUSxFQUFFLGFBQWE7b0JBQ3ZCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUU7Ozs7S0FJVDtvQkFDRCxTQUFTLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztvQkFDM0YsT0FBTyxFQUFFLENBQUMsc0JBQXNCLENBQUM7aUJBQ3BDOzhCQUVZLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRU8sT0FBTztzQkFBbkIsS0FBSztnQkFJTyxHQUFHO3NCQUFmLEtBQUs7Z0JBSU8sSUFBSTtzQkFBaEIsS0FBSztnQkFJTyxPQUFPO3NCQUFuQixLQUFLO2dCQUlPLE1BQU07c0JBQWxCLEtBQUs7Z0JBSU8sR0FBRztzQkFBZixLQUFLO2dCQUlJLE1BQU07c0JBQWYsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIENVU1RPTV9FTEVNRU5UU19TQ0hFTUEsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGluamVjdCxcbiAgICBJbmplY3Rpb25Ub2tlbixcbiAgICBJbnB1dCxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGV4dGVuZCwgaW5qZWN0QmVmb3JlUmVuZGVyLCBpbmplY3ROZ3RSZWYsIGlzLCBOZ3RSeFN0b3JlLCBOZ3RTdG9yZSB9IGZyb20gJ2FuZ3VsYXItdGhyZWUnO1xuaW1wb3J0IHsgY29tYmluZUxhdGVzdCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgKiBhcyBUSFJFRSBmcm9tICd0aHJlZSc7XG5pbXBvcnQgeyBHcm91cCB9IGZyb20gJ3RocmVlJztcblxuZXhwb3J0IGludGVyZmFjZSBOZ3RzQm91bmRzU2l6ZSB7XG4gICAgYm94OiBUSFJFRS5Cb3gzO1xuICAgIHNpemU6IFRIUkVFLlZlY3RvcjM7XG4gICAgY2VudGVyOiBUSFJFRS5WZWN0b3IzO1xuICAgIGRpc3RhbmNlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmd0c0JvdW5kc0FwaSB7XG4gICAgZ2V0U2l6ZTogKCkgPT4gTmd0c0JvdW5kc1NpemU7XG4gICAgcmVmcmVzaDogKG9iamVjdD86IFRIUkVFLk9iamVjdDNEIHwgVEhSRUUuQm94MykgPT4gTmd0c0JvdW5kc0FwaTtcbiAgICBjbGlwOiAoKSA9PiBOZ3RzQm91bmRzQXBpO1xuICAgIGZpdDogKCkgPT4gTmd0c0JvdW5kc0FwaTtcbiAgICB0bzogKHtcbiAgICAgICAgcG9zaXRpb24sXG4gICAgICAgIHRhcmdldCxcbiAgICB9OiB7XG4gICAgICAgIHBvc2l0aW9uOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgICAgIHRhcmdldD86IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICB9KSA9PiBOZ3RzQm91bmRzQXBpO1xufVxuXG50eXBlIENvbnRyb2xzUHJvdG8gPSB7XG4gICAgdXBkYXRlKCk6IHZvaWQ7XG4gICAgdGFyZ2V0OiBUSFJFRS5WZWN0b3IzO1xuICAgIG1heERpc3RhbmNlOiBudW1iZXI7XG4gICAgYWRkRXZlbnRMaXN0ZW5lcjogKGV2ZW50OiBzdHJpbmcsIGNhbGxiYWNrOiAoZXZlbnQ6IGFueSkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgICByZW1vdmVFdmVudExpc3RlbmVyOiAoZXZlbnQ6IHN0cmluZywgY2FsbGJhY2s6IChldmVudDogYW55KSA9PiB2b2lkKSA9PiB2b2lkO1xufTtcblxuY29uc3QgaXNCb3gzID0gKGRlZjogdW5rbm93bik6IGRlZiBpcyBUSFJFRS5Cb3gzID0+ICEhZGVmICYmIChkZWYgYXMgVEhSRUUuQm94MykuaXNCb3gzO1xuXG5mdW5jdGlvbiBlcXVhbHMoYTogVEhSRUUuVmVjdG9yMywgYjogVEhSRUUuVmVjdG9yMywgZXBzOiBudW1iZXIpIHtcbiAgICByZXR1cm4gTWF0aC5hYnMoYS54IC0gYi54KSA8IGVwcyAmJiBNYXRoLmFicyhhLnkgLSBiLnkpIDwgZXBzICYmIE1hdGguYWJzKGEueiAtIGIueikgPCBlcHM7XG59XG5cbmZ1bmN0aW9uIGRhbXAodjogVEhSRUUuVmVjdG9yMywgdDogVEhSRUUuVmVjdG9yMywgbGFtYmRhOiBudW1iZXIsIGRlbHRhOiBudW1iZXIpIHtcbiAgICB2LnggPSBUSFJFRS5NYXRoVXRpbHMuZGFtcCh2LngsIHQueCwgbGFtYmRhLCBkZWx0YSk7XG4gICAgdi55ID0gVEhSRUUuTWF0aFV0aWxzLmRhbXAodi55LCB0LnksIGxhbWJkYSwgZGVsdGEpO1xuICAgIHYueiA9IFRIUkVFLk1hdGhVdGlscy5kYW1wKHYueiwgdC56LCBsYW1iZGEsIGRlbHRhKTtcbn1cblxuZXhwb3J0IGNvbnN0IE5HVFNfQk9VTkRTX0FQSSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxOZ3RzQm91bmRzQXBpPignTmd0c0JvdW5kcyBBUEknKTtcblxuZnVuY3Rpb24gYm91bmRzQXBpRmFjdG9yeShib3VuZHM6IE5ndHNCb3VuZHMpIHtcbiAgICBjb25zdCBzdG9yZSA9IGluamVjdChOZ3RTdG9yZSk7XG4gICAgY29uc3QgYm94ID0gbmV3IFRIUkVFLkJveDMoKTtcblxuICAgIGZ1bmN0aW9uIGdldFNpemUoKSB7XG4gICAgICAgIGNvbnN0IGNhbWVyYSA9IHN0b3JlLmdldCgnY2FtZXJhJyk7XG4gICAgICAgIGNvbnN0IG1hcmdpbiA9IGJvdW5kcy5nZXQoJ21hcmdpbicpO1xuXG4gICAgICAgIGNvbnN0IHNpemUgPSBib3guZ2V0U2l6ZShuZXcgVEhSRUUuVmVjdG9yMygpKTtcbiAgICAgICAgY29uc3QgY2VudGVyID0gYm94LmdldENlbnRlcihuZXcgVEhSRUUuVmVjdG9yMygpKTtcbiAgICAgICAgY29uc3QgbWF4U2l6ZSA9IE1hdGgubWF4KHNpemUueCwgc2l6ZS55LCBzaXplLnopO1xuICAgICAgICBjb25zdCBmaXRIZWlnaHREaXN0YW5jZSA9IGlzLm9ydGhvZ3JhcGhpY0NhbWVyYShjYW1lcmEpXG4gICAgICAgICAgICA/IG1heFNpemUgKiA0XG4gICAgICAgICAgICA6IG1heFNpemUgLyAoMiAqIE1hdGguYXRhbigoTWF0aC5QSSAqIGNhbWVyYS5mb3YpIC8gMzYwKSk7XG4gICAgICAgIGNvbnN0IGZpdFdpZHRoRGlzdGFuY2UgPSBpcy5vcnRob2dyYXBoaWNDYW1lcmEoY2FtZXJhKSA/IG1heFNpemUgKiA0IDogZml0SGVpZ2h0RGlzdGFuY2UgLyBjYW1lcmEuYXNwZWN0O1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IG1hcmdpbiAqIE1hdGgubWF4KGZpdEhlaWdodERpc3RhbmNlLCBmaXRXaWR0aERpc3RhbmNlKTtcbiAgICAgICAgcmV0dXJuIHsgYm94LCBzaXplLCBjZW50ZXIsIGRpc3RhbmNlIH07XG4gICAgfVxuXG4gICAgY29uc3QgYXBpID0ge1xuICAgICAgICBnZXRTaXplLFxuICAgICAgICByZWZyZXNoKG9iamVjdD86IFRIUkVFLk9iamVjdDNEIHwgVEhSRUUuQm94Mykge1xuICAgICAgICAgICAgY29uc3QgeyBjYW1lcmEsIGNvbnRyb2xzOiBzdG9yZUNvbnRyb2xzIH0gPSBzdG9yZS5nZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRyb2xzID0gc3RvcmVDb250cm9scyBhcyB1bmtub3duIGFzIENvbnRyb2xzUHJvdG87XG5cbiAgICAgICAgICAgIGlmIChpc0JveDMob2JqZWN0KSkgYm94LmNvcHkob2JqZWN0KTtcbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IG9iamVjdCB8fCBib3VuZHMuYm91bmRzUmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQudXBkYXRlV29ybGRNYXRyaXgodHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJveC5zZXRGcm9tT2JqZWN0KHRhcmdldCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJveC5pc0VtcHR5KCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXggPSBjYW1lcmEucG9zaXRpb24ubGVuZ3RoKCkgfHwgMTA7XG4gICAgICAgICAgICAgICAgYm94LnNldEZyb21DZW50ZXJBbmRTaXplKG5ldyBUSFJFRS5WZWN0b3IzKCksIG5ldyBUSFJFRS5WZWN0b3IzKG1heCwgbWF4LCBtYXgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbnRyb2xzPy5jb25zdHJ1Y3Rvci5uYW1lID09PSAnT3J0aG9ncmFwaGljVHJhY2tiYWxsQ29udHJvbHMnKSB7XG4gICAgICAgICAgICAgICAgLy8gcHV0IGNhbWVyYSBvbiBhIHNwaGVyZSBhbG9uZyB3aGljaCBpdCB3b3VsZCBtb3ZlXG4gICAgICAgICAgICAgICAgY29uc3QgeyBkaXN0YW5jZSB9ID0gZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IGNhbWVyYS5wb3NpdGlvbi5jbG9uZSgpLnN1Yihjb250cm9scy50YXJnZXQpLm5vcm1hbGl6ZSgpLm11bHRpcGx5U2NhbGFyKGRpc3RhbmNlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQb3MgPSBjb250cm9scy50YXJnZXQuY2xvbmUoKS5hZGQoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICBjYW1lcmEucG9zaXRpb24uY29weShuZXdQb3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgIGNsaXAoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGRpc3RhbmNlIH0gPSBnZXRTaXplKCk7XG4gICAgICAgICAgICBjb25zdCB7IGNhbWVyYSwgY29udHJvbHM6IHN0b3JlQ29udHJvbHMsIGludmFsaWRhdGUgfSA9IHN0b3JlLmdldCgpO1xuICAgICAgICAgICAgY29uc3QgY29udHJvbHMgPSBzdG9yZUNvbnRyb2xzIGFzIHVua25vd24gYXMgQ29udHJvbHNQcm90bztcbiAgICAgICAgICAgIGlmIChjb250cm9scykgY29udHJvbHMubWF4RGlzdGFuY2UgPSBkaXN0YW5jZSAqIDEwO1xuICAgICAgICAgICAgY2FtZXJhLm5lYXIgPSBkaXN0YW5jZSAvIDEwMDtcbiAgICAgICAgICAgIGNhbWVyYS5mYXIgPSBkaXN0YW5jZSAqIDEwMDtcbiAgICAgICAgICAgIGNhbWVyYS51cGRhdGVQcm9qZWN0aW9uTWF0cml4KCk7XG4gICAgICAgICAgICBpZiAoY29udHJvbHMpIGNvbnRyb2xzLnVwZGF0ZSgpO1xuICAgICAgICAgICAgaW52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgIHRvKHsgcG9zaXRpb24sIHRhcmdldCB9OiB7IHBvc2l0aW9uOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl07IHRhcmdldD86IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSB9KSB7XG4gICAgICAgICAgICBjb25zdCB7IGNhbWVyYSB9ID0gc3RvcmUuZ2V0KCk7XG4gICAgICAgICAgICBjb25zdCB7IGRhbXBpbmcgfSA9IGJvdW5kcy5nZXQoKTtcblxuICAgICAgICAgICAgYm91bmRzLmN1cnJlbnQuY2FtZXJhLmNvcHkoY2FtZXJhLnBvc2l0aW9uKTtcbiAgICAgICAgICAgIGNvbnN0IHsgY2VudGVyIH0gPSBnZXRTaXplKCk7XG4gICAgICAgICAgICBib3VuZHMuZ29hbC5jYW1lcmEuc2V0KC4uLnBvc2l0aW9uKTtcblxuICAgICAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgICAgICAgIGJvdW5kcy5nb2FsLmZvY3VzLnNldCguLi50YXJnZXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBib3VuZHMuZ29hbC5mb2N1cy5jb3B5KGNlbnRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChkYW1waW5nKSB7XG4gICAgICAgICAgICAgICAgYm91bmRzLmN1cnJlbnQuYW5pbWF0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhLnBvc2l0aW9uLnNldCguLi5wb3NpdGlvbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuICAgICAgICBmaXQoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGNhbWVyYSwgY29udHJvbHM6IHN0b3JlQ29udHJvbHMsIGludmFsaWRhdGUgfSA9IHN0b3JlLmdldCgpO1xuICAgICAgICAgICAgY29uc3QgY29udHJvbHMgPSBzdG9yZUNvbnRyb2xzIGFzIHVua25vd24gYXMgQ29udHJvbHNQcm90bztcblxuICAgICAgICAgICAgY29uc3QgeyBkYW1waW5nLCBtYXJnaW4gfSA9IGJvdW5kcy5nZXQoKTtcblxuICAgICAgICAgICAgYm91bmRzLmN1cnJlbnQuY2FtZXJhLmNvcHkoY2FtZXJhLnBvc2l0aW9uKTtcbiAgICAgICAgICAgIGlmIChjb250cm9scykgYm91bmRzLmN1cnJlbnQuZm9jdXMuY29weShjb250cm9scy50YXJnZXQpO1xuXG4gICAgICAgICAgICBjb25zdCB7IGNlbnRlciwgZGlzdGFuY2UgfSA9IGdldFNpemUoKTtcbiAgICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IGNlbnRlci5jbG9uZSgpLnN1YihjYW1lcmEucG9zaXRpb24pLm5vcm1hbGl6ZSgpLm11bHRpcGx5U2NhbGFyKGRpc3RhbmNlKTtcblxuICAgICAgICAgICAgYm91bmRzLmdvYWwuY2FtZXJhLmNvcHkoY2VudGVyKS5zdWIoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIGJvdW5kcy5nb2FsLmZvY3VzLmNvcHkoY2VudGVyKTtcblxuICAgICAgICAgICAgaWYgKGlzLm9ydGhvZ3JhcGhpY0NhbWVyYShjYW1lcmEpKSB7XG4gICAgICAgICAgICAgICAgYm91bmRzLmN1cnJlbnQuem9vbSA9IGNhbWVyYS56b29tO1xuXG4gICAgICAgICAgICAgICAgbGV0IG1heEhlaWdodCA9IDAsXG4gICAgICAgICAgICAgICAgICAgIG1heFdpZHRoID0gMDtcbiAgICAgICAgICAgICAgICBjb25zdCB2ZXJ0aWNlcyA9IFtcbiAgICAgICAgICAgICAgICAgICAgbmV3IFRIUkVFLlZlY3RvcjMoYm94Lm1pbi54LCBib3gubWluLnksIGJveC5taW4ueiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBUSFJFRS5WZWN0b3IzKGJveC5taW4ueCwgYm94Lm1heC55LCBib3gubWluLnopLFxuICAgICAgICAgICAgICAgICAgICBuZXcgVEhSRUUuVmVjdG9yMyhib3gubWluLngsIGJveC5taW4ueSwgYm94Lm1heC56KSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFRIUkVFLlZlY3RvcjMoYm94Lm1pbi54LCBib3gubWF4LnksIGJveC5tYXgueiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBUSFJFRS5WZWN0b3IzKGJveC5tYXgueCwgYm94Lm1heC55LCBib3gubWF4LnopLFxuICAgICAgICAgICAgICAgICAgICBuZXcgVEhSRUUuVmVjdG9yMyhib3gubWF4LngsIGJveC5tYXgueSwgYm94Lm1pbi56KSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFRIUkVFLlZlY3RvcjMoYm94Lm1heC54LCBib3gubWluLnksIGJveC5tYXgueiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBUSFJFRS5WZWN0b3IzKGJveC5tYXgueCwgYm94Lm1pbi55LCBib3gubWluLnopLFxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgLy8gVHJhbnNmb3JtIHRoZSBjZW50ZXIgYW5kIGVhY2ggY29ybmVyIHRvIGNhbWVyYSBzcGFjZVxuICAgICAgICAgICAgICAgIGNlbnRlci5hcHBseU1hdHJpeDQoY2FtZXJhLm1hdHJpeFdvcmxkSW52ZXJzZSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB2IG9mIHZlcnRpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHYuYXBwbHlNYXRyaXg0KGNhbWVyYS5tYXRyaXhXb3JsZEludmVyc2UpO1xuICAgICAgICAgICAgICAgICAgICBtYXhIZWlnaHQgPSBNYXRoLm1heChtYXhIZWlnaHQsIE1hdGguYWJzKHYueSAtIGNlbnRlci55KSk7XG4gICAgICAgICAgICAgICAgICAgIG1heFdpZHRoID0gTWF0aC5tYXgobWF4V2lkdGgsIE1hdGguYWJzKHYueCAtIGNlbnRlci54KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1heEhlaWdodCAqPSAyO1xuICAgICAgICAgICAgICAgIG1heFdpZHRoICo9IDI7XG4gICAgICAgICAgICAgICAgY29uc3Qgem9vbUZvckhlaWdodCA9IChjYW1lcmEudG9wIC0gY2FtZXJhLmJvdHRvbSkgLyBtYXhIZWlnaHQ7XG4gICAgICAgICAgICAgICAgY29uc3Qgem9vbUZvcldpZHRoID0gKGNhbWVyYS5yaWdodCAtIGNhbWVyYS5sZWZ0KSAvIG1heFdpZHRoO1xuICAgICAgICAgICAgICAgIGJvdW5kcy5nb2FsLnpvb20gPSBNYXRoLm1pbih6b29tRm9ySGVpZ2h0LCB6b29tRm9yV2lkdGgpIC8gbWFyZ2luO1xuICAgICAgICAgICAgICAgIGlmICghZGFtcGluZykge1xuICAgICAgICAgICAgICAgICAgICBjYW1lcmEuem9vbSA9IGJvdW5kcy5nb2FsLnpvb207XG4gICAgICAgICAgICAgICAgICAgIGNhbWVyYS51cGRhdGVQcm9qZWN0aW9uTWF0cml4KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZGFtcGluZykge1xuICAgICAgICAgICAgICAgIGJvdW5kcy5jdXJyZW50LmFuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbWVyYS5wb3NpdGlvbi5jb3B5KGJvdW5kcy5nb2FsLmNhbWVyYSk7XG4gICAgICAgICAgICAgICAgY2FtZXJhLmxvb2tBdChib3VuZHMuZ29hbC5mb2N1cyk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2xzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzLnRhcmdldC5jb3B5KGJvdW5kcy5nb2FsLmZvY3VzKTtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbHMudXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJvdW5kcy5maXR0ZWQub2JzZXJ2ZWQpIGJvdW5kcy5maXR0ZWQuZW1pdCh0aGlzLmdldFNpemUoKSk7XG4gICAgICAgICAgICBpbnZhbGlkYXRlKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcbiAgICB9IGFzIE5ndHNCb3VuZHNBcGk7XG5cbiAgICBsZXQgY291bnQgPSAwO1xuICAgIGJvdW5kcy5ob2xkKFxuICAgICAgICBib3VuZHMuYm91bmRzUmVmLiQucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgICAgICAgICAgIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICAgICAgICAgICAgICBib3VuZHMuc2VsZWN0KCdjbGlwJyksXG4gICAgICAgICAgICAgICAgICAgIGJvdW5kcy5zZWxlY3QoJ2ZpdCcpLFxuICAgICAgICAgICAgICAgICAgICBib3VuZHMuc2VsZWN0KCdvYnNlcnZlJyksXG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnNlbGVjdCgnY2FtZXJhJyksXG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnNlbGVjdCgnY29udHJvbHMnKSxcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUuc2VsZWN0KCdzaXplJyksXG4gICAgICAgICAgICAgICAgICAgIGJvdW5kcy5ib3VuZHNSZWYuY2hpbGRyZW4kKCksXG4gICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgICAgKFtjbGlwLCBmaXQsIG9ic2VydmVdKSA9PiB7XG4gICAgICAgICAgICBpZiAob2JzZXJ2ZSB8fCBjb3VudCsrID09PSAwKSB7XG4gICAgICAgICAgICAgICAgYXBpLnJlZnJlc2goKTtcbiAgICAgICAgICAgICAgICBpZiAoZml0KSBhcGkuZml0KCk7XG4gICAgICAgICAgICAgICAgaWYgKGNsaXApIGFwaS5jbGlwKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICApO1xuXG4gICAgaW5qZWN0QmVmb3JlUmVuZGVyKCh7IGRlbHRhIH0pID0+IHtcbiAgICAgICAgaWYgKGJvdW5kcy5jdXJyZW50LmFuaW1hdGluZykge1xuICAgICAgICAgICAgY29uc3QgeyBkYW1waW5nLCBlcHMgfSA9IGJvdW5kcy5nZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgY2FtZXJhLCBjb250cm9sczogc3RvcmVDb250cm9scywgaW52YWxpZGF0ZSB9ID0gc3RvcmUuZ2V0KCk7XG4gICAgICAgICAgICBjb25zdCBjb250cm9scyA9IHN0b3JlQ29udHJvbHMgYXMgdW5rbm93biBhcyBDb250cm9sc1Byb3RvO1xuXG4gICAgICAgICAgICBkYW1wKGJvdW5kcy5jdXJyZW50LmZvY3VzLCBib3VuZHMuZ29hbC5mb2N1cywgZGFtcGluZywgZGVsdGEpO1xuICAgICAgICAgICAgZGFtcChib3VuZHMuY3VycmVudC5jYW1lcmEsIGJvdW5kcy5nb2FsLmNhbWVyYSwgZGFtcGluZywgZGVsdGEpO1xuICAgICAgICAgICAgYm91bmRzLmN1cnJlbnQuem9vbSA9IFRIUkVFLk1hdGhVdGlscy5kYW1wKGJvdW5kcy5jdXJyZW50Lnpvb20sIGJvdW5kcy5nb2FsLnpvb20sIGRhbXBpbmcsIGRlbHRhKTtcbiAgICAgICAgICAgIGNhbWVyYS5wb3NpdGlvbi5jb3B5KGJvdW5kcy5jdXJyZW50LmNhbWVyYSk7XG5cbiAgICAgICAgICAgIGlmIChpcy5vcnRob2dyYXBoaWNDYW1lcmEoY2FtZXJhKSkge1xuICAgICAgICAgICAgICAgIGNhbWVyYS56b29tID0gYm91bmRzLmN1cnJlbnQuem9vbTtcbiAgICAgICAgICAgICAgICBjYW1lcmEudXBkYXRlUHJvamVjdGlvbk1hdHJpeCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWNvbnRyb2xzKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhLmxvb2tBdChib3VuZHMuY3VycmVudC5mb2N1cyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRyb2xzLnRhcmdldC5jb3B5KGJvdW5kcy5jdXJyZW50LmZvY3VzKTtcbiAgICAgICAgICAgICAgICBjb250cm9scy51cGRhdGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaW52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgaWYgKGlzLm9ydGhvZ3JhcGhpY0NhbWVyYShjYW1lcmEpICYmICEoTWF0aC5hYnMoYm91bmRzLmN1cnJlbnQuem9vbSAtIGJvdW5kcy5nb2FsLnpvb20pIDwgZXBzKSkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKCFpcy5vcnRob2dyYXBoaWNDYW1lcmEoY2FtZXJhKSAmJiAhZXF1YWxzKGJvdW5kcy5jdXJyZW50LmNhbWVyYSwgYm91bmRzLmdvYWwuY2FtZXJhLCBlcHMpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoY29udHJvbHMgJiYgIWVxdWFscyhib3VuZHMuY3VycmVudC5mb2N1cywgYm91bmRzLmdvYWwuZm9jdXMsIGVwcykpIHJldHVybjtcbiAgICAgICAgICAgIGJvdW5kcy5jdXJyZW50LmFuaW1hdGluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXBpO1xufVxuXG5leHRlbmQoeyBHcm91cCB9KTtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICduZ3RzLWJvdW5kcycsXG4gICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgICB0ZW1wbGF0ZTogYFxuICAgICAgICA8bmd0LWdyb3VwIG5ndENvbXBvdW5kIFtyZWZdPVwiYm91bmRzUmVmXCI+XG4gICAgICAgICAgICA8bmctY29udGVudCAvPlxuICAgICAgICA8L25ndC1ncm91cD5cbiAgICBgLFxuICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogTkdUU19CT1VORFNfQVBJLCB1c2VGYWN0b3J5OiBib3VuZHNBcGlGYWN0b3J5LCBkZXBzOiBbTmd0c0JvdW5kc10gfV0sXG4gICAgc2NoZW1hczogW0NVU1RPTV9FTEVNRU5UU19TQ0hFTUFdLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3RzQm91bmRzIGV4dGVuZHMgTmd0UnhTdG9yZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgQElucHV0KCkgYm91bmRzUmVmID0gaW5qZWN0Tmd0UmVmPEdyb3VwPigpO1xuXG4gICAgQElucHV0KCkgc2V0IGRhbXBpbmcoZGFtcGluZzogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgZGFtcGluZyB9KTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSBzZXQgZml0KGZpdDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnNldCh7IGZpdCB9KTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSBzZXQgY2xpcChjbGlwOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgY2xpcCB9KTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSBzZXQgb2JzZXJ2ZShvYnNlcnZlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgb2JzZXJ2ZSB9KTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSBzZXQgbWFyZ2luKG1hcmdpbjogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0KHsgbWFyZ2luIH0pO1xuICAgIH1cblxuICAgIEBJbnB1dCgpIHNldCBlcHMoZXBzOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5zZXQoeyBlcHMgfSk7XG4gICAgfVxuXG4gICAgQE91dHB1dCgpIGZpdHRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Tmd0c0JvdW5kc1NpemU+KCk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0b3JlID0gaW5qZWN0KE5ndFN0b3JlKTtcblxuICAgIHJlYWRvbmx5IGN1cnJlbnQgPSB7IGFuaW1hdGluZzogZmFsc2UsIGZvY3VzOiBuZXcgVEhSRUUuVmVjdG9yMygpLCBjYW1lcmE6IG5ldyBUSFJFRS5WZWN0b3IzKCksIHpvb206IDEgfTtcbiAgICByZWFkb25seSBnb2FsID0geyBmb2N1czogbmV3IFRIUkVFLlZlY3RvcjMoKSwgY2FtZXJhOiBuZXcgVEhSRUUuVmVjdG9yMygpLCB6b29tOiAxIH07XG5cbiAgICBvdmVycmlkZSBpbml0aWFsaXplKCkge1xuICAgICAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgICAgIHRoaXMuc2V0KHsgZGFtcGluZzogNiwgZml0OiBmYWxzZSwgY2xpcDogZmFsc2UsIG9ic2VydmU6IGZhbHNlLCBtYXJnaW46IDEuMiwgZXBzOiAwLjAxIH0pO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLnByZXZlbnREcmFnSGlqYWNraW5nKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmV2ZW50RHJhZ0hpamFja2luZygpIHtcbiAgICAgICAgdGhpcy5lZmZlY3QodGhpcy5zdG9yZS5zZWxlY3QoJ2NvbnRyb2xzJyksIChjb250cm9scykgPT4ge1xuICAgICAgICAgICAgaWYgKGNvbnRyb2xzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoKSA9PiAodGhpcy5jdXJyZW50LmFuaW1hdGluZyA9IGZhbHNlKTtcbiAgICAgICAgICAgICAgICAoY29udHJvbHMgYXMgdW5rbm93biBhcyBDb250cm9sc1Byb3RvKS5hZGRFdmVudExpc3RlbmVyKCdzdGFydCcsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKCkgPT4gKGNvbnRyb2xzIGFzIHVua25vd24gYXMgQ29udHJvbHNQcm90bykucmVtb3ZlRXZlbnRMaXN0ZW5lcignc3RhcnQnLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiJdfQ==
|