UNPKG

@esotericsoftware/spine-webgl

Version:
113 lines 17.3 kB
/****************************************************************************** * Spine Runtimes License Agreement * Last updated April 5, 2025. Replaces all prior versions. * * Copyright (c) 2013-2025, Esoteric Software LLC * * Integration of the Spine Runtimes into software or otherwise creating * derivative works of the Spine Runtimes is permitted under the terms and * conditions of Section 2 of the Spine Editor License Agreement: * http://esotericsoftware.com/spine-editor-license * * Otherwise, it is permitted to integrate the Spine Runtimes into software * or otherwise create derivative works of the Spine Runtimes (collectively, * "Products"), provided that each user of the Products must obtain their own * Spine Editor license and redistribution of the Products in any form must * include this license and copyright notice. * * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ import { AssetManager, Input, ManagedWebGLRenderingContext, SceneRenderer, TimeKeeper } from "./index.js"; /** Manages the life-cycle and WebGL context of a {@link SpineCanvasApp}. The app loads * assets and initializes itself, then updates and renders its state at the screen refresh rate. */ export class SpineCanvas { config; context; /** Tracks the current time, delta, and other time related statistics. */ time = new TimeKeeper(); /** The HTML canvas to render to. */ htmlCanvas; /** The WebGL rendering context. */ gl; /** The scene renderer for easy drawing of skeletons, shapes, and images. */ renderer; /** The asset manager to load assets with. */ assetManager; /** The input processor used to listen to mouse, touch, and keyboard events. */ input; disposed = false; /** Constructs a new spine canvas, rendering to the provided HTML canvas. */ constructor(canvas, config) { this.config = config; if (!config.pathPrefix) config.pathPrefix = ""; if (!config.app) config.app = { loadAssets: () => { }, initialize: () => { }, update: () => { }, render: () => { }, error: () => { }, dispose: () => { }, }; if (!config.webglConfig) config.webglConfig = { alpha: true }; this.htmlCanvas = canvas; this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); this.renderer = new SceneRenderer(canvas, this.context); this.gl = this.context.gl; this.assetManager = new AssetManager(this.context, config.pathPrefix); this.input = new Input(canvas); if (config.app.loadAssets) config.app.loadAssets(this); const loop = () => { if (this.disposed) return; requestAnimationFrame(loop); this.time.update(); if (config.app.update) config.app.update(this, this.time.delta); if (config.app.render) config.app.render(this); }; const waitForAssets = () => { if (this.disposed) return; if (this.assetManager.isLoadingComplete()) { if (this.assetManager.hasErrors()) { if (config.app.error) config.app.error(this, this.assetManager.getErrors()); } else { if (config.app.initialize) config.app.initialize(this); loop(); } return; } requestAnimationFrame(waitForAssets); }; requestAnimationFrame(waitForAssets); } /** Clears the canvas with the given color. The color values are given in the range [0,1]. */ clear(r, g, b, a) { this.gl.clearColor(r, g, b, a); this.gl.clear(this.gl.COLOR_BUFFER_BIT); } /** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/ dispose() { if (this.config.app.dispose) this.config.app.dispose(this); this.disposed = true; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVDYW52YXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU3BpbmVDYW52YXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLE9BQU8sRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLDRCQUE0QixFQUFFLGFBQWEsRUFBa0IsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBK0IxSDttR0FDbUc7QUFDbkcsTUFBTSxPQUFPLFdBQVc7SUFtQnlCO0lBbEJ2QyxPQUFPLENBQStCO0lBRS9DLHlFQUF5RTtJQUNoRSxJQUFJLEdBQUcsSUFBSSxVQUFVLEVBQUUsQ0FBQztJQUNqQyxvQ0FBb0M7SUFDM0IsVUFBVSxDQUFvQjtJQUN2QyxtQ0FBbUM7SUFDMUIsRUFBRSxDQUF3QjtJQUNuQyw0RUFBNEU7SUFDbkUsUUFBUSxDQUFnQjtJQUNqQyw2Q0FBNkM7SUFDcEMsWUFBWSxDQUFlO0lBQ3BDLCtFQUErRTtJQUN0RSxLQUFLLENBQVE7SUFFZCxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBRXpCLDRFQUE0RTtJQUM1RSxZQUFhLE1BQXlCLEVBQVUsTUFBeUI7UUFBekIsV0FBTSxHQUFOLE1BQU0sQ0FBbUI7UUFDeEUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVO1lBQUUsTUFBTSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHO1lBQUUsTUFBTSxDQUFDLEdBQUcsR0FBRztnQkFDN0IsVUFBVSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUM7Z0JBQ3JCLFVBQVUsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO2dCQUNyQixNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztnQkFDakIsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUM7Z0JBQ2pCLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO2dCQUNoQixPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQzthQUNsQixDQUFBO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXO1lBQUUsTUFBTSxDQUFDLFdBQVcsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUU5RCxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksNEJBQTRCLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RSxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEQsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFL0IsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVU7WUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUV2RCxNQUFNLElBQUksR0FBRyxHQUFHLEVBQUU7WUFDakIsSUFBSSxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBQzFCLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU07Z0JBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEUsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU07Z0JBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFBO1FBRUQsTUFBTSxhQUFhLEdBQUcsR0FBRyxFQUFFO1lBQzFCLElBQUksSUFBSSxDQUFDLFFBQVE7Z0JBQUUsT0FBTztZQUMxQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDO2dCQUMzQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQztvQkFDbkMsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUs7d0JBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztnQkFDN0UsQ0FBQztxQkFBTSxDQUFDO29CQUNQLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxVQUFVO3dCQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN2RCxJQUFJLEVBQUUsQ0FBQztnQkFDUixDQUFDO2dCQUNELE9BQU87WUFDUixDQUFDO1lBQ0QscUJBQXFCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDdEMsQ0FBQyxDQUFBO1FBQ0QscUJBQXFCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELDZGQUE2RjtJQUM3RixLQUFLLENBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUztRQUNoRCxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELGtIQUFrSDtJQUNsSCxPQUFPO1FBQ04sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPO1lBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7Q0FDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgQXByaWwgNSwgMjAyNS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDI1LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0ZcbiAqIFRIRSBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHsgQXNzZXRNYW5hZ2VyLCBJbnB1dCwgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgU2NlbmVSZW5kZXJlciwgdHlwZSBTdHJpbmdNYXAsIFRpbWVLZWVwZXIgfSBmcm9tIFwiLi9pbmRleC5qc1wiO1xuXG4vKiogQW4gYXBwIHJ1bm5pbmcgaW5zaWRlIGEge0BsaW5rIFNwaW5lQ2FudmFzfS4gVGhlIGFwcCBsaWZlLWN5Y2xlXG4gKiBpcyBhcyBmb2xsb3dzOlxuICpcbiAqIDEuIGBsb2FkQXNzZXRzKClgIGlzIGNhbGxlZC4gVGhlIGFwcCBjYW4gcXVldWUgYXNzZXRzIGZvciBsb2FkaW5nIHZpYSB7QGxpbmsgU3BpbmVDYW52YXMuYXNzZXRNYW5hZ2VyfS5cbiAqIDIuIGBpbml0aWFsaXplKClgIGlzIGNhbGxlZCB3aGVuIGFsbCBhc3NldHMgYXJlIGxvYWRlZC4gVGhlIGFwcCBjYW4gc2V0dXAgYW55dGhpbmcgaXQgbmVlZHMgdG8gZW50ZXIgdGhlIG1haW4gYXBwbGljYXRpb24gbG9naWMuXG4gKiAzLiBgdXBkYXRlKClgIGlzIGNhbGxlZCBwZXJpb2RpY2FsbHkgYXQgc2NyZWVuIHJlZnJlc2ggcmF0ZS4gVGhlIGFwcCBjYW4gdXBkYXRlIGl0cyBzdGF0ZS5cbiAqIDQuIGByZW5kZXIoKWAgaXMgY2FsbGVkIHBlcmlvZGljYWxseSBhdCBzY3JlZW4gcmVmcmVzaCByYXRlLiBUaGUgYXBwIGNhbiByZW5kZXIgaXRzIHN0YXRlIHZpYSB7QGxpbmsgU3BpbmVDYW52YXMucmVuZGVyZXJ9IG9yIGRpcmVjdGx5IHZpYSB0aGUgV2ViR0wgY29udGV4dCBpbiB7QGxpbmsgU3BpbmVDYW52YXMuZ2x9LlxuICpcbiAqIFRoZSBgZXJyb3IoKWAgbWV0aG9kIGlzIGNhbGxlZCBpbiBjYXNlIHRoZSBhc3NldHMgY291bGQgbm90IGJlIGxvYWRlZC4gVGhlIGBkaXNwb3NlKClgIG1ldGhvZCBpcyBjYWxsZWQgaW4gY2FzZSB0aGUgY2FudmFzIGhhcyBiZWVuIGRpc3Bvc2VkIHZpYSB7QGxpbmsgU3BpbmVDYW52YXMuZGlzcG9zZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3BpbmVDYW52YXNBcHAge1xuXHRsb2FkQXNzZXRzPyhjYW52YXM6IFNwaW5lQ2FudmFzKTogdm9pZDtcblx0aW5pdGlhbGl6ZT8oY2FudmFzOiBTcGluZUNhbnZhcyk6IHZvaWQ7XG5cdHVwZGF0ZT8oY2FudmFzOiBTcGluZUNhbnZhcywgZGVsdGE6IG51bWJlcik6IHZvaWQ7XG5cdHJlbmRlcj8oY2FudmFzOiBTcGluZUNhbnZhcyk6IHZvaWQ7XG5cdGVycm9yPyhjYW52YXM6IFNwaW5lQ2FudmFzLCBlcnJvcnM6IFN0cmluZ01hcDxzdHJpbmc+KTogdm9pZDtcblx0ZGlzcG9zZT8oY2FudmFzOiBTcGluZUNhbnZhcyk6IHZvaWQ7XG59XG5cbi8qKiBDb25maWd1cmF0aW9uIHBhc3NlZCB0byB0aGUge0BsaW5rIFNwaW5lQ2FudmFzfSBjb25zdHJ1Y3RvciAqL1xuZXhwb3J0IGludGVyZmFjZSBTcGluZUNhbnZhc0NvbmZpZyB7XG5cdC8qIFRoZSB7QGxpbmsgU3BpbmVDYW52YXNBcHB9IHRvIGJlIHJ1biBpbiB0aGUgY2FudmFzLiAqL1xuXHRhcHA6IFNwaW5lQ2FudmFzQXBwO1xuXHQvKiBUaGUgcGF0aCBwcmVmaXggdG8gYmUgdXNlZCBieSB0aGUge0BsaW5rIEFzc2V0TWFuYWdlcn0uICovXG5cdHBhdGhQcmVmaXg/OiBzdHJpbmc7XG5cdC8qIFRoZSBXZWJHTCBjb250ZXh0IGNvbmZpZ3VyYXRpb24gKi9cblx0d2ViZ2xDb25maWc/OiBXZWJHTENvbnRleHRBdHRyaWJ1dGVzO1xufVxuXG4vKiogTWFuYWdlcyB0aGUgbGlmZS1jeWNsZSBhbmQgV2ViR0wgY29udGV4dCBvZiBhIHtAbGluayBTcGluZUNhbnZhc0FwcH0uIFRoZSBhcHAgbG9hZHNcbiAqIGFzc2V0cyBhbmQgaW5pdGlhbGl6ZXMgaXRzZWxmLCB0aGVuIHVwZGF0ZXMgYW5kIHJlbmRlcnMgaXRzIHN0YXRlIGF0IHRoZSBzY3JlZW4gcmVmcmVzaCByYXRlLiAqL1xuZXhwb3J0IGNsYXNzIFNwaW5lQ2FudmFzIHtcblx0cmVhZG9ubHkgY29udGV4dDogTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcblxuXHQvKiogVHJhY2tzIHRoZSBjdXJyZW50IHRpbWUsIGRlbHRhLCBhbmQgb3RoZXIgdGltZSByZWxhdGVkIHN0YXRpc3RpY3MuICovXG5cdHJlYWRvbmx5IHRpbWUgPSBuZXcgVGltZUtlZXBlcigpO1xuXHQvKiogVGhlIEhUTUwgY2FudmFzIHRvIHJlbmRlciB0by4gKi9cblx0cmVhZG9ubHkgaHRtbENhbnZhczogSFRNTENhbnZhc0VsZW1lbnQ7XG5cdC8qKiBUaGUgV2ViR0wgcmVuZGVyaW5nIGNvbnRleHQuICovXG5cdHJlYWRvbmx5IGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cdC8qKiBUaGUgc2NlbmUgcmVuZGVyZXIgZm9yIGVhc3kgZHJhd2luZyBvZiBza2VsZXRvbnMsIHNoYXBlcywgYW5kIGltYWdlcy4gKi9cblx0cmVhZG9ubHkgcmVuZGVyZXI6IFNjZW5lUmVuZGVyZXI7XG5cdC8qKiBUaGUgYXNzZXQgbWFuYWdlciB0byBsb2FkIGFzc2V0cyB3aXRoLiAqL1xuXHRyZWFkb25seSBhc3NldE1hbmFnZXI6IEFzc2V0TWFuYWdlcjtcblx0LyoqIFRoZSBpbnB1dCBwcm9jZXNzb3IgdXNlZCB0byBsaXN0ZW4gdG8gbW91c2UsIHRvdWNoLCBhbmQga2V5Ym9hcmQgZXZlbnRzLiAqL1xuXHRyZWFkb25seSBpbnB1dDogSW5wdXQ7XG5cblx0cHJpdmF0ZSBkaXNwb3NlZCA9IGZhbHNlO1xuXG5cdC8qKiBDb25zdHJ1Y3RzIGEgbmV3IHNwaW5lIGNhbnZhcywgcmVuZGVyaW5nIHRvIHRoZSBwcm92aWRlZCBIVE1MIGNhbnZhcy4gKi9cblx0Y29uc3RydWN0b3IgKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHByaXZhdGUgY29uZmlnOiBTcGluZUNhbnZhc0NvbmZpZykge1xuXHRcdGlmICghY29uZmlnLnBhdGhQcmVmaXgpIGNvbmZpZy5wYXRoUHJlZml4ID0gXCJcIjtcblx0XHRpZiAoIWNvbmZpZy5hcHApIGNvbmZpZy5hcHAgPSB7XG5cdFx0XHRsb2FkQXNzZXRzOiAoKSA9PiB7IH0sXG5cdFx0XHRpbml0aWFsaXplOiAoKSA9PiB7IH0sXG5cdFx0XHR1cGRhdGU6ICgpID0+IHsgfSxcblx0XHRcdHJlbmRlcjogKCkgPT4geyB9LFxuXHRcdFx0ZXJyb3I6ICgpID0+IHsgfSxcblx0XHRcdGRpc3Bvc2U6ICgpID0+IHsgfSxcblx0XHR9XG5cdFx0aWYgKCFjb25maWcud2ViZ2xDb25maWcpIGNvbmZpZy53ZWJnbENvbmZpZyA9IHsgYWxwaGE6IHRydWUgfTtcblxuXHRcdHRoaXMuaHRtbENhbnZhcyA9IGNhbnZhcztcblx0XHR0aGlzLmNvbnRleHQgPSBuZXcgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dChjYW52YXMsIGNvbmZpZy53ZWJnbENvbmZpZyk7XG5cdFx0dGhpcy5yZW5kZXJlciA9IG5ldyBTY2VuZVJlbmRlcmVyKGNhbnZhcywgdGhpcy5jb250ZXh0KTtcblx0XHR0aGlzLmdsID0gdGhpcy5jb250ZXh0LmdsO1xuXHRcdHRoaXMuYXNzZXRNYW5hZ2VyID0gbmV3IEFzc2V0TWFuYWdlcih0aGlzLmNvbnRleHQsIGNvbmZpZy5wYXRoUHJlZml4KTtcblx0XHR0aGlzLmlucHV0ID0gbmV3IElucHV0KGNhbnZhcyk7XG5cblx0XHRpZiAoY29uZmlnLmFwcC5sb2FkQXNzZXRzKSBjb25maWcuYXBwLmxvYWRBc3NldHModGhpcyk7XG5cblx0XHRjb25zdCBsb29wID0gKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuZGlzcG9zZWQpIHJldHVybjtcblx0XHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZShsb29wKTtcblx0XHRcdHRoaXMudGltZS51cGRhdGUoKTtcblx0XHRcdGlmIChjb25maWcuYXBwLnVwZGF0ZSkgY29uZmlnLmFwcC51cGRhdGUodGhpcywgdGhpcy50aW1lLmRlbHRhKTtcblx0XHRcdGlmIChjb25maWcuYXBwLnJlbmRlcikgY29uZmlnLmFwcC5yZW5kZXIodGhpcyk7XG5cdFx0fVxuXG5cdFx0Y29uc3Qgd2FpdEZvckFzc2V0cyA9ICgpID0+IHtcblx0XHRcdGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm47XG5cdFx0XHRpZiAodGhpcy5hc3NldE1hbmFnZXIuaXNMb2FkaW5nQ29tcGxldGUoKSkge1xuXHRcdFx0XHRpZiAodGhpcy5hc3NldE1hbmFnZXIuaGFzRXJyb3JzKCkpIHtcblx0XHRcdFx0XHRpZiAoY29uZmlnLmFwcC5lcnJvcikgY29uZmlnLmFwcC5lcnJvcih0aGlzLCB0aGlzLmFzc2V0TWFuYWdlci5nZXRFcnJvcnMoKSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKGNvbmZpZy5hcHAuaW5pdGlhbGl6ZSkgY29uZmlnLmFwcC5pbml0aWFsaXplKHRoaXMpO1xuXHRcdFx0XHRcdGxvb3AoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUod2FpdEZvckFzc2V0cyk7XG5cdFx0fVxuXHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZSh3YWl0Rm9yQXNzZXRzKTtcblx0fVxuXG5cdC8qKiBDbGVhcnMgdGhlIGNhbnZhcyB3aXRoIHRoZSBnaXZlbiBjb2xvci4gVGhlIGNvbG9yIHZhbHVlcyBhcmUgZ2l2ZW4gaW4gdGhlIHJhbmdlIFswLDFdLiAqL1xuXHRjbGVhciAocjogbnVtYmVyLCBnOiBudW1iZXIsIGI6IG51bWJlciwgYTogbnVtYmVyKSB7XG5cdFx0dGhpcy5nbC5jbGVhckNvbG9yKHIsIGcsIGIsIGEpO1xuXHRcdHRoaXMuZ2wuY2xlYXIodGhpcy5nbC5DT0xPUl9CVUZGRVJfQklUKTtcblx0fVxuXG5cdC8qKiBEaXNwb3NlcyB0aGUgYXBwLCBzbyB0aGUgdXBkYXRlKCkgYW5kIHJlbmRlcigpIGZ1bmN0aW9ucyBhcmUgbm8gbG9uZ2VyIGNhbGxlZC4gQ2FsbHMgdGhlIGRpc3Bvc2UoKSBjYWxsYmFjay4qL1xuXHRkaXNwb3NlICgpIHtcblx0XHRpZiAodGhpcy5jb25maWcuYXBwLmRpc3Bvc2UpIHRoaXMuY29uZmlnLmFwcC5kaXNwb3NlKHRoaXMpO1xuXHRcdHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuXHR9XG59XG4iXX0=