mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
JSON and binary path attachment and constraint loading.
This commit is contained in:
parent
a6ccff5fde
commit
40950eded7
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user