mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-05 06:44:56 +08:00
Multiple constrained bones for transform constraints.
This commit is contained in:
parent
8b3b0169ad
commit
92d7ef32f4
@ -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. */
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 () {
|
||||
|
||||
@ -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 () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user