浏览代码

* Added separate X and Y for transform constraint translate and scale mix.
* Renamed `xxxMix` to `mixXxx` to avoid names like `scaleXMix`.

Nathan Sweet 4 年之前
父节点
当前提交
dbd90caa53

+ 73 - 54
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java

@@ -188,7 +188,7 @@ public class Animation {
 	}
 
 	static private enum Property {
-		rotate, translateX, translateY, scaleX, scaleY, shearX, shearY, //
+		rotate, x, y, scaleX, scaleY, shearX, shearY, //
 		rgb, alpha, rgb2, //
 		attachment, deform, //
 		event, drawOrder, //
@@ -316,7 +316,7 @@ public class Animation {
 		 * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and <code>bezierCount - 1</code> (specified
 		 *           in the constructor), inclusive.
 		 * @param frame Between 0 and <code>frameCount - 1</code>, inclusive.
-		 * @param value The index of the value for this frame that this curve is used for.
+		 * @param value The index of the value for the frame this curve is used for.
 		 * @param time1 The time for the first key.
 		 * @param value1 The value for the first key.
 		 * @param cx1 The time for the first Bezier handle.
@@ -494,8 +494,8 @@ public class Animation {
 
 		public TranslateTimeline (int frameCount, int bezierCount, int boneIndex) {
 			super(frameCount, bezierCount, //
-				Property.translateX.ordinal() + "|" + boneIndex, //
-				Property.translateY.ordinal() + "|" + boneIndex);
+				Property.x.ordinal() + "|" + boneIndex, //
+				Property.y.ordinal() + "|" + boneIndex);
 			this.boneIndex = boneIndex;
 		}
 
@@ -565,7 +565,7 @@ public class Animation {
 		final int boneIndex;
 
 		public TranslateXTimeline (int frameCount, int bezierCount, int boneIndex) {
-			super(frameCount, bezierCount, Property.translateX.ordinal() + "|" + boneIndex);
+			super(frameCount, bezierCount, Property.x.ordinal() + "|" + boneIndex);
 			this.boneIndex = boneIndex;
 		}
 
@@ -611,7 +611,7 @@ public class Animation {
 		final int boneIndex;
 
 		public TranslateYTimeline (int frameCount, int bezierCount, int boneIndex) {
-			super(frameCount, bezierCount, Property.translateY.ordinal() + "|" + boneIndex);
+			super(frameCount, bezierCount, Property.y.ordinal() + "|" + boneIndex);
 			this.boneIndex = boneIndex;
 		}
 
@@ -2109,11 +2109,12 @@ public class Animation {
 		}
 	}
 
-	/** Changes a transform constraint's {@link TransformConstraint#getRotateMix()}, {@link TransformConstraint#getTranslateMix()},
-	 * {@link TransformConstraint#getScaleMix()}, and {@link TransformConstraint#getShearMix()}. */
+	/** Changes a transform constraint's {@link TransformConstraint#getMixRotate()}, {@link TransformConstraint#getMixX()},
+	 * {@link TransformConstraint#getMixY()}, {@link TransformConstraint#getMixScaleX()},
+	 * {@link TransformConstraint#getMixScaleY()}, and {@link TransformConstraint#getMixShearY()}. */
 	static public class TransformConstraintTimeline extends CurveTimeline {
-		static public final int ENTRIES = 5;
-		static private final int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4;
+		static public final int ENTRIES = 7;
+		static private final int ROTATE = 1, X = 2, Y = 3, SCALEX = 4, SCALEY = 5, SHEARY = 6;
 
 		final int transformConstraintIndex;
 
@@ -2135,13 +2136,16 @@ public class Animation {
 		/** Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame.
 		 * @param frame Between 0 and <code>frameCount</code>, inclusive.
 		 * @param time The frame time in seconds. */
-		public void setFrame (int frame, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) {
+		public void setFrame (int frame, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY,
+			float mixShearY) {
 			frame *= ENTRIES;
 			frames[frame] = time;
-			frames[frame + ROTATE] = rotateMix;
-			frames[frame + TRANSLATE] = translateMix;
-			frames[frame + SCALE] = scaleMix;
-			frames[frame + SHEAR] = shearMix;
+			frames[frame + ROTATE] = mixRotate;
+			frames[frame + X] = mixX;
+			frames[frame + Y] = mixY;
+			frames[frame + SCALEX] = mixScaleX;
+			frames[frame + SCALEY] = mixScaleY;
+			frames[frame + SHEARY] = mixShearY;
 		}
 
 		public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
@@ -2155,59 +2159,75 @@ public class Animation {
 				TransformConstraintData data = constraint.data;
 				switch (blend) {
 				case setup:
-					constraint.rotateMix = data.rotateMix;
-					constraint.translateMix = data.translateMix;
-					constraint.scaleMix = data.scaleMix;
-					constraint.shearMix = data.shearMix;
+					constraint.mixRotate = data.mixRotate;
+					constraint.mixX = data.mixX;
+					constraint.mixY = data.mixY;
+					constraint.mixScaleX = data.mixScaleX;
+					constraint.mixScaleY = data.mixScaleY;
+					constraint.mixShearY = data.mixShearY;
 					return;
 				case first:
-					constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha;
-					constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha;
-					constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;
-					constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha;
+					constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;
+					constraint.mixX += (data.mixX - constraint.mixX) * alpha;
+					constraint.mixY += (data.mixY - constraint.mixY) * alpha;
+					constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;
+					constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;
+					constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;
 				}
 				return;
 			}
 
-			float rotate, translate, scale, shear;
+			float rotate, x, y, scaleX, scaleY, shearY;
 			int i = search(frames, time, ENTRIES), curveType = (int)curves[i / ENTRIES];
 			switch (curveType) {
 			case LINEAR:
 				float before = frames[i];
 				rotate = frames[i + ROTATE];
-				translate = frames[i + TRANSLATE];
-				scale = frames[i + SCALE];
-				shear = frames[i + SHEAR];
+				x = frames[i + X];
+				y = frames[i + Y];
+				scaleX = frames[i + SCALEX];
+				scaleY = frames[i + SCALEY];
+				shearY = frames[i + SHEARY];
 				float t = (time - before) / (frames[i + ENTRIES] - before);
 				rotate += (frames[i + ENTRIES + ROTATE] - rotate) * t;
-				translate += (frames[i + ENTRIES + TRANSLATE] - translate) * t;
-				scale += (frames[i + ENTRIES + SCALE] - scale) * t;
-				shear += (frames[i + ENTRIES + SHEAR] - shear) * t;
+				x += (frames[i + ENTRIES + X] - x) * t;
+				y += (frames[i + ENTRIES + Y] - y) * t;
+				scaleX += (frames[i + ENTRIES + SCALEX] - scaleX) * t;
+				scaleY += (frames[i + ENTRIES + SCALEY] - scaleY) * t;
+				shearY += (frames[i + ENTRIES + SHEARY] - shearY) * t;
 				break;
 			case STEPPED:
 				rotate = frames[i + ROTATE];
-				translate = frames[i + TRANSLATE];
-				scale = frames[i + SCALE];
-				shear = frames[i + SHEAR];
+				x = frames[i + X];
+				y = frames[i + Y];
+				scaleX = frames[i + SCALEX];
+				scaleY = frames[i + SCALEY];
+				shearY = frames[i + SHEARY];
 				break;
 			default:
 				rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER);
-				translate = getBezierValue(time, i, TRANSLATE, curveType + BEZIER_SIZE - BEZIER);
-				scale = getBezierValue(time, i, TRANSLATE, curveType + BEZIER_SIZE * 2 - BEZIER);
-				shear = getBezierValue(time, i, TRANSLATE, curveType + BEZIER_SIZE * 3 - BEZIER);
+				x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
+				y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
+				scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER);
+				scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER);
+				shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER);
 			}
 
 			if (blend == setup) {
 				TransformConstraintData data = constraint.data;
-				constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha;
-				constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha;
-				constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha;
-				constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha;
+				constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
+				constraint.mixX = data.mixX + (x - data.mixX) * alpha;
+				constraint.mixY = data.mixY + (y - data.mixY) * alpha;
+				constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;
+				constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;
+				constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;
 			} else {
-				constraint.rotateMix += (rotate - constraint.rotateMix) * alpha;
-				constraint.translateMix += (translate - constraint.translateMix) * alpha;
-				constraint.scaleMix += (scale - constraint.scaleMix) * alpha;
-				constraint.shearMix += (shear - constraint.shearMix) * alpha;
+				constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
+				constraint.mixX += (x - constraint.mixX) * alpha;
+				constraint.mixY += (y - constraint.mixY) * alpha;
+				constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;
+				constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;
+				constraint.mixShearY += (shearY - constraint.mixShearY) * alpha;
 			}
 		}
 	}
