JSON and binary path attachment and constraint loading.

This commit is contained in:
NathanSweet 2016-06-09 03:33:48 +02:00
parent a6ccff5fde
commit 40950eded7
5 changed files with 78 additions and 49 deletions

View File

@ -90,12 +90,14 @@ public class PathConstraint implements Updatable {
float[] positions = computeWorldPositions((PathAttachment)attachment, spacesCount, tangents,
data.positionMode == PositionMode.percent, spacingMode == SpacingMode.percent);
Skeleton skeleton = target.getSkeleton();
float skeletonX = skeleton.x, skeletonY = skeleton.y;
float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
boolean tip = rotateMode == RotateMode.chain && offsetRotation == 0;
for (int i = 0, p = 3; i < boneCount; i++, p += 3) {
Bone bone = (Bone)bones[i];
bone.worldX += (boneX - bone.worldX) * translateMix;
bone.worldY += (boneY - bone.worldY) * translateMix;
bone.worldX += (boneX - bone.worldX) * translateMix - skeletonX;
bone.worldY += (boneY - bone.worldY) * translateMix - skeletonY;
float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
if (scale) {
float length = lengths[i];
@ -147,7 +149,7 @@ public class PathConstraint implements Updatable {
boolean closed = path.getClosed();
if (!path.getConstantSpeed()) {
float pathLength = path.getTotalLength();
float pathLength = path.getLength();
if (percentPosition) position *= pathLength;
if (percentSpacing) {
for (int i = 0; i < spacesCount; i++)
@ -203,7 +205,7 @@ public class PathConstraint implements Updatable {
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0);
}
addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
tangents || (space == 0 && i > 0));
tangents || (i > 0 && space == 0));
}
return out;
}
@ -351,8 +353,7 @@ public class PathConstraint implements Updatable {
}
break;
}
addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (space == 0 && i > 0));
addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));
}
return out;
}

View File

