ngx-acuw
Version:
Angular components using WEBGL (threejs)
196 lines • 36.1 kB
JavaScript
import { Subject } from 'rxjs';
import { Euler, Quaternion } from 'three';
import { Object3D, Vector2 } from 'three';
import { RxjsTween } from '../tween/rxjs-tween';
export class ObjectControls {
constructor(rendererDom, object, touchArea) {
// ============= Private Properties =============
this.isUserInteracting = false;
this.restoringAnimationOngoing = false;
this.restoringOriginPosTimeout = 0;
this.userInteracted = false;
this.userInteractedSubject = new Subject();
// ============= Public Properties =============
this.rotationSpeed = 1;
this.verticalRotation = true;
this.horizontalRotation = true;
this.autoRotationY = false;
this.autoRotationX = false;
this.autoRotationZ = false;
this.restoreOriginPosition = false;
this.autoRotationSpeed = 0.002;
this.userInteracted$ = this.userInteractedSubject.asObservable();
this.controlsEnabled = true;
/****************** MOUSE interaction functions - desktop *****/
/**
* Prepares everything, when the mouse is clicked
* @param e mouse event
*/
this.mouseDown = (e) => {
// Ignore mouse down interaction, if the controls are not enabled
// Ignore mouse down interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing === true)
return;
// Reset restoration animation timout
window.clearTimeout(this.restoringOriginPosTimeout);
this.isUserInteracting = true;
this.startDraggingPosition = new Vector2(0, 0);
this.startDraggingPosition.set(e.offsetX, e.offsetY);
this.touchArea.addEventListener('pointermove', this.mouseMove, false);
this.touchArea.addEventListener('pointerup', this.mouseUp, false);
};
/**
* Calculates the x and y rotation of the object depending on the mouse movement
* @param e MouseEvent
*/
this.mouseMove = (e) => {
// Ignore mouse movement interaction, if the controls are not enabled
// Ignore mouse movement interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing)
return;
if (this.isUserInteracting) {
if (this.userInteracted == false) {
this.userInteracted = true;
this.userInteractedSubject.next(this.userInteracted);
}
const deltaMove = new Vector2(e.offsetX - this.startDraggingPosition.x, e.offsetY - this.startDraggingPosition.y);
this.startDraggingPosition.set(e.offsetX, e.offsetY);
const rotationX = this.verticalRotation == true ? (deltaMove.x * Math.PI / 180 * this.rotationSpeed) : 0;
const rotationY = this.horizontalRotation == true ? (deltaMove.y * Math.PI / 180 * this.rotationSpeed) : 0;
var deltaRotationQuaternion = new Quaternion().setFromEuler(new Euler(rotationY, rotationX, 0, 'XYZ'));
this.obj.quaternion.multiplyQuaternions(deltaRotationQuaternion, this.obj.quaternion);
//console.log(`rotX: ${Math.round(THREE.MathUtils.radToDeg(this.obj.rotation.x))}, rotY: ${Math.round(THREE.MathUtils.radToDeg(this.obj.rotation.y))}, rotZ: ${Math.round(THREE.MathUtils.radToDeg(this.obj.rotation.z))}`);
}
};
this.mouseUp = () => {
// Ignore mouse movement interaction, if the controls are not enabled
// Ignore mouse up interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing)
return;
this.resetMousePosition();
this.isUserInteracting = false;
if (this.restoreOriginPosition)
this.restoreOriginalPosition();
this.touchArea.removeEventListener('mousemove', this.mouseMove, false);
this.touchArea.removeEventListener('mouseup', this.mouseUp, false);
};
/****************** TOUCH interaction functions - mobile *****/
this.onTouchStart = (e) => {
// Ignore mouse movement interaction, if the controls are not enabled
// Ignore touch start interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing)
return;
// Reset restoration animation timout
window.clearTimeout(this.restoringOriginPosTimeout);
//e.preventDefault();
this.isUserInteracting = true;
this.restoringAnimationOngoing = false;
this.startDraggingPosition.set(e.touches[0].pageX, e.touches[0].pageY);
};
this.onTouchMove = (e) => {
// Ignore mouse movement interaction, if the controls are not enabled
// Ignore mouse move interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing)
return;
//e.preventDefault();
if (this.isUserInteracting && !this.restoringAnimationOngoing) {
if (this.userInteracted == false) {
this.userInteracted = true;
this.userInteractedSubject.next(this.userInteracted);
}
const deltaMove = new Vector2(e.touches[0].pageX - this.startDraggingPosition.x, e.touches[0].pageY - this.startDraggingPosition.y);
this.startDraggingPosition.set(e.touches[0].pageX, e.touches[0].pageY);
const rotationX = this.verticalRotation == true ? (deltaMove.x * Math.PI / 180 * this.rotationSpeed) : 0;
const rotationY = this.horizontalRotation == true ? (deltaMove.y * Math.PI / 180 * this.rotationSpeed) : 0;
var deltaRotationQuaternion = new Quaternion().setFromEuler(new Euler(rotationY, rotationX, 0, 'XYZ'));
this.obj.quaternion.multiplyQuaternions(deltaRotationQuaternion, this.obj.quaternion);
}
};
this.onTouchEnd = (e) => {
// Ignore mouse movement interaction, if the controls are not enabled
// Ignore mouse up interaction, if the restoration animation is ongoing
if (this.controlsEnabled === false || this.restoringAnimationOngoing)
return;
//e.preventDefault();
this.isUserInteracting = false;
this.resetMousePosition();
if (this.restoreOriginPosition)
this.restoreOriginalPosition();
};
this.rendererDom = rendererDom;
this.obj = object;
this.touchArea = touchArea != null ? touchArea : this.rendererDom;
this.startDraggingPosition = new Vector2(0, 0);
this.addEventlisteners();
}
// ============= Public Methods =============
/**
* Method, which needs to be called, in case autorotation is used
*/
update() {
if (this.isUserInteracting || this.restoringAnimationOngoing || this.userInteracted)
return;
var rotationY = this.autoRotationY == true ? this.autoRotationSpeed : 0;
var rotationX = this.autoRotationX == true ? this.autoRotationSpeed : 0;
var rorationZ = this.autoRotationZ == true ? this.autoRotationSpeed : 0;
var deltaRotationQuaternion = new Quaternion().setFromEuler(new Euler(rotationX, rotationY, rorationZ, 'XYZ'));
this.obj.quaternion.multiplyQuaternions(deltaRotationQuaternion, this.obj.quaternion);
}
/**
* Removes the event listners
*/
removeEventlisteners() {
// desktop events
this.touchArea.removeEventListener('mousedown', this.mouseDown, false);
this.touchArea.removeEventListener('mousemove', this.mouseMove, false);
this.touchArea.removeEventListener('mouseup', this.mouseUp, false);
// mobile events
this.touchArea.removeEventListener('touchstart', this.onTouchStart, false);
this.touchArea.removeEventListener('touchmove', this.onTouchMove, false);
this.touchArea.removeEventListener('touchend', this.onTouchEnd, false);
}
resetUserInteractionFlag() {
this.userInteracted = false,
this.userInteractedSubject.next(this.userInteracted);
}
// ============= Private Methods =============
/**
* Adds the event listeners
*/
addEventlisteners() {
// desktop events
this.touchArea.addEventListener('mousedown', this.mouseDown, false);
// mobile events
this.touchArea.addEventListener('touchend', this.onTouchEnd, false);
this.touchArea.addEventListener('touchstart', this.onTouchStart, false);
this.touchArea.addEventListener('touchmove', this.onTouchMove, false);
}
/**
* Reset the mouse position to x=0 and y=0
*/
resetMousePosition() {
this.startDraggingPosition.set(0, 0);
}
/**
* Rotates the object to the position 0,0,0 after a some timeout
*/
restoreOriginalPosition() {
this.restoringOriginPosTimeout = window.setTimeout(() => {
var objSet = new Object3D();
objSet.position.set(0, 0, 0);
objSet.rotation.set(0, 0, 0);
RxjsTween.createTween(RxjsTween.linear, [this.obj.position.x, this.obj.position.y, this.obj.position.z], [objSet.position.x, objSet.position.y, objSet.position.z], 1000).subscribe({
next: tweenVal => {
if (this.restoringAnimationOngoing == false)
this.restoringAnimationOngoing = true;
this.obj.rotation.set(tweenVal[0], tweenVal[1], tweenVal[2]);
},
complete: () => {
this.restoringAnimationOngoing = false;
this.resetUserInteractionFlag();
}
});
}, 5000);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0LWNvbnRyb2xzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWFjdXcvc3JjL2xpYi9jb250cm9scy9vYmplY3QtY29udHJvbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUMxQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUMxQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFaEQsTUFBTSxPQUFPLGNBQWM7SUF5QnZCLFlBQVksV0FBd0IsRUFBRSxNQUFnQyxFQUFFLFNBQXVCO1FBdkIvRixpREFBaUQ7UUFDekMsc0JBQWlCLEdBQVksS0FBSyxDQUFDO1FBQ25DLDhCQUF5QixHQUFZLEtBQUssQ0FBQztRQUMzQyw4QkFBeUIsR0FBRyxDQUFDLENBQUM7UUFLOUIsbUJBQWMsR0FBWSxLQUFLLENBQUM7UUFDaEMsMEJBQXFCLEdBQXFCLElBQUksT0FBTyxFQUFFLENBQUM7UUFFaEUsZ0RBQWdEO1FBQ2hELGtCQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLHFCQUFnQixHQUFHLElBQUksQ0FBQztRQUN4Qix1QkFBa0IsR0FBRyxJQUFJLENBQUM7UUFDMUIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsMEJBQXFCLEdBQUcsS0FBSyxDQUFDO1FBQzlCLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUMxQixvQkFBZSxHQUF3QixJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDakYsb0JBQWUsR0FBRyxJQUFJLENBQUM7UUF5RXZCLGtFQUFr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LEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDYixDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEV1bGVyLCBRdWF0ZXJuaW9uIH0gZnJvbSAndGhyZWUnO1xyXG5pbXBvcnQgeyBPYmplY3QzRCwgVmVjdG9yMiB9IGZyb20gJ3RocmVlJztcclxuaW1wb3J0IHsgUnhqc1R3ZWVuIH0gZnJvbSAnLi4vdHdlZW4vcnhqcy10d2Vlbic7XHJcblxyXG5leHBvcnQgY2xhc3MgT2JqZWN0Q29udHJvbHMge1xyXG5cclxuICAgIC8vID09PT09PT09PT09PT0gUHJpdmF0ZSBQcm9wZXJ0aWVzID09PT09PT09PT09PT1cclxuICAgIHByaXZhdGUgaXNVc2VySW50ZXJhY3Rpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHByaXZhdGUgcmVzdG9yaW5nQW5pbWF0aW9uT25nb2luZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSByZXN0b3JpbmdPcmlnaW5Qb3NUaW1lb3V0ID0gMDtcclxuICAgIHByaXZhdGUgc3RhcnREcmFnZ2luZ1Bvc2l0aW9uOiBWZWN0b3IyO1xyXG4gICAgcHJpdmF0ZSByZW5kZXJlckRvbTogSFRNTEVsZW1lbnQ7XHJcbiAgICBwcml2YXRlIHRvdWNoQXJlYTogSFRNTEVsZW1lbnQ7XHJcbiAgICBwcml2YXRlIG9iajogVEhSRUUuTWVzaCB8IFRIUkVFLkdyb3VwO1xyXG4gICAgcHJpdmF0ZSB1c2VySW50ZXJhY3RlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSB1c2VySW50ZXJhY3RlZFN1YmplY3Q6IFN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAgIC8vID09PT09PT09PT09PT0gUHVibGljIFByb3BlcnRpZXMgPT09PT09PT09PT09PVxyXG4gICAgcm90YXRpb25TcGVlZCA9IDE7XHJcbiAgICB2ZXJ0aWNhbFJvdGF0aW9uID0gdHJ1ZTtcclxuICAgIGhvcml6b250YWxSb3RhdGlvbiA9IHRydWU7XHJcbiAgICBhdXRvUm90YXRpb25ZID0gZmFsc2U7XHJcbiAgICBhdXRvUm90YXRpb25YID0gZmFsc2U7XHJcbiAgICBhdXRvUm90YXRpb25aID0gZmFsc2U7XHJcbiAgICByZXN0b3JlT3JpZ2luUG9zaXRpb24gPSBmYWxzZTtcclxuICAgIGF1dG9Sb3RhdGlvblNwZWVkID0gMC4wMDI7XHJcbiAgICB1c2VySW50ZXJhY3RlZCQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLnVzZXJJbnRlcmFjdGVkU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuICAgIGNvbnRyb2xzRW5hYmxlZCA9IHRydWU7XHJcblxyXG4gICAgY29uc3RydWN0b3IocmVuZGVyZXJEb206IEhUTUxFbGVtZW50LCBvYmplY3Q6IFRIUkVFLk1lc2ggfCBUSFJFRS5Hcm91cCwgdG91Y2hBcmVhPzogSFRNTEVsZW1lbnQpIHtcclxuICAgICAgICB0aGlzLnJlbmRlcmVyRG9tID0gcmVuZGVyZXJEb207XHJcbiAgICAgICAgdGhpcy5vYmogPSBvYmplY3Q7XHJcbiAgICAgICAgdGhpcy50b3VjaEFyZWEgPSB0b3VjaEFyZWEgIT0gbnVsbCA/IHRvdWNoQXJlYSA6IHRoaXMucmVuZGVyZXJEb207XHJcblxyXG4gICAgICAgIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uID0gbmV3IFZlY3RvcjIoMCwgMCk7XHJcblxyXG4gICAgICAgIHRoaXMuYWRkRXZlbnRsaXN0ZW5lcnMoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA9PT09PT09PT09PT09IFB1YmxpYyBNZXRob2RzID09PT09PT09PT09PT1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldGhvZCwgd2hpY2ggbmVlZHMgdG8gYmUgY2FsbGVkLCBpbiBjYXNlIGF1dG9yb3RhdGlvbiBpcyB1c2VkXHJcbiAgICAgKi9cclxuICAgIHVwZGF0ZSgpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5pc1VzZXJJbnRlcmFjdGluZyB8fCB0aGlzLnJlc3RvcmluZ0FuaW1hdGlvbk9uZ29pbmcgfHwgdGhpcy51c2VySW50ZXJhY3RlZCkgcmV0dXJuO1xyXG5cclxuICAgICAgICB2YXIgcm90YXRpb25ZID0gdGhpcy5hdXRvUm90YXRpb25ZID09IHRydWUgPyB0aGlzLmF1dG9Sb3RhdGlvblNwZWVkIDogMDtcclxuICAgICAgICB2YXIgcm90YXRpb25YID0gdGhpcy5hdXRvUm90YXRpb25YID09IHRydWUgPyB0aGlzLmF1dG9Sb3RhdGlvblNwZWVkIDogMDtcclxuICAgICAgICB2YXIgcm9yYXRpb25aID0gdGhpcy5hdXRvUm90YXRpb25aID09IHRydWUgPyB0aGlzLmF1dG9Sb3RhdGlvblNwZWVkIDogMDtcclxuXHJcbiAgICAgICAgdmFyIGRlbHRhUm90YXRpb25RdWF0ZXJuaW9uID0gbmV3IFF1YXRlcm5pb24oKS5zZXRGcm9tRXVsZXIobmV3IEV1bGVyKFxyXG4gICAgICAgICAgICByb3RhdGlvblgsXHJcbiAgICAgICAgICAgIHJvdGF0aW9uWSxcclxuICAgICAgICAgICAgcm9yYXRpb25aLFxyXG4gICAgICAgICAgICAnWFlaJ1xyXG4gICAgICAgICkpO1xyXG4gICAgICAgIHRoaXMub2JqLnF1YXRlcm5pb24ubXVsdGlwbHlRdWF0ZXJuaW9ucyhkZWx0YVJvdGF0aW9uUXVhdGVybmlvbiwgdGhpcy5vYmoucXVhdGVybmlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZW1vdmVzIHRoZSBldmVudCBsaXN0bmVyc1xyXG4gICAgICovXHJcbiAgICByZW1vdmVFdmVudGxpc3RlbmVycygpOiB2b2lkIHtcclxuICAgICAgICAvLyBkZXNrdG9wIGV2ZW50c1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMubW91c2VEb3duLCBmYWxzZSk7XHJcbiAgICAgICAgdGhpcy50b3VjaEFyZWEucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5tb3VzZU1vdmUsIGZhbHNlKTtcclxuICAgICAgICB0aGlzLnRvdWNoQXJlYS5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5tb3VzZVVwLCBmYWxzZSk7XHJcbiAgICAgICAgLy8gbW9iaWxlIGV2ZW50c1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLm9uVG91Y2hTdGFydCwgZmFsc2UpO1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMub25Ub3VjaE1vdmUsIGZhbHNlKTtcclxuICAgICAgICB0aGlzLnRvdWNoQXJlYS5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMub25Ub3VjaEVuZCwgZmFsc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIHJlc2V0VXNlckludGVyYWN0aW9uRmxhZygpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnVzZXJJbnRlcmFjdGVkID0gZmFsc2UsXHJcbiAgICAgICAgICAgIHRoaXMudXNlckludGVyYWN0ZWRTdWJqZWN0Lm5leHQodGhpcy51c2VySW50ZXJhY3RlZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gPT09PT09PT09PT09PSBQcml2YXRlIE1ldGhvZHMgPT09PT09PT09PT09PVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkcyB0aGUgZXZlbnQgbGlzdGVuZXJzXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYWRkRXZlbnRsaXN0ZW5lcnMoKTogdm9pZCB7XHJcbiAgICAgICAgLy8gZGVza3RvcCBldmVudHNcclxuICAgICAgICB0aGlzLnRvdWNoQXJlYS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLm1vdXNlRG93biwgZmFsc2UpO1xyXG4gICAgICAgIC8vIG1vYmlsZSBldmVudHNcclxuICAgICAgICB0aGlzLnRvdWNoQXJlYS5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMub25Ub3VjaEVuZCwgZmFsc2UpO1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLm9uVG91Y2hTdGFydCwgZmFsc2UpO1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMub25Ub3VjaE1vdmUsIGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlc2V0IHRoZSBtb3VzZSBwb3NpdGlvbiB0byB4PTAgYW5kIHk9MFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlc2V0TW91c2VQb3NpdGlvbigpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnN0YXJ0RHJhZ2dpbmdQb3NpdGlvbi5zZXQoMCwgMCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKiAgTU9VU0UgaW50ZXJhY3Rpb24gZnVuY3Rpb25zIC0gZGVza3RvcCAgKioqKiovXHJcbiAgICAvKipcclxuICAgICAqIFByZXBhcmVzIGV2ZXJ5dGhpbmcsIHdoZW4gdGhlIG1vdXNlIGlzIGNsaWNrZWRcclxuICAgICAqIEBwYXJhbSBlIG1vdXNlIGV2ZW50XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbW91c2VEb3duID0gKGU6IE1vdXNlRXZlbnQpID0+IHtcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgZG93biBpbnRlcmFjdGlvbiwgaWYgdGhlIGNvbnRyb2xzIGFyZSBub3QgZW5hYmxlZFxyXG4gICAgICAgIC8vIElnbm9yZSBtb3VzZSBkb3duIGludGVyYWN0aW9uLCBpZiB0aGUgcmVzdG9yYXRpb24gYW5pbWF0aW9uIGlzIG9uZ29pbmdcclxuICAgICAgICBpZiAodGhpcy5jb250cm9sc0VuYWJsZWQgPT09IGZhbHNlIHx8IHRoaXMucmVzdG9yaW5nQW5pbWF0aW9uT25nb2luZyA9PT0gdHJ1ZSkgcmV0dXJuO1xyXG4gICAgICAgIC8vIFJlc2V0IHJlc3RvcmF0aW9uIGFuaW1hdGlvbiB0aW1vdXRcclxuICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMucmVzdG9yaW5nT3JpZ2luUG9zVGltZW91dCk7XHJcblxyXG4gICAgICAgIHRoaXMuaXNVc2VySW50ZXJhY3RpbmcgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uID0gbmV3IFZlY3RvcjIoMCwgMCk7XHJcbiAgICAgICAgdGhpcy5zdGFydERyYWdnaW5nUG9zaXRpb24uc2V0KGUub2Zmc2V0WCwgZS5vZmZzZXRZKTtcclxuXHJcbiAgICAgICAgdGhpcy50b3VjaEFyZWEuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCB0aGlzLm1vdXNlTW92ZSwgZmFsc2UpO1xyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIHRoaXMubW91c2VVcCwgZmFsc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgeCBhbmQgeSByb3RhdGlvbiBvZiB0aGUgb2JqZWN0IGRlcGVuZGluZyBvbiB0aGUgbW91c2UgbW92ZW1lbnRcclxuICAgICAqIEBwYXJhbSBlIE1vdXNlRXZlbnRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBtb3VzZU1vdmUgPSAoZTogTW91c2VFdmVudCkgPT4ge1xyXG4gICAgICAgIC8vIElnbm9yZSBtb3VzZSBtb3ZlbWVudCBpbnRlcmFjdGlvbiwgaWYgdGhlIGNvbnRyb2xzIGFyZSBub3QgZW5hYmxlZFxyXG4gICAgICAgIC8vIElnbm9yZSBtb3VzZSBtb3ZlbWVudCBpbnRlcmFjdGlvbiwgaWYgdGhlIHJlc3RvcmF0aW9uIGFuaW1hdGlvbiBpcyBvbmdvaW5nXHJcbiAgICAgICAgaWYgKHRoaXMuY29udHJvbHNFbmFibGVkID09PSBmYWxzZSB8fCB0aGlzLnJlc3RvcmluZ0FuaW1hdGlvbk9uZ29pbmcpIHJldHVybjtcclxuICAgICAgICBpZiAodGhpcy5pc1VzZXJJbnRlcmFjdGluZykge1xyXG4gICAgICAgICAgICBpZiAodGhpcy51c2VySW50ZXJhY3RlZCA9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy51c2VySW50ZXJhY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnVzZXJJbnRlcmFjdGVkU3ViamVjdC5uZXh0KHRoaXMudXNlckludGVyYWN0ZWQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBkZWx0YU1vdmUgPSBuZXcgVmVjdG9yMihcclxuICAgICAgICAgICAgICAgIGUub2Zmc2V0WCAtIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uLngsXHJcbiAgICAgICAgICAgICAgICBlLm9mZnNldFkgLSB0aGlzLnN0YXJ0RHJhZ2dpbmdQb3NpdGlvbi55XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uLnNldChlLm9mZnNldFgsIGUub2Zmc2V0WSk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCByb3RhdGlvblggPSB0aGlzLnZlcnRpY2FsUm90YXRpb24gPT0gdHJ1ZSA/IChkZWx0YU1vdmUueCAqIE1hdGguUEkgLyAxODAgKiB0aGlzLnJvdGF0aW9uU3BlZWQpIDogMDtcclxuICAgICAgICAgICAgY29uc3Qgcm90YXRpb25ZID0gdGhpcy5ob3Jpem9udGFsUm90YXRpb24gPT0gdHJ1ZSA/IChkZWx0YU1vdmUueSAqIE1hdGguUEkgLyAxODAgKiB0aGlzLnJvdGF0aW9uU3BlZWQpIDogMDtcclxuXHJcbiAgICAgICAgICAgIHZhciBkZWx0YVJvdGF0aW9uUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCkuc2V0RnJvbUV1bGVyKG5ldyBFdWxlcihcclxuICAgICAgICAgICAgICAgIHJvdGF0aW9uWSxcclxuICAgICAgICAgICAgICAgIHJvdGF0aW9uWCxcclxuICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgICAgICAgICAnWFlaJ1xyXG4gICAgICAgICAgICApKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMub2JqLnF1YXRlcm5pb24ubXVsdGlwbHlRdWF0ZXJuaW9ucyhkZWx0YVJvdGF0aW9uUXVhdGVybmlvbiwgdGhpcy5vYmoucXVhdGVybmlvbik7XHJcblxyXG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKGByb3RYOiAke01hdGgucm91bmQoVEhSRUUuTWF0aFV0aWxzLnJhZFRvRGVnKHRoaXMub2JqLnJvdGF0aW9uLngpKX0sIHJvdFk6ICR7TWF0aC5yb3VuZChUSFJFRS5NYXRoVXRpbHMucmFkVG9EZWcodGhpcy5vYmoucm90YXRpb24ueSkpfSwgcm90WjogJHtNYXRoLnJvdW5kKFRIUkVFLk1hdGhVdGlscy5yYWRUb0RlZyh0aGlzLm9iai5yb3RhdGlvbi56KSl9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgbW91c2VVcCA9ICgpID0+IHtcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgbW92ZW1lbnQgaW50ZXJhY3Rpb24sIGlmIHRoZSBjb250cm9scyBhcmUgbm90IGVuYWJsZWRcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgdXAgaW50ZXJhY3Rpb24sIGlmIHRoZSByZXN0b3JhdGlvbiBhbmltYXRpb24gaXMgb25nb2luZ1xyXG4gICAgICAgIGlmICh0aGlzLmNvbnRyb2xzRW5hYmxlZCA9PT0gZmFsc2UgfHwgdGhpcy5yZXN0b3JpbmdBbmltYXRpb25PbmdvaW5nKSByZXR1cm47XHJcbiAgICAgICAgdGhpcy5yZXNldE1vdXNlUG9zaXRpb24oKTtcclxuICAgICAgICB0aGlzLmlzVXNlckludGVyYWN0aW5nID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKHRoaXMucmVzdG9yZU9yaWdpblBvc2l0aW9uKSB0aGlzLnJlc3RvcmVPcmlnaW5hbFBvc2l0aW9uKCk7XHJcblxyXG4gICAgICAgIHRoaXMudG91Y2hBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMubW91c2VNb3ZlLCBmYWxzZSk7XHJcbiAgICAgICAgdGhpcy50b3VjaEFyZWEucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMubW91c2VVcCwgZmFsc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKiogVE9VQ0ggaW50ZXJhY3Rpb24gZnVuY3Rpb25zIC0gbW9iaWxlICAqKioqKi9cclxuICAgIHByaXZhdGUgb25Ub3VjaFN0YXJ0ID0gKGU6IFRvdWNoRXZlbnQpID0+IHtcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgbW92ZW1lbnQgaW50ZXJhY3Rpb24sIGlmIHRoZSBjb250cm9scyBhcmUgbm90IGVuYWJsZWRcclxuICAgICAgICAvLyBJZ25vcmUgdG91Y2ggc3RhcnQgaW50ZXJhY3Rpb24sIGlmIHRoZSByZXN0b3JhdGlvbiBhbmltYXRpb24gaXMgb25nb2luZ1xyXG4gICAgICAgIGlmICh0aGlzLmNvbnRyb2xzRW5hYmxlZCA9PT0gZmFsc2UgfHwgdGhpcy5yZXN0b3JpbmdBbmltYXRpb25PbmdvaW5nKSByZXR1cm47XHJcbiAgICAgICAgLy8gUmVzZXQgcmVzdG9yYXRpb24gYW5pbWF0aW9uIHRpbW91dFxyXG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5yZXN0b3JpbmdPcmlnaW5Qb3NUaW1lb3V0KTtcclxuXHJcbiAgICAgICAgLy9lLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgdGhpcy5pc1VzZXJJbnRlcmFjdGluZyA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5yZXN0b3JpbmdBbmltYXRpb25PbmdvaW5nID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5zdGFydERyYWdnaW5nUG9zaXRpb24uc2V0KFxyXG4gICAgICAgICAgICBlLnRvdWNoZXNbMF0ucGFnZVgsIGUudG91Y2hlc1swXS5wYWdlWVxyXG4gICAgICAgIClcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIG9uVG91Y2hNb3ZlID0gKGU6IFRvdWNoRXZlbnQpID0+IHtcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgbW92ZW1lbnQgaW50ZXJhY3Rpb24sIGlmIHRoZSBjb250cm9scyBhcmUgbm90IGVuYWJsZWRcclxuICAgICAgICAvLyBJZ25vcmUgbW91c2UgbW92ZSBpbnRlcmFjdGlvbiwgaWYgdGhlIHJlc3RvcmF0aW9uIGFuaW1hdGlvbiBpcyBvbmdvaW5nXHJcbiAgICAgICAgaWYgKHRoaXMuY29udHJvbHNFbmFibGVkID09PSBmYWxzZSB8fCB0aGlzLnJlc3RvcmluZ0FuaW1hdGlvbk9uZ29pbmcpIHJldHVybjtcclxuICAgICAgICAvL2UucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBpZiAodGhpcy5pc1VzZXJJbnRlcmFjdGluZyAmJiAhdGhpcy5yZXN0b3JpbmdBbmltYXRpb25PbmdvaW5nKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnVzZXJJbnRlcmFjdGVkID09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnVzZXJJbnRlcmFjdGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHRoaXMudXNlckludGVyYWN0ZWRTdWJqZWN0Lm5leHQodGhpcy51c2VySW50ZXJhY3RlZCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhTW92ZSA9IG5ldyBWZWN0b3IyKFxyXG4gICAgICAgICAgICAgICAgZS50b3VjaGVzWzBdLnBhZ2VYIC0gdGhpcy5zdGFydERyYWdnaW5nUG9zaXRpb24ueCxcclxuICAgICAgICAgICAgICAgIGUudG91Y2hlc1swXS5wYWdlWSAtIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uLnlcclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnREcmFnZ2luZ1Bvc2l0aW9uLnNldChlLnRvdWNoZXNbMF0ucGFnZVgsIGUudG91Y2hlc1swXS5wYWdlWSk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCByb3RhdGlvblggPSB0aGlzLnZlcnRpY2FsUm90YXRpb24gPT0gdHJ1ZSA/IChkZWx0YU1vdmUueCAqIE1hdGguUEkgLyAxODAgKiB0aGlzLnJvdGF0aW9uU3BlZWQpIDogMDtcclxuICAgICAgICAgICAgY29uc3Qgcm90YXRpb25ZID0gdGhpcy5ob3Jpem9udGFsUm90YXRpb24gPT0gdHJ1ZSA/IChkZWx0YU1vdmUueSAqIE1hdGguUEkgLyAxODAgKiB0aGlzLnJvdGF0aW9uU3BlZWQpIDogMDtcclxuXHJcbiAgICAgICAgICAgIHZhciBkZWx0YVJvdGF0aW9uUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCkuc2V0RnJvbUV1bGVyKG5ldyBFdWxlcihcclxuICAgICAgICAgICAgICAgIHJvdGF0aW9uWSxcclxuICAgICAgICAgICAgICAgIHJvdGF0aW9uWCxcclxuICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgICAgICAgICAnWFlaJ1xyXG4gICAgICAgICAgICApKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMub2JqLnF1YXRlcm5pb24ubXVsdGlwbHlRdWF0ZXJuaW9ucyhkZWx0YVJvdGF0aW9uUXVhdGVybmlvbiwgdGhpcy5vYmoucXVhdGVybmlvbik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgb25Ub3VjaEVuZCA9IChlOiBUb3VjaEV2ZW50KSA9PiB7XHJcbiAgICAgICAgLy8gSWdub3JlIG1vdXNlIG1vdmVtZW50IGludGVyYWN0aW9uLCBpZiB0aGUgY29udHJvbHMgYXJlIG5vdCBlbmFibGVkXHJcbiAgICAgICAgLy8gSWdub3JlIG1vdXNlIHVwIGludGVyYWN0aW9uLCBpZiB0aGUgcmVzdG9yYXRpb24gYW5pbWF0aW9uIGlzIG9uZ29pbmdcclxuICAgICAgICBpZiAodGhpcy5jb250cm9sc0VuYWJsZWQgPT09IGZhbHNlIHx8IHRoaXMucmVzdG9yaW5nQW5pbWF0aW9uT25nb2luZykgcmV0dXJuO1xyXG4gICAgICAgIC8vZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHRoaXMuaXNVc2VySW50ZXJhY3RpbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnJlc2V0TW91c2VQb3NpdGlvbigpO1xyXG4gICAgICAgIGlmICh0aGlzLnJlc3RvcmVPcmlnaW5Qb3NpdGlvbikgdGhpcy5yZXN0b3JlT3JpZ2luYWxQb3NpdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUm90YXRlcyB0aGUgb2JqZWN0IHRvIHRoZSBwb3NpdGlvbiAwLDAsMCBhZnRlciBhIHNvbWUgdGltZW91dFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlc3RvcmVPcmlnaW5hbFBvc2l0aW9uKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucmVzdG9yaW5nT3JpZ2luUG9zVGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgdmFyIG9ialNldCA9IG5ldyBPYmplY3QzRCgpO1xyXG4gICAgICAgICAgICBvYmpTZXQucG9zaXRpb24uc2V0KDAsIDAsIDApO1xyXG4gICAgICAgICAgICBvYmpTZXQucm90YXRpb24uc2V0KDAsIDAsIDApO1xyXG5cclxuICAgICAgICAgICAgUnhqc1R3ZWVuLmNyZWF0ZVR3ZWVuKFJ4anNUd2Vlbi5saW5lYXIsIFt0aGlzLm9iai5wb3NpdGlvbi54LCB0aGlzLm9iai5wb3NpdGlvbi55LCB0aGlzLm9iai5wb3NpdGlvbi56XSxcclxuICAgICAgICAgICAgICAgIFtvYmpTZXQucG9zaXRpb24ueCwgb2JqU2V0LnBvc2l0aW9uLnksIG9ialNldC5wb3NpdGlvbi56XSwgMTAwMCkuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgICAgICAgICBuZXh0OiB0d2VlblZhbCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3RvcmluZ0FuaW1hdGlvbk9uZ29pbmcgPT0gZmFsc2UpIHRoaXMucmVzdG9yaW5nQW5pbWF0aW9uT25nb2luZyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2JqLnJvdGF0aW9uLnNldCh0d2VlblZhbFswXSwgdHdlZW5WYWxbMV0sIHR3ZWVuVmFsWzJdKTtcclxuICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yaW5nQW5pbWF0aW9uT25nb2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2V0VXNlckludGVyYWN0aW9uRmxhZygpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0sIDUwMDApO1xyXG4gICAgfVxyXG59XHJcbiJdfQ==