@@ -2292,8 +2312,7 @@ public class Animation {
 		}
 	}
 
-	/** Changes a transform constraint's {@link PathConstraint#getRotateMix()} and
-	 * {@link TransformConstraint#getTranslateMix()}. */
+	/** Changes a transform constraint's {@link PathConstraint#getMixRotate()} and {@link PathConstraint#getMixTranslate()}. */
 	static public class PathConstraintMixTimeline extends CurveTimeline2 {
 		final int pathConstraintIndex;
 
@@ -2318,12 +2337,12 @@ public class Animation {
 			if (time < frames[0]) { // Time is before first frame.
 				switch (blend) {
 				case setup:
-					constraint.rotateMix = constraint.data.rotateMix;
-					constraint.translateMix = constraint.data.translateMix;
+					constraint.mixRotate = constraint.data.mixRotate;
+					constraint.mixTranslate = constraint.data.mixTranslate;
 					return;
 				case first:
-					constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha;
-					constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha;
+					constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha;
+					constraint.mixTranslate += (constraint.data.mixTranslate - constraint.mixTranslate) * alpha;
 				}
 				return;
 			}
@@ -2349,11 +2368,11 @@ public class Animation {
 			}
 
 			if (blend == setup) {
-				constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha;
-				constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha;
+				constraint.mixRotate = constraint.data.mixRotate + (rotate - constraint.data.mixRotate) * alpha;
+				constraint.mixTranslate = constraint.data.mixTranslate + (translate - constraint.data.mixTranslate) * alpha;
 			} else {
-				constraint.rotateMix += (rotate - constraint.rotateMix) * alpha;
-				constraint.translateMix += (translate - constraint.translateMix) * alpha;
+				constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
+				constraint.mixTranslate += (translate - constraint.mixTranslate) * alpha;
 			}
 		}
 	}

+ 1 - 1
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java

