Эх сурвалжийг харах

Multiple constrained bones for transform constraints.

NathanSweet 9 жил өмнө
parent
commit
92d7ef32f4

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

@@ -27,14 +27,14 @@ public class PathConstraint 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;
-		position = data.position;
-		spacing = data.spacing;
-		rotateMix = data.rotateMix;
-		translateMix = data.translateMix;
 		bones = new Array(data.bones.size);
 		for (BoneData boneData : data.bones)
 			bones.add(skeleton.findBone(boneData.name));
 		target = skeleton.findSlot(data.target.name);
+		position = data.position;
+		spacing = data.spacing;
+		rotateMix = data.rotateMix;
+		translateMix = data.translateMix;
 	}
 
 	/** Copy constructor. */

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

@@ -227,21 +227,17 @@ public class Skeleton {
 
 			sortBone(constraint.target);
 
-			// BOZO! - Update transform constraints to support multiple constrained bones.
-			// Array<Bone> constrained = constraint.bones;
-			// int boneCount = constrained.size;
-			// for (int ii = 0; ii < boneCount; ii++)
-			// sortBone(constrained.get(ii));
-			sortBone(constraint.bone);
+			Array<Bone> constrained = constraint.bones;
+			int boneCount = constrained.size;
+			for (int ii = 0; ii < boneCount; ii++)
+				sortBone(constrained.get(ii));
 
 			updateCache.add(constraint);
 
-			// for (int ii = 0; ii < boneCount; ii++)
-			// reset(constrained.get(ii).children);
-			sortReset(constraint.bone.children); // BOZO - Remove.
-			// for (int ii = 0; ii < boneCount; ii++)
-			// constrained.get(ii).sorted = true;
-			constraint.bone.sorted = true; // BOZO - Remove.
+			for (int ii = 0; ii < boneCount; ii++)
+				sortReset(constrained.get(ii).children);
+			for (int ii = 0; ii < boneCount; ii++)
+				constrained.get(ii).sorted = true;
 		}
 
 		for (int i = 0, n = bones.size; i < n; i++)

+ 2 - 1
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java

