angular-three-rapier 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.
- package/README.md +7 -0
- package/esm2022/angular-three-rapier.mjs +5 -0
- package/esm2022/index.mjs +7 -0
- package/esm2022/lib/colliders.mjs +355 -0
- package/esm2022/lib/debug.mjs +46 -0
- package/esm2022/lib/frame-stepper.mjs +46 -0
- package/esm2022/lib/instanced-rigid-bodies.mjs +185 -0
- package/esm2022/lib/joints.mjs +111 -0
- package/esm2022/lib/mesh-collider.mjs +69 -0
- package/esm2022/lib/physics.mjs +362 -0
- package/esm2022/lib/rigid-body.mjs +536 -0
- package/esm2022/lib/shared.mjs +10 -0
- package/esm2022/lib/types.mjs +2 -0
- package/esm2022/lib/utils.mjs +151 -0
- package/fesm2022/angular-three-rapier.mjs +1831 -0
- package/fesm2022/angular-three-rapier.mjs.map +1 -0
- package/index.d.ts +7 -0
- package/lib/colliders.d.ts +93 -0
- package/lib/debug.d.ts +9 -0
- package/lib/frame-stepper.d.ts +10 -0
- package/lib/instanced-rigid-bodies.d.ts +46 -0
- package/lib/joints.d.ts +64 -0
- package/lib/mesh-collider.d.ts +23 -0
- package/lib/physics.d.ts +50 -0
- package/lib/rigid-body.d.ts +104 -0
- package/lib/shared.d.ts +9 -0
- package/lib/types.d.ts +500 -0
- package/lib/utils.d.ts +26 -0
- package/package.json +51 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, Directive, effect, ElementRef, inject, input, model, output, untracked, } from '@angular/core';
|
|
2
|
+
import { ActiveEvents, ColliderDesc, RigidBodyDesc } from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { extend, getEmitter, getLocalState, hasListener, pick, } from 'angular-three';
|
|
4
|
+
import { mergeInputs } from 'ngxtension/inject-inputs';
|
|
5
|
+
import { Object3D, Vector3 } from 'three';
|
|
6
|
+
import { NgtrPhysics } from './physics';
|
|
7
|
+
import { _matrix4, _position, _rotation, _scale, _vector3 } from './shared';
|
|
8
|
+
import { createColliderOptions } from './utils';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
const colliderDefaultOptions = {
|
|
11
|
+
contactSkin: 0,
|
|
12
|
+
};
|
|
13
|
+
export class NgtrAnyCollider {
|
|
14
|
+
position = input([0, 0, 0]);
|
|
15
|
+
rotation = input([0, 0, 0]);
|
|
16
|
+
scale = input([1, 1, 1]);
|
|
17
|
+
quaternion = input([0, 0, 0, 1]);
|
|
18
|
+
userData = input({});
|
|
19
|
+
name = input();
|
|
20
|
+
options = input(colliderDefaultOptions, { transform: mergeInputs(rigidBodyDefaultOptions) });
|
|
21
|
+
// TODO: change this to input required when Angular allows setting hostDirective input
|
|
22
|
+
shape = model(undefined, { alias: 'ngtrCollider' });
|
|
23
|
+
args = model([]);
|
|
24
|
+
collisionEnter = output();
|
|
25
|
+
collisionExit = output();
|
|
26
|
+
intersectionEnter = output();
|
|
27
|
+
intersectionExit = output();
|
|
28
|
+
contactForce = output();
|
|
29
|
+
sensor = pick(this.options, 'sensor');
|
|
30
|
+
collisionGroups = pick(this.options, 'collisionGroups');
|
|
31
|
+
solverGroups = pick(this.options, 'solverGroups');
|
|
32
|
+
friction = pick(this.options, 'friction');
|
|
33
|
+
frictionCombineRule = pick(this.options, 'frictionCombineRule');
|
|
34
|
+
restitution = pick(this.options, 'restitution');
|
|
35
|
+
restitutionCombineRule = pick(this.options, 'restitutionCombineRule');
|
|
36
|
+
activeCollisionTypes = pick(this.options, 'activeCollisionTypes');
|
|
37
|
+
contactSkin = pick(this.options, 'contactSkin');
|
|
38
|
+
mass = pick(this.options, 'mass');
|
|
39
|
+
massProperties = pick(this.options, 'massProperties');
|
|
40
|
+
density = pick(this.options, 'density');
|
|
41
|
+
rigidBody = inject(NgtrRigidBody, { optional: true });
|
|
42
|
+
physics = inject(NgtrPhysics);
|
|
43
|
+
objectRef = inject(ElementRef);
|
|
44
|
+
scaledArgs = computed(() => {
|
|
45
|
+
const [shape, args] = [
|
|
46
|
+
this.shape(),
|
|
47
|
+
this.args(),
|
|
48
|
+
];
|
|
49
|
+
const cloned = args.slice();
|
|
50
|
+
// Heightfield uses a vector
|
|
51
|
+
if (shape === 'heightfield') {
|
|
52
|
+
const s = cloned[3];
|
|
53
|
+
s.x *= this.worldScale.x;
|
|
54
|
+
s.y *= this.worldScale.y;
|
|
55
|
+
s.z *= this.worldScale.z;
|
|
56
|
+
return cloned;
|
|
57
|
+
}
|
|
58
|
+
// Trimesh and convex scale the vertices
|
|
59
|
+
if (shape === 'trimesh' || shape === 'convexHull') {
|
|
60
|
+
cloned[0] = this.scaleVertices(cloned[0], this.worldScale);
|
|
61
|
+
return cloned;
|
|
62
|
+
}
|
|
63
|
+
// prefill with some extra
|
|
64
|
+
const scaleArray = [this.worldScale.x, this.worldScale.y, this.worldScale.z, this.worldScale.x, this.worldScale.x];
|
|
65
|
+
return cloned.map((arg, index) => scaleArray[index] * arg);
|
|
66
|
+
});
|
|
67
|
+
collider = computed(() => {
|
|
68
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
69
|
+
if (!worldSingleton)
|
|
70
|
+
return null;
|
|
71
|
+
const [shape, args, rigidBody] = [this.shape(), this.scaledArgs(), this.rigidBody?.rigidBody()];
|
|
72
|
+
// @ts-expect-error - we know the type of the data
|
|
73
|
+
const desc = ColliderDesc[shape](...args);
|
|
74
|
+
if (!desc)
|
|
75
|
+
return null;
|
|
76
|
+
return worldSingleton.proxy.createCollider(desc, rigidBody ?? undefined);
|
|
77
|
+
});
|
|
78
|
+
constructor() {
|
|
79
|
+
extend({ Object3D });
|
|
80
|
+
effect((onCleanup) => {
|
|
81
|
+
const cleanup = this.createColliderStateEffect();
|
|
82
|
+
onCleanup(() => cleanup?.());
|
|
83
|
+
});
|
|
84
|
+
effect((onCleanup) => {
|
|
85
|
+
const cleanup = this.createColliderEventsEffect();
|
|
86
|
+
onCleanup(() => cleanup?.());
|
|
87
|
+
});
|
|
88
|
+
effect(() => {
|
|
89
|
+
this.updateColliderEffect();
|
|
90
|
+
this.updateMassPropertiesEffect();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
get worldScale() {
|
|
94
|
+
return this.objectRef.nativeElement.getWorldScale(new Vector3());
|
|
95
|
+
}
|
|
96
|
+
setShape(shape) {
|
|
97
|
+
this.shape.set(shape);
|
|
98
|
+
}
|
|
99
|
+
setArgs(args) {
|
|
100
|
+
this.args.set(args);
|
|
101
|
+
}
|
|
102
|
+
createColliderStateEffect() {
|
|
103
|
+
const collider = this.collider();
|
|
104
|
+
if (!collider)
|
|
105
|
+
return;
|
|
106
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
107
|
+
if (!worldSingleton)
|
|
108
|
+
return;
|
|
109
|
+
const state = this.createColliderState(collider, this.objectRef.nativeElement, this.rigidBody?.objectRef.nativeElement);
|
|
110
|
+
this.physics.colliderStates.set(collider.handle, state);
|
|
111
|
+
return () => {
|
|
112
|
+
this.physics.colliderStates.delete(collider.handle);
|
|
113
|
+
if (worldSingleton.proxy.getCollider(collider.handle)) {
|
|
114
|
+
worldSingleton.proxy.removeCollider(collider, true);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
createColliderEventsEffect() {
|
|
119
|
+
const collider = this.collider();
|
|
120
|
+
if (!collider)
|
|
121
|
+
return;
|
|
122
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
123
|
+
if (!worldSingleton)
|
|
124
|
+
return;
|
|
125
|
+
const collisionEnter = getEmitter(this.collisionEnter);
|
|
126
|
+
const collisionExit = getEmitter(this.collisionExit);
|
|
127
|
+
const intersectionEnter = getEmitter(this.intersectionEnter);
|
|
128
|
+
const intersectionExit = getEmitter(this.intersectionExit);
|
|
129
|
+
const contactForce = getEmitter(this.contactForce);
|
|
130
|
+
const hasCollisionEvent = hasListener(this.collisionEnter, this.collisionExit, this.intersectionEnter, this.intersectionExit, this.rigidBody?.collisionEnter, this.rigidBody?.collisionExit, this.rigidBody?.intersectionEnter, this.rigidBody?.intersectionExit);
|
|
131
|
+
const hasContactForceEvent = hasListener(this.contactForce, this.rigidBody?.contactForce);
|
|
132
|
+
if (hasCollisionEvent && hasContactForceEvent) {
|
|
133
|
+
collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS | ActiveEvents.CONTACT_FORCE_EVENTS);
|
|
134
|
+
}
|
|
135
|
+
else if (hasCollisionEvent) {
|
|
136
|
+
collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
|
137
|
+
}
|
|
138
|
+
else if (hasContactForceEvent) {
|
|
139
|
+
collider.setActiveEvents(ActiveEvents.CONTACT_FORCE_EVENTS);
|
|
140
|
+
}
|
|
141
|
+
this.physics.colliderEvents.set(collider.handle, {
|
|
142
|
+
onCollisionEnter: collisionEnter,
|
|
143
|
+
onCollisionExit: collisionExit,
|
|
144
|
+
onIntersectionEnter: intersectionEnter,
|
|
145
|
+
onIntersectionExit: intersectionExit,
|
|
146
|
+
onContactForce: contactForce,
|
|
147
|
+
});
|
|
148
|
+
return () => {
|
|
149
|
+
this.physics.colliderEvents.delete(collider.handle);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
updateColliderEffect() {
|
|
153
|
+
const collider = this.collider();
|
|
154
|
+
if (!collider)
|
|
155
|
+
return;
|
|
156
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
157
|
+
if (!worldSingleton)
|
|
158
|
+
return;
|
|
159
|
+
const state = this.physics.colliderStates.get(collider.handle);
|
|
160
|
+
if (!state)
|
|
161
|
+
return;
|
|
162
|
+
// Update collider position based on the object's position
|
|
163
|
+
const parentWorldScale = state.object.parent.getWorldScale(_vector3);
|
|
164
|
+
const parentInvertedWorldMatrix = state.worldParent?.matrixWorld.clone().invert();
|
|
165
|
+
state.object.updateWorldMatrix(true, false);
|
|
166
|
+
_matrix4.copy(state.object.matrixWorld);
|
|
167
|
+
if (parentInvertedWorldMatrix) {
|
|
168
|
+
_matrix4.premultiply(parentInvertedWorldMatrix);
|
|
169
|
+
}
|
|
170
|
+
_matrix4.decompose(_position, _rotation, _scale);
|
|
171
|
+
if (collider.parent()) {
|
|
172
|
+
collider.setTranslationWrtParent({
|
|
173
|
+
x: _position.x * parentWorldScale.x,
|
|
174
|
+
y: _position.y * parentWorldScale.y,
|
|
175
|
+
z: _position.z * parentWorldScale.z,
|
|
176
|
+
});
|
|
177
|
+
collider.setRotationWrtParent(_rotation);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
collider.setTranslation({
|
|
181
|
+
x: _position.x * parentWorldScale.x,
|
|
182
|
+
y: _position.y * parentWorldScale.y,
|
|
183
|
+
z: _position.z * parentWorldScale.z,
|
|
184
|
+
});
|
|
185
|
+
collider.setRotation(_rotation);
|
|
186
|
+
}
|
|
187
|
+
const [sensor, collisionGroups, solverGroups, friction, frictionCombineRule, restitution, restitutionCombineRule, activeCollisionTypes, contactSkin,] = [
|
|
188
|
+
this.sensor(),
|
|
189
|
+
this.collisionGroups(),
|
|
190
|
+
this.solverGroups(),
|
|
191
|
+
this.friction(),
|
|
192
|
+
this.frictionCombineRule(),
|
|
193
|
+
this.restitution(),
|
|
194
|
+
this.restitutionCombineRule(),
|
|
195
|
+
this.activeCollisionTypes(),
|
|
196
|
+
this.contactSkin(),
|
|
197
|
+
];
|
|
198
|
+
if (sensor !== undefined)
|
|
199
|
+
collider.setSensor(sensor);
|
|
200
|
+
if (collisionGroups !== undefined)
|
|
201
|
+
collider.setCollisionGroups(collisionGroups);
|
|
202
|
+
if (solverGroups !== undefined)
|
|
203
|
+
collider.setSolverGroups(solverGroups);
|
|
204
|
+
if (friction !== undefined)
|
|
205
|
+
collider.setFriction(friction);
|
|
206
|
+
if (frictionCombineRule !== undefined)
|
|
207
|
+
collider.setFrictionCombineRule(frictionCombineRule);
|
|
208
|
+
if (restitution !== undefined)
|
|
209
|
+
collider.setRestitution(restitution);
|
|
210
|
+
if (restitutionCombineRule !== undefined)
|
|
211
|
+
collider.setRestitutionCombineRule(restitutionCombineRule);
|
|
212
|
+
if (activeCollisionTypes !== undefined)
|
|
213
|
+
collider.setActiveCollisionTypes(activeCollisionTypes);
|
|
214
|
+
if (contactSkin !== undefined)
|
|
215
|
+
collider.setContactSkin(contactSkin);
|
|
216
|
+
}
|
|
217
|
+
updateMassPropertiesEffect() {
|
|
218
|
+
const collider = this.collider();
|
|
219
|
+
if (!collider)
|
|
220
|
+
return;
|
|
221
|
+
const [mass, massProperties, density] = [this.mass(), this.massProperties(), this.density()];
|
|
222
|
+
if (density !== undefined) {
|
|
223
|
+
if (mass !== undefined || massProperties !== undefined) {
|
|
224
|
+
throw new Error('[NGT Rapier] Cannot set mass and massProperties along with density');
|
|
225
|
+
}
|
|
226
|
+
collider.setDensity(density);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (mass !== undefined) {
|
|
230
|
+
if (massProperties !== undefined) {
|
|
231
|
+
throw new Error('[NGT Rapier] Cannot set massProperties along with mass');
|
|
232
|
+
}
|
|
233
|
+
collider.setMass(mass);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (massProperties !== undefined) {
|
|
237
|
+
collider.setMassProperties(massProperties.mass, massProperties.centerOfMass, massProperties.principalAngularInertia, massProperties.angularInertiaLocalFrame);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
createColliderState(collider, object, rigidBodyObject) {
|
|
242
|
+
return { collider, worldParent: rigidBodyObject || undefined, object };
|
|
243
|
+
}
|
|
244
|
+
scaleVertices(vertices, scale) {
|
|
245
|
+
const scaledVerts = Array.from(vertices);
|
|
246
|
+
for (let i = 0; i < vertices.length / 3; i++) {
|
|
247
|
+
scaledVerts[i * 3] *= scale.x;
|
|
248
|
+
scaledVerts[i * 3 + 1] *= scale.y;
|
|
249
|
+
scaledVerts[i * 3 + 2] *= scale.z;
|
|
250
|
+
}
|
|
251
|
+
return scaledVerts;
|
|
252
|
+
}
|
|
253
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtrAnyCollider, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
254
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.0", type: NgtrAnyCollider, isStandalone: true, selector: "ngt-object3D[ngtrCollider]", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, rotation: { classPropertyName: "rotation", publicName: "rotation", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, quaternion: { classPropertyName: "quaternion", publicName: "quaternion", isSignal: true, isRequired: false, transformFunction: null }, userData: { classPropertyName: "userData", publicName: "userData", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "ngtrCollider", isSignal: true, isRequired: false, transformFunction: null }, args: { classPropertyName: "args", publicName: "args", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { shape: "ngtrColliderChange", args: "argsChange", collisionEnter: "collisionEnter", collisionExit: "collisionExit", intersectionEnter: "intersectionEnter", intersectionExit: "intersectionExit", contactForce: "contactForce" }, host: { properties: { "position": "position()", "rotation": "rotation()", "scale": "scale()", "quaternion": "quaternion()", "userData": "userData()", "name": "name()" } }, ngImport: i0 });
|
|
255
|
+
}
|
|
256
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtrAnyCollider, decorators: [{
|
|
257
|
+
type: Directive,
|
|
258
|
+
args: [{
|
|
259
|
+
selector: 'ngt-object3D[ngtrCollider]',
|
|
260
|
+
standalone: true,
|
|
261
|
+
host: {
|
|
262
|
+
'[position]': 'position()',
|
|
263
|
+
'[rotation]': 'rotation()',
|
|
264
|
+
'[scale]': 'scale()',
|
|
265
|
+
'[quaternion]': 'quaternion()',
|
|
266
|
+
'[userData]': 'userData()',
|
|
267
|
+
'[name]': 'name()',
|
|
268
|
+
},
|
|
269
|
+
}]
|
|
270
|
+
}], ctorParameters: () => [] });
|
|
271
|
+
const RIGID_BODY_TYPE_MAP = {
|
|
272
|
+
fixed: 1,
|
|
273
|
+
dynamic: 0,
|
|
274
|
+
kinematicPosition: 2,
|
|
275
|
+
kinematicVelocity: 3,
|
|
276
|
+
};
|
|
277
|
+
export const rigidBodyDefaultOptions = {
|
|
278
|
+
canSleep: true,
|
|
279
|
+
linearVelocity: [0, 0, 0],
|
|
280
|
+
angularVelocity: [0, 0, 0],
|
|
281
|
+
gravityScale: 1,
|
|
282
|
+
dominanceGroup: 0,
|
|
283
|
+
ccd: false,
|
|
284
|
+
softCcdPrediction: 0,
|
|
285
|
+
contactSkin: 0,
|
|
286
|
+
};
|
|
287
|
+
export class NgtrRigidBody {
|
|
288
|
+
type = input('dynamic', {
|
|
289
|
+
alias: 'ngtrRigidBody',
|
|
290
|
+
transform: (value) => {
|
|
291
|
+
if (value === '' || value === undefined)
|
|
292
|
+
return 'dynamic';
|
|
293
|
+
return value;
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
position = input([0, 0, 0]);
|
|
297
|
+
rotation = input([0, 0, 0]);
|
|
298
|
+
scale = input([1, 1, 1]);
|
|
299
|
+
quaternion = input([0, 0, 0, 1]);
|
|
300
|
+
userData = input({});
|
|
301
|
+
options = input(rigidBodyDefaultOptions, { transform: mergeInputs(rigidBodyDefaultOptions) });
|
|
302
|
+
wake = output();
|
|
303
|
+
sleep = output();
|
|
304
|
+
collisionEnter = output();
|
|
305
|
+
collisionExit = output();
|
|
306
|
+
intersectionEnter = output();
|
|
307
|
+
intersectionExit = output();
|
|
308
|
+
contactForce = output();
|
|
309
|
+
canSleep = pick(this.options, 'canSleep');
|
|
310
|
+
colliders = pick(this.options, 'colliders');
|
|
311
|
+
transformState = pick(this.options, 'transformState');
|
|
312
|
+
gravityScale = pick(this.options, 'gravityScale');
|
|
313
|
+
dominanceGroup = pick(this.options, 'dominanceGroup');
|
|
314
|
+
ccd = pick(this.options, 'ccd');
|
|
315
|
+
softCcdPrediction = pick(this.options, 'softCcdPrediction');
|
|
316
|
+
additionalSolverIterations = pick(this.options, 'additionalSolverIterations');
|
|
317
|
+
linearDamping = pick(this.options, 'linearDamping');
|
|
318
|
+
angularDamping = pick(this.options, 'angularDamping');
|
|
319
|
+
lockRotations = pick(this.options, 'lockRotations');
|
|
320
|
+
lockTranslations = pick(this.options, 'lockTranslations');
|
|
321
|
+
enabledRotations = pick(this.options, 'enabledRotations');
|
|
322
|
+
enabledTranslations = pick(this.options, 'enabledTranslations');
|
|
323
|
+
angularVelocity = pick(this.options, 'angularVelocity');
|
|
324
|
+
linearVelocity = pick(this.options, 'linearVelocity');
|
|
325
|
+
objectRef = inject(ElementRef);
|
|
326
|
+
physics = inject(NgtrPhysics);
|
|
327
|
+
bodyType = computed(() => RIGID_BODY_TYPE_MAP[this.type()]);
|
|
328
|
+
bodyDesc = computed(() => {
|
|
329
|
+
const [canSleep, bodyType] = [this.canSleep(), untracked(this.bodyType), this.colliders()];
|
|
330
|
+
return new RigidBodyDesc(bodyType).setCanSleep(canSleep);
|
|
331
|
+
});
|
|
332
|
+
rigidBody = computed(() => {
|
|
333
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
334
|
+
if (!worldSingleton)
|
|
335
|
+
return null;
|
|
336
|
+
return worldSingleton.proxy.createRigidBody(this.bodyDesc());
|
|
337
|
+
});
|
|
338
|
+
childColliderOptions = computed(() => {
|
|
339
|
+
const colliders = this.colliders();
|
|
340
|
+
// if self colliders is false explicitly, disable auto colliders for this object entirely.
|
|
341
|
+
if (colliders === false)
|
|
342
|
+
return [];
|
|
343
|
+
const physicsColliders = this.physics.colliders();
|
|
344
|
+
// if physics colliders is false explicitly, disable auto colliders for this object entirely.
|
|
345
|
+
if (physicsColliders === false)
|
|
346
|
+
return [];
|
|
347
|
+
const options = this.options();
|
|
348
|
+
// if colliders on object is not set, use physics colliders
|
|
349
|
+
if (!options.colliders)
|
|
350
|
+
options.colliders = physicsColliders;
|
|
351
|
+
const objectLocalState = getLocalState(this.objectRef.nativeElement);
|
|
352
|
+
// track object's children
|
|
353
|
+
objectLocalState?.nonObjects();
|
|
354
|
+
return createColliderOptions(this.objectRef.nativeElement, options, true);
|
|
355
|
+
});
|
|
356
|
+
constructor() {
|
|
357
|
+
extend({ Object3D });
|
|
358
|
+
effect((onCleanup) => {
|
|
359
|
+
const cleanup = this.createRigidBodyStateEffect();
|
|
360
|
+
onCleanup(() => cleanup?.());
|
|
361
|
+
});
|
|
362
|
+
effect((onCleanup) => {
|
|
363
|
+
const cleanup = this.createRigidBodyEventsEffect();
|
|
364
|
+
onCleanup(() => cleanup?.());
|
|
365
|
+
});
|
|
366
|
+
effect(() => {
|
|
367
|
+
this.updateRigidBodyEffect();
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
createRigidBodyStateEffect() {
|
|
371
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
372
|
+
if (!worldSingleton)
|
|
373
|
+
return;
|
|
374
|
+
const body = this.rigidBody();
|
|
375
|
+
if (!body)
|
|
376
|
+
return;
|
|
377
|
+
const transformState = untracked(this.transformState);
|
|
378
|
+
const state = this.createRigidBodyState(body, this.objectRef.nativeElement);
|
|
379
|
+
this.physics.rigidBodyStates.set(body.handle, transformState ? transformState(state) : state);
|
|
380
|
+
return () => {
|
|
381
|
+
this.physics.rigidBodyStates.delete(body.handle);
|
|
382
|
+
if (worldSingleton.proxy.getRigidBody(body.handle)) {
|
|
383
|
+
worldSingleton.proxy.removeRigidBody(body);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
createRigidBodyEventsEffect() {
|
|
388
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
389
|
+
if (!worldSingleton)
|
|
390
|
+
return;
|
|
391
|
+
const body = this.rigidBody();
|
|
392
|
+
if (!body)
|
|
393
|
+
return;
|
|
394
|
+
const wake = getEmitter(this.wake);
|
|
395
|
+
const sleep = getEmitter(this.sleep);
|
|
396
|
+
const collisionEnter = getEmitter(this.collisionEnter);
|
|
397
|
+
const collisionExit = getEmitter(this.collisionExit);
|
|
398
|
+
const intersectionEnter = getEmitter(this.intersectionEnter);
|
|
399
|
+
const intersectionExit = getEmitter(this.intersectionExit);
|
|
400
|
+
const contactForce = getEmitter(this.contactForce);
|
|
401
|
+
this.physics.rigidBodyEvents.set(body.handle, {
|
|
402
|
+
onWake: wake,
|
|
403
|
+
onSleep: sleep,
|
|
404
|
+
onCollisionEnter: collisionEnter,
|
|
405
|
+
onCollisionExit: collisionExit,
|
|
406
|
+
onIntersectionEnter: intersectionEnter,
|
|
407
|
+
onIntersectionExit: intersectionExit,
|
|
408
|
+
onContactForce: contactForce,
|
|
409
|
+
});
|
|
410
|
+
return () => {
|
|
411
|
+
this.physics.rigidBodyEvents.delete(body.handle);
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
updateRigidBodyEffect() {
|
|
415
|
+
const worldSingleton = this.physics.worldSingleton();
|
|
416
|
+
if (!worldSingleton)
|
|
417
|
+
return;
|
|
418
|
+
const body = this.rigidBody();
|
|
419
|
+
if (!body)
|
|
420
|
+
return;
|
|
421
|
+
const state = this.physics.rigidBodyStates.get(body.handle);
|
|
422
|
+
if (!state)
|
|
423
|
+
return;
|
|
424
|
+
state.object.updateWorldMatrix(true, false);
|
|
425
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
|
426
|
+
body.setTranslation(_position, true);
|
|
427
|
+
body.setRotation(_rotation, true);
|
|
428
|
+
const [gravityScale, additionalSolverIterations, linearDamping, angularDamping, lockRotations, lockTranslations, enabledRotations, enabledTranslations, angularVelocity, linearVelocity, ccd, softCcdPrediction, dominanceGroup, userData, bodyType,] = [
|
|
429
|
+
this.gravityScale(),
|
|
430
|
+
this.additionalSolverIterations(),
|
|
431
|
+
this.linearDamping(),
|
|
432
|
+
this.angularDamping(),
|
|
433
|
+
this.lockRotations(),
|
|
434
|
+
this.lockTranslations(),
|
|
435
|
+
this.enabledRotations(),
|
|
436
|
+
this.enabledTranslations(),
|
|
437
|
+
this.angularVelocity(),
|
|
438
|
+
this.linearVelocity(),
|
|
439
|
+
this.ccd(),
|
|
440
|
+
this.softCcdPrediction(),
|
|
441
|
+
this.dominanceGroup(),
|
|
442
|
+
this.userData(),
|
|
443
|
+
this.bodyType(),
|
|
444
|
+
];
|
|
445
|
+
body.setGravityScale(gravityScale, true);
|
|
446
|
+
if (additionalSolverIterations !== undefined)
|
|
447
|
+
body.setAdditionalSolverIterations(additionalSolverIterations);
|
|
448
|
+
if (linearDamping !== undefined)
|
|
449
|
+
body.setLinearDamping(linearDamping);
|
|
450
|
+
if (angularDamping !== undefined)
|
|
451
|
+
body.setAngularDamping(angularDamping);
|
|
452
|
+
body.setDominanceGroup(dominanceGroup);
|
|
453
|
+
if (enabledRotations !== undefined)
|
|
454
|
+
body.setEnabledRotations(...enabledRotations, true);
|
|
455
|
+
if (enabledTranslations !== undefined)
|
|
456
|
+
body.setEnabledTranslations(...enabledTranslations, true);
|
|
457
|
+
if (lockRotations !== undefined)
|
|
458
|
+
body.lockRotations(lockRotations, true);
|
|
459
|
+
if (lockTranslations !== undefined)
|
|
460
|
+
body.lockTranslations(lockTranslations, true);
|
|
461
|
+
body.setAngvel({ x: angularVelocity[0], y: angularVelocity[1], z: angularVelocity[2] }, true);
|
|
462
|
+
body.setLinvel({ x: linearVelocity[0], y: linearVelocity[1], z: linearVelocity[2] }, true);
|
|
463
|
+
body.enableCcd(ccd);
|
|
464
|
+
body.setSoftCcdPrediction(softCcdPrediction);
|
|
465
|
+
if (userData !== undefined)
|
|
466
|
+
body.userData = userData;
|
|
467
|
+
if (bodyType !== body.bodyType())
|
|
468
|
+
body.setBodyType(bodyType, true);
|
|
469
|
+
}
|
|
470
|
+
createRigidBodyState(rigidBody, object, setMatrix, getMatrix, worldScale, meshType = 'mesh') {
|
|
471
|
+
object.updateWorldMatrix(true, false);
|
|
472
|
+
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
|
473
|
+
return {
|
|
474
|
+
object,
|
|
475
|
+
rigidBody,
|
|
476
|
+
invertedWorldMatrix,
|
|
477
|
+
setMatrix: setMatrix
|
|
478
|
+
? setMatrix
|
|
479
|
+
: (matrix) => {
|
|
480
|
+
object.matrix.copy(matrix);
|
|
481
|
+
},
|
|
482
|
+
getMatrix: getMatrix ? getMatrix : (matrix) => matrix.copy(object.matrix),
|
|
483
|
+
scale: worldScale || object.getWorldScale(_scale).clone(),
|
|
484
|
+
isSleeping: false,
|
|
485
|
+
meshType,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtrRigidBody, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
489
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: NgtrRigidBody, isStandalone: true, selector: "ngt-object3D[ngtrRigidBody]", inputs: { type: { classPropertyName: "type", publicName: "ngtrRigidBody", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, rotation: { classPropertyName: "rotation", publicName: "rotation", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, quaternion: { classPropertyName: "quaternion", publicName: "quaternion", isSignal: true, isRequired: false, transformFunction: null }, userData: { classPropertyName: "userData", publicName: "userData", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wake: "wake", sleep: "sleep", collisionEnter: "collisionEnter", collisionExit: "collisionExit", intersectionEnter: "intersectionEnter", intersectionExit: "intersectionExit", contactForce: "contactForce" }, host: { properties: { "position": "position()", "rotation": "rotation()", "scale": "scale()", "quaternion": "quaternion()", "userData": "userData()" } }, exportAs: ["rigidBody"], ngImport: i0, template: `
|
|
490
|
+
<ng-content />
|
|
491
|
+
@for (childColliderOption of childColliderOptions(); track $index) {
|
|
492
|
+
<ngt-object3D
|
|
493
|
+
[ngtrCollider]="childColliderOption.shape"
|
|
494
|
+
[args]="childColliderOption.args"
|
|
495
|
+
[position]="childColliderOption.position"
|
|
496
|
+
[rotation]="childColliderOption.rotation"
|
|
497
|
+
[scale]="childColliderOption.scale"
|
|
498
|
+
[name]="objectRef.nativeElement.name + '-collider-' + $index"
|
|
499
|
+
[options]="childColliderOption.colliderOptions"
|
|
500
|
+
/>
|
|
501
|
+
}
|
|
502
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgtrAnyCollider, selector: "ngt-object3D[ngtrCollider]", inputs: ["position", "rotation", "scale", "quaternion", "userData", "name", "options", "ngtrCollider", "args"], outputs: ["ngtrColliderChange", "argsChange", "collisionEnter", "collisionExit", "intersectionEnter", "intersectionExit", "contactForce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
503
|
+
}
|
|
504
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgtrRigidBody, decorators: [{
|
|
505
|
+
type: Component,
|
|
506
|
+
args: [{
|
|
507
|
+
selector: 'ngt-object3D[ngtrRigidBody]',
|
|
508
|
+
exportAs: 'rigidBody',
|
|
509
|
+
standalone: true,
|
|
510
|
+
template: `
|
|
511
|
+
<ng-content />
|
|
512
|
+
@for (childColliderOption of childColliderOptions(); track $index) {
|
|
513
|
+
<ngt-object3D
|
|
514
|
+
[ngtrCollider]="childColliderOption.shape"
|
|
515
|
+
[args]="childColliderOption.args"
|
|
516
|
+
[position]="childColliderOption.position"
|
|
517
|
+
[rotation]="childColliderOption.rotation"
|
|
518
|
+
[scale]="childColliderOption.scale"
|
|
519
|
+
[name]="objectRef.nativeElement.name + '-collider-' + $index"
|
|
520
|
+
[options]="childColliderOption.colliderOptions"
|
|
521
|
+
/>
|
|
522
|
+
}
|
|
523
|
+
`,
|
|
524
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
525
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
526
|
+
host: {
|
|
527
|
+
'[position]': 'position()',
|
|
528
|
+
'[rotation]': 'rotation()',
|
|
529
|
+
'[scale]': 'scale()',
|
|
530
|
+
'[quaternion]': 'quaternion()',
|
|
531
|
+
'[userData]': 'userData()',
|
|
532
|
+
},
|
|
533
|
+
imports: [NgtrAnyCollider],
|
|
534
|
+
}]
|
|
535
|
+
}], ctorParameters: () => [] });
|
|
536
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmlnaWQtYm9keS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMvcmFwaWVyL3NyYy9saWIvcmlnaWQtYm9keS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1Isc0JBQXNCLEVBQ3RCLFNBQVMsRUFDVCxNQUFNLEVBQ04sVUFBVSxFQUNWLE1BQU0sRUFDTixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBWSxZQUFZLEVBQWEsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0csT0FBTyxFQUNOLE1BQU0sRUFDTixVQUFVLEVBQ1YsYUFBYSxFQUNiLFdBQVcsRUFLWCxJQUFJLEdBQ0osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBVyxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ25ELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDeEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFjNUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sU0FBUyxDQUFDOztBQUVoRCxNQUFNLHNCQUFzQixHQUF3QjtJQUNuRCxXQUFXLEVBQUUsQ0FBQztDQUNkLENBQUM7QUFjRixNQUFNLE9BQU8sZUFBZTtJQUMzQixRQUFRLEdBQUcsS0FBSyxDQUF5QixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLEdBQUcsS0FBSyxDQUF1QixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FB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QkFBbUI7WUFDbkIsU0FBUyxFQUFFLFNBQVM7Z0JBQ25CLENBQUMsQ0FBQyxTQUFTO2dCQUNYLENBQUMsQ0FBQyxDQUFDLE1BQWUsRUFBRSxFQUFFO29CQUNwQixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDNUIsQ0FBQztZQUNILFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFlLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUNsRixLQUFLLEVBQUUsVUFBVSxJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFO1lBQ3pELFVBQVUsRUFBRSxLQUFLO1lBQ2pCLFFBQVE7U0FDUixDQUFDO0lBQ0gsQ0FBQzt1R0F4T1csYUFBYTsyRkFBYixhQUFhLDYyQ0F6QmY7Ozs7Ozs7Ozs7Ozs7RUFhVCw0REFuVlcsZUFBZTs7MkZBK1ZmLGFBQWE7a0JBN0J6QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSw2QkFBNkI7b0JBQ3ZDLFFBQVEsRUFBRSxXQUFXO29CQUNyQixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7O0VBYVQ7b0JBQ0QsT0FBTyxFQUFFLENBQUMsc0JBQXNCLENBQUM7b0JBQ2pDLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxJQUFJLEVBQUU7d0JBQ0wsWUFBWSxFQUFFLFlBQVk7d0JBQzFCLFlBQVksRUFBRSxZQUFZO3dCQUMxQixTQUFTLEVBQUUsU0FBUzt3QkFDcEIsY0FBYyxFQUFFLGNBQWM7d0JBQzlCLFlBQVksRUFBRSxZQUFZO3FCQUMxQjtvQkFDRCxPQUFPLEVBQUUsQ0FBQyxlQUFlLENBQUM7aUJBQzFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG5cdENvbXBvbmVudCxcblx0Y29tcHV0ZWQsXG5cdENVU1RPTV9FTEVNRU5UU19TQ0hFTUEsXG5cdERpcmVjdGl2ZSxcblx0ZWZmZWN0LFxuXHRFbGVtZW50UmVmLFxuXHRpbmplY3QsXG5cdGlucHV0LFxuXHRtb2RlbCxcblx0b3V0cHV0LFxuXHR1bnRyYWNrZWQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZlRXZlbnRzLCBDb2xsaWRlciwgQ29sbGlkZXJEZXNjLCBSaWdpZEJvZHksIFJpZ2lkQm9keURlc2MgfSBmcm9tICdAZGltZm9yZ2UvcmFwaWVyM2QtY29tcGF0JztcbmltcG9ydCB7XG5cdGV4dGVuZCxcblx0Z2V0RW1pdHRlcixcblx0Z2V0TG9jYWxTdGF0ZSxcblx0aGFzTGlzdGVuZXIsXG5cdE5ndEV1bGVyLFxuXHROZ3RPYmplY3QzRCxcblx0Tmd0UXVhdGVybmlvbixcblx0Tmd0VmVjdG9yMyxcblx0cGljayxcbn0gZnJvbSAnYW5ndWxhci10aHJlZSc7XG5pbXBvcnQgeyBtZXJnZUlucHV0cyB9IGZyb20gJ25neHRlbnNpb24vaW5qZWN0LWlucHV0cyc7XG5pbXBvcnQgeyBNYXRyaXg0LCBPYmplY3QzRCwgVmVjdG9yMyB9IGZyb20gJ3RocmVlJztcbmltcG9ydCB7IE5ndHJQaHlzaWNzIH0gZnJvbSAnLi9waHlzaWNzJztcbmltcG9ydCB7IF9tYXRyaXg0LCBfcG9zaXRpb24sIF9yb3RhdGlvbiwgX3NjYWxlLCBfdmVjdG9yMyB9IGZyb20gJy4vc2hhcmVkJztcbmltcG9ydCB7XG5cdE5ndHJDb2xsaWRlck9wdGlvbnMsXG5cdE5ndHJDb2xsaWRlclNoYXBlLFxuXHROZ3RyQ29sbGlkZXJTdGF0ZSxcblx0Tmd0ckNvbGxpc2lvbkVudGVyUGF5bG9hZCxcblx0Tmd0ckNvbGxpc2lvbkV4aXRQYXlsb2FkLFxuXHROZ3RyQ29udGFjdEZvcmNlUGF5bG9hZCxcblx0Tmd0ckludGVyc2VjdGlvbkVudGVyUGF5bG9hZCxcblx0Tmd0ckludGVyc2VjdGlvbkV4aXRQYXlsb2FkLFxuXHROZ3RyUmlnaWRCb2R5T3B0aW9ucyxcblx0Tmd0clJpZ2lkQm9keVN0YXRlLFxuXHROZ3RyUmlnaWRCb2R5VHlwZSxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBjcmVhdGVDb2xsaWRlck9wdGlvbnMgfSBmcm9tICcuL3V0aWxzJztcblxuY29uc3QgY29sbGlkZXJEZWZhdWx0T3B0aW9uczogTmd0ckNvbGxpZGVyT3B0aW9ucyA9IHtcblx0Y29udGFjdFNraW46IDAsXG59O1xuXG5ARGlyZWN0aXZlKHtcblx0c2VsZWN0b3I6ICduZ3Qtb2JqZWN0M0Rbbmd0ckNvbGxpZGVyXScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGhvc3Q6IHtcblx0XHQnW3Bvc2l0aW9uXSc6ICdwb3NpdGlvbigpJyxcblx0XHQnW3JvdGF0aW9uXSc6ICdyb3RhdGlvbigpJyxcblx0XHQnW3NjYWxlXSc6ICdzY2FsZSgpJyxcblx0XHQnW3F1YXRlcm5pb25dJzogJ3F1YXRlcm5pb24oKScsXG5cdFx0J1t1c2VyRGF0YV0nOiAndXNlckRhdGEoKScsXG5cdFx0J1tuYW1lXSc6ICduYW1lKCknLFxuXHR9LFxufSlcbmV4cG9ydCBjbGFzcyBOZ3RyQW55Q29sbGlkZXIge1xuXHRwb3NpdGlvbiA9IGlucHV0PE5ndFZlY3RvcjMgfCB1bmRlZmluZWQ+KFswLCAwLCAwXSk7XG5cdHJvdGF0aW9uID0gaW5wdXQ8Tmd0RXVsZXIgfCB1bmRlZmluZWQ+KFswLCAwLCAwXSk7XG5cdHNjYWxlID0gaW5wdXQ8Tmd0VmVjdG9yMyB8IHVuZGVmaW5lZD4oWzEsIDEsIDFdKTtcblx0cXVhdGVybmlvbiA9IGlucHV0PE5ndFF1YXRlcm5pb24gfCB1bmRlZmluZWQ+KFswLCAwLCAwLCAxXSk7XG5cdHVzZXJEYXRhID0gaW5wdXQ8Tmd0T2JqZWN0M0RbJ3VzZXJEYXRhJ10gfCB1bmRlZmluZWQ+KHt9KTtcblx0bmFtZSA9IGlucHV0PE5ndE9iamVjdDNEWyduYW1lJ10gfCB1bmRlZmluZWQ+KCk7XG5cdG9wdGlvbnMgPSBpbnB1dChjb2xsaWRlckRlZmF1bHRPcHRpb25zLCB7IHRyYW5zZm9ybTogbWVyZ2VJbnB1dHMocmlnaWRCb2R5RGVmYXVsdE9wdGlvbnMpIH0pO1xuXG5cdC8vIFRPRE86IGNoYW5nZSB0aGlzIHRvIGlucHV0IHJlcXVpcmVkIHdoZW4gQW5ndWxhciBhbGxvd3Mgc2V0dGluZyBob3N0RGlyZWN0aXZlIGlucHV0XG5cdHNoYXBlID0gbW9kZWw8Tmd0ckNvbGxpZGVyU2hhcGUgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCwgeyBhbGlhczogJ25ndHJDb2xsaWRlcicgfSk7XG5cdGFyZ3MgPSBtb2RlbDx1bmtub3duW10+KFtdKTtcblxuXHRjb2xsaXNpb25FbnRlciA9IG91dHB1dDxOZ3RyQ29sbGlzaW9uRW50ZXJQYXlsb2FkPigpO1xuXHRjb2xsaXNpb25FeGl0ID0gb3V0cHV0PE5ndHJDb2xsaXNpb25FeGl0UGF5bG9hZD4oKTtcblx0aW50ZXJzZWN0aW9uRW50ZXIgPSBvdXRwdXQ8Tmd0ckludGVyc2VjdGlvbkVudGVyUGF5bG9hZD4oKTtcblx0aW50ZXJzZWN0aW9uRXhpdCA9IG91dHB1dDxOZ3RySW50ZXJzZWN0aW9uRXhpdFBheWxvYWQ+KCk7XG5cdGNvbnRhY3RGb3JjZSA9IG91dHB1dDxOZ3RyQ29udGFjdEZvcmNlUGF5bG9hZD4oKTtcblxuXHRwcml2YXRlIHNlbnNvciA9IHBpY2sodGhpcy5vcHRpb25zLCAnc2Vuc29yJyk7XG5cdHByaXZhdGUgY29sbGlzaW9uR3JvdXBzID0gcGljayh0aGlzLm9wdGlvbnMsICdjb2xsaXNpb25Hcm91cHMnKTtcblx0cHJpdmF0ZSBzb2x2ZXJHcm91cHMgPSBwaWNrKHRoaXMub3B0aW9ucywgJ3NvbHZlckdyb3VwcycpO1xuXHRwcml2YXRlIGZyaWN0aW9uID0gcGljayh0aGlzLm9wdGlvbnMsICdmcmljdGlvbicpO1xuXHRwcml2YXRlIGZyaWN0aW9uQ29tYmluZVJ1bGUgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2ZyaWN0aW9uQ29tYmluZVJ1bGUnKTtcblx0cHJpdmF0ZSByZXN0aXR1dGlvbiA9IHBpY2sodGhpcy5vcHRpb25zLCAncmVzdGl0dXRpb24nKTtcblx0cHJpdmF0ZSByZXN0aXR1dGlvbkNvbWJpbmVSdWxlID0gcGljayh0aGlzLm9wdGlvbnMsICdyZXN0aXR1dGlvbkNvbWJpbmVSdWxlJyk7XG5cdHByaXZhdGUgYWN0aXZlQ29sbGlzaW9uVHlwZXMgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2FjdGl2ZUNvbGxpc2lvblR5cGVzJyk7XG5cdHByaXZhdGUgY29udGFjdFNraW4gPSBwaWNrKHRoaXMub3B0aW9ucywgJ2NvbnRhY3RTa2luJyk7XG5cdHByaXZhdGUgbWFzcyA9IHBpY2sodGhpcy5vcHRpb25zLCAnbWFzcycpO1xuXHRwcml2YXRlIG1hc3NQcm9wZXJ0aWVzID0gcGljayh0aGlzLm9wdGlvbnMsICdtYXNzUHJvcGVydGllcycpO1xuXHRwcml2YXRlIGRlbnNpdHkgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2RlbnNpdHknKTtcblxuXHRwcml2YXRlIHJpZ2lkQm9keSA9IGluamVjdChOZ3RyUmlnaWRCb2R5LCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuXHRwcml2YXRlIHBoeXNpY3MgPSBpbmplY3QoTmd0clBoeXNpY3MpO1xuXHRvYmplY3RSZWYgPSBpbmplY3Q8RWxlbWVudFJlZjxPYmplY3QzRD4+KEVsZW1lbnRSZWYpO1xuXG5cdHByaXZhdGUgc2NhbGVkQXJncyA9IGNvbXB1dGVkKCgpID0+IHtcblx0XHRjb25zdCBbc2hhcGUsIGFyZ3NdID0gW1xuXHRcdFx0dGhpcy5zaGFwZSgpLFxuXHRcdFx0dGhpcy5hcmdzKCkgYXMgKG51bWJlciB8IEFycmF5TGlrZTxudW1iZXI+IHwgeyB4OiBudW1iZXI7IHk6IG51bWJlcjsgejogbnVtYmVyIH0pW10sXG5cdFx0XTtcblxuXHRcdGNvbnN0IGNsb25lZCA9IGFyZ3Muc2xpY2UoKTtcblxuXHRcdC8vIEhlaWdodGZpZWxkIHVzZXMgYSB2ZWN0b3Jcblx0XHRpZiAoc2hhcGUgPT09ICdoZWlnaHRmaWVsZCcpIHtcblx0XHRcdGNvbnN0IHMgPSBjbG9uZWRbM10gYXMgeyB4OiBudW1iZXI7IHk6IG51bWJlcjsgejogbnVtYmVyIH07XG5cdFx0XHRzLnggKj0gdGhpcy53b3JsZFNjYWxlLng7XG5cdFx0XHRzLnkgKj0gdGhpcy53b3JsZFNjYWxlLnk7XG5cdFx0XHRzLnogKj0gdGhpcy53b3JsZFNjYWxlLno7XG5cblx0XHRcdHJldHVybiBjbG9uZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gVHJpbWVzaCBhbmQgY29udmV4IHNjYWxlIHRoZSB2ZXJ0aWNlc1xuXHRcdGlmIChzaGFwZSA9PT0gJ3RyaW1lc2gnIHx8IHNoYXBlID09PSAnY29udmV4SHVsbCcpIHtcblx0XHRcdGNsb25lZFswXSA9IHRoaXMuc2NhbGVWZXJ0aWNlcyhjbG9uZWRbMF0gYXMgQXJyYXlMaWtlPG51bWJlcj4sIHRoaXMud29ybGRTY2FsZSk7XG5cdFx0XHRyZXR1cm4gY2xvbmVkO1xuXHRcdH1cblxuXHRcdC8vIHByZWZpbGwgd2l0aCBzb21lIGV4dHJhXG5cdFx0Y29uc3Qgc2NhbGVBcnJheSA9IFt0aGlzLndvcmxkU2NhbGUueCwgdGhpcy53b3JsZFNjYWxlLnksIHRoaXMud29ybGRTY2FsZS56LCB0aGlzLndvcmxkU2NhbGUueCwgdGhpcy53b3JsZFNjYWxlLnhdO1xuXHRcdHJldHVybiBjbG9uZWQubWFwKChhcmcsIGluZGV4KSA9PiBzY2FsZUFycmF5W2luZGV4XSAqIChhcmcgYXMgbnVtYmVyKSk7XG5cdH0pO1xuXG5cdHByaXZhdGUgY29sbGlkZXIgPSBjb21wdXRlZCgoKSA9PiB7XG5cdFx0Y29uc3Qgd29ybGRTaW5nbGV0b24gPSB0aGlzLnBoeXNpY3Mud29ybGRTaW5nbGV0b24oKTtcblx0XHRpZiAoIXdvcmxkU2luZ2xldG9uKSByZXR1cm4gbnVsbDtcblxuXHRcdGNvbnN0IFtzaGFwZSwgYXJncywgcmlnaWRCb2R5XSA9IFt0aGlzLnNoYXBlKCksIHRoaXMuc2NhbGVkQXJncygpLCB0aGlzLnJpZ2lkQm9keT8ucmlnaWRCb2R5KCldO1xuXG5cdFx0Ly8gQHRzLWV4cGVjdC1lcnJvciAtIHdlIGtub3cgdGhlIHR5cGUgb2YgdGhlIGRhdGFcblx0XHRjb25zdCBkZXNjID0gQ29sbGlkZXJEZXNjW3NoYXBlXSguLi5hcmdzKTtcblx0XHRpZiAoIWRlc2MpIHJldHVybiBudWxsO1xuXG5cdFx0cmV0dXJuIHdvcmxkU2luZ2xldG9uLnByb3h5LmNyZWF0ZUNvbGxpZGVyKGRlc2MsIHJpZ2lkQm9keSA/PyB1bmRlZmluZWQpO1xuXHR9KTtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRleHRlbmQoeyBPYmplY3QzRCB9KTtcblxuXHRcdGVmZmVjdCgob25DbGVhbnVwKSA9PiB7XG5cdFx0XHRjb25zdCBjbGVhbnVwID0gdGhpcy5jcmVhdGVDb2xsaWRlclN0YXRlRWZmZWN0KCk7XG5cdFx0XHRvbkNsZWFudXAoKCkgPT4gY2xlYW51cD8uKCkpO1xuXHRcdH0pO1xuXG5cdFx0ZWZmZWN0KChvbkNsZWFudXApID0+IHtcblx0XHRcdGNvbnN0IGNsZWFudXAgPSB0aGlzLmNyZWF0ZUNvbGxpZGVyRXZlbnRzRWZmZWN0KCk7XG5cdFx0XHRvbkNsZWFudXAoKCkgPT4gY2xlYW51cD8uKCkpO1xuXHRcdH0pO1xuXG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdHRoaXMudXBkYXRlQ29sbGlkZXJFZmZlY3QoKTtcblx0XHRcdHRoaXMudXBkYXRlTWFzc1Byb3BlcnRpZXNFZmZlY3QoKTtcblx0XHR9KTtcblx0fVxuXG5cdGdldCB3b3JsZFNjYWxlKCkge1xuXHRcdHJldHVybiB0aGlzLm9iamVjdFJlZi5uYXRpdmVFbGVtZW50LmdldFdvcmxkU2NhbGUobmV3IFZlY3RvcjMoKSk7XG5cdH1cblxuXHRzZXRTaGFwZShzaGFwZTogTmd0ckNvbGxpZGVyU2hhcGUpIHtcblx0XHR0aGlzLnNoYXBlLnNldChzaGFwZSk7XG5cdH1cblxuXHRzZXRBcmdzKGFyZ3M6IHVua25vd25bXSkge1xuXHRcdHRoaXMuYXJncy5zZXQoYXJncyk7XG5cdH1cblxuXHRwcml2YXRlIGNyZWF0ZUNvbGxpZGVyU3RhdGVFZmZlY3QoKSB7XG5cdFx0Y29uc3QgY29sbGlkZXIgPSB0aGlzLmNvbGxpZGVyKCk7XG5cdFx0aWYgKCFjb2xsaWRlcikgcmV0dXJuO1xuXG5cdFx0Y29uc3Qgd29ybGRTaW5nbGV0b24gPSB0aGlzLnBoeXNpY3Mud29ybGRTaW5nbGV0b24oKTtcblx0XHRpZiAoIXdvcmxkU2luZ2xldG9uKSByZXR1cm47XG5cblx0XHRjb25zdCBzdGF0ZSA9IHRoaXMuY3JlYXRlQ29sbGlkZXJTdGF0ZShcblx0XHRcdGNvbGxpZGVyLFxuXHRcdFx0dGhpcy5vYmplY3RSZWYubmF0aXZlRWxlbWVudCxcblx0XHRcdHRoaXMucmlnaWRCb2R5Py5vYmplY3RSZWYubmF0aXZlRWxlbWVudCxcblx0XHQpO1xuXHRcdHRoaXMucGh5c2ljcy5jb2xsaWRlclN0YXRlcy5zZXQoY29sbGlkZXIuaGFuZGxlLCBzdGF0ZSk7XG5cblx0XHRyZXR1cm4gKCkgPT4ge1xuXHRcdFx0dGhpcy5waHlzaWNzLmNvbGxpZGVyU3RhdGVzLmRlbGV0ZShjb2xsaWRlci5oYW5kbGUpO1xuXHRcdFx0aWYgKHdvcmxkU2luZ2xldG9uLnByb3h5LmdldENvbGxpZGVyKGNvbGxpZGVyLmhhbmRsZSkpIHtcblx0XHRcdFx0d29ybGRTaW5nbGV0b24ucHJveHkucmVtb3ZlQ29sbGlkZXIoY29sbGlkZXIsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHRwcml2YXRlIGNyZWF0ZUNvbGxpZGVyRXZlbnRzRWZmZWN0KCkge1xuXHRcdGNvbnN0IGNvbGxpZGVyID0gdGhpcy5jb2xsaWRlcigpO1xuXHRcdGlmICghY29sbGlkZXIpIHJldHVybjtcblxuXHRcdGNvbnN0IHdvcmxkU2luZ2xldG9uID0gdGhpcy5waHlzaWNzLndvcmxkU2luZ2xldG9uKCk7XG5cdFx0aWYgKCF3b3JsZFNpbmdsZXRvbikgcmV0dXJuO1xuXG5cdFx0Y29uc3QgY29sbGlzaW9uRW50ZXIgPSBnZXRFbWl0dGVyKHRoaXMuY29sbGlzaW9uRW50ZXIpO1xuXHRcdGNvbnN0IGNvbGxpc2lvbkV4aXQgPSBnZXRFbWl0dGVyKHRoaXMuY29sbGlzaW9uRXhpdCk7XG5cdFx0Y29uc3QgaW50ZXJzZWN0aW9uRW50ZXIgPSBnZXRFbWl0dGVyKHRoaXMuaW50ZXJzZWN0aW9uRW50ZXIpO1xuXHRcdGNvbnN0IGludGVyc2VjdGlvbkV4aXQgPSBnZXRFbWl0dGVyKHRoaXMuaW50ZXJzZWN0aW9uRXhpdCk7XG5cdFx0Y29uc3QgY29udGFjdEZvcmNlID0gZ2V0RW1pdHRlcih0aGlzLmNvbnRhY3RGb3JjZSk7XG5cblx0XHRjb25zdCBoYXNDb2xsaXNpb25FdmVudCA9IGhhc0xpc3RlbmVyKFxuXHRcdFx0dGhpcy5jb2xsaXNpb25FbnRlcixcblx0XHRcdHRoaXMuY29sbGlzaW9uRXhpdCxcblx0XHRcdHRoaXMuaW50ZXJzZWN0aW9uRW50ZXIsXG5cdFx0XHR0aGlzLmludGVyc2VjdGlvbkV4aXQsXG5cdFx0XHR0aGlzLnJpZ2lkQm9keT8uY29sbGlzaW9uRW50ZXIsXG5cdFx0XHR0aGlzLnJpZ2lkQm9keT8uY29sbGlzaW9uRXhpdCxcblx0XHRcdHRoaXMucmlnaWRCb2R5Py5pbnRlcnNlY3Rpb25FbnRlcixcblx0XHRcdHRoaXMucmlnaWRCb2R5Py5pbnRlcnNlY3Rpb25FeGl0LFxuXHRcdCk7XG5cdFx0Y29uc3QgaGFzQ29udGFjdEZvcmNlRXZlbnQgPSBoYXNMaXN0ZW5lcih0aGlzLmNvbnRhY3RGb3JjZSwgdGhpcy5yaWdpZEJvZHk/LmNvbnRhY3RGb3JjZSk7XG5cblx0XHRpZiAoaGFzQ29sbGlzaW9uRXZlbnQgJiYgaGFzQ29udGFjdEZvcmNlRXZlbnQpIHtcblx0XHRcdGNvbGxpZGVyLnNldEFjdGl2ZUV2ZW50cyhBY3RpdmVFdmVudHMuQ09MTElTSU9OX0VWRU5UUyB8IEFjdGl2ZUV2ZW50cy5DT05UQUNUX0ZPUkNFX0VWRU5UUyk7XG5cdFx0fSBlbHNlIGlmIChoYXNDb2xsaXNpb25FdmVudCkge1xuXHRcdFx0Y29sbGlkZXIuc2V0QWN0aXZlRXZlbnRzKEFjdGl2ZUV2ZW50cy5DT0xMSVNJT05fRVZFTlRTKTtcblx0XHR9IGVsc2UgaWYgKGhhc0NvbnRhY3RGb3JjZUV2ZW50KSB7XG5cdFx0XHRjb2xsaWRlci5zZXRBY3RpdmVFdmVudHMoQWN0aXZlRXZlbnRzLkNPTlRBQ1RfRk9SQ0VfRVZFTlRTKTtcblx0XHR9XG5cblx0XHR0aGlzLnBoeXNpY3MuY29sbGlkZXJFdmVudHMuc2V0KGNvbGxpZGVyLmhhbmRsZSwge1xuXHRcdFx0b25Db2xsaXNpb25FbnRlcjogY29sbGlzaW9uRW50ZXIsXG5cdFx0XHRvbkNvbGxpc2lvbkV4aXQ6IGNvbGxpc2lvbkV4aXQsXG5cdFx0XHRvbkludGVyc2VjdGlvbkVudGVyOiBpbnRlcnNlY3Rpb25FbnRlcixcblx0XHRcdG9uSW50ZXJzZWN0aW9uRXhpdDogaW50ZXJzZWN0aW9uRXhpdCxcblx0XHRcdG9uQ29udGFjdEZvcmNlOiBjb250YWN0Rm9yY2UsXG5cdFx0fSk7XG5cdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdHRoaXMucGh5c2ljcy5jb2xsaWRlckV2ZW50cy5kZWxldGUoY29sbGlkZXIuaGFuZGxlKTtcblx0XHR9O1xuXHR9XG5cblx0cHJpdmF0ZSB1cGRhdGVDb2xsaWRlckVmZmVjdCgpIHtcblx0XHRjb25zdCBjb2xsaWRlciA9IHRoaXMuY29sbGlkZXIoKTtcblx0XHRpZiAoIWNvbGxpZGVyKSByZXR1cm47XG5cblx0XHRjb25zdCB3b3JsZFNpbmdsZXRvbiA9IHRoaXMucGh5c2ljcy53b3JsZFNpbmdsZXRvbigpO1xuXHRcdGlmICghd29ybGRTaW5nbGV0b24pIHJldHVybjtcblxuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5waHlzaWNzLmNvbGxpZGVyU3RhdGVzLmdldChjb2xsaWRlci5oYW5kbGUpO1xuXHRcdGlmICghc3RhdGUpIHJldHVybjtcblxuXHRcdC8vIFVwZGF0ZSBjb2xsaWRlciBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgb2JqZWN0J3MgcG9zaXRpb25cblx0XHRjb25zdCBwYXJlbnRXb3JsZFNjYWxlID0gc3RhdGUub2JqZWN0LnBhcmVudCEuZ2V0V29ybGRTY2FsZShfdmVjdG9yMyk7XG5cdFx0Y29uc3QgcGFyZW50SW52ZXJ0ZWRXb3JsZE1hdHJpeCA9IHN0YXRlLndvcmxkUGFyZW50Py5tYXRyaXhXb3JsZC5jbG9uZSgpLmludmVydCgpO1xuXG5cdFx0c3RhdGUub2JqZWN0LnVwZGF0ZVdvcmxkTWF0cml4KHRydWUsIGZhbHNlKTtcblxuXHRcdF9tYXRyaXg0LmNvcHkoc3RhdGUub2JqZWN0Lm1hdHJpeFdvcmxkKTtcblxuXHRcdGlmIChwYXJlbnRJbnZlcnRlZFdvcmxkTWF0cml4KSB7XG5cdFx0XHRfbWF0cml4NC5wcmVtdWx0aXBseShwYXJlbnRJbnZlcnRlZFdvcmxkTWF0cml4KTtcblx0XHR9XG5cblx0XHRfbWF0cml4NC5kZWNvbXBvc2UoX3Bvc2l0aW9uLCBfcm90YXRpb24sIF9zY2FsZSk7XG5cblx0XHRpZiAoY29sbGlkZXIucGFyZW50KCkpIHtcblx0XHRcdGNvbGxpZGVyLnNldFRyYW5zbGF0aW9uV3J0UGFyZW50KHtcblx0XHRcdFx0eDogX3Bvc2l0aW9uLnggKiBwYXJlbnRXb3JsZFNjYWxlLngsXG5cdFx0XHRcdHk6IF9wb3NpdGlvbi55ICogcGFyZW50V29ybGRTY2FsZS55LFxuXHRcdFx0XHR6OiBfcG9zaXRpb24ueiAqIHBhcmVudFdvcmxkU2NhbGUueixcblx0XHRcdH0pO1xuXHRcdFx0Y29sbGlkZXIuc2V0Um90YXRpb25XcnRQYXJlbnQoX3JvdGF0aW9uKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29sbGlkZXIuc2V0VHJhbnNsYXRpb24oe1xuXHRcdFx0XHR4OiBfcG9zaXRpb24ueCAqIHBhcmVudFdvcmxkU2NhbGUueCxcblx0XHRcdFx0eTogX3Bvc2l0aW9uLnkgKiBwYXJlbnRXb3JsZFNjYWxlLnksXG5cdFx0XHRcdHo6IF9wb3NpdGlvbi56ICogcGFyZW50V29ybGRTY2FsZS56LFxuXHRcdFx0fSk7XG5cdFx0XHRjb2xsaWRlci5zZXRSb3RhdGlvbihfcm90YXRpb24pO1xuXHRcdH1cblxuXHRcdGNvbnN0IFtcblx0XHRcdHNlbnNvcixcblx0XHRcdGNvbGxpc2lvbkdyb3Vwcyxcblx0XHRcdHNvbHZlckdyb3Vwcyxcblx0XHRcdGZyaWN0aW9uLFxuXHRcdFx0ZnJpY3Rpb25Db21iaW5lUnVsZSxcblx0XHRcdHJlc3RpdHV0aW9uLFxuXHRcdFx0cmVzdGl0dXRpb25Db21iaW5lUnVsZSxcblx0XHRcdGFjdGl2ZUNvbGxpc2lvblR5cGVzLFxuXHRcdFx0Y29udGFjdFNraW4sXG5cdFx0XSA9IFtcblx0XHRcdHRoaXMuc2Vuc29yKCksXG5cdFx0XHR0aGlzLmNvbGxpc2lvbkdyb3VwcygpLFxuXHRcdFx0dGhpcy5zb2x2ZXJHcm91cHMoKSxcblx0XHRcdHRoaXMuZnJpY3Rpb24oKSxcblx0XHRcdHRoaXMuZnJpY3Rpb25Db21iaW5lUnVsZSgpLFxuXHRcdFx0dGhpcy5yZXN0aXR1dGlvbigpLFxuXHRcdFx0dGhpcy5yZXN0aXR1dGlvbkNvbWJpbmVSdWxlKCksXG5cdFx0XHR0aGlzLmFjdGl2ZUNvbGxpc2lvblR5cGVzKCksXG5cdFx0XHR0aGlzLmNvbnRhY3RTa2luKCksXG5cdFx0XTtcblxuXHRcdGlmIChzZW5zb3IgIT09IHVuZGVmaW5lZCkgY29sbGlkZXIuc2V0U2Vuc29yKHNlbnNvcik7XG5cdFx0aWYgKGNvbGxpc2lvbkdyb3VwcyAhPT0gdW5kZWZpbmVkKSBjb2xsaWRlci5zZXRDb2xsaXNpb25Hcm91cHMoY29sbGlzaW9uR3JvdXBzKTtcblx0XHRpZiAoc29sdmVyR3JvdXBzICE9PSB1bmRlZmluZWQpIGNvbGxpZGVyLnNldFNvbHZlckdyb3Vwcyhzb2x2ZXJHcm91cHMpO1xuXHRcdGlmIChmcmljdGlvbiAhPT0gdW5kZWZpbmVkKSBjb2xsaWRlci5zZXRGcmljdGlvbihmcmljdGlvbik7XG5cdFx0aWYgKGZyaWN0aW9uQ29tYmluZVJ1bGUgIT09IHVuZGVmaW5lZCkgY29sbGlkZXIuc2V0RnJpY3Rpb25Db21iaW5lUnVsZShmcmljdGlvbkNvbWJpbmVSdWxlKTtcblx0XHRpZiAocmVzdGl0dXRpb24gIT09IHVuZGVmaW5lZCkgY29sbGlkZXIuc2V0UmVzdGl0dXRpb24ocmVzdGl0dXRpb24pO1xuXHRcdGlmIChyZXN0aXR1dGlvbkNvbWJpbmVSdWxlICE9PSB1bmRlZmluZWQpIGNvbGxpZGVyLnNldFJlc3RpdHV0aW9uQ29tYmluZVJ1bGUocmVzdGl0dXRpb25Db21iaW5lUnVsZSk7XG5cdFx0aWYgKGFjdGl2ZUNvbGxpc2lvblR5cGVzICE9PSB1bmRlZmluZWQpIGNvbGxpZGVyLnNldEFjdGl2ZUNvbGxpc2lvblR5cGVzKGFjdGl2ZUNvbGxpc2lvblR5cGVzKTtcblx0XHRpZiAoY29udGFjdFNraW4gIT09IHVuZGVmaW5lZCkgY29sbGlkZXIuc2V0Q29udGFjdFNraW4oY29udGFjdFNraW4pO1xuXHR9XG5cblx0cHJpdmF0ZSB1cGRhdGVNYXNzUHJvcGVydGllc0VmZmVjdCgpIHtcblx0XHRjb25zdCBjb2xsaWRlciA9IHRoaXMuY29sbGlkZXIoKTtcblx0XHRpZiAoIWNvbGxpZGVyKSByZXR1cm47XG5cblx0XHRjb25zdCBbbWFzcywgbWFzc1Byb3BlcnRpZXMsIGRlbnNpdHldID0gW3RoaXMubWFzcygpLCB0aGlzLm1hc3NQcm9wZXJ0aWVzKCksIHRoaXMuZGVuc2l0eSgpXTtcblxuXHRcdGlmIChkZW5zaXR5ICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdGlmIChtYXNzICE9PSB1bmRlZmluZWQgfHwgbWFzc1Byb3BlcnRpZXMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1tOR1QgUmFwaWVyXSBDYW5ub3Qgc2V0IG1hc3MgYW5kIG1hc3NQcm9wZXJ0aWVzIGFsb25nIHdpdGggZGVuc2l0eScpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb2xsaWRlci5zZXREZW5zaXR5KGRlbnNpdHkpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChtYXNzICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdGlmIChtYXNzUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcignW05HVCBSYXBpZXJdIENhbm5vdCBzZXQgbWFzc1Byb3BlcnRpZXMgYWxvbmcgd2l0aCBtYXNzJyk7XG5cdFx0XHR9XG5cdFx0XHRjb2xsaWRlci5zZXRNYXNzKG1hc3MpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChtYXNzUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRjb2xsaWRlci5zZXRNYXNzUHJvcGVydGllcyhcblx0XHRcdFx0bWFzc1Byb3BlcnRpZXMubWFzcyxcblx0XHRcdFx0bWFzc1Byb3BlcnRpZXMuY2VudGVyT2ZNYXNzLFxuXHRcdFx0XHRtYXNzUHJvcGVydGllcy5wcmluY2lwYWxBbmd1bGFySW5lcnRpYSxcblx0XHRcdFx0bWFzc1Byb3BlcnRpZXMuYW5ndWxhckluZXJ0aWFMb2NhbEZyYW1lLFxuXHRcdFx0KTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGNyZWF0ZUNvbGxpZGVyU3RhdGUoXG5cdFx0Y29sbGlkZXI6IENvbGxpZGVyLFxuXHRcdG9iamVjdDogT2JqZWN0M0QsXG5cdFx0cmlnaWRCb2R5T2JqZWN0PzogT2JqZWN0M0QgfCBudWxsLFxuXHQpOiBOZ3RyQ29sbGlkZXJTdGF0ZSB7XG5cdFx0cmV0dXJuIHsgY29sbGlkZXIsIHdvcmxkUGFyZW50OiByaWdpZEJvZHlPYmplY3QgfHwgdW5kZWZpbmVkLCBvYmplY3QgfTtcblx0fVxuXG5cdHByaXZhdGUgc2NhbGVWZXJ0aWNlcyh2ZXJ0aWNlczogQXJyYXlMaWtlPG51bWJlcj4sIHNjYWxlOiBWZWN0b3IzKSB7XG5cdFx0Y29uc3Qgc2NhbGVkVmVydHMgPSBBcnJheS5mcm9tKHZlcnRpY2VzKTtcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoIC8gMzsgaSsrKSB7XG5cdFx0XHRzY2FsZWRWZXJ0c1tpICogM10gKj0gc2NhbGUueDtcblx0XHRcdHNjYWxlZFZlcnRzW2kgKiAzICsgMV0gKj0gc2NhbGUueTtcblx0XHRcdHNjYWxlZFZlcnRzW2kgKiAzICsgMl0gKj0gc2NhbGUuejtcblx0XHR9XG5cblx0XHRyZXR1cm4gc2NhbGVkVmVydHM7XG5cdH1cbn1cblxuY29uc3QgUklHSURfQk9EWV9UWVBFX01BUDogUmVjb3JkPE5ndHJSaWdpZEJvZHlUeXBlLCBudW1iZXI+ID0ge1xuXHRmaXhlZDogMSxcblx0ZHluYW1pYzogMCxcblx0a2luZW1hdGljUG9zaXRpb246IDIsXG5cdGtpbmVtYXRpY1ZlbG9jaXR5OiAzLFxufTtcblxuZXhwb3J0IGNvbnN0IHJpZ2lkQm9keURlZmF1bHRPcHRpb25zOiBOZ3RyUmlnaWRCb2R5T3B0aW9ucyA9IHtcblx0Y2FuU2xlZXA6IHRydWUsXG5cdGxpbmVhclZlbG9jaXR5OiBbMCwgMCwgMF0sXG5cdGFuZ3VsYXJWZWxvY2l0eTogWzAsIDAsIDBdLFxuXHRncmF2aXR5U2NhbGU6IDEsXG5cdGRvbWluYW5jZUdyb3VwOiAwLFxuXHRjY2Q6IGZhbHNlLFxuXHRzb2Z0Q2NkUHJlZGljdGlvbjogMCxcblx0Y29udGFjdFNraW46IDAsXG59O1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICduZ3Qtb2JqZWN0M0Rbbmd0clJpZ2lkQm9keV0nLFxuXHRleHBvcnRBczogJ3JpZ2lkQm9keScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdHRlbXBsYXRlOiBgXG5cdFx0PG5nLWNvbnRlbnQgLz5cblx0XHRAZm9yIChjaGlsZENvbGxpZGVyT3B0aW9uIG9mIGNoaWxkQ29sbGlkZXJPcHRpb25zKCk7IHRyYWNrICRpbmRleCkge1xuXHRcdFx0PG5ndC1vYmplY3QzRFxuXHRcdFx0XHRbbmd0ckNvbGxpZGVyXT1cImNoaWxkQ29sbGlkZXJPcHRpb24uc2hhcGVcIlxuXHRcdFx0XHRbYXJnc109XCJjaGlsZENvbGxpZGVyT3B0aW9uLmFyZ3NcIlxuXHRcdFx0XHRbcG9zaXRpb25dPVwiY2hpbGRDb2xsaWRlck9wdGlvbi5wb3NpdGlvblwiXG5cdFx0XHRcdFtyb3RhdGlvbl09XCJjaGlsZENvbGxpZGVyT3B0aW9uLnJvdGF0aW9uXCJcblx0XHRcdFx0W3NjYWxlXT1cImNoaWxkQ29sbGlkZXJPcHRpb24uc2NhbGVcIlxuXHRcdFx0XHRbbmFtZV09XCJvYmplY3RSZWYubmF0aXZlRWxlbWVudC5uYW1lICsgJy1jb2xsaWRlci0nICsgJGluZGV4XCJcblx0XHRcdFx0W29wdGlvbnNdPVwiY2hpbGRDb2xsaWRlck9wdGlvbi5jb2xsaWRlck9wdGlvbnNcIlxuXHRcdFx0Lz5cblx0XHR9XG5cdGAsXG5cdHNjaGVtYXM6IFtDVVNUT01fRUxFTUVOVFNfU0NIRU1BXSxcblx0Y2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG5cdGhvc3Q6IHtcblx0XHQnW3Bvc2l0aW9uXSc6ICdwb3NpdGlvbigpJyxcblx0XHQnW3JvdGF0aW9uXSc6ICdyb3RhdGlvbigpJyxcblx0XHQnW3NjYWxlXSc6ICdzY2FsZSgpJyxcblx0XHQnW3F1YXRlcm5pb25dJzogJ3F1YXRlcm5pb24oKScsXG5cdFx0J1t1c2VyRGF0YV0nOiAndXNlckRhdGEoKScsXG5cdH0sXG5cdGltcG9ydHM6IFtOZ3RyQW55Q29sbGlkZXJdLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3RyUmlnaWRCb2R5IHtcblx0dHlwZSA9IGlucHV0KCdkeW5hbWljJywge1xuXHRcdGFsaWFzOiAnbmd0clJpZ2lkQm9keScsXG5cdFx0dHJhbnNmb3JtOiAodmFsdWU6IE5ndHJSaWdpZEJvZHlUeXBlIHwgJycgfCB1bmRlZmluZWQpID0+IHtcblx0XHRcdGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuICdkeW5hbWljJyBhcyBOZ3RyUmlnaWRCb2R5VHlwZTtcblx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHR9LFxuXHR9KTtcblx0cG9zaXRpb24gPSBpbnB1dDxOZ3RWZWN0b3IzIHwgdW5kZWZpbmVkPihbMCwgMCwgMF0pO1xuXHRyb3RhdGlvbiA9IGlucHV0PE5ndEV1bGVyIHwgdW5kZWZpbmVkPihbMCwgMCwgMF0pO1xuXHRzY2FsZSA9IGlucHV0PE5ndFZlY3RvcjMgfCB1bmRlZmluZWQ+KFsxLCAxLCAxXSk7XG5cdHF1YXRlcm5pb24gPSBpbnB1dDxOZ3RRdWF0ZXJuaW9uIHwgdW5kZWZpbmVkPihbMCwgMCwgMCwgMV0pO1xuXHR1c2VyRGF0YSA9IGlucHV0PE5ndE9iamVjdDNEWyd1c2VyRGF0YSddIHwgdW5kZWZpbmVkPih7fSk7XG5cdG9wdGlvbnMgPSBpbnB1dChyaWdpZEJvZHlEZWZhdWx0T3B0aW9ucywgeyB0cmFuc2Zvcm06IG1lcmdlSW5wdXRzKHJpZ2lkQm9keURlZmF1bHRPcHRpb25zKSB9KTtcblxuXHR3YWtlID0gb3V0cHV0PHZvaWQ+KCk7XG5cdHNsZWVwID0gb3V0cHV0PHZvaWQ+KCk7XG5cdGNvbGxpc2lvbkVudGVyID0gb3V0cHV0PE5ndHJDb2xsaXNpb25FbnRlclBheWxvYWQ+KCk7XG5cdGNvbGxpc2lvbkV4aXQgPSBvdXRwdXQ8Tmd0ckNvbGxpc2lvbkV4aXRQYXlsb2FkPigpO1xuXHRpbnRlcnNlY3Rpb25FbnRlciA9IG91dHB1dDxOZ3RySW50ZXJzZWN0aW9uRW50ZXJQYXlsb2FkPigpO1xuXHRpbnRlcnNlY3Rpb25FeGl0ID0gb3V0cHV0PE5ndHJJbnRlcnNlY3Rpb25FeGl0UGF5bG9hZD4oKTtcblx0Y29udGFjdEZvcmNlID0gb3V0cHV0PE5ndHJDb250YWN0Rm9yY2VQYXlsb2FkPigpO1xuXG5cdHByaXZhdGUgY2FuU2xlZXAgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2NhblNsZWVwJyk7XG5cdHByaXZhdGUgY29sbGlkZXJzID0gcGljayh0aGlzLm9wdGlvbnMsICdjb2xsaWRlcnMnKTtcblx0cHJpdmF0ZSB0cmFuc2Zvcm1TdGF0ZSA9IHBpY2sodGhpcy5vcHRpb25zLCAndHJhbnNmb3JtU3RhdGUnKTtcblx0cHJpdmF0ZSBncmF2aXR5U2NhbGUgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2dyYXZpdHlTY2FsZScpO1xuXHRwcml2YXRlIGRvbWluYW5jZUdyb3VwID0gcGljayh0aGlzLm9wdGlvbnMsICdkb21pbmFuY2VHcm91cCcpO1xuXHRwcml2YXRlIGNjZCA9IHBpY2sodGhpcy5vcHRpb25zLCAnY2NkJyk7XG5cdHByaXZhdGUgc29mdENjZFByZWRpY3Rpb24gPSBwaWNrKHRoaXMub3B0aW9ucywgJ3NvZnRDY2RQcmVkaWN0aW9uJyk7XG5cdHByaXZhdGUgYWRkaXRpb25hbFNvbHZlckl0ZXJhdGlvbnMgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2FkZGl0aW9uYWxTb2x2ZXJJdGVyYXRpb25zJyk7XG5cdHByaXZhdGUgbGluZWFyRGFtcGluZyA9IHBpY2sodGhpcy5vcHRpb25zLCAnbGluZWFyRGFtcGluZycpO1xuXHRwcml2YXRlIGFuZ3VsYXJEYW1waW5nID0gcGljayh0aGlzLm9wdGlvbnMsICdhbmd1bGFyRGFtcGluZycpO1xuXHRwcml2YXRlIGxvY2tSb3RhdGlvbnMgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2xvY2tSb3RhdGlvbnMnKTtcblx0cHJpdmF0ZSBsb2NrVHJhbnNsYXRpb25zID0gcGljayh0aGlzLm9wdGlvbnMsICdsb2NrVHJhbnNsYXRpb25zJyk7XG5cdHByaXZhdGUgZW5hYmxlZFJvdGF0aW9ucyA9IHBpY2sodGhpcy5vcHRpb25zLCAnZW5hYmxlZFJvdGF0aW9ucycpO1xuXHRwcml2YXRlIGVuYWJsZWRUcmFuc2xhdGlvbnMgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2VuYWJsZWRUcmFuc2xhdGlvbnMnKTtcblx0cHJpdmF0ZSBhbmd1bGFyVmVsb2NpdHkgPSBwaWNrKHRoaXMub3B0aW9ucywgJ2FuZ3VsYXJWZWxvY2l0eScpO1xuXHRwcml2YXRlIGxpbmVhclZlbG9jaXR5ID0gcGljayh0aGlzLm9wdGlvbnMsICdsaW5lYXJWZWxvY2l0eScpO1xuXG5cdG9iamVjdFJlZiA9IGluamVjdDxFbGVtZW50UmVmPE9iamVjdDNEPj4oRWxlbWVudFJlZik7XG5cdHByaXZhdGUgcGh5c2ljcyA9IGluamVjdChOZ3RyUGh5c2ljcyk7XG5cblx0cHJpdmF0ZSBib2R5VHlwZSA9IGNvbXB1dGVkKCgpID0+IFJJR0lEX0JPRFlfVFlQRV9NQVBbdGhpcy50eXBlKCldKTtcblx0cHJpdmF0ZSBib2R5RGVzYyA9IGNvbXB1dGVkKCgpID0+IHtcblx0XHRjb25zdCBbY2FuU2xlZXAsIGJvZHlUeXBlXSA9IFt0aGlzLmNhblNsZWVwKCksIHVudHJhY2tlZCh0aGlzLmJvZHlUeXBlKSwgdGhpcy5jb2xsaWRlcnMoKV07XG5cdFx0cmV0dXJuIG5ldyBSaWdpZEJvZHlEZXNjKGJvZHlUeXBlKS5zZXRDYW5TbGVlcChjYW5TbGVlcCk7XG5cdH0pO1xuXHRyaWdpZEJvZHkgPSBjb21wdXRlZCgoKSA9PiB7XG5cdFx0Y29uc3Qgd29ybGRTaW5nbGV0b24gPSB0aGlzLnBoeXNpY3Mud29ybGRTaW5nbGV0b24oKTtcblx0XHRpZiAoIXdvcmxkU2luZ2xldG9uKSByZXR1cm4gbnVsbDtcblx0XHRyZXR1cm4gd29ybGRTaW5nbGV0b24ucHJveHkuY3JlYXRlUmlnaWRCb2R5KHRoaXMuYm9keURlc2MoKSk7XG5cdH0pO1xuXG5cdHByb3RlY3RlZCBjaGlsZENvbGxpZGVyT3B0aW9ucyA9IGNvbXB1dGVkKCgpID0+IHtcblx0XHRjb25zdCBjb2xsaWRlcnMgPSB0aGlzLmNvbGxpZGVycygpO1xuXHRcdC8vIGlmIHNlbGYgY29sbGlkZXJzIGlzIGZhbHNlIGV4cGxpY2l0bHksIGRpc2FibGUgYXV0byBjb2xsaWRlcnMgZm9yIHRoaXMgb2JqZWN0IGVudGlyZWx5LlxuXHRcdGlmIChjb2xsaWRlcnMgPT09IGZhbHNlKSByZXR1cm4gW107XG5cblx0XHRjb25zdCBwaHlzaWNzQ29sbGlkZXJzID0gdGhpcy5waHlzaWNzLmNvbGxpZGVycygpO1xuXHRcdC8vIGlmIHBoeXNpY3MgY29sbGlkZXJzIGlzIGZhbHNlIGV4cGxpY2l0bHksIGRpc2FibGUgYXV0byBjb2xsaWRlcnMgZm9yIHRoaXMgb2JqZWN0IGVudGlyZWx5LlxuXHRcdGlmIChwaHlzaWNzQ29sbGlkZXJzID09PSBmYWxzZSkgcmV0dXJuIFtdO1xuXG5cdFx0Y29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucygpO1xuXHRcdC8vIGlmIGNvbGxpZGVycyBvbiBvYmplY3QgaXMgbm90IHNldCwgdXNlIHBoeXNpY3MgY29sbGlkZXJzXG5cdFx0aWYgKCFvcHRpb25zLmNvbGxpZGVycykgb3B0aW9ucy5jb2xsaWRlcnMgPSBwaHlzaWNzQ29sbGlkZXJzO1xuXG5cdFx0Y29uc3Qgb2JqZWN0TG9jYWxTdGF0ZSA9IGdldExvY2FsU3RhdGUodGhpcy5vYmplY3RSZWYubmF0aXZlRWxlbWVudCk7XG5cdFx0Ly8gdHJhY2sgb2JqZWN0J3MgY2hpbGRyZW5cblx0XHRvYmplY3RMb2NhbFN0YXRlPy5ub25PYmplY3RzKCk7XG5cblx0XHRyZXR1cm4gY3JlYXRlQ29sbGlkZXJPcHRpb25zKHRoaXMub2JqZWN0UmVmLm5hdGl2ZUVsZW1lbnQsIG9wdGlvbnMsIHRydWUpO1xuXHR9KTtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRleHRlbmQoeyBPYmplY3QzRCB9KTtcblxuXHRcdGVmZmVjdCgob25DbGVhbnVwKSA9PiB7XG5cdFx0XHRjb25zdCBjbGVhbnVwID0gdGhpcy5jcmVhdGVSaWdpZEJvZHlTdGF0ZUVmZmVjdCgpO1xuXHRcdFx0b25DbGVhbnVwKCgpID0+IGNsZWFudXA/LigpKTtcblx0XHR9KTtcblxuXHRcdGVmZmVjdCgob25DbGVhbnVwKSA9PiB7XG5cdFx0XHRjb25zdCBjbGVhbnVwID0gdGhpcy5jcmVhdGVSaWdpZEJvZHlFdmVudHNFZmZlY3QoKTtcblx0XHRcdG9uQ2xlYW51cCgoKSA9PiBjbGVhbnVwPy4oKSk7XG5cdFx0fSk7XG5cblx0XHRlZmZlY3QoKCkgPT4ge1xuXHRcdFx0dGhpcy51cGRhdGVSaWdpZEJvZHlFZmZlY3QoKTtcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUmlnaWRCb2R5U3RhdGVFZmZlY3QoKSB7XG5cdFx0Y29uc3Qgd29ybGRTaW5nbGV0b24gPSB0aGlzLnBoeXNpY3Mud29ybGRTaW5nbGV0b24oKTtcblx0XHRpZiAoIXdvcmxkU2luZ2xldG9uKSByZXR1cm47XG5cblx0XHRjb25zdCBib2R5ID0gdGhpcy5yaWdpZEJvZHkoKTtcblx0XHRpZiAoIWJvZHkpIHJldHVybjtcblxuXHRcdGNvbnN0IHRyYW5zZm9ybVN0YXRlID0gdW50cmFja2VkKHRoaXMudHJhbnNmb3JtU3RhdGUpO1xuXG5cdFx0Y29uc3Qgc3RhdGUgPSB0aGlzLmNyZWF0ZVJpZ2lkQm9keVN0YXRlKGJvZHksIHRoaXMub2JqZWN0UmVmLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdHRoaXMucGh5c2ljcy5yaWdpZEJvZHlTdGF0ZXMuc2V0KGJvZHkuaGFuZGxlLCB0cmFuc2Zvcm1TdGF0ZSA/IHRyYW5zZm9ybVN0YXRlKHN0YXRlKSA6IHN0YXRlKTtcblxuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHR0aGlzLnBoeXNpY3MucmlnaWRCb2R5U3RhdGVzLmRlbGV0ZShib2R5LmhhbmRsZSk7XG5cdFx0XHRpZiAod29ybGRTaW5nbGV0b24ucHJveHkuZ2V0UmlnaWRCb2R5KGJvZHkuaGFuZGxlKSkge1xuXHRcdFx0XHR3b3JsZFNpbmdsZXRvbi5wcm94eS5yZW1vdmVSaWdpZEJvZHkoYm9keSk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUmlnaWRCb2R5RXZlbnRzRWZmZWN0KCkge1xuXHRcdGNvbnN0IHdvcmxkU2luZ2xldG9uID0gdGhpcy5waHlzaWNzLndvcmxkU2luZ2xldG9uKCk7XG5cdFx0aWYgKCF3b3JsZFNpbmdsZXRvbikgcmV0dXJuO1xuXG5cdFx0Y29uc3QgYm9keSA9IHRoaXMucmlnaWRCb2R5KCk7XG5cdFx0aWYgKCFib2R5KSByZXR1cm47XG5cblx0XHRjb25zdCB3YWtlID0gZ2V0RW1pdHRlcih0aGlzLndha2UpO1xuXHRcdGNvbnN0IHNsZWVwID0gZ2V0RW1pdHRlcih0aGlzLnNsZWVwKTtcblx0XHRjb25zdCBjb2xsaXNpb25FbnRlciA9IGdldEVtaXR0ZXIodGhpcy5jb2xsaXNpb25FbnRlcik7XG5cdFx0Y29uc3QgY29sbGlzaW9uRXhpdCA9IGdldEVtaXR0ZXIodGhpcy5jb2xsaXNpb25FeGl0KTtcblx0XHRjb25zdCBpbnRlcnNlY3Rpb25FbnRlciA9IGdldEVtaXR0ZXIodGhpcy5pbnRlcnNlY3Rpb25FbnRlcik7XG5cdFx0Y29uc3QgaW50ZXJzZWN0aW9uRXhpdCA9IGdldEVtaXR0ZXIodGhpcy5pbnRlcnNlY3Rpb25FeGl0KTtcblx0XHRjb25zdCBjb250YWN0Rm9yY2UgPSBnZXRFbWl0dGVyKHRoaXMuY29udGFjdEZvcmNlKTtcblxuXHRcdHRoaXMucGh5c2ljcy5yaWdpZEJvZHlFdmVudHMuc2V0KGJvZHkuaGFuZGxlLCB7XG5cdFx0XHRvbldha2U6IHdha2UsXG5cdFx0XHRvblNsZWVwOiBzbGVlcCxcblx0XHRcdG9uQ29sbGlzaW9uRW50ZXI6IGNvbGxpc2lvbkVudGVyLFxuXHRcdFx0b25Db2xsaXNpb25FeGl0OiBjb2xsaXNpb25FeGl0LFxuXHRcdFx0b25JbnRlcnNlY3Rpb25FbnRlcjogaW50ZXJzZWN0aW9uRW50ZXIsXG5cdFx0XHRvbkludGVyc2VjdGlvbkV4aXQ6IGludGVyc2VjdGlvbkV4aXQsXG5cdFx0XHRvbkNvbnRhY3RGb3JjZTogY29udGFjdEZvcmNlLFxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdHRoaXMucGh5c2ljcy5yaWdpZEJvZHlFdmVudHMuZGVsZXRlKGJvZHkuaGFuZGxlKTtcblx0XHR9O1xuXHR9XG5cblx0cHJpdmF0ZSB1cGRhdGVSaWdpZEJvZHlFZmZlY3QoKSB7XG5cdFx0Y29uc3Qgd29ybGRTaW5nbGV0b24gPSB0aGlzLnBoeXNpY3Mud29ybGRTaW5nbGV0b24oKTtcblx0XHRpZiAoIXdvcmxkU2luZ2xldG9uKSByZXR1cm47XG5cblx0XHRjb25zdCBib2R5ID0gdGhpcy5yaWdpZEJvZHkoKTtcblx0XHRpZiAoIWJvZHkpIHJldHVybjtcblxuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5waHlzaWNzLnJpZ2lkQm9keVN0YXRlcy5nZXQoYm9keS5oYW5kbGUpO1xuXHRcdGlmICghc3RhdGUpIHJldHVybjtcblxuXHRcdHN0YXRlLm9iamVjdC51cGRhdGVXb3JsZE1hdHJpeCh0cnVlLCBmYWxzZSk7XG5cdFx0X21hdHJpeDQuY29weShzdGF0ZS5vYmplY3QubWF0cml4V29ybGQpLmRlY29tcG9zZShfcG9zaXRpb24sIF9yb3RhdGlvbiwgX3NjYWxlKTtcblx0XHRib2R5LnNldFRyYW5zbGF0aW9uKF9wb3NpdGlvbiwgdHJ1ZSk7XG5cdFx0Ym9keS5zZXRSb3RhdGlvbihfcm90YXRpb24sIHRydWUpO1xuXG5cdFx0Y29uc3QgW1xuXHRcdFx0Z3Jhdml0eVNjYWxlLFxuXHRcdFx0YWRkaXRpb25hbFNvbHZlckl0ZXJhdGlvbnMsXG5cdFx0XHRsaW5lYXJEYW1waW5nLFxuXHRcdFx0YW5ndWxhckRhbXBpbmcsXG5cdFx0XHRsb2NrUm90YXRpb25zLFxuXHRcdFx0bG9ja1RyYW5zbGF0aW9ucyxcblx0XHRcdGVuYWJsZWRSb3RhdGlvbnMsXG5cdFx0XHRlbmFibGVkVHJhbnNsYXRpb25zLFxuXHRcdFx0YW5ndWxhclZlbG9jaXR5LFxuXHRcdFx0bGluZWFyVmVsb2NpdHksXG5cdFx0XHRjY2QsXG5cdFx0XHRzb2Z0Q2NkUHJlZGljdGlvbixcblx0XHRcdGRvbWluYW5jZUdyb3VwLFxuXHRcdFx0dXNlckRhdGEsXG5cdFx0XHRib2R5VHlwZSxcblx0XHRdID0gW1xuXHRcdFx0dGhpcy5ncmF2aXR5U2NhbGUoKSxcblx0XHRcdHRoaXMuYWRkaXRpb25hbFNvbHZlckl0ZXJhdGlvbnMoKSxcblx0XHRcdHRoaXMubGluZWFyRGFtcGluZygpLFxuXHRcdFx0dGhpcy5hbmd1bGFyRGFtcGluZygpLFxuXHRcdFx0dGhpcy5sb2NrUm90YXRpb25zKCksXG5cdFx0XHR0aGlzLmxvY2tUcmFuc2xhdGlvbnMoKSxcblx0XHRcdHRoaXMuZW5hYmxlZFJvdGF0aW9ucygpLFxuXHRcdFx0dGhpcy5lbmFibGVkVHJhbnNsYXRpb25zKCksXG5cdFx0XHR0aGlzLmFuZ3VsYXJWZWxvY2l0eSgpLFxuXHRcdFx0dGhpcy5saW5lYXJWZWxvY2l0eSgpLFxuXHRcdFx0dGhpcy5jY2QoKSxcblx0XHRcdHRoaXMuc29mdENjZFByZWRpY3Rpb24oKSxcblx0XHRcdHRoaXMuZG9taW5hbmNlR3JvdXAoKSxcblx0XHRcdHRoaXMudXNlckRhdGEoKSxcblx0XHRcdHRoaXMuYm9keVR5cGUoKSxcblx0XHRdO1xuXG5cdFx0Ym9keS5zZXRHcmF2aXR5U2NhbGUoZ3Jhdml0eVNjYWxlLCB0cnVlKTtcblx0XHRpZiAoYWRkaXRpb25hbFNvbHZlckl0ZXJhdGlvbnMgIT09IHVuZGVmaW5lZCkgYm9keS5zZXRBZGRpdGlvbmFsU29sdmVySXRlcmF0aW9ucyhhZGRpdGlvbmFsU29sdmVySXRlcmF0aW9ucyk7XG5cdFx0aWYgKGxpbmVhckRhbXBpbmcgIT09IHVuZGVmaW5lZCkgYm9keS5zZXRMaW5lYXJEYW1waW5nKGxpbmVhckRhbXBpbmcpO1xuXHRcdGlmIChhbmd1bGFyRGFtcGluZyAhPT0gdW5kZWZpbmVkKSBib2R5LnNldEFuZ3VsYXJEYW1waW5nKGFuZ3VsYXJEYW1waW5nKTtcblx0XHRib2R5LnNldERvbWluYW5jZUdyb3VwKGRvbWluYW5jZUdyb3VwKTtcblx0XHRpZiAoZW5hYmxlZFJvdGF0aW9ucyAhPT0gdW5kZWZpbmVkKSBib2R5LnNldEVuYWJsZWRSb3RhdGlvbnMoLi4uZW5hYmxlZFJvdGF0aW9ucywgdHJ1ZSk7XG5cdFx0aWYgKGVuYWJsZWRUcmFuc2xhdGlvbnMgIT09IHVuZGVmaW5lZCkgYm9keS5zZXRFbmFibGVkVHJhbnNsYXRpb25zKC4uLmVuYWJsZWRUcmFuc2xhdGlvbnMsIHRydWUpO1xuXHRcdGlmIChsb2NrUm90YXRpb25zICE9PSB1bmRlZmluZWQpIGJvZHkubG9ja1JvdGF0aW9ucyhsb2NrUm90YXRpb25zLCB0cnVlKTtcblx0XHRpZiAobG9ja1RyYW5zbGF0aW9ucyAhPT0gdW5kZWZpbmVkKSBib2R5LmxvY2tUcmFuc2xhdGlvbnMobG9ja1RyYW5zbGF0aW9ucywgdHJ1ZSk7XG5cdFx0Ym9keS5zZXRBbmd2ZWwoeyB4OiBhbmd1bGFyVmVsb2NpdHlbMF0sIHk6IGFuZ3VsYXJWZWxvY2l0eVsxXSwgejogYW5ndWxhclZlbG9jaXR5WzJdIH0sIHRydWUpO1xuXHRcdGJvZHkuc2V0TGludmVsKHsgeDogbGluZWFyVmVsb2NpdHlbMF0sIHk6IGxpbmVhclZlbG9jaXR5WzFdLCB6OiBsaW5lYXJWZWxvY2l0eVsyXSB9LCB0cnVlKTtcblx0XHRib2R5LmVuYWJsZUNjZChjY2QpO1xuXHRcdGJvZHkuc2V0U29mdENjZFByZWRpY3Rpb24oc29mdENjZFByZWRpY3Rpb24pO1xuXHRcdGlmICh1c2VyRGF0YSAhPT0gdW5kZWZpbmVkKSBib2R5LnVzZXJEYXRhID0gdXNlckRhdGE7XG5cdFx0aWYgKGJvZHlUeXBlICE9PSBib2R5LmJvZHlUeXBlKCkpIGJvZHkuc2V0Qm9keVR5cGUoYm9keVR5cGUsIHRydWUpO1xuXHR9XG5cblx0cHJpdmF0ZSBjcmVhdGVSaWdpZEJvZHlTdGF0ZShcblx0XHRyaWdpZEJvZHk6IFJpZ2lkQm9keSxcblx0XHRvYmplY3Q6IE9iamVjdDNELFxuXHRcdHNldE1hdHJpeD86IChtYXRyaXg6IE1hdHJpeDQpID0+IHZvaWQsXG5cdFx0Z2V0TWF0cml4PzogKG1hdHJpeDogTWF0cml4NCkgPT4gTWF0cml4NCxcblx0XHR3b3JsZFNjYWxlPzogVmVjdG9yMyxcblx0XHRtZXNoVHlwZTogTmd0clJpZ2lkQm9keVN0YXRlWydtZXNoVHlwZSddID0gJ21lc2gnLFxuXHQpIHtcblx0XHRvYmplY3QudXBkYXRlV29ybGRNYXRyaXgodHJ1ZSwgZmFsc2UpO1xuXHRcdGNvbnN0IGludmVydGVkV29ybGRNYXRyaXggPSBvYmplY3QucGFyZW50IS5tYXRyaXhXb3JsZC5jbG9uZSgpLmludmVydCgpO1xuXHRcdHJldHVybiB7XG5cdFx0XHRvYmplY3QsXG5cdFx0XHRyaWdpZEJvZHksXG5cdFx0XHRpbnZlcnRlZFdvcmxkTWF0cml4LFxuXHRcdFx0c2V0TWF0cml4OiBzZXRNYXRyaXhcblx0XHRcdFx0PyBzZXRNYXRyaXhcblx0XHRcdFx0OiAobWF0cml4OiBNYXRyaXg0KSA9PiB7XG5cdFx0XHRcdFx0XHRvYmplY3QubWF0cml4LmNvcHkobWF0cml4KTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0Z2V0TWF0cml4OiBnZXRNYXRyaXggPyBnZXRNYXRyaXggOiAobWF0cml4OiBNYXRyaXg0KSA9PiBtYXRyaXguY29weShvYmplY3QubWF0cml4KSxcblx0XHRcdHNjYWxlOiB3b3JsZFNjYWxlIHx8IG9iamVjdC5nZXRXb3JsZFNjYWxlKF9zY2FsZSkuY2xvbmUoKSxcblx0XHRcdGlzU2xlZXBpbmc6IGZhbHNlLFxuXHRcdFx0bWVzaFR5cGUsXG5cdFx0fTtcblx0fVxufVxuIl19
|