@@ -109,7 +109,7 @@ public class IkConstraint implements Updatable {
 		this.target = target;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
 	public float getMix () {
 		return mix;
 	}

+ 1 - 1
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java

@@ -60,7 +60,7 @@ public class IkConstraintData extends ConstraintData {
 		this.target = target;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
 	public float getMix () {
 		return mix;
 	}

+ 23 - 23
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java

@@ -50,7 +50,7 @@ public class PathConstraint implements Updatable {
 	final PathConstraintData data;
 	final Array<Bone> bones;
 	Slot target;
-	float position, spacing, rotateMix, translateMix;
+	float position, spacing, mixRotate, mixTranslate;
 
 	boolean active;
 
@@ -68,8 +68,8 @@ public class PathConstraint implements Updatable {
 		target = skeleton.findSlot(data.target.name);
 		position = data.position;
 		spacing = data.spacing;
-		rotateMix = data.rotateMix;
-		translateMix = data.translateMix;
+		mixRotate = data.mixRotate;
+		mixTranslate = data.mixTranslate;
 	}
 
 	/** Copy constructor. */
@@ -83,8 +83,8 @@ public class PathConstraint implements Updatable {
 		target = skeleton.slots.get(constraint.target.data.index);
 		position = constraint.position;
 		spacing = constraint.spacing;
-		rotateMix = constraint.rotateMix;
-		translateMix = constraint.translateMix;
+		mixRotate = constraint.mixRotate;
+		mixTranslate = constraint.mixTranslate;
 	}
 
 	/** Applies the constraint to the constrained bones. */
@@ -92,8 +92,8 @@ public class PathConstraint implements Updatable {
 		Attachment attachment = target.attachment;
 		if (!(attachment instanceof PathAttachment)) return;
 
-		float rotateMix = this.rotateMix, translateMix = this.translateMix;
-		boolean translate = translateMix > 0, rotate = rotateMix > 0;
+		float mixRotate = this.mixRotate, mixTranslate = this.mixTranslate;
+		boolean translate = mixTranslate > 0, rotate = mixRotate > 0;
 		if (!translate && !rotate) return;
 
 		PathConstraintData data = this.data;
@@ -145,13 +145,13 @@ public class PathConstraint implements Updatable {
 		}
 		for (int i = 0, p = 3; i < boneCount; i++, p += 3) {
 			Bone bone = (Bone)bones[i];
-			bone.worldX += (boneX - bone.worldX) * translateMix;
-			bone.worldY += (boneY - bone.worldY) * translateMix;
+			bone.worldX += (boneX - bone.worldX) * mixTranslate;
+			bone.worldY += (boneY - bone.worldY) * mixTranslate;
 			float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
 			if (scale) {
 				float length = lengths[i];
 				if (length >= epsilon) {
-					float s = ((float)Math.sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
+					float s = ((float)Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
 					bone.a *= s;
 					bone.c *= s;
 				}
@@ -171,15 +171,15 @@ public class PathConstraint implements Updatable {
 					cos = (float)Math.cos(r);
 					sin = (float)Math.sin(r);
 					float length = bone.data.length;
-					boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
-					boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
+					boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
+					boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
 				} else
 					r += offsetRotation;
 				if (r > SpineUtils.PI)
 					r -= SpineUtils.PI2;
 				else if (r < -SpineUtils.PI) //
 					r += SpineUtils.PI2;
-				r *= rotateMix;
+				r *= mixRotate;
 				cos = (float)Math.cos(r);
 				sin = (float)Math.sin(r);
 				bone.a = cos * a - sin * c;
@@ -464,22 +464,22 @@ public class PathConstraint implements Updatable {
 		this.spacing = spacing;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
-	public float getRotateMix () {
-		return rotateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
+	public float getMixRotate () {
+		return mixRotate;
 	}
 
-	public void setRotateMix (float rotateMix) {
-		this.rotateMix = rotateMix;
+	public void setMixRotate (float mixRotate) {
+		this.mixRotate = mixRotate;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
-	public float getTranslateMix () {
-		return translateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation. */
+	public float getMixTranslate () {
+		return mixTranslate;
 	}
 
-	public void setTranslateMix (float translateMix) {
-		this.translateMix = translateMix;
+	public void setMixTranslate (float mixTranslate) {
+		this.mixTranslate = mixTranslate;
 	}
 
 	/** The bones that will be modified by this path constraint. */

+ 11 - 11
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java

@@ -41,7 +41,7 @@ public class PathConstraintData extends ConstraintData {
 	SpacingMode spacingMode;
 	RotateMode rotateMode;
 	float offsetRotation;
-	float position, spacing, rotateMix, translateMix;
+	float position, spacing, mixRotate, mixTranslate;
 
 	public PathConstraintData (String name) {
 		super(name);
@@ -119,22 +119,22 @@ public class PathConstraintData extends ConstraintData {
 		this.spacing = spacing;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
-	public float getRotateMix () {
-		return rotateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
+	public float getMixRotate () {
+		return mixRotate;
 	}
 
-	public void setRotateMix (float rotateMix) {
-		this.rotateMix = rotateMix;
+	public void setMixRotate (float mixRotate) {
+		this.mixRotate = mixRotate;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
-	public float getTranslateMix () {
-		return translateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation. */
+	public float getMixTranslate () {
+		return mixTranslate;
 	}
 
-	public void setTranslateMix (float translateMix) {
-		this.translateMix = translateMix;
+	public void setMixTranslate (float mixTranslate) {
+		this.mixTranslate = mixTranslate;
 	}
 
 	/** Controls how the first bone is positioned along the path.

+ 8 - 6
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java

@@ -405,10 +405,12 @@ public class Skeleton {
 		for (int i = 0, n = this.transformConstraints.size; i < n; i++) {
 			TransformConstraint constraint = (TransformConstraint)transformConstraints[i];
 			TransformConstraintData data = constraint.data;
-			constraint.rotateMix = data.rotateMix;
-			constraint.translateMix = data.translateMix;
-			constraint.scaleMix = data.scaleMix;
-			constraint.shearMix = data.shearMix;
+			constraint.mixRotate = data.mixRotate;
+			constraint.mixX = data.mixX;
+			constraint.mixY = data.mixY;
+			constraint.mixScaleX = data.mixScaleX;
+			constraint.mixScaleY = data.mixScaleY;
+			constraint.mixShearY = data.mixShearY;
 		}
 
 		Object[] pathConstraints = this.pathConstraints.items;
@@ -417,8 +419,8 @@ public class Skeleton {
 			PathConstraintData data = constraint.data;
 			constraint.position = data.position;
 			constraint.spacing = data.spacing;
-			constraint.rotateMix = data.rotateMix;
-			constraint.translateMix = data.translateMix;
+			constraint.mixRotate = data.mixRotate;
+			constraint.mixTranslate = data.mixTranslate;
 		}
 	}
 

+ 25 - 19
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java

@@ -239,10 +239,12 @@ public class SkeletonBinary extends SkeletonLoader {
 				data.offsetScaleX = input.readFloat();
 				data.offsetScaleY = input.readFloat();
 				data.offsetShearY = input.readFloat();
-				data.rotateMix = input.readFloat();
-				data.translateMix = input.readFloat();
-				data.scaleMix = input.readFloat();
-				data.shearMix = input.readFloat();
+				data.mixRotate = input.readFloat();
+				data.mixX = input.readFloat();
+				data.mixY = input.readFloat();
+				data.mixScaleX = input.readFloat();
+				data.mixScaleY = input.readFloat();
+				data.mixShearY = input.readFloat();
 				o[i] = data;
 			}
 
@@ -264,8 +266,8 @@ public class SkeletonBinary extends SkeletonLoader {
 				if (data.positionMode == PositionMode.fixed) data.position *= scale;
 				data.spacing = input.readFloat();
 				if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale;
-				data.rotateMix = input.readFloat();
-				data.translateMix = input.readFloat();
+				data.mixRotate = input.readFloat();
+				data.mixTranslate = input.readFloat();
 				o[i] = data;
 			}
 
@@ -810,28 +812,32 @@ public class SkeletonBinary extends SkeletonLoader {
 		for (int i = 0, n = input.readInt(true); i < n; i++) {
 			int index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;
 			TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index);
-			float time = input.readFloat(), rotateMix = input.readFloat(), translateMix = input.readFloat(),
-				scaleMix = input.readFloat(), shearMix = input.readFloat();
+			float time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(),
+				mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat();
 			for (int frame = 0, bezier = 0;; frame++) {
-				timeline.setFrame(frame, time, rotateMix, translateMix, scaleMix, shearMix);
+				timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
 				if (frame == frameLast) break;
-				float time2 = input.readFloat(), rotateMix2 = input.readFloat(), translateMix2 = input.readFloat(),
-					scaleMix2 = input.readFloat(), shearMix2 = input.readFloat();
+				float time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(),
+					mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat();
 				switch (input.readByte()) {
 				case CURVE_STEPPED:
 					timeline.setStepped(frame);
 					break;
 				case CURVE_BEZIER:
-					setBezier(input, timeline, bezier++, frame, 0, time, time2, rotateMix, rotateMix2, 1);
-					setBezier(input, timeline, bezier++, frame, 1, time, time2, translateMix, translateMix2, 1);
-					setBezier(input, timeline, bezier++, frame, 2, time, time2, scaleMix, scaleMix2, 1);
-					setBezier(input, timeline, bezier++, frame, 3, time, time2, shearMix, shearMix2, 1);
+					setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
+					setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
+					setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
+					setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
+					setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
+					setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);
 				}
 				time = time2;
-				rotateMix = rotateMix2;
-				translateMix = translateMix2;
-				scaleMix = scaleMix2;
-				shearMix = shearMix2;
+				mixRotate = mixRotate2;
+				mixX = mixX2;
+				mixY = mixY2;
+				mixScaleX = mixScaleX2;
+				mixScaleY = mixScaleY2;
+				mixShearY = mixShearY2;
 			}
 			timelines.add(timeline);
 		}

+ 1 - 1
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java

@@ -57,7 +57,7 @@ public class SkeletonBounds {
 		if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
 		Array<BoundingBoxAttachment> boundingBoxes = this.boundingBoxes;
 		Array<FloatArray> polygons = this.polygons;
-		Object[]  slots = skeleton.slots.items;
+		Object[] slots = skeleton.slots.items;
 		int slotCount = skeleton.slots.size;
 
 		boundingBoxes.clear();

+ 28 - 20
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java

@@ -226,10 +226,12 @@ public class SkeletonJson extends SkeletonLoader {
 			data.offsetScaleY = constraintMap.getFloat("scaleY", 0);
 			data.offsetShearY = constraintMap.getFloat("shearY", 0);
 
-			data.rotateMix = constraintMap.getFloat("rotateMix", 1);
-			data.translateMix = constraintMap.getFloat("translateMix", 1);
-			data.scaleMix = constraintMap.getFloat("scaleMix", 1);
-			data.shearMix = constraintMap.getFloat("shearMix", 1);
+			data.mixRotate = constraintMap.getFloat("mixRotate", 1);
+			data.mixX = constraintMap.getFloat("mixX", 1);
+			data.mixY = constraintMap.getFloat("mixY", data.mixX);
+			data.mixScaleX = constraintMap.getFloat("mixScaleX", 1);
+			data.mixScaleY = constraintMap.getFloat("mixScaleY", data.mixScaleX);
+			data.mixShearY = constraintMap.getFloat("mixShearY", 1);
 
 			skeletonData.transformConstraints.add(data);
 		}
@@ -258,8 +260,8 @@ public class SkeletonJson extends SkeletonLoader {
 			if (data.positionMode == PositionMode.fixed) data.position *= scale;
 			data.spacing = constraintMap.getFloat("spacing", 0);
 			if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale;
-			data.rotateMix = constraintMap.getFloat("rotateMix", 1);
-			data.translateMix = constraintMap.getFloat("translateMix", 1);
+			data.mixRotate = constraintMap.getFloat("mixRotate", 1);
+			data.mixTranslate = constraintMap.getFloat("mixTranslate", 1);
 
 			skeletonData.pathConstraints.add(data);
 		}
@@ -765,30 +767,36 @@ public class SkeletonJson extends SkeletonLoader {
 			TransformConstraintTimeline timeline = new TransformConstraintTimeline(timelineMap.size, timelineMap.size << 2,
 				skeletonData.getTransformConstraints().indexOf(constraint, true));
 			float time = keyMap.getFloat("time", 0);
-			float rotateMix = keyMap.getFloat("rotateMix", 1), translateMix = keyMap.getFloat("translateMix", 1);
-			float scaleMix = keyMap.getFloat("scaleMix", 1), shearMix = keyMap.getFloat("shearMix", 1);
+			float mixRotate = keyMap.getFloat("mixRotate", 1), mixShearY = keyMap.getFloat("mixShearY", 1);
+			float mixX = keyMap.getFloat("mixX", 1), mixY = keyMap.getFloat("mixY", mixX);
+			float mixScaleX = keyMap.getFloat("mixScaleX", 1), mixScaleY = keyMap.getFloat("mixScaleY", mixScaleX);
 			for (int frame = 0, bezier = 0;; frame++) {
-				timeline.setFrame(frame, time, rotateMix, translateMix, scaleMix, shearMix);
+				timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
 				JsonValue nextMap = keyMap.next;
 				if (nextMap == null) {
 					timeline.shrink(bezier);
 					break;
 				}
 				float time2 = nextMap.getFloat("time", 0);
-				float rotateMix2 = nextMap.getFloat("rotateMix", 1), translateMix2 = nextMap.getFloat("translateMix", 1);
-				float scaleMix2 = nextMap.getFloat("scaleMix", 1), shearMix2 = nextMap.getFloat("shearMix", 1);
+				float mixRotate2 = nextMap.getFloat("mixRotate", 1), mixShearY2 = nextMap.getFloat("mixShearY", 1);
+				float mixX2 = nextMap.getFloat("mixX", 1), mixY2 = nextMap.getFloat("mixY", mixX2);
+				float mixScaleX2 = nextMap.getFloat("mixScaleX", 1), mixScaleY2 = nextMap.getFloat("mixScaleY", mixScaleX2);
 				JsonValue curve = keyMap.get("curve");
 				if (curve != null) {
-					bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, rotateMix, rotateMix2, 1);
-					bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, translateMix, translateMix2, 1);
-					bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, scaleMix, scaleMix2, 1);
-					bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, shearMix, shearMix2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
+					bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);
 				}
 				time = time2;
-				rotateMix = rotateMix2;
-				translateMix = translateMix2;
-				scaleMix = scaleMix2;
-				shearMix = shearMix2;
+				mixRotate = mixRotate2;
+				mixX = mixX2;
+				mixY = mixY2;
+				mixScaleX = mixScaleX2;
+				mixScaleY = mixScaleY2;
+				mixScaleX = mixScaleX2;
 				keyMap = nextMap;
 			}
 			timelines.add(timeline);
@@ -812,7 +820,7 @@ public class SkeletonJson extends SkeletonLoader {
 						data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed ? scale : 1));
 				} else if (timelineName.equals("mix")) {
 					CurveTimeline2 timeline = new PathConstraintMixTimeline(timelineMap.size, timelineMap.size << 1, index);
-					timelines.add(readTimeline(keyMap, timeline, "rotateMix", "translateMix", 1, 1));
+					timelines.add(readTimeline(keyMap, timeline, "mixRotate", "mixTranslate", 1, 1));
 				}
 			}
 		}

+ 119 - 88
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java

@@ -42,7 +42,7 @@ public class TransformConstraint implements Updatable {
 	final TransformConstraintData data;
 	final Array<Bone> bones;
 	Bone target;
-	float rotateMix, translateMix, scaleMix, shearMix;
+	float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
 
 	boolean active;
 	final Vector2 temp = new Vector2();
@@ -51,10 +51,12 @@ public class TransformConstraint implements Updatable {
 		if (data == null) throw new IllegalArgumentException("data cannot be null.");
 		if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
 		this.data = data;
-		rotateMix = data.rotateMix;
-		translateMix = data.translateMix;
-		scaleMix = data.scaleMix;
-		shearMix = data.shearMix;
+		mixRotate = data.mixRotate;
+		mixX = data.mixX;
+		mixY = data.mixY;
+		mixScaleX = data.mixScaleX;
+		mixScaleY = data.mixScaleY;
+		mixShearY = data.mixShearY;
 		bones = new Array(data.bones.size);
 		for (BoneData boneData : data.bones)
 			bones.add(skeleton.findBone(boneData.name));
@@ -70,15 +72,17 @@ public class TransformConstraint implements Updatable {
 		for (Bone bone : constraint.bones)
 			bones.add(skeleton.bones.get(bone.data.index));
 		target = skeleton.bones.get(constraint.target.data.index);
-		rotateMix = constraint.rotateMix;
-		translateMix = constraint.translateMix;
-		scaleMix = constraint.scaleMix;
-		shearMix = constraint.shearMix;
+		mixRotate = constraint.mixRotate;
+		mixX = constraint.mixX;
+		mixY = constraint.mixY;
+		mixScaleX = constraint.mixScaleX;
+		mixScaleY = constraint.mixScaleY;
+		mixShearY = constraint.mixShearY;
 	}
 
 	/** Applies the constraint to the constrained bones. */
 	public void update () {
-		if (rotateMix == 0 && translateMix == 0 && scaleMix == 0 && shearMix == 0) return;
+		if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleX == 0 && mixShearY == 0) return;
 		if (data.local) {
 			if (data.relative)
 				applyRelativeLocal();
@@ -93,22 +97,27 @@ public class TransformConstraint implements Updatable {
 	}
 
 	private void applyAbsoluteWorld () {
-		float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+		float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
+			mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
+		boolean translate = mixX != 0 || mixY != 0;
+
 		Bone target = this.target;
 		float ta = target.a, tb = target.b, tc = target.c, td = target.d;
 		float degRadReflect = ta * td - tb * tc > 0 ? degRad : -degRad;
 		float offsetRotation = data.offsetRotation * degRadReflect, offsetShearY = data.offsetShearY * degRadReflect;
+
 		Object[] bones = this.bones.items;
 		for (int i = 0, n = this.bones.size; i < n; i++) {
 			Bone bone = (Bone)bones[i];
 
-			if (rotateMix != 0) {
+			if (mixRotate != 0) {
 				float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
 				float r = atan2(tc, ta) - atan2(c, a) + offsetRotation;
 				if (r > PI)
 					r -= PI2;
-				else if (r < -PI) r += PI2;
-				r *= rotateMix;
+				else if (r < -PI) //
+					r += PI2;
+				r *= mixRotate;
 				float cos = cos(r), sin = sin(r);
 				bone.a = cos * a - sin * c;
 				bone.b = cos * b - sin * d;
@@ -116,32 +125,35 @@ public class TransformConstraint implements Updatable {
 				bone.d = sin * b + cos * d;
 			}
 
-			if (translateMix != 0) {
+			if (translate) {
 				Vector2 temp = this.temp;
 				target.localToWorld(temp.set(data.offsetX, data.offsetY));
-				bone.worldX += (temp.x - bone.worldX) * translateMix;
-				bone.worldY += (temp.y - bone.worldY) * translateMix;
+				bone.worldX += (temp.x - bone.worldX) * mixX;
+				bone.worldY += (temp.y - bone.worldY) * mixY;
 			}
 
-			if (scaleMix > 0) {
+			if (mixScaleX != 0) {
 				float s = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
-				if (s != 0) s = (s + ((float)Math.sqrt(ta * ta + tc * tc) - s + data.offsetScaleX) * scaleMix) / s;
+				if (s != 0) s = (s + ((float)Math.sqrt(ta * ta + tc * tc) - s + data.offsetScaleX) * mixScaleX) / s;
 				bone.a *= s;
 				bone.c *= s;
-				s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
-				if (s != 0) s = (s + ((float)Math.sqrt(tb * tb + td * td) - s + data.offsetScaleY) * scaleMix) / s;
+			}
+			if (mixScaleY != 0) {
+				float s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
+				if (s != 0) s = (s + ((float)Math.sqrt(tb * tb + td * td) - s + data.offsetScaleY) * mixScaleY) / s;
 				bone.b *= s;
 				bone.d *= s;
 			}
 
-			if (shearMix > 0) {
+			if (mixShearY > 0) {
 				float b = bone.b, d = bone.d;
 				float by = atan2(d, b);
 				float r = atan2(td, tb) - atan2(tc, ta) - (by - atan2(bone.c, bone.a));
 				if (r > PI)
 					r -= PI2;
-				else if (r < -PI) r += PI2;
-				r = by + (r + offsetShearY) * shearMix;
+				else if (r < -PI) //
+					r += PI2;
+				r = by + (r + offsetShearY) * mixShearY;
 				float s = (float)Math.sqrt(b * b + d * d);
 				bone.b = cos(r) * s;
 				bone.d = sin(r) * s;
@@ -152,22 +164,27 @@ public class TransformConstraint implements Updatable {
 	}
 
 	private void applyRelativeWorld () {
-		float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+		float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
+			mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
+		boolean translate = mixX != 0 || mixY != 0;
+
 		Bone target = this.target;
 		float ta = target.a, tb = target.b, tc = target.c, td = target.d;
 		float degRadReflect = ta * td - tb * tc > 0 ? degRad : -degRad;
 		float offsetRotation = data.offsetRotation * degRadReflect, offsetShearY = data.offsetShearY * degRadReflect;
+
 		Object[] bones = this.bones.items;
 		for (int i = 0, n = this.bones.size; i < n; i++) {
 			Bone bone = (Bone)bones[i];
 
-			if (rotateMix != 0) {
+			if (mixRotate != 0) {
 				float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
 				float r = atan2(tc, ta) + offsetRotation;
 				if (r > PI)
 					r -= PI2;
-				else if (r < -PI) r += PI2;
-				r *= rotateMix;
+				else if (r < -PI) //
+					r += PI2;
+				r *= mixRotate;
 				float cos = cos(r), sin = sin(r);
 				bone.a = cos * a - sin * c;
 				bone.b = cos * b - sin * d;
@@ -175,29 +192,32 @@ public class TransformConstraint implements Updatable {
 				bone.d = sin * b + cos * d;
 			}
 
-			if (translateMix != 0) {
+			if (translate) {
 				Vector2 temp = this.temp;
 				target.localToWorld(temp.set(data.offsetX, data.offsetY));
-				bone.worldX += temp.x * translateMix;
-				bone.worldY += temp.y * translateMix;
+				bone.worldX += temp.x * mixX;
+				bone.worldY += temp.y * mixY;
 			}
 
-			if (scaleMix > 0) {
-				float s = ((float)Math.sqrt(ta * ta + tc * tc) - 1 + data.offsetScaleX) * scaleMix + 1;
+			if (mixScaleX != 0) {
+				float s = ((float)Math.sqrt(ta * ta + tc * tc) - 1 + data.offsetScaleX) * mixScaleX + 1;
 				bone.a *= s;
 				bone.c *= s;
-				s = ((float)Math.sqrt(tb * tb + td * td) - 1 + data.offsetScaleY) * scaleMix + 1;
+			}
+			if (mixScaleY != 0) {
+				float s = ((float)Math.sqrt(tb * tb + td * td) - 1 + data.offsetScaleY) * mixScaleY + 1;
 				bone.b *= s;
 				bone.d *= s;
 			}
 
-			if (shearMix > 0) {
+			if (mixShearY > 0) {
 				float r = atan2(td, tb) - atan2(tc, ta);
 				if (r > PI)
 					r -= PI2;
-				else if (r < -PI) r += PI2;
+				else if (r < -PI) //
+					r += PI2;
 				float b = bone.b, d = bone.d;
-				r = atan2(d, b) + (r - PI / 2 + offsetShearY) * shearMix;
+				r = atan2(d, b) + (r - PI / 2 + offsetShearY) * mixShearY;
 				float s = (float)Math.sqrt(b * b + d * d);
 				bone.b = cos(r) * s;
 				bone.d = sin(r) * s;
@@ -208,38 +228,39 @@ public class TransformConstraint implements Updatable {
 	}
 
 	private void applyAbsoluteLocal () {
-		float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+		float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
+			mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
+
 		Bone target = this.target;
 		if (!target.appliedValid) target.updateAppliedTransform();
+
 		Object[] bones = this.bones.items;
 		for (int i = 0, n = this.bones.size; i < n; i++) {
 			Bone bone = (Bone)bones[i];
 			if (!bone.appliedValid) bone.updateAppliedTransform();
 
 			float rotation = bone.arotation;
-			if (rotateMix != 0) {
+			if (mixRotate != 0) {
 				float r = target.arotation - rotation + data.offsetRotation;
 				r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
-				rotation += r * rotateMix;
+				rotation += r * mixRotate;
 			}
 
 			float x = bone.ax, y = bone.ay;
-			if (translateMix != 0) {
-				x += (target.ax - x + data.offsetX) * translateMix;
-				y += (target.ay - y + data.offsetY) * translateMix;
-			}
+			x += (target.ax - x + data.offsetX) * mixX;
+			y += (target.ay - y + data.offsetY) * mixY;
 
 			float scaleX = bone.ascaleX, scaleY = bone.ascaleY;
-			if (scaleMix != 0) {
-				if (scaleX != 0) scaleX = (scaleX + (target.ascaleX - scaleX + data.offsetScaleX) * scaleMix) / scaleX;
-				if (scaleY != 0) scaleY = (scaleY + (target.ascaleY - scaleY + data.offsetScaleY) * scaleMix) / scaleY;
-			}
+			if (mixScaleX != 0 && scaleX != 0)
+				scaleX = (scaleX + (target.ascaleX - scaleX + data.offsetScaleX) * mixScaleX) / scaleX;
+			if (mixScaleY != 0 && scaleY != 0)
+				scaleY = (scaleY + (target.ascaleY - scaleY + data.offsetScaleY) * mixScaleY) / scaleY;
 
 			float shearY = bone.ashearY;
-			if (shearMix != 0) {
+			if (mixShearY != 0) {
 				float r = target.ashearY - shearY + data.offsetShearY;
 				r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
-				shearY += r * shearMix;
+				shearY += r * mixShearY;
 			}
 
 			bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
@@ -247,31 +268,23 @@ public class TransformConstraint implements Updatable {
 	}
 
 	private void applyRelativeLocal () {
-		float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+		float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
+			mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
+
 		Bone target = this.target;
 		if (!target.appliedValid) target.updateAppliedTransform();
+
 		Object[] bones = this.bones.items;
 		for (int i = 0, n = this.bones.size; i < n; i++) {
 			Bone bone = (Bone)bones[i];
 			if (!bone.appliedValid) bone.updateAppliedTransform();
 
-			float rotation = bone.arotation;
-			if (rotateMix != 0) rotation += (target.arotation + data.offsetRotation) * rotateMix;
-
-			float x = bone.ax, y = bone.ay;
-			if (translateMix != 0) {
-				x += (target.ax + data.offsetX) * translateMix;
-				y += (target.ay + data.offsetY) * translateMix;
-			}
-
-			float scaleX = bone.ascaleX, scaleY = bone.ascaleY;
-			if (scaleMix != 0) {
-				scaleX *= ((target.ascaleX - 1 + data.offsetScaleX) * scaleMix) + 1;
-				scaleY *= ((target.ascaleY - 1 + data.offsetScaleY) * scaleMix) + 1;
-			}
-
-			float shearY = bone.ashearY;
-			if (shearMix != 0) shearY += (target.ashearY + data.offsetShearY) * shearMix;
+			float rotation = bone.arotation + (target.arotation + data.offsetRotation) * mixRotate;
+			float x = bone.ax + (target.ax + data.offsetX) * mixX;
+			float y = bone.ay + (target.ay + data.offsetY) * mixY;
+			float scaleX = (bone.ascaleX * ((target.ascaleX - 1 + data.offsetScaleX) * mixScaleX) + 1);
+			float scaleY = (bone.ascaleY * ((target.ascaleY - 1 + data.offsetScaleY) * mixScaleY) + 1);
+			float shearY = bone.ashearY + (target.ashearY + data.offsetShearY) * mixShearY;
 
 			bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
 		}
@@ -292,40 +305,58 @@ public class TransformConstraint implements Updatable {
 		this.target = target;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
-	public float getRotateMix () {
-		return rotateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
+	public float getMixRotate () {
+		return mixRotate;
+	}
+
+	public void setMixRotate (float mixRotate) {
+		this.mixRotate = mixRotate;
+	}
+
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
+	public float getMixX () {
+		return mixX;
+	}
+
+	public void setMixX (float mixX) {
+		this.mixX = mixX;
+	}
+
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
+	public float getMixY () {
+		return mixY;
 	}
 
-	public void setRotateMix (float rotateMix) {
-		this.rotateMix = rotateMix;
+	public void setMixY (float mixY) {
+		this.mixY = mixY;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
-	public float getTranslateMix () {
-		return translateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
+	public float getMixScaleX () {
+		return mixScaleX;
 	}
 
-	public void setTranslateMix (float translateMix) {
-		this.translateMix = translateMix;
+	public void setMixScaleX (float mixScaleX) {
+		this.mixScaleX = mixScaleX;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
-	public float getScaleMix () {
-		return scaleMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
+	public float getMixScaleY () {
+		return mixScaleY;
 	}
 
-	public void setScaleMix (float scaleMix) {
-		this.scaleMix = scaleMix;
+	public void setMixScaleY (float mixScaleY) {
+		this.mixScaleY = mixScaleY;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
-	public float getShearMix () {
-		return shearMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
+	public float getMixShearY () {
+		return mixShearY;
 	}
 
-	public void setShearMix (float shearMix) {
-		this.shearMix = shearMix;
+	public void setMixShearY (float mixShearY) {
+		this.mixShearY = mixShearY;
 	}
 
 	public boolean isActive () {

+ 39 - 21
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java

@@ -37,7 +37,7 @@ import com.badlogic.gdx.utils.Array;
 public class TransformConstraintData extends ConstraintData {
 	final Array<BoneData> bones = new Array();
 	BoneData target;
-	float rotateMix, translateMix, scaleMix, shearMix;
+	float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
 	float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
 	boolean relative, local;
 
@@ -60,40 +60,58 @@ public class TransformConstraintData extends ConstraintData {
 		this.target = target;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */
-	public float getRotateMix () {
-		return rotateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */
+	public float getMixRotate () {
+		return mixRotate;
 	}
 
-	public void setRotateMix (float rotateMix) {
-		this.rotateMix = rotateMix;
+	public void setMixRotate (float mixRotate) {
+		this.mixRotate = mixRotate;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translations. */
-	public float getTranslateMix () {
-		return translateMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */
+	public float getMixX () {
+		return mixX;
 	}
 
-	public void setTranslateMix (float translateMix) {
-		this.translateMix = translateMix;
+	public void setMixX (float mixX) {
+		this.mixX = mixX;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scales. */
-	public float getScaleMix () {
-		return scaleMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
+	public float getMixY () {
+		return mixY;
 	}
 
-	public void setScaleMix (float scaleMix) {
-		this.scaleMix = scaleMix;
+	public void setMixY (float mixY) {
+		this.mixY = mixY;
 	}
 
-	/** A percentage (0-1) that controls the mix between the constrained and unconstrained shears. */
-	public float getShearMix () {
-		return shearMix;
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */
+	public float getMixScaleX () {
+		return mixScaleX;
 	}
 
-	public void setShearMix (float shearMix) {
-		this.shearMix = shearMix;
+	public void setMixScaleX (float mixScaleX) {
+		this.mixScaleX = mixScaleX;
+	}
+
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */
+	public float getMixScaleY () {
+		return mixScaleY;
+	}
+
+	public void setMixScaleY (float mixScaleY) {
+		this.mixScaleY = mixScaleY;
+	}
+
+	/** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */
+	public float getMixShearY () {
+		return mixShearY;
+	}
+
+	public void setMixShearY (float mixShearY) {
+		this.mixShearY = mixShearY;
 	}
 
 	/** An offset added to the constrained bone rotation. */

+ 1 - 0
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/vertexeffects/JitterEffect.java

@@ -32,6 +32,7 @@ package com.esotericsoftware.spine.vertexeffects;
 import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.math.MathUtils;
 import com.badlogic.gdx.math.Vector2;
+
 import com.esotericsoftware.spine.Skeleton;
 import com.esotericsoftware.spine.SkeletonRenderer.VertexEffect;
 

+ 1 - 0
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/vertexeffects/SwirlEffect.java

@@ -33,6 +33,7 @@ import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.math.Interpolation;
 import com.badlogic.gdx.math.MathUtils;
 import com.badlogic.gdx.math.Vector2;
+
 import com.esotericsoftware.spine.Skeleton;
 import com.esotericsoftware.spine.SkeletonRenderer.VertexEffect;
 import com.esotericsoftware.spine.utils.SpineUtils;