Constraint order WIP.

This commit is contained in:
NathanSweet 2016-08-09 21:24:54 +02:00
parent 2dee5d6103
commit 1459abcb06
11 changed files with 201 additions and 158 deletions

View File

@ -44,7 +44,8 @@ public class Bone implements Updatable {
final Bone parent;
final Array<Bone> children = new Array();
float x, y, rotation, scaleX, scaleY, shearX, shearY;
float appliedRotation;
float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
boolean appliedValid; // BOZO! - Use everywhere.
float a, b, worldX;
float c, d, worldY;
@ -91,7 +92,13 @@ public class Bone implements Updatable {
/** Computes the world transform using the parent bone and the specified local transform. */
public void updateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
appliedRotation = rotation;
ax = x;
ay = y;
arotation = rotation;
ascaleX = scaleX;
ascaleY = scaleY;
ashearX = shearX;
ashearY = shearY;
float rotationY = rotation + 90 + shearY;
float la = cosDeg(rotation + shearX) * scaleX, lb = cosDeg(rotationY) * scaleY;
@ -160,8 +167,8 @@ public class Bone implements Updatable {
pc = 0;
pd = 1;
do {
float cos = cosDeg(parent.appliedRotation), sin = sinDeg(parent.appliedRotation);
float psx = parent.scaleX, psy = parent.scaleY;
float cos = cosDeg(parent.arotation), sin = sinDeg(parent.arotation);
float psx = parent.ascaleX, psy = parent.ascaleY;
float za = cos * psx, zb = sin * psy, zc = sin * psx, zd = cos * psy;
float temp = pa * za + pb * zc;
pb = pb * zd - pa * zb;
@ -170,7 +177,8 @@ public class Bone implements Updatable {
pd = pd * zd - pc * zb;
pc = temp;
if (psx >= 0) sin = -sin;
if (psx >= 0) // BOZO! - Why? Should always do this? Fix in new code?
sin = -sin;
temp = pa * cos + pb * sin;
pb = pb * cos - pa * sin;
pa = temp;
@ -350,14 +358,14 @@ public class Bone implements Updatable {
public float worldToLocalRotationX () {
Bone parent = this.parent;
if (parent == null) return rotation;
if (parent == null) return arotation;
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c;
return atan2(pa * c - pc * a, pd * a - pb * c) * radDeg;
}
public float worldToLocalRotationY () {
Bone parent = this.parent;
if (parent == null) return rotation;
if (parent == null) return arotation;
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d;
return atan2(pa * d - pc * b, pd * b - pb * d) * radDeg;
}
@ -371,29 +379,27 @@ public class Bone implements Updatable {
this.d = sin * b + cos * d;
}
/** Computes the local transform from the world transform. This can be useful to perform processing on the local transform
* after the world transform has been modified directly (eg, by a constraint).
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
* the applied transform after the world transform has been modified directly (eg, by a constraint).
* <p>
* Some redundant information is lost by the world transform, such as -1,-1 scale versus 180 rotation. The computed local
* transform values may differ from the original values but are functionally the same. */
public void updateLocalTransform () {
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
public void updateAppliedTransform () {
Bone parent = this.parent;
if (parent == null) {
x = worldX;
y = worldY;
rotation = atan2(c, a) * radDeg;
scaleX = (float)Math.sqrt(a * a + c * c);
scaleY = (float)Math.sqrt(b * b + d * d);
float det = a * d - b * c;
shearX = 0;
shearY = atan2(a * b + c * d, det) * radDeg;
ax = worldX;
ay = worldY;
arotation = atan2(c, a) * radDeg;
ascaleX = (float)Math.sqrt(a * a + c * c);
ascaleY = (float)Math.sqrt(b * b + d * d);
ashearX = 0;
ashearY = atan2(a * b + c * d, a * d - b * c) * radDeg;
return;
}
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
float pid = 1 / (pa * pd - pb * pc);
float dx = worldX - parent.worldX, dy = worldY - parent.worldY;
x = (dx * pd * pid - dy * pb * pid);
y = (dy * pa * pid - dx * pc * pid);
ax = (dx * pd * pid - dy * pb * pid);
ay = (dy * pa * pid - dx * pc * pid);
float ia = pid * pd;
float id = pid * pa;
float ib = pid * pb;
@ -402,20 +408,19 @@ public class Bone implements Updatable {
float rb = ia * b - ib * d;
float rc = id * c - ic * a;
float rd = id * d - ic * b;
shearX = 0;
scaleX = (float)Math.sqrt(ra * ra + rc * rc);
if (scaleX > 0.0001f) {
ashearX = 0;
ascaleX = (float)Math.sqrt(ra * ra + rc * rc);
if (ascaleX > 0.0001f) {
float det = ra * rd - rb * rc;
scaleY = det / scaleX;
shearY = atan2(ra * rb + rc * rd, det) * radDeg;
rotation = atan2(rc, ra) * radDeg;
ascaleY = det / ascaleX;
ashearY = atan2(ra * rb + rc * rd, det) * radDeg;
arotation = atan2(rc, ra) * radDeg;
} else {
scaleX = 0;
scaleY = (float)Math.sqrt(rb * rb + rd * rd);
shearY = 0;
rotation = 90 - atan2(rd, rb) * radDeg;
ascaleX = 0;
ascaleY = (float)Math.sqrt(rb * rb + rd * rd);
ashearY = 0;
arotation = 90 - atan2(rd, rb) * radDeg;
}
appliedRotation = rotation;
}
public Matrix3 getWorldTransform (Matrix3 worldTransform) {

View File

@ -0,0 +1,6 @@
package com.esotericsoftware.spine;
public interface Constraint extends Updatable {
public int getOrder ();
}

View File

@ -35,15 +35,13 @@ import static com.badlogic.gdx.math.MathUtils.*;
import com.badlogic.gdx.utils.Array;
public class IkConstraint implements Updatable {
public class IkConstraint implements Constraint {
final IkConstraintData data;
final Array<Bone> bones;
Bone target;
float mix = 1;
int bendDirection;
int level;
public IkConstraint (IkConstraintData data, Skeleton skeleton) {
if (data == null) throw new IllegalArgumentException("data cannot be null.");
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
@ -87,6 +85,10 @@ public class IkConstraint implements Updatable {
}
}
public int getOrder () {
return data.order;
}
public Array<Bone> getBones () {
return bones;
}
@ -126,17 +128,17 @@ public class IkConstraint implements Updatable {
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
* coordinate system. */
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
Bone pp = bone.parent;
float id = 1 / (pp.a * pp.d - pp.b * pp.c);
float x = targetX - pp.worldX, y = targetY - pp.worldY;
float tx = (x * pp.d - y * pp.b) * id - bone.x, ty = (y * pp.a - x * pp.c) * id - bone.y;
float rotationIK = atan2(ty, tx) * radDeg - bone.shearX - bone.rotation;
if (bone.scaleX < 0) rotationIK += 180;
Bone p = bone.parent;
float id = 1 / (p.a * p.d - p.b * p.c);
float x = targetX - p.worldX, y = targetY - p.worldY;
float tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay;
float rotationIK = atan2(ty, tx) * radDeg - bone.ashearX - bone.arotation;
if (bone.ascaleX < 0) rotationIK += 180;
if (rotationIK > 180)
rotationIK -= 360;
else if (rotationIK < -180) rotationIK += 360;
bone.updateWorldTransform(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX,
bone.shearY);
bone.updateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX,
bone.ashearY);
}
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
@ -147,7 +149,12 @@ public class IkConstraint implements Updatable {
child.updateWorldTransform();
return;
}
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX;
// BOZO! - Only when each bone needs it.
// child.updateLocalTransform();
// parent.updateLocalTransform();
float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX;
int os1, os2, s2;
if (psx < 0) {
psx = -psx;
@ -166,14 +173,14 @@ public class IkConstraint implements Updatable {
os2 = 180;
} else
os2 = 0;
float cx = child.x, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
float cx = child.ax, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
boolean u = Math.abs(psx - psy) <= 0.0001f;
if (!u) {
cy = 0;
cwx = a * cx + parent.worldX;
cwy = c * cx + parent.worldY;
} else {
cy = child.y;
cy = child.ay;
cwx = a * cx + b * cy + parent.worldX;
cwy = c * cx + d * cy + parent.worldY;
}
@ -260,17 +267,17 @@ public class IkConstraint implements Updatable {
}
}
float os = atan2(cy, cx) * s2;
float rotation = parent.rotation;
float rotation = parent.arotation;
a1 = (a1 - os) * radDeg + os1 - rotation;
if (a1 > 180)
a1 -= 360;
else if (a1 < -180) a1 += 360;
parent.updateWorldTransform(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0);
rotation = child.rotation;
a2 = ((a2 + os) * radDeg - child.shearX) * s2 + os2 - rotation;
parent.updateWorldTransform(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0);
rotation = child.arotation;
a2 = ((a2 + os) * radDeg - child.ashearX) * s2 + os2 - rotation;
if (a2 > 180)
a2 -= 360;
else if (a2 < -180) a2 += 360;
child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY);
child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
}
}

View File

@ -35,6 +35,7 @@ import com.badlogic.gdx.utils.Array;
public class IkConstraintData {
final String name;
int order;
final Array<BoneData> bones = new Array();
BoneData target;
int bendDirection = 1;
@ -49,6 +50,14 @@ public class IkConstraintData {
return name;
}
public int getOrder () {
return order;
}
public void setOrder (int order) {
this.order = order;
}
public Array<BoneData> getBones () {
return bones;
}

View File

@ -11,7 +11,7 @@ import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.PathAttachment;
public class PathConstraint implements Updatable {
public class PathConstraint implements Constraint {
static private final int NONE = -1, BEFORE = -2, AFTER = -3;
final PathConstraintData data;
@ -382,6 +382,10 @@ public class PathConstraint implements Updatable {
if (tangents) out[o + 2] = atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
}
public int getOrder () {
return data.order;
}
public float getPosition () {
return position;
}

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Array;
public class PathConstraintData {
final String name;
int order;
final Array<BoneData> bones = new Array();
SlotData target;
PositionMode positionMode;
@ -18,6 +19,18 @@ public class PathConstraintData {
this.name = name;
}
public String getName () {
return name;
}
public int getOrder () {
return order;
}
public void setOrder (int order) {
this.order = order;
}
public Array<BoneData> getBones () {
return bones;
}
@ -94,10 +107,6 @@ public class PathConstraintData {
this.translateMix = translateMix;
}
public String getName () {
return name;
}
public String toString () {
return name;
}

View File

@ -31,6 +31,8 @@
package com.esotericsoftware.spine;
import java.util.Comparator;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
@ -46,9 +48,10 @@ public class Skeleton {
final Array<Bone> bones;
final Array<Slot> slots;
Array<Slot> drawOrder;
final Array<IkConstraint> ikConstraints, ikConstraintsSorted;
final Array<IkConstraint> ikConstraints;
final Array<TransformConstraint> transformConstraints;
final Array<PathConstraint> pathConstraints;
final Array<Constraint> sortedConstraints = new Array();
final Array<Updatable> updateCache = new Array();
Skin skin;
final Color color;
@ -56,6 +59,9 @@ public class Skeleton {
boolean flipX, flipY;
float x, y;
final Comparator<Constraint> constraintComparator = new Comparator<Constraint>() {
public int compare (Constraint o1,Constraint o2){return o1.getOrder()-o2.getOrder();}};
public Skeleton (SkeletonData data) {
if (data == null) throw new IllegalArgumentException("data cannot be null.");
this.data = data;
@ -83,7 +89,6 @@ public class Skeleton {
}
ikConstraints = new Array(data.ikConstraints.size);
ikConstraintsSorted = new Array(ikConstraints.size);
for (IkConstraintData ikConstraintData : data.ikConstraints)
ikConstraints.add(new IkConstraint(ikConstraintData, this));
@ -107,15 +112,8 @@ public class Skeleton {
bones = new Array(skeleton.bones.size);
for (Bone bone : skeleton.bones) {
Bone copy;
if (bone.parent == null)
copy = new Bone(bone, this, null);
else {
Bone parent = bones.get(bone.parent.data.index);
copy = new Bone(bone, this, parent);
parent.children.add(copy);
}
bones.add(copy);
Bone parent = bone.parent == null ? null : bones.get(bone.parent.data.index);
bones.add(new Bone(bone, this, parent));
}
slots = new Array(skeleton.slots.size);
@ -129,7 +127,6 @@ public class Skeleton {
drawOrder.add(slots.get(slot.data.index));
ikConstraints = new Array(skeleton.ikConstraints.size);
ikConstraintsSorted = new Array(ikConstraints.size);
for (IkConstraint ikConstraint : skeleton.ikConstraints)
ikConstraints.add(new IkConstraint(ikConstraint, this));
@ -155,100 +152,87 @@ public class Skeleton {
public void updateCache () {
Array<Updatable> updateCache = this.updateCache;
updateCache.clear();
Array<Bone> bones = this.bones;
for (int i = 0, n = bones.size; i < n; i++)
bones.get(i).sorted = false;
// IK first, lowest hierarchy depth first.
Array<IkConstraint> ikConstraints = this.ikConstraintsSorted;
ikConstraints.clear();
ikConstraints.addAll(this.ikConstraints);
int ikCount = ikConstraints.size;
for (int i = 0, level, n = ikCount; i < n; i++) {
IkConstraint ik = ikConstraints.get(i);
Bone bone = ik.bones.first().parent;
for (level = 0; bone != null; level++)
bone = bone.parent;
ik.level = level;
Array<Constraint> constraints = sortedConstraints;
constraints.addAll(ikConstraints);
constraints.addAll(transformConstraints);
constraints.addAll(pathConstraints);
constraints.sort(constraintComparator);
for (int i = 0, n = constraints.size; i < n; i++) {
Constraint constraint = constraints.get(i);
if (constraint instanceof IkConstraint)
sortIkConstraint((IkConstraint)constraint);
else if (constraint instanceof TransformConstraint)
sortTransformConstraint((TransformConstraint)constraint);
else
sortPathConstraint((PathConstraint)constraint);
}
for (int i = 1, ii; i < ikCount; i++) {
IkConstraint ik = ikConstraints.get(i);
int level = ik.level;
for (ii = i - 1; ii >= 0; ii--) {
IkConstraint other = ikConstraints.get(ii);
if (other.level < level) break;
ikConstraints.set(ii + 1, other);
}
ikConstraints.set(ii + 1, ik);
}
for (int i = 0, n = ikConstraints.size; i < n; i++) {
IkConstraint constraint = ikConstraints.get(i);
Bone target = constraint.target;
sortBone(target);
Array<Bone> constrained = constraint.bones;
Bone parent = constrained.first();
sortBone(parent);
updateCache.add(constraint);
sortReset(parent.children);
constrained.peek().sorted = true;
}
Array<PathConstraint> pathConstraints = this.pathConstraints;
for (int i = 0, n = pathConstraints.size; i < n; i++) {
PathConstraint constraint = pathConstraints.get(i);
Slot slot = constraint.target;
int slotIndex = slot.getData().index;
Bone slotBone = slot.bone;
if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
if (data.defaultSkin != null && data.defaultSkin != skin)
sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
for (int ii = 0, nn = data.skins.size; ii < nn; ii++)
sortPathConstraintAttachment(data.skins.get(ii), slotIndex, slotBone);
Attachment attachment = slot.attachment;
if (attachment instanceof PathAttachment) sortPathConstraintAttachment(attachment, slotBone);
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++)
sortReset(constrained.get(ii).children);
for (int ii = 0; ii < boneCount; ii++)
constrained.get(ii).sorted = true;
}
Array<TransformConstraint> transformConstraints = this.transformConstraints;
for (int i = 0, n = transformConstraints.size; i < n; i++) {
TransformConstraint constraint = transformConstraints.get(i);
sortBone(constraint.target);
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++)
sortReset(constrained.get(ii).children);
for (int ii = 0; ii < boneCount; ii++)
constrained.get(ii).sorted = true;
}
constraints.clear();
for (int i = 0, n = bones.size; i < n; i++)
sortBone(bones.get(i));
}
private void sortIkConstraint (IkConstraint constraint) {
Bone target = constraint.target;
sortBone(target);
Array<Bone> constrained = constraint.bones;
Bone parent = constrained.first();
sortBone(parent);
updateCache.add(constraint);
sortReset(parent.children);
constrained.peek().sorted = true;
}
private void sortPathConstraint (PathConstraint constraint) {
Slot slot = constraint.target;
int slotIndex = slot.getData().index;
Bone slotBone = slot.bone;
if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
if (data.defaultSkin != null && data.defaultSkin != skin)
sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
for (int ii = 0, nn = data.skins.size; ii < nn; ii++)
sortPathConstraintAttachment(data.skins.get(ii), slotIndex, slotBone);
Attachment attachment = slot.attachment;
if (attachment instanceof PathAttachment) sortPathConstraintAttachment(attachment, slotBone);
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++)
sortReset(constrained.get(ii).children);
for (int ii = 0; ii < boneCount; ii++)
constrained.get(ii).sorted = true;
}
private void sortTransformConstraint (TransformConstraint constraint) {
sortBone(constraint.target);
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++)
sortReset(constrained.get(ii).children);
for (int ii = 0; ii < boneCount; ii++)
constrained.get(ii).sorted = true;
}
private void sortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) {
for (Entry<Key, Attachment> entry : skin.attachments.entries())
if (entry.key.slotIndex == slotIndex) sortPathConstraintAttachment(entry.value, slotBone);

View File

@ -206,6 +206,7 @@ public class SkeletonBinary {
// IK constraints.
for (int i = 0, n = input.readInt(true); i < n; i++) {
IkConstraintData data = new IkConstraintData(input.readString());
data.order = 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));
@ -217,6 +218,7 @@ public class SkeletonBinary {
// Transform constraints.
for (int i = 0, n = input.readInt(true); i < n; i++) {
TransformConstraintData data = new TransformConstraintData(input.readString());
data.order = 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));
@ -236,6 +238,7 @@ public class SkeletonBinary {
// Path constraints.
for (int i = 0, n = input.readInt(true); i < n; i++) {
PathConstraintData data = new PathConstraintData(input.readString());
data.order = 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.slots.get(input.readInt(true));

View File

@ -157,6 +157,7 @@ public class SkeletonJson {
// IK constraints.
for (JsonValue constraintMap = root.getChild("ik"); constraintMap != null; constraintMap = constraintMap.next) {
IkConstraintData data = new IkConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
String boneName = boneMap.asString();
@ -178,6 +179,7 @@ public class SkeletonJson {
// Transform constraints.
for (JsonValue constraintMap = root.getChild("transform"); constraintMap != null; constraintMap = constraintMap.next) {
TransformConstraintData data = new TransformConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
String boneName = boneMap.asString();
@ -208,6 +210,7 @@ public class SkeletonJson {
// Path constraints.
for (JsonValue constraintMap = root.getChild("path"); constraintMap != null; constraintMap = constraintMap.next) {
PathConstraintData data = new PathConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
String boneName = boneMap.asString();

View File

@ -6,7 +6,7 @@ import static com.badlogic.gdx.math.MathUtils.*;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
public class TransformConstraint implements Updatable {
public class TransformConstraint implements Constraint {
final TransformConstraintData data;
final Array<Bone> bones;
Bone target;
@ -54,7 +54,7 @@ public class TransformConstraint implements Updatable {
for (int i = 0, n = bones.size; i < n; i++) {
Bone bone = bones.get(i);
if (rotateMix > 0) {
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)
@ -68,7 +68,7 @@ public class TransformConstraint implements Updatable {
bone.d = sin * b + cos * d;
}
if (translateMix > 0) {
if (translateMix != 0) {
Vector2 temp = this.temp;
target.localToWorld(temp.set(data.offsetX, data.offsetY));
bone.worldX += (temp.x - bone.worldX) * translateMix;
@ -103,6 +103,10 @@ public class TransformConstraint implements Updatable {
}
}
public int getOrder () {
return data.order;
}
public Array<Bone> getBones () {
return bones;
}

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Array;
public class TransformConstraintData {
final String name;
int order;
final Array<BoneData> bones = new Array();
BoneData target;
float rotateMix, translateMix, scaleMix, shearMix;
@ -19,6 +20,14 @@ public class TransformConstraintData {
return name;
}
public int getOrder () {
return order;
}
public void setOrder (int order) {
this.order = order;
}
public Array<BoneData> getBones () {
return bones;
}