mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Updated for Spine 3.0.00.
This commit is contained in:
parent
f6e4027ef1
commit
37f2f9e880
8
LICENSE
8
LICENSE
@ -1,7 +1,7 @@
|
|||||||
Spine Runtimes Software License
|
Spine Runtimes Software License
|
||||||
Version 2.3
|
Version 2.4
|
||||||
|
|
||||||
Copyright (c) 2013-2015, Esoteric Software
|
Copyright (c) 2013-2016, Esoteric Software
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
You are granted a perpetual, non-exclusive, non-sublicensable and
|
You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||||
@ -9,8 +9,8 @@ non-transferable license to use, install, execute and perform the Spine
|
|||||||
Runtimes Software (the "Software") and derivative works solely for personal
|
Runtimes Software (the "Software") and derivative works solely for personal
|
||||||
or internal use. Without the written permission of Esoteric Software (see
|
or internal use. Without the written permission of Esoteric Software (see
|
||||||
Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||||
translate, adapt or otherwise create derivative works, improvements of the
|
translate, adapt or otherwise create derivative works, improvements of
|
||||||
Software or develop new applications using the Software or (b) remove,
|
the Software or develop new applications using the Software or (b) remove,
|
||||||
delete, alter or obscure any trademarks or any copyright, trademark, patent
|
delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||||
or other intellectual property or proprietary rights notices on or in the
|
or other intellectual property or proprietary rights notices on or in the
|
||||||
Software, including any copy thereof. Redistributions in binary or source
|
Software, including any copy thereof. Redistributions in binary or source
|
||||||
|
|||||||
@ -67,8 +67,8 @@ public class BonePlotting {
|
|||||||
while (time < animation.getDuration()) {
|
while (time < animation.getDuration()) {
|
||||||
animation.apply(skeleton, time, time, false, null);
|
animation.apply(skeleton, time, time, false, null);
|
||||||
skeleton.updateWorldTransform();
|
skeleton.updateWorldTransform();
|
||||||
System.out.println(animation.getName() + "," + bone.getWorldX() + "," + bone.getWorldY() + ","
|
System.out
|
||||||
+ bone.getWorldRotation() + "," + bone.getWorldScaleX() + "," + bone.getWorldScaleY());
|
.println(animation.getName() + "," + bone.getWorldX() + "," + bone.getWorldY() + "," + bone.getWorldRotationX());
|
||||||
time += fps;
|
time += fps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -160,7 +160,7 @@ public class Box2DExample extends ApplicationAdapter {
|
|||||||
if (attachment.body == null) continue;
|
if (attachment.body == null) continue;
|
||||||
float x = skeleton.x + slot.getBone().getWorldX();
|
float x = skeleton.x + slot.getBone().getWorldX();
|
||||||
float y = skeleton.y + slot.getBone().getWorldY();
|
float y = skeleton.y + slot.getBone().getWorldY();
|
||||||
float rotation = slot.getBone().getWorldRotation();
|
float rotation = slot.getBone().getWorldRotationX();
|
||||||
attachment.body.setTransform(x, y, rotation * MathUtils.degRad);
|
attachment.body.setTransform(x, y, rotation * MathUtils.degRad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
|||||||
public class SimpleTest3 extends ApplicationAdapter {
|
public class SimpleTest3 extends ApplicationAdapter {
|
||||||
OrthographicCamera camera;
|
OrthographicCamera camera;
|
||||||
PolygonSpriteBatch batch;
|
PolygonSpriteBatch batch;
|
||||||
SkeletonRenderer renderer;
|
SkeletonMeshRenderer renderer;
|
||||||
SkeletonRendererDebug debugRenderer;
|
SkeletonRendererDebug debugRenderer;
|
||||||
|
|
||||||
TextureAtlas atlas;
|
TextureAtlas atlas;
|
||||||
@ -52,7 +52,7 @@ public class SimpleTest3 extends ApplicationAdapter {
|
|||||||
public void create () {
|
public void create () {
|
||||||
camera = new OrthographicCamera();
|
camera = new OrthographicCamera();
|
||||||
batch = new PolygonSpriteBatch(); // Required to render meshes. SpriteBatch can't render meshes.
|
batch = new PolygonSpriteBatch(); // Required to render meshes. SpriteBatch can't render meshes.
|
||||||
renderer = new SkeletonRenderer();
|
renderer = new SkeletonMeshRenderer();
|
||||||
renderer.setPremultipliedAlpha(true);
|
renderer.setPremultipliedAlpha(true);
|
||||||
debugRenderer = new SkeletonRendererDebug();
|
debugRenderer = new SkeletonRendererDebug();
|
||||||
debugRenderer.setMeshTriangles(false);
|
debugRenderer.setMeshTriangles(false);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
|||||||
public class SkeletonAttachmentTest extends ApplicationAdapter {
|
public class SkeletonAttachmentTest extends ApplicationAdapter {
|
||||||
OrthographicCamera camera;
|
OrthographicCamera camera;
|
||||||
PolygonSpriteBatch batch;
|
PolygonSpriteBatch batch;
|
||||||
SkeletonRenderer renderer;
|
SkeletonMeshRenderer renderer;
|
||||||
|
|
||||||
Skeleton spineboy, goblin;
|
Skeleton spineboy, goblin;
|
||||||
AnimationState spineboyState, goblinState;
|
AnimationState spineboyState, goblinState;
|
||||||
@ -53,7 +53,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter {
|
|||||||
public void create () {
|
public void create () {
|
||||||
camera = new OrthographicCamera();
|
camera = new OrthographicCamera();
|
||||||
batch = new PolygonSpriteBatch();
|
batch = new PolygonSpriteBatch();
|
||||||
renderer = new SkeletonRenderer();
|
renderer = new SkeletonMeshRenderer();
|
||||||
renderer.setPremultipliedAlpha(true);
|
renderer.setPremultipliedAlpha(true);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -77,9 +77,9 @@ public class SkeletonAttachmentTest extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("goblins/goblins-ffd.atlas"));
|
TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("goblins/goblins-mesh.atlas"));
|
||||||
SkeletonJson json = new SkeletonJson(atlas);
|
SkeletonJson json = new SkeletonJson(atlas);
|
||||||
SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("goblins/goblins-ffd.json"));
|
SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("goblins/goblins-mesh.json"));
|
||||||
goblin = new Skeleton(skeletonData);
|
goblin = new Skeleton(skeletonData);
|
||||||
goblin.setSkin("goblin");
|
goblin.setSkin("goblin");
|
||||||
goblin.setSlotsToSetupPose();
|
goblin.setSlotsToSetupPose();
|
||||||
|
|||||||
@ -777,62 +777,4 @@ public class Animation {
|
|||||||
ikConstraint.bendDirection = (int)frames[frameIndex + PREV_FRAME_BEND_DIRECTION];
|
ikConstraint.bendDirection = (int)frames[frameIndex + PREV_FRAME_BEND_DIRECTION];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public class FlipXTimeline implements Timeline {
|
|
||||||
int boneIndex;
|
|
||||||
final float[] frames; // time, flip, ...
|
|
||||||
|
|
||||||
public FlipXTimeline (int frameCount) {
|
|
||||||
frames = new float[frameCount << 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBoneIndex (int boneIndex) {
|
|
||||||
this.boneIndex = boneIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBoneIndex () {
|
|
||||||
return boneIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFrameCount () {
|
|
||||||
return frames.length >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float[] getFrames () {
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the time and value of the specified keyframe. */
|
|
||||||
public void setFrame (int frameIndex, float time, boolean flip) {
|
|
||||||
frameIndex *= 2;
|
|
||||||
frames[frameIndex] = time;
|
|
||||||
frames[frameIndex + 1] = flip ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha) {
|
|
||||||
float[] frames = this.frames;
|
|
||||||
if (time < frames[0]) {
|
|
||||||
if (lastTime > time) apply(skeleton, lastTime, Integer.MAX_VALUE, null, 0);
|
|
||||||
return;
|
|
||||||
} else if (lastTime > time) //
|
|
||||||
lastTime = -1;
|
|
||||||
int frameIndex = (time >= frames[frames.length - 2] ? frames.length : binarySearch(frames, time, 2)) - 2;
|
|
||||||
if (frames[frameIndex] < lastTime) return;
|
|
||||||
setFlip(skeleton.bones.get(boneIndex), frames[frameIndex + 1] != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setFlip (Bone bone, boolean flip) {
|
|
||||||
bone.setFlipX(flip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public class FlipYTimeline extends FlipXTimeline {
|
|
||||||
public FlipYTimeline (int frameCount) {
|
|
||||||
super(frameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setFlip (Bone bone, boolean flip) {
|
|
||||||
bone.setFlipY(flip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import com.badlogic.gdx.utils.Pool.Poolable;
|
|||||||
|
|
||||||
/** Stores state for an animation and automatically mixes between animations. */
|
/** Stores state for an animation and automatically mixes between animations. */
|
||||||
public class AnimationState {
|
public class AnimationState {
|
||||||
private final AnimationStateData data;
|
private AnimationStateData data;
|
||||||
private Array<TrackEntry> tracks = new Array();
|
private Array<TrackEntry> tracks = new Array();
|
||||||
private final Array<Event> events = new Array();
|
private final Array<Event> events = new Array();
|
||||||
private final Array<AnimationStateListener> listeners = new Array();
|
private final Array<AnimationStateListener> listeners = new Array();
|
||||||
@ -49,6 +49,10 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Creates an uninitialized AnimationState. The animation state data must be set. */
|
||||||
|
public AnimationState () {
|
||||||
|
}
|
||||||
|
|
||||||
public AnimationState (AnimationStateData data) {
|
public AnimationState (AnimationStateData data) {
|
||||||
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -269,6 +273,10 @@ public class AnimationState {
|
|||||||
listeners.removeValue(listener, true);
|
listeners.removeValue(listener, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearListeners () {
|
||||||
|
listeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public float getTimeScale () {
|
public float getTimeScale () {
|
||||||
return timeScale;
|
return timeScale;
|
||||||
}
|
}
|
||||||
@ -281,6 +289,10 @@ public class AnimationState {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setData (AnimationStateData data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the list of tracks that have animations, which may contain nulls. */
|
/** Returns the list of tracks that have animations, which may contain nulls. */
|
||||||
public Array<TrackEntry> getTracks () {
|
public Array<TrackEntry> getTracks () {
|
||||||
return tracks;
|
return tracks;
|
||||||
|
|||||||
@ -31,26 +31,23 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine;
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
import static com.badlogic.gdx.math.MathUtils.*;
|
||||||
import static com.badlogic.gdx.math.Matrix3.*;
|
import static com.badlogic.gdx.math.Matrix3.*;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.math.Matrix3;
|
import com.badlogic.gdx.math.Matrix3;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
public class Bone {
|
public class Bone implements Updatable {
|
||||||
final BoneData data;
|
final BoneData data;
|
||||||
final Skeleton skeleton;
|
final Skeleton skeleton;
|
||||||
final Bone parent;
|
final Bone parent;
|
||||||
float x, y;
|
float x, y, rotation, scaleX, scaleY;
|
||||||
float rotation, rotationIK;
|
float appliedRotation, appliedScaleX, appliedScaleY;
|
||||||
float scaleX, scaleY;
|
|
||||||
boolean flipX, flipY;
|
|
||||||
|
|
||||||
float m00, m01, worldX; // a b x
|
float a, b, worldX;
|
||||||
float m10, m11, worldY; // c d y
|
float c, d, worldY;
|
||||||
float worldRotation;
|
float worldSignX, worldSignY;
|
||||||
float worldScaleX, worldScaleY;
|
|
||||||
boolean worldFlipX, worldFlipY;
|
|
||||||
|
|
||||||
Bone (BoneData data) {
|
Bone (BoneData data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -78,69 +75,135 @@ public class Bone {
|
|||||||
x = bone.x;
|
x = bone.x;
|
||||||
y = bone.y;
|
y = bone.y;
|
||||||
rotation = bone.rotation;
|
rotation = bone.rotation;
|
||||||
rotationIK = bone.rotationIK;
|
|
||||||
scaleX = bone.scaleX;
|
scaleX = bone.scaleX;
|
||||||
scaleY = bone.scaleY;
|
scaleY = bone.scaleY;
|
||||||
flipX = bone.flipX;
|
|
||||||
flipY = bone.flipY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the world SRT using the parent bone and the local SRT. */
|
/** Computes the world SRT using the parent bone and this bone's local SRT. */
|
||||||
public void updateWorldTransform () {
|
public void updateWorldTransform () {
|
||||||
Skeleton skeleton = this.skeleton;
|
updateWorldTransform(x, y, rotation, scaleX, scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Computes the world SRT using the parent bone and the specified local SRT. */
|
||||||
|
public void updateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY) {
|
||||||
|
appliedRotation = rotation;
|
||||||
|
appliedScaleX = scaleX;
|
||||||
|
appliedScaleY = scaleY;
|
||||||
|
|
||||||
|
float cos = MathUtils.cosDeg(rotation), sin = MathUtils.sinDeg(rotation);
|
||||||
|
float la = cos * scaleX, lb = -sin * scaleY, lc = sin * scaleX, ld = cos * scaleY;
|
||||||
Bone parent = this.parent;
|
Bone parent = this.parent;
|
||||||
float x = this.x, y = this.y;
|
if (parent == null) { // Root bone.
|
||||||
if (parent != null) {
|
Skeleton skeleton = this.skeleton;
|
||||||
worldX = x * parent.m00 + y * parent.m01 + parent.worldX;
|
|
||||||
worldY = x * parent.m10 + y * parent.m11 + parent.worldY;
|
|
||||||
if (data.inheritScale) {
|
|
||||||
worldScaleX = parent.worldScaleX * scaleX;
|
|
||||||
worldScaleY = parent.worldScaleY * scaleY;
|
|
||||||
} else {
|
|
||||||
worldScaleX = scaleX;
|
|
||||||
worldScaleY = scaleY;
|
|
||||||
}
|
|
||||||
worldRotation = data.inheritRotation ? parent.worldRotation + rotationIK : rotationIK;
|
|
||||||
worldFlipX = parent.worldFlipX ^ flipX;
|
|
||||||
worldFlipY = parent.worldFlipY ^ flipY;
|
|
||||||
} else {
|
|
||||||
boolean skeletonFlipX = skeleton.flipX, skeletonFlipY = skeleton.flipY;
|
boolean skeletonFlipX = skeleton.flipX, skeletonFlipY = skeleton.flipY;
|
||||||
worldX = skeletonFlipX ? -x : x;
|
if (skeletonFlipX) {
|
||||||
worldY = skeletonFlipY ? -y : y;
|
scaleX = -scaleX;
|
||||||
worldScaleX = scaleX;
|
x = -x;
|
||||||
worldScaleY = scaleY;
|
}
|
||||||
worldRotation = rotationIK;
|
if (skeletonFlipY) {
|
||||||
worldFlipX = skeletonFlipX ^ flipX;
|
scaleY = -scaleY;
|
||||||
worldFlipY = skeletonFlipY ^ flipY;
|
y = -y;
|
||||||
|
}
|
||||||
|
a = la;
|
||||||
|
b = lb;
|
||||||
|
c = lc;
|
||||||
|
d = ld;
|
||||||
|
worldX = x;
|
||||||
|
worldY = y;
|
||||||
|
worldSignX = Math.signum(scaleX);
|
||||||
|
worldSignY = Math.signum(scaleY);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
float cos = MathUtils.cosDeg(worldRotation);
|
|
||||||
float sin = MathUtils.sinDeg(worldRotation);
|
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||||
if (worldFlipX) {
|
worldX = pa * x + pb * y + parent.worldX;
|
||||||
m00 = -cos * worldScaleX;
|
worldY = pc * x + pd * y + parent.worldY;
|
||||||
m01 = sin * worldScaleY;
|
worldSignX = parent.worldSignX * Math.signum(scaleX);
|
||||||
|
worldSignY = parent.worldSignY * Math.signum(scaleY);
|
||||||
|
|
||||||
|
if (data.inheritRotation && data.inheritScale) {
|
||||||
|
a = pa * la + pb * lc;
|
||||||
|
b = pa * lb + pb * ld;
|
||||||
|
c = pc * la + pd * lc;
|
||||||
|
d = pc * lb + pd * ld;
|
||||||
|
} else if (data.inheritRotation) { // No scale inheritance.
|
||||||
|
Bone p = parent;
|
||||||
|
pa = 1;
|
||||||
|
pb = 0;
|
||||||
|
pc = 0;
|
||||||
|
pd = 1;
|
||||||
|
while (p != null) {
|
||||||
|
cos = MathUtils.cosDeg(p.appliedRotation);
|
||||||
|
sin = MathUtils.sinDeg(p.appliedRotation);
|
||||||
|
float a = pa * cos + pb * sin;
|
||||||
|
float b = pa * -sin + pb * cos;
|
||||||
|
float c = pc * cos + pd * sin;
|
||||||
|
float d = pc * -sin + pd * cos;
|
||||||
|
pa = a;
|
||||||
|
pb = b;
|
||||||
|
pc = c;
|
||||||
|
pd = d;
|
||||||
|
p = p.parent;
|
||||||
|
}
|
||||||
|
a = pa * la + pb * lc;
|
||||||
|
b = pa * lb + pb * ld;
|
||||||
|
c = pc * la + pd * lc;
|
||||||
|
d = pc * lb + pd * ld;
|
||||||
|
} else if (data.inheritScale) { // No rotation inheritance.
|
||||||
|
Bone p = parent;
|
||||||
|
pa = 1;
|
||||||
|
pb = 0;
|
||||||
|
pc = 0;
|
||||||
|
pd = 1;
|
||||||
|
while (p != null) {
|
||||||
|
float r = p.rotation;
|
||||||
|
cos = MathUtils.cosDeg(r);
|
||||||
|
sin = MathUtils.sinDeg(r);
|
||||||
|
float psx = p.appliedScaleX, psy = p.appliedScaleY;
|
||||||
|
float za = cos * psx, zb = -sin * psy, zc = sin * psx, zd = cos * psy;
|
||||||
|
float temp = pa * za + pb * zc;
|
||||||
|
pb = pa * zb + pb * zd;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * za + pd * zc;
|
||||||
|
pd = pc * zb + pd * zd;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (psx < 0) r = PI - r;
|
||||||
|
cos = MathUtils.cosDeg(-r);
|
||||||
|
sin = MathUtils.sinDeg(-r);
|
||||||
|
temp = pa * cos + pb * sin;
|
||||||
|
pb = pa * -sin + pb * cos;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * cos + pd * sin;
|
||||||
|
pd = pc * -sin + pd * cos;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
p = p.parent;
|
||||||
|
}
|
||||||
|
a = pa * la + pb * lc;
|
||||||
|
b = pa * lb + pb * ld;
|
||||||
|
c = pc * la + pd * lc;
|
||||||
|
d = pc * lb + pd * ld;
|
||||||
} else {
|
} else {
|
||||||
m00 = cos * worldScaleX;
|
a = la;
|
||||||
m01 = -sin * worldScaleY;
|
b = lb;
|
||||||
}
|
c = lc;
|
||||||
if (worldFlipY) {
|
d = ld;
|
||||||
m10 = -sin * worldScaleX;
|
|
||||||
m11 = -cos * worldScaleY;
|
|
||||||
} else {
|
|
||||||
m10 = sin * worldScaleX;
|
|
||||||
m11 = cos * worldScaleY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Same as {@link #updateWorldTransform()}. This method exists for Bone to implement {@link Updatable}. */
|
||||||
|
public void update () {
|
||||||
|
updateWorldTransform(x, y, rotation, scaleX, scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
public void setToSetupPose () {
|
public void setToSetupPose () {
|
||||||
BoneData data = this.data;
|
BoneData data = this.data;
|
||||||
x = data.x;
|
x = data.x;
|
||||||
y = data.y;
|
y = data.y;
|
||||||
rotation = data.rotation;
|
rotation = data.rotation;
|
||||||
rotationIK = rotation;
|
|
||||||
scaleX = data.scaleX;
|
scaleX = data.scaleX;
|
||||||
scaleY = data.scaleY;
|
scaleY = data.scaleY;
|
||||||
flipX = data.flipX;
|
|
||||||
flipY = data.flipY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoneData getData () {
|
public BoneData getData () {
|
||||||
@ -185,15 +248,6 @@ public class Bone {
|
|||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the inverse kinetics rotation, as calculated by any IK constraints. */
|
|
||||||
public float getRotationIK () {
|
|
||||||
return rotationIK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRotationIK (float rotationIK) {
|
|
||||||
this.rotationIK = rotationIK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getScaleX () {
|
public float getScaleX () {
|
||||||
return scaleX;
|
return scaleX;
|
||||||
}
|
}
|
||||||
@ -220,36 +274,20 @@ public class Bone {
|
|||||||
scaleY = scale;
|
scaleY = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFlipX () {
|
public float getA () {
|
||||||
return flipX;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlipX (boolean flipX) {
|
public float getB () {
|
||||||
this.flipX = flipX;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFlipY () {
|
public float getC () {
|
||||||
return flipY;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlipY (boolean flipY) {
|
public float getD () {
|
||||||
this.flipY = flipY;
|
return d;
|
||||||
}
|
|
||||||
|
|
||||||
public float getM00 () {
|
|
||||||
return m00;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getM01 () {
|
|
||||||
return m01;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getM10 () {
|
|
||||||
return m10;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getM11 () {
|
|
||||||
return m11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWorldX () {
|
public float getWorldX () {
|
||||||
@ -260,33 +298,37 @@ public class Bone {
|
|||||||
return worldY;
|
return worldY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWorldRotation () {
|
public float getWorldRotationX () {
|
||||||
return worldRotation;
|
return (float)Math.atan2(c, a) * MathUtils.radDeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getWorldRotationY () {
|
||||||
|
return (float)Math.atan2(d, b) * MathUtils.radDeg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWorldScaleX () {
|
public float getWorldScaleX () {
|
||||||
return worldScaleX;
|
return (float)Math.sqrt(a * a + b * b) * worldSignX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWorldScaleY () {
|
public float getWorldScaleY () {
|
||||||
return worldScaleY;
|
return (float)Math.sqrt(c * c + d * d) * worldSignY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getWorldFlipX () {
|
public float getWorldSignX () {
|
||||||
return worldFlipX;
|
return worldSignX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getWorldFlipY () {
|
public float getWorldSignY () {
|
||||||
return worldFlipY;
|
return worldSignY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix3 getWorldTransform (Matrix3 worldTransform) {
|
public Matrix3 getWorldTransform (Matrix3 worldTransform) {
|
||||||
if (worldTransform == null) throw new IllegalArgumentException("worldTransform cannot be null.");
|
if (worldTransform == null) throw new IllegalArgumentException("worldTransform cannot be null.");
|
||||||
float[] val = worldTransform.val;
|
float[] val = worldTransform.val;
|
||||||
val[M00] = m00;
|
val[M00] = a;
|
||||||
val[M01] = m01;
|
val[M01] = b;
|
||||||
val[M10] = m10;
|
val[M10] = c;
|
||||||
val[M11] = m11;
|
val[M11] = d;
|
||||||
val[M02] = worldX;
|
val[M02] = worldX;
|
||||||
val[M12] = worldY;
|
val[M12] = worldY;
|
||||||
val[M20] = 0;
|
val[M20] = 0;
|
||||||
@ -297,21 +339,17 @@ public class Bone {
|
|||||||
|
|
||||||
public Vector2 worldToLocal (Vector2 world) {
|
public Vector2 worldToLocal (Vector2 world) {
|
||||||
float x = world.x - worldX, y = world.y - worldY;
|
float x = world.x - worldX, y = world.y - worldY;
|
||||||
float m00 = this.m00, m10 = this.m10, m01 = this.m01, m11 = this.m11;
|
float a = this.a, b = this.b, c = this.c, d = this.d;
|
||||||
if (worldFlipX != worldFlipY) {
|
float invDet = 1 / (a * d - b * c);
|
||||||
m00 = -m00;
|
world.x = (x * a * invDet - y * b * invDet);
|
||||||
m11 = -m11;
|
world.y = (y * d * invDet - x * c * invDet);
|
||||||
}
|
|
||||||
float invDet = 1 / (m00 * m11 - m01 * m10);
|
|
||||||
world.x = (x * m00 * invDet - y * m01 * invDet);
|
|
||||||
world.y = (y * m11 * invDet - x * m10 * invDet);
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 localToWorld (Vector2 local) {
|
public Vector2 localToWorld (Vector2 local) {
|
||||||
float x = local.x, y = local.y;
|
float x = local.x, y = local.y;
|
||||||
local.x = x * m00 + y * m01 + worldX;
|
local.x = x * a + y * b + worldX;
|
||||||
local.y = x * m10 + y * m11 + worldY;
|
local.y = x * c + y * d + worldY;
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,8 +40,7 @@ public class BoneData {
|
|||||||
float x, y;
|
float x, y;
|
||||||
float rotation;
|
float rotation;
|
||||||
float scaleX = 1, scaleY = 1;
|
float scaleX = 1, scaleY = 1;
|
||||||
boolean flipX, flipY;
|
boolean inheritScale, inheritRotation;
|
||||||
boolean inheritScale = true, inheritRotation = true;
|
|
||||||
|
|
||||||
// Nonessential.
|
// Nonessential.
|
||||||
final Color color = new Color(0.61f, 0.61f, 0.61f, 1);
|
final Color color = new Color(0.61f, 0.61f, 0.61f, 1);
|
||||||
@ -65,8 +64,6 @@ public class BoneData {
|
|||||||
rotation = bone.rotation;
|
rotation = bone.rotation;
|
||||||
scaleX = bone.scaleX;
|
scaleX = bone.scaleX;
|
||||||
scaleY = bone.scaleY;
|
scaleY = bone.scaleY;
|
||||||
flipX = bone.flipX;
|
|
||||||
flipY = bone.flipY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return May be null. */
|
/** @return May be null. */
|
||||||
@ -136,22 +133,6 @@ public class BoneData {
|
|||||||
this.scaleY = scaleY;
|
this.scaleY = scaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFlipX () {
|
|
||||||
return flipX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlipX (boolean flipX) {
|
|
||||||
this.flipX = flipX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getFlipY () {
|
|
||||||
return flipY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlipY (boolean flipY) {
|
|
||||||
this.flipY = flipY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getInheritScale () {
|
public boolean getInheritScale () {
|
||||||
return inheritScale;
|
return inheritScale;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,12 +33,9 @@ package com.esotericsoftware.spine;
|
|||||||
|
|
||||||
import static com.badlogic.gdx.math.MathUtils.*;
|
import static com.badlogic.gdx.math.MathUtils.*;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
public class IkConstraint {
|
public class IkConstraint implements Updatable {
|
||||||
static private final Vector2 temp = new Vector2();
|
|
||||||
|
|
||||||
final IkConstraintData data;
|
final IkConstraintData data;
|
||||||
final Array<Bone> bones;
|
final Array<Bone> bones;
|
||||||
Bone target;
|
Bone target;
|
||||||
@ -59,15 +56,21 @@ public class IkConstraint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Copy constructor. */
|
/** Copy constructor. */
|
||||||
public IkConstraint (IkConstraint ikConstraint, Array<Bone> bones, Bone target) {
|
public IkConstraint (IkConstraint ikConstraint, Skeleton skeleton) {
|
||||||
data = ikConstraint.data;
|
data = ikConstraint.data;
|
||||||
this.bones = bones;
|
bones = new Array(ikConstraint.bones.size);
|
||||||
this.target = target;
|
for (Bone bone : ikConstraint.bones)
|
||||||
|
bones.add(skeleton.bones.get(bone.skeleton.bones.indexOf(bone, true)));
|
||||||
|
target = skeleton.bones.get(ikConstraint.target.skeleton.bones.indexOf(ikConstraint.target, true));
|
||||||
mix = ikConstraint.mix;
|
mix = ikConstraint.mix;
|
||||||
bendDirection = ikConstraint.bendDirection;
|
bendDirection = ikConstraint.bendDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply () {
|
public void apply () {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update () {
|
||||||
Bone target = this.target;
|
Bone target = this.target;
|
||||||
Array<Bone> bones = this.bones;
|
Array<Bone> bones = this.bones;
|
||||||
switch (bones.size) {
|
switch (bones.size) {
|
||||||
@ -113,67 +116,143 @@ public class IkConstraint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return data.name;
|
return data.name + " CONSTRAINT";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
|
/** 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. */
|
* coordinate system. */
|
||||||
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
||||||
float parentRotation = (!bone.data.inheritRotation || bone.parent == null) ? 0 : bone.parent.worldRotation;
|
float parentRotation = bone.parent == null ? 0 : bone.parent.getWorldRotationX();
|
||||||
float rotation = bone.rotation;
|
float rotation = bone.rotation;
|
||||||
float rotationIK = (float)Math.atan2(targetY - bone.worldY, targetX - bone.worldX) * radDeg - parentRotation;
|
float rotationIK = atan2(targetY - bone.worldY, targetX - bone.worldX) * radDeg - parentRotation;
|
||||||
bone.rotationIK = rotation + (rotationIK - rotation) * alpha;
|
if (rotationIK > 180)
|
||||||
|
rotationIK -= 360;
|
||||||
|
else if (rotationIK < -180) rotationIK += 360;
|
||||||
|
bone.updateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.scaleX, bone.scaleY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
|
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
|
||||||
* target is specified in the world coordinate system.
|
* target is specified in the world coordinate system.
|
||||||
* @param child Any descendant bone of the parent. */
|
* @param child Any descendant bone of the parent. */
|
||||||
static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha) {
|
static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
|
||||||
float childRotation = child.rotation, parentRotation = parent.rotation;
|
if (alpha == 0) return;
|
||||||
if (alpha == 0) {
|
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX, cy = child.y;
|
||||||
child.rotationIK = childRotation;
|
int offset1, offset2, sign2;
|
||||||
parent.rotationIK = parentRotation;
|
if (psx < 0) {
|
||||||
return;
|
psx = -psx;
|
||||||
}
|
offset1 = 180;
|
||||||
Vector2 position = temp;
|
sign2 = -1;
|
||||||
Bone parentParent = parent.parent;
|
|
||||||
if (parentParent != null) {
|
|
||||||
parentParent.worldToLocal(position.set(targetX, targetY));
|
|
||||||
targetX = (position.x - parent.x) * parentParent.worldScaleX;
|
|
||||||
targetY = (position.y - parent.y) * parentParent.worldScaleY;
|
|
||||||
} else {
|
} else {
|
||||||
targetX -= parent.x;
|
offset1 = 0;
|
||||||
targetY -= parent.y;
|
sign2 = 1;
|
||||||
}
|
}
|
||||||
if (child.parent == parent)
|
if (psy < 0) {
|
||||||
position.set(child.x, child.y);
|
psy = -psy;
|
||||||
else
|
sign2 = -sign2;
|
||||||
parent.worldToLocal(child.parent.localToWorld(position.set(child.x, child.y)));
|
|
||||||
float childX = position.x * parent.worldScaleX, childY = position.y * parent.worldScaleY;
|
|
||||||
float offset = (float)Math.atan2(childY, childX);
|
|
||||||
float len1 = (float)Math.sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX;
|
|
||||||
// Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
|
|
||||||
float cosDenom = 2 * len1 * len2;
|
|
||||||
if (cosDenom < 0.0001f) {
|
|
||||||
child.rotationIK = childRotation + ((float)Math.atan2(targetY, targetX) * radDeg - parentRotation - childRotation)
|
|
||||||
* alpha;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
float cos = clamp((targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom, -1, 1);
|
if (csx < 0) {
|
||||||
float childAngle = (float)Math.acos(cos) * bendDirection;
|
csx = -csx;
|
||||||
float adjacent = len1 + len2 * cos, opposite = len2 * sin(childAngle);
|
offset2 = 180;
|
||||||
float parentAngle = (float)Math.atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
|
} else
|
||||||
float rotation = (parentAngle - offset) * radDeg - parentRotation;
|
offset2 = 0;
|
||||||
if (rotation > 180)
|
Bone pp = parent.parent;
|
||||||
rotation -= 360;
|
float tx, ty, dx, dy;
|
||||||
else if (rotation < -180) //
|
if (pp == null) {
|
||||||
rotation += 360;
|
tx = targetX - px;
|
||||||
parent.rotationIK = parentRotation + rotation * alpha;
|
ty = targetY - py;
|
||||||
rotation = (childAngle + offset) * radDeg - childRotation;
|
dx = child.worldX - px;
|
||||||
if (rotation > 180)
|
dy = child.worldY - py;
|
||||||
rotation -= 360;
|
} else {
|
||||||
else if (rotation < -180) //
|
float a = pp.a, b = pp.b, c = pp.c, d = pp.d, invDet = 1 / (a * d - b * c);
|
||||||
rotation += 360;
|
float wx = pp.worldX, wy = pp.worldY, x = targetX - wx, y = targetY - wy;
|
||||||
child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha;
|
tx = (x * d - y * b) * invDet - px;
|
||||||
|
ty = (y * a - x * c) * invDet - py;
|
||||||
|
x = child.worldX - wx;
|
||||||
|
y = child.worldY - wy;
|
||||||
|
dx = (x * d - y * b) * invDet - px;
|
||||||
|
dy = (y * a - x * c) * invDet - py;
|
||||||
|
}
|
||||||
|
float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
||||||
|
outer:
|
||||||
|
if (Math.abs(psx - psy) <= 0.0001f) {
|
||||||
|
l2 *= psx;
|
||||||
|
float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
||||||
|
if (cos < -1)
|
||||||
|
cos = -1;
|
||||||
|
else if (cos > 1) cos = 1;
|
||||||
|
a2 = (float)Math.acos(cos) * bendDir;
|
||||||
|
float a = l1 + l2 * cos, o = l2 * sin(a2);
|
||||||
|
a1 = atan2(ty * a - tx * o, tx * a + ty * o);
|
||||||
|
} else {
|
||||||
|
cy = 0;
|
||||||
|
float a = psx * l2, b = psy * l2, ta = atan2(ty, tx);
|
||||||
|
float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
|
||||||
|
float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
|
||||||
|
float d = c1 * c1 - 4 * c2 * c0;
|
||||||
|
if (d >= 0) {
|
||||||
|
float q = (float)Math.sqrt(d);
|
||||||
|
if (c1 < 0) q = -q;
|
||||||
|
q = -(c1 + q) / 2;
|
||||||
|
float r0 = q / c2, r1 = c0 / q;
|
||||||
|
float r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
|
||||||
|
if (r * r <= dd) {
|
||||||
|
float y = (float)Math.sqrt(dd - r * r) * bendDir;
|
||||||
|
a1 = ta - atan2(y, r);
|
||||||
|
a2 = atan2(y / psy, (r - l1) / psx);
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float minAngle = 0, minDist = Float.MAX_VALUE, minX = 0, minY = 0;
|
||||||
|
float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
|
||||||
|
float x = l1 + a, dist = x * x;
|
||||||
|
if (dist > maxDist) {
|
||||||
|
maxAngle = 0;
|
||||||
|
maxDist = dist;
|
||||||
|
maxX = x;
|
||||||
|
}
|
||||||
|
x = l1 - a;
|
||||||
|
dist = x * x;
|
||||||
|
if (dist < minDist) {
|
||||||
|
minAngle = PI;
|
||||||
|
minDist = dist;
|
||||||
|
minX = x;
|
||||||
|
}
|
||||||
|
float angle = (float)Math.acos(-a * l1 / (aa - bb));
|
||||||
|
x = a * cos(angle) + l1;
|
||||||
|
float y = b * sin(angle);
|
||||||
|
dist = x * x + y * y;
|
||||||
|
if (dist < minDist) {
|
||||||
|
minAngle = angle;
|
||||||
|
minDist = dist;
|
||||||
|
minX = x;
|
||||||
|
minY = y;
|
||||||
|
}
|
||||||
|
if (dist > maxDist) {
|
||||||
|
maxAngle = angle;
|
||||||
|
maxDist = dist;
|
||||||
|
maxX = x;
|
||||||
|
maxY = y;
|
||||||
|
}
|
||||||
|
if (dd <= (minDist + maxDist) / 2) {
|
||||||
|
a1 = ta - atan2(minY * bendDir, minX);
|
||||||
|
a2 = minAngle * bendDir;
|
||||||
|
} else {
|
||||||
|
a1 = ta - atan2(maxY * bendDir, maxX);
|
||||||
|
a2 = maxAngle * bendDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float offset = atan2(cy, child.x) * sign2;
|
||||||
|
a1 = (a1 - offset) * radDeg + offset1;
|
||||||
|
a2 = (a2 + offset) * radDeg * sign2 + offset2;
|
||||||
|
if (a1 > 180)
|
||||||
|
a1 -= 360;
|
||||||
|
else if (a1 < -180) a1 += 360;
|
||||||
|
if (a2 > 180)
|
||||||
|
a2 -= 360;
|
||||||
|
else if (a2 < -180) a2 += 360;
|
||||||
|
float rotation = parent.rotation;
|
||||||
|
parent.updateWorldTransform(parent.x, parent.y, rotation + (a1 - rotation) * alpha, parent.scaleX, parent.scaleY);
|
||||||
|
rotation = child.rotation;
|
||||||
|
child.updateWorldTransform(child.x, cy, rotation + (a2 - rotation) * alpha, child.scaleX, child.scaleY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,8 @@ public class Skeleton {
|
|||||||
final Array<Slot> slots;
|
final Array<Slot> slots;
|
||||||
Array<Slot> drawOrder;
|
Array<Slot> drawOrder;
|
||||||
final Array<IkConstraint> ikConstraints;
|
final Array<IkConstraint> ikConstraints;
|
||||||
private final Array<Array<Bone>> boneCache = new Array();
|
final Array<TransformConstraint> transformConstraints;
|
||||||
|
private final Array<Updatable> updateCache = new Array();
|
||||||
Skin skin;
|
Skin skin;
|
||||||
final Color color;
|
final Color color;
|
||||||
float time;
|
float time;
|
||||||
@ -75,6 +76,10 @@ public class Skeleton {
|
|||||||
for (IkConstraintData ikConstraintData : data.ikConstraints)
|
for (IkConstraintData ikConstraintData : data.ikConstraints)
|
||||||
ikConstraints.add(new IkConstraint(ikConstraintData, this));
|
ikConstraints.add(new IkConstraint(ikConstraintData, this));
|
||||||
|
|
||||||
|
transformConstraints = new Array(data.transformConstraints.size);
|
||||||
|
for (TransformConstraintData transformConstraintData : data.transformConstraints)
|
||||||
|
transformConstraints.add(new TransformConstraint(transformConstraintData, this));
|
||||||
|
|
||||||
color = new Color(1, 1, 1, 1);
|
color = new Color(1, 1, 1, 1);
|
||||||
|
|
||||||
updateCache();
|
updateCache();
|
||||||
@ -102,13 +107,12 @@ public class Skeleton {
|
|||||||
drawOrder.add(slots.get(skeleton.slots.indexOf(slot, true)));
|
drawOrder.add(slots.get(skeleton.slots.indexOf(slot, true)));
|
||||||
|
|
||||||
ikConstraints = new Array(skeleton.ikConstraints.size);
|
ikConstraints = new Array(skeleton.ikConstraints.size);
|
||||||
for (IkConstraint ikConstraint : skeleton.ikConstraints) {
|
for (IkConstraint ikConstraint : skeleton.ikConstraints)
|
||||||
Bone target = bones.get(skeleton.bones.indexOf(ikConstraint.target, true));
|
ikConstraints.add(new IkConstraint(ikConstraint, this));
|
||||||
Array<Bone> ikBones = new Array(ikConstraint.bones.size);
|
|
||||||
for (Bone bone : ikConstraint.bones)
|
transformConstraints = new Array(skeleton.transformConstraints.size);
|
||||||
ikBones.add(bones.get(skeleton.bones.indexOf(bone, true)));
|
for (TransformConstraint transformConstraint : skeleton.transformConstraints)
|
||||||
ikConstraints.add(new IkConstraint(ikConstraint, ikBones, target));
|
transformConstraints.add(new TransformConstraint(transformConstraint, this));
|
||||||
}
|
|
||||||
|
|
||||||
skin = skeleton.skin;
|
skin = skeleton.skin;
|
||||||
color = new Color(skeleton.color);
|
color = new Color(skeleton.color);
|
||||||
@ -119,72 +123,49 @@ public class Skeleton {
|
|||||||
updateCache();
|
updateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or removed. */
|
/** Caches information about bones and constraints. Must be called if bones or constraints are added or removed. */
|
||||||
public void updateCache () {
|
public void updateCache () {
|
||||||
Array<Bone> bones = this.bones;
|
Array<Bone> bones = this.bones;
|
||||||
Array<Array<Bone>> boneCache = this.boneCache;
|
Array<Updatable> updateCache = this.updateCache;
|
||||||
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
||||||
|
Array<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||||
int ikConstraintsCount = ikConstraints.size;
|
int ikConstraintsCount = ikConstraints.size;
|
||||||
|
int transformConstraintsCount = transformConstraints.size;
|
||||||
int arrayCount = ikConstraintsCount + 1;
|
updateCache.clear();
|
||||||
while (boneCache.size < arrayCount)
|
|
||||||
boneCache.add(new Array());
|
|
||||||
for (int i = 0; i < arrayCount; i++)
|
|
||||||
boneCache.get(i).clear();
|
|
||||||
|
|
||||||
Array<Bone> nonIkBones = boneCache.first();
|
|
||||||
|
|
||||||
outer:
|
|
||||||
for (int i = 0, n = bones.size; i < n; i++) {
|
for (int i = 0, n = bones.size; i < n; i++) {
|
||||||
Bone bone = bones.get(i);
|
Bone bone = bones.get(i);
|
||||||
Bone current = bone;
|
updateCache.add(bone);
|
||||||
do {
|
for (int ii = 0; ii < transformConstraintsCount; ii++) {
|
||||||
for (int ii = 0; ii < ikConstraintsCount; ii++) {
|
TransformConstraint transformConstraint = transformConstraints.get(ii);
|
||||||
IkConstraint ikConstraint = ikConstraints.get(ii);
|
if (bone == transformConstraint.bone) {
|
||||||
Bone parent = ikConstraint.bones.first();
|
updateCache.add(transformConstraint);
|
||||||
Bone child = ikConstraint.bones.peek();
|
break;
|
||||||
while (true) {
|
|
||||||
if (current == child) {
|
|
||||||
boneCache.get(ii).add(bone);
|
|
||||||
boneCache.get(ii + 1).add(bone);
|
|
||||||
continue outer;
|
|
||||||
}
|
|
||||||
if (child == parent) break;
|
|
||||||
child = child.parent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
current = current.parent;
|
}
|
||||||
} while (current != null);
|
for (int ii = 0; ii < ikConstraintsCount; ii++) {
|
||||||
nonIkBones.add(bone);
|
IkConstraint ikConstraint = ikConstraints.get(ii);
|
||||||
|
if (bone == ikConstraint.bones.peek()) {
|
||||||
|
updateCache.add(ikConstraint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the world transform for each bone and applies IK constraints. */
|
/** Updates the world transform for each bone and applies constraints. */
|
||||||
public void updateWorldTransform () {
|
public void updateWorldTransform () {
|
||||||
Array<Bone> bones = this.bones;
|
Array<Updatable> updateCache = this.updateCache;
|
||||||
for (int i = 0, nn = bones.size; i < nn; i++) {
|
for (int i = 0, n = updateCache.size; i < n; i++)
|
||||||
Bone bone = bones.get(i);
|
updateCache.get(i).update();
|
||||||
bone.rotationIK = bone.rotation;
|
|
||||||
}
|
|
||||||
Array<Array<Bone>> boneCache = this.boneCache;
|
|
||||||
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
|
||||||
int i = 0, last = ikConstraints.size;
|
|
||||||
while (true) {
|
|
||||||
Array<Bone> updateBones = boneCache.get(i);
|
|
||||||
for (int ii = 0, nn = updateBones.size; ii < nn; ii++)
|
|
||||||
updateBones.get(ii).updateWorldTransform();
|
|
||||||
if (i == last) break;
|
|
||||||
ikConstraints.get(i).apply();
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the bones and slots to their setup pose values. */
|
/** Sets the bones, constraints, and slots to their setup pose values. */
|
||||||
public void setToSetupPose () {
|
public void setToSetupPose () {
|
||||||
setBonesToSetupPose();
|
setBonesToSetupPose();
|
||||||
setSlotsToSetupPose();
|
setSlotsToSetupPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the bones and constraints to their setup pose values. */
|
||||||
public void setBonesToSetupPose () {
|
public void setBonesToSetupPose () {
|
||||||
Array<Bone> bones = this.bones;
|
Array<Bone> bones = this.bones;
|
||||||
for (int i = 0, n = bones.size; i < n; i++)
|
for (int i = 0, n = bones.size; i < n; i++)
|
||||||
@ -192,9 +173,17 @@ public class Skeleton {
|
|||||||
|
|
||||||
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
||||||
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
||||||
IkConstraint ikConstraint = ikConstraints.get(i);
|
IkConstraint constraint = ikConstraints.get(i);
|
||||||
ikConstraint.bendDirection = ikConstraint.data.bendDirection;
|
constraint.bendDirection = constraint.data.bendDirection;
|
||||||
ikConstraint.mix = ikConstraint.data.mix;
|
constraint.mix = constraint.data.mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||||
|
for (int i = 0, n = transformConstraints.size; i < n; i++) {
|
||||||
|
TransformConstraint constraint = transformConstraints.get(i);
|
||||||
|
constraint.translateMix = constraint.data.translateMix;
|
||||||
|
constraint.x = constraint.data.x;
|
||||||
|
constraint.y = constraint.data.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,12 +339,27 @@ public class Skeleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return May be null. */
|
/** @return May be null. */
|
||||||
public IkConstraint findIkConstraint (String ikConstraintName) {
|
public IkConstraint findIkConstraint (String constraintName) {
|
||||||
if (ikConstraintName == null) throw new IllegalArgumentException("ikConstraintName cannot be null.");
|
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||||
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
Array<IkConstraint> ikConstraints = this.ikConstraints;
|
||||||
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
||||||
IkConstraint ikConstraint = ikConstraints.get(i);
|
IkConstraint ikConstraint = ikConstraints.get(i);
|
||||||
if (ikConstraint.data.name.equals(ikConstraintName)) return ikConstraint;
|
if (ikConstraint.data.name.equals(constraintName)) return ikConstraint;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<TransformConstraint> getTransformConstraints () {
|
||||||
|
return transformConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return May be null. */
|
||||||
|
public TransformConstraint findTransformConstraint (String constraintName) {
|
||||||
|
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||||
|
Array<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||||
|
for (int i = 0, n = transformConstraints.size; i < n; i++) {
|
||||||
|
TransformConstraint constraint = transformConstraints.get(i);
|
||||||
|
if (constraint.data.name.equals(constraintName)) return constraint;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -371,19 +375,13 @@ public class Skeleton {
|
|||||||
float[] vertices = null;
|
float[] vertices = null;
|
||||||
Attachment attachment = slot.attachment;
|
Attachment attachment = slot.attachment;
|
||||||
if (attachment instanceof RegionAttachment) {
|
if (attachment instanceof RegionAttachment) {
|
||||||
RegionAttachment region = (RegionAttachment)attachment;
|
vertices = ((RegionAttachment)attachment).updateWorldVertices(slot, false);
|
||||||
region.updateWorldVertices(slot, false);
|
|
||||||
vertices = region.getWorldVertices();
|
|
||||||
|
|
||||||
} else if (attachment instanceof MeshAttachment) {
|
} else if (attachment instanceof MeshAttachment) {
|
||||||
MeshAttachment mesh = (MeshAttachment)attachment;
|
vertices = ((MeshAttachment)attachment).updateWorldVertices(slot, true);
|
||||||
mesh.updateWorldVertices(slot, true);
|
|
||||||
vertices = mesh.getWorldVertices();
|
|
||||||
|
|
||||||
} else if (attachment instanceof SkinnedMeshAttachment) {
|
} else if (attachment instanceof SkinnedMeshAttachment) {
|
||||||
SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment;
|
vertices = ((SkinnedMeshAttachment)attachment).updateWorldVertices(slot, true);
|
||||||
mesh.updateWorldVertices(slot, true);
|
|
||||||
vertices = mesh.getWorldVertices();
|
|
||||||
}
|
}
|
||||||
if (vertices != null) {
|
if (vertices != null) {
|
||||||
for (int ii = 0, nn = vertices.length; ii < nn; ii += 5) {
|
for (int ii = 0, nn = vertices.length; ii < nn; ii += 5) {
|
||||||
|
|||||||
@ -47,8 +47,6 @@ import com.esotericsoftware.spine.Animation.CurveTimeline;
|
|||||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FlipXTimeline;
|
|
||||||
import com.esotericsoftware.spine.Animation.FlipYTimeline;
|
|
||||||
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||||
@ -69,8 +67,6 @@ public class SkeletonBinary {
|
|||||||
static public final int TIMELINE_TRANSLATE = 2;
|
static public final int TIMELINE_TRANSLATE = 2;
|
||||||
static public final int TIMELINE_ATTACHMENT = 3;
|
static public final int TIMELINE_ATTACHMENT = 3;
|
||||||
static public final int TIMELINE_COLOR = 4;
|
static public final int TIMELINE_COLOR = 4;
|
||||||
static public final int TIMELINE_FLIPX = 5;
|
|
||||||
static public final int TIMELINE_FLIPY = 6;
|
|
||||||
|
|
||||||
static public final int CURVE_LINEAR = 0;
|
static public final int CURVE_LINEAR = 0;
|
||||||
static public final int CURVE_STEPPED = 1;
|
static public final int CURVE_STEPPED = 1;
|
||||||
@ -135,10 +131,6 @@ public class SkeletonBinary {
|
|||||||
boneData.scaleY = input.readFloat();
|
boneData.scaleY = input.readFloat();
|
||||||
boneData.rotation = input.readFloat();
|
boneData.rotation = input.readFloat();
|
||||||
boneData.length = input.readFloat() * scale;
|
boneData.length = input.readFloat() * scale;
|
||||||
boneData.flipX = input.readBoolean();
|
|
||||||
boneData.flipY = input.readBoolean();
|
|
||||||
boneData.inheritScale = input.readBoolean();
|
|
||||||
boneData.inheritRotation = input.readBoolean();
|
|
||||||
if (nonessential) Color.rgba8888ToColor(boneData.color, input.readInt());
|
if (nonessential) Color.rgba8888ToColor(boneData.color, input.readInt());
|
||||||
skeletonData.bones.add(boneData);
|
skeletonData.bones.add(boneData);
|
||||||
}
|
}
|
||||||
@ -419,17 +411,6 @@ public class SkeletonBinary {
|
|||||||
duration = Math.max(duration, timeline.getFrames()[frameCount * 3 - 3]);
|
duration = Math.max(duration, timeline.getFrames()[frameCount * 3 - 3]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TIMELINE_FLIPX:
|
|
||||||
case TIMELINE_FLIPY: {
|
|
||||||
FlipXTimeline timeline = timelineType == TIMELINE_FLIPX ? new FlipXTimeline(frameCount) : new FlipYTimeline(
|
|
||||||
frameCount);
|
|
||||||
timeline.boneIndex = boneIndex;
|
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
|
|
||||||
timeline.setFrame(frameIndex, input.readFloat(), input.readBoolean());
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = Math.max(duration, timeline.getFrames()[frameCount * 2 - 2]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ public class SkeletonData {
|
|||||||
final Array<EventData> events = new Array();
|
final Array<EventData> events = new Array();
|
||||||
final Array<Animation> animations = new Array();
|
final Array<Animation> animations = new Array();
|
||||||
final Array<IkConstraintData> ikConstraints = new Array();
|
final Array<IkConstraintData> ikConstraints = new Array();
|
||||||
|
final Array<TransformConstraintData> transformConstraints = new Array();
|
||||||
float width, height;
|
float width, height;
|
||||||
String version, hash, imagesPath;
|
String version, hash, imagesPath;
|
||||||
|
|
||||||
@ -153,19 +154,36 @@ public class SkeletonData {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- IK
|
// --- IK constraints
|
||||||
|
|
||||||
public Array<IkConstraintData> getIkConstraints () {
|
public Array<IkConstraintData> getIkConstraints () {
|
||||||
return ikConstraints;
|
return ikConstraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return May be null. */
|
/** @return May be null. */
|
||||||
public IkConstraintData findIkConstraint (String ikConstraintName) {
|
public IkConstraintData findIkConstraint (String constraintName) {
|
||||||
if (ikConstraintName == null) throw new IllegalArgumentException("ikConstraintName cannot be null.");
|
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||||
Array<IkConstraintData> ikConstraints = this.ikConstraints;
|
Array<IkConstraintData> ikConstraints = this.ikConstraints;
|
||||||
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
for (int i = 0, n = ikConstraints.size; i < n; i++) {
|
||||||
IkConstraintData ikConstraint = ikConstraints.get(i);
|
IkConstraintData constraint = ikConstraints.get(i);
|
||||||
if (ikConstraint.name.equals(ikConstraintName)) return ikConstraint;
|
if (constraint.name.equals(constraintName)) return constraint;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Transform constraints
|
||||||
|
|
||||||
|
public Array<TransformConstraintData> getTransformConstraints () {
|
||||||
|
return transformConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return May be null. */
|
||||||
|
public TransformConstraintData findTransformConstraint (String constraintName) {
|
||||||
|
if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null.");
|
||||||
|
Array<TransformConstraintData> transformConstraints = this.transformConstraints;
|
||||||
|
for (int i = 0, n = transformConstraints.size; i < n; i++) {
|
||||||
|
TransformConstraintData constraint = transformConstraints.get(i);
|
||||||
|
if (constraint.name.equals(constraintName)) return constraint;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,8 +46,6 @@ import com.esotericsoftware.spine.Animation.CurveTimeline;
|
|||||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FlipXTimeline;
|
|
||||||
import com.esotericsoftware.spine.Animation.FlipYTimeline;
|
|
||||||
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||||
@ -118,10 +116,6 @@ public class SkeletonJson {
|
|||||||
boneData.rotation = boneMap.getFloat("rotation", 0);
|
boneData.rotation = boneMap.getFloat("rotation", 0);
|
||||||
boneData.scaleX = boneMap.getFloat("scaleX", 1);
|
boneData.scaleX = boneMap.getFloat("scaleX", 1);
|
||||||
boneData.scaleY = boneMap.getFloat("scaleY", 1);
|
boneData.scaleY = boneMap.getFloat("scaleY", 1);
|
||||||
boneData.flipX = boneMap.getBoolean("flipX", false);
|
|
||||||
boneData.flipY = boneMap.getBoolean("flipY", false);
|
|
||||||
boneData.inheritScale = boneMap.getBoolean("inheritScale", true);
|
|
||||||
boneData.inheritRotation = boneMap.getBoolean("inheritRotation", true);
|
|
||||||
|
|
||||||
String color = boneMap.getString("color", null);
|
String color = boneMap.getString("color", null);
|
||||||
if (color != null) boneData.getColor().set(Color.valueOf(color));
|
if (color != null) boneData.getColor().set(Color.valueOf(color));
|
||||||
@ -389,20 +383,6 @@ public class SkeletonJson {
|
|||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() * 3 - 3]);
|
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() * 3 - 3]);
|
||||||
|
|
||||||
} else if (timelineName.equals("flipX") || timelineName.equals("flipY")) {
|
|
||||||
boolean x = timelineName.equals("flipX");
|
|
||||||
FlipXTimeline timeline = x ? new FlipXTimeline(timelineMap.size) : new FlipYTimeline(timelineMap.size);
|
|
||||||
timeline.boneIndex = boneIndex;
|
|
||||||
|
|
||||||
String field = x ? "x" : "y";
|
|
||||||
int frameIndex = 0;
|
|
||||||
for (JsonValue valueMap = timelineMap.child; valueMap != null; valueMap = valueMap.next) {
|
|
||||||
timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getBoolean(field, false));
|
|
||||||
frameIndex++;
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() * 2 - 2]);
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
throw new RuntimeException("Invalid timeline type for a bone: " + timelineName + " (" + boneMap.name + ")");
|
throw new RuntimeException("Invalid timeline type for a bone: " + timelineName + " (" + boneMap.name + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,108 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes Software License
|
||||||
|
* Version 2.3
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2015, Esoteric Software
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||||
|
* non-transferable license to use, install, execute and perform the Spine
|
||||||
|
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||||
|
* or internal use. Without the written permission of Esoteric Software (see
|
||||||
|
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||||
|
* translate, adapt or otherwise create derivative works, improvements of the
|
||||||
|
* Software or develop new applications using the Software or (b) remove,
|
||||||
|
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||||
|
* or other intellectual property or proprietary rights notices on or in the
|
||||||
|
* Software, including any copy thereof. Redistributions in binary or source
|
||||||
|
* form must include this license and terms.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.esotericsoftware.spine.attachments.Attachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||||
|
|
||||||
|
public class SkeletonMeshRenderer extends SkeletonRenderer<PolygonSpriteBatch> {
|
||||||
|
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
public void draw (PolygonSpriteBatch batch, Skeleton skeleton) {
|
||||||
|
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||||
|
BlendMode blendMode = null;
|
||||||
|
|
||||||
|
float[] vertices = null;
|
||||||
|
short[] triangles = null;
|
||||||
|
Array<Slot> drawOrder = skeleton.drawOrder;
|
||||||
|
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
||||||
|
Slot slot = drawOrder.get(i);
|
||||||
|
Attachment attachment = slot.attachment;
|
||||||
|
Texture texture = null;
|
||||||
|
if (attachment instanceof RegionAttachment) {
|
||||||
|
RegionAttachment region = (RegionAttachment)attachment;
|
||||||
|
vertices = region.updateWorldVertices(slot, premultipliedAlpha);
|
||||||
|
triangles = quadTriangles;
|
||||||
|
texture = region.getRegion().getTexture();
|
||||||
|
|
||||||
|
} else if (attachment instanceof MeshAttachment) {
|
||||||
|
MeshAttachment mesh = (MeshAttachment)attachment;
|
||||||
|
vertices = mesh.updateWorldVertices(slot, premultipliedAlpha);
|
||||||
|
triangles = mesh.getTriangles();
|
||||||
|
texture = mesh.getRegion().getTexture();
|
||||||
|
|
||||||
|
} else if (attachment instanceof SkinnedMeshAttachment) {
|
||||||
|
SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment;
|
||||||
|
vertices = mesh.updateWorldVertices(slot, premultipliedAlpha);
|
||||||
|
triangles = mesh.getTriangles();
|
||||||
|
texture = mesh.getRegion().getTexture();
|
||||||
|
|
||||||
|
} else if (attachment instanceof SkeletonAttachment) {
|
||||||
|
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
|
||||||
|
if (attachmentSkeleton == null) continue;
|
||||||
|
Bone bone = slot.getBone();
|
||||||
|
Bone rootBone = attachmentSkeleton.getRootBone();
|
||||||
|
float oldScaleX = rootBone.getScaleX();
|
||||||
|
float oldScaleY = rootBone.getScaleY();
|
||||||
|
float oldRotation = rootBone.getRotation();
|
||||||
|
attachmentSkeleton.setPosition(skeleton.getX() + bone.getWorldX(), skeleton.getY() + bone.getWorldY());
|
||||||
|
// rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
|
||||||
|
// rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
|
||||||
|
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
|
||||||
|
attachmentSkeleton.updateWorldTransform();
|
||||||
|
|
||||||
|
draw(batch, attachmentSkeleton);
|
||||||
|
|
||||||
|
attachmentSkeleton.setPosition(0, 0);
|
||||||
|
rootBone.setScaleX(oldScaleX);
|
||||||
|
rootBone.setScaleY(oldScaleY);
|
||||||
|
rootBone.setRotation(oldRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != null) {
|
||||||
|
BlendMode slotBlendMode = slot.data.getBlendMode();
|
||||||
|
if (slotBlendMode != blendMode) {
|
||||||
|
blendMode = slotBlendMode;
|
||||||
|
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
|
||||||
|
}
|
||||||
|
batch.draw(texture, vertices, 0, vertices.length, triangles, 0, triangles.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,9 +31,7 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine;
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.esotericsoftware.spine.attachments.Attachment;
|
import com.esotericsoftware.spine.attachments.Attachment;
|
||||||
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||||
@ -41,78 +39,14 @@ import com.esotericsoftware.spine.attachments.RegionAttachment;
|
|||||||
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||||
|
|
||||||
public class SkeletonRenderer {
|
public class SkeletonRenderer<T extends Batch> {
|
||||||
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
boolean premultipliedAlpha;
|
||||||
|
|
||||||
private boolean premultipliedAlpha;
|
public SkeletonRenderer () {
|
||||||
|
super();
|
||||||
@SuppressWarnings("null")
|
|
||||||
public void draw (PolygonSpriteBatch batch, Skeleton skeleton) {
|
|
||||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
|
||||||
BlendMode blendMode = null;
|
|
||||||
|
|
||||||
float[] vertices = null;
|
|
||||||
short[] triangles = null;
|
|
||||||
Array<Slot> drawOrder = skeleton.drawOrder;
|
|
||||||
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
|
||||||
Slot slot = drawOrder.get(i);
|
|
||||||
Attachment attachment = slot.attachment;
|
|
||||||
Texture texture = null;
|
|
||||||
if (attachment instanceof RegionAttachment) {
|
|
||||||
RegionAttachment region = (RegionAttachment)attachment;
|
|
||||||
region.updateWorldVertices(slot, premultipliedAlpha);
|
|
||||||
vertices = region.getWorldVertices();
|
|
||||||
triangles = quadTriangles;
|
|
||||||
texture = region.getRegion().getTexture();
|
|
||||||
|
|
||||||
} else if (attachment instanceof MeshAttachment) {
|
|
||||||
MeshAttachment mesh = (MeshAttachment)attachment;
|
|
||||||
mesh.updateWorldVertices(slot, premultipliedAlpha);
|
|
||||||
vertices = mesh.getWorldVertices();
|
|
||||||
triangles = mesh.getTriangles();
|
|
||||||
texture = mesh.getRegion().getTexture();
|
|
||||||
|
|
||||||
} else if (attachment instanceof SkinnedMeshAttachment) {
|
|
||||||
SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment;
|
|
||||||
mesh.updateWorldVertices(slot, premultipliedAlpha);
|
|
||||||
vertices = mesh.getWorldVertices();
|
|
||||||
triangles = mesh.getTriangles();
|
|
||||||
texture = mesh.getRegion().getTexture();
|
|
||||||
|
|
||||||
} else if (attachment instanceof SkeletonAttachment) {
|
|
||||||
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
|
|
||||||
if (attachmentSkeleton == null) continue;
|
|
||||||
Bone bone = slot.getBone();
|
|
||||||
Bone rootBone = attachmentSkeleton.getRootBone();
|
|
||||||
float oldScaleX = rootBone.getScaleX();
|
|
||||||
float oldScaleY = rootBone.getScaleY();
|
|
||||||
float oldRotation = rootBone.getRotation();
|
|
||||||
attachmentSkeleton.setPosition(skeleton.getX() + bone.getWorldX(), skeleton.getY() + bone.getWorldY());
|
|
||||||
rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
|
|
||||||
rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
|
|
||||||
rootBone.setRotation(oldRotation + bone.getWorldRotation());
|
|
||||||
attachmentSkeleton.updateWorldTransform();
|
|
||||||
|
|
||||||
draw(batch, attachmentSkeleton);
|
|
||||||
|
|
||||||
attachmentSkeleton.setPosition(0, 0);
|
|
||||||
rootBone.setScaleX(oldScaleX);
|
|
||||||
rootBone.setScaleY(oldScaleY);
|
|
||||||
rootBone.setRotation(oldRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture != null) {
|
|
||||||
BlendMode slotBlendMode = slot.data.getBlendMode();
|
|
||||||
if (slotBlendMode != blendMode) {
|
|
||||||
blendMode = slotBlendMode;
|
|
||||||
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
|
|
||||||
}
|
|
||||||
batch.draw(texture, vertices, 0, vertices.length, triangles, 0, triangles.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw (Batch batch, Skeleton skeleton) {
|
public void draw (T batch, Skeleton skeleton) {
|
||||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||||
BlendMode blendMode = null;
|
BlendMode blendMode = null;
|
||||||
|
|
||||||
@ -122,8 +56,7 @@ public class SkeletonRenderer {
|
|||||||
Attachment attachment = slot.attachment;
|
Attachment attachment = slot.attachment;
|
||||||
if (attachment instanceof RegionAttachment) {
|
if (attachment instanceof RegionAttachment) {
|
||||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||||
regionAttachment.updateWorldVertices(slot, premultipliedAlpha);
|
float[] vertices = regionAttachment.updateWorldVertices(slot, premultipliedAlpha);
|
||||||
float[] vertices = regionAttachment.getWorldVertices();
|
|
||||||
BlendMode slotBlendMode = slot.data.getBlendMode();
|
BlendMode slotBlendMode = slot.data.getBlendMode();
|
||||||
if (slotBlendMode != blendMode) {
|
if (slotBlendMode != blendMode) {
|
||||||
blendMode = slotBlendMode;
|
blendMode = slotBlendMode;
|
||||||
@ -132,7 +65,7 @@ public class SkeletonRenderer {
|
|||||||
batch.draw(regionAttachment.getRegion().getTexture(), vertices, 0, 20);
|
batch.draw(regionAttachment.getRegion().getTexture(), vertices, 0, 20);
|
||||||
|
|
||||||
} else if (attachment instanceof MeshAttachment || attachment instanceof SkinnedMeshAttachment) {
|
} else if (attachment instanceof MeshAttachment || attachment instanceof SkinnedMeshAttachment) {
|
||||||
throw new RuntimeException("PolygonSpriteBatch is required to render meshes.");
|
throw new RuntimeException("SkeletonMeshRenderer is required to render meshes.");
|
||||||
|
|
||||||
} else if (attachment instanceof SkeletonAttachment) {
|
} else if (attachment instanceof SkeletonAttachment) {
|
||||||
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
|
Skeleton attachmentSkeleton = ((SkeletonAttachment)attachment).getSkeleton();
|
||||||
@ -143,9 +76,9 @@ public class SkeletonRenderer {
|
|||||||
float oldScaleY = rootBone.getScaleY();
|
float oldScaleY = rootBone.getScaleY();
|
||||||
float oldRotation = rootBone.getRotation();
|
float oldRotation = rootBone.getRotation();
|
||||||
attachmentSkeleton.setPosition(skeleton.getX() + bone.getWorldX(), skeleton.getY() + bone.getWorldY());
|
attachmentSkeleton.setPosition(skeleton.getX() + bone.getWorldX(), skeleton.getY() + bone.getWorldY());
|
||||||
rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
|
// rootBone.setScaleX(1 + bone.getWorldScaleX() - oldScaleX);
|
||||||
rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
|
// rootBone.setScaleY(1 + bone.getWorldScaleY() - oldScaleY);
|
||||||
rootBone.setRotation(oldRotation + bone.getWorldRotation());
|
rootBone.setRotation(oldRotation + bone.getWorldRotationX());
|
||||||
attachmentSkeleton.updateWorldTransform();
|
attachmentSkeleton.updateWorldTransform();
|
||||||
|
|
||||||
draw(batch, attachmentSkeleton);
|
draw(batch, attachmentSkeleton);
|
||||||
|
|||||||
@ -87,8 +87,8 @@ public class SkeletonRendererDebug {
|
|||||||
for (int i = 0, n = bones.size; i < n; i++) {
|
for (int i = 0, n = bones.size; i < n; i++) {
|
||||||
Bone bone = bones.get(i);
|
Bone bone = bones.get(i);
|
||||||
if (bone.parent == null) continue;
|
if (bone.parent == null) continue;
|
||||||
float x = skeletonX + bone.data.length * bone.m00 + bone.worldX;
|
float x = skeletonX + bone.data.length * bone.a + bone.worldX;
|
||||||
float y = skeletonY + bone.data.length * bone.m10 + bone.worldY;
|
float y = skeletonY + bone.data.length * bone.c + bone.worldY;
|
||||||
shapes.rectLine(skeletonX + bone.worldX, skeletonY + bone.worldY, x, y, boneWidth * scale);
|
shapes.rectLine(skeletonX + bone.worldX, skeletonY + bone.worldY, x, y, boneWidth * scale);
|
||||||
}
|
}
|
||||||
shapes.end();
|
shapes.end();
|
||||||
@ -105,8 +105,7 @@ public class SkeletonRendererDebug {
|
|||||||
Attachment attachment = slot.attachment;
|
Attachment attachment = slot.attachment;
|
||||||
if (attachment instanceof RegionAttachment) {
|
if (attachment instanceof RegionAttachment) {
|
||||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||||
regionAttachment.updateWorldVertices(slot, false);
|
float[] vertices = regionAttachment.updateWorldVertices(slot, false);
|
||||||
float[] vertices = regionAttachment.getWorldVertices();
|
|
||||||
shapes.line(vertices[X1], vertices[Y1], vertices[X2], vertices[Y2]);
|
shapes.line(vertices[X1], vertices[Y1], vertices[X2], vertices[Y2]);
|
||||||
shapes.line(vertices[X2], vertices[Y2], vertices[X3], vertices[Y3]);
|
shapes.line(vertices[X2], vertices[Y2], vertices[X3], vertices[Y3]);
|
||||||
shapes.line(vertices[X3], vertices[Y3], vertices[X4], vertices[Y4]);
|
shapes.line(vertices[X3], vertices[Y3], vertices[X4], vertices[Y4]);
|
||||||
|
|||||||
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
|
public class TransformConstraint implements Updatable {
|
||||||
|
final TransformConstraintData data;
|
||||||
|
Bone bone, target;
|
||||||
|
float translateMix, x, y;
|
||||||
|
final Vector2 temp = new Vector2();
|
||||||
|
|
||||||
|
public TransformConstraint (TransformConstraintData data, Skeleton skeleton) {
|
||||||
|
this.data = data;
|
||||||
|
translateMix = data.translateMix;
|
||||||
|
|
||||||
|
if (skeleton != null) {
|
||||||
|
bone = skeleton.findBone(data.bone.name);
|
||||||
|
target = skeleton.findBone(data.target.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Copy constructor. */
|
||||||
|
public TransformConstraint (TransformConstraint constraint, Skeleton skeleton) {
|
||||||
|
data = constraint.data;
|
||||||
|
translateMix = data.translateMix;
|
||||||
|
bone = skeleton.bones.get(constraint.bone.skeleton.bones.indexOf(constraint.target, true));
|
||||||
|
target = skeleton.bones.get(constraint.target.skeleton.bones.indexOf(constraint.target, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply () {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update () {
|
||||||
|
float translateMix = this.translateMix;
|
||||||
|
if (translateMix > 0) {
|
||||||
|
Bone bone = this.bone;
|
||||||
|
Vector2 temp = this.temp;
|
||||||
|
target.localToWorld(temp.set(x, y));
|
||||||
|
bone.worldX += (temp.x - bone.worldX) * translateMix;
|
||||||
|
bone.worldY += (temp.y - bone.worldY) * translateMix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bone getBone () {
|
||||||
|
return bone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBone (Bone bone) {
|
||||||
|
this.bone = bone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bone getTarget () {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget (Bone target) {
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTranslateMix () {
|
||||||
|
return translateMix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTranslateMix (float translateMix) {
|
||||||
|
this.translateMix = translateMix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransformConstraintData getData () {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString () {
|
||||||
|
return data.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
public class TransformConstraintData {
|
||||||
|
final String name;
|
||||||
|
BoneData bone, target;
|
||||||
|
float translateMix;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
public TransformConstraintData (String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoneData getBone () {
|
||||||
|
return bone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBone (BoneData bone) {
|
||||||
|
this.bone = bone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoneData getTarget () {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget (BoneData target) {
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTranslateMix () {
|
||||||
|
return translateMix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTranslateMix (float translateMix) {
|
||||||
|
this.translateMix = translateMix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX () {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX (float x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY () {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY (float y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
|
public interface Updatable {
|
||||||
|
public void update ();
|
||||||
|
}
|
||||||
@ -44,10 +44,10 @@ public class BoundingBoxAttachment extends Attachment {
|
|||||||
public void computeWorldVertices (Bone bone, float[] worldVertices) {
|
public void computeWorldVertices (Bone bone, float[] worldVertices) {
|
||||||
Skeleton skeleton = bone.getSkeleton();
|
Skeleton skeleton = bone.getSkeleton();
|
||||||
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
||||||
float m00 = bone.getM00();
|
float m00 = bone.getA();
|
||||||
float m01 = bone.getM01();
|
float m01 = bone.getB();
|
||||||
float m10 = bone.getM10();
|
float m10 = bone.getC();
|
||||||
float m11 = bone.getM11();
|
float m11 = bone.getD();
|
||||||
float[] vertices = this.vertices;
|
float[] vertices = this.vertices;
|
||||||
for (int i = 0, n = vertices.length; i < n; i += 2) {
|
for (int i = 0, n = vertices.length; i < n; i += 2) {
|
||||||
float px = vertices[i];
|
float px = vertices[i];
|
||||||
|
|||||||
@ -98,7 +98,8 @@ public class MeshAttachment extends Attachment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
/** @return The updated world vertices. */
|
||||||
|
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||||
Skeleton skeleton = slot.getSkeleton();
|
Skeleton skeleton = slot.getSkeleton();
|
||||||
Color skeletonColor = skeleton.getColor();
|
Color skeletonColor = skeleton.getColor();
|
||||||
Color slotColor = slot.getColor();
|
Color slotColor = slot.getColor();
|
||||||
@ -117,7 +118,7 @@ public class MeshAttachment extends Attachment {
|
|||||||
if (slotVertices.size == vertices.length) vertices = slotVertices.items;
|
if (slotVertices.size == vertices.length) vertices = slotVertices.items;
|
||||||
Bone bone = slot.getBone();
|
Bone bone = slot.getBone();
|
||||||
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
||||||
float m00 = bone.getM00(), m01 = bone.getM01(), m10 = bone.getM10(), m11 = bone.getM11();
|
float m00 = bone.getA(), m01 = bone.getB(), m10 = bone.getC(), m11 = bone.getD();
|
||||||
for (int v = 0, w = 0, n = worldVertices.length; w < n; v += 2, w += 5) {
|
for (int v = 0, w = 0, n = worldVertices.length; w < n; v += 2, w += 5) {
|
||||||
float vx = vertices[v];
|
float vx = vertices[v];
|
||||||
float vy = vertices[v + 1];
|
float vy = vertices[v + 1];
|
||||||
@ -125,6 +126,7 @@ public class MeshAttachment extends Attachment {
|
|||||||
worldVertices[w + 1] = vx * m10 + vy * m11 + y;
|
worldVertices[w + 1] = vx * m10 + vy * m11 + y;
|
||||||
worldVertices[w + 2] = color;
|
worldVertices[w + 2] = color;
|
||||||
}
|
}
|
||||||
|
return worldVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[] getWorldVertices () {
|
public float[] getWorldVertices () {
|
||||||
|
|||||||
@ -146,7 +146,8 @@ public class RegionAttachment extends Attachment {
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
/** @return The updated world vertices. */
|
||||||
|
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||||
Skeleton skeleton = slot.getSkeleton();
|
Skeleton skeleton = slot.getSkeleton();
|
||||||
Color skeletonColor = skeleton.getColor();
|
Color skeletonColor = skeleton.getColor();
|
||||||
Color slotColor = slot.getColor();
|
Color slotColor = slot.getColor();
|
||||||
@ -163,7 +164,7 @@ public class RegionAttachment extends Attachment {
|
|||||||
float[] offset = this.offset;
|
float[] offset = this.offset;
|
||||||
Bone bone = slot.getBone();
|
Bone bone = slot.getBone();
|
||||||
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
float x = skeleton.getX() + bone.getWorldX(), y = skeleton.getY() + bone.getWorldY();
|
||||||
float m00 = bone.getM00(), m01 = bone.getM01(), m10 = bone.getM10(), m11 = bone.getM11();
|
float m00 = bone.getA(), m01 = bone.getB(), m10 = bone.getC(), m11 = bone.getD();
|
||||||
float offsetX, offsetY;
|
float offsetX, offsetY;
|
||||||
|
|
||||||
offsetX = offset[BRX];
|
offsetX = offset[BRX];
|
||||||
@ -189,6 +190,7 @@ public class RegionAttachment extends Attachment {
|
|||||||
vertices[X4] = offsetX * m00 + offsetY * m01 + x; // ur
|
vertices[X4] = offsetX * m00 + offsetY * m01 + x; // ur
|
||||||
vertices[Y4] = offsetX * m10 + offsetY * m11 + y;
|
vertices[Y4] = offsetX * m10 + offsetY * m11 + y;
|
||||||
vertices[C4] = color;
|
vertices[C4] = color;
|
||||||
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[] getWorldVertices () {
|
public float[] getWorldVertices () {
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class RegionSequenceAttachment extends RegionAttachment {
|
|||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||||
if (regions == null) throw new IllegalStateException("Regions have not been set: " + this);
|
if (regions == null) throw new IllegalStateException("Regions have not been set: " + this);
|
||||||
|
|
||||||
int frameIndex = (int)(slot.getAttachmentTime() / frameTime);
|
int frameIndex = (int)(slot.getAttachmentTime() / frameTime);
|
||||||
@ -74,7 +74,7 @@ public class RegionSequenceAttachment extends RegionAttachment {
|
|||||||
}
|
}
|
||||||
setRegion(regions[frameIndex]);
|
setRegion(regions[frameIndex]);
|
||||||
|
|
||||||
super.updateWorldVertices(slot, premultipliedAlpha);
|
return super.updateWorldVertices(slot, premultipliedAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureRegion[] getRegions () {
|
public TextureRegion[] getRegions () {
|
||||||
|
|||||||
@ -99,7 +99,8 @@ public class SkinnedMeshAttachment extends Attachment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
/** @return The updated world vertices. */
|
||||||
|
public float[] updateWorldVertices (Slot slot, boolean premultipliedAlpha) {
|
||||||
Skeleton skeleton = slot.getSkeleton();
|
Skeleton skeleton = slot.getSkeleton();
|
||||||
Color skeletonColor = skeleton.getColor();
|
Color skeletonColor = skeleton.getColor();
|
||||||
Color meshColor = slot.getColor();
|
Color meshColor = slot.getColor();
|
||||||
@ -126,8 +127,8 @@ public class SkinnedMeshAttachment extends Attachment {
|
|||||||
for (; v < nn; v++, b += 3) {
|
for (; v < nn; v++, b += 3) {
|
||||||
Bone bone = (Bone)skeletonBones[bones[v]];
|
Bone bone = (Bone)skeletonBones[bones[v]];
|
||||||
float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2];
|
float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2];
|
||||||
wx += (vx * bone.getM00() + vy * bone.getM01() + bone.getWorldX()) * weight;
|
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||||
wy += (vx * bone.getM10() + vy * bone.getM11() + bone.getWorldY()) * weight;
|
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||||
}
|
}
|
||||||
worldVertices[w] = wx + x;
|
worldVertices[w] = wx + x;
|
||||||
worldVertices[w + 1] = wy + y;
|
worldVertices[w + 1] = wy + y;
|
||||||
@ -141,14 +142,15 @@ public class SkinnedMeshAttachment extends Attachment {
|
|||||||
for (; v < nn; v++, b += 3, f += 2) {
|
for (; v < nn; v++, b += 3, f += 2) {
|
||||||
Bone bone = (Bone)skeletonBones[bones[v]];
|
Bone bone = (Bone)skeletonBones[bones[v]];
|
||||||
float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2];
|
float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2];
|
||||||
wx += (vx * bone.getM00() + vy * bone.getM01() + bone.getWorldX()) * weight;
|
wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight;
|
||||||
wy += (vx * bone.getM10() + vy * bone.getM11() + bone.getWorldY()) * weight;
|
wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight;
|
||||||
}
|
}
|
||||||
worldVertices[w] = wx + x;
|
worldVertices[w] = wx + x;
|
||||||
worldVertices[w + 1] = wy + y;
|
worldVertices[w + 1] = wy + y;
|
||||||
worldVertices[w + 2] = color;
|
worldVertices[w + 2] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return worldVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[] getWorldVertices () {
|
public float[] getWorldVertices () {
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine.utils;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||||
|
import com.esotericsoftware.spine.AnimationState;
|
||||||
|
import com.esotericsoftware.spine.Skeleton;
|
||||||
|
import com.esotericsoftware.spine.SkeletonRenderer;
|
||||||
|
|
||||||
|
/** A scene2d actor that draws a skeleton. */
|
||||||
|
public class SkeletonActor extends Actor {
|
||||||
|
private SkeletonRenderer renderer;
|
||||||
|
private Skeleton skeleton;
|
||||||
|
AnimationState state;
|
||||||
|
|
||||||
|
/** Creates an uninitialized SkeletonActor. The renderer, skeleton, and animation state must be set before use. */
|
||||||
|
public SkeletonActor () {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonActor (SkeletonRenderer renderer, Skeleton skeleton, AnimationState state) {
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.skeleton = skeleton;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void act (float delta) {
|
||||||
|
state.update(delta);
|
||||||
|
state.apply(skeleton);
|
||||||
|
skeleton.updateWorldTransform();
|
||||||
|
super.act(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw (Batch batch, float parentAlpha) {
|
||||||
|
Color color = skeleton.getColor();
|
||||||
|
float oldAlpha = color.a;
|
||||||
|
skeleton.getColor().a *= parentAlpha;
|
||||||
|
|
||||||
|
skeleton.setPosition(getX(), getY());
|
||||||
|
renderer.draw(batch, skeleton);
|
||||||
|
|
||||||
|
color.a = oldAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonRenderer getRenderer () {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRenderer (SkeletonRenderer renderer) {
|
||||||
|
this.renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Skeleton getSkeleton () {
|
||||||
|
return skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkeleton (Skeleton skeleton) {
|
||||||
|
this.skeleton = skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimationState getAnimationState () {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnimationState (AnimationState state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine.utils;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Pool;
|
||||||
|
import com.esotericsoftware.spine.AnimationState;
|
||||||
|
import com.esotericsoftware.spine.AnimationState.TrackEntry;
|
||||||
|
import com.esotericsoftware.spine.AnimationStateData;
|
||||||
|
import com.esotericsoftware.spine.Skeleton;
|
||||||
|
import com.esotericsoftware.spine.SkeletonData;
|
||||||
|
import com.esotericsoftware.spine.SkeletonRenderer;
|
||||||
|
import com.esotericsoftware.spine.Skin;
|
||||||
|
|
||||||
|
public class SkeletonActorPool extends Pool<SkeletonActor> {
|
||||||
|
private SkeletonRenderer renderer;
|
||||||
|
SkeletonData skeletonData;
|
||||||
|
AnimationStateData stateData;
|
||||||
|
private final Pool<Skeleton> skeletonPool;
|
||||||
|
private final Pool<AnimationState> statePool;
|
||||||
|
private final Array<SkeletonActor> obtained;
|
||||||
|
|
||||||
|
public SkeletonActorPool (SkeletonRenderer renderer, SkeletonData skeletonData, AnimationStateData stateData) {
|
||||||
|
this(renderer, skeletonData, stateData, 16, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonActorPool (SkeletonRenderer renderer, SkeletonData skeletonData, AnimationStateData stateData,
|
||||||
|
int initialCapacity, int max) {
|
||||||
|
super(initialCapacity, max);
|
||||||
|
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.skeletonData = skeletonData;
|
||||||
|
this.stateData = stateData;
|
||||||
|
|
||||||
|
obtained = new Array(false, initialCapacity);
|
||||||
|
|
||||||
|
skeletonPool = new Pool<Skeleton>(initialCapacity, max) {
|
||||||
|
protected Skeleton newObject () {
|
||||||
|
return new Skeleton(SkeletonActorPool.this.skeletonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset (Skeleton skeleton) {
|
||||||
|
skeleton.setColor(Color.WHITE);
|
||||||
|
skeleton.setFlip(false, false);
|
||||||
|
skeleton.setSkin((Skin)null);
|
||||||
|
skeleton.setSkin(SkeletonActorPool.this.skeletonData.getDefaultSkin());
|
||||||
|
skeleton.setToSetupPose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
statePool = new Pool<AnimationState>(initialCapacity, max) {
|
||||||
|
protected AnimationState newObject () {
|
||||||
|
return new AnimationState(SkeletonActorPool.this.stateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset (AnimationState state) {
|
||||||
|
state.clearTracks();
|
||||||
|
state.clearListeners();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Each obtained skeleton actor that is no longer playing an animation is removed from the stage and returned to the pool. */
|
||||||
|
public void freeComplete () {
|
||||||
|
Array<SkeletonActor> obtained = this.obtained;
|
||||||
|
outer:
|
||||||
|
for (int i = obtained.size - 1; i >= 0; i--) {
|
||||||
|
SkeletonActor actor = obtained.get(i);
|
||||||
|
Array<TrackEntry> tracks = actor.state.getTracks();
|
||||||
|
for (int ii = 0, nn = tracks.size; ii < nn; ii++)
|
||||||
|
if (tracks.get(ii) != null) continue outer;
|
||||||
|
free(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SkeletonActor newObject () {
|
||||||
|
SkeletonActor actor = new SkeletonActor();
|
||||||
|
actor.setRenderer(renderer);
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This pool keeps a reference to the obtained instance, so it should be returned to the pool via {@link #free(SkeletonActor)}
|
||||||
|
* , {@link #freeAll(Array)}, or {@link #freeComplete()} to avoid leaking memory. */
|
||||||
|
public SkeletonActor obtain () {
|
||||||
|
SkeletonActor actor = super.obtain();
|
||||||
|
actor.setSkeleton(skeletonPool.obtain());
|
||||||
|
actor.setAnimationState(statePool.obtain());
|
||||||
|
obtained.add(actor);
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset (SkeletonActor actor) {
|
||||||
|
actor.remove();
|
||||||
|
obtained.removeValue(actor, true);
|
||||||
|
skeletonPool.free(actor.getSkeleton());
|
||||||
|
statePool.free(actor.getAnimationState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<SkeletonActor> getObtained () {
|
||||||
|
return obtained;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
package com.esotericsoftware.spine.utils;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Pool;
|
||||||
|
import com.esotericsoftware.spine.Skeleton;
|
||||||
|
import com.esotericsoftware.spine.SkeletonData;
|
||||||
|
|
||||||
|
public class SkeletonPool extends Pool<Skeleton> {
|
||||||
|
private SkeletonData skeletonData;
|
||||||
|
|
||||||
|
public SkeletonPool (SkeletonData skeletonData) {
|
||||||
|
this.skeletonData = skeletonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonPool (SkeletonData skeletonData, int initialCapacity) {
|
||||||
|
super(initialCapacity);
|
||||||
|
this.skeletonData = skeletonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonPool (SkeletonData skeletonData, int initialCapacity, int max) {
|
||||||
|
super(initialCapacity, max);
|
||||||
|
this.skeletonData = skeletonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Skeleton newObject () {
|
||||||
|
return new Skeleton(skeletonData);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,206 @@
|
|||||||
|
info face="Calibri" size=-12 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=0 aa=1 padding=1,1,2,1 spacing=1,1 outline=0
|
||||||
|
common lineHeight=14 base=11 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||||
|
page id=0 file="font-calibri-12_0.png"
|
||||||
|
chars count=95
|
||||||
|
char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=3 page=0 chnl=15
|
||||||
|
char id=33 x=494 y=0 width=3 height=11 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=34 x=157 y=12 width=5 height=6 xoffset=0 yoffset=2 xadvance=5 page=0 chnl=15
|
||||||
|
char id=35 x=162 y=0 width=8 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=36 x=16 y=0 width=6 height=13 xoffset=0 yoffset=1 xadvance=6 page=0 chnl=15
|
||||||
|
char id=37 x=101 y=0 width=10 height=11 xoffset=-1 yoffset=2 xadvance=9 page=0 chnl=15
|
||||||
|
char id=38 x=123 y=0 width=9 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=39 x=168 y=12 width=3 height=6 xoffset=0 yoffset=2 xadvance=3 page=0 chnl=15
|
||||||
|
char id=40 x=51 y=0 width=4 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=41 x=41 y=0 width=4 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=42 x=117 y=12 width=7 height=8 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=43 x=109 y=12 width=7 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=44 x=163 y=12 width=4 height=6 xoffset=-1 yoffset=9 xadvance=3 page=0 chnl=15
|
||||||
|
char id=45 x=194 y=12 width=5 height=4 xoffset=-1 yoffset=6 xadvance=4 page=0 chnl=15
|
||||||
|
char id=46 x=204 y=12 width=3 height=4 xoffset=0 yoffset=9 xadvance=3 page=0 chnl=15
|
||||||
|
char id=47 x=0 y=0 width=7 height=14 xoffset=-1 yoffset=1 xadvance=5 page=0 chnl=15
|
||||||
|
char id=48 x=362 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=49 x=370 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=50 x=402 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=51 x=410 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=52 x=234 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=53 x=242 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=54 x=330 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=55 x=258 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=56 x=266 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=57 x=274 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=58 x=105 y=12 width=3 height=9 xoffset=0 yoffset=4 xadvance=3 page=0 chnl=15
|
||||||
|
char id=59 x=481 y=0 width=4 height=11 xoffset=-1 yoffset=4 xadvance=3 page=0 chnl=15
|
||||||
|
char id=60 x=133 y=12 width=7 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=61 x=149 y=12 width=7 height=6 xoffset=-1 yoffset=5 xadvance=6 page=0 chnl=15
|
||||||
|
char id=62 x=125 y=12 width=7 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=63 x=468 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=64 x=65 y=0 width=11 height=12 xoffset=0 yoffset=2 xadvance=11 page=0 chnl=15
|
||||||
|
char id=65 x=143 y=0 width=9 height=11 xoffset=-1 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=66 x=290 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=67 x=298 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=68 x=171 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=69 x=461 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=70 x=433 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=71 x=180 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=72 x=216 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=73 x=498 y=0 width=3 height=11 xoffset=0 yoffset=2 xadvance=3 page=0 chnl=15
|
||||||
|
char id=74 x=475 y=0 width=5 height=11 xoffset=-1 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=75 x=314 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=76 x=440 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=77 x=112 y=0 width=10 height=11 xoffset=0 yoffset=2 xadvance=10 page=0 chnl=15
|
||||||
|
char id=78 x=225 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=79 x=198 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=80 x=282 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=81 x=77 y=0 width=9 height=12 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=82 x=306 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=83 x=447 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=84 x=250 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=85 x=207 y=0 width=8 height=11 xoffset=0 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=86 x=133 y=0 width=9 height=11 xoffset=-1 yoffset=2 xadvance=8 page=0 chnl=15
|
||||||
|
char id=87 x=87 y=0 width=13 height=11 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||||
|
char id=88 x=189 y=0 width=8 height=11 xoffset=-1 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=89 x=322 y=0 width=7 height=11 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=90 x=153 y=0 width=8 height=11 xoffset=-1 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=91 x=46 y=0 width=4 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=92 x=8 y=0 width=7 height=14 xoffset=-1 yoffset=1 xadvance=5 page=0 chnl=15
|
||||||
|
char id=93 x=56 y=0 width=4 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=94 x=141 y=12 width=7 height=7 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=95 x=185 y=12 width=8 height=4 xoffset=-1 yoffset=11 xadvance=6 page=0 chnl=15
|
||||||
|
char id=96 x=180 y=12 width=4 height=5 xoffset=0 yoffset=1 xadvance=4 page=0 chnl=15
|
||||||
|
char id=97 x=71 y=13 width=7 height=9 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=98 x=338 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=99 x=79 y=13 width=6 height=9 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=100 x=346 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=101 x=23 y=14 width=7 height=9 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=102 x=426 y=0 width=6 height=11 xoffset=-1 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=103 x=354 y=0 width=7 height=11 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=104 x=386 y=0 width=7 height=11 xoffset=0 yoffset=2 xadvance=7 page=0 chnl=15
|
||||||
|
char id=105 x=486 y=0 width=3 height=11 xoffset=0 yoffset=2 xadvance=3 page=0 chnl=15
|
||||||
|
char id=106 x=29 y=0 width=5 height=13 xoffset=-2 yoffset=2 xadvance=2 page=0 chnl=15
|
||||||
|
char id=107 x=454 y=0 width=6 height=11 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=108 x=490 y=0 width=3 height=11 xoffset=0 yoffset=2 xadvance=3 page=0 chnl=15
|
||||||
|
char id=109 x=12 y=15 width=10 height=9 xoffset=0 yoffset=4 xadvance=10 page=0 chnl=15
|
||||||
|
char id=110 x=31 y=14 width=7 height=9 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=111 x=39 y=14 width=7 height=9 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=112 x=378 y=0 width=7 height=11 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=113 x=418 y=0 width=7 height=11 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=114 x=93 y=12 width=5 height=9 xoffset=0 yoffset=4 xadvance=4 page=0 chnl=15
|
||||||
|
char id=115 x=86 y=13 width=6 height=9 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=116 x=502 y=0 width=6 height=10 xoffset=-1 yoffset=3 xadvance=5 page=0 chnl=15
|
||||||
|
char id=117 x=47 y=14 width=7 height=9 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||||
|
char id=118 x=55 y=14 width=7 height=9 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=119 x=0 y=15 width=11 height=9 xoffset=-1 yoffset=4 xadvance=10 page=0 chnl=15
|
||||||
|
char id=120 x=63 y=14 width=7 height=9 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
char id=121 x=394 y=0 width=7 height=11 xoffset=-1 yoffset=4 xadvance=5 page=0 chnl=15
|
||||||
|
char id=122 x=99 y=12 width=5 height=9 xoffset=0 yoffset=4 xadvance=5 page=0 chnl=15
|
||||||
|
char id=123 x=35 y=0 width=5 height=13 xoffset=-1 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=124 x=61 y=0 width=3 height=13 xoffset=1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||||
|
char id=125 x=23 y=0 width=5 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=15
|
||||||
|
char id=126 x=172 y=12 width=7 height=5 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||||
|
kernings count=104
|
||||||
|
kerning first=65 second=84 amount=-1
|
||||||
|
kerning first=65 second=86 amount=-1
|
||||||
|
kerning first=65 second=89 amount=-1
|
||||||
|
kerning first=70 second=65 amount=-1
|
||||||
|
kerning first=70 second=74 amount=-1
|
||||||
|
kerning first=70 second=44 amount=-1
|
||||||
|
kerning first=70 second=46 amount=-1
|
||||||
|
kerning first=75 second=79 amount=-1
|
||||||
|
kerning first=75 second=81 amount=-1
|
||||||
|
kerning first=75 second=118 amount=-1
|
||||||
|
kerning first=75 second=119 amount=-1
|
||||||
|
kerning first=76 second=84 amount=-1
|
||||||
|
kerning first=76 second=86 amount=-1
|
||||||
|
kerning first=76 second=87 amount=-1
|
||||||
|
kerning first=76 second=89 amount=-1
|
||||||
|
kerning first=76 second=101 amount=-1
|
||||||
|
kerning first=80 second=65 amount=-1
|
||||||
|
kerning first=80 second=74 amount=-1
|
||||||
|
kerning first=80 second=44 amount=-1
|
||||||
|
kerning first=80 second=46 amount=-2
|
||||||
|
kerning first=80 second=47 amount=-1
|
||||||
|
kerning first=81 second=44 amount=1
|
||||||
|
kerning first=81 second=47 amount=1
|
||||||
|
kerning first=84 second=65 amount=-1
|
||||||
|
kerning first=84 second=97 amount=-1
|
||||||
|
kerning first=84 second=99 amount=-1
|
||||||
|
kerning first=84 second=100 amount=-1
|
||||||
|
kerning first=84 second=101 amount=-1
|
||||||
|
kerning first=84 second=103 amount=-1
|
||||||
|
kerning first=84 second=109 amount=-1
|
||||||
|
kerning first=84 second=110 amount=-1
|
||||||
|
kerning first=84 second=111 amount=-1
|
||||||
|
kerning first=84 second=112 amount=-1
|
||||||
|
kerning first=84 second=113 amount=-1
|
||||||
|
kerning first=84 second=114 amount=-1
|
||||||
|
kerning first=84 second=115 amount=-1
|
||||||
|
kerning first=84 second=117 amount=-1
|
||||||
|
kerning first=84 second=118 amount=-1
|
||||||
|
kerning first=84 second=119 amount=-1
|
||||||
|
kerning first=84 second=120 amount=-1
|
||||||
|
kerning first=84 second=121 amount=-1
|
||||||
|
kerning first=84 second=122 amount=-1
|
||||||
|
kerning first=84 second=44 amount=-1
|
||||||
|
kerning first=84 second=59 amount=-1
|
||||||
|
kerning first=84 second=58 amount=-1
|
||||||
|
kerning first=84 second=46 amount=-1
|
||||||
|
kerning first=84 second=47 amount=-1
|
||||||
|
kerning first=86 second=65 amount=-1
|
||||||
|
kerning first=86 second=97 amount=-1
|
||||||
|
kerning first=86 second=99 amount=-1
|
||||||
|
kerning first=86 second=100 amount=-1
|
||||||
|
kerning first=86 second=101 amount=-1
|
||||||
|
kerning first=86 second=103 amount=-1
|
||||||
|
kerning first=86 second=111 amount=-1
|
||||||
|
kerning first=86 second=113 amount=-1
|
||||||
|
kerning first=86 second=115 amount=-1
|
||||||
|
kerning first=86 second=44 amount=-1
|
||||||
|
kerning first=86 second=59 amount=-1
|
||||||
|
kerning first=86 second=46 amount=-1
|
||||||
|
kerning first=86 second=47 amount=-1
|
||||||
|
kerning first=87 second=65 amount=-1
|
||||||
|
kerning first=87 second=74 amount=-1
|
||||||
|
kerning first=87 second=111 amount=-1
|
||||||
|
kerning first=87 second=44 amount=-1
|
||||||
|
kerning first=87 second=59 amount=-1
|
||||||
|
kerning first=87 second=46 amount=-1
|
||||||
|
kerning first=89 second=65 amount=-1
|
||||||
|
kerning first=89 second=74 amount=-1
|
||||||
|
kerning first=89 second=97 amount=-1
|
||||||
|
kerning first=89 second=99 amount=-1
|
||||||
|
kerning first=89 second=100 amount=-1
|
||||||
|
kerning first=89 second=101 amount=-1
|
||||||
|
kerning first=89 second=103 amount=-1
|
||||||
|
kerning first=89 second=109 amount=-1
|
||||||
|
kerning first=89 second=110 amount=-1
|
||||||
|
kerning first=89 second=111 amount=-1
|
||||||
|
kerning first=89 second=112 amount=-1
|
||||||
|
kerning first=89 second=113 amount=-1
|
||||||
|
kerning first=89 second=114 amount=-1
|
||||||
|
kerning first=89 second=115 amount=-1
|
||||||
|
kerning first=89 second=117 amount=-1
|
||||||
|
kerning first=89 second=122 amount=-1
|
||||||
|
kerning first=89 second=44 amount=-1
|
||||||
|
kerning first=89 second=59 amount=-1
|
||||||
|
kerning first=89 second=58 amount=-1
|
||||||
|
kerning first=89 second=46 amount=-1
|
||||||
|
kerning first=89 second=47 amount=-1
|
||||||
|
kerning first=102 second=44 amount=-1
|
||||||
|
kerning first=102 second=46 amount=-1
|
||||||
|
kerning first=102 second=116 amount=1
|
||||||
|
kerning first=114 second=44 amount=-1
|
||||||
|
kerning first=114 second=46 amount=-1
|
||||||
|
kerning first=118 second=44 amount=-1
|
||||||
|
kerning first=118 second=46 amount=-1
|
||||||
|
kerning first=119 second=44 amount=-1
|
||||||
|
kerning first=119 second=46 amount=-1
|
||||||
|
kerning first=121 second=44 amount=-1
|
||||||
|
kerning first=121 second=46 amount=-1
|
||||||
|
kerning first=44 second=84 amount=-1
|
||||||
|
kerning first=44 second=86 amount=-1
|
||||||
|
kerning first=44 second=87 amount=-1
|
||||||
|
kerning first=44 second=89 amount=-1
|
||||||
|
kerning first=46 second=84 amount=-1
|
||||||
|
kerning first=46 second=86 amount=-1
|
||||||
|
kerning first=46 second=87 amount=-1
|
||||||
|
kerning first=46 second=89 amount=-1
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
@ -1,200 +1,194 @@
|
|||||||
|
|
||||||
skin.png
|
skin.png
|
||||||
size: 256,128
|
size: 93,139
|
||||||
format: RGBA8888
|
format: RGBA8888
|
||||||
filter: Linear,Linear
|
filter: Linear,Linear
|
||||||
repeat: none
|
repeat: none
|
||||||
check-off
|
button-disabled
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 11, 5
|
xy: 75, 73
|
||||||
size: 14, 14
|
size: 17, 17
|
||||||
orig: 14, 14
|
split: 6, 6, 5, 5
|
||||||
|
pad: -1, -1, 3, 3
|
||||||
|
orig: 17, 17
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
textfield
|
button-down
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 11, 5
|
xy: 75, 54
|
||||||
size: 14, 14
|
size: 17, 17
|
||||||
split: 3, 3, 3, 3
|
split: 6, 6, 5, 5
|
||||||
orig: 14, 14
|
pad: -1, -1, 3, 3
|
||||||
|
orig: 17, 17
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
check-on
|
button-over
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 125, 35
|
xy: 66, 35
|
||||||
size: 14, 14
|
size: 17, 17
|
||||||
orig: 14, 14
|
split: 6, 6, 5, 5
|
||||||
|
pad: -1, -1, 3, 3
|
||||||
|
orig: 17, 17
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
cursor
|
button-up
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 23, 1
|
xy: 24, 30
|
||||||
|
size: 17, 17
|
||||||
|
split: 6, 6, 5, 5
|
||||||
|
pad: -1, -1, 3, 3
|
||||||
|
orig: 17, 17
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
checkbox-off
|
||||||
|
rotate: false
|
||||||
|
xy: 66, 18
|
||||||
|
size: 15, 15
|
||||||
|
orig: 19, 18
|
||||||
|
offset: 0, 2
|
||||||
|
index: -1
|
||||||
|
checkbox-offDisabled
|
||||||
|
rotate: false
|
||||||
|
xy: 24, 13
|
||||||
|
size: 15, 15
|
||||||
|
orig: 19, 18
|
||||||
|
offset: 0, 2
|
||||||
|
index: -1
|
||||||
|
checkbox-on
|
||||||
|
rotate: false
|
||||||
|
xy: 1, 5
|
||||||
|
size: 15, 15
|
||||||
|
orig: 19, 18
|
||||||
|
offset: 0, 2
|
||||||
|
index: -1
|
||||||
|
checkbox-onDisabled
|
||||||
|
rotate: false
|
||||||
|
xy: 66, 1
|
||||||
|
size: 15, 15
|
||||||
|
orig: 19, 18
|
||||||
|
offset: 0, 2
|
||||||
|
index: -1
|
||||||
|
group
|
||||||
|
rotate: false
|
||||||
|
xy: 27, 72
|
||||||
|
size: 23, 23
|
||||||
|
split: 6, 6, 8, 8
|
||||||
|
pad: 11, 11, 11, 11
|
||||||
|
orig: 23, 23
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
list-selection
|
||||||
|
rotate: false
|
||||||
|
xy: 18, 8
|
||||||
|
size: 11, 3
|
||||||
|
split: 5, 5, 1, 1
|
||||||
|
orig: 11, 3
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
loading
|
||||||
|
rotate: false
|
||||||
|
xy: 61, 92
|
||||||
|
size: 30, 31
|
||||||
|
orig: 30, 31
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
scrollpane-horiz
|
||||||
|
rotate: false
|
||||||
|
xy: 1, 120
|
||||||
|
size: 58, 18
|
||||||
|
split: 3, 51, 0, 18
|
||||||
|
orig: 58, 18
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
scrollpane-vert
|
||||||
|
rotate: false
|
||||||
|
xy: 46, 9
|
||||||
|
size: 18, 58
|
||||||
|
split: 0, 18, 51, 3
|
||||||
|
orig: 18, 58
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
selectBox-closed
|
||||||
|
rotate: false
|
||||||
|
xy: 1, 97
|
||||||
|
size: 24, 21
|
||||||
|
split: 6, 14, 5, 13
|
||||||
|
pad: 5, 13, 3, 3
|
||||||
|
orig: 24, 21
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
selectBox-list
|
||||||
|
rotate: false
|
||||||
|
xy: 24, 49
|
||||||
|
size: 20, 21
|
||||||
|
split: 5, 12, 5, 13
|
||||||
|
orig: 20, 21
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
selectBox-open
|
||||||
|
rotate: false
|
||||||
|
xy: 27, 97
|
||||||
|
size: 24, 21
|
||||||
|
split: 6, 14, 5, 13
|
||||||
|
pad: 5, 13, 3, 3
|
||||||
|
orig: 24, 21
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
selectBox-over
|
||||||
|
rotate: false
|
||||||
|
xy: 1, 74
|
||||||
|
size: 24, 21
|
||||||
|
split: 6, 14, 5, 13
|
||||||
|
pad: 5, 13, 3, 3
|
||||||
|
orig: 24, 21
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
slider-bg
|
||||||
|
rotate: false
|
||||||
|
xy: 61, 125
|
||||||
|
size: 31, 13
|
||||||
|
split: 7, 6, 0, 13
|
||||||
|
pad: 3, 2, -1, -1
|
||||||
|
orig: 31, 13
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
slider-handle
|
||||||
|
rotate: false
|
||||||
|
xy: 53, 101
|
||||||
|
size: 6, 17
|
||||||
|
orig: 6, 17
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
textField-cursor
|
||||||
|
rotate: false
|
||||||
|
xy: 53, 96
|
||||||
size: 3, 3
|
size: 3, 3
|
||||||
split: 1, 1, 1, 1
|
split: 1, 1, 1, 1
|
||||||
orig: 3, 3
|
orig: 3, 3
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
default
|
textField-round
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 1, 50
|
xy: 52, 69
|
||||||
size: 253, 77
|
size: 21, 21
|
||||||
orig: 254, 77
|
split: 6, 5, 5, 5
|
||||||
offset: 1, 0
|
pad: -1, -1, 3, 3
|
||||||
index: -1
|
orig: 21, 21
|
||||||
default-pane
|
|
||||||
rotate: false
|
|
||||||
xy: 11, 1
|
|
||||||
size: 5, 3
|
|
||||||
split: 1, 1, 1, 1
|
|
||||||
orig: 5, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-rect-pad
|
|
||||||
rotate: false
|
|
||||||
xy: 11, 1
|
|
||||||
size: 5, 3
|
|
||||||
split: 1, 1, 1, 1
|
|
||||||
orig: 5, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-pane-noborder
|
|
||||||
rotate: false
|
|
||||||
xy: 129, 33
|
|
||||||
size: 1, 1
|
|
||||||
split: 0, 0, 0, 0
|
|
||||||
orig: 1, 1
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-rect
|
|
||||||
rotate: false
|
|
||||||
xy: 38, 25
|
|
||||||
size: 3, 3
|
|
||||||
split: 1, 1, 1, 1
|
|
||||||
orig: 3, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-rect-down
|
|
||||||
rotate: false
|
|
||||||
xy: 170, 46
|
|
||||||
size: 3, 3
|
|
||||||
split: 1, 1, 1, 1
|
|
||||||
orig: 3, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-round
|
|
||||||
rotate: false
|
|
||||||
xy: 112, 29
|
|
||||||
size: 12, 20
|
|
||||||
split: 5, 5, 5, 4
|
|
||||||
pad: 4, 4, 1, 1
|
|
||||||
orig: 12, 20
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-round-down
|
|
||||||
rotate: false
|
|
||||||
xy: 99, 29
|
|
||||||
size: 12, 20
|
|
||||||
split: 5, 5, 5, 4
|
|
||||||
pad: 4, 4, 1, 1
|
|
||||||
orig: 12, 20
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-round-large
|
|
||||||
rotate: false
|
|
||||||
xy: 57, 29
|
|
||||||
size: 20, 20
|
|
||||||
split: 5, 5, 5, 4
|
|
||||||
orig: 20, 20
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-scroll
|
|
||||||
rotate: false
|
|
||||||
xy: 78, 29
|
|
||||||
size: 20, 20
|
|
||||||
split: 2, 2, 2, 2
|
|
||||||
orig: 20, 20
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-select
|
|
||||||
rotate: false
|
|
||||||
xy: 29, 29
|
|
||||||
size: 27, 20
|
|
||||||
split: 4, 14, 4, 4
|
|
||||||
orig: 27, 20
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-select-selection
|
|
||||||
rotate: false
|
|
||||||
xy: 26, 16
|
|
||||||
size: 3, 3
|
|
||||||
split: 1, 1, 1, 1
|
|
||||||
orig: 3, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-slider
|
|
||||||
rotate: false
|
|
||||||
xy: 29, 20
|
|
||||||
size: 8, 8
|
|
||||||
split: 2, 2, 2, 2
|
|
||||||
orig: 8, 8
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-slider-knob
|
|
||||||
rotate: false
|
|
||||||
xy: 1, 1
|
|
||||||
size: 9, 18
|
|
||||||
orig: 9, 18
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-splitpane
|
|
||||||
rotate: false
|
|
||||||
xy: 17, 1
|
|
||||||
size: 5, 3
|
|
||||||
split: 0, 5, 0, 0
|
|
||||||
orig: 5, 3
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-splitpane-vertical
|
|
||||||
rotate: false
|
|
||||||
xy: 125, 29
|
|
||||||
size: 3, 5
|
|
||||||
split: 0, 0, 0, 5
|
|
||||||
orig: 3, 5
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
default-window
|
|
||||||
rotate: false
|
|
||||||
xy: 1, 20
|
|
||||||
size: 27, 29
|
|
||||||
split: 4, 3, 20, 3
|
|
||||||
orig: 27, 29
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
selection
|
|
||||||
rotate: false
|
|
||||||
xy: 170, 44
|
|
||||||
size: 1, 1
|
|
||||||
orig: 1, 1
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
tree-minus
|
|
||||||
rotate: false
|
|
||||||
xy: 140, 35
|
|
||||||
size: 14, 14
|
|
||||||
orig: 14, 14
|
|
||||||
offset: 0, 0
|
|
||||||
index: -1
|
|
||||||
tree-plus
|
|
||||||
rotate: false
|
|
||||||
xy: 155, 35
|
|
||||||
size: 14, 14
|
|
||||||
orig: 14, 14
|
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
white
|
white
|
||||||
rotate: false
|
rotate: false
|
||||||
xy: 174, 48
|
xy: 66, 64
|
||||||
size: 1, 1
|
size: 3, 3
|
||||||
orig: 1, 1
|
orig: 3, 3
|
||||||
|
offset: 0, 0
|
||||||
|
index: -1
|
||||||
|
window
|
||||||
|
rotate: false
|
||||||
|
xy: 1, 22
|
||||||
|
size: 21, 50
|
||||||
|
split: 10, 10, 36, 11
|
||||||
|
pad: 9, 9, 41, 8
|
||||||
|
orig: 21, 50
|
||||||
offset: 0, 0
|
offset: 0, 0
|
||||||
index: -1
|
index: -1
|
||||||
|
|||||||
@ -1,59 +1,66 @@
|
|||||||
{
|
{
|
||||||
com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: com/badlogic/gdx/utils/arial-15.fnt } },
|
com.badlogic.gdx.graphics.g2d.BitmapFont: {
|
||||||
|
default: { file: font-calibri-12.fnt }
|
||||||
|
}
|
||||||
com.badlogic.gdx.graphics.Color: {
|
com.badlogic.gdx.graphics.Color: {
|
||||||
green: { a: 1, b: 0, g: 1, r: 0 },
|
white: { r: 1, g: 1, b: 1 },
|
||||||
white: { a: 1, b: 1, g: 1, r: 1 },
|
black: {},
|
||||||
red: { a: 1, b: 0, g: 0, r: 1 },
|
disabled: { r: 0.53, g: 0.53, b: 0.53 },
|
||||||
black: { a: 1, b: 0, g: 0, r: 0 }
|
selection: { r: 0.77, g: 1, b: 1, a: 0.25 },
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {
|
com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {
|
||||||
dialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }
|
selection: { name: white, color: selection },
|
||||||
},
|
dim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.3 } },
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {
|
list-selection: { name: list-selection, color: selection },
|
||||||
default: { down: default-round-down, up: default-round },
|
|
||||||
toggle: { down: default-round-down, checked: default-round-down, up: default-round }
|
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
|
||||||
default: { down: default-round-down, up: default-round, font: default-font, fontColor: white },
|
default: {
|
||||||
toggle: { down: default-round-down, up: default-round, checked: default-round-down, font: default-font, fontColor: white, downFontColor: red }
|
up: button-up, down: button-down, over: button-over, disabled: button-disabled,
|
||||||
|
font: default, fontColor: white, disabledFontColor: disabled, pressedOffsetY: -1
|
||||||
|
},
|
||||||
|
toggle: {
|
||||||
|
up: button-up, down: button-down, over: button-over, disabled: button-disabled, checked: button-down,
|
||||||
|
font: default, fontColor: white, disabledFontColor: disabled, pressedOffsetY: -1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
|
||||||
|
default: { font: default, fontColor: white },
|
||||||
|
title: { font: default, fontColor: { hex: 00ffccff } },
|
||||||
|
}
|
||||||
|
com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {
|
||||||
|
default: { background: textField-round, font: default, fontColor: white, disabledFontColor: disabled,
|
||||||
|
selection: selection, cursor: textField-cursor },
|
||||||
|
}
|
||||||
|
com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {
|
||||||
|
default: { titleFont: default, titleFontColor: white, background: window },
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {
|
||||||
default: { vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large }
|
default: { hScrollKnob: scrollpane-horiz, vScrollKnob: scrollpane-vert },
|
||||||
|
bg: { hScrollKnob: scrollpane-horiz, vScrollKnob: scrollpane-vert, background: textField-round },
|
||||||
|
},
|
||||||
|
com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {
|
||||||
|
default: { font: default, selection: list-selection }
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {
|
||||||
default: {
|
default: {
|
||||||
font: default-font, fontColor: white, background: default-select,
|
background: selectBox-closed, backgroundOver: selectBox-over, backgroundOpen: selectBox-open, font: default, fontColor: white,
|
||||||
scrollStyle: default,
|
scrollStyle: { background: selectBox-list, hScrollKnob: scrollpane-horiz, vScrollKnob: scrollpane-vert },
|
||||||
listStyle: { font: default-font, selection: default-select-selection }
|
listStyle: { font: default, selection: list-selection },
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {
|
||||||
default-vertical: { handle: default-splitpane-vertical },
|
default: {
|
||||||
default-horizontal: { handle: default-splitpane }
|
label: { font: default, fontColor: white },
|
||||||
},
|
background: group
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {
|
},
|
||||||
default: { titleFont: default-font, background: default-window, titleFontColor: white },
|
|
||||||
dialog: { titleFont: default-font, background: default-window, titleFontColor: white, stageBackground: dialogDim }
|
|
||||||
},
|
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {
|
|
||||||
default-horizontal: { background: default-slider, knob: default-slider-knob }
|
|
||||||
},
|
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
|
|
||||||
default: { font: default-font, fontColor: white }
|
|
||||||
},
|
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {
|
|
||||||
default: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor }
|
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {
|
||||||
default: { checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white }
|
default: {
|
||||||
|
checkboxOn: checkbox-on, checkboxOff: checkbox-off, checkboxOffDisabled: checkbox-offDisabled,
|
||||||
|
checkboxOnDisabled: checkbox-onDisabled, font: default, fontColor: white, disabledFontColor: disabled
|
||||||
|
},
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {
|
com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {
|
||||||
default: { fontColorUnselected: white, selection: selection, fontColorSelected: white, font: default-font }
|
default-horizontal: { background: slider-bg, knob: slider-handle },
|
||||||
},
|
},
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {
|
|
||||||
default: { background: default-pane, knob: default-round-large }
|
|
||||||
},
|
|
||||||
com.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {
|
|
||||||
default: { minus: tree-minus, plus: tree-plus, selection: default-select-selection }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 5.6 KiB |
@ -50,6 +50,7 @@ import com.badlogic.gdx.graphics.GL20;
|
|||||||
import com.badlogic.gdx.graphics.Pixmap;
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.Texture.TextureFilter;
|
||||||
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
||||||
@ -83,7 +84,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
UI ui;
|
UI ui;
|
||||||
|
|
||||||
PolygonSpriteBatch batch;
|
PolygonSpriteBatch batch;
|
||||||
SkeletonRenderer renderer;
|
SkeletonMeshRenderer renderer;
|
||||||
SkeletonRendererDebug debugRenderer;
|
SkeletonRendererDebug debugRenderer;
|
||||||
SkeletonData skeletonData;
|
SkeletonData skeletonData;
|
||||||
Skeleton skeleton;
|
Skeleton skeleton;
|
||||||
@ -96,38 +97,49 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
public void create () {
|
public void create () {
|
||||||
ui = new UI();
|
ui = new UI();
|
||||||
batch = new PolygonSpriteBatch();
|
batch = new PolygonSpriteBatch();
|
||||||
renderer = new SkeletonRenderer();
|
renderer = new SkeletonMeshRenderer();
|
||||||
debugRenderer = new SkeletonRendererDebug();
|
debugRenderer = new SkeletonRendererDebug();
|
||||||
skeletonX = (int)(ui.window.getWidth() + (Gdx.graphics.getWidth() - ui.window.getWidth()) / 2);
|
skeletonX = (int)(ui.window.getWidth() + (Gdx.graphics.getWidth() - ui.window.getWidth()) / 2);
|
||||||
skeletonY = Gdx.graphics.getHeight() / 4;
|
skeletonY = Gdx.graphics.getHeight() / 4;
|
||||||
|
|
||||||
loadSkeleton(
|
loadSkeleton(
|
||||||
Gdx.files.internal(Gdx.app.getPreferences("spine-skeletontest").getString("lastFile", "spineboy/spineboy.json")), false);
|
Gdx.files.internal(Gdx.app.getPreferences("spine-skeletonviewer").getString("lastFile", "spineboy/spineboy.json")),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSkeleton (FileHandle skeletonFile, boolean reload) {
|
void loadSkeleton (final FileHandle skeletonFile, boolean reload) {
|
||||||
if (skeletonFile == null) return;
|
if (skeletonFile == null) return;
|
||||||
|
|
||||||
// A regular texture atlas would normally usually be used. This returns a white image for images not found in the atlas.
|
|
||||||
Pixmap pixmap = new Pixmap(32, 32, Format.RGBA8888);
|
|
||||||
pixmap.setColor(new Color(1, 1, 1, 0.33f));
|
|
||||||
pixmap.fill();
|
|
||||||
final AtlasRegion fake = new AtlasRegion(new Texture(pixmap), 0, 0, 32, 32);
|
|
||||||
pixmap.dispose();
|
|
||||||
|
|
||||||
String atlasFileName = skeletonFile.nameWithoutExtension();
|
|
||||||
if (atlasFileName.endsWith(".json")) atlasFileName = new FileHandle(atlasFileName).nameWithoutExtension();
|
|
||||||
FileHandle atlasFile = skeletonFile.sibling(atlasFileName + ".atlas");
|
|
||||||
if (!atlasFile.exists()) atlasFile = skeletonFile.sibling(atlasFileName + ".atlas.txt");
|
|
||||||
TextureAtlasData data = !atlasFile.exists() ? null : new TextureAtlasData(atlasFile, atlasFile.parent(), false);
|
|
||||||
TextureAtlas atlas = new TextureAtlas(data) {
|
|
||||||
public AtlasRegion findRegion (String name) {
|
|
||||||
AtlasRegion region = super.findRegion(name);
|
|
||||||
return region != null ? region : fake;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// A regular texture atlas would normally usually be used. This returns a white image for images not found in the atlas.
|
||||||
|
Pixmap pixmap = new Pixmap(32, 32, Format.RGBA8888);
|
||||||
|
pixmap.setColor(new Color(1, 1, 1, 0.33f));
|
||||||
|
pixmap.fill();
|
||||||
|
final AtlasRegion fake = new AtlasRegion(new Texture(pixmap), 0, 0, 32, 32);
|
||||||
|
pixmap.dispose();
|
||||||
|
|
||||||
|
String atlasFileName = skeletonFile.nameWithoutExtension();
|
||||||
|
if (atlasFileName.endsWith(".json")) atlasFileName = new FileHandle(atlasFileName).nameWithoutExtension();
|
||||||
|
FileHandle atlasFile = skeletonFile.sibling(atlasFileName + ".atlas");
|
||||||
|
if (!atlasFile.exists()) atlasFile = skeletonFile.sibling(atlasFileName + ".atlas.txt");
|
||||||
|
TextureAtlasData data = !atlasFile.exists() ? null : new TextureAtlasData(atlasFile, atlasFile.parent(), false);
|
||||||
|
TextureAtlas atlas = new TextureAtlas(data) {
|
||||||
|
public AtlasRegion findRegion (String name) {
|
||||||
|
AtlasRegion region = super.findRegion(name);
|
||||||
|
if (region == null) {
|
||||||
|
// Look for separate image file.
|
||||||
|
FileHandle file = skeletonFile.sibling(name + ".png");
|
||||||
|
if (file.exists()) {
|
||||||
|
Texture texture = new Texture(file);
|
||||||
|
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
|
||||||
|
region = new AtlasRegion(texture, 0, 0, texture.getWidth(), texture.getHeight());
|
||||||
|
region.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return region != null ? region : fake;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
String extension = skeletonFile.extension();
|
String extension = skeletonFile.extension();
|
||||||
if (extension.equalsIgnoreCase("json") || extension.equalsIgnoreCase("txt")) {
|
if (extension.equalsIgnoreCase("json") || extension.equalsIgnoreCase("txt")) {
|
||||||
SkeletonJson json = new SkeletonJson(atlas);
|
SkeletonJson json = new SkeletonJson(atlas);
|
||||||
@ -137,6 +149,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
SkeletonBinary binary = new SkeletonBinary(atlas);
|
SkeletonBinary binary = new SkeletonBinary(atlas);
|
||||||
binary.setScale(ui.scaleSlider.getValue());
|
binary.setScale(ui.scaleSlider.getValue());
|
||||||
skeletonData = binary.readSkeletonData(skeletonFile);
|
skeletonData = binary.readSkeletonData(skeletonFile);
|
||||||
|
if (skeletonData.getBones().size == 0) throw new Exception("No bones in skeleton data.");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
@ -153,7 +166,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
state = new AnimationState(new AnimationStateData(skeletonData));
|
state = new AnimationState(new AnimationStateData(skeletonData));
|
||||||
|
|
||||||
this.skeletonFile = skeletonFile;
|
this.skeletonFile = skeletonFile;
|
||||||
Preferences prefs = Gdx.app.getPreferences("spine-skeletontest");
|
Preferences prefs = Gdx.app.getPreferences("spine-skeletonviewer");
|
||||||
prefs.putString("lastFile", skeletonFile.path());
|
prefs.putString("lastFile", skeletonFile.path());
|
||||||
prefs.flush();
|
prefs.flush();
|
||||||
lastModified = skeletonFile.lastModified();
|
lastModified = skeletonFile.lastModified();
|
||||||
@ -161,7 +174,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
|
|
||||||
// Populate UI.
|
// Populate UI.
|
||||||
|
|
||||||
ui.skeletonLabel.setText(skeletonFile.name());
|
ui.window.getTitleLabel().setText(skeletonFile.name());
|
||||||
{
|
{
|
||||||
Array<String> items = new Array();
|
Array<String> items = new Array();
|
||||||
for (Skin skin : skeletonData.getSkins())
|
for (Skin skin : skeletonData.getSkins())
|
||||||
@ -177,8 +190,9 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
|
|
||||||
// Configure skeleton from UI.
|
// Configure skeleton from UI.
|
||||||
|
|
||||||
skeleton.setSkin(ui.skinList.getSelected());
|
if (ui.skinList.getSelected() != null) skeleton.setSkin(ui.skinList.getSelected());
|
||||||
state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked());
|
if (ui.animationList.getSelected() != null)
|
||||||
|
state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked());
|
||||||
|
|
||||||
if (reload) ui.toast("Reloaded.");
|
if (reload) ui.toast("Reloaded.");
|
||||||
}
|
}
|
||||||
@ -217,6 +231,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
// skeleton.getRootBone().setY(skeletonY);
|
// skeleton.getRootBone().setY(skeletonY);
|
||||||
skeleton.updateWorldTransform();
|
skeleton.updateWorldTransform();
|
||||||
|
|
||||||
|
batch.setColor(Color.WHITE);
|
||||||
batch.begin();
|
batch.begin();
|
||||||
renderer.draw(batch, skeleton);
|
renderer.draw(batch, skeleton);
|
||||||
batch.end();
|
batch.end();
|
||||||
@ -252,7 +267,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
||||||
debugRenderer.getShapeRenderer().setProjectionMatrix(batch.getProjectionMatrix());
|
debugRenderer.getShapeRenderer().setProjectionMatrix(batch.getProjectionMatrix());
|
||||||
ui.stage.getViewport().update(width, height, true);
|
ui.stage.getViewport().update(width, height, true);
|
||||||
if (!ui.minimizeButton.isChecked()) ui.window.setHeight(height);
|
if (!ui.minimizeButton.isChecked()) ui.window.setHeight(height + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UI {
|
class UI {
|
||||||
@ -262,8 +277,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
|
|
||||||
Window window = new Window("Skeleton", skin);
|
Window window = new Window("Skeleton", skin);
|
||||||
Table root = new Table(skin);
|
Table root = new Table(skin);
|
||||||
TextButton browseButton = new TextButton("Browse", skin);
|
TextButton openButton = new TextButton("Open", skin);
|
||||||
Label skeletonLabel = new Label("", skin);
|
|
||||||
List<String> animationList = new List(skin);
|
List<String> animationList = new List(skin);
|
||||||
List<String> skinList = new List(skin);
|
List<String> skinList = new List(skin);
|
||||||
CheckBox loopCheckbox = new CheckBox(" Loop", skin);
|
CheckBox loopCheckbox = new CheckBox(" Loop", skin);
|
||||||
@ -305,30 +319,24 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
|
|
||||||
window.setMovable(false);
|
window.setMovable(false);
|
||||||
window.setResizable(false);
|
window.setResizable(false);
|
||||||
|
window.setKeepWithinStage(false);
|
||||||
|
window.setX(-3);
|
||||||
|
window.setY(-2);
|
||||||
|
|
||||||
minimizeButton.padTop(-2).padLeft(5);
|
window.getTitleTable().add(openButton).space(3);
|
||||||
minimizeButton.getColor().a = 0.66f;
|
window.getTitleTable().add(minimizeButton).width(20);
|
||||||
window.getTitleTable().add(minimizeButton).size(20, 20);
|
|
||||||
|
|
||||||
ScrollPane skinScroll = new ScrollPane(skinList, skin);
|
ScrollPane skinScroll = new ScrollPane(skinList, skin, "bg");
|
||||||
skinScroll.setFadeScrollBars(false);
|
skinScroll.setFadeScrollBars(false);
|
||||||
|
|
||||||
ScrollPane animationScroll = new ScrollPane(animationList, skin);
|
ScrollPane animationScroll = new ScrollPane(animationList, skin, "bg");
|
||||||
animationScroll.setFadeScrollBars(false);
|
animationScroll.setFadeScrollBars(false);
|
||||||
|
|
||||||
// Layout.
|
// Layout.
|
||||||
|
|
||||||
root.pad(2, 4, 4, 4).defaults().space(6);
|
root.defaults().space(6);
|
||||||
root.columnDefaults(0).top().right();
|
root.columnDefaults(0).top().right().padTop(3);
|
||||||
root.columnDefaults(1).left();
|
root.columnDefaults(1).left();
|
||||||
root.row().padTop(6);
|
|
||||||
root.add("Skeleton:");
|
|
||||||
{
|
|
||||||
Table table = table();
|
|
||||||
table.add(skeletonLabel).fillX().expandX();
|
|
||||||
table.add(browseButton);
|
|
||||||
root.add(table).fill().row();
|
|
||||||
}
|
|
||||||
root.add("Scale:");
|
root.add("Scale:");
|
||||||
{
|
{
|
||||||
Table table = table();
|
Table table = table();
|
||||||
@ -378,7 +386,6 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
stage.addActor(table);
|
stage.addActor(table);
|
||||||
table.pad(10).bottom().right();
|
table.pad(10).bottom().right();
|
||||||
table.add(toasts);
|
table.add(toasts);
|
||||||
table.debug();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events.
|
// Events.
|
||||||
@ -390,7 +397,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
browseButton.addListener(new ChangeListener() {
|
openButton.addListener(new ChangeListener() {
|
||||||
public void changed (ChangeEvent event, Actor actor) {
|
public void changed (ChangeEvent event, Actor actor) {
|
||||||
FileDialog fileDialog = new FileDialog((Frame)null, "Choose skeleton file");
|
FileDialog fileDialog = new FileDialog((Frame)null, "Choose skeleton file");
|
||||||
fileDialog.setMode(FileDialog.LOAD);
|
fileDialog.setMode(FileDialog.LOAD);
|
||||||
@ -427,11 +434,11 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
public void clicked (InputEvent event, float x, float y) {
|
public void clicked (InputEvent event, float x, float y) {
|
||||||
if (minimizeButton.isChecked()) {
|
if (minimizeButton.isChecked()) {
|
||||||
window.getCells().get(0).setActor(null);
|
window.getCells().get(0).setActor(null);
|
||||||
window.setHeight(20);
|
window.setHeight(37);
|
||||||
minimizeButton.setText("+");
|
minimizeButton.setText("+");
|
||||||
} else {
|
} else {
|
||||||
window.getCells().get(0).setActor(root);
|
window.getCells().get(0).setActor(root);
|
||||||
ui.window.setHeight(Gdx.graphics.getHeight());
|
ui.window.setHeight(Gdx.graphics.getHeight() + 8);
|
||||||
minimizeButton.setText("-");
|
minimizeButton.setText("-");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +473,11 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
skinList.addListener(new ChangeListener() {
|
skinList.addListener(new ChangeListener() {
|
||||||
public void changed (ChangeEvent event, Actor actor) {
|
public void changed (ChangeEvent event, Actor actor) {
|
||||||
if (skeleton != null) {
|
if (skeleton != null) {
|
||||||
skeleton.setSkin(skinList.getSelected());
|
String skinName = skinList.getSelected();
|
||||||
|
if (skinName == null)
|
||||||
|
skeleton.setSkin((Skin)null);
|
||||||
|
else
|
||||||
|
skeleton.setSkin(skinName);
|
||||||
skeleton.setSlotsToSetupPose();
|
skeleton.setSlotsToSetupPose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -504,7 +515,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|||||||
delay(5f), //
|
delay(5f), //
|
||||||
parallel(moveBy(0, table.getHeight(), 0.3f), fadeOut(0.3f)), //
|
parallel(moveBy(0, table.getHeight(), 0.3f), fadeOut(0.3f)), //
|
||||||
removeActor() //
|
removeActor() //
|
||||||
));
|
));
|
||||||
for (Actor actor : toasts.getChildren())
|
for (Actor actor : toasts.getChildren())
|
||||||
actor.addAction(moveBy(0, table.getHeight(), 0.3f));
|
actor.addAction(moveBy(0, table.getHeight(), 0.3f));
|
||||||
toasts.addActor(table);
|
toasts.addActor(table);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user