UNPKG

ngx-spine

Version:

[![Build Status](https://travis-ci.org/PoiScript/ngx-spine.svg?branch=master)](https://travis-ci.org/PoiScript/ngx-spine)

723 lines 60.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Input, Output, EventEmitter, ViewChild, Component, ElementRef, ChangeDetectionStrategy } from "@angular/core"; import { AssetManager, SceneRenderer, ManagedWebGLRenderingContext, ResizeMode } from "./spine-ts/webgl"; import { TimeKeeper, Skeleton, AnimationState, AtlasAttachmentLoader, SkeletonJson, SkeletonBinary, AnimationStateData, Vector2 } from "./spine-ts/core"; /** * @record */ function Viewport() { } if (false) { /** @type {?} */ Viewport.prototype.x; /** @type {?} */ Viewport.prototype.y; /** @type {?} */ Viewport.prototype.width; /** @type {?} */ Viewport.prototype.height; /** @type {?} */ Viewport.prototype.padLeft; /** @type {?} */ Viewport.prototype.padRight; /** @type {?} */ Viewport.prototype.padTop; /** @type {?} */ Viewport.prototype.padBottom; } /** * @record */ function DataUrls() { } if (false) { /** @type {?|undefined} */ DataUrls.prototype.json; /** @type {?|undefined} */ DataUrls.prototype.skel; /** @type {?} */ DataUrls.prototype.atlas; } var NgxSpineWebglComponent = /** @class */ (function () { function NgxSpineWebglComponent() { /* Optional: the default mix time used to switch between two animations. */ this.defaultMix = 0.25; /* Optional: whether the skeleton uses premultiplied alpha. Default: true. */ this.premultipliedAlpha = true; this.transitionTime = 0.2; this.speed = 1; // The name of the animation to be played. Default: first animation in the skeleton. this.animationValue = null; this.animationChange = new EventEmitter(); /* Optional: list of animation names from which the user can choose. */ this.animationsValue = []; this.animationsChange = new EventEmitter(); /* Optional: the name of the skin to be set. Default: the default skin. */ this.skinValue = null; this.skinChange = new EventEmitter(); /* Optional: list of skin names from which the user can choose. */ this.skinsValue = []; this.skinsChange = new EventEmitter(); this.loaded = new EventEmitter(); this.time = new TimeKeeper(); this.paused = true; this.playTime = 0; this.currentViewport = null; this.previousViewport = null; this.viewportTransitionStart = 0; this.init = false; } Object.defineProperty(NgxSpineWebglComponent.prototype, "dataUrls", { get: /** * @return {?} */ function () { return this.urls; }, set: /** * @param {?} urls * @return {?} */ function (urls) { var _this = this; this.urls = urls; if (!this.urls.json && !this.urls.skel) { throw new Error("Please specify the URL of the skeleton JSON or .skel file."); } if (!this.urls.atlas) { throw new Error("Please specify the URL of the atlas file."); } if (this.init) { this.loaded.emit(false); this.loadAsset().then((/** * @return {?} */ function () { console.log("load assets"); _this.loadSkeleton(); _this.loaded.emit(true); requestAnimationFrame((/** * @return {?} */ function () { return _this.drawFrame(); })); })); } }, enumerable: true, configurable: true }); Object.defineProperty(NgxSpineWebglComponent.prototype, "animation", { get: /** * @return {?} */ function () { return this.animationValue; }, set: /** * @param {?} val * @return {?} */ function (val) { this.animationValue = val; this.animationChange.emit(val); if (this.skeleton && this.animations.length > 0) { this.playTime = 0; this.setAnimation(val); } }, enumerable: true, configurable: true }); Object.defineProperty(NgxSpineWebglComponent.prototype, "animations", { get: /** * @return {?} */ function () { return this.animationsValue; }, set: /** * @param {?} val * @return {?} */ function (val) { this.animationsValue = val; this.animationsChange.emit(val); }, enumerable: true, configurable: true }); Object.defineProperty(NgxSpineWebglComponent.prototype, "skin", { get: /** * @return {?} */ function () { return this.skinValue; }, set: /** * @param {?} val * @return {?} */ function (val) { this.skinValue = val; this.skinChange.emit(this.skinValue); if (this.skeleton && this.animations.length > 0) { this.skeleton.setSkinByName(val); this.skeleton.setSlotsToSetupPose(); } }, enumerable: true, configurable: true }); Object.defineProperty(NgxSpineWebglComponent.prototype, "skins", { get: /** * @return {?} */ function () { return this.skinsValue; }, set: /** * @param {?} val * @return {?} */ function (val) { this.skinsValue = val; this.skinsChange.emit(val); }, enumerable: true, configurable: true }); /** * @return {?} */ NgxSpineWebglComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { var _this = this; this.loaded.emit(false); // webgl setup this.context = new ManagedWebGLRenderingContext(this.canvas.nativeElement, { alpha: true }); this.sceneRenderer = new SceneRenderer(this.canvas.nativeElement, this.context, true); // load the assets this.assetManager = new AssetManager(this.context); this.init = true; this.loadAsset().then((/** * @return {?} */ function () { console.log("load assets"); _this.loadSkeleton(); _this.loaded.emit(true); requestAnimationFrame((/** * @return {?} */ function () { return _this.drawFrame(); })); })); }; /** * @private * @return {?} */ NgxSpineWebglComponent.prototype.loadAsset = /** * @private * @return {?} */ function () { var _this = this; /** @type {?} */ var promises = []; promises.push(new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { _this.assetManager.loadTextureAtlas(_this.dataUrls.atlas, resolve, reject); }))); if (this.dataUrls.json) { promises.push(new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { _this.assetManager.loadText(_this.dataUrls.json, resolve, reject); }))); } else { promises.push(new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { _this.assetManager.loadBinary(_this.dataUrls.skel, resolve, reject); }))); } return Promise.all(promises); }; /** * @private * @return {?} */ NgxSpineWebglComponent.prototype.loadSkeleton = /** * @private * @return {?} */ function () { /** @type {?} */ var atlas = this.assetManager.get(this.dataUrls.atlas); /** @type {?} */ var skeletonData; if (this.dataUrls.json) { /** @type {?} */ var json = this.assetManager.get(this.dataUrls.json); /** @type {?} */ var skeletonJson = new SkeletonJson(new AtlasAttachmentLoader(atlas)); skeletonData = skeletonJson.readSkeletonData(json); } else { /** @type {?} */ var binary = this.assetManager.get(this.dataUrls.skel); /** @type {?} */ var skeletonBinary = new SkeletonBinary(new AtlasAttachmentLoader(atlas)); skeletonData = skeletonBinary.readSkeletonData(binary); } this.skeleton = new Skeleton(skeletonData); /** @type {?} */ var stateData = new AnimationStateData(skeletonData); stateData.defaultMix = this.defaultMix; this.animationState = new AnimationState(stateData); /// Setup skin if (skeletonData.skins.length > 0) { this.skins = skeletonData.skins.map((/** * @param {?} s * @return {?} */ function (s) { return s.name; })); } else { throw new Error(""); } if (this.skin) { if (!this.skins.includes(this.skin)) { throw new Error(""); } this.skeleton.setSkinByName(this.skin); this.skeleton.setSlotsToSetupPose(); } else { this.skin = this.skins[0]; } /// Setup animations if (skeletonData.animations.length > 0) { this.animations = skeletonData.animations.map((/** * @param {?} a * @return {?} */ function (a) { return a.name; })); } if (this.animation) { if (!this.animations.includes(this.animation)) { throw new Error(""); } } else { this.animation = this.animations[0]; } this.play(); }; /** * @param {?=} requestNextFrame * @return {?} */ NgxSpineWebglComponent.prototype.drawFrame = /** * @param {?=} requestNextFrame * @return {?} */ function (requestNextFrame) { var _this = this; if (requestNextFrame === void 0) { requestNextFrame = true; } if (requestNextFrame) { requestAnimationFrame((/** * @return {?} */ function () { return _this.drawFrame(); })); } /** @type {?} */ var gl = this.context.gl; gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); // Resize the canvas this.sceneRenderer.resize(ResizeMode.Expand); // Update animation and skeleton if (!this.paused && this.animation) { this.time.update(); /** @type {?} */ var delta = this.time.delta * this.speed; /** @type {?} */ var animationDuration = this.animationState.getCurrent(0).animation .duration; this.playTime += delta; while (this.playTime >= animationDuration && animationDuration !== 0) { this.playTime -= animationDuration; } this.playTime = Math.max(0, Math.min(this.playTime, animationDuration)); // this.timelineSlider.setValue(this.playTime / animationDuration); this.animationState.update(delta); this.animationState.apply(this.skeleton); } this.skeleton.updateWorldTransform(); /** @type {?} */ var viewport = { x: this.currentViewport.x - ((/** @type {?} */ (this.currentViewport.padLeft))), y: this.currentViewport.y - ((/** @type {?} */ (this.currentViewport.padBottom))), width: this.currentViewport.width + ((/** @type {?} */ (this.currentViewport.padLeft))) + ((/** @type {?} */ (this.currentViewport.padRight))), height: this.currentViewport.height + ((/** @type {?} */ (this.currentViewport.padBottom))) + ((/** @type {?} */ (this.currentViewport.padTop))) }; /** @type {?} */ var transitionAlpha = (performance.now() - this.viewportTransitionStart) / 1000 / this.transitionTime; if (this.previousViewport && transitionAlpha < 1) { /** @type {?} */ var oldViewport = { x: this.previousViewport.x - ((/** @type {?} */ (this.previousViewport.padLeft))), y: this.previousViewport.y - ((/** @type {?} */ (this.previousViewport.padBottom))), width: this.previousViewport.width + ((/** @type {?} */ (this.previousViewport.padLeft))) + ((/** @type {?} */ (this.previousViewport.padRight))), height: this.previousViewport.height + ((/** @type {?} */ (this.previousViewport.padBottom))) + ((/** @type {?} */ (this.previousViewport.padTop))) }; viewport = { x: oldViewport.x + (viewport.x - oldViewport.x) * transitionAlpha, y: oldViewport.y + (viewport.y - oldViewport.y) * transitionAlpha, width: oldViewport.width + (viewport.width - oldViewport.width) * transitionAlpha, height: oldViewport.height + (viewport.height - oldViewport.height) * transitionAlpha }; } /** @type {?} */ var viewportSize = this.scale(viewport.width, viewport.height, this.canvas.nativeElement.width, this.canvas.nativeElement.height); this.sceneRenderer.camera.zoom = viewport.width / viewportSize.x; this.sceneRenderer.camera.position.x = viewport.x + viewport.width / 2; this.sceneRenderer.camera.position.y = viewport.y + viewport.height / 2; this.sceneRenderer.begin(); this.sceneRenderer.drawSkeleton(this.skeleton, this.premultipliedAlpha); this.sceneRenderer.end(); this.sceneRenderer.camera.zoom = 0; }; /** * @private * @return {?} */ NgxSpineWebglComponent.prototype.play = /** * @private * @return {?} */ function () { this.paused = false; this.setAnimation(this.animation); }; /** * @private * @return {?} */ NgxSpineWebglComponent.prototype.pause = /** * @private * @return {?} */ function () { this.paused = true; }; /** * @param {?} animation * @return {?} */ NgxSpineWebglComponent.prototype.setAnimation = /** * @param {?} animation * @return {?} */ function (animation) { // Determine viewport this.previousViewport = this.currentViewport; /** @type {?} */ var animViewport = this.calculateAnimationViewport(animation); // The calculated animation viewport is the base /** @type {?} */ var viewport = { x: animViewport.x, y: animViewport.y, width: animViewport.width, height: animViewport.height, padLeft: "10%", padRight: "10%", padTop: "10%", padBottom: "10%" }; // Translate percentage paddings to world units viewport.padLeft = this.percentageToWorldUnit(viewport.width, viewport.padLeft); viewport.padRight = this.percentageToWorldUnit(viewport.width, viewport.padRight); viewport.padBottom = this.percentageToWorldUnit(viewport.height, viewport.padBottom); viewport.padTop = this.percentageToWorldUnit(viewport.height, viewport.padTop); // Adjust x, y, width, and height by padding. this.currentViewport = viewport; this.viewportTransitionStart = performance.now(); this.animationState.clearTracks(); this.skeleton.setToSetupPose(); this.animationState.setAnimation(0, animation, true); }; /** * @private * @param {?} size * @param {?} percentageOrAbsolute * @return {?} */ NgxSpineWebglComponent.prototype.percentageToWorldUnit = /** * @private * @param {?} size * @param {?} percentageOrAbsolute * @return {?} */ function (size, percentageOrAbsolute) { if (typeof percentageOrAbsolute === "string") { return ((size * parseFloat(percentageOrAbsolute.substr(0, percentageOrAbsolute.length - 1))) / 100); } else { return percentageOrAbsolute; } }; /** * @private * @param {?} animationName * @return {?} */ NgxSpineWebglComponent.prototype.calculateAnimationViewport = /** * @private * @param {?} animationName * @return {?} */ function (animationName) { /** @type {?} */ var animation = this.skeleton.data.findAnimation(animationName); this.animationState.clearTracks(); this.skeleton.setToSetupPose(); this.animationState.setAnimationWith(0, animation, true); /** @type {?} */ var steps = 100; /** @type {?} */ var stepTime = animation.duration > 0 ? animation.duration / steps : 0; /** @type {?} */ var offset = new Vector2(); /** @type {?} */ var size = new Vector2(); /** @type {?} */ var minX = 100000000; /** @type {?} */ var maxX = -100000000; /** @type {?} */ var minY = 100000000; /** @type {?} */ var maxY = -100000000; for (var i = 0; i < steps; i++) { this.animationState.update(stepTime); this.animationState.apply(this.skeleton); this.skeleton.updateWorldTransform(); this.skeleton.getBounds(offset, size); minX = Math.min(offset.x, minX); maxX = Math.max(offset.x + size.x, maxX); minY = Math.min(offset.y, minY); maxY = Math.max(offset.y + size.y, maxY); } offset.x = minX; offset.y = minY; size.x = maxX - minX; size.y = maxY - minY; return { x: offset.x, y: offset.y, width: size.x, height: size.y }; }; /** * @private * @param {?} sourceWidth * @param {?} sourceHeight * @param {?} targetWidth * @param {?} targetHeight * @return {?} */ NgxSpineWebglComponent.prototype.scale = /** * @private * @param {?} sourceWidth * @param {?} sourceHeight * @param {?} targetWidth * @param {?} targetHeight * @return {?} */ function (sourceWidth, sourceHeight, targetWidth, targetHeight) { /** @type {?} */ var targetRatio = targetHeight / targetWidth; /** @type {?} */ var sourceRatio = sourceHeight / sourceWidth; /** @type {?} */ var scale = targetRatio > sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; /** @type {?} */ var temp = new Vector2(); temp.x = sourceWidth * scale; temp.y = sourceHeight * scale; return temp; }; NgxSpineWebglComponent.decorators = [ { type: Component, args: [{ selector: "ngx-spine-webgl", template: "\n <canvas class=\"ngx-spine-webgl\" #canvas></canvas>\n", changeDetection: ChangeDetectionStrategy.OnPush }] } ]; NgxSpineWebglComponent.propDecorators = { dataUrls: [{ type: Input }], defaultMix: [{ type: Input }], premultipliedAlpha: [{ type: Input }], transitionTime: [{ type: Input }], speed: [{ type: Input }], canvas: [{ type: ViewChild, args: ["canvas", { static: true, read: ElementRef },] }], animationChange: [{ type: Output }], animation: [{ type: Input }], animationsChange: [{ type: Output }], animations: [{ type: Input }], skinChange: [{ type: Output }], skin: [{ type: Input }], skinsChange: [{ type: Output }], skins: [{ type: Input }], loaded: [{ type: Output }] }; return NgxSpineWebglComponent; }()); export { NgxSpineWebglComponent }; if (false) { /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.urls; /** @type {?} */ NgxSpineWebglComponent.prototype.defaultMix; /** @type {?} */ NgxSpineWebglComponent.prototype.premultipliedAlpha; /** @type {?} */ NgxSpineWebglComponent.prototype.transitionTime; /** @type {?} */ NgxSpineWebglComponent.prototype.speed; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.canvas; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.animationValue; /** @type {?} */ NgxSpineWebglComponent.prototype.animationChange; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.animationsValue; /** @type {?} */ NgxSpineWebglComponent.prototype.animationsChange; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.skinValue; /** @type {?} */ NgxSpineWebglComponent.prototype.skinChange; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.skinsValue; /** @type {?} */ NgxSpineWebglComponent.prototype.skinsChange; /** @type {?} */ NgxSpineWebglComponent.prototype.loaded; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.sceneRenderer; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.context; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.assetManager; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.skeleton; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.animationState; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.time; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.paused; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.playTime; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.currentViewport; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.previousViewport; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.viewportTransitionStart; /** * @type {?} * @private */ NgxSpineWebglComponent.prototype.init; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNwaW5lLXdlYmdsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1zcGluZS8iLCJzb3VyY2VzIjpbImxpYi9uZ3gtc3BpbmUtd2ViZ2wuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osU0FBUyxFQUNULFNBQVMsRUFDVCxVQUFVLEVBRVYsdUJBQXVCLEVBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFDTCxZQUFZLEVBQ1osYUFBYSxFQUNiLDRCQUE0QixFQUM1QixVQUFVLEVBQ1gsTUFBTSxrQkFBa0IsQ0FBQztBQUUxQixPQUFPLEVBQ0wsVUFBVSxFQUNWLFFBQVEsRUFDUixjQUFjLEVBRWQscUJBQXFCLEVBQ3JCLFlBQVksRUFDWixjQUFjLEVBQ2Qsa0JBQWtCLEVBQ2xCLE9BQU8sRUFDUixNQUFNLGlCQUFpQixDQUFDOzs7O0FBRXpCLHVCQVNDOzs7SUFSQyxxQkFBVTs7SUFDVixxQkFBVTs7SUFDVix5QkFBYzs7SUFDZCwwQkFBZTs7SUFDZiwyQkFBeUI7O0lBQ3pCLDRCQUEwQjs7SUFDMUIsMEJBQXdCOztJQUN4Qiw2QkFBMkI7Ozs7O0FBRzdCLHVCQVNDOzs7SUFQQyx3QkFBYzs7SUFHZCx3QkFBYzs7SUFHZCx5QkFBYzs7QUFHaEI7SUFBQTs7UUF1Q1csZUFBVSxHQUFHLElBQUksQ0FBQzs7UUFHbEIsdUJBQWtCLEdBQUcsSUFBSSxDQUFDO1FBRTFCLG1CQUFjLEdBQUcsR0FBRyxDQUFDO1FBRXJCLFVBQUssR0FBRyxDQUFDLENBQUM7O1FBTVgsbUJBQWMsR0FBRyxJQUFJLENBQUM7UUFFcEIsb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDOztRQWtCdkMsb0JBQWUsR0FBRyxFQUFFLENBQUM7UUFFbkIscUJBQWdCLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQzs7UUFheEMsY0FBUyxHQUFHLElBQUks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QWtCL0MsaURBQTZCOztJQUU3QixrREFBZ0Q7Ozs7O0lBYWhELDJDQUF5Qjs7SUFFekIsNENBQTBDOzs7OztJQWtCMUMsNENBQXdCOztJQUV4Qiw2Q0FBMkM7O0lBWTNDLHdDQUErQzs7Ozs7SUFFL0MsK0NBQXFDOzs7OztJQUNyQyx5Q0FBOEM7Ozs7O0lBQzlDLDhDQUFtQzs7Ozs7SUFDbkMsMENBQTJCOzs7OztJQUMzQixnREFBdUM7Ozs7O0lBQ3ZDLHNDQUFnQzs7Ozs7SUFDaEMsd0NBQXNCOzs7OztJQUN0QiwwQ0FBcUI7Ozs7O0lBQ3JCLGlEQUF5Qzs7Ozs7SUFDekMsa0RBQTBDOzs7OztJQUMxQyx5REFBb0M7Ozs7O0lBQ3BDLHNDQUFxQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgVmlld0NoaWxkLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5XG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5cbmltcG9ydCB7XG4gIEFzc2V0TWFuYWdlcixcbiAgU2NlbmVSZW5kZXJlcixcbiAgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCxcbiAgUmVzaXplTW9kZVxufSBmcm9tIFwiLi9zcGluZS10cy93ZWJnbFwiO1xuXG5pbXBvcnQge1xuICBUaW1lS2VlcGVyLFxuICBTa2VsZXRvbixcbiAgQW5pbWF0aW9uU3RhdGUsXG4gIFNrZWxldG9uRGF0YSxcbiAgQXRsYXNBdHRhY2htZW50TG9hZGVyLFxuICBTa2VsZXRvbkpzb24sXG4gIFNrZWxldG9uQmluYXJ5LFxuICBBbmltYXRpb25TdGF0ZURhdGEsXG4gIFZlY3RvcjJcbn0gZnJvbSBcIi4vc3BpbmUtdHMvY29yZVwiO1xuXG5pbnRlcmZhY2UgVmlld3BvcnQge1xuICB4OiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG4gIHBhZExlZnQ6IHN0cmluZyB8IG51bWJlcjtcbiAgcGFkUmlnaHQ6IHN0cmluZyB8IG51bWJlcjtcbiAgcGFkVG9wOiBzdHJpbmcgfCBudW1iZXI7XG4gIHBhZEJvdHRvbTogc3RyaW5nIHwgbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgRGF0YVVybHMge1xuICAvKiB0aGUgVVJMIG9mIHRoZSBza2VsZXRvbiAuanNvbiBmaWxlICovXG4gIGpzb24/OiBzdHJpbmc7XG5cbiAgLyogdGhlIFVSTCBvZiB0aGUgc2tlbGV0b24gLnNrZWwgZmlsZSAqL1xuICBza2VsPzogc3RyaW5nO1xuXG4gIC8qIHRoZSBVUkwgb2YgdGhlIHNrZWxldG9uIC5hdGxhcyBmaWxlLiBBdGxhcyBwYWdlIGltYWdlcyBhcmUgYXV0b21hdGljYWxseSByZXNvbHZlZC4gKi9cbiAgYXRsYXM6IHN0cmluZztcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcIm5neC1zcGluZS13ZWJnbFwiLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxjYW52YXMgY2xhc3M9XCJuZ3gtc3BpbmUtd2ViZ2xcIiAjY2FudmFzPjwvY2FudmFzPlxuYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgTmd4U3BpbmVXZWJnbENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuICBwcml2YXRlIHVybHM6IERhdGFVcmxzO1xuXG4gIGdldCBkYXRhVXJscygpOiBEYXRhVXJscyB7XG4gICAgcmV0dXJuIHRoaXMudXJscztcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHNldCBkYXRhVXJscyh1cmxzOiBEYXRhVXJscykge1xuICAgIHRoaXMudXJscyA9IHVybHM7XG5cbiAgICBpZiAoIXRoaXMudXJscy5qc29uICYmICF0aGlzLnVybHMuc2tlbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlBsZWFzZSBzcGVjaWZ5IHRoZSBVUkwgb2YgdGhlIHNrZWxldG9uIEpTT04gb3IgLnNrZWwgZmlsZS5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnVybHMuYXRsYXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlBsZWFzZSBzcGVjaWZ5IHRoZSBVUkwgb2YgdGhlIGF0bGFzIGZpbGUuXCIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmluaXQpIHtcbiAgICAgIHRoaXMubG9hZGVkLmVtaXQoZmFsc2UpO1xuICAgICAgdGhpcy5sb2FkQXNzZXQoKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coXCJsb2FkIGFzc2V0c1wiKTtcbiAgICAgICAgdGhpcy5sb2FkU2tlbGV0b24oKTtcbiAgICAgICAgdGhpcy5sb2FkZWQuZW1pdCh0cnVlKTtcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuZHJhd0ZyYW1lKCkpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyogT3B0aW9uYWw6IHRoZSBkZWZhdWx0IG1peCB0aW1lIHVzZWQgdG8gc3dpdGNoIGJldHdlZW4gdHdvIGFuaW1hdGlvbnMuICovXG4gIEBJbnB1dCgpIGRlZmF1bHRNaXggPSAwLjI1O1xuXG4gIC8qIE9wdGlvbmFsOiB3aGV0aGVyIHRoZSBza2VsZXRvbiB1c2VzIHByZW11bHRpcGxpZWQgYWxwaGEuIERlZmF1bHQ6IHRydWUuICovXG4gIEBJbnB1dCgpIHByZW11bHRpcGxpZWRBbHBoYSA9IHRydWU7XG5cbiAgQElucHV0KCkgdHJhbnNpdGlvblRpbWUgPSAwLjI7XG5cbiAgQElucHV0KCkgc3BlZWQgPSAxO1xuXG4gIEBWaWV3Q2hpbGQoXCJjYW52YXNcIiwgeyBzdGF0aWM6IHRydWUsIHJlYWQ6IEVsZW1lbnRSZWYgfSlcbiAgcHJpdmF0ZSBjYW52YXM6IEVsZW1lbnRSZWY7XG5cbiAgLy8gVGhlIG5hbWUgb2YgdGhlIGFuaW1hdGlvbiB0byBiZSBwbGF5ZWQuIERlZmF1bHQ6IGZpcnN0IGFuaW1hdGlvbiBpbiB0aGUgc2tlbGV0b24uXG4gIHByaXZhdGUgYW5pbWF0aW9uVmFsdWUgPSBudWxsO1xuXG4gIEBPdXRwdXQoKSBhbmltYXRpb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQElucHV0KClcbiAgc2V0IGFuaW1hdGlvbih2YWw6IHN0cmluZykge1xuICAgIHRoaXMuYW5pbWF0aW9uVmFsdWUgPSB2YWw7XG4gICAgdGhpcy5hbmltYXRpb25DaGFuZ2UuZW1pdCh2YWwpO1xuXG4gICAgaWYgKHRoaXMuc2tlbGV0b24gJiYgdGhpcy5hbmltYXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucGxheVRpbWUgPSAwO1xuICAgICAgdGhpcy5zZXRBbmltYXRpb24odmFsKTtcbiAgICB9XG4gIH1cblxuICBnZXQgYW5pbWF0aW9uKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYW5pbWF0aW9uVmFsdWU7XG4gIH1cblxuICAvKiBPcHRpb25hbDogbGlzdCBvZiBhbmltYXRpb24gbmFtZXMgZnJvbSB3aGljaCB0aGUgdXNlciBjYW4gY2hvb3NlLiAqL1xuICBwcml2YXRlIGFuaW1hdGlvbnNWYWx1ZSA9IFtdO1xuXG4gIEBPdXRwdXQoKSBhbmltYXRpb25zQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBJbnB1dCgpXG4gIHNldCBhbmltYXRpb25zKHZhbDogc3RyaW5nW10pIHtcbiAgICB0aGlzLmFuaW1hdGlvbnNWYWx1ZSA9IHZhbDtcbiAgICB0aGlzLmFuaW1hdGlvbnNDaGFuZ2UuZW1pdCh2YWwpO1xuICB9XG5cbiAgZ2V0IGFuaW1hdGlvbnMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmFuaW1hdGlvbnNWYWx1ZTtcbiAgfVxuXG4gIC8qIE9wdGlvbmFsOiB0aGUgbmFtZSBvZiB0aGUgc2tpbiB0byBiZSBzZXQuIERlZmF1bHQ6IHRoZSBkZWZhdWx0IHNraW4uICovXG4gIHByaXZhdGUgc2tpblZhbHVlID0gbnVsbDtcblxuICBAT3V0cHV0KCkgc2tpbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBASW5wdXQoKVxuICBzZXQgc2tpbih2YWw6IHN0cmluZykge1xuICAgIHRoaXMuc2tpblZhbHVlID0gdmFsO1xuICAgIHRoaXMuc2tpbkNoYW5nZS5lbWl0KHRoaXMuc2tpblZhbHVlKTtcblxuICAgIGlmICh0aGlzLnNrZWxldG9uICYmIHRoaXMuYW5pbWF0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNrZWxldG9uLnNldFNraW5CeU5hbWUodmFsKTtcbiAgICAgIHRoaXMuc2tlbGV0b24uc2V0U2xvdHNUb1NldHVwUG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBza2luKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2tpblZhbHVlO1xuICB9XG5cbiAgLyogT3B0aW9uYWw6IGxpc3Qgb2Ygc2tpbiBuYW1lcyBmcm9tIHdoaWNoIHRoZSB1c2VyIGNhbiBjaG9vc2UuICovXG4gIHByaXZhdGUgc2tpbnNWYWx1ZSA9IFtdO1xuXG4gIEBPdXRwdXQoKSBza2luc0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBASW5wdXQoKVxuICBzZXQgc2tpbnModmFsOiBzdHJpbmdbXSkge1xuICAgIHRoaXMuc2tpbnNWYWx1ZSA9IHZhbDtcbiAgICB0aGlzLnNraW5zQ2hhbmdlLmVtaXQodmFsKTtcbiAgfVxuXG4gIGdldCBza2lucygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuc2tpbnNWYWx1ZTtcbiAgfVxuXG4gIEBPdXRwdXQoKSBsb2FkZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgcHJpdmF0ZSBzY2VuZVJlbmRlcmVyOiBTY2VuZVJlbmRlcmVyO1xuICBwcml2YXRlIGNvbnRleHQ6IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG4gIHByaXZhdGUgYXNzZXRNYW5hZ2VyOiBBc3NldE1hbmFnZXI7XG4gIHByaXZhdGUgc2tlbGV0b246IFNrZWxldG9uO1xuICBwcml2YXRlIGFuaW1hdGlvblN0YXRlOiBBbmltYXRpb25TdGF0ZTtcbiAgcHJpdmF0ZSB0aW1lID0gbmV3IFRpbWVLZWVwZXIoKTtcbiAgcHJpdmF0ZSBwYXVzZWQgPSB0cnVlO1xuICBwcml2YXRlIHBsYXlUaW1lID0gMDtcbiAgcHJpdmF0ZSBjdXJyZW50Vmlld3BvcnQ6IFZpZXdwb3J0ID0gbnVsbDtcbiAgcHJpdmF0ZSBwcmV2aW91c1ZpZXdwb3J0OiBWaWV3cG9ydCA9IG51bGw7XG4gIHByaXZhdGUgdmlld3BvcnRUcmFuc2l0aW9uU3RhcnQgPSAwO1xuICBwcml2YXRlIGluaXQgPSBmYWxzZTtcblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5sb2FkZWQuZW1pdChmYWxzZSk7XG4gICAgLy8gd2ViZ2wgc2V0dXBcbiAgICB0aGlzLmNvbnRleHQgPSBuZXcgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCh0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LCB7XG4gICAgICBhbHBoYTogdHJ1ZVxuICAgIH0pO1xuICAgIHRoaXMuc2NlbmVSZW5kZXJlciA9IG5ldyBTY2VuZVJlbmRlcmVyKFxuICAgICAgdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudCxcbiAgICAgIHRoaXMuY29udGV4dCxcbiAgICAgIHRydWVcbiAgICApO1xuXG4gICAgLy8gbG9hZCB0aGUgYXNzZXRzXG4gICAgdGhpcy5hc3NldE1hbmFnZXIgPSBuZXcgQXNzZXRNYW5hZ2VyKHRoaXMuY29udGV4dCk7XG5cbiAgICB0aGlzLmluaXQgPSB0cnVlO1xuXG4gICAgdGhpcy5sb2FkQXNzZXQoKS50aGVuKCgpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKFwibG9hZCBhc3NldHNcIik7XG4gICAgICB0aGlzLmxvYWRTa2VsZXRvbigpO1xuICAgICAgdGhpcy5sb2FkZWQuZW1pdCh0cnVlKTtcbiAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLmRyYXdGcmFtZSgpKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbG9hZEFzc2V0KCkge1xuICAgIGNvbnN0IHByb21pc2VzID0gW107XG4gICAgcHJvbWlzZXMucHVzaChcbiAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5hc3NldE1hbmFnZXIubG9hZFRleHR1cmVBdGxhcyhcbiAgICAgICAgICB0aGlzLmRhdGFVcmxzLmF0bGFzLFxuICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgcmVqZWN0XG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG4gICAgaWYgKHRoaXMuZGF0YVVybHMuanNvbikge1xuICAgICAgcHJvbWlzZXMucHVzaChcbiAgICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIHRoaXMuYXNzZXRNYW5hZ2VyLmxvYWRUZXh0KHRoaXMuZGF0YVVybHMuanNvbiwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2VzLnB1c2goXG4gICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICB0aGlzLmFzc2V0TWFuYWdlci5sb2FkQmluYXJ5KHRoaXMuZGF0YVVybHMuc2tlbCwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIH1cblxuICBwcml2YXRlIGxvYWRTa2VsZXRvbigpIHtcbiAgICBjb25zdCBhdGxhcyA9IHRoaXMuYXNzZXRNYW5hZ2VyLmdldCh0aGlzLmRhdGFVcmxzLmF0bGFzKTtcbiAgICBsZXQgc2tlbGV0b25EYXRhOiBTa2VsZXRvbkRhdGE7XG5cbiAgICBpZiAodGhpcy5kYXRhVXJscy5qc29uKSB7XG4gICAgICBjb25zdCBqc29uID0gdGhpcy5hc3NldE1hbmFnZXIuZ2V0KHRoaXMuZGF0YVVybHMuanNvbik7XG4gICAgICBjb25zdCBza2VsZXRvbkpzb24gPSBuZXcgU2tlbGV0b25Kc29uKG5ldyBBdGxhc0F0dGFjaG1lbnRMb2FkZXIoYXRsYXMpKTtcbiAgICAgIHNrZWxldG9uRGF0YSA9IHNrZWxldG9uSnNvbi5yZWFkU2tlbGV0b25EYXRhKGpzb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBiaW5hcnkgPSB0aGlzLmFzc2V0TWFuYWdlci5nZXQodGhpcy5kYXRhVXJ