Multiple constrained bones for transform constraints.

This commit is contained in:
NathanSweet 2016-06-10 03:21:54 +02:00
parent 8b3b0169ad
commit 92d7ef32f4
6 changed files with 86 additions and 82 deletions

View File

@ -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. */

View File

@ -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++)

View File

@ -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;

View File

@ -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);

View File

@ -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;
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(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;
}
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 (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 (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 (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;
}
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;
}
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;
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;
}
}
}
public Bone getBone () {
return bone;
}
public void setBone (Bone bone) {
this.bone = bone;
public Array<Bone> getBones () {
return bones;
}
public Bone getTarget () {

View File

@ -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 () {