@@ -217,7 +217,8 @@ public class SkeletonBinary {
 			// Transform constraints.
 			for (int i = 0, n = input.readInt(true); i < n; i++) {
 				TransformConstraintData data = new TransformConstraintData(input.readString());
-				data.bone = skeletonData.bones.get(input.readInt(true));
+				for (int ii = 0, nn = input.readInt(true); ii < nn; ii++)
+					data.bones.add(skeletonData.bones.get(input.readInt(true)));
 				data.target = skeletonData.bones.get(input.readInt(true));
 				data.offsetRotation = input.readFloat();
 				data.offsetX = input.readFloat() * scale;

+ 6 - 3
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java

@@ -179,9 +179,12 @@ public class SkeletonJson {
 		for (JsonValue constraintMap = root.getChild("transform"); constraintMap != null; constraintMap = constraintMap.next) {
 			TransformConstraintData data = new TransformConstraintData(constraintMap.getString("name"));
 
-			String boneName = constraintMap.getString("bone");
-			data.bone = skeletonData.findBone(boneName);
-			if (data.bone == null) throw new SerializationException("Bone not found: " + boneName);
+			for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
+				String boneName = boneMap.asString();
+				BoneData bone = skeletonData.findBone(boneName);
+				if (bone == null) throw new SerializationException("Path bone not found: " + boneName);
+				data.bones.add(bone);
+			}
 
 			String targetName = constraintMap.getString("target");
 			data.target = skeletonData.findBone(targetName);

+ 64 - 58
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java

@@ -4,10 +4,12 @@ package com.esotericsoftware.spine;
 import static com.badlogic.gdx.math.MathUtils.*;
 
 import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.utils.Array;
 
 public class TransformConstraint implements Updatable {
 	final TransformConstraintData data;
-	Bone bone, target;
+	final Array<Bone> bones;
+	Bone target;
 	float rotateMix, translateMix, scaleMix, shearMix;
 	final Vector2 temp = new Vector2();
 
@@ -19,7 +21,9 @@ public class TransformConstraint implements Updatable {
 		translateMix = data.translateMix;
 		scaleMix = data.scaleMix;
 		shearMix = data.shearMix;
-		bone = skeleton.findBone(data.bone.name);
+		bones = new Array(data.bones.size);
+		for (BoneData boneData : data.bones)
+			bones.add(skeleton.findBone(boneData.name));
 		target = skeleton.findBone(data.target.name);
 	}
 
@@ -28,12 +32,14 @@ public class TransformConstraint implements Updatable {
 		if (constraint == null) throw new IllegalArgumentException("constraint cannot be null.");
 		if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
 		data = constraint.data;
+		bones = new Array(constraint.bones.size);
+		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;
-		bone = skeleton.bones.get(constraint.bone.data.index);
-		target = skeleton.bones.get(constraint.target.data.index);
 	}
 
 	public void apply () {
@@ -41,64 +47,64 @@ public class TransformConstraint implements Updatable {
 	}
 
 	public void update () {
-		Bone bone = this.bone;
+		float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
 		Bone target = this.target;
-
-		if (rotateMix > 0) {
-			float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
-			float r = atan2(target.c, target.a) - atan2(c, a) + data.offsetRotation * degRad;
-			if (r > PI)
-				r -= PI2;
-			else if (r < -PI) r += PI2;
-			r *= rotateMix;
-			float cos = cos(r), sin = sin(r);
-			bone.a = cos * a - sin * c;
-			bone.b = cos * b - sin * d;
-			bone.c = sin * a + cos * c;
-			bone.d = sin * b + cos * d;
+		float ta = target.a, tb = target.b, tc = target.c, td = target.d;
+		Array<Bone> bones = this.bones;
+		for (int i = 0, n = bones.size; i < n; i++) {
+			Bone bone = bones.get(i);
+
+			if (rotateMix > 0) {
+				float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+				float r = atan2(tc, ta) - atan2(c, a) + data.offsetRotation * degRad;
+				if (r > PI)
+					r -= PI2;
+				else if (r < -PI) r += PI2;
+				r *= rotateMix;
+				float cos = cos(r), sin = sin(r);
+				bone.a = cos * a - sin * c;
+				bone.b = cos * b - sin * d;
+				bone.c = sin * a + cos * c;
+				bone.d = sin * b + cos * d;
+			}
+
+			if (translateMix > 0) {
+				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;
+			}
+
+			if (scaleMix > 0) {
+				float bs = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
+				float ts = (float)Math.sqrt(ta * ta + tc * tc);
+				float s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleX) * scaleMix) / bs : 0;
+				bone.a *= s;
+				bone.c *= s;
+				bs = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
+				ts = (float)Math.sqrt(tb * tb + td * td);
+				s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
+				bone.b *= s;
+				bone.d *= s;
+			}
+
+			if (shearMix > 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 + data.offsetShearY * degRad) * shearMix;
+				float s = (float)Math.sqrt(b * b + d * d);
+				bone.b = cos(r) * s;
+				bone.d = sin(r) * s;
+			}
 		}
-
-		if (scaleMix > 0) {
-			float bs = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
-			float ts = (float)Math.sqrt(target.a * target.a + target.c * target.c);
-			float s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleX) * scaleMix) / bs : 0;
-			bone.a *= s;
-			bone.c *= s;
-			bs = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
-			ts = (float)Math.sqrt(target.b * target.b + target.d * target.d);
-			s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
-			bone.b *= s;
-			bone.d *= s;
-		}
-
-		if (shearMix > 0) {
-			float b = bone.b, d = bone.d;
-			float by = atan2(d, b);
-			float r = atan2(target.d, target.b) - atan2(target.c, target.a) - (by - atan2(bone.c, bone.a));
-			if (r > PI)
-				r -= PI2;
-			else if (r < -PI) r += PI2;
-			r = by + (r + data.offsetShearY * degRad) * shearMix;
-			float s = (float)Math.sqrt(b * b + d * d);
-			bone.b = cos(r) * s;
-			bone.d = sin(r) * s;
-		}
-
-		float translateMix = this.translateMix;
-		if (translateMix > 0) {
-			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;
-		}
-	}
-
-	public Bone getBone () {
-		return bone;
 	}
 
-	public void setBone (Bone bone) {
-		this.bone = bone;
+	public Array<Bone> getBones () {
+		return bones;
 	}
 
 	public Bone getTarget () {

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

@@ -1,9 +1,12 @@
 
 package com.esotericsoftware.spine;
 
+import com.badlogic.gdx.utils.Array;
+
 public class TransformConstraintData {
 	final String name;
-	BoneData bone, target;
+	final Array<BoneData> bones = new Array();
+	BoneData target;
 	float rotateMix, translateMix, scaleMix, shearMix;
 	float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
 
@@ -16,13 +19,8 @@ public class TransformConstraintData {
 		return name;
 	}
 
-	public BoneData getBone () {
-		return bone;
-	}
-
-	public void setBone (BoneData bone) {
-		if (bone == null) throw new IllegalArgumentException("bone cannot be null.");
-		this.bone = bone;
+	public Array<BoneData> getBones () {
+		return bones;
 	}
 
 	public BoneData getTarget () {