ngx-spine
Version:
[](https://travis-ci.org/PoiScript/ngx-spine)
359 lines • 35.2 kB
JavaScript
/**
* @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==