diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index 621fc406f..f2a166e61 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -44,7 +44,8 @@ public class Bone implements Updatable { final Bone parent; final Array 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). *

- * 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) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java new file mode 100644 index 000000000..cf73f60ef --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java @@ -0,0 +1,6 @@ + +package com.esotericsoftware.spine; + +public interface Constraint extends Updatable { + public int getOrder (); +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 58e99dd18..e8074b252 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -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 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 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); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java index dfced65cc..53bef1806 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java @@ -35,6 +35,7 @@ import com.badlogic.gdx.utils.Array; public class IkConstraintData { final String name; + int order; final Array 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 getBones () { return bones; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index 7037eeb27..6f048a133 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -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; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java index c3be9bd2f..49ba08d95 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Array; public class PathConstraintData { final String name; + int order; final Array 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 getBones () { return bones; } @@ -94,10 +107,6 @@ public class PathConstraintData { this.translateMix = translateMix; } - public String getName () { - return name; - } - public String toString () { return name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 55ff6615f..e2055c45e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -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 bones; final Array slots; Array drawOrder; - final Array ikConstraints, ikConstraintsSorted; + final Array ikConstraints; final Array transformConstraints; final Array pathConstraints; + final Array sortedConstraints = new Array(); final Array updateCache = new Array(); Skin skin; final Color color; @@ -56,6 +59,9 @@ public class Skeleton { boolean flipX, flipY; float x, y; + final Comparator constraintComparator = new Comparator() { + 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 updateCache = this.updateCache; updateCache.clear(); - + Array 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 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 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 constrained = constraint.bones; - Bone parent = constrained.first(); - sortBone(parent); - - updateCache.add(constraint); - - sortReset(parent.children); - constrained.peek().sorted = true; - } - - Array 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 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 transformConstraints = this.transformConstraints; - for (int i = 0, n = transformConstraints.size; i < n; i++) { - TransformConstraint constraint = transformConstraints.get(i); - - sortBone(constraint.target); - - Array 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 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 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 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 entry : skin.attachments.entries()) if (entry.key.slotIndex == slotIndex) sortPathConstraintAttachment(entry.value, slotBone); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index a24fe562f..aa0c320cf 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -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)); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index f737f54e5..d920586ff 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -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(); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 2b6be66cd..fbe56d777 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -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 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 getBones () { return bones; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java index e20700526..964a48f1c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Array; public class TransformConstraintData { final String name; + int order; final Array 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 getBones () { return bones; }