angular-cesium
Version:
Angular library for working with Cesium.
266 lines • 31.5 kB
JavaScript
import { Injectable } from '@angular/core';
import { SceneMode } from '../../models/scene-mode.enum';
/**
* The service exposes the scene's camera and screenSpaceCameraController
* SceneMode.PERFORMANCE_SCENE2D - is a 3D scene mode that acts like Cesium 2D mode,
* but is more efficient performance wise.
*/
export class CameraService {
constructor() {
this.isSceneModePerformance2D = false;
}
init(cesiumService) {
this.viewer = cesiumService.getViewer();
this.scene = cesiumService.getScene();
this.screenSpaceCameraController = this.scene.screenSpaceCameraController;
this.camera = this.scene.camera;
this.lastRotate = this.screenSpaceCameraController.enableRotate;
this.lastTilt = this.screenSpaceCameraController.enableTilt;
this.lastLook = this.screenSpaceCameraController.enableLook;
}
_listenToSceneModeMorph(callback) {
this.morphListenerCancelFn = this.scene.morphStart.addEventListener(callback);
}
_revertCameraProperties() {
this.isSceneModePerformance2D = false;
this.enableTilt(this.lastTilt);
this.enableRotate(this.lastRotate);
this.enableLook(this.lastLook);
}
/**
* Gets the scene's camera
*/
getCamera() {
return this.camera;
}
/**
* Gets the scene's screenSpaceCameraController
*/
getScreenSpaceCameraController() {
return this.screenSpaceCameraController;
}
/**
* Gets the minimum zoom value in meters
*/
getMinimumZoom() {
return this.screenSpaceCameraController.minimumZoomDistance;
}
/**
* Sets the minimum zoom value in meters
* @param zoom amount
*/
setMinimumZoom(amount) {
this.screenSpaceCameraController.minimumZoomDistance = amount;
}
/**
* Gets the maximum zoom value in meters
*/
getMaximumZoom() {
return this.screenSpaceCameraController.maximumZoomDistance;
}
/**
* Sets the maximum zoom value in meters
* @param zoom amount
*/
setMaximumZoom(amount) {
this.screenSpaceCameraController.maximumZoomDistance = amount;
}
/**
* Sets if the camera is able to tilt
*/
enableTilt(tilt) {
this.screenSpaceCameraController.enableTilt = tilt;
}
/**
* Sets if the camera is able to rotate
*/
enableRotate(rotate) {
this.screenSpaceCameraController.enableRotate = rotate;
}
/**
* Sets if the camera is able to free-look
*/
enableLook(lock) {
this.screenSpaceCameraController.enableLook = lock;
}
/**
* Sets if the camera is able to translate
*/
enableTranslate(translate) {
this.screenSpaceCameraController.enableTranslate = translate;
}
/**
* Sets if the camera is able to zoom
*/
enableZoom(zoom) {
this.screenSpaceCameraController.enableZoom = zoom;
}
/**
* Sets if the camera receives inputs
*/
enableInputs(inputs) {
this.screenSpaceCameraController.enableInputs = inputs;
}
/**
* Sets the map's SceneMode
* @param sceneMode - The SceneMode to morph the scene into.
* @param duration - The duration of scene morph animations, in seconds
*/
setSceneMode(sceneMode, duration) {
switch (sceneMode) {
case SceneMode.SCENE3D: {
if (this.isSceneModePerformance2D) {
this._revertCameraProperties();
}
this.scene.morphTo3D(duration);
break;
}
case SceneMode.COLUMBUS_VIEW: {
if (this.isSceneModePerformance2D) {
this._revertCameraProperties();
}
this.scene.morphToColumbusView(duration);
break;
}
case SceneMode.SCENE2D: {
if (this.isSceneModePerformance2D) {
this._revertCameraProperties();
}
this.scene.morphTo2D(duration);
break;
}
case SceneMode.PERFORMANCE_SCENE2D: {
this.isSceneModePerformance2D = true;
this.lastLook = this.screenSpaceCameraController.enableLook;
this.lastTilt = this.screenSpaceCameraController.enableTilt;
this.lastRotate = this.screenSpaceCameraController.enableRotate;
this.screenSpaceCameraController.enableTilt = false;
this.screenSpaceCameraController.enableRotate = false;
this.screenSpaceCameraController.enableLook = false;
if (this.morphListenerCancelFn) {
this.morphListenerCancelFn();
}
this.scene.morphToColumbusView(duration);
const morphCompleteEventListener = this.scene.morphComplete.addEventListener(() => {
this.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(0.0, 0.0, Math.min(CameraService.PERFORMANCE_2D_ALTITUDE, this.getMaximumZoom())),
orientation: {
pitch: Cesium.Math.toRadians(-90)
}
});
morphCompleteEventListener();
this._listenToSceneModeMorph(this._revertCameraProperties.bind(this));
});
break;
}
}
}
/**
* Flies the camera to a destination
* API: https://cesiumjs.org/Cesium/Build/Documentation/Camera.html?classFilter=cam#flyTo
*/
cameraFlyTo(options) {
return this.camera.flyTo(options);
}
/**
* Flies the camera to a target
* API: https://cesiumjs.org/Cesium/Build/Documentation/Viewer.html?classFilter=viewer#flyTo
* @returns Promise<boolean>
*/
flyTo(target, options) {
return this.viewer.flyTo(target, options);
}
/**
* Zooms amount along the camera's view vector.
* API: https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#zoomIn
*/
zoomIn(amount) {
return this.camera.zoomIn(amount || this.camera.defaultZoomAmount);
}
/**
* Zooms amount along the opposite direction of the camera's view vector.
* API: https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#zoomOut
*/
zoomOut(amount) {
return this.camera.zoomOut(amount || this.camera.defaultZoomAmount);
}
/**
* Zoom the camera to a target
* API: https://cesiumjs.org/Cesium/Build/Documentation/Viewer.html?classFilter=viewer#zoomTo
* @returns Promise<boolean>
*/
zoomTo(target, offset) {
return this.viewer.zoomTo(target, offset);
}
/**
* Flies the camera to a destination
* API: https://cesiumjs.org/Cesium/Build/Documentation/Camera.html?classFilter=camera#setView
* @param options viewer options
*/
setView(options) {
this.camera.setView(options);
}
/**
* Set camera's rotation
*/
setRotation(degreesInRadians) {
this.setView({ orientation: { heading: degreesInRadians } });
}
/**
* Locks or unlocks camera rotation
*/
lockRotation(lock) {
this.scene.screenSpaceCameraController.enableRotate = !lock;
}
/**
* Make the camera track a specific entity
* API: https://cesiumjs.org/Cesium/Build/Documentation/Viewer.html?classFilter=viewer#trackedEntity
* @param cesiumEntity - cesium entity( billboard, polygon...) to track
* @param options - track entity options
*/
trackEntity(cesiumEntity, options) {
const flyTo = (options && options.flyTo) || false;
this.viewer.trackedEntity = undefined;
return new Promise(resolve => {
if (flyTo) {
const flyToDuration = (options && options.flyToDuration) || 1;
const altitude = (options && options.altitude) || 10000;
// Calc entity flyTo position and wanted altitude
const entPosCar3 = cesiumEntity.position.getValue(Cesium.JulianDate.now());
const entPosCart = Cesium.Cartographic.fromCartesian(entPosCar3);
const zoomAmount = altitude - entPosCart.height;
entPosCart.height = altitude;
const flyToPosition = Cesium.Cartesian3.fromRadians(entPosCart.longitude, entPosCart.latitude, entPosCart.height);
this.cameraFlyTo({
duration: flyToDuration,
destination: flyToPosition,
complete: () => {
this.viewer.trackedEntity = cesiumEntity;
setTimeout(() => {
if (zoomAmount > 0) {
this.camera.zoomOut(zoomAmount);
}
else {
this.camera.zoomIn(zoomAmount);
}
}, 0);
resolve();
}
});
}
else {
this.viewer.trackedEntity = cesiumEntity;
resolve();
}
});
}
untrackEntity() {
this.trackEntity();
}
}
CameraService.PERFORMANCE_2D_ALTITUDE = 25000000;
CameraService.decorators = [
{ type: Injectable }
];
CameraService.ctorParameters = () => [];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FtZXJhLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNlc2l1bS9zcmMvbGliL2FuZ3VsYXItY2VzaXVtL3NlcnZpY2VzL2NhbWVyYS9jYW1lcmEuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUV6RDs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLGFBQWE7SUFheEI7UUFGUSw2QkFBd0IsR0FBRyxLQUFLLENBQUM7SUFHekMsQ0FBQztJQUVELElBQUksQ0FBQyxhQUE0QjtRQUMvQixJQUFJLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN4QyxJQUFJLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN0QyxJQUFJLENBQUMsMkJBQTJCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQztRQUMxRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLFlBQVksQ0FBQztRQUNoRSxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxVQUFVLENBQUM7UUFDNUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsMkJBQTJCLENBQUMsVUFBVSxDQUFDO0lBQzlELENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxRQUFrQjtRQUN4QyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQ2pFLFFBQVEsQ0FDVCxDQUFDO0lBQ0osQ0FBQztJ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QVUsQ0FBQyxRQUFRLEVBQ25CLFVBQVUsQ0FBQyxNQUFNLENBQ2xCLENBQUM7Z0JBRUYsSUFBSSxDQUFDLFdBQVcsQ0FBQztvQkFDZixRQUFRLEVBQUUsYUFBYTtvQkFDdkIsV0FBVyxFQUFFLGFBQWE7b0JBQzFCLFFBQVEsRUFBRSxHQUFHLEVBQUU7d0JBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO3dCQUN6QyxVQUFVLENBQUMsR0FBRyxFQUFFOzRCQUNkLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtnQ0FDbEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7NkJBQ2pDO2lDQUFNO2dDQUNMLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDOzZCQUNoQzt3QkFDSCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7d0JBQ04sT0FBTyxFQUFFLENBQUM7b0JBQ1osQ0FBQztpQkFDRixDQUFDLENBQUM7YUFDSjtpQkFBTTtnQkFDTCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsR0FBRyxZQUFZLENBQUM7Z0JBQ3pDLE9BQU8sRUFBRSxDQUFDO2FBQ1g7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxhQUFhO1FBQ1gsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7O0FBMVRNLHFDQUF1QixHQUFHLFFBQVEsQ0FBQzs7WUFGM0MsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ2VzaXVtU2VydmljZSB9IGZyb20gJy4uL2Nlc2l1bS9jZXNpdW0uc2VydmljZSc7XHJcbmltcG9ydCB7IFNjZW5lTW9kZSB9IGZyb20gJy4uLy4uL21vZGVscy9zY2VuZS1tb2RlLmVudW0nO1xyXG5cclxuLyoqXHJcbiAqICBUaGUgc2VydmljZSBleHBvc2VzIHRoZSBzY2VuZSdzIGNhbWVyYSBhbmQgc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyXHJcbiAqICBTY2VuZU1vZGUuUEVSRk9STUFOQ0VfU0NFTkUyRCAtICBpcyBhIDNEIHNjZW5lIG1vZGUgdGhhdCBhY3RzIGxpa2UgQ2VzaXVtIDJEIG1vZGUsXHJcbiAqICBidXQgaXMgbW9yZSBlZmZpY2llbnQgcGVyZm9ybWFuY2Ugd2lzZS5cclxuICovXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIENhbWVyYVNlcnZpY2Uge1xyXG4gIHN0YXRpYyBQRVJGT1JNQU5DRV8yRF9BTFRJVFVERSA9IDI1MDAwMDAwO1xyXG5cclxuICBwcml2YXRlIHZpZXdlcjogYW55O1xyXG4gIHByaXZhdGUgc2NlbmU6IGFueTtcclxuICBwcml2YXRlIGNhbWVyYTogYW55O1xyXG4gIHByaXZhdGUgc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyOiBhbnk7XHJcbiAgcHJpdmF0ZSBtb3JwaExpc3RlbmVyQ2FuY2VsRm46IGFueTtcclxuICBwcml2YXRlIGxhc3RSb3RhdGU6IGJvb2xlYW47XHJcbiAgcHJpdmF0ZSBsYXN0VGlsdDogYm9vbGVhbjtcclxuICBwcml2YXRlIGxhc3RMb29rOiBib29sZWFuO1xyXG4gIHByaXZhdGUgaXNTY2VuZU1vZGVQZXJmb3JtYW5jZTJEID0gZmFsc2U7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gIH1cclxuXHJcbiAgaW5pdChjZXNpdW1TZXJ2aWNlOiBDZXNpdW1TZXJ2aWNlKSB7XHJcbiAgICB0aGlzLnZpZXdlciA9IGNlc2l1bVNlcnZpY2UuZ2V0Vmlld2VyKCk7XHJcbiAgICB0aGlzLnNjZW5lID0gY2VzaXVtU2VydmljZS5nZXRTY2VuZSgpO1xyXG4gICAgdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIgPSB0aGlzLnNjZW5lLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlcjtcclxuICAgIHRoaXMuY2FtZXJhID0gdGhpcy5zY2VuZS5jYW1lcmE7XHJcbiAgICB0aGlzLmxhc3RSb3RhdGUgPSB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVSb3RhdGU7XHJcbiAgICB0aGlzLmxhc3RUaWx0ID0gdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIuZW5hYmxlVGlsdDtcclxuICAgIHRoaXMubGFzdExvb2sgPSB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVMb29rO1xyXG4gIH1cclxuXHJcbiAgX2xpc3RlblRvU2NlbmVNb2RlTW9ycGgoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XHJcbiAgICB0aGlzLm1vcnBoTGlzdGVuZXJDYW5jZWxGbiA9IHRoaXMuc2NlbmUubW9ycGhTdGFydC5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICBjYWxsYmFja1xyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIF9yZXZlcnRDYW1lcmFQcm9wZXJ0aWVzKCkge1xyXG4gICAgdGhpcy5pc1NjZW5lTW9kZVBlcmZvcm1hbmNlMkQgPSBmYWxzZTtcclxuICAgIHRoaXMuZW5hYmxlVGlsdCh0aGlzLmxhc3RUaWx0KTtcclxuICAgIHRoaXMuZW5hYmxlUm90YXRlKHRoaXMubGFzdFJvdGF0ZSk7XHJcbiAgICB0aGlzLmVuYWJsZUxvb2sodGhpcy5sYXN0TG9vayk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBzY2VuZSdzIGNhbWVyYVxyXG4gICAqL1xyXG4gIGdldENhbWVyYSgpIHtcclxuICAgIHJldHVybiB0aGlzLmNhbWVyYTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIHNjZW5lJ3Mgc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyXHJcbiAgICovXHJcbiAgZ2V0U2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgbWluaW11bSB6b29tIHZhbHVlIGluIG1ldGVyc1xyXG4gICAqL1xyXG4gIGdldE1pbmltdW1ab29tKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIubWluaW11bVpvb21EaXN0YW5jZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgdGhlIG1pbmltdW0gem9vbSB2YWx1ZSBpbiBtZXRlcnNcclxuICAgKiBAcGFyYW0gem9vbSBhbW91bnRcclxuICAgKi9cclxuICBzZXRNaW5pbXVtWm9vbShhbW91bnQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIubWluaW11bVpvb21EaXN0YW5jZSA9IGFtb3VudDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIG1heGltdW0gem9vbSB2YWx1ZSBpbiBtZXRlcnNcclxuICAgKi9cclxuICBnZXRNYXhpbXVtWm9vbSgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLm1heGltdW1ab29tRGlzdGFuY2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBtYXhpbXVtIHpvb20gdmFsdWUgaW4gbWV0ZXJzXHJcbiAgICogQHBhcmFtIHpvb20gYW1vdW50XHJcbiAgICovXHJcbiAgc2V0TWF4aW11bVpvb20oYW1vdW50OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLm1heGltdW1ab29tRGlzdGFuY2UgPSBhbW91bnQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIGlmIHRoZSBjYW1lcmEgaXMgYWJsZSB0byB0aWx0XHJcbiAgICovXHJcbiAgZW5hYmxlVGlsdCh0aWx0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVUaWx0ID0gdGlsdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgaWYgdGhlIGNhbWVyYSBpcyBhYmxlIHRvIHJvdGF0ZVxyXG4gICAqL1xyXG4gIGVuYWJsZVJvdGF0ZShyb3RhdGU6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLmVuYWJsZVJvdGF0ZSA9IHJvdGF0ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgaWYgdGhlIGNhbWVyYSBpcyBhYmxlIHRvIGZyZWUtbG9va1xyXG4gICAqL1xyXG4gIGVuYWJsZUxvb2sobG9jazogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIuZW5hYmxlTG9vayA9IGxvY2s7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIGlmIHRoZSBjYW1lcmEgaXMgYWJsZSB0byB0cmFuc2xhdGVcclxuICAgKi9cclxuICBlbmFibGVUcmFuc2xhdGUodHJhbnNsYXRlOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVUcmFuc2xhdGUgPSB0cmFuc2xhdGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIGlmIHRoZSBjYW1lcmEgaXMgYWJsZSB0byB6b29tXHJcbiAgICovXHJcbiAgZW5hYmxlWm9vbSh6b29tOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVab29tID0gem9vbTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgaWYgdGhlIGNhbWVyYSByZWNlaXZlcyBpbnB1dHNcclxuICAgKi9cclxuICBlbmFibGVJbnB1dHMoaW5wdXRzOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVJbnB1dHMgPSBpbnB1dHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBtYXAncyBTY2VuZU1vZGVcclxuICAgKiBAcGFyYW0gc2NlbmVNb2RlIC0gVGhlIFNjZW5lTW9kZSB0byBtb3JwaCB0aGUgc2NlbmUgaW50by5cclxuICAgKiBAcGFyYW0gZHVyYXRpb24gLSBUaGUgZHVyYXRpb24gb2Ygc2NlbmUgbW9ycGggYW5pbWF0aW9ucywgaW4gc2Vjb25kc1xyXG4gICAqL1xyXG4gIHNldFNjZW5lTW9kZShzY2VuZU1vZGU6IFNjZW5lTW9kZSwgZHVyYXRpb24/OiBudW1iZXIpIHtcclxuICAgIHN3aXRjaCAoc2NlbmVNb2RlKSB7XHJcbiAgICAgIGNhc2UgU2NlbmVNb2RlLlNDRU5FM0Q6IHtcclxuICAgICAgICBpZiAodGhpcy5pc1NjZW5lTW9kZVBlcmZvcm1hbmNlMkQpIHtcclxuICAgICAgICAgIHRoaXMuX3JldmVydENhbWVyYVByb3BlcnRpZXMoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2NlbmUubW9ycGhUbzNEKGR1cmF0aW9uKTtcclxuXHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgICAgY2FzZSBTY2VuZU1vZGUuQ09MVU1CVVNfVklFVzoge1xyXG4gICAgICAgIGlmICh0aGlzLmlzU2NlbmVNb2RlUGVyZm9ybWFuY2UyRCkge1xyXG4gICAgICAgICAgdGhpcy5fcmV2ZXJ0Q2FtZXJhUHJvcGVydGllcygpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zY2VuZS5tb3JwaFRvQ29sdW1idXNWaWV3KGR1cmF0aW9uKTtcclxuXHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgICAgY2FzZSBTY2VuZU1vZGUuU0NFTkUyRDoge1xyXG4gICAgICAgIGlmICh0aGlzLmlzU2NlbmVNb2RlUGVyZm9ybWFuY2UyRCkge1xyXG4gICAgICAgICAgdGhpcy5fcmV2ZXJ0Q2FtZXJhUHJvcGVydGllcygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNjZW5lLm1vcnBoVG8yRChkdXJhdGlvbik7XHJcblxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICAgIGNhc2UgU2NlbmVNb2RlLlBFUkZPUk1BTkNFX1NDRU5FMkQ6IHtcclxuICAgICAgICB0aGlzLmlzU2NlbmVNb2RlUGVyZm9ybWFuY2UyRCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5sYXN0TG9vayA9IHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLmVuYWJsZUxvb2s7XHJcbiAgICAgICAgdGhpcy5sYXN0VGlsdCA9IHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLmVuYWJsZVRpbHQ7XHJcbiAgICAgICAgdGhpcy5sYXN0Um90YXRlID0gdGhpcy5zY3JlZW5TcGFjZUNhbWVyYUNvbnRyb2xsZXIuZW5hYmxlUm90YXRlO1xyXG4gICAgICAgIHRoaXMuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLmVuYWJsZVRpbHQgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVSb3RhdGUgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNjcmVlblNwYWNlQ2FtZXJhQ29udHJvbGxlci5lbmFibGVMb29rID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKHRoaXMubW9ycGhMaXN0ZW5lckNhbmNlbEZuKSB7XHJcbiAgICAgICAgICB0aGlzLm1vcnBoTGlzdGVuZXJDYW5jZWxGbigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNjZW5lLm1vcnBoVG9Db2x1bWJ1c1ZpZXcoZHVyYXRpb24pO1xyXG4gICAgICAgIGNvbnN0IG1vcnBoQ29tcGxldGVFdmVudExpc3RlbmVyID0gdGhpcy5zY2VuZS5tb3JwaENvbXBsZXRlLmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuY2FtZXJhLnNldFZpZXcoe1xyXG4gICAgICAgICAgICAgIGRlc3RpbmF0aW9uOiBDZXNpdW0uQ2FydGVzaWFuMy5mcm9tRGVncmVlcyhcclxuICAgICAgICAgICAgICAgIDAuMCxcclxuICAgICAgICAgICAgICAgIDAuMCxcclxuICAgICAgICAgICAgICAgIE1hdGgubWluKFxyXG4gICAgICAgICAgICAgICAgICBDYW1lcmFTZXJ2aWNlLlBFUkZPUk1BTkNFXzJEX0FMVElUVURFLFxyXG4gICAgICAgICAgICAgICAgICB0aGlzLmdldE1heGltdW1ab29tKClcclxuICAgICAgICAgICAgICAgIClcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgIG9yaWVudGF0aW9uOiB7XHJcbiAgICAgICAgICAgICAgICBwaXRjaDogQ2VzaXVtLk1hdGgudG9SYWRpYW5zKC05MClcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBtb3JwaENvbXBsZXRlRXZlbnRMaXN0ZW5lcigpO1xyXG4gICAgICAgICAgICB0aGlzLl9saXN0ZW5Ub1NjZW5lTW9kZU1vcnBoKFxyXG4gICAgICAgICAgICAgIHRoaXMuX3JldmVydENhbWVyYVByb3BlcnRpZXMuYmluZCh0aGlzKVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGbGllcyB0aGUgY2FtZXJhIHRvIGEgZGVzdGluYXRpb25cclxuICAgKiBBUEk6IGh0dHBzOi8vY2VzaXVtanMub3JnL0Nlc2l1bS9CdWlsZC9Eb2N1bWVudGF0aW9uL0NhbWVyYS5odG1sP2NsYXNzRmlsdGVyPWNhbSNmbHlUb1xyXG4gICAqL1xyXG4gIGNhbWVyYUZseVRvKG9wdGlvbnM6IGFueSkge1xyXG4gICAgcmV0dXJuIHRoaXMuY2FtZXJhLmZseVRvKG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRmxpZXMgdGhlIGNhbWVyYSB0byBhIHRhcmdldFxyXG4gICAqIEFQSTogaHR0cHM6Ly9jZXNpdW1qcy5vcmcvQ2VzaXVtL0J1aWxkL0RvY3VtZW50YXRpb24vVmlld2VyLmh0bWw/Y2xhc3NGaWx0ZXI9dmlld2VyI2ZseVRvXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTxib29sZWFuPlxyXG4gICAqL1xyXG4gIGZseVRvKHRhcmdldDogYW55LCBvcHRpb25zPzogYW55KSB7XHJcbiAgICByZXR1cm4gdGhpcy52aWV3ZXIuZmx5VG8odGFyZ2V0LCBvcHRpb25zKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFpvb21zIGFtb3VudCBhbG9uZyB0aGUgY2FtZXJhJ3MgdmlldyB2ZWN0b3IuXHJcbiAgICogQVBJOiBodHRwczovL2Nlc2l1bWpzLm9yZy9DZXNpdW0vQnVpbGQvRG9jdW1lbnRhdGlvbi9DYW1lcmEuaHRtbCN6b29tSW5cclxuICAgKi9cclxuICB6b29tSW4oYW1vdW50OiBudW1iZXIpIHtcclxuICAgIHJldHVybiB0aGlzLmNhbWVyYS56b29tSW4oYW1vdW50IHx8IHRoaXMuY2FtZXJhLmRlZmF1bHRab29tQW1vdW50KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFpvb21zIGFtb3VudCBhbG9uZyB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uIG9mIHRoZSBjYW1lcmEncyB2aWV3IHZlY3Rvci5cclxuICAgKiBBUEk6IGh0dHBzOi8vY2VzaXVtanMub3JnL0Nlc2l1bS9CdWlsZC9Eb2N1bWVudGF0aW9uL0NhbWVyYS5odG1sI3pvb21PdXRcclxuICAgKi9cclxuICB6b29tT3V0KGFtb3VudDogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jYW1lcmEuem9vbU91dChhbW91bnQgfHwgdGhpcy5jYW1lcmEuZGVmYXVsdFpvb21BbW91bnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogWm9vbSB0aGUgY2FtZXJhIHRvIGEgdGFyZ2V0XHJcbiAgICogQVBJOiBodHRwczovL2Nlc2l1bWpzLm9yZy9DZXNpdW0vQnVpbGQvRG9jdW1lbnRhdGlvbi9WaWV3ZXIuaHRtbD9jbGFzc0ZpbHRlcj12aWV3ZXIjem9vbVRvXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTxib29sZWFuPlxyXG4gICAqL1xyXG4gIHpvb21Ubyh0YXJnZXQ6IGFueSwgb2Zmc2V0PzogYW55KSB7XHJcbiAgICByZXR1cm4gdGhpcy52aWV3ZXIuem9vbVRvKHRhcmdldCwgb2Zmc2V0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZsaWVzIHRoZSBjYW1lcmEgdG8gYSBkZXN0aW5hdGlvblxyXG4gICAqIEFQSTogaHR0cHM6Ly9jZXNpdW1qcy5vcmcvQ2VzaXVtL0J1aWxkL0RvY3VtZW50YXRpb24vQ2FtZXJhLmh0bWw/Y2xhc3NGaWx0ZXI9Y2FtZXJhI3NldFZpZXdcclxuICAgKiBAcGFyYW0gb3B0aW9ucyB2aWV3ZXIgb3B0aW9uc1xyXG4gICAqL1xyXG4gIHNldFZpZXcob3B0aW9uczogYW55KSB7XHJcbiAgICB0aGlzLmNhbWVyYS5zZXRWaWV3KG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IGNhbWVyYSdzIHJvdGF0aW9uXHJcbiAgICovXHJcbiAgc2V0Um90YXRpb24oZGVncmVlc0luUmFkaWFuczogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnNldFZpZXcoe29yaWVudGF0aW9uOiB7aGVhZGluZzogZGVncmVlc0luUmFkaWFuc319KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvY2tzIG9yIHVubG9ja3MgY2FtZXJhIHJvdGF0aW9uXHJcbiAgICovXHJcbiAgbG9ja1JvdGF0aW9uKGxvY2s6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuc2NlbmUuc2NyZWVuU3BhY2VDYW1lcmFDb250cm9sbGVyLmVuYWJsZVJvdGF0ZSA9ICFsb2NrO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWFrZSB0aGUgY2FtZXJhIHRyYWNrIGEgc3BlY2lmaWMgZW50aXR5XHJcbiAgICogQVBJOiBodHRwczovL2Nlc2l1bWpzLm9yZy9DZXNpdW0vQnVpbGQvRG9jdW1lbnRhdGlvbi9WaWV3ZXIuaHRtbD9jbGFzc0ZpbHRlcj12aWV3ZXIjdHJhY2tlZEVudGl0eVxyXG4gICAqIEBwYXJhbSBjZXNpdW1FbnRpdHkgLSBjZXNpdW0gZW50aXR5KCBiaWxsYm9hcmQsIHBvbHlnb24uLi4pIHRvIHRyYWNrXHJcbiAgICogQHBhcmFtIG9wdGlvbnMgLSB0cmFjayBlbnRpdHkgb3B0aW9uc1xyXG4gICAqL1xyXG4gIHRyYWNrRW50aXR5KFxyXG4gICAgY2VzaXVtRW50aXR5PzogYW55LFxyXG4gICAgb3B0aW9ucz86IHsgZmx5VG86IGJvb2xlYW47IGZseVRvRHVyYXRpb24/OiBudW1iZXI7IGFsdGl0dWRlPzogbnVtYmVyIH1cclxuICApIHtcclxuICAgIGNvbnN0IGZseVRvID0gKG9wdGlvbnMgJiYgb3B0aW9ucy5mbHlUbykgfHwgZmFsc2U7XHJcblxyXG4gICAgdGhpcy52aWV3ZXIudHJhY2tlZEVudGl0eSA9IHVuZGVmaW5lZDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IHtcclxuICAgICAgaWYgKGZseVRvKSB7XHJcbiAgICAgICAgY29uc3QgZmx5VG9EdXJhdGlvbiA9IChvcHRpb25zICYmIG9wdGlvbnMuZmx5VG9EdXJhdGlvbikgfHwgMTtcclxuICAgICAgICBjb25zdCBhbHRpdHVkZSA9IChvcHRpb25zICYmIG9wdGlvbnMuYWx0aXR1ZGUpIHx8IDEwMDAwO1xyXG5cclxuICAgICAgICAvLyBDYWxjIGVudGl0eSBmbHlUbyBwb3NpdGlvbiBhbmQgd2FudGVkIGFsdGl0dWRlXHJcbiAgICAgICAgY29uc3QgZW50UG9zQ2FyMyA9IGNlc2l1bUVudGl0eS5wb3NpdGlvbi5nZXRWYWx1ZShDZXNpdW0uSnVsaWFuRGF0ZS5ub3coKSk7XHJcbiAgICAgICAgY29uc3QgZW50UG9zQ2FydCA9IENlc2l1bS5DYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihlbnRQb3NDYXIzKTtcclxuICAgICAgICBjb25zdCB6b29tQW1vdW50ID0gYWx0aXR1ZGUgLSBlbnRQb3NDYXJ0LmhlaWdodDtcclxuICAgICAgICBlbnRQb3NDYXJ0LmhlaWdodCA9IGFsdGl0dWRlO1xyXG4gICAgICAgIGNvbnN0IGZseVRvUG9zaXRpb24gPSBDZXNpdW0uQ2FydGVzaWFuMy5mcm9tUmFkaWFucyhcclxuICAgICAgICAgIGVudFBvc0NhcnQubG9uZ2l0dWRlLFxyXG4gICAgICAgICAgZW50UG9zQ2FydC5sYXRpdHVkZSxcclxuICAgICAgICAgIGVudFBvc0NhcnQuaGVpZ2h0XHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW1lcmFGbHlUbyh7XHJcbiAgICAgICAgICBkdXJhdGlvbjogZmx5VG9EdXJhdGlvbixcclxuICAgICAgICAgIGRlc3RpbmF0aW9uOiBmbHlUb1Bvc2l0aW9uLFxyXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy52aWV3ZXIudHJhY2tlZEVudGl0eSA9IGNlc2l1bUVudGl0eTtcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgaWYgKHpvb21BbW91bnQgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNhbWVyYS56b29tT3V0KHpvb21BbW91bnQpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNhbWVyYS56b29tSW4oem9vbUFtb3VudCk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LCAwKTtcclxuICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudmlld2VyLnRyYWNrZWRFbnRpdHkgPSBjZXNpdW1FbnRpdHk7XHJcbiAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHVudHJhY2tFbnRpdHkoKSB7XHJcbiAgICB0aGlzLnRyYWNrRW50aXR5KCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==