UNPKG

@esotericsoftware/spine-core

Version:
189 lines 30.6 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. *****************************************************************************/ /** * Tracks movement of a host runtime object and applies that movement to skeleton physics constraints. * * This is useful for runtimes where a Spine skeleton is displayed by a movable object or container. * When enabled, changes in the host object's position are converted to skeleton coordinates and passed to * {@link Skeleton.physicsTranslate}. Changes in its rotation are passed to {@link Skeleton.physicsRotate}. * * Movement inheritance is opt-in. Position and rotation inheritance default to `0`, so * {@link applyTransformMovement} returns immediately until one of the inheritance values is non-zero. */ export class SkeletonPhysicsMovement { skeleton; adapter; positionInheritanceFactorX = 0; positionInheritanceFactorY = 0; rotationInheritanceFactor = 0; hasLastTransform = false; lastX = 0; lastY = 0; lastZ = 0; lastRotation = 0; currentTransform = { x: 0, y: 0, z: 0, rotation: 0 }; currentPosition = { x: 0, y: 0, z: 0 }; lastPosition = { x: 0, y: 0, z: 0 }; /** * Creates a movement tracker for a skeleton displayed by a host runtime object. * @param skeleton The skeleton whose physics constraints receive inherited movement. * @param adapter Runtime-specific hooks used to read and convert the host object's transform. * @param options Initial movement inheritance values. */ constructor(skeleton, adapter, options = {}) { this.skeleton = skeleton; this.adapter = adapter; this.positionInheritanceFactorX = options.positionInheritanceX ?? 0; this.positionInheritanceFactorY = options.positionInheritanceY ?? 0; this.rotationInheritanceFactor = options.rotationInheritance ?? 0; } /** Horizontal position inheritance factor. `0` disables horizontal position inheritance. */ get positionInheritanceX() { return this.positionInheritanceFactorX; } /** Vertical position inheritance factor. `0` disables vertical position inheritance. */ get positionInheritanceY() { return this.positionInheritanceFactorY; } /** * Sets how much host object translation is inherited by skeleton physics constraints. * Use `(1, 1)` for normal inheritance, or `(0, 0)` to disable position inheritance. * @param x The horizontal position inheritance factor. * @param y The vertical position inheritance factor. */ setPositionInheritance(x, y) { const wasDisabled = this.positionInheritanceFactorX === 0 && this.positionInheritanceFactorY === 0; const isEnabled = x !== 0 || y !== 0; this.positionInheritanceFactorX = x; this.positionInheritanceFactorY = y; if (wasDisabled && isEnabled) this.resetPosition(); } /** Rotation inheritance factor. `0` disables rotation inheritance. */ get rotationInheritance() { return this.rotationInheritanceFactor; } /** * Sets how much host object rotation is inherited by skeleton physics constraints. * @param value The rotation inheritance factor. */ set rotationInheritance(value) { const wasDisabled = this.rotationInheritanceFactor === 0; this.rotationInheritanceFactor = value; if (wasDisabled && value !== 0) this.resetRotation(); } /** Resets the previous position used to calculate inherited translation. */ resetPosition() { const transform = this.currentTransform; const readRotation = !this.hasLastTransform && this.rotationInheritanceFactor !== 0; this.adapter.readTransform(transform, readRotation); this.lastX = transform.x; this.lastY = transform.y; this.lastZ = transform.z; if (readRotation) this.lastRotation = transform.rotation; this.hasLastTransform = true; } /** Resets the previous rotation used to calculate inherited rotation. */ resetRotation() { const transform = this.currentTransform; this.adapter.readTransform(transform, true); this.lastRotation = transform.rotation; if (!this.hasLastTransform) { this.lastX = transform.x; this.lastY = transform.y; this.lastZ = transform.z; } this.hasLastTransform = true; } /** Resets both previous position and previous rotation. */ resetTransform() { const transform = this.currentTransform; this.adapter.readTransform(transform, true); this.setLastTransform(transform.x, transform.y, transform.z, transform.rotation); } /** * Applies host object transform movement since the previous call to the skeleton's physics constraints. * * The first call records the current transform as the baseline and does not apply movement. */ applyTransformMovement() { const inheritPosition = this.positionInheritanceFactorX !== 0 || this.positionInheritanceFactorY !== 0; const inheritRotation = this.rotationInheritanceFactor !== 0; if (!inheritPosition && !inheritRotation) return; const transform = this.currentTransform; this.adapter.readTransform(transform, inheritRotation); const { x, y, z } = transform; const currentRotation = inheritRotation ? transform.rotation : this.lastRotation; const positionChanged = x !== this.lastX || y !== this.lastY || z !== this.lastZ; if (this.hasLastTransform) { if (!positionChanged && currentRotation === this.lastRotation) return; if (inheritPosition && positionChanged) this.applyPositionMovement(x, y, z); if (inheritRotation && currentRotation !== this.lastRotation) this.applyRotationMovement(currentRotation); } this.setLastTransform(x, y, z, currentRotation); } applyPositionMovement(currentX, currentY, currentZ) { const currentPosition = this.currentPosition; currentPosition.x = currentX; currentPosition.y = currentY; currentPosition.z = currentZ; this.adapter.worldToSkeleton(currentPosition); const lastPosition = this.lastPosition; lastPosition.x = this.lastX; lastPosition.y = this.lastY; lastPosition.z = this.lastZ; this.adapter.worldToSkeleton(lastPosition); this.skeleton.physicsTranslate((currentPosition.x - lastPosition.x) * this.positionInheritanceFactorX, (currentPosition.y - lastPosition.y) * this.positionInheritanceFactorY); } applyRotationMovement(currentRotation) { const rotationFactor = this.rotationInheritanceFactor; if (rotationFactor === 0) return; this.skeleton.physicsRotate(0, 0, this.getRotationDelta(currentRotation, this.lastRotation) * rotationFactor); } setLastTransform(x, y, z, rotation) { this.lastX = x; this.lastY = y; this.lastZ = z; this.lastRotation = rotation; this.hasLastTransform = true; } getRotationDelta(current, previous) { let delta = current - previous; delta = (delta + 180) % 360 - 180; return delta < -180 ? delta + 360 : delta; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25QaHlzaWNzTW92ZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU2tlbGV0b25QaHlzaWNzTW92ZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBZ0QvRTs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLE9BQU8sdUJBQXVCO0lBb0IxQjtJQUNBO0lBcEJELDBCQUEwQixHQUFHLENBQUMsQ0FBQztJQUMvQiwwQkFBMEIsR0FBRyxDQUFDLENBQUM7SUFDL0IseUJBQXlCLEdBQUcsQ0FBQyxDQUFDO0lBQzlCLGdCQUFnQixHQUFHLEtBQUssQ0FBQztJQUN6QixLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNWLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDVixZQUFZLEdBQUcsQ0FBQyxDQUFDO0lBQ1IsZ0JBQWdCLEdBQXFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3ZGLGVBQWUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDdkMsWUFBWSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUVyRDs7Ozs7T0FLRztJQUNILFlBQ1MsUUFBa0IsRUFDbEIsT0FBdUMsRUFDL0MsVUFBMEMsRUFBRTtRQUZwQyxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLFlBQU8sR0FBUCxPQUFPLENBQWdDO1FBRy9DLElBQUksQ0FBQywwQkFBMEIsR0FBRyxPQUFPLENBQUMsb0JBQW9CLElBQUksQ0FBQyxDQUFDO1FBQ3BF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LDBCQUEwQixDQUN0RSxDQUFDO0lBQ0gsQ0FBQztJQUVPLHFCQUFxQixDQUFFLGVBQXVCO1FBQ3JELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztRQUN0RCxJQUFJLGNBQWMsS0FBSyxDQUFDO1lBQUUsT0FBTztRQUNqQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLGNBQWMsQ0FBQyxDQUFDO0lBQy9HLENBQUM7SUFFTyxnQkFBZ0IsQ0FBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxRQUFnQjtRQUMxRSxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQztRQUM3QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0lBQzlCLENBQUM7SUFFTyxnQkFBZ0IsQ0FBRSxPQUFlLEVBQUUsUUFBZ0I7UUFDMUQsSUFBSSxLQUFLLEdBQUcsT0FBTyxHQUFHLFFBQVEsQ0FBQztRQUMvQixLQUFLLEdBQUcsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNsQyxPQUFPLEtBQUssR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQzNDLENBQUM7Q0FDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgQXByaWwgNSwgMjAyNS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDI1LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yXG4gKiBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0ZcbiAqIFRIRSBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHR5cGUgeyBTa2VsZXRvbiB9IGZyb20gXCIuL1NrZWxldG9uLmpzXCI7XG5cbi8qKiBBIGhvc3QgcnVudGltZSBvYmplY3QncyB3b3JsZCBwb3NpdGlvbiBhbmQgcm90YXRpb24gdXNlZCBmb3Igc2tlbGV0b24gcGh5c2ljcyBtb3ZlbWVudCBpbmhlcml0YW5jZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2tlbGV0b25QaHlzaWNzTW92ZW1lbnRUcmFuc2Zvcm0ge1xuXHQvKiogVGhlIGhvc3Qgb2JqZWN0J3MgWCBwb3NpdGlvbiBpbiB3b3JsZCBjb29yZGluYXRlcy4gKi9cblx0eDogbnVtYmVyO1xuXG5cdC8qKiBUaGUgaG9zdCBvYmplY3QncyBZIHBvc2l0aW9uIGluIHdvcmxkIGNvb3JkaW5hdGVzLiAqL1xuXHR5OiBudW1iZXI7XG5cblx0LyoqIFRoZSBob3N0IG9iamVjdCdzIFogcG9zaXRpb24gaW4gd29ybGQgY29vcmRpbmF0ZXMuIFNldCB0byBgMGAgaW4gMkQgcnVudGltZXMuICovXG5cdHo6IG51bWJlcjtcblxuXHQvKiogVGhlIGhvc3Qgb2JqZWN0J3Mgcm90YXRpb24gYXJvdW5kIHRoZSBza2VsZXRvbiBwbGFuZSBub3JtYWwsIGluIGRlZ3JlZXMgYW5kIGluIHRoZSBkaXJlY3Rpb24gZXhwZWN0ZWQgYnkgU3BpbmUgcGh5c2ljcy4gKi9cblx0cm90YXRpb246IG51bWJlcjtcbn1cblxuLyoqIEluaXRpYWwgbW92ZW1lbnQgaW5oZXJpdGFuY2UgdmFsdWVzIGZvciB7QGxpbmsgU2tlbGV0b25QaHlzaWNzTW92ZW1lbnR9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTa2VsZXRvblBoeXNpY3NNb3ZlbWVudE9wdGlvbnMge1xuXHQvKiogSW5pdGlhbCBob3Jpem9udGFsIHBvc2l0aW9uIGluaGVyaXRhbmNlLiBEZWZhdWx0cyB0byBgMGAuICovXG5cdHBvc2l0aW9uSW5oZXJpdGFuY2VYPzogbnVtYmVyO1xuXG5cdC8qKiBJbml0aWFsIHZlcnRpY2FsIHBvc2l0aW9uIGluaGVyaXRhbmNlLiBEZWZhdWx0cyB0byBgMGAuICovXG5cdHBvc2l0aW9uSW5oZXJpdGFuY2VZPzogbnVtYmVyO1xuXG5cdC8qKiBJbml0aWFsIHJvdGF0aW9uIGluaGVyaXRhbmNlLiBEZWZhdWx0cyB0byBgMGAuICovXG5cdHJvdGF0aW9uSW5oZXJpdGFuY2U/OiBudW1iZXI7XG59XG5cbi8qKiBSdW50aW1lLXNwZWNpZmljIGhvb2tzIG5lZWRlZCBieSB7QGxpbmsgU2tlbGV0b25QaHlzaWNzTW92ZW1lbnR9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTa2VsZXRvblBoeXNpY3NNb3ZlbWVudEFkYXB0ZXIge1xuXHQvKipcblx0ICogV3JpdGVzIHRoZSBjdXJyZW50IGhvc3Qgb2JqZWN0IHdvcmxkIHBvc2l0aW9uIHRvIGBvdXRgIGFuZCwgd2hlbiBgcmVhZFJvdGF0aW9uYCBpcyB0cnVlLCBpdHMgcm90YXRpb24uXG5cdCAqIEltcGxlbWVudGF0aW9ucyBtYXkgc2tpcCBjYWxjdWxhdGluZyBhbmQgd3JpdGluZyBgb3V0LnJvdGF0aW9uYCB3aGVuIGByZWFkUm90YXRpb25gIGlzIGZhbHNlLlxuXHQgKiBAcGFyYW0gb3V0IFJlY2VpdmVzIHRoZSBjdXJyZW50IGhvc3Qgb2JqZWN0IHRyYW5zZm9ybS5cblx0ICogQHBhcmFtIHJlYWRSb3RhdGlvbiBXaGV0aGVyIHRoZSBjdXJyZW50IHJvdGF0aW9uIGlzIG5lZWRlZC5cblx0ICovXG5cdHJlYWRUcmFuc2Zvcm0gKG91dDogU2tlbGV0b25QaHlzaWNzTW92ZW1lbnRUcmFuc2Zvcm0sIHJlYWRSb3RhdGlvbjogYm9vbGVhbik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGBwb2ludGAgaW4tcGxhY2UgZnJvbSBob3N0IHdvcmxkIGNvb3JkaW5hdGVzIHRvIHNrZWxldG9uIGNvb3JkaW5hdGVzLlxuXHQgKiBUaGUgY29udmVydGVkIHNrZWxldG9uIGNvb3JkaW5hdGVzIGFyZSByZXR1cm5lZCBpbiBgcG9pbnQueGAgYW5kIGBwb2ludC55YC5cblx0ICovXG5cdHdvcmxkVG9Ta2VsZXRvbiAocG9pbnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHo6IG51bWJlciB9KTogdm9pZDtcbn1cblxuLyoqXG4gKiBUcmFja3MgbW92ZW1lbnQgb2YgYSBob3N0IHJ1bnRpbWUgb2JqZWN0IGFuZCBhcHBsaWVzIHRoYXQgbW92ZW1lbnQgdG8gc2tlbGV0b24gcGh5c2ljcyBjb25zdHJhaW50cy5cbiAqXG4gKiBUaGlzIGlzIHVzZWZ1bCBmb3IgcnVudGltZXMgd2hlcmUgYSBTcGluZSBza2VsZXRvbiBpcyBkaXNwbGF5ZWQgYnkgYSBtb3ZhYmxlIG9iamVjdCBvciBjb250YWluZXIuXG4gKiBXaGVuIGVuYWJsZWQsIGNoYW5nZXMgaW4gdGhlIGhvc3Qgb2JqZWN0J3MgcG9zaXRpb24gYXJlIGNvbnZlcnRlZCB0byBza2VsZXRvbiBjb29yZGluYXRlcyBhbmQgcGFzc2VkIHRvXG4gKiB7QGxpbmsgU2tlbGV0b24ucGh5c2ljc1RyYW5zbGF0ZX0uIENoYW5nZXMgaW4gaXRzIHJvdGF0aW9uIGFyZSBwYXNzZWQgdG8ge0BsaW5rIFNrZWxldG9uLnBoeXNpY3NSb3RhdGV9LlxuICpcbiAqIE1vdmVtZW50IGluaGVyaXRhbmNlIGlzIG9wdC1pbi4gUG9zaXRpb24gYW5kIHJvdGF0aW9uIGluaGVyaXRhbmNlIGRlZmF1bHQgdG8gYDBgLCBzb1xuICoge0BsaW5rIGFwcGx5VHJhbnNmb3JtTW92ZW1lbnR9IHJldHVybnMgaW1tZWRpYXRlbHkgdW50aWwgb25lIG9mIHRoZSBpbmhlcml0YW5jZSB2YWx1ZXMgaXMgbm9uLXplcm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBTa2VsZXRvblBoeXNpY3NNb3ZlbWVudCB7XG5cdHByaXZhdGUgcG9zaXRpb25Jbmhlcml0YW5jZUZhY3RvclggPSAwO1xuXHRwcml2YXRlIHBvc2l0aW9uSW5oZXJpdGFuY2VGYWN0b3JZID0gMDtcblx0cHJpdmF0ZSByb3RhdGlvbkluaGVyaXRhbmNlRmFjdG9yID0gMDtcblx0cHJpdmF0ZSBoYXNMYXN0VHJhbnNmb3JtID0gZmFsc2U7XG5cdHByaXZhdGUgbGFzdFggPSAwO1xuXHRwcml2YXRlIGxhc3RZID0gMDtcblx0cHJpdmF0ZSBsYXN0WiA9IDA7XG5cdHByaXZhdGUgbGFzdFJvdGF0aW9uID0gMDtcblx0cHJpdmF0ZSByZWFkb25seSBjdXJyZW50VHJhbnNmb3JtOiBTa2VsZXRvblBoeXNpY3NNb3ZlbWVudFRyYW5zZm9ybSA9IHsgeDogMCwgeTogMCwgejogMCwgcm90YXRpb246IDAgfTtcblx0cHJpdmF0ZSByZWFkb25seSBjdXJyZW50UG9zaXRpb24gPSB7IHg6IDAsIHk6IDAsIHo6IDAgfTtcblx0cHJpdmF0ZSByZWFkb25seSBsYXN0UG9zaXRpb24gPSB7IHg6IDAsIHk6IDAsIHo6IDAgfTtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG1vdmVtZW50IHRyYWNrZXIgZm9yIGEgc2tlbGV0b24gZGlzcGxheWVkIGJ5IGEgaG9zdCBydW50aW1lIG9iamVjdC5cblx0ICogQHBhcmFtIHNrZWxldG9uIFRoZSBza2VsZXRvbiB3aG9zZSBwaHlzaWNzIGNvbnN0cmFpbnRzIHJlY2VpdmUgaW5oZXJpdGVkIG1vdmVtZW50LlxuXHQgKiBAcGFyYW0gYWRhcHRlciBSdW50aW1lLXNwZWNpZmljIGhvb2tzIHVzZWQgdG8gcmVhZCBhbmQgY29udmVydCB0aGUgaG9zdCBvYmplY3QncyB0cmFuc2Zvcm0uXG5cdCAqIEBwYXJhbSBvcHRpb25zIEluaXRpYWwgbW92ZW1lbnQgaW5oZXJpdGFuY2UgdmFsdWVzLlxuXHQgKi9cblx0Y29uc3RydWN0b3IgKFxuXHRcdHByaXZhdGUgc2tlbGV0b246IFNrZWxldG9uLFxuXHRcdHByaXZhdGUgYWRhcHRlcjogU2tlbGV0b25QaHlzaWNzTW92ZW1lbnRBZGFwdGVyLFxuXHRcdG9wdGlvbnM6IFNrZWxldG9uUGh5c2ljc01vdmVtZW50T3B0aW9ucyA9IHt9LFxuXHQpIHtcblx0XHR0aGlzLnBvc2l0aW9uSW5oZXJpdGFuY2VGYWN0b3JYID0gb3B0aW9ucy5wb3NpdGlvbkluaGVyaXRhbmNlWCA/PyAwO1xuXHRcdHRoaXMucG9zaXRpb25Jbmhlcml0YW5jZUZhY3RvclkgPSBvcHRpb25zLnBvc2l0aW9uSW5oZXJpdGFuY2VZID8/IDA7XG5cdFx0dGhpcy5yb3RhdGlvbkluaGVyaXRhbmNlRmFjdG9yID0gb3B0aW9ucy5yb3RhdGlvbkluaGVyaXRhbmNlID8/IDA7XG5cdH1cblxuXHQvKiogSG9yaXpvbnRhbCBwb3NpdGlvbiBpbmhlcml0YW5jZSBmYWN0b3IuIGAwYCBkaXNhYmxlcyBob3Jpem9udGFsIHBvc2l0aW9uIGluaGVyaXRhbmNlLiAqL1xuXHRnZXQgcG9zaXRpb25Jbmhlcml0YW5jZVggKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMucG9zaXRpb25Jbmhlcml0YW5jZUZhY3Rvclg7XG5cdH1cblxuXHQvKiogVmVydGljYWwgcG9zaXRpb24gaW5oZXJpdGFuY2UgZmFjdG9yLiBgMGAgZGlzYWJsZXMgdmVydGljYWwgcG9zaXRpb24gaW5oZXJpdGFuY2UuICovXG5cdGdldCBwb3NpdGlvbkluaGVyaXRhbmNlWSAoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGhvdyBtdWNoIGhvc3Qgb2JqZWN0IHRyYW5zbGF0aW9uIGlzIGluaGVyaXRlZCBieSBza2VsZXRvbiBwaHlzaWNzIGNvbnN0cmFpbnRzLlxuXHQgKiBVc2UgYCgxLCAxKWAgZm9yIG5vcm1hbCBpbmhlcml0YW5jZSwgb3IgYCgwLCAwKWAgdG8gZGlzYWJsZSBwb3NpdGlvbiBpbmhlcml0YW5jZS5cblx0ICogQHBhcmFtIHggVGhlIGhvcml6b250YWwgcG9zaXRpb24gaW5oZXJpdGFuY2UgZmFjdG9yLlxuXHQgKiBAcGFyYW0geSBUaGUgdmVydGljYWwgcG9zaXRpb24gaW5oZXJpdGFuY2UgZmFjdG9yLlxuXHQgKi9cblx0c2V0UG9zaXRpb25Jbmhlcml0YW5jZSAoeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCB3YXNEaXNhYmxlZCA9IHRoaXMucG9zaXRpb25Jbmhlcml0YW5jZUZhY3RvclggPT09IDAgJiYgdGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWSA9PT0gMDtcblx0XHRjb25zdCBpc0VuYWJsZWQgPSB4ICE9PSAwIHx8IHkgIT09IDA7XG5cdFx0dGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWCA9IHg7XG5cdFx0dGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWSA9IHk7XG5cdFx0aWYgKHdhc0Rpc2FibGVkICYmIGlzRW5hYmxlZCkgdGhpcy5yZXNldFBvc2l0aW9uKCk7XG5cdH1cblxuXHQvKiogUm90YXRpb24gaW5oZXJpdGFuY2UgZmFjdG9yLiBgMGAgZGlzYWJsZXMgcm90YXRpb24gaW5oZXJpdGFuY2UuICovXG5cdGdldCByb3RhdGlvbkluaGVyaXRhbmNlICgpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLnJvdGF0aW9uSW5oZXJpdGFuY2VGYWN0b3I7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBob3cgbXVjaCBob3N0IG9iamVjdCByb3RhdGlvbiBpcyBpbmhlcml0ZWQgYnkgc2tlbGV0b24gcGh5c2ljcyBjb25zdHJhaW50cy5cblx0ICogQHBhcmFtIHZhbHVlIFRoZSByb3RhdGlvbiBpbmhlcml0YW5jZSBmYWN0b3IuXG5cdCAqL1xuXHRzZXQgcm90YXRpb25Jbmhlcml0YW5jZSAodmFsdWU6IG51bWJlcikge1xuXHRcdGNvbnN0IHdhc0Rpc2FibGVkID0gdGhpcy5yb3RhdGlvbkluaGVyaXRhbmNlRmFjdG9yID09PSAwO1xuXHRcdHRoaXMucm90YXRpb25Jbmhlcml0YW5jZUZhY3RvciA9IHZhbHVlO1xuXHRcdGlmICh3YXNEaXNhYmxlZCAmJiB2YWx1ZSAhPT0gMCkgdGhpcy5yZXNldFJvdGF0aW9uKCk7XG5cdH1cblxuXHQvKiogUmVzZXRzIHRoZSBwcmV2aW91cyBwb3NpdGlvbiB1c2VkIHRvIGNhbGN1bGF0ZSBpbmhlcml0ZWQgdHJhbnNsYXRpb24uICovXG5cdHJlc2V0UG9zaXRpb24gKCk6IHZvaWQge1xuXHRcdGNvbnN0IHRyYW5zZm9ybSA9IHRoaXMuY3VycmVudFRyYW5zZm9ybTtcblx0XHRjb25zdCByZWFkUm90YXRpb24gPSAhdGhpcy5oYXNMYXN0VHJhbnNmb3JtICYmIHRoaXMucm90YXRpb25Jbmhlcml0YW5jZUZhY3RvciAhPT0gMDtcblx0XHR0aGlzLmFkYXB0ZXIucmVhZFRyYW5zZm9ybSh0cmFuc2Zvcm0sIHJlYWRSb3RhdGlvbik7XG5cdFx0dGhpcy5sYXN0WCA9IHRyYW5zZm9ybS54O1xuXHRcdHRoaXMubGFzdFkgPSB0cmFuc2Zvcm0ueTtcblx0XHR0aGlzLmxhc3RaID0gdHJhbnNmb3JtLno7XG5cdFx0aWYgKHJlYWRSb3RhdGlvbikgdGhpcy5sYXN0Um90YXRpb24gPSB0cmFuc2Zvcm0ucm90YXRpb247XG5cdFx0dGhpcy5oYXNMYXN0VHJhbnNmb3JtID0gdHJ1ZTtcblx0fVxuXG5cdC8qKiBSZXNldHMgdGhlIHByZXZpb3VzIHJvdGF0aW9uIHVzZWQgdG8gY2FsY3VsYXRlIGluaGVyaXRlZCByb3RhdGlvbi4gKi9cblx0cmVzZXRSb3RhdGlvbiAoKTogdm9pZCB7XG5cdFx0Y29uc3QgdHJhbnNmb3JtID0gdGhpcy5jdXJyZW50VHJhbnNmb3JtO1xuXHRcdHRoaXMuYWRhcHRlci5yZWFkVHJhbnNmb3JtKHRyYW5zZm9ybSwgdHJ1ZSk7XG5cdFx0dGhpcy5sYXN0Um90YXRpb24gPSB0cmFuc2Zvcm0ucm90YXRpb247XG5cdFx0aWYgKCF0aGlzLmhhc0xhc3RUcmFuc2Zvcm0pIHtcblx0XHRcdHRoaXMubGFzdFggPSB0cmFuc2Zvcm0ueDtcblx0XHRcdHRoaXMubGFzdFkgPSB0cmFuc2Zvcm0ueTtcblx0XHRcdHRoaXMubGFzdFogPSB0cmFuc2Zvcm0uejtcblx0XHR9XG5cdFx0dGhpcy5oYXNMYXN0VHJhbnNmb3JtID0gdHJ1ZTtcblx0fVxuXG5cdC8qKiBSZXNldHMgYm90aCBwcmV2aW91cyBwb3NpdGlvbiBhbmQgcHJldmlvdXMgcm90YXRpb24uICovXG5cdHJlc2V0VHJhbnNmb3JtICgpOiB2b2lkIHtcblx0XHRjb25zdCB0cmFuc2Zvcm0gPSB0aGlzLmN1cnJlbnRUcmFuc2Zvcm07XG5cdFx0dGhpcy5hZGFwdGVyLnJlYWRUcmFuc2Zvcm0odHJhbnNmb3JtLCB0cnVlKTtcblx0XHR0aGlzLnNldExhc3RUcmFuc2Zvcm0odHJhbnNmb3JtLngsIHRyYW5zZm9ybS55LCB0cmFuc2Zvcm0ueiwgdHJhbnNmb3JtLnJvdGF0aW9uKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBcHBsaWVzIGhvc3Qgb2JqZWN0IHRyYW5zZm9ybSBtb3ZlbWVudCBzaW5jZSB0aGUgcHJldmlvdXMgY2FsbCB0byB0aGUgc2tlbGV0b24ncyBwaHlzaWNzIGNvbnN0cmFpbnRzLlxuXHQgKlxuXHQgKiBUaGUgZmlyc3QgY2FsbCByZWNvcmRzIHRoZSBjdXJyZW50IHRyYW5zZm9ybSBhcyB0aGUgYmFzZWxpbmUgYW5kIGRvZXMgbm90IGFwcGx5IG1vdmVtZW50LlxuXHQgKi9cblx0YXBwbHlUcmFuc2Zvcm1Nb3ZlbWVudCAoKTogdm9pZCB7XG5cdFx0Y29uc3QgaW5oZXJpdFBvc2l0aW9uID0gdGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWCAhPT0gMCB8fCB0aGlzLnBvc2l0aW9uSW5oZXJpdGFuY2VGYWN0b3JZICE9PSAwO1xuXHRcdGNvbnN0IGluaGVyaXRSb3RhdGlvbiA9IHRoaXMucm90YXRpb25Jbmhlcml0YW5jZUZhY3RvciAhPT0gMDtcblx0XHRpZiAoIWluaGVyaXRQb3NpdGlvbiAmJiAhaW5oZXJpdFJvdGF0aW9uKSByZXR1cm47XG5cblx0XHRjb25zdCB0cmFuc2Zvcm0gPSB0aGlzLmN1cnJlbnRUcmFuc2Zvcm07XG5cdFx0dGhpcy5hZGFwdGVyLnJlYWRUcmFuc2Zvcm0odHJhbnNmb3JtLCBpbmhlcml0Um90YXRpb24pO1xuXHRcdGNvbnN0IHsgeCwgeSwgeiB9ID0gdHJhbnNmb3JtO1xuXHRcdGNvbnN0IGN1cnJlbnRSb3RhdGlvbiA9IGluaGVyaXRSb3RhdGlvbiA/IHRyYW5zZm9ybS5yb3RhdGlvbiA6IHRoaXMubGFzdFJvdGF0aW9uO1xuXHRcdGNvbnN0IHBvc2l0aW9uQ2hhbmdlZCA9IHggIT09IHRoaXMubGFzdFggfHwgeSAhPT0gdGhpcy5sYXN0WSB8fCB6ICE9PSB0aGlzLmxhc3RaO1xuXG5cdFx0aWYgKHRoaXMuaGFzTGFzdFRyYW5zZm9ybSkge1xuXHRcdFx0aWYgKCFwb3NpdGlvbkNoYW5nZWQgJiYgY3VycmVudFJvdGF0aW9uID09PSB0aGlzLmxhc3RSb3RhdGlvbikgcmV0dXJuO1xuXHRcdFx0aWYgKGluaGVyaXRQb3NpdGlvbiAmJiBwb3NpdGlvbkNoYW5nZWQpIHRoaXMuYXBwbHlQb3NpdGlvbk1vdmVtZW50KHgsIHksIHopO1xuXHRcdFx0aWYgKGluaGVyaXRSb3RhdGlvbiAmJiBjdXJyZW50Um90YXRpb24gIT09IHRoaXMubGFzdFJvdGF0aW9uKSB0aGlzLmFwcGx5Um90YXRpb25Nb3ZlbWVudChjdXJyZW50Um90YXRpb24pO1xuXHRcdH1cblxuXHRcdHRoaXMuc2V0TGFzdFRyYW5zZm9ybSh4LCB5LCB6LCBjdXJyZW50Um90YXRpb24pO1xuXHR9XG5cblx0cHJpdmF0ZSBhcHBseVBvc2l0aW9uTW92ZW1lbnQgKGN1cnJlbnRYOiBudW1iZXIsIGN1cnJlbnRZOiBudW1iZXIsIGN1cnJlbnRaOiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCBjdXJyZW50UG9zaXRpb24gPSB0aGlzLmN1cnJlbnRQb3NpdGlvbjtcblx0XHRjdXJyZW50UG9zaXRpb24ueCA9IGN1cnJlbnRYO1xuXHRcdGN1cnJlbnRQb3NpdGlvbi55ID0gY3VycmVudFk7XG5cdFx0Y3VycmVudFBvc2l0aW9uLnogPSBjdXJyZW50Wjtcblx0XHR0aGlzLmFkYXB0ZXIud29ybGRUb1NrZWxldG9uKGN1cnJlbnRQb3NpdGlvbik7XG5cblx0XHRjb25zdCBsYXN0UG9zaXRpb24gPSB0aGlzLmxhc3RQb3NpdGlvbjtcblx0XHRsYXN0UG9zaXRpb24ueCA9IHRoaXMubGFzdFg7XG5cdFx0bGFzdFBvc2l0aW9uLnkgPSB0aGlzLmxhc3RZO1xuXHRcdGxhc3RQb3NpdGlvbi56ID0gdGhpcy5sYXN0Wjtcblx0XHR0aGlzLmFkYXB0ZXIud29ybGRUb1NrZWxldG9uKGxhc3RQb3NpdGlvbik7XG5cblx0XHR0aGlzLnNrZWxldG9uLnBoeXNpY3NUcmFuc2xhdGUoXG5cdFx0XHQoY3VycmVudFBvc2l0aW9uLnggLSBsYXN0UG9zaXRpb24ueCkgKiB0aGlzLnBvc2l0aW9uSW5oZXJpdGFuY2VGYWN0b3JYLFxuXHRcdFx0KGN1cnJlbnRQb3NpdGlvbi55IC0gbGFzdFBvc2l0aW9uLnkpICogdGhpcy5wb3NpdGlvbkluaGVyaXRhbmNlRmFjdG9yWVxuXHRcdCk7XG5cdH1cblxuXHRwcml2YXRlIGFwcGx5Um90YXRpb25Nb3ZlbWVudCAoY3VycmVudFJvdGF0aW9uOiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCByb3RhdGlvbkZhY3RvciA9IHRoaXMucm90YXRpb25Jbmhlcml0YW5jZUZhY3Rvcjtcblx0XHRpZiAocm90YXRpb25GYWN0b3IgPT09IDApIHJldHVybjtcblx0XHR0aGlzLnNrZWxldG9uLnBoeXNpY3NSb3RhdGUoMCwgMCwgdGhpcy5nZXRSb3RhdGlvbkRlbHRhKGN1cnJlbnRSb3RhdGlvbiwgdGhpcy5sYXN0Um90YXRpb24pICogcm90YXRpb25GYWN0b3IpO1xuXHR9XG5cblx0cHJpdmF0ZSBzZXRMYXN0VHJhbnNmb3JtICh4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyLCByb3RhdGlvbjogbnVtYmVyKTogdm9pZCB7XG5cdFx0dGhpcy5sYXN0WCA9IHg7XG5cdFx0dGhpcy5sYXN0WSA9IHk7XG5cdFx0dGhpcy5sYXN0WiA9IHo7XG5cdFx0dGhpcy5sYXN0Um90YXRpb24gPSByb3RhdGlvbjtcblx0XHR0aGlzLmhhc0xhc3RUcmFuc2Zvcm0gPSB0cnVlO1xuXHR9XG5cblx0cHJpdmF0ZSBnZXRSb3RhdGlvbkRlbHRhIChjdXJyZW50OiBudW1iZXIsIHByZXZpb3VzOiBudW1iZXIpOiBudW1iZXIge1xuXHRcdGxldCBkZWx0YSA9IGN1cnJlbnQgLSBwcmV2aW91cztcblx0XHRkZWx0YSA9IChkZWx0YSArIDE4MCkgJSAzNjAgLSAxODA7XG5cdFx0cmV0dXJuIGRlbHRhIDwgLTE4MCA/IGRlbHRhICsgMzYwIDogZGVsdGE7XG5cdH1cbn1cbiJdfQ==