diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index 028106efe..834e53967 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -55,7 +55,7 @@ public class Bone implements Updatable { float a, b, worldX; float c, d, worldY; - boolean sorted; + boolean sorted, update; /** @param parent May be null. */ public Bone (BoneData data, Skeleton skeleton, Bone parent) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java index 0965f95e6..b9d74fa39 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java @@ -40,6 +40,7 @@ public class BoneData { float length; float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY; TransformMode transformMode = TransformMode.normal; + boolean skinRequired; // Nonessential. final Color color = new Color(0.61f, 0.61f, 0.61f, 1); // 9b9b9bff @@ -176,6 +177,17 @@ public class BoneData { this.transformMode = transformMode; } + /** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#getSkin()} contains this + * bone. + * @see Skin#getBones() */ + public boolean getSkinRequired () { + return skinRequired; + } + + public void setSkinRequired (boolean skinRequired) { + this.skinRequired = skinRequired; + } + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually * rendered at runtime. */ public Color getColor () { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java deleted file mode 100644 index 8864b026b..000000000 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constraint.java +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF - * USE, DATA, OR PROFITS) 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; - -/** The interface for all constraints. */ -public interface Constraint extends Updatable { - /** The ordinal for the order a skeleton's constraints will be applied. */ - public int getOrder (); -} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java new file mode 100644 index 000000000..4a706e297 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java @@ -0,0 +1,44 @@ + +package com.esotericsoftware.spine; + +/** The base class for all constraint datas. */ +abstract public class ConstraintData { + final String name; + int order; + boolean skinRequired; + + public ConstraintData (String name) { + if (name == null) throw new IllegalArgumentException("name cannot be null."); + this.name = name; + } + + /** The constraint's name, which is unique across all constraints in the skeleton of the same type. */ + public String getName () { + return name; + } + + /** The ordinal of this constraint for the order a skeleton's constraints will be applied by + * {@link Skeleton#updateWorldTransform()}. */ + public int getOrder () { + return order; + } + + public void setOrder (int order) { + this.order = order; + } + + /** When true, {@link Skeleton#updateWorldTransform()} only updates this constraint if the {@link Skeleton#getSkin()} contains + * this constraint. + * @see Skin#getConstraints() */ + public boolean getSkinRequired () { + return skinRequired; + } + + public void setSkinRequired (boolean skinRequired) { + this.skinRequired = skinRequired; + } + + public String toString () { + return name; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 4fbcebab4..29b5895f8 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -38,7 +38,7 @@ import com.badlogic.gdx.utils.Array; * the last bone is as close to the target bone as possible. *
* See IK constraints in the Spine User Guide. */
-public class IkConstraint implements Constraint {
+public class IkConstraint implements Updatable {
final IkConstraintData data;
final Array
* See IK constraints in the Spine User Guide. */
-public class IkConstraintData {
- final String name;
- int order;
+public class IkConstraintData extends ConstraintData {
final Array
* See Path constraints in the Spine User Guide. */
-public class PathConstraint implements Constraint {
+public class PathConstraint implements Updatable {
static private final int NONE = -1, BEFORE = -2, AFTER = -3;
static private final float epsilon = 0.00001f;
@@ -449,10 +449,6 @@ public class PathConstraint implements Constraint {
}
}
- public int getOrder () {
- return data.order;
- }
-
/** The position along the path. */
public float getPosition () {
return position;
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java
index 4007a142c..62ccec5f2 100644
--- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java
@@ -35,9 +35,7 @@ import com.badlogic.gdx.utils.Array;
/** Stores the setup pose for a {@link PathConstraint}.
*
* See Path constraints in the Spine User Guide. */
-public class PathConstraintData {
- final String name;
- int order;
+public class PathConstraintData extends ConstraintData {
final Array
* See Position mode in the Spine User Guide. */
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java
index 498dd54d2..819167734 100644
--- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java
@@ -156,40 +156,44 @@ public class Skeleton {
updateCache();
}
- /** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are
- * added or removed. */
+ /** Caches information about bones and constraints. Must be called if the skin is changed or if bones, constraints, or weighted
+ * path attachments are added or removed. */
public void updateCache () {
Array
* See World transforms in the Spine
* Runtimes Guide. */
@@ -354,8 +363,7 @@ public class Skeleton {
bone.appliedValid = true;
}
- // Apply the parent bone transform to the root bone. The root bone
- // always inherits scale, rotation and reflection.
+ // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
Bone rootBone = getRootBone();
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
rootBone.worldX = pa * x + pb * y + parent.worldX;
@@ -515,6 +523,7 @@ public class Skeleton {
* skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
* @param newSkin May be null. */
public void setSkin (Skin newSkin) {
+ if (newSkin == skin) return;
if (newSkin != null) {
if (skin != null)
newSkin.attachAll(this, skin);
@@ -531,6 +540,7 @@ public class Skeleton {
}
}
skin = newSkin;
+ updateCache();
}
/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java
index 6f19ace48..3652ee824 100644
--- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java
@@ -41,6 +41,7 @@ import com.badlogic.gdx.utils.DataInput;
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.SerializationException;
+
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
import com.esotericsoftware.spine.Animation.ColorTimeline;
import com.esotericsoftware.spine.Animation.CurveTimeline;
@@ -206,6 +207,7 @@ public class SkeletonBinary {
data.shearY = input.readFloat();
data.length = input.readFloat() * scale;
data.transformMode = TransformMode.values[input.readInt(true)];
+ data.skinRequired = input.readBoolean();
if (nonessential) Color.rgba8888ToColor(data.color, input.readInt());
skeletonData.bones.add(data);
}
@@ -229,6 +231,7 @@ public class SkeletonBinary {
for (int i = 0, n = input.readInt(true); i < n; i++) {
IkConstraintData data = new IkConstraintData(input.readString());
data.order = input.readInt(true);
+ data.skinRequired = input.readBoolean();
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++)
data.bones.add(skeletonData.bones.get(input.readInt(true)));
data.target = skeletonData.bones.get(input.readInt(true));
@@ -244,6 +247,7 @@ public class SkeletonBinary {
for (int i = 0, n = input.readInt(true); i < n; i++) {
TransformConstraintData data = new TransformConstraintData(input.readString());
data.order = input.readInt(true);
+ data.skinRequired = input.readBoolean();
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++)
data.bones.add(skeletonData.bones.get(input.readInt(true)));
data.target = skeletonData.bones.get(input.readInt(true));
@@ -266,6 +270,7 @@ public class SkeletonBinary {
for (int i = 0, n = input.readInt(true); i < n; i++) {
PathConstraintData data = new PathConstraintData(input.readString());
data.order = input.readInt(true);
+ data.skinRequired = input.readBoolean();
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++)
data.bones.add(skeletonData.bones.get(input.readInt(true)));
data.target = skeletonData.slots.get(input.readInt(true));
@@ -283,7 +288,7 @@ public class SkeletonBinary {
}
// Default skin.
- Skin defaultSkin = readSkin(input, skeletonData, "default", nonessential);
+ Skin defaultSkin = readSkin(input, skeletonData, true, nonessential);
if (defaultSkin != null) {
skeletonData.defaultSkin = defaultSkin;
skeletonData.skins.add(defaultSkin);
@@ -291,7 +296,7 @@ public class SkeletonBinary {
// Skins.
for (int i = 0, n = input.readInt(true); i < n; i++)
- skeletonData.skins.add(readSkin(input, skeletonData, input.readString(), nonessential));
+ skeletonData.skins.add(readSkin(input, skeletonData, false, nonessential));
// Linked meshes.
for (int i = 0, n = linkedMeshes.size; i < n; i++) {
@@ -341,12 +346,18 @@ public class SkeletonBinary {
return skeletonData;
}
- /** @return May be null. */
- private Skin readSkin (DataInput input, SkeletonData skeletonData, String skinName, boolean nonessential) throws IOException {
- int slotCount = input.readInt(true);
- if (slotCount == 0) return null;
- Skin skin = new Skin(skinName);
- for (int i = 0; i < slotCount; i++) {
+ private Skin readSkin (DataInput input, SkeletonData skeletonData, boolean defaultSkin, boolean nonessential)
+ throws IOException {
+ Skin skin = new Skin(defaultSkin ? "default" : input.readString());
+ for (int i = 0, n = input.readInt(true); i < n; i++)
+ skin.bones.add(skeletonData.bones.get(input.readInt(true)));
+ for (int i = 0, n = input.readInt(true); i < n; i++)
+ skin.constraints.add(skeletonData.ikConstraints.get(input.readInt(true)));
+ for (int i = 0, n = input.readInt(true); i < n; i++)
+ skin.constraints.add(skeletonData.transformConstraints.get(input.readInt(true)));
+ for (int i = 0, n = input.readInt(true); i < n; i++)
+ skin.constraints.add(skeletonData.pathConstraints.get(input.readInt(true)));
+ for (int i = 0, n = input.readInt(true); i < n; i++) {
int slotIndex = input.readInt(true);
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
String name = input.readString();
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java
index 10fa289b4..e61592f97 100644
--- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java
@@ -149,6 +149,7 @@ public class SkeletonJson {
data.shearX = boneMap.getFloat("shearX", 0);
data.shearY = boneMap.getFloat("shearY", 0);
data.transformMode = TransformMode.valueOf(boneMap.getString("transform", TransformMode.normal.name()));
+ data.skinRequired = boneMap.getBoolean("skin", false);
String color = boneMap.getString("color", null);
if (color != null) data.getColor().set(Color.valueOf(color));
@@ -179,11 +180,11 @@ public class SkeletonJson {
for (JsonValue constraintMap = root.getChild("ik"); constraintMap != null; constraintMap = constraintMap.next) {
IkConstraintData data = new IkConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
+ data.skinRequired = constraintMap.getBoolean("skin", false);
- for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
- String boneName = boneMap.asString();
- BoneData bone = skeletonData.findBone(boneName);
- if (bone == null) throw new SerializationException("IK bone not found: " + boneName);
+ for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
+ BoneData bone = skeletonData.findBone(entry.asString());
+ if (bone == null) throw new SerializationException("IK bone not found: " + entry);
data.bones.add(bone);
}
@@ -204,11 +205,11 @@ public class SkeletonJson {
for (JsonValue constraintMap = root.getChild("transform"); constraintMap != null; constraintMap = constraintMap.next) {
TransformConstraintData data = new TransformConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
+ data.skinRequired = constraintMap.getBoolean("skin", false);
- for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
- String boneName = boneMap.asString();
- BoneData bone = skeletonData.findBone(boneName);
- if (bone == null) throw new SerializationException("Transform constraint bone not found: " + boneName);
+ for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
+ BoneData bone = skeletonData.findBone(entry.asString());
+ if (bone == null) throw new SerializationException("Transform constraint bone not found: " + entry);
data.bones.add(bone);
}
@@ -238,11 +239,11 @@ public class SkeletonJson {
for (JsonValue constraintMap = root.getChild("path"); constraintMap != null; constraintMap = constraintMap.next) {
PathConstraintData data = new PathConstraintData(constraintMap.getString("name"));
data.order = constraintMap.getInt("order", 0);
+ data.skinRequired = constraintMap.getBoolean("skin", false);
- for (JsonValue boneMap = constraintMap.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
- String boneName = boneMap.asString();
- BoneData bone = skeletonData.findBone(boneName);
- if (bone == null) throw new SerializationException("Path bone not found: " + boneName);
+ for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
+ BoneData bone = skeletonData.findBone(entry.asString());
+ if (bone == null) throw new SerializationException("Path bone not found: " + entry);
data.bones.add(bone);
}
@@ -266,8 +267,28 @@ public class SkeletonJson {
// Skins.
for (JsonValue skinMap = root.getChild("skins"); skinMap != null; skinMap = skinMap.next) {
- Skin skin = new Skin(skinMap.name);
- for (JsonValue slotEntry = skinMap.child; slotEntry != null; slotEntry = slotEntry.next) {
+ Skin skin = new Skin(skinMap.getString("name"));
+ for (JsonValue entry = skinMap.getChild("bones"); entry != null; entry = entry.next) {
+ BoneData bone = skeletonData.findBone(entry.asString());
+ if (bone == null) throw new SerializationException("Skin bone not found: " + entry);
+ skin.bones.add(bone);
+ }
+ for (JsonValue entry = skinMap.getChild("ik"); entry != null; entry = entry.next) {
+ IkConstraintData constraint = skeletonData.findIkConstraint(entry.asString());
+ if (constraint == null) throw new SerializationException("Skin IK constraint not found: " + entry);
+ skin.constraints.add(constraint);
+ }
+ for (JsonValue entry = skinMap.getChild("transform"); entry != null; entry = entry.next) {
+ TransformConstraintData constraint = skeletonData.findTransformConstraint(entry.asString());
+ if (constraint == null) throw new SerializationException("Skin transform constraint not found: " + entry);
+ skin.constraints.add(constraint);
+ }
+ for (JsonValue entry = skinMap.getChild("path"); entry != null; entry = entry.next) {
+ PathConstraintData constraint = skeletonData.findPathConstraint(entry.asString());
+ if (constraint == null) throw new SerializationException("Skin path constraint not found: " + entry);
+ skin.constraints.add(constraint);
+ }
+ for (JsonValue slotEntry = skinMap.getChild("attachments"); slotEntry != null; slotEntry = slotEntry.next) {
SlotData slot = skeletonData.findSlot(slotEntry.name);
if (slot == null) throw new SerializationException("Slot not found: " + slotEntry.name);
for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) {
@@ -608,7 +629,7 @@ public class SkeletonJson {
}
// Path constraint timelines.
- for (JsonValue constraintMap = map.getChild("paths"); constraintMap != null; constraintMap = constraintMap.next) {
+ for (JsonValue constraintMap = map.getChild("path"); constraintMap != null; constraintMap = constraintMap.next) {
PathConstraintData data = skeletonData.findPathConstraint(constraintMap.name);
if (data == null) throw new SerializationException("Path constraint not found: " + constraintMap.name);
int index = skeletonData.pathConstraints.indexOf(data, true);
@@ -768,9 +789,8 @@ public class SkeletonJson {
if (curve == null) return;
if (curve.isString() && curve.asString().equals("stepped"))
timeline.setStepped(frameIndex);
- else if (curve.isArray()) {
+ else if (curve.isArray())
timeline.setCurve(frameIndex, curve.getFloat(0), curve.getFloat(1), curve.getFloat(2), curve.getFloat(3));
- }
}
static class LinkedMesh {
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java
index 5c5f205fd..9d9addcb9 100644
--- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java
@@ -44,6 +44,8 @@ import com.esotericsoftware.spine.attachments.Attachment;
public class Skin {
final String name;
final ObjectMap
* See Transform constraints in the Spine User Guide. */
-public class TransformConstraint implements Constraint {
+public class TransformConstraint implements Updatable {
final TransformConstraintData data;
final Array
* See Transform constraints in the Spine User Guide. */
-public class TransformConstraintData {
- final String name;
- int order;
+public class TransformConstraintData extends ConstraintData {
final Array