diff --git a/spine-ts/spine-core/src/AnimationState.ts b/spine-ts/spine-core/src/AnimationState.ts
index bfcb0c6e4..8b3ef7d40 100644
--- a/spine-ts/spine-core/src/AnimationState.ts
+++ b/spine-ts/spine-core/src/AnimationState.ts
@@ -564,7 +564,7 @@ export class AnimationState {
return this.addAnimationWith(trackIndex, animation, loop, delay);
}
- /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is
+ /** Adds an animation to be played after the current or last queued animation for a track. If the track has no entries, this is
* equivalent to calling {@link #setAnimationWith()}.
* @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry
* minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix
@@ -609,7 +609,10 @@ export class AnimationState {
* {@link #addAnimation()} and on the returned track entry, set the
* {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and
* more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the
- * setup pose value if no lower tracks key the property to the value keyed in the new animation. */
+ * setup pose value if no lower tracks key the property to the value keyed in the new animation.
+ *
+ * See Empty animations in the Spine
+ * Runtimes Guide. */
setEmptyAnimation (trackIndex: number, mixDuration: number = 0) {
let entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation(), false);
entry.mixDuration = mixDuration;
@@ -618,16 +621,18 @@ export class AnimationState {
}
/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
- * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling
- * {@link #setEmptyAnimation()}.
- *
- * See {@link #setEmptyAnimation()}.
- * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry
- * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or
- * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next
+ * {@link TrackEntry#getMixDuration()}. If the track has no entries, it is equivalent to calling
+ * {@link #setEmptyAnimation(int, float)}.
+ *
+ * See {@link #setEmptyAnimation(int, float)} and
+ * Empty animations in the Spine
+ * Runtimes Guide.
+ * @param delay If > 0, sets {@link TrackEntry#getDelay()}. If <= 0, the delay set is the duration of the previous track entry
+ * minus any mix duration plus the specified delay (ie the mix ends at (delay = 0) or
+ * before (delay < 0) the previous track entry duration). If the previous entry is looping, its next
* loop completion is used instead of its duration.
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
- * after the {@link AnimationStateListener#dispose()} event occurs. */
+ * after the {@link AnimationStateListener#dispose(TrackEntry)} event occurs. */
addEmptyAnimation (trackIndex: number, mixDuration: number = 0, delay: number = 0) {
let entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation(), false, delay);
if (delay <= 0) entry.delay += entry.mixDuration - mixDuration;
@@ -636,8 +641,10 @@ export class AnimationState {
return entry;
}
- /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix
- * duration. */
+ /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.
+ *
+ * See Empty animations in the Spine
+ * Runtimes Guide. */
setEmptyAnimations (mixDuration: number = 0) {
let oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
diff --git a/spine-ts/spine-core/src/PathConstraint.ts b/spine-ts/spine-core/src/PathConstraint.ts
index 9bdd57d0e..4127691c3 100644
--- a/spine-ts/spine-core/src/PathConstraint.ts
+++ b/spine-ts/spine-core/src/PathConstraint.ts
@@ -51,7 +51,7 @@ export class PathConstraint implements Updatable {
bones: Array;
/** The slot whose path attachment will be used to constrained the bones. */
- target: Slot;
+ slot: Slot;
/** The position along the path. */
position = 0;
@@ -82,9 +82,9 @@ export class PathConstraint implements Updatable {
if (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
this.bones.push(bone);
}
- let target = skeleton.findSlot(data.target.name);
- if (!target) throw new Error(`Couldn't find target bone ${data.target.name}`);
- this.target = target;
+ let target = skeleton.findSlot(data.slot.name);
+ if (!target) throw new Error(`Couldn't find target bone ${data.slot.name}`);
+ this.slot = target;
this.position = data.position;
this.spacing = data.spacing;
@@ -107,7 +107,7 @@ export class PathConstraint implements Updatable {
}
update (physics: Physics) {
- let attachment = this.target.getAttachment();
+ let attachment = this.slot.getAttachment();
if (!(attachment instanceof PathAttachment)) return;
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
@@ -179,7 +179,7 @@ export class PathConstraint implements Updatable {
tip = data.rotateMode == RotateMode.Chain;
else {
tip = false;
- let p = this.target.bone;
+ let p = this.slot.bone;
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad;
}
for (let i = 0, p = 3; i < boneCount; i++, p += 3) {
@@ -232,7 +232,7 @@ export class PathConstraint implements Updatable {
}
computeWorldPositions (path: PathAttachment, spacesCount: number, tangents: boolean) {
- let target = this.target;
+ let slot = this.slot;
let position = this.position;
let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world: Array = this.world;
let closed = path.closed;
@@ -268,14 +268,14 @@ export class PathConstraint implements Updatable {
} else if (p < 0) {
if (prevCurve != PathConstraint.BEFORE) {
prevCurve = PathConstraint.BEFORE;
- path.computeWorldVertices(target, 2, 4, world, 0, 2);
+ path.computeWorldVertices(slot, 2, 4, world, 0, 2);
}
this.addBeforePosition(p, world, 0, out, o);
continue;
} else if (p > pathLength) {
if (prevCurve != PathConstraint.AFTER) {
prevCurve = PathConstraint.AFTER;
- path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
+ path.computeWorldVertices(slot, verticesLength - 6, 4, world, 0, 2);
}
this.addAfterPosition(p - pathLength, world, 0, out, o);
continue;
@@ -296,10 +296,10 @@ export class PathConstraint implements Updatable {
if (curve != prevCurve) {
prevCurve = curve;
if (closed && curve == curveCount) {
- path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
- path.computeWorldVertices(target, 0, 4, world, 4, 2);
+ path.computeWorldVertices(slot, verticesLength - 4, 4, world, 0, 2);
+ path.computeWorldVertices(slot, 0, 4, world, 4, 2);
} else
- path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
+ path.computeWorldVertices(slot, curve * 6 + 2, 8, world, 0, 2);
}
this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
tangents || (i > 0 && space == 0));
@@ -311,15 +311,15 @@ export class PathConstraint implements Updatable {
if (closed) {
verticesLength += 2;
world = Utils.setArraySize(this.world, verticesLength);
- path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
- path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
+ path.computeWorldVertices(slot, 2, verticesLength - 4, world, 0, 2);
+ path.computeWorldVertices(slot, 0, 2, world, verticesLength - 4, 2);
world[verticesLength - 2] = world[0];
world[verticesLength - 1] = world[1];
} else {
curveCount--;
verticesLength -= 4;
world = Utils.setArraySize(this.world, verticesLength);
- path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
+ path.computeWorldVertices(slot, 2, verticesLength, world, 0, 2);
}
// Curve lengths.
diff --git a/spine-ts/spine-core/src/PathConstraintData.ts b/spine-ts/spine-core/src/PathConstraintData.ts
index ffa65c697..f4eaa5a6e 100644
--- a/spine-ts/spine-core/src/PathConstraintData.ts
+++ b/spine-ts/spine-core/src/PathConstraintData.ts
@@ -41,11 +41,11 @@ export class PathConstraintData extends ConstraintData {
bones = new Array();
/** The slot whose path attachment will be used to constrained the bones. */
- private _target: SlotData | null = null;
- public set target (slotData: SlotData) { this._target = slotData; }
- public get target () {
- if (!this._target) throw new Error("SlotData not set.")
- else return this._target;
+ private _slot: SlotData | null = null;
+ public set slot (slotData: SlotData) { this._slot = slotData; }
+ public get slot () {
+ if (!this._slot) throw new Error("SlotData not set.")
+ else return this._slot;
}
/** The mode for positioning the first bone on the path. */
diff --git a/spine-ts/spine-core/src/Skeleton.ts b/spine-ts/spine-core/src/Skeleton.ts
index 6322d2688..141a794ab 100644
--- a/spine-ts/spine-core/src/Skeleton.ts
+++ b/spine-ts/spine-core/src/Skeleton.ts
@@ -241,8 +241,7 @@ export class Skeleton {
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);
+ this.sortBone(constraint.target);
let constrained = constraint.bones;
let parent = constrained[0];
@@ -263,11 +262,11 @@ export class Skeleton {
}
sortPathConstraint (constraint: PathConstraint) {
- constraint.active = constraint.target.bone.isActive()
+ constraint.active = constraint.slot.bone.isActive()
&& (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;
if (!constraint.active) return;
- let slot = constraint.target;
+ let slot = constraint.slot;
let slotIndex = slot.data.index;
let slotBone = slot.bone;
if (this.skin) this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
@@ -292,14 +291,14 @@ export class Skeleton {
}
sortTransformConstraint (constraint: TransformConstraint) {
- constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;
+ constraint.active = constraint.source.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;
if (!constraint.active) return;
- this.sortBone(constraint.target);
+ this.sortBone(constraint.source);
let constrained = constraint.bones;
let boneCount = constrained.length;
- if (constraint.data.localFrom) {
+ if (constraint.data.localSource) {
for (let i = 0; i < boneCount; i++) {
let child = constrained[i];
this.sortBone(child.parent!);
diff --git a/spine-ts/spine-core/src/SkeletonBinary.ts b/spine-ts/spine-core/src/SkeletonBinary.ts
index 555db38db..dfb2cd9d9 100644
--- a/spine-ts/spine-core/src/SkeletonBinary.ts
+++ b/spine-ts/spine-core/src/SkeletonBinary.ts
@@ -173,12 +173,12 @@ export class SkeletonBinary {
nn = input.readInt(true);
for (let ii = 0; ii < nn; ii++)
data.bones.push(skeletonData.bones[input.readInt(true)]);
- data.target = skeletonData.bones[input.readInt(true)];
+ data.source = skeletonData.bones[input.readInt(true)];
let flags = input.readUnsignedByte();
data.skinRequired = (flags & 1) != 0;
- data.localFrom = (flags & 2) != 0;
- data.localTo = (flags & 4) != 0;
- data.relative = (flags & 8) != 0;
+ data.localSource = (flags & 2) != 0;
+ data.localTarget = (flags & 4) != 0;
+ data.additive = (flags & 8) != 0;
data.clamp = (flags & 16) != 0;
nn = flags >> 5;
@@ -219,12 +219,15 @@ export class SkeletonBinary {
}
flags = input.readByte();
- if ((flags & 1) != 0) data.mixRotate = input.readFloat();
- if ((flags & 2) != 0) data.mixX = input.readFloat();
- if ((flags & 4) != 0) data.mixY = input.readFloat();
- if ((flags & 8) != 0) data.mixScaleX = input.readFloat();
- if ((flags & 16) != 0) data.mixScaleY = input.readFloat();
- if ((flags & 32) != 0) data.mixShearY = input.readFloat();
+ if ((flags & 1) != 0) data.offsetX = input.readFloat();
+ if ((flags & 2) != 0) data.offsetY = input.readFloat();
+ if ((flags & 4) != 0) data.mixRotate = input.readFloat();
+ if ((flags & 8) != 0) data.mixX = input.readFloat();
+ if ((flags & 16) != 0) data.mixY = input.readFloat();
+ if ((flags & 32) != 0) data.mixScaleX = input.readFloat();
+ if ((flags & 64) != 0) data.mixScaleY = input.readFloat();
+ if ((flags & 128) != 0) data.mixShearY = input.readFloat();
+
skeletonData.transformConstraints.push(data);
}
@@ -239,7 +242,7 @@ export class SkeletonBinary {
nn = input.readInt(true);
for (let ii = 0; ii < nn; ii++)
data.bones.push(skeletonData.bones[input.readInt(true)]);
- data.target = skeletonData.slots[input.readInt(true)];
+ data.slot = skeletonData.slots[input.readInt(true)];
const flags = input.readByte();
data.positionMode = flags & 1;
data.spacingMode = (flags >> 1) & 3;
diff --git a/spine-ts/spine-core/src/SkeletonJson.ts b/spine-ts/spine-core/src/SkeletonJson.ts
index 6a65deffc..72e7257d6 100644
--- a/spine-ts/spine-core/src/SkeletonJson.ts
+++ b/spine-ts/spine-core/src/SkeletonJson.ts
@@ -179,16 +179,17 @@ export class SkeletonJson {
data.bones.push(bone);
}
- let targetName: string = constraintMap.target;
- let target = skeletonData.findBone(targetName);
- if (!target) throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`);
- data.target = target;
+ let sourceName: string = constraintMap.source;
+ let source = skeletonData.findBone(sourceName);
+ if (!source) throw new Error(`Couldn't find source bone ${sourceName} for transform constraint ${constraintMap.name}.`);
+ data.source = source;
- data.localFrom = getValue(constraintMap, "localFrom", false);
- data.localFrom = getValue(constraintMap, "localTo", false);
- data.relative = getValue(constraintMap, "relative", false);
+ data.localSource = getValue(constraintMap, "localSource", false);
+ data.localTarget = getValue(constraintMap, "localTarget", false);
+ data.additive = getValue(constraintMap, "additive", false);
data.clamp = getValue(constraintMap, "clamp", false);
+ let rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false;
const propertiesEntries = Object.entries(getValue(constraintMap, "properties", {})) as [string, any][];
for (let ii = 0; ii < propertiesEntries.length; ii++) {
let name = propertiesEntries[ii][0];
@@ -209,12 +210,36 @@ export class SkeletonJson {
let name = toEntries[t][0];
let to: ToProperty;
switch (name) {
- case "rotate": to = new ToRotate(); break;
- case "x": to = new ToX(); break;
- case "y": to = new ToY(); break;
- case "scaleX": to = new ToScaleX(); break;
- case "scaleY": to = new ToScaleY(); break;
- case "shearY": to = new ToShearY(); break;
+ case "rotate": {
+ rotate = true
+ to = new ToRotate();
+ break;
+ }
+ case "x": {
+ x = true
+ to = new ToX();
+ break;
+ }
+ case "y": {
+ y = true
+ to = new ToY();
+ break;
+ }
+ case "scaleX": {
+ scaleX = true
+ to = new ToScaleX();
+ break;
+ }
+ case "scaleY": {
+ scaleY = true
+ to = new ToScaleY();
+ break;
+ }
+ case "shearY": {
+ shearY = true
+ to = new ToShearY();
+ break;
+ }
default: throw new Error("Invalid transform constraint to property: " + name);
}
let toEntry = toEntries[t][1];
@@ -226,12 +251,14 @@ export class SkeletonJson {
if (from.to.length > 0) data.properties.push(from);
}
- data.mixRotate = getValue(constraintMap, "mixRotate", 1);
- data.mixX = getValue(constraintMap, "mixX", 1);
- data.mixY = getValue(constraintMap, "mixY", data.mixX);
- data.mixScaleX = getValue(constraintMap, "mixScaleX", 1);
- data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX);
- data.mixShearY = getValue(constraintMap, "mixShearY", 1);
+ data.offsetX = getValue(constraintMap, "x", 0);
+ data.offsetY = getValue(constraintMap, "y", 0);
+ if (rotate) data.mixRotate = getValue(constraintMap, "mixRotate", 1);
+ if (x) data.mixX = getValue(constraintMap, "mixX", 1);
+ if (y) data.mixY = getValue(constraintMap, "mixY", data.mixX);
+ if (scaleX) data.mixScaleX = getValue(constraintMap, "mixScaleX", 1);
+ if (scaleY) data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX);
+ if (shearY) data.mixShearY = getValue(constraintMap, "mixShearY", 1);
skeletonData.transformConstraints.push(data);
}
@@ -252,10 +279,10 @@ export class SkeletonJson {
data.bones.push(bone);
}
- let targetName: string = constraintMap.target;
- let target = skeletonData.findSlot(targetName);
- if (!target) throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`);
- data.target = target;
+ let slotName: string = constraintMap.slot;
+ let slot = skeletonData.findSlot(slotName);
+ if (!slot) throw new Error(`Couldn't find slot ${slotName} for path constraint ${constraintMap.name}.`);
+ data.slot = slot;
data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent"));
data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length"));
diff --git a/spine-ts/spine-core/src/TransformConstraint.ts b/spine-ts/spine-core/src/TransformConstraint.ts
index 667370957..798656bf9 100644
--- a/spine-ts/spine-core/src/TransformConstraint.ts
+++ b/spine-ts/spine-core/src/TransformConstraint.ts
@@ -35,7 +35,7 @@ import { Vector2, MathUtils } from "./Utils.js";
/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
- * bones to match that of the target bone.
+ * bones to match that of the source bone.
*
* See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */
export class TransformConstraint implements Updatable {
@@ -46,8 +46,8 @@ export class TransformConstraint implements Updatable {
/** The bones that will be modified by this transform constraint. */
bones: Array;
- /** The target bone whose world transform will be copied to the constrained bones. */
- target: Bone;
+ /** The bone whose world transform will be copied to the constrained bones. */
+ source: Bone;
mixRotate = 0; mixX = 0; mixY = 0; mixScaleX = 0; mixScaleY = 0; mixShearY = 0;
@@ -65,9 +65,9 @@ export class TransformConstraint implements Updatable {
if (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
this.bones.push(bone);
}
- let target = skeleton.findBone(data.target.name);
- if (!target) throw new Error(`Couldn't find target bone ${data.target.name}.`);
- this.target = target;
+ let target = skeleton.findBone(data.source.name);
+ if (!target) throw new Error(`Couldn't find target bone ${data.source.name}.`);
+ this.source = target;
this.mixRotate = data.mixRotate;
this.mixX = data.mixX;
@@ -94,8 +94,9 @@ export class TransformConstraint implements Updatable {
update (physics: Physics) {
if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) return;
- const data = this.data, localFrom = data.localFrom, localTo = data.localTo, relative = data.relative, clamp = data.clamp;
- const target = this.target;
+ const data = this.data;
+ const localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
+ const source = this.source;
const fromItems = data.properties;
const fn = data.properties.length;
const bones = this.bones;
@@ -103,12 +104,11 @@ export class TransformConstraint implements Updatable {
const bone = bones[i];
for (let f = 0; f < fn; f++) {
const from = fromItems[f];
- const mix = from.mix(this);
- if (mix != 0) {
- const value = from.value(target, localFrom) - from.offset;
- const toItems = from.to;
- for (let t = 0, tn = from.to.length; t < tn; t++) {
- var to = toItems[t];
+ const value = from.value(data, source, localFrom) - from.offset;
+ const toItems = from.to;
+ for (let t = 0, tn = from.to.length; t < tn; t++) {
+ var to = toItems[t];
+ if (to.mix(this) != 0) {
let clamped = to.offset + value * to.scale;
if (clamp) {
if (to.offset < to.max)
@@ -116,11 +116,11 @@ export class TransformConstraint implements Updatable {
else
clamped = MathUtils.clamp(clamped, to.max, to.offset);
}
- to.apply(bone, clamped, localTo, relative, mix);
+ to.apply(this, bone, clamped, localTarget, additive);
}
}
}
- if (localTo)
+ if (localTarget)
bone.update(null);
else
bone.updateAppliedTransform();
diff --git a/spine-ts/spine-core/src/TransformConstraintData.ts b/spine-ts/spine-core/src/TransformConstraintData.ts
index 89f162d3e..a2d3c5376 100644
--- a/spine-ts/spine-core/src/TransformConstraintData.ts
+++ b/spine-ts/spine-core/src/TransformConstraintData.ts
@@ -41,29 +41,46 @@ export class TransformConstraintData extends ConstraintData {
/** The bones that will be modified by this transform constraint. */
bones = new Array();
- /** The target bone whose world transform will be copied to the constrained bones. */
- private _target: BoneData | null = null;
- public set target (boneData: BoneData) { this._target = boneData; }
- public get target () {
- if (!this._target) throw new Error("BoneData not set.")
- else return this._target;
+ /** The bone whose world transform will be copied to the constrained bones. */
+ private _source: BoneData | null = null;
+ public set source (source: BoneData) { this._source = source; }
+ public get source () {
+ if (!this._source) throw new Error("BoneData not set.")
+ else return this._source;
}
+ /** An offset added to the constrained bone X translation. */
+ offsetX = 0;
+
+ /** An offset added to the constrained bone Y translation. */
+ offsetY = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
mixRotate = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
mixX = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
mixY = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
mixScaleX = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */
mixScaleY = 0;
+
+ /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
mixShearY = 0;
- /** Reads the target bone's local transform instead of its world transform. */
- localFrom = false;
+ /** Reads the source bone's local transform instead of its world transform. */
+ localSource = false;
/** Sets the constrained bones' local transforms instead of their world transforms. */
- localTo = false;
+ localTarget = false;
- /** Adds the target bone transform to the constrained bones instead of setting it absolutely. */
- relative = false;
+ /** Adds the source bone transform to the constrained bones instead of setting it absolutely. */
+ additive = false;
/** Prevents constrained bones from exceeding the ranged defined by {@link ToProperty#offset} and {@link ToProperty#max}. */
clamp = false;
@@ -86,10 +103,7 @@ export abstract class FromProperty {
readonly to: Array = [];
/** Reads this property from the specified bone. */
- abstract value (target: Bone, local: boolean): number;
-
- /** Reads the mix for this property from the specified constraint. */
- abstract mix (constraint: TransformConstraint): number;
+ abstract value (data: TransformConstraintData, source: Bone, local: boolean): number;
}
/** Constrained property for a {@link TransformConstraint}. */
@@ -103,34 +117,37 @@ export abstract class ToProperty {
/** The scale of the {@link FromProperty} value in relation to this property. */
scale = 0;
+ /** Reads the mix for this property from the specified constraint. */
+ abstract mix (constraint: TransformConstraint): number;
+
/** Applies the value to this property. */
- abstract apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void;
+ abstract apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void;
}
export class FromRotate extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.arotation : Math.atan2(target.c, target.a) * MathUtils.radDeg;
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixRotate;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.arotation : Math.atan2(source.c, source.a) * MathUtils.radDeg;
}
}
export class ToRotate extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixRotate;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (!relative) value -= bone.arotation;
- bone.arotation += value * mix;
+ if (!additive) value -= bone.arotation;
+ bone.arotation += value * constraint.mixRotate;
} else {
const a = bone.a, b = bone.b, c = bone.c, d = bone.d;
value *= MathUtils.degRad;
- if (!relative) value -= Math.atan2(c, a);
+ if (!additive) value -= Math.atan2(c, a);
if (value > MathUtils.PI)
value -= MathUtils.PI2;
else if (value < -MathUtils.PI) //
value += MathUtils.PI2;
- value *= mix;
+ value *= constraint.mixRotate;
const cos = Math.cos(value), sin = Math.sin(value);
bone.a = cos * a - sin * c;
bone.b = cos * b - sin * d;
@@ -141,73 +158,73 @@ export class ToRotate extends ToProperty {
}
export class FromX extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.ax : target.worldX;
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixX;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.ax + data.offsetX : data.offsetX * source.a + data.offsetY * source.b + source.worldX;
}
}
export class ToX extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixX;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (!relative) value -= bone.ax;
- bone.ax += value * mix;
+ if (!additive) value -= bone.ax;
+ bone.ax += value * constraint.mixX;
} else {
- if (!relative) value -= bone.worldX;
- bone.worldX += value * mix;
+ if (!additive) value -= bone.worldX;
+ bone.worldX += value * constraint.mixX;
}
}
}
export class FromY extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.ay : target.worldY;
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixY;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.ay + data.offsetY : data.offsetX * source.c + data.offsetY * source.d + source.worldY;
}
}
export class ToY extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixY;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (!relative) value -= bone.ay;
- bone.ay += value * mix;
+ if (!additive) value -= bone.ay;
+ bone.ay += value * constraint.mixY;
} else {
- if (!relative) value -= bone.worldY;
- bone.worldY += value * mix;
+ if (!additive) value -= bone.worldY;
+ bone.worldY += value * constraint.mixY;
}
}
}
export class FromScaleX extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.ascaleX : Math.sqrt(target.a * target.a + target.c * target.c);
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixScaleX;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.ascaleX : Math.sqrt(source.a * source.a + source.c * source.c);
}
}
export class ToScaleX extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixScaleX;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (relative)
- bone.ascaleX *= 1 + ((value - 1) * mix);
- else if (bone.ascaleX != 0) //
- bone.ascaleX = 1 + (value / bone.ascaleX - 1) * mix;
+ if (additive)
+ bone.ascaleX *= 1 + ((value - 1) * constraint.mixScaleX);
+ else if (bone.ascaleX != 0)
+ bone.ascaleX = 1 + (value / bone.ascaleX - 1) * constraint.mixScaleX;
} else {
let s: number;
- if (relative)
- s = 1 + (value - 1) * mix;
+ if (additive)
+ s = 1 + (value - 1) * constraint.mixScaleX;
else {
s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
- if (s != 0) s = 1 + (value / s - 1) * mix;
+ if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleX;
}
bone.a *= s;
bone.c *= s;
@@ -216,29 +233,29 @@ export class ToScaleX extends ToProperty {
}
export class FromScaleY extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.ascaleY : Math.sqrt(target.b * target.b + target.d * target.d);
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixScaleY;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.ascaleY : Math.sqrt(source.b * source.b + source.d * source.d);
}
}
export class ToScaleY extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixScaleY;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (relative)
- bone.ascaleY *= 1 + ((value - 1) * mix);
+ if (additive)
+ bone.ascaleY *= 1 + ((value - 1) * constraint.mixScaleY);
else if (bone.ascaleY != 0) //
- bone.ascaleY = 1 + (value / bone.ascaleY - 1) * mix;
+ bone.ascaleY = 1 + (value / bone.ascaleY - 1) * constraint.mixScaleY;
} else {
let s: number;
- if (relative)
- s = 1 + (value - 1) * mix;
+ if (additive)
+ s = 1 + (value - 1) * constraint.mixScaleY;
else {
s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
- if (s != 0) s = 1 + (value / s - 1) * mix;
+ if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleY;
}
bone.b *= s;
bone.d *= s;
@@ -247,33 +264,33 @@ export class ToScaleY extends ToProperty {
}
export class FromShearY extends FromProperty {
- value (target: Bone, local: boolean): number {
- return local ? target.ashearY : (Math.atan2(target.d, target.b) - Math.atan2(target.c, target.a)) * MathUtils.radDeg - 90;
- }
-
- mix (constraint: TransformConstraint): number {
- return constraint.mixShearY;
+ value (data: TransformConstraintData, source: Bone, local: boolean): number {
+ return local ? source.ashearY : (Math.atan2(source.d, source.b) - Math.atan2(source.c, source.a)) * MathUtils.radDeg - 90;
}
}
export class ToShearY extends ToProperty {
- apply (bone: Bone, value: number, local: boolean, relative: boolean, mix: number): void {
+ mix (constraint: TransformConstraint): number {
+ return constraint.mixShearY;
+ }
+
+ apply (constraint: TransformConstraint, bone: Bone, value: number, local: boolean, additive: boolean): void {
if (local) {
- if (!relative) value -= bone.ashearY;
- bone.ashearY += value * mix;
+ if (!additive) value -= bone.ashearY;
+ bone.ashearY += value * constraint.mixShearY;
} else {
const b = bone.b, d = bone.d, by = Math.atan2(d, b);
value = (value + 90) * MathUtils.degRad;
- if (relative)
+ if (additive)
value -= MathUtils.PI / 2;
else {
value -= by - Math.atan2(bone.c, bone.a);
if (value > MathUtils.PI)
value -= MathUtils.PI2;
- else if (value < -MathUtils.PI) //
+ else if (value < -MathUtils.PI)
value += MathUtils.PI2;
}
- value = by + value * mix;
+ value = by + value * constraint.mixShearY;
const s = Math.sqrt(b * b + d * d);
bone.b = Math.cos(value) * s;
bone.d = Math.sin(value) * s;