@esotericsoftware/spine-core
Version:
The official Spine Runtimes for the web.
661 lines • 100 kB
JavaScript
/******************************************************************************
* 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 { PathAttachment } from "./attachments/PathAttachment.js";
import { RegionAttachment } from "./attachments/RegionAttachment.js";
import { Bone } from "./Bone.js";
import { IkConstraint } from "./IkConstraint.js";
import { PathConstraint } from "./PathConstraint.js";
import { PhysicsConstraint } from "./PhysicsConstraint.js";
import { Slot } from "./Slot.js";
import { TransformConstraint } from "./TransformConstraint.js";
import { Color, Utils, MathUtils, Vector2 } from "./Utils.js";
/** Stores the current pose for a skeleton.
*
* 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;
/** 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 in the setup pose draw order. */
slots;
/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */
drawOrder;
/** The skeleton's IK constraints. */
ikConstraints;
/** The skeleton's transform constraints. */
transformConstraints;
/** The skeleton's path constraints. */
pathConstraints;
/** The skeleton's physics constraints. */
physicsConstraints;
/** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */
_updateCache = new Array();
/** 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. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
scaleX = 1;
/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
_scaleY = 1;
get scaleY() {
return Skeleton.yDown ? -this._scaleY : this._scaleY;
}
set scaleY(scaleY) {
this._scaleY = scaleY;
}
/** Sets the skeleton X position, which is added to the root bone worldX position. */
x = 0;
/** Sets the skeleton Y position, which is added to the root bone worldY position. */
y = 0;
/** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}.
* <p>
* See {@link #update(float)}. */
time = 0;
constructor(data) {
if (!data)
throw new Error("data cannot be null.");
this.data = data;
this.bones = new Array();
for (let i = 0; i < data.bones.length; i++) {
let boneData = data.bones[i];
let bone;
if (!boneData.parent)
bone = new Bone(boneData, this, null);
else {
let parent = this.bones[boneData.parent.index];
bone = new Bone(boneData, this, parent);
parent.children.push(bone);
}
this.bones.push(bone);
}
this.slots = new Array();
this.drawOrder = new Array();
for (let i = 0; i < data.slots.length; i++) {
let slotData = data.slots[i];
let bone = this.bones[slotData.boneData.index];
let slot = new Slot(slotData, bone);
this.slots.push(slot);
this.drawOrder.push(slot);
}
this.ikConstraints = new Array();
for (let i = 0; i < data.ikConstraints.length; i++) {
let ikConstraintData = data.ikConstraints[i];
this.ikConstraints.push(new IkConstraint(ikConstraintData, this));
}
this.transformConstraints = new Array();
for (let i = 0; i < data.transformConstraints.length; i++) {
let transformConstraintData = data.transformConstraints[i];
this.transformConstraints.push(new TransformConstraint(transformConstraintData, this));
}
this.pathConstraints = new Array();
for (let i = 0; i < data.pathConstraints.length; i++) {
let pathConstraintData = data.pathConstraints[i];
this.pathConstraints.push(new PathConstraint(pathConstraintData, this));
}
this.physicsConstraints = new Array();
for (let i = 0; i < data.physicsConstraints.length; i++) {
let physicsConstraintData = data.physicsConstraints[i];
this.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this));
}
this.color = new Color(1, 1, 1, 1);
this.updateCache();
}
/** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones,
* constraints, or weighted path attachments are added or removed. */
updateCache() {
let updateCache = this._updateCache;
updateCache.length = 0;
let bones = this.bones;
for (let i = 0, n = bones.length; i < n; i++) {
let bone = bones[i];
bone.sorted = bone.data.skinRequired;
bone.active = !bone.sorted;
}
if (this.skin) {
let 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);
}
}
// IK first, lowest hierarchy depth first.
let ikConstraints = this.ikConstraints;
let transformConstraints = this.transformConstraints;
let pathConstraints = this.pathConstraints;
let physicsConstraints = this.physicsConstraints;
let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length;
let constraintCount = ikCount + transformCount + pathCount + physicsCount;
outer: for (let i = 0; i < constraintCount; i++) {
for (let ii = 0; ii < ikCount; ii++) {
let constraint = ikConstraints[ii];
if (constraint.data.order == i) {
this.sortIkConstraint(constraint);
continue outer;
}
}
for (let ii = 0; ii < transformCount; ii++) {
let constraint = transformConstraints[ii];
if (constraint.data.order == i) {
this.sortTransformConstraint(constraint);
continue outer;
}
}
for (let ii = 0; ii < pathCount; ii++) {
let constraint = pathConstraints[ii];
if (constraint.data.order == i) {
this.sortPathConstraint(constraint);
continue outer;
}
}
for (let ii = 0; ii < physicsCount; ii++) {
const constraint = physicsConstraints[ii];
if (constraint.data.order == i) {
this.sortPhysicsConstraint(constraint);
continue outer;
}
}
}
for (let i = 0, n = bones.length; i < n; i++)
this.sortBone(bones[i]);
}
sortIkConstraint(constraint) {
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)));
if (!constraint.active)
return;
let target = constraint.target;
this.sortBone(target);
let constrained = constraint.bones;
let parent = constrained[0];
this.sortBone(parent);
if (constrained.length == 1) {
this._updateCache.push(constraint);
this.sortReset(parent.children);
}
else {
let child = constrained[constrained.length - 1];
this.sortBone(child);
this._updateCache.push(constraint);
this.sortReset(parent.children);
child.sorted = true;
}
}
sortPathConstraint(constraint) {
constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)));
if (!constraint.active)
return;
let slot = constraint.target;
let slotIndex = slot.data.index;
let slotBone = slot.bone;
if (this.skin)
this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
if (this.data.defaultSkin && this.data.defaultSkin != this.skin)
this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);
for (let i = 0, n = this.data.skins.length; i < n; i++)
this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);
let attachment = slot.getAttachment();
if (attachment instanceof PathAttachment)
this.sortPathConstraintAttachmentWith(attachment, slotBone);
let constrained = constraint.bones;
let boneCount = constrained.length;
for (let i = 0; i < boneCount; i++)
this.sortBone(constrained[i]);
this._updateCache.push(constraint);
for (let i = 0; i < boneCount; i++)
this.sortReset(constrained[i].children);
for (let i = 0; i < boneCount; i++)
constrained[i].sorted = true;
}
sortTransformConstraint(constraint) {
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)));
if (!constraint.active)
return;
this.sortBone(constraint.target);
let constrained = constraint.bones;
let boneCount = constrained.length;
if (constraint.data.local) {
for (let i = 0; i < boneCount; i++) {
let child = constrained[i];
this.sortBone(child.parent);
this.sortBone(child);
}
}
else {
for (let i = 0; i < boneCount; i++) {
this.sortBone(constrained[i]);
}
}
this._updateCache.push(constraint);
for (let i = 0; i < boneCount; i++)
this.sortReset(constrained[i].children);
for (let i = 0; i < boneCount; i++)
constrained[i].sorted = true;
}
sortPathConstraintAttachment(skin, slotIndex, slotBone) {
let attachments = skin.attachments[slotIndex];
if (!attachments)
return;
for (let key in attachments) {
this.sortPathConstraintAttachmentWith(attachments[key], slotBone);
}
}
sortPathConstraintAttachmentWith(attachment, slotBone) {
if (!(attachment instanceof PathAttachment))
return;
let pathBones = attachment.bones;
if (!pathBones)
this.sortBone(slotBone);
else {
let bones = this.bones;
for (let i = 0, n = pathBones.length; i < n;) {
let nn = pathBones[i++];
nn += i;
while (i < nn)
this.sortBone(bones[pathBones[i++]]);
}
}
}
sortPhysicsConstraint(constraint) {
const bone = constraint.bone;
constraint.active = bone.active && (!constraint.data.skinRequired || (this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)));
if (!constraint.active)
return;
this.sortBone(bone);
this._updateCache.push(constraint);
this.sortReset(bone.children);
bone.sorted = true;
}
sortBone(bone) {
if (!bone)
return;
if (bone.sorted)
return;
let 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++) {
let bone = bones[i];
if (!bone.active)
continue;
if (bone.sorted)
this.sortReset(bone.children);
bone.sorted = false;
}
}
/** Updates the world transform for each bone and applies all constraints.
*
* See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
* Runtimes Guide. */
updateWorldTransform(physics) {
if (physics === undefined || physics === null)
throw new Error("physics is undefined");
let bones = this.bones;
for (let i = 0, n = bones.length; i < n; i++) {
let bone = bones[i];
bone.ax = bone.x;
bone.ay = bone.y;
bone.arotation = bone.rotation;
bone.ascaleX = bone.scaleX;
bone.ascaleY = bone.scaleY;
bone.ashearX = bone.shearX;
bone.ashearY = bone.shearY;
}
let updateCache = this._updateCache;
for (let i = 0, n = updateCache.length; i < n; i++)
updateCache[i].update(physics);
}
updateWorldTransformWith(physics, parent) {
if (!parent)
throw new Error("parent cannot be null.");
let bones = this.bones;
for (let i = 1, n = bones.length; i < n; i++) { // Skip root bone.
let bone = bones[i];
bone.ax = bone.x;
bone.ay = bone.y;
bone.arotation = bone.rotation;
bone.ascaleX = bone.scaleX;
bone.ascaleY = bone.scaleY;
bone.ashearX = bone.shearX;
bone.ashearY = bone.shearY;
}
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
let rootBone = this.getRootBone();
if (!rootBone)
throw new Error("Root bone must not be null.");
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
rootBone.worldX = pa * this.x + pb * this.y + parent.worldX;
rootBone.worldY = pc * this.x + pd * this.y + parent.worldY;
const rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad;
const ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad;
const la = Math.cos(rx) * rootBone.scaleX;
const lb = Math.cos(ry) * rootBone.scaleY;
const lc = Math.sin(rx) * rootBone.scaleX;
const ld = Math.sin(ry) * rootBone.scaleY;
rootBone.a = (pa * la + pb * lc) * this.scaleX;
rootBone.b = (pa * lb + pb * ld) * this.scaleX;
rootBone.c = (pc * la + pd * lc) * this.scaleY;
rootBone.d = (pc * lb + pd * ld) * this.scaleY;
// Update everything except root bone.
let updateCache = this._updateCache;
for (let i = 0, n = updateCache.length; i < n; i++) {
let updatable = updateCache[i];
if (updatable != rootBone)
updatable.update(physics);
}
}
/** Sets the bones, constraints, and slots to their setup pose values. */
setToSetupPose() {
this.setBonesToSetupPose();
this.setSlotsToSetupPose();
}
/** Sets the bones and constraints to their setup pose values. */
setBonesToSetupPose() {
for (const bone of this.bones)
bone.setToSetupPose();
for (const constraint of this.ikConstraints)
constraint.setToSetupPose();
for (const constraint of this.transformConstraints)
constraint.setToSetupPose();
for (const constraint of this.pathConstraints)
constraint.setToSetupPose();
for (const constraint of this.physicsConstraints)
constraint.setToSetupPose();
}
/** Sets the slots and draw order to their setup pose values. */
setSlotsToSetupPose() {
let slots = this.slots;
Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);
for (let i = 0, n = slots.length; i < n; i++)
slots[i].setToSetupPose();
}
/** @returns May return null. */
getRootBone() {
if (this.bones.length == 0)
return null;
return this.bones[0];
}
/** @returns May be null. */
findBone(boneName) {
if (!boneName)
throw new Error("boneName cannot be null.");
let bones = this.bones;
for (let i = 0, n = bones.length; i < n; i++) {
let bone = bones[i];
if (bone.data.name == boneName)
return bone;
}
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.
* @returns May be null. */
findSlot(slotName) {
if (!slotName)
throw new Error("slotName cannot be null.");
let slots = this.slots;
for (let i = 0, n = slots.length; i < n; i++) {
let slot = slots[i];
if (slot.data.name == slotName)
return slot;
}
return null;
}
/** Sets a skin by name.
*
* See {@link #setSkin()}. */
setSkinByName(skinName) {
let skin = this.data.findSkin(skinName);
if (!skin)
throw new Error("Skin not found: " + skinName);
this.setSkin(skin);
}
/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the
* skin is changed, {@link #updateCache()} is called.
*
* Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no
* old skin, each slot's setup mode attachment is attached from the new skin.
*
* After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
* {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the
* skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
* @param newSkin May be null. */
setSkin(newSkin) {
if (newSkin == this.skin)
return;
if (newSkin) {
if (this.skin)
newSkin.attachAll(this, this.skin);
else {
let slots = this.slots;
for (let i = 0, n = slots.length; i < n; i++) {
let slot = slots[i];
let name = slot.data.attachmentName;
if (name) {
let attachment = newSkin.getAttachment(i, name);
if (attachment)
slot.setAttachment(attachment);
}
}
}
}
this.skin = newSkin;
this.updateCache();
}
/** 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, attachmentName) {
let slot = this.data.findSlot(slotName);
if (!slot)
throw new Error(`Can't find slot with name ${slotName}`);
return this.getAttachment(slot.index, attachmentName);
}
/** 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. */
getAttachment(slotIndex, attachmentName) {
if (!attachmentName)
throw new Error("attachmentName cannot be null.");
if (this.skin) {
let attachment = this.skin.getAttachment(slotIndex, attachmentName);
if (attachment)
return attachment;
}
if (this.data.defaultSkin)
return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
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 attachmentName May be null to clear the slot's attachment. */
setAttachment(slotName, attachmentName) {
if (!slotName)
throw new Error("slotName cannot be null.");
let slots = this.slots;
for (let i = 0, n = slots.length; i < n; i++) {
let slot = slots[i];
if (slot.data.name == slotName) {
let attachment = null;
if (attachmentName) {
attachment = this.getAttachment(i, attachmentName);
if (!attachment)
throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName);
}
slot.setAttachment(attachment);
return;
}
}
throw new Error("Slot not found: " + slotName);
}
/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
* than to call it repeatedly.
* @return May be null. */
findIkConstraint(constraintName) {
if (!constraintName)
throw new Error("constraintName cannot be null.");
return this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;
}
/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
* this method than to call it repeatedly.
* @return May be null. */
findTransformConstraint(constraintName) {
if (!constraintName)
throw new Error("constraintName cannot be null.");
return this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;
}
/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
* than to call it repeatedly.
* @return May be null. */
findPathConstraint(constraintName) {
if (!constraintName)
throw new Error("constraintName cannot be null.");
return this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;
}
/** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this
* method than to call it repeatedly. */
findPhysicsConstraint(constraintName) {
if (constraintName == null)
throw new Error("constraintName cannot be null.");
return this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;
}
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`.
* Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */
getBoundsRect(clipper) {
let offset = new Vector2();
let 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 current 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.
* @param clipper {@link SkeletonClipping} to use. If <code>null</code>, 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.");
let drawOrder = this.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++) {
let slot = drawOrder[i];
if (!slot.bone.active)
continue;
let verticesLength = 0;
let vertices = null;
let triangles = null;
let attachment = slot.getAttachment();
if (attachment instanceof RegionAttachment) {
verticesLength = 8;
vertices = Utils.setArraySize(temp, verticesLength, 0);
attachment.computeWorldVertices(slot, vertices, 0, 2);
triangles = Skeleton.quadTriangles;
}
else if (attachment instanceof MeshAttachment) {
let mesh = attachment;
verticesLength = mesh.worldVerticesLength;
vertices = Utils.setArraySize(temp, verticesLength, 0);
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
triangles = mesh.triangles;
}
else if (attachment instanceof ClippingAttachment && clipper != null) {
clipper.clipStart(slot, attachment);
continue;
}
if (vertices && triangles) {
if (clipper != null && 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) {
let 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 != null)
clipper.clipEndWithSlot(slot);
}
if (clipper != null)
clipper.clipEnd();
offset.set(minX, minY);
size.set(maxX - minX, maxY - minY);
}
/** Increments the skeleton's {@link #time}. */
update(delta) {
this.time += delta;
}
physicsTranslate(x, y) {
const physicsConstraints = this.physicsConstraints;
for (let i = 0, n = physicsConstraints.length; i < n; i++)
physicsConstraints[i].translate(x, y);
}
/** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
physicsRotate(x, y, degrees) {
const physicsConstraints = this.physicsConstraints;
for (let i = 0, n = physicsConstraints.length; i < n; i++)
physicsConstraints[i].rotate(x, y, degrees);
}
}
/** Determines how physics and other non-deterministic updates are applied. */
export var Physics;
(function (Physics) {
/** Physics are not updated or applied. */
Physics[Physics["none"] = 0] = "none";
/** Physics are reset to the current pose. */
Physics[Physics["reset"] = 1] = "reset";
/** Physics are updated and the pose from physics is applied. */
Physics[Physics["update"] = 2] = "update";
/** Physics are not updated but the pose from physics is applied. */
Physics[Physics["pose"] = 3] = "pose";
})(Physics || (Physics = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU2tlbGV0b24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRy9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNqQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBSTNELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDakMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFL0QsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBbUIsTUFBTSxZQUFZLENBQUM7QUFFL0U7O2tJQUVrSTtBQUNsSSxNQUFNLE9BQU8sUUFBUTtJQUNaLE1BQU0sQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBRXJCLHNDQUFzQztJQUN0QyxJQUFJLENBQWU7SUFFbkIseUZBQXlGO0lBQ3pGLEtBQUssQ0FBYztJQUVuQix5REFBeUQ7SUFDekQsS0FBSyxD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LEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUN6RSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7UUFDMUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO1FBQzFDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUMxQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7UUFDMUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDL0MsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDL0MsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQