UNPKG

ngx-spine

Version:

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

359 lines 35.2 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /****************************************************************************** * Spine Runtimes License Agreement * Last updated May 1, 2019. Replaces all prior versions. * * Copyright (c) 2013-2019, 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. * * THIS SOFTWARE IS 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 THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ import { Pool, Utils } from "./Utils"; import { BoundingBoxAttachment } from "./attachments/BoundingBoxAttachment"; export class SkeletonBounds { constructor() { this.minX = 0; this.minY = 0; this.maxX = 0; this.maxY = 0; this.boundingBoxes = new Array(); this.polygons = new Array(); this.polygonPool = new Pool((/** * @return {?} */ () => { return Utils.newFloatArray(16); })); } /** * @param {?} skeleton * @param {?} updateAabb * @return {?} */ update(skeleton, updateAabb) { if (skeleton == null) throw new Error("skeleton cannot be null."); /** @type {?} */ let boundingBoxes = this.boundingBoxes; /** @type {?} */ let polygons = this.polygons; /** @type {?} */ let polygonPool = this.polygonPool; /** @type {?} */ let slots = skeleton.slots; /** @type {?} */ let slotCount = slots.length; boundingBoxes.length = 0; polygonPool.freeAll(polygons); polygons.length = 0; for (let i = 0; i < slotCount; i++) { /** @type {?} */ let slot = slots[i]; if (!slot.bone.active) continue; /** @type {?} */ let attachment = slot.getAttachment(); if (attachment instanceof BoundingBoxAttachment) { /** @type {?} */ let boundingBox = (/** @type {?} */ (attachment)); boundingBoxes.push(boundingBox); /** @type {?} */ let polygon = polygonPool.obtain(); if (polygon.length != boundingBox.worldVerticesLength) { polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); } polygons.push(polygon); boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); } } if (updateAabb) { this.aabbCompute(); } else { this.minX = Number.POSITIVE_INFINITY; this.minY = Number.POSITIVE_INFINITY; this.maxX = Number.NEGATIVE_INFINITY; this.maxY = Number.NEGATIVE_INFINITY; } } /** * @return {?} */ aabbCompute() { /** @type {?} */ let minX = Number.POSITIVE_INFINITY; /** @type {?} */ let minY = Number.POSITIVE_INFINITY; /** @type {?} */ let maxX = Number.NEGATIVE_INFINITY; /** @type {?} */ let maxY = Number.NEGATIVE_INFINITY; /** @type {?} */ let polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) { /** @type {?} */ let polygon = polygons[i]; /** @type {?} */ let vertices = polygon; for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { /** @type {?} */ let x = vertices[ii]; /** @type {?} */ let y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); } } this.minX = minX; this.minY = minY; this.maxX = maxX; this.maxY = maxY; } /** * Returns true if the axis aligned bounding box contains the point. * @param {?} x * @param {?} y * @return {?} */ aabbContainsPoint(x, y) { return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; } /** * Returns true if the axis aligned bounding box intersects the line segment. * @param {?} x1 * @param {?} y1 * @param {?} x2 * @param {?} y2 * @return {?} */ aabbIntersectsSegment(x1, y1, x2, y2) { /** @type {?} */ let minX = this.minX; /** @type {?} */ let minY = this.minY; /** @type {?} */ let maxX = this.maxX; /** @type {?} */ let maxY = this.maxY; if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) return false; /** @type {?} */ let m = (y2 - y1) / (x2 - x1); /** @type {?} */ let y = m * (minX - x1) + y1; if (y > minY && y < maxY) return true; y = m * (maxX - x1) + y1; if (y > minY && y < maxY) return true; /** @type {?} */ let x = (minY - y1) / m + x1; if (x > minX && x < maxX) return true; x = (maxY - y1) / m + x1; if (x > minX && x < maxX) return true; return false; } /** * Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. * @param {?} bounds * @return {?} */ aabbIntersectsSkeleton(bounds) { return (this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY); } /** * Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more * efficient to only call this method if {\@link #aabbContainsPoint(float, float)} returns true. * @param {?} x * @param {?} y * @return {?} */ containsPoint(x, y) { /** @type {?} */ let polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) if (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i]; return null; } /** * Returns true if the polygon contains the point. * @param {?} polygon * @param {?} x * @param {?} y * @return {?} */ containsPointPolygon(polygon, x, y) { /** @type {?} */ let vertices = polygon; /** @type {?} */ let nn = polygon.length; /** @type {?} */ let prevIndex = nn - 2; /** @type {?} */ let inside = false; for (let ii = 0; ii < nn; ii += 2) { /** @type {?} */ let vertexY = vertices[ii + 1]; /** @type {?} */ let prevY = vertices[prevIndex + 1]; if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { /** @type {?} */ let vertexX = vertices[ii]; if (vertexX + ((y - vertexY) / (prevY - vertexY)) * (vertices[prevIndex] - vertexX) < x) inside = !inside; } prevIndex = ii; } return inside; } /** * Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it * is usually more efficient to only call this method if {\@link #aabbIntersectsSegment(float, float, float, float)} returns * true. * @param {?} x1 * @param {?} y1 * @param {?} x2 * @param {?} y2 * @return {?} */ intersectsSegment(x1, y1, x2, y2) { /** @type {?} */ let polygons = this.polygons; for (let i = 0, n = polygons.length; i < n; i++) if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i]; return null; } /** * Returns true if the polygon contains any part of the line segment. * @param {?} polygon * @param {?} x1 * @param {?} y1 * @param {?} x2 * @param {?} y2 * @return {?} */ intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { /** @type {?} */ let vertices = polygon; /** @type {?} */ let nn = polygon.length; /** @type {?} */ let width12 = x1 - x2; /** @type {?} */ let height12 = y1 - y2; /** @type {?} */ let det1 = x1 * y2 - y1 * x2; /** @type {?} */ let x3 = vertices[nn - 2]; /** @type {?} */ let y3 = vertices[nn - 1]; for (let ii = 0; ii < nn; ii += 2) { /** @type {?} */ let x4 = vertices[ii]; /** @type {?} */ let y4 = vertices[ii + 1]; /** @type {?} */ let det2 = x3 * y4 - y3 * x4; /** @type {?} */ let width34 = x3 - x4; /** @type {?} */ let height34 = y3 - y4; /** @type {?} */ let det3 = width12 * height34 - height12 * width34; /** @type {?} */ let x = (det1 * width34 - width12 * det2) / det3; if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) { /** @type {?} */ let y = (det1 * height34 - height12 * det2) / det3; if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true; } x3 = x4; y3 = y4; } return false; } /** * Returns the polygon for the specified bounding box, or null. * @param {?} boundingBox * @return {?} */ getPolygon(boundingBox) { if (boundingBox == null) throw new Error("boundingBox cannot be null."); /** @type {?} */ let index = this.boundingBoxes.indexOf(boundingBox); return index == -1 ? null : this.polygons[index]; } /** * @return {?} */ getWidth() { return this.maxX - this.minX; } /** * @return {?} */ getHeight() { return this.maxY - this.minY; } } if (false) { /** @type {?} */ SkeletonBounds.prototype.minX; /** @type {?} */ SkeletonBounds.prototype.minY; /** @type {?} */ SkeletonBounds.prototype.maxX; /** @type {?} */ SkeletonBounds.prototype.maxY; /** @type {?} */ SkeletonBounds.prototype.boundingBoxes; /** @type {?} */ SkeletonBounds.prototype.polygons; /** * @type {?} * @private */ SkeletonBounds.prototype.polygonPool; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25Cb3VuZHMuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtc3BpbmUvIiwic291cmNlcyI6WyJsaWIvc3BpbmUtdHMvY29yZS9Ta2VsZXRvbkJvdW5kcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCQSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN0QyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUc1RSxNQUFNLE9BQU8sY0FBYztJQUEzQjtRQUNFLFNBQUksR0FBRyxDQUFDLENBQUM7UUFDVCxTQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ1QsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULFNBQUksR0FBRyxDQUFDLENBQUM7UUFDVCxrQkFBYSxHQUFHLElBQUksS0FBSyxFQUF5QixDQUFDO1FBQ25ELGFBQVEsR0FBRyxJQUFJLEtBQUssRUFBcUIsQ0FBQztRQUNsQyxnQkFBVyxHQUFHLElBQUksSUFBSTs7O1FBQW9CLEdBQUcsRUFBRTtZQUNyRCxPQUFPLEtBQUssQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakMsQ0FBQyxFQUFDLENBQUM7SUFtTUwsQ0FBQzs7Ozs7O0lBbE1DLE1BQU0sQ0FBQyxRQUFrQixFQUFFLFVBQW1CO1FBQzVDLElBQUksUUFBUSxJQUFJLElBQUk7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7O1lBQzlELGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYTs7WUFDbEMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFROztZQUN4QixXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVc7O1lBQzlCLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSzs7WUFDdEIsU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNO1FBQzVCLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FB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QU8sQ0FBQyxXQUFXLENBQUM7UUFDbkQsT0FBTyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuRCxDQUFDOzs7O0lBQ0QsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQy9CLENBQUM7Ozs7SUFDRCxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDL0IsQ0FBQztDQUNGOzs7SUEzTUMsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsdUNBQW1EOztJQUNuRCxrQ0FBMEM7Ozs7O0lBQzFDLHFDQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxyXG4gKiBMYXN0IHVwZGF0ZWQgTWF5IDEsIDIwMTkuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cclxuICpcclxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTksIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xyXG4gKlxyXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcclxuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcclxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcclxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXHJcbiAqXHJcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxyXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXHJcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cclxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XHJcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWSBFWFBSRVNTXHJcbiAqIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVNcclxuICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU5cclxuICogTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsXHJcbiAqIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsXHJcbiAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUywgQlVTSU5FU1NcclxuICogSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWVxyXG4gKiBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkdcclxuICogTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLFxyXG4gKiBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG5pbXBvcnQgeyBQb29sLCBVdGlscyB9IGZyb20gXCIuL1V0aWxzXCI7XHJcbmltcG9ydCB7IEJvdW5kaW5nQm94QXR0YWNobWVudCB9IGZyb20gXCIuL2F0dGFjaG1lbnRzL0JvdW5kaW5nQm94QXR0YWNobWVudFwiO1xyXG5pbXBvcnQgeyBTa2VsZXRvbiB9IGZyb20gXCIuL1NrZWxldG9uXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgU2tlbGV0b25Cb3VuZHMge1xyXG4gIG1pblggPSAwO1xyXG4gIG1pblkgPSAwO1xyXG4gIG1heFggPSAwO1xyXG4gIG1heFkgPSAwO1xyXG4gIGJvdW5kaW5nQm94ZXMgPSBuZXcgQXJyYXk8Qm91bmRpbmdCb3hBdHRhY2htZW50PigpO1xyXG4gIHBvbHlnb25zID0gbmV3IEFycmF5PEFycmF5TGlrZTxudW1iZXI+PigpO1xyXG4gIHByaXZhdGUgcG9seWdvblBvb2wgPSBuZXcgUG9vbDxBcnJheUxpa2U8bnVtYmVyPj4oKCkgPT4ge1xyXG4gICAgcmV0dXJuIFV0aWxzLm5ld0Zsb2F0QXJyYXkoMTYpO1xyXG4gIH0pO1xyXG4gIHVwZGF0ZShza2VsZXRvbjogU2tlbGV0b24sIHVwZGF0ZUFhYmI6IGJvb2xlYW4pIHtcclxuICAgIGlmIChza2VsZXRvbiA9PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoXCJza2VsZXRvbiBjYW5ub3QgYmUgbnVsbC5cIik7XHJcbiAgICBsZXQgYm91bmRpbmdCb3hlcyA9IHRoaXMuYm91bmRpbmdCb3hlcztcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBsZXQgcG9seWdvblBvb2wgPSB0aGlzLnBvbHlnb25Qb29sO1xyXG4gICAgbGV0IHNsb3RzID0gc2tlbGV0b24uc2xvdHM7XHJcbiAgICBsZXQgc2xvdENvdW50ID0gc2xvdHMubGVuZ3RoO1xyXG4gICAgYm91bmRpbmdCb3hlcy5sZW5ndGggPSAwO1xyXG4gICAgcG9seWdvblBvb2wuZnJlZUFsbChwb2x5Z29ucyk7XHJcbiAgICBwb2x5Z29ucy5sZW5ndGggPSAwO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbG90Q291bnQ7IGkrKykge1xyXG4gICAgICBsZXQgc2xvdCA9IHNsb3RzW2ldO1xyXG4gICAgICBpZiAoIXNsb3QuYm9uZS5hY3RpdmUpIGNvbnRpbnVlO1xyXG4gICAgICBsZXQgYXR0YWNobWVudCA9IHNsb3QuZ2V0QXR0YWNobWVudCgpO1xyXG4gICAgICBpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIEJvdW5kaW5nQm94QXR0YWNobWVudCkge1xyXG4gICAgICAgIGxldCBib3VuZGluZ0JveCA9IGF0dGFjaG1lbnQgYXMgQm91bmRpbmdCb3hBdHRhY2htZW50O1xyXG4gICAgICAgIGJvdW5kaW5nQm94ZXMucHVzaChib3VuZGluZ0JveCk7XHJcbiAgICAgICAgbGV0IHBvbHlnb24gPSBwb2x5Z29uUG9vbC5vYnRhaW4oKTtcclxuICAgICAgICBpZiAocG9seWdvbi5sZW5ndGggIT0gYm91bmRpbmdCb3gud29ybGRWZXJ0aWNlc0xlbmd0aCkge1xyXG4gICAgICAgICAgcG9seWdvbiA9IFV0aWxzLm5ld0Zsb2F0QXJyYXkoYm91bmRpbmdCb3gud29ybGRWZXJ0aWNlc0xlbmd0aCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHBvbHlnb25zLnB1c2gocG9seWdvbik7XHJcbiAgICAgICAgYm91bmRpbmdCb3guY29tcHV0ZVdvcmxkVmVydGljZXMoXHJcbiAgICAgICAgICBzbG90LFxyXG4gICAgICAgICAgMCxcclxuICAgICAgICAgIGJvdW5kaW5nQm94LndvcmxkVmVydGljZXNMZW5ndGgsXHJcbiAgICAgICAgICBwb2x5Z29uLFxyXG4gICAgICAgICAgMCxcclxuICAgICAgICAgIDJcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodXBkYXRlQWFiYikge1xyXG4gICAgICB0aGlzLmFhYmJDb21wdXRlKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLm1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XHJcbiAgICAgIHRoaXMubWluWSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcclxuICAgICAgdGhpcy5tYXhYID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xyXG4gICAgICB0aGlzLm1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGFhYmJDb21wdXRlKCkge1xyXG4gICAgbGV0IG1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1pblkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1heFggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XHJcbiAgICBsZXQgcG9seWdvbnMgPSB0aGlzLnBvbHlnb25zO1xyXG4gICAgZm9yIChsZXQgaSA9IDAsIG4gPSBwb2x5Z29ucy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgbGV0IHBvbHlnb24gPSBwb2x5Z29uc1tpXTtcclxuICAgICAgbGV0IHZlcnRpY2VzID0gcG9seWdvbjtcclxuICAgICAgZm9yIChsZXQgaWkgPSAwLCBubiA9IHBvbHlnb24ubGVuZ3RoOyBpaSA8IG5uOyBpaSArPSAyKSB7XHJcbiAgICAgICAgbGV0IHggPSB2ZXJ0aWNlc1tpaV07XHJcbiAgICAgICAgbGV0IHkgPSB2ZXJ0aWNlc1tpaSArIDFdO1xyXG4gICAgICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCB4KTtcclxuICAgICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgeSk7XHJcbiAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHgpO1xyXG4gICAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCB5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5taW5YID0gbWluWDtcclxuICAgIHRoaXMubWluWSA9IG1pblk7XHJcbiAgICB0aGlzLm1heFggPSBtYXhYO1xyXG4gICAgdGhpcy5tYXhZID0gbWF4WTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBjb250YWlucyB0aGUgcG9pbnQuICovXHJcbiAgYWFiYkNvbnRhaW5zUG9pbnQoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcclxuICAgIHJldHVybiB4ID49IHRoaXMubWluWCAmJiB4IDw9IHRoaXMubWF4WCAmJiB5ID49IHRoaXMubWluWSAmJiB5IDw9IHRoaXMubWF4WTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBpbnRlcnNlY3RzIHRoZSBsaW5lIHNlZ21lbnQuICovXHJcbiAgYWFiYkludGVyc2VjdHNTZWdtZW50KHgxOiBudW1iZXIsIHkxOiBudW1iZXIsIHgyOiBudW1iZXIsIHkyOiBudW1iZXIpIHtcclxuICAgIGxldCBtaW5YID0gdGhpcy5taW5YO1xyXG4gICAgbGV0IG1pblkgPSB0aGlzLm1pblk7XHJcbiAgICBsZXQgbWF4WCA9IHRoaXMubWF4WDtcclxuICAgIGxldCBtYXhZID0gdGhpcy5tYXhZO1xyXG4gICAgaWYgKFxyXG4gICAgICAoeDEgPD0gbWluWCAmJiB4MiA8PSBtaW5YKSB8fFxyXG4gICAgICAoeTEgPD0gbWluWSAmJiB5MiA8PSBtaW5ZKSB8fFxyXG4gICAgICAoeDEgPj0gbWF4WCAmJiB4MiA+PSBtYXhYKSB8fFxyXG4gICAgICAoeTEgPj0gbWF4WSAmJiB5MiA+PSBtYXhZKVxyXG4gICAgKVxyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICBsZXQgbSA9ICh5MiAtIHkxKSAvICh4MiAtIHgxKTtcclxuICAgIGxldCB5ID0gbSAqIChtaW5YIC0geDEpICsgeTE7XHJcbiAgICBpZiAoeSA+IG1pblkgJiYgeSA8IG1heFkpIHJldHVybiB0cnVlO1xyXG4gICAgeSA9IG0gKiAobWF4WCAtIHgxKSArIHkxO1xyXG4gICAgaWYgKHkgPiBtaW5ZICYmIHkgPCBtYXhZKSByZXR1cm4gdHJ1ZTtcclxuICAgIGxldCB4ID0gKG1pblkgLSB5MSkgLyBtICsgeDE7XHJcbiAgICBpZiAoeCA+IG1pblggJiYgeCA8IG1heFgpIHJldHVybiB0cnVlO1xyXG4gICAgeCA9IChtYXhZIC0geTEpIC8gbSArIHgxO1xyXG4gICAgaWYgKHggPiBtaW5YICYmIHggPCBtYXhYKSByZXR1cm4gdHJ1ZTtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBpbnRlcnNlY3RzIHRoZSBheGlzIGFsaWduZWQgYm91bmRpbmcgYm94IG9mIHRoZSBzcGVjaWZpZWQgYm91bmRzLiAqL1xyXG4gIGFhYmJJbnRlcnNlY3RzU2tlbGV0b24oYm91bmRzOiBTa2VsZXRvbkJvdW5kcykge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdGhpcy5taW5YIDwgYm91bmRzLm1heFggJiZcclxuICAgICAgdGhpcy5tYXhYID4gYm91bmRzLm1pblggJiZcclxuICAgICAgdGhpcy5taW5ZIDwgYm91bmRzLm1heFkgJiZcclxuICAgICAgdGhpcy5tYXhZID4gYm91bmRzLm1pbllcclxuICAgICk7XHJcbiAgfVxyXG4gIC8qKiBSZXR1cm5zIHRoZSBmaXJzdCBib3VuZGluZyBib3ggYXR0YWNobWVudCB0aGF0IGNvbnRhaW5zIHRoZSBwb2ludCwgb3IgbnVsbC4gV2hlbiBkb2luZyBtYW55IGNoZWNrcywgaXQgaXMgdXN1YWxseSBtb3JlXHJcbiAgICogZWZmaWNpZW50IHRvIG9ubHkgY2FsbCB0aGlzIG1ldGhvZCBpZiB7QGxpbmsgI2FhYmJDb250YWluc1BvaW50KGZsb2F0LCBmbG9hdCl9IHJldHVybnMgdHJ1ZS4gKi9cclxuICBjb250YWluc1BvaW50KHg6IG51bWJlciwgeTogbnVtYmVyKTogQm91bmRpbmdCb3hBdHRhY2htZW50IHtcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IHBvbHlnb25zLmxlbmd0aDsgaSA8IG47IGkrKylcclxuICAgICAgaWYgKHRoaXMuY29udGFpbnNQb2ludFBvbHlnb24ocG9seWdvbnNbaV0sIHgsIHkpKVxyXG4gICAgICAgIHJldHVybiB0aGlzLmJvdW5kaW5nQm94ZXNbaV07XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcG9seWdvbiBjb250YWlucyB0aGUgcG9pbnQuICovXHJcbiAgY29udGFpbnNQb2ludFBvbHlnb24ocG9seWdvbjogQXJyYXlMaWtlPG51bWJlcj4sIHg6IG51bWJlciwgeTogbnVtYmVyKSB7XHJcbiAgICBsZXQgdmVydGljZXMgPSBwb2x5Z29uO1xyXG4gICAgbGV0IG5uID0gcG9seWdvbi5sZW5ndGg7XHJcbiAgICBsZXQgcHJldkluZGV4ID0gbm4gLSAyO1xyXG4gICAgbGV0IGluc2lkZSA9IGZhbHNlO1xyXG4gICAgZm9yIChsZXQgaWkgPSAwOyBpaSA8IG5uOyBpaSArPSAyKSB7XHJcbiAgICAgIGxldCB2ZXJ0ZXhZID0gdmVydGljZXNbaWkgKyAxXTtcclxuICAgICAgbGV0IHByZXZZID0gdmVydGljZXNbcHJldkluZGV4ICsgMV07XHJcbiAgICAgIGlmICgodmVydGV4WSA8IHkgJiYgcHJldlkgPj0geSkgfHwgKHByZXZZIDwgeSAmJiB2ZXJ0ZXhZID49IHkpKSB7XHJcbiAgICAgICAgbGV0IHZlcnRleFggPSB2ZXJ0aWNlc1tpaV07XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgdmVydGV4WCArXHJcbiAgICAgICAgICAgICgoeSAtIHZlcnRleFkpIC8gKHByZXZZIC0gdmVydGV4WSkpICpcclxuICAgICAgICAgICAgICAodmVydGljZXNbcHJldkluZGV4XSAtIHZlcnRleFgpIDxcclxuICAgICAgICAgIHhcclxuICAgICAgICApXHJcbiAgICAgICAgICBpbnNpZGUgPSAhaW5zaWRlO1xyXG4gICAgICB9XHJcbiAgICAgIHByZXZJbmRleCA9IGlpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGluc2lkZTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdGhlIGZpcnN0IGJvdW5kaW5nIGJveCBhdHRhY2htZW50IHRoYXQgY29udGFpbnMgYW55IHBhcnQgb2YgdGhlIGxpbmUgc2VnbWVudCwgb3IgbnVsbC4gV2hlbiBkb2luZyBtYW55IGNoZWNrcywgaXRcclxuICAgKiBpcyB1c3VhbGx5IG1vcmUgZWZmaWNpZW50IHRvIG9ubHkgY2FsbCB0aGlzIG1ldGhvZCBpZiB7QGxpbmsgI2FhYmJJbnRlcnNlY3RzU2VnbWVudChmbG9hdCwgZmxvYXQsIGZsb2F0LCBmbG9hdCl9IHJldHVybnNcclxuICAgKiB0cnVlLiAqL1xyXG4gIGludGVyc2VjdHNTZWdtZW50KHgxOiBudW1iZXIsIHkxOiBudW1iZXIsIHgyOiBudW1iZXIsIHkyOiBudW1iZXIpIHtcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IHBvbHlnb25zLmxlbmd0aDsgaSA8IG47IGkrKylcclxuICAgICAgaWYgKHRoaXMuaW50ZXJzZWN0c1NlZ21lbnRQb2x5Z29uKHBvbHlnb25zW2ldLCB4MSwgeTEsIHgyLCB5MikpXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYm91bmRpbmdCb3hlc1tpXTtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuICAvKiogUmV0dXJucyB0cnVlIGlmIHRoZSBwb2x5Z29uIGNvbnRhaW5zIGFueSBwYXJ0IG9mIHRoZSBsaW5lIHNlZ21lbnQuICovXHJcbiAgaW50ZXJzZWN0c1NlZ21lbnRQb2x5Z29uKFxyXG4gICAgcG9seWdvbjogQXJyYXlMaWtlPG51bWJlcj4sXHJcbiAgICB4MTogbnVtYmVyLFxyXG4gICAgeTE6IG51bWJlcixcclxuICAgIHgyOiBudW1iZXIsXHJcbiAgICB5MjogbnVtYmVyXHJcbiAgKSB7XHJcbiAgICBsZXQgdmVydGljZXMgPSBwb2x5Z29uO1xyXG4gICAgbGV0IG5uID0gcG9seWdvbi5sZW5ndGg7XHJcbiAgICBsZXQgd2lkdGgxMiA9IHgxIC0geDIsXHJcbiAgICAgIGhlaWdodDEyID0geTEgLSB5MjtcclxuICAgIGxldCBkZXQxID0geDEgKiB5MiAtIHkxICogeDI7XHJcbiAgICBsZXQgeDMgPSB2ZXJ0aWNlc1tubiAtIDJdLFxyXG4gICAgICB5MyA9IHZlcnRpY2VzW25uIC0gMV07XHJcbiAgICBmb3IgKGxldCBpaSA9IDA7IGlpIDwgbm47IGlpICs9IDIpIHtcclxuICAgICAgbGV0IHg0ID0gdmVydGljZXNbaWldLFxyXG4gICAgICAgIHk0ID0gdmVydGljZXNbaWkgKyAxXTtcclxuICAgICAgbGV0IGRldDIgPSB4MyAqIHk0IC0geTMgKiB4NDtcclxuICAgICAgbGV0IHdpZHRoMzQgPSB4MyAtIHg0LFxyXG4gICAgICAgIGhlaWdodDM0ID0geTMgLSB5NDtcclxuICAgICAgbGV0IGRldDMgPSB3aWR0aDEyICogaGVpZ2h0MzQgLSBoZWlnaHQxMiAqIHdpZHRoMzQ7XHJcbiAgICAgIGxldCB4ID0gKGRldDEgKiB3aWR0aDM0IC0gd2lkdGgxMiAqIGRldDIpIC8gZGV0MztcclxuICAgICAgaWYgKFxyXG4gICAgICAgICgoeCA+PSB4MyAmJiB4IDw9IHg0KSB8fCAoeCA+PSB4NCAmJiB4IDw9IHgzKSkgJiZcclxuICAgICAgICAoKHggPj0geDEgJiYgeCA8PSB4MikgfHwgKHggPj0geDIgJiYgeCA8PSB4MSkpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGxldCB5ID0gKGRldDEgKiBoZWlnaHQzNCAtIGhlaWdodDEyICogZGV0MikgLyBkZXQzO1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICgoeSA+PSB5MyAmJiB5IDw9IHk0KSB8fCAoeSA+PSB5NCAmJiB5IDw9IHkzKSkgJiZcclxuICAgICAgICAgICgoeSA+PSB5MSAmJiB5IDw9IHkyKSB8fCAoeSA+PSB5MiAmJiB5IDw9IHkxKSlcclxuICAgICAgICApXHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgICB4MyA9IHg0O1xyXG4gICAgICB5MyA9IHk0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuICAvKiogUmV0dXJucyB0aGUgcG9seWdvbiBmb3IgdGhlIHNwZWNpZmllZCBib3VuZGluZyBib3gsIG9yIG51bGwuICovXHJcbiAgZ2V0UG9seWdvbihib3VuZGluZ0JveDogQm91bmRpbmdCb3hBdHRhY2htZW50KSB7XHJcbiAgICBpZiAoYm91bmRpbmdCb3ggPT0gbnVsbCkgdGhyb3cgbmV3IEVycm9yKFwiYm91bmRpbmdCb3ggY2Fubm90IGJlIG51bGwuXCIpO1xyXG4gICAgbGV0IGluZGV4ID0gdGhpcy5ib3VuZGluZ0JveGVzLmluZGV4T2YoYm91bmRpbmdCb3gpO1xyXG4gICAgcmV0dXJuIGluZGV4ID09IC0xID8gbnVsbCA6IHRoaXMucG9seWdvbnNbaW5kZXhdO1xyXG4gIH1cclxuICBnZXRXaWR0aCgpIHtcclxuICAgIHJldHVybiB0aGlzLm1heFggLSB0aGlzLm1pblg7XHJcbiAgfVxyXG4gIGdldEhlaWdodCgpIHtcclxuICAgIHJldHVybiB0aGlzLm1heFkgLSB0aGlzLm1pblk7XHJcbiAgfVxyXG59XHJcbiJdfQ==