@ -140,7 +140,8 @@ public class Skeleton {
updateCache();
}
/** Caches information about bones and constraints. Must be called if bones or constraints are added or removed. */
/** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are
* added or removed. */
public void updateCache () {
Array<Updatable> updateCache = this.updateCache;
updateCache.clear();
@ -191,6 +192,7 @@ public class Skeleton {
for (int i = 0, n = pathConstraints.size; i < n; i++) {
PathConstraint constraint = pathConstraints.get(i);
// BOZO! - All bones any paths in the target slot are weighted to must come before the path constraint.
Bone target = constraint.target.bone;
sortBone(target);
@ -215,7 +217,7 @@ public class Skeleton {
Bone target = constraint.target;
sortBone(target);
// BOZO - Update transform constraints to support multiple constrained bones.
// BOZO! - Update transform constraints to support multiple constrained bones.
// Array<Bone> constrained = constraint.bones;
// int boneCount = constrained.size;
// for (int ii = 0; ii < boneCount; ii++)
@ -235,6 +237,8 @@ public class Skeleton {
for (int i = 0, n = bones.size; i < n; i++)
sortBone(bones.get(i));
System.out.println(updateCache);
}
private void sortBone (Bone bone) {

View File

@ -57,6 +57,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
import com.esotericsoftware.spine.Animation.Timeline;
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
import com.esotericsoftware.spine.Animation.TranslateTimeline;
import com.esotericsoftware.spine.PathConstraintData.PositionMode;
import com.esotericsoftware.spine.PathConstraintData.RotateMode;
import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
import com.esotericsoftware.spine.SkeletonJson.LinkedMesh;
@ -188,6 +189,17 @@ public class SkeletonBinary {
skeletonData.bones.add(data);
}
// Slots.
for (int i = 0, n = input.readInt(true); i < n; i++) {
String slotName = input.readString();
BoneData boneData = skeletonData.bones.get(input.readInt(true));
SlotData data = new SlotData(i, slotName, boneData);
Color.rgba8888ToColor(data.color, input.readInt());
data.attachmentName = input.readString();
data.blendMode = BlendMode.values[input.readInt(true)];
skeletonData.slots.add(data);
}
// IK constraints.
for (int i = 0, n = input.readInt(true); i < n; i++) {
IkConstraintData data = new IkConstraintData(input.readString());
@ -223,27 +235,17 @@ public class SkeletonBinary {
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));
data.positionMode = PositionMode.values[input.readInt(true)];
data.spacingMode = SpacingMode.values[input.readInt(true)];
data.rotateMode = RotateMode.values[input.readInt(true)];
data.offsetRotation = input.readFloat();
data.position = input.readFloat();
data.spacing = input.readFloat();
data.spacingMode = SpacingMode.values[input.readInt(true)];
data.rotateMode = RotateMode.values[input.readInt(true)];
data.rotateMix = input.readFloat();
data.translateMix = input.readFloat();
skeletonData.pathConstraints.add(data);
}
// Slots.
for (int i = 0, n = input.readInt(true); i < n; i++) {
String slotName = input.readString();
BoneData boneData = skeletonData.bones.get(input.readInt(true));
SlotData data = new SlotData(i, slotName, boneData);
Color.rgba8888ToColor(data.color, input.readInt());
data.attachmentName = input.readString();
data.blendMode = BlendMode.values[input.readInt(true)];
skeletonData.slots.add(data);
}
// Default skin.
Skin defaultSkin = readSkin(input, "default", nonessential);
if (defaultSkin != null) {
@ -422,15 +424,25 @@ public class SkeletonBinary {
return mesh;
}
case path: {
boolean closed = input.readBoolean();
boolean constantSpeed = input.readBoolean();
int vertexCount = input.readInt(true);
Vertices vertices = readVertices(input, vertexCount);
float length = input.readFloat();
float[] curveLengths = new float[vertexCount / 3];
for (int i = 0, n = curveLengths.length; i < n; i++)
curveLengths[i] = input.readFloat();
int color = nonessential ? input.readInt() : 0;
PathAttachment path = attachmentLoader.newPathAttachment(skin, name);
if (path == null) return null;
path.setClosed(closed);
path.setConstantSpeed(constantSpeed);
path.setLength(length);
path.setWorldVerticesLength(vertexCount << 1);
path.setVertices(vertices.vertices);
path.setBones(vertices.bones);
path.getCurveLengths().addAll(curveLengths);
if (nonessential) Color.rgba8888ToColor(path.getColor(), color);
return path;
}

View File

@ -56,6 +56,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
import com.esotericsoftware.spine.Animation.Timeline;
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
import com.esotericsoftware.spine.Animation.TranslateTimeline;
import com.esotericsoftware.spine.PathConstraintData.PositionMode;
import com.esotericsoftware.spine.PathConstraintData.RotateMode;
import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader;
@ -137,6 +138,22 @@ public class SkeletonJson {
skeletonData.bones.add(data);
}
// Slots.
for (JsonValue slotMap = root.getChild("slots"); slotMap != null; slotMap = slotMap.next) {
String slotName = slotMap.getString("name");
String boneName = slotMap.getString("bone");
BoneData boneData = skeletonData.findBone(boneName);
if (boneData == null) throw new SerializationException("Slot bone not found: " + boneName);
SlotData data = new SlotData(skeletonData.slots.size, slotName, boneData);
String color = slotMap.getString("color", null);
if (color != null) data.getColor().set(Color.valueOf(color));
data.attachmentName = slotMap.getString("attachment", null);
data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name()));
skeletonData.slots.add(data);
}
// IK constraints.
for (JsonValue constraintMap = root.getChild("ik"); constraintMap != null; constraintMap = constraintMap.next) {
IkConstraintData data = new IkConstraintData(constraintMap.getString("name"));
@ -200,33 +217,18 @@ public class SkeletonJson {
data.target = skeletonData.findSlot(targetName);
if (data.target == null) throw new SerializationException("Target slot not found: " + targetName);
data.positionMode = PositionMode.valueOf(constraintMap.getString("positionMode", "percent"));
data.spacingMode = SpacingMode.valueOf(constraintMap.getString("spacingMode", "length"));
data.rotateMode = RotateMode.valueOf(constraintMap.getString("rotateMode", "tangent"));
data.offsetRotation = constraintMap.getFloat("rotation", 0);
data.position = constraintMap.getFloat("position", 0);
data.spacing = constraintMap.getFloat("spacing", 0);
data.spacingMode = SpacingMode.valueOf(constraintMap.getString("spacingMode", "length"));
data.rotateMode = RotateMode.valueOf(constraintMap.getString("rotateMode", "tangent"));
data.rotateMix = constraintMap.getFloat("rotateMix", 1);
data.translateMix = constraintMap.getFloat("translateMix", 1);
skeletonData.pathConstraints.add(data);
}
// Slots.
for (JsonValue slotMap = root.getChild("slots"); slotMap != null; slotMap = slotMap.next) {
String slotName = slotMap.getString("name");
String boneName = slotMap.getString("bone");
BoneData boneData = skeletonData.findBone(boneName);
if (boneData == null) throw new SerializationException("Slot bone not found: " + boneName);
SlotData data = new SlotData(skeletonData.slots.size, slotName, boneData);
String color = slotMap.getString("color", null);
if (color != null) data.getColor().set(Color.valueOf(color));
data.attachmentName = slotMap.getString("attachment", null);
data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name()));
skeletonData.slots.add(data);
}
// Skins.
for (JsonValue skinMap = root.getChild("skins"); skinMap != null; skinMap = skinMap.next) {
Skin skin = new Skin(skinMap.name);
@ -349,7 +351,17 @@ public class SkeletonJson {
case path: {
PathAttachment path = attachmentLoader.newPathAttachment(skin, name);
if (path == null) return null;
readVertices(map, path, map.getInt("vertexCount") << 1);
path.setClosed(map.getBoolean("closed", false));
path.setConstantSpeed(map.getBoolean("constantSpeed", true));
path.setLength(map.getFloat("length"));
int vertexCount = map.getInt("vertexCount");
readVertices(map, path, vertexCount << 1);
float[] curveLengths = path.getCurveLengths().setSize(vertexCount / 3);
int i = 0;
for (JsonValue curves = map.get("curves").child; curves != null; curves = curves.next)
curveLengths[i++] = curves.asFloat();
String color = map.getString("color", null);
if (color != null) path.getColor().set(Color.valueOf(color));
@ -519,8 +531,8 @@ public class SkeletonJson {
timeline = new PathConstraintPositionTimeline(timelineMap.size);
timeline.pathConstraintIndex = index;
int frameIndex = 0;
for (JsonValue valueMap = constraintMap.child; valueMap != null; valueMap = valueMap.next) {
timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getFloat(timelineName, 1));
for (JsonValue valueMap = timelineMap.child; valueMap != null; valueMap = valueMap.next) {
timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getFloat(timelineName, 0));
readCurve(valueMap, timeline, frameIndex);
frameIndex++;
}
@ -531,7 +543,7 @@ public class SkeletonJson {
PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(timelineMap.size);
timeline.pathConstraintIndex = index;
int frameIndex = 0;
for (JsonValue valueMap = constraintMap.child; valueMap != null; valueMap = valueMap.next) {
for (JsonValue valueMap = timelineMap.child; valueMap != null; valueMap = valueMap.next) {
timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getFloat("rotateMix", 1),
valueMap.getFloat("translateMix", 1));
readCurve(valueMap, timeline, frameIndex);

View File

@ -36,7 +36,7 @@ import com.badlogic.gdx.utils.FloatArray;
import com.esotericsoftware.spine.Slot;
public class PathAttachment extends VertexAttachment {
float totalLength;
float length;
final FloatArray lengths = new FloatArray();
boolean closed, constantSpeed;
@ -72,15 +72,15 @@ public class PathAttachment extends VertexAttachment {
}
/** Returns the length of the path in the setup pose. */
public float getTotalLength () {
return totalLength;
public float getLength () {
return length;
}
public void setTotalLength (float totalLength) {
this.totalLength = totalLength;
public void setLength (float totalLength) {
this.length = totalLength;
}
/** Returns the length of each curve in the setup pose. */
/** Returns the distance in the setup pose from the start of the path to the end of each curve. */
public FloatArray getCurveLengths () {
return lengths;
}