UNPKG

@esotericsoftware/spine-core

Version:
483 lines 72.8 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 { ClippingAttachment } from "./attachments/ClippingAttachment.js"; import { MeshAttachment } from "./attachments/MeshAttachment.js"; import { RegionAttachment } from "./attachments/RegionAttachment.js"; import { Bone } from "./Bone.js"; import { DrawOrder } from "./DrawOrder.js"; import { PhysicsConstraint } from "./PhysicsConstraint.js"; import { Slot } from "./Slot.js"; import { Color, Utils, Vector2 } from "./Utils.js"; /** Stores bones and slots to be posed by animations and application code. Multiple skeleton instances can share the same * {@link SkeletonData}, including animations, attachments, and skins. * * After posing, call {@link updateWorldTransform} to apply constraints and compute world transforms for rendering. * * See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine Runtimes Guide. */ export class Skeleton { static quadTriangles = [0, 1, 2, 2, 3, 0]; static yDown = false; static get yDir() { return Skeleton.yDown ? -1 : 1; } /** The skeleton's setup pose data. */ data; /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ bones; /** The skeleton's slots. To add a slot, also add it to {@link DrawOrder.pose}. */ slots; /** The skeleton's draw order. Use {@link DrawOrder.appliedPose} for rendering and {@link DrawOrder.pose} for changing the draw * order. */ drawOrder; /** The skeleton's constraints. */ // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types constraints; /** The skeleton's physics constraints. */ physics; /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link updateCache}. */ // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types _updateCache = []; // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types resetCache = []; /** The skeleton's current skin. May be null. */ skin = null; /** The color to tint all the skeleton's attachments. */ color; /** Scales the entire skeleton on the X axis. * * Bones that do not inherit scale are still affected by this property. */ scaleX = 1; _scaleY = 1; /** Scales the entire skeleton on the Y axis. * * Bones that do not inherit scale are still affected by this property. */ get scaleY() { return this._scaleY * Skeleton.yDir; } set scaleY(scaleY) { this._scaleY = scaleY; } /** Sets the skeleton X position, which is added to the root bone worldX position. * * Bones that do not inherit translation are still affected by this property. */ x = 0; /** Sets the skeleton Y position, which is added to the root bone worldY position. * * Bones that do not inherit translation are still affected by this property. */ y = 0; /** Returns the skeleton's time, is used for time-based manipulations, such as {@link PhysicsConstraint}. * * See {@link _update}. */ time = 0; /** The x component of a vector that defines the direction {@link PhysicsConstraintPose.wind} is applied. */ windX = 1; /** The y component of a vector that defines the direction {@link PhysicsConstraintPose.wind} is applied. */ windY = 0; /** The x component of a vector that defines the direction {@link PhysicsConstraintPose.gravity} is applied. */ gravityX = 0; /** The y component of a vector that defines the direction {@link PhysicsConstraintPose.gravity} is applied. */ gravityY = 1; _update = 0; constructor(data) { if (!data) throw new Error("data cannot be null."); this.data = data; this.bones = []; for (let i = 0; i < data.bones.length; i++) { const boneData = data.bones[i]; let bone; if (!boneData.parent) bone = new Bone(boneData, null); else { const parent = this.bones[boneData.parent.index]; bone = new Bone(boneData, parent); parent.children.push(bone); } this.bones.push(bone); } this.slots = []; for (const slotData of this.data.slots) this.slots.push(new Slot(slotData, this)); this.drawOrder = new DrawOrder(this.slots); this.physics = []; // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types this.constraints = []; for (const constraintData of this.data.constraints) { const constraint = constraintData.create(this); if (constraint instanceof PhysicsConstraint) this.physics.push(constraint); this.constraints.push(constraint); } this.color = new Color(1, 1, 1, 1); this.updateCache(); } /** Caches information about bones and constraints. Must be called if the {@link skin} is modified or if bones, constraints, * or weighted path attachments are added or removed. */ updateCache() { this._updateCache.length = 0; this.resetCache.length = 0; this.drawOrder.unconstrained(); const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) slots[i].unconstrained(); const bones = this.bones; const boneCount = bones.length; for (let i = 0, n = boneCount; i < n; i++) { const bone = bones[i]; bone.sorted = bone.data.skinRequired; bone.active = !bone.sorted; bone.unconstrained(); } if (this.skin) { const skinBones = this.skin.bones; for (let i = 0, n = this.skin.bones.length; i < n; i++) { let bone = this.bones[skinBones[i].index]; do { bone.sorted = false; bone.active = true; bone = bone.parent; } while (bone); } } const constraints = this.constraints; let n = this.constraints.length; for (let i = 0; i < n; i++) constraints[i].unconstrained(); for (let i = 0; i < n; i++) { const constraint = constraints[i]; constraint.active = constraint.isSourceActive() // biome-ignore lint/complexity/useOptionalChain: changing to this might return undefined && (!constraint.data.skinRequired || (this.skin != null && this.skin.constraints.includes(constraint.data))); if (constraint.active) constraint.sort(this); } for (let i = 0; i < boneCount; i++) this.sortBone(bones[i]); n = this._updateCache.length; for (let i = 0; i < n; i++) { const updateable = this._updateCache[i]; if (updateable instanceof Bone) this._updateCache[i] = updateable.appliedPose; } } // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types constrained(object) { if (object.pose === object.appliedPose) { object.constrained(); this.resetCache.push(object); } } sortBone(bone) { if (bone.sorted || !bone.active) return; const parent = bone.parent; if (parent) this.sortBone(parent); bone.sorted = true; this._updateCache.push(bone); } sortReset(bones) { for (let i = 0, n = bones.length; i < n; i++) { const bone = bones[i]; if (bone.active) { if (bone.sorted) this.sortReset(bone.children); bone.sorted = false; } } } /** Updates the world transform for each bone and applies all constraints. * * See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine * Runtimes Guide. */ updateWorldTransform(physics) { this._update++; if (this.drawOrder.appliedPose === this.drawOrder.constrainedPose) this.drawOrder.resetConstrained(); const resetCache = this.resetCache; for (let i = 0, n = this.resetCache.length; i < n; i++) resetCache[i].resetConstrained(); const updateCache = this._updateCache; for (let i = 0, n = this._updateCache.length; i < n; i++) updateCache[i].update(this, physics); } /** Sets the bones, constraints, and slots to their setup pose values. */ setupPose() { this.setupPoseBones(); this.setupPoseSlots(); } /** Sets the bones and constraints to their setup pose values. */ setupPoseBones() { const bones = this.bones; for (let i = 0, n = bones.length; i < n; i++) bones[i].setupPose(); const constraints = this.constraints; for (let i = 0, n = constraints.length; i < n; i++) constraints[i].setupPose(); } /** Sets the slots and draw order to their setup pose values. */ setupPoseSlots() { this.drawOrder.setupPose(); const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) slots[i].setupPose(); } /** Returns the root bone, or null if the skeleton has no bones. */ getRootBone() { if (this.bones.length === 0) return null; return this.bones[0]; } /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it * repeatedly. */ findBone(boneName) { if (!boneName) throw new Error("boneName cannot be null."); const bones = this.bones; for (let i = 0, n = bones.length; i < n; i++) if (bones[i].data.name === boneName) return bones[i]; return null; } /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it * repeatedly. */ findSlot(slotName) { if (!slotName) throw new Error("slotName cannot be null."); const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) if (slots[i].data.name === slotName) return slots[i]; return null; } setSkin(newSkin) { if (typeof newSkin === "string") this.setSkinByName(newSkin); else this.setSkinBySkin(newSkin); } ; setSkinByName(skinName) { const skin = this.data.findSkin(skinName); if (!skin) throw new Error(`Skin not found: ${skinName}`); this.setSkin(skin); } setSkinBySkin(newSkin) { if (newSkin === this.skin) return; if (newSkin) { if (this.skin) newSkin.attachAll(this, this.skin); else { const slots = this.slots; for (let i = 0, n = slots.length; i < n; i++) { const slot = slots[i]; const name = slot.data.attachmentName; if (name) { const attachment = newSkin.getAttachment(i, name); if (attachment) slot.pose.setAttachment(attachment); } } } } this.skin = newSkin; this.updateCache(); } getAttachment(slotNameOrIndex, placeholder) { if (typeof slotNameOrIndex === 'string') return this.getAttachmentByName(slotNameOrIndex, placeholder); return this.getAttachmentByIndex(slotNameOrIndex, placeholder); } /** Finds an attachment by looking in the {@link skin} and {@link SkeletonData.defaultSkin} using the slot name and attachment * name. * * See {@link getAttachment}. * @returns May be null. */ getAttachmentByName(slotName, placeholder) { const slot = this.data.findSlot(slotName); if (!slot) throw new Error(`Can't find slot with name ${slotName}`); return this.getAttachment(slot.index, placeholder); } /** Finds an attachment by looking in the {@link skin} and {@link SkeletonData.defaultSkin} using the slot index and * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. * * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. * @returns May be null. */ getAttachmentByIndex(slotIndex, placeholder) { if (!placeholder) throw new Error("placeholder cannot be null."); if (this.skin) { const attachment = this.skin.getAttachment(slotIndex, placeholder); if (attachment) return attachment; } if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, placeholder); return null; } /** A convenience method to set an attachment by finding the slot with {@link findSlot}, finding the attachment with * {@link getAttachment}, then setting the slot's {@link Slot.attachment}. * @param placeholder May be null to clear the slot's attachment. */ setAttachment(slotName, placeholder) { if (!slotName) throw new Error("slotName cannot be null."); const slot = this.findSlot(slotName); if (!slot) throw new Error(`Slot not found: ${slotName}`); let attachment = null; if (placeholder) { attachment = this.getAttachment(slot.data.index, placeholder); if (!attachment) throw new Error(`Attachment not found: ${placeholder}, for slot: ${slotName}`); } slot.pose.setAttachment(attachment); } /** Finds a constraint of the specified type by comparing each constraints's name. It is more efficient to cache the results of * this method than to call it multiple times. */ // biome-ignore lint/suspicious/noExplicitAny: reference runtime does not restrict to specific types findConstraint(constraintName, type) { if (constraintName == null) throw new Error("constraintName cannot be null."); if (type == null) throw new Error("type cannot be null."); const constraints = this.constraints; for (let i = 0, n = constraints.length; i < n; i++) { const constraint = constraints[i]; if (constraint instanceof type && constraint.data.name === constraintName) return constraint; } return null; } /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. * @param size An output value, the width and height of the AABB. * @param temp Working memory to temporarily store attachments' computed world vertices. */ getBoundsRect(clipper) { const offset = new Vector2(); const size = new Vector2(); this.getBounds(offset, size, undefined, clipper); return { x: offset.x, y: offset.y, width: size.x, height: size.y }; } /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose. Optionally applies * clipping. * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. * @param size An output value, the width and height of the AABB. * @param temp Working memory to temporarily store attachments' computed world vertices. * @param clipper {@link SkeletonClipping} to use. If `null`, no clipping is applied. */ getBounds(offset, size, temp = new Array(2), clipper = null) { if (!offset) throw new Error("offset cannot be null."); if (!size) throw new Error("size cannot be null."); const drawOrder = this.drawOrder.appliedPose; const slots = drawOrder; let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = slots[i]; if (!slot.bone.active) continue; let verticesLength = 0; let vertices = null; let triangles = null; const attachment = slot.appliedPose.attachment; if (attachment) { if (attachment instanceof RegionAttachment) { verticesLength = 8; vertices = Utils.setArraySize(temp, verticesLength, 0); attachment.computeWorldVertices(slot, attachment.getOffsets(slot.appliedPose), vertices, 0, 2); triangles = Skeleton.quadTriangles; } else if (attachment instanceof MeshAttachment) { verticesLength = attachment.worldVerticesLength; vertices = Utils.setArraySize(temp, verticesLength, 0); attachment.computeWorldVertices(this, slot, 0, verticesLength, vertices, 0, 2); triangles = attachment.triangles; } else if (attachment instanceof ClippingAttachment && clipper) { clipper.clipEnd(slot); clipper.clipStart(this, slot, attachment); continue; } if (vertices && triangles) { if (clipper?.isClipping() && clipper.clipTriangles(vertices, triangles, triangles.length)) { vertices = clipper.clippedVertices; verticesLength = clipper.clippedVertices.length; } for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { const x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); } } } if (clipper) clipper.clipEnd(slot); } if (clipper) clipper.clipEnd(); offset.set(minX, minY); size.set(maxX - minX, maxY - minY); } /** Scales the entire skeleton on the X and Y axes. * * Bones that do not inherit scale are still affected by this property. */ setScale(scaleX, scaleY) { this.scaleX = scaleX; this.scaleY = scaleY; } /** Sets the skeleton X and Y position, which is added to the root bone worldX and worldY position. * * Bones that do not inherit translation are still affected by this property. */ setPosition(x, y) { this.x = x; this.y = y; } /** Increments the skeleton's {@link time}. */ update(delta) { this.time += delta; } /** Calls {@link PhysicsConstraint.translate} for each physics constraint. */ physicsTranslate(x, y) { const constraints = this.physics; for (let i = 0, n = constraints.length; i < n; i++) constraints[i].translate(x, y); } /** Calls {@link PhysicsConstraint.rotate} for each physics constraint. */ physicsRotate(x, y, degrees) { const constraints = this.physics; for (let i = 0, n = constraints.length; i < n; i++) constraints[i].rotate(x, y, degrees); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU2tlbGV0b24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBSS9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNyRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRWpDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU0zRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxLQUFLLEVBQXdCLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFekU7Ozs7O2tJQUtrSTtBQUNsSSxNQUFNLE9BQU8sUUFBUTtJQUNaLE1BQU0sQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLE1BQU0sS0FBSyxJQUFJO1FBQ2QsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCxzQ0FBc0M7SUFDN0IsSUFBSSxDQUFlO0lBRTVCLHlGQUF5RjtJQUNoRixLQUFLLENBQWM7SUFFNUIsa0ZBQWtGO0lBQ3pFLEtBQUssQ0FBYztJQUU1QjtnQkFDWTtJQUNILFNBQVMsQ0FBWTtJ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RyxDQUFDLENBQUM7UUFDWCxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNaLENBQUM7SUFFRCw4Q0FBOEM7SUFDOUMsTUFBTSxDQUFFLEtBQWE7UUFDcEIsSUFBSSxDQUFDLElBQUksSUFBSSxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSxnQkFBZ0IsQ0FBRSxDQUFTLEVBQUUsQ0FBUztRQUNyQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ2pDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ2pELFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsYUFBYSxDQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsT0FBZTtRQUNuRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ2pDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ2pELFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgdHlwZSB7IEFuaW1hdGlvblN0YXRlIH0gZnJvbSBcIi4vQW5pbWF0aW9uU3RhdGUuanNcIjtcbmltcG9ydCB0eXBlIHsgQXR0YWNobWVudCB9IGZyb20gXCIuL2F0dGFjaG1lbnRzL0F0dGFjaG1lbnQuanNcIjtcbmltcG9ydCB7IENsaXBwaW5nQXR0YWNobWVudCB9IGZyb20gXCIuL2F0dGFjaG1lbnRzL0NsaXBwaW5nQXR0YWNobWVudC5qc1wiO1xuaW1wb3J0IHsgTWVzaEF0dGFjaG1lbnQgfSBmcm9tIFwiLi9hdHRhY2htZW50cy9NZXNoQXR0YWNobWVudC5qc1wiO1xuaW1wb3J0IHsgUmVnaW9uQXR0YWNobWVudCB9IGZyb20gXCIuL2F0dGFjaG1lbnRzL1JlZ2lvbkF0dGFjaG1lbnQuanNcIjtcbmltcG9ydCB7IEJvbmUgfSBmcm9tIFwiLi9Cb25lLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnN0cmFpbnQgfSBmcm9tIFwiLi9Db25zdHJhaW50LmpzXCI7XG5pbXBvcnQgeyBEcmF3T3JkZXIgfSBmcm9tIFwiLi9EcmF3T3JkZXIuanNcIjtcbmltcG9ydCB0eXBlIHsgUGh5c2ljcyB9IGZyb20gXCIuL1BoeXNpY3MuanNcIjtcbmltcG9ydCB7IFBoeXNpY3NDb25zdHJhaW50IH0gZnJvbSBcIi4vUGh5c2ljc0NvbnN0cmFpbnQuanNcIjtcbmltcG9ydCB0eXBlIHsgUGh5c2ljc0NvbnN0cmFpbnRQb3NlIH0gZnJvbSBcIi4vUGh5c2ljc0NvbnN0cmFpbnRQb3NlLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFBvc2VkIH0gZnJvbSBcIi4vUG9zZWQuanNcIjtcbmltcG9ydCB0eXBlIHsgU2tlbGV0b25DbGlwcGluZyB9IGZyb20gXCIuL1NrZWxldG9uQ2xpcHBpbmcuanNcIjtcbmltcG9ydCB0eXBlIHsgU2tlbGV0b25EYXRhIH0gZnJvbSBcIi4vU2tlbGV0b25EYXRhLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFNraW4gfSBmcm9tIFwiLi9Ta2luLmpzXCI7XG5pbXBvcnQgeyBTbG90IH0gZnJvbSBcIi4vU2xvdC5qc1wiO1xuaW1wb3J0IHsgQ29sb3IsIHR5cGUgTnVtYmVyQXJyYXlMaWtlLCBVdGlscywgVmVjdG9yMiB9IGZyb20gXCIuL1V0aWxzLmpzXCI7XG5cbi8qKiBTdG9yZXMgYm9uZXMgYW5kIHNsb3RzIHRvIGJlIHBvc2VkIGJ5IGFuaW1hdGlvbnMgYW5kIGFwcGxpY2F0aW9uIGNvZGUuIE11bHRpcGxlIHNrZWxldG9uIGluc3RhbmNlcyBjYW4gc2hhcmUgdGhlIHNhbWVcbiAqIHtAbGluayBTa2VsZXRvbkRhdGF9LCBpbmNsdWRpbmcgYW5pbWF0aW9ucywgYXR0YWNobWVudHMsIGFuZCBza2lucy5cbiAqXG4gKiBBZnRlciBwb3NpbmcsIGNhbGwge0BsaW5rIHVwZGF0ZVdvcmxkVHJhbnNmb3JtfSB0byBhcHBseSBjb25zdHJhaW50cyBhbmQgY29tcHV0ZSB3b3JsZCB0cmFuc2Zvcm1zIGZvciByZW5kZXJpbmcuXG4gKlxuICogU2VlIFtJbnN0YW5jZSBvYmplY3RzXShodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtcnVudGltZS1hcmNoaXRlY3R1cmUjSW5zdGFuY2Utb2JqZWN0cykgaW4gdGhlIFNwaW5lIFJ1bnRpbWVzIEd1aWRlLiAqL1xuZXhwb3J0IGNsYXNzIFNrZWxldG9uIHtcblx0cHJpdmF0ZSBzdGF0aWMgcXVhZFRyaWFuZ2xlcyA9IFswLCAxLCAyLCAyLCAzLCAwXTtcblx0c3RhdGljIHlEb3duID0gZmFsc2U7XG5cdHN0YXRpYyBnZXQgeURpciAoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gU2tlbGV0b24ueURvd24gPyAtMSA6IDE7XG5cdH1cblxuXHQvKiogVGhlIHNrZWxldG9uJ3Mgc2V0dXAgcG9zZSBkYXRhLiAqL1xuXHRyZWFkb25seSBkYXRhOiBTa2VsZXRvbkRhdGE7XG5cblx0LyoqIFRoZSBza2VsZXRvbidzIGJvbmVzLCBzb3J0ZWQgcGFyZW50IGZpcnN0LiBUaGUgcm9vdCBib25lIGlzIGFsd2F5cyB0aGUgZmlyc3QgYm9uZS4gKi9cblx0cmVhZG9ubHkgYm9uZXM6IEFycmF5PEJvbmU+O1xuXG5cdC8qKiBUaGUgc2tlbGV0b24ncyBzbG90cy4gVG8gYWRkIGEgc2xvdCwgYWxzbyBhZGQgaXQgdG8ge0BsaW5rIERyYXdPcmRlci5wb3NlfS4gKi9cblx0cmVhZG9ubHkgc2xvdHM6IEFycmF5PFNsb3Q+O1xuXG5cdC8qKiBUaGUgc2tlbGV0b24ncyBkcmF3IG9yZGVyLiBVc2Uge0BsaW5rIERyYXdPcmRlci5hcHBsaWVkUG9zZX0gZm9yIHJlbmRlcmluZyBhbmQge0BsaW5rIERyYXdPcmRlci5wb3NlfSBmb3IgY2hhbmdpbmcgdGhlIGRyYXdcblx0ICogb3JkZXIuICovXG5cdHJlYWRvbmx5IGRyYXdPcmRlcjogRHJhd09yZGVyO1xuXG5cdC8qKiBUaGUgc2tlbGV0b24ncyBjb25zdHJhaW50cy4gKi9cblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiByZWZlcmVuY2UgcnVudGltZSBkb2VzIG5vdCByZXN0cmljdCB0byBzcGVjaWZpYyB0eXBlc1xuXHRyZWFkb25seSBjb25zdHJhaW50czogQXJyYXk8Q29uc3RyYWludDxhbnksIGFueSwgYW55Pj47XG5cblx0LyoqIFRoZSBza2VsZXRvbidzIHBoeXNpY3MgY29uc3RyYWludHMuICovXG5cdHJlYWRvbmx5IHBoeXNpY3M6IEFycmF5PFBoeXNpY3NDb25zdHJhaW50PjtcblxuXHQvKiogVGhlIGxpc3Qgb2YgYm9uZXMgYW5kIGNvbnN0cmFpbnRzLCBzb3J0ZWQgaW4gdGhlIG9yZGVyIHRoZXkgc2hvdWxkIGJlIHVwZGF0ZWQsIGFzIGNvbXB1dGVkIGJ5IHtAbGluayB1cGRhdGVDYWNoZX0uICovXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogcmVmZXJlbmNlIHJ1bnRpbWUgZG9lcyBub3QgcmVzdHJpY3QgdG8gc3BlY2lmaWMgdHlwZXNcblx0cmVhZG9ubHkgX3VwZGF0ZUNhY2hlID0gW10gYXMgYW55W107XG5cblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiByZWZlcmVuY2UgcnVudGltZSBkb2VzIG5vdCByZXN0cmljdCB0byBzcGVjaWZpYyB0eXBlc1xuXHRyZWFkb25seSByZXNldENhY2hlOiBBcnJheTxQb3NlZDxhbnksIGFueT4+ID0gW107XG5cblx0LyoqIFRoZSBza2VsZXRvbidzIGN1cnJlbnQgc2tpbi4gTWF5IGJlIG51bGwuICovXG5cdHNraW46IFNraW4gfCBudWxsID0gbnVsbDtcblxuXHQvKiogVGhlIGNvbG9yIHRvIHRpbnQgYWxsIHRoZSBza2VsZXRvbidzIGF0dGFjaG1lbnRzLiAqL1xuXHRyZWFkb25seSBjb2xvcjogQ29sb3I7XG5cblx0LyoqIFNjYWxlcyB0aGUgZW50aXJlIHNrZWxldG9uIG9uIHRoZSBYIGF4aXMuXG5cdCAqXG5cdCAqIEJvbmVzIHRoYXQgZG8gbm90IGluaGVyaXQgc2NhbGUgYXJlIHN0aWxsIGFmZmVjdGVkIGJ5IHRoaXMgcHJvcGVydHkuICovXG5cdHNjYWxlWCA9IDE7XG5cblx0cHJpdmF0ZSBfc2NhbGVZID0gMTtcblxuXHQvKiogU2NhbGVzIHRoZSBlbnRpcmUgc2tlbGV0b24gb24gdGhlIFkgYXhpcy5cblx0ICpcblx0ICogQm9uZXMgdGhhdCBkbyBub3QgaW5oZXJpdCBzY2FsZSBhcmUgc3RpbGwgYWZmZWN0ZWQgYnkgdGhpcyBwcm9wZXJ0eS4gKi9cblx0cHVibGljIGdldCBzY2FsZVkgKCkge1xuXHRcdHJldHVybiB0aGlzLl9zY2FsZVkgKiBTa2VsZXRvbi55RGlyO1xuXHR9XG5cblx0cHVibGljIHNldCBzY2FsZVkgKHNjYWxlWTogbnVtYmVyKSB7XG5cdFx0dGhpcy5fc2NhbGVZID0gc2NhbGVZO1xuXHR9XG5cblx0LyoqIFNldHMgdGhlIHNrZWxldG9uIFggcG9zaXRpb24sIHdoaWNoIGlzIGFkZGVkIHRvIHRoZSByb290IGJvbmUgd29ybGRYIHBvc2l0aW9uLlxuXHQgKlxuXHQgKiBCb25lcyB0aGF0IGRvIG5vdCBpbmhlcml0IHRyYW5zbGF0aW9uIGFyZSBzdGlsbCBhZmZlY3RlZCBieSB0aGlzIHByb3BlcnR5LiAqL1xuXHR4ID0gMDtcblxuXHQvKiogU2V0cyB0aGUgc2tlbGV0b24gWSBwb3NpdGlvbiwgd2hpY2ggaXMgYWRkZWQgdG8gdGhlIHJvb3QgYm9uZSB3b3JsZFkgcG9zaXRpb24uXG5cdCAqXG5cdCAqIEJvbmVzIHRoYXQgZG8gbm90IGluaGVyaXQgdHJhbnNsYXRpb24gYXJlIHN0aWxsIGFmZmVjdGVkIGJ5IHRoaXMgcHJvcGVydHkuICovXG5cdHkgPSAwO1xuXG5cdC8qKiBSZXR1cm5zIHRoZSBza2VsZXRvbidzIHRpbWUsIGlzIHVzZWQgZm9yIHRpbWUtYmFzZWQgbWFuaXB1bGF0aW9ucywgc3VjaCBhcyB7QGxpbmsgUGh5c2ljc0NvbnN0cmFpbnR9LlxuXHQgKlxuXHQgKiBTZWUge0BsaW5rIF91cGRhdGV9LiAqL1xuXHR0aW1lID0gMDtcblxuXHQvKiogVGhlIHggY29tcG9uZW50IG9mIGEgdmVjdG9yIHRoYXQgZGVmaW5lcyB0aGUgZGlyZWN0aW9uIHtAbGluayBQaHlzaWNzQ29uc3RyYWludFBvc2Uud2luZH0gaXMgYXBwbGllZC4gKi9cblx0d2luZFggPSAxO1xuXG5cdC8qKiBUaGUgeSBjb21wb25lbnQgb2YgYSB2ZWN0b3IgdGhhdCBkZWZpbmVzIHRoZSBkaXJlY3Rpb24ge0BsaW5rIFBoeXNpY3NDb25zdHJhaW50UG9zZS53aW5kfSBpcyBhcHBsaWVkLiAqL1xuXHR3aW5kWSA9IDA7XG5cblx0LyoqIFRoZSB4IGNvbXBvbmVudCBvZiBhIHZlY3RvciB0aGF0IGRlZmluZXMgdGhlIGRpcmVjdGlvbiB7QGxpbmsgUGh5c2ljc0NvbnN0cmFpbnRQb3NlLmdyYXZpdHl9IGlzIGFwcGxpZWQuICovXG5cdGdyYXZpdHlYID0gMDtcblxuXHQvKi