Skip to content

Commit

Permalink
Changed skeleton flipX/Y to scaleX/Y.
Browse files Browse the repository at this point in the history
Cleans up applying transforms and is more powerful. Allows scaling a whole skeleton which has bones that disallow scale inheritance.
  • Loading branch information
NathanSweet committed Jul 2, 2018
1 parent b82b27e commit d9a6b91
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 117 deletions.
Expand Up @@ -50,7 +50,7 @@ public void create () {

skeleton = new Skeleton(skeletonData);
skeleton.setPosition(320, 590);
skeleton.flipY = true;
skeleton.setScaleY(-1);

AnimationStateData stateData = new AnimationStateData(skeletonData);
state = new AnimationState(stateData);
Expand Down
55 changes: 16 additions & 39 deletions spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java
Expand Up @@ -30,13 +30,12 @@

package com.esotericsoftware.spine;

import static com.esotericsoftware.spine.utils.SpineUtils.*;
import static com.badlogic.gdx.math.Matrix3.*;
import static com.esotericsoftware.spine.utils.SpineUtils.*;

import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.esotericsoftware.spine.BoneData.TransformMode;

/** Stores a bone's current pose.
* <p>
Expand Down Expand Up @@ -111,28 +110,14 @@ public void updateWorldTransform (float x, float y, float rotation, float scaleX

Bone parent = this.parent;
if (parent == null) { // Root bone.
float rotationY = rotation + 90 + shearY;
float la = cosDeg(rotation + shearX) * scaleX;
float lb = cosDeg(rotationY) * scaleY;
float lc = sinDeg(rotation + shearX) * scaleX;
float ld = sinDeg(rotationY) * scaleY;
Skeleton skeleton = this.skeleton;
if (skeleton.flipX) {
x = -x;
la = -la;
lb = -lb;
}
if (skeleton.flipY) {
y = -y;
lc = -lc;
ld = -ld;
}
a = la;
b = lb;
c = lc;
d = ld;
worldX = x + skeleton.x;
worldY = y + skeleton.y;
float rotationY = rotation + 90 + shearY, sx = skeleton.scaleX, sy = skeleton.scaleY;
a = cosDeg(rotation + shearX) * scaleX * sx;
b = cosDeg(rotationY) * scaleY * sy;
c = sinDeg(rotation + shearX) * scaleX * sx;
d = sinDeg(rotationY) * scaleY * sy;
worldX = x * sx + skeleton.x;
worldY = y * sy + skeleton.y;
return;
}

Expand Down Expand Up @@ -188,8 +173,8 @@ public void updateWorldTransform (float x, float y, float rotation, float scaleX
case noScale:
case noScaleOrReflection: {
float cos = cosDeg(rotation), sin = sinDeg(rotation);
float za = pa * cos + pb * sin;
float zc = pc * cos + pd * sin;
float za = (pa * cos + pb * sin) / skeleton.scaleX;
float zc = (pc * cos + pd * sin) / skeleton.scaleY;
float s = (float)Math.sqrt(za * za + zc * zc);
if (s > 0.00001f) s = 1 / s;
za *= s;
Expand All @@ -201,26 +186,18 @@ public void updateWorldTransform (float x, float y, float rotation, float scaleX
float la = cosDeg(shearX) * scaleX;
float lb = cosDeg(90 + shearY) * scaleY;
float lc = sinDeg(shearX) * scaleX;
float ld = sinDeg(90 + shearY) * scaleY;
if (data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
zb = -zb;
zd = -zd;
}
float ld = sinDeg(90 + shearY) * scaleY;
a = za * la + zb * lc;
b = za * lb + zb * ld;
c = zc * la + zd * lc;
d = zc * lb + zd * ld;
return;
}
}
if (skeleton.flipX) {
a = -a;
b = -b;
break;
}
if (skeleton.flipY) {
c = -c;
d = -d;
}
a *= skeleton.scaleX;
b *= skeleton.scaleX;
c *= skeleton.scaleY;
d *= skeleton.scaleY;
}

/** Sets this bone's local transform to the setup pose. */
Expand Down
Expand Up @@ -30,14 +30,14 @@

package com.esotericsoftware.spine;

import static com.esotericsoftware.spine.utils.SpineUtils.cosDeg;
import static com.esotericsoftware.spine.utils.SpineUtils.sinDeg;
import static com.esotericsoftware.spine.utils.SpineUtils.*;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.ObjectMap.Entry;

import com.esotericsoftware.spine.Skin.Key;
import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.MeshAttachment;
Expand All @@ -61,7 +61,7 @@ public class Skeleton {
Skin skin;
final Color color;
float time;
boolean flipX, flipY;
float scaleX = 1, scaleY = 1;
float x, y;

public Skeleton (SkeletonData data) {
Expand Down Expand Up @@ -150,8 +150,8 @@ public Skeleton (Skeleton skeleton) {
skin = skeleton.skin;
color = new Color(skeleton.color);
time = skeleton.time;
flipX = skeleton.flipX;
flipY = skeleton.flipY;
scaleX = skeleton.scaleX;
scaleY = skeleton.scaleY;

updateCache();
}
Expand Down Expand Up @@ -331,9 +331,9 @@ public void updateWorldTransform () {
for (int i = 0, n = updateCache.size; i < n; i++)
updateCache.get(i).update();
}
/** Updates the world transform for each bone and applies all constraints. The
* root bone will be temporarily parented to the specified bone.

/** Updates the world transform for each bone and applies all constraints. The root bone will be temporarily parented to the
* specified bone.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
* Runtimes Guide. */
Expand All @@ -353,7 +353,7 @@ public void updateWorldTransform (Bone parent) {
bone.ashearY = bone.shearY;
bone.appliedValid = true;
}

// Apply the parent bone transform to the root bone. The root bone
// always inherits scale, rotation and reflection.
Bone rootBone = getRootBone();
Expand All @@ -366,20 +366,11 @@ public void updateWorldTransform (Bone parent) {
float lb = cosDeg(rotationY) * rootBone.scaleY;
float lc = sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
float ld = sinDeg(rotationY) * rootBone.scaleY;
rootBone.a = pa * la + pb * lc;
rootBone.b = pa * lb + pb * ld;
rootBone.c = pc * la + pd * lc;
rootBone.d = pc * lb + pd * ld;

if (flipY) {
rootBone.a = -rootBone.a;
rootBone.b = -rootBone.b;
}
if (flipX) {
rootBone.c = -rootBone.c;
rootBone.d = -rootBone.d;
}

rootBone.a = (pa * la + pb * lc) * scaleX;
rootBone.b = (pa * lb + pb * ld) * scaleX;
rootBone.c = (pc * la + pd * lc) * scaleY;
rootBone.d = (pc * lb + pd * ld) * scaleY;

// Update everything except root bone.
Array<Updatable> updateCache = this.updateCache;
for (int i = 0, n = updateCache.size; i < n; i++) {
Expand Down Expand Up @@ -685,29 +676,29 @@ public void setColor (Color color) {
this.color.set(color);
}

/** If true, the entire skeleton is flipped over the Y axis. This affects all bones, even if the bone's transform mode
* disallows scale inheritance. */
public boolean getFlipX () {
return flipX;
/** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
public float getScaleX () {
return scaleX;
}

public void setFlipX (boolean flipX) {
this.flipX = flipX;
public void setScaleX (float scaleX) {
this.scaleX = scaleX;
}

/** If true, the entire skeleton is flipped over the X axis. This affects all bones, even if the bone's transform mode
* disallows scale inheritance. */
public boolean getFlipY () {
return flipY;
/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale
* inheritance. */
public float getScaleY () {
return scaleY;
}

public void setFlipY (boolean flipY) {
this.flipY = flipY;
public void setScaleY (float scaleY) {
this.scaleY = scaleY;
}

public void setFlip (boolean flipX, boolean flipY) {
this.flipX = flipX;
this.flipY = flipY;
public void setScale (float scaleX, float scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
}

/** Sets the skeleton X position, which is added to the root bone worldX position. */
Expand Down
Expand Up @@ -70,7 +70,7 @@ protected Skeleton newObject () {

protected void reset (Skeleton skeleton) {
skeleton.setColor(Color.WHITE);
skeleton.setFlip(false, false);
skeleton.setScale(1, 1);
skeleton.setSkin((Skin)null);
skeleton.setSkin(SkeletonActorPool.this.skeletonData.getDefaultSkin());
skeleton.setToSetupPose();
Expand Down

0 comments on commit d9a6b91

Please sign in to comment.