mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-25 22:23:42 +08:00
[libgdx] Added DrawOrderFolderTimeline.
This commit is contained in:
parent
516518b2d9
commit
cf45806bdd
@ -1,26 +1,65 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine.utils;
|
package com.esotericsoftware.spine.utils;
|
||||||
|
|
||||||
import com.esotericsoftware.spine.*;
|
import java.util.HashMap;
|
||||||
import com.esotericsoftware.spine.Animation.*;
|
import java.util.Map;
|
||||||
import com.esotericsoftware.spine.AnimationState.*;
|
|
||||||
import com.esotericsoftware.spine.BoneData.Inherit;
|
|
||||||
import com.esotericsoftware.spine.Skin.SkinEntry;
|
|
||||||
import com.esotericsoftware.spine.PathConstraintData.*;
|
|
||||||
import com.esotericsoftware.spine.TransformConstraintData.*;
|
|
||||||
import com.esotericsoftware.spine.attachments.*;
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.IntArray;
|
|
||||||
import com.badlogic.gdx.utils.FloatArray;
|
import com.badlogic.gdx.utils.FloatArray;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
|
|
||||||
import java.util.Locale;
|
import com.esotericsoftware.spine.Animation;
|
||||||
import java.util.Map;
|
import com.esotericsoftware.spine.Animation.Timeline;
|
||||||
import java.util.HashMap;
|
import com.esotericsoftware.spine.AnimationState;
|
||||||
|
import com.esotericsoftware.spine.AnimationState.TrackEntry;
|
||||||
|
import com.esotericsoftware.spine.AnimationStateData;
|
||||||
|
import com.esotericsoftware.spine.Bone;
|
||||||
|
import com.esotericsoftware.spine.BoneData;
|
||||||
|
import com.esotericsoftware.spine.BoneLocal;
|
||||||
|
import com.esotericsoftware.spine.BonePose;
|
||||||
|
import com.esotericsoftware.spine.Constraint;
|
||||||
|
import com.esotericsoftware.spine.ConstraintData;
|
||||||
|
import com.esotericsoftware.spine.Event;
|
||||||
|
import com.esotericsoftware.spine.EventData;
|
||||||
|
import com.esotericsoftware.spine.IkConstraint;
|
||||||
|
import com.esotericsoftware.spine.IkConstraintData;
|
||||||
|
import com.esotericsoftware.spine.IkConstraintPose;
|
||||||
|
import com.esotericsoftware.spine.PathConstraint;
|
||||||
|
import com.esotericsoftware.spine.PathConstraintData;
|
||||||
|
import com.esotericsoftware.spine.PathConstraintPose;
|
||||||
|
import com.esotericsoftware.spine.PhysicsConstraint;
|
||||||
|
import com.esotericsoftware.spine.PhysicsConstraintData;
|
||||||
|
import com.esotericsoftware.spine.PhysicsConstraintPose;
|
||||||
|
import com.esotericsoftware.spine.Skeleton;
|
||||||
|
import com.esotericsoftware.spine.SkeletonData;
|
||||||
|
import com.esotericsoftware.spine.Skin;
|
||||||
|
import com.esotericsoftware.spine.Skin.SkinEntry;
|
||||||
|
import com.esotericsoftware.spine.Slider;
|
||||||
|
import com.esotericsoftware.spine.SliderData;
|
||||||
|
import com.esotericsoftware.spine.SliderPose;
|
||||||
|
import com.esotericsoftware.spine.Slot;
|
||||||
|
import com.esotericsoftware.spine.SlotData;
|
||||||
|
import com.esotericsoftware.spine.SlotPose;
|
||||||
|
import com.esotericsoftware.spine.TransformConstraint;
|
||||||
|
import com.esotericsoftware.spine.TransformConstraintData;
|
||||||
|
import com.esotericsoftware.spine.TransformConstraintData.FromProperty;
|
||||||
|
import com.esotericsoftware.spine.TransformConstraintData.ToProperty;
|
||||||
|
import com.esotericsoftware.spine.TransformConstraintPose;
|
||||||
|
import com.esotericsoftware.spine.Update;
|
||||||
|
import com.esotericsoftware.spine.attachments.Attachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.ClippingAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.PathAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.PointAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||||
|
import com.esotericsoftware.spine.attachments.Sequence;
|
||||||
|
import com.esotericsoftware.spine.attachments.VertexAttachment;
|
||||||
|
|
||||||
public class SkeletonSerializer {
|
public class SkeletonSerializer {
|
||||||
private final Map<Object, String> visitedObjects = new HashMap<>();
|
private final Map<Object, String> visitedObjects = new HashMap();
|
||||||
private int nextId = 1;
|
private int nextId = 1;
|
||||||
private JsonWriter json;
|
private JsonWriter json;
|
||||||
|
|
||||||
@ -3271,7 +3310,7 @@ public class SkeletonSerializer {
|
|||||||
json.writeValue("Skin");
|
json.writeValue("Skin");
|
||||||
|
|
||||||
json.writeName("attachments");
|
json.writeName("attachments");
|
||||||
Array<SkinEntry> sortedAttachments = new Array<>(obj.getAttachments());
|
var sortedAttachments = new Array<SkinEntry>(obj.getAttachments());
|
||||||
sortedAttachments.sort( (a, b) -> Integer.compare(a.getSlotIndex(), b.getSlotIndex()));
|
sortedAttachments.sort( (a, b) -> Integer.compare(a.getSlotIndex(), b.getSlotIndex()));
|
||||||
json.writeArrayStart();
|
json.writeArrayStart();
|
||||||
for (SkinEntry item : sortedAttachments) {
|
for (SkinEntry item : sortedAttachments) {
|
||||||
|
|||||||
@ -1880,8 +1880,7 @@ public class Animation {
|
|||||||
/** Sets the time and draw order for the specified frame.
|
/** Sets the time and draw order for the specified frame.
|
||||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||||
* @param time The frame time in seconds.
|
* @param time The frame time in seconds.
|
||||||
* @param drawOrder For each slot in {@link Skeleton#slots}, the index of the slot in the new draw order. May be null to use
|
* @param drawOrder Ordered {@link Skeleton#slots} indices, or null to use setup pose order. */
|
||||||
* setup pose draw order. */
|
|
||||||
public void setFrame (int frame, float time, @Null int[] drawOrder) {
|
public void setFrame (int frame, float time, @Null int[] drawOrder) {
|
||||||
frames[frame] = time;
|
frames[frame] = time;
|
||||||
drawOrders[frame] = drawOrder;
|
drawOrders[frame] = drawOrder;
|
||||||
@ -1913,6 +1912,87 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Changes a subset of a skeleton's {@link Skeleton#getDrawOrder()}. */
|
||||||
|
static public class DrawOrderFolderTimeline extends Timeline {
|
||||||
|
private final int[] slots;
|
||||||
|
private final boolean[] inFolder;
|
||||||
|
private final int[][] drawOrders;
|
||||||
|
|
||||||
|
/** @param slots {@link Skeleton#getSlots()} indices controlled by this timeline, in setup order.
|
||||||
|
* @param slotCount The maximum number of slots in the skeleton. */
|
||||||
|
public DrawOrderFolderTimeline (int frameCount, int[] slots, int slotCount) {
|
||||||
|
super(frameCount, DrawOrderTimeline.propertyIds);
|
||||||
|
this.slots = slots;
|
||||||
|
drawOrders = new int[frameCount][];
|
||||||
|
inFolder = new boolean[slotCount];
|
||||||
|
for (int i : slots)
|
||||||
|
inFolder[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFrameCount () {
|
||||||
|
return frames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The {@link Skeleton#getSlots()} indices that this timeline affects, in setup order. */
|
||||||
|
public int[] getSlots () {
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The draw order for each frame. See {@link #setFrame(int, float, int[])}. */
|
||||||
|
public int[][] getDrawOrders () {
|
||||||
|
return drawOrders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the time and draw order for the specified frame.
|
||||||
|
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||||
|
* @param time The frame time in seconds.
|
||||||
|
* @param drawOrder Ordered {@link #getSlots()} indices, or null to use setup pose order. */
|
||||||
|
public void setFrame (int frame, float time, @Null int[] drawOrder) {
|
||||||
|
frames[frame] = time;
|
||||||
|
drawOrders[frame] = drawOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||||
|
MixDirection direction, boolean appliedPose) {
|
||||||
|
|
||||||
|
if (direction == out) {
|
||||||
|
if (blend == setup) setup(skeleton);
|
||||||
|
} else if (time < frames[0]) {
|
||||||
|
if (blend == setup || blend == first) setup(skeleton);
|
||||||
|
} else {
|
||||||
|
int[] order = drawOrders[search(frames, time)];
|
||||||
|
if (order == null)
|
||||||
|
setup(skeleton);
|
||||||
|
else
|
||||||
|
apply(skeleton, order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setup (Skeleton skeleton) {
|
||||||
|
boolean[] inFolder = this.inFolder;
|
||||||
|
Slot[] drawOrder = skeleton.drawOrder.items, allSlots = skeleton.slots.items;
|
||||||
|
int[] slots = this.slots;
|
||||||
|
for (int i = 0, found = 0, done = slots.length;; i++) {
|
||||||
|
if (inFolder[drawOrder[i].data.index]) {
|
||||||
|
drawOrder[i] = allSlots[slots[found]];
|
||||||
|
if (++found == done) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply (Skeleton skeleton, int[] order) {
|
||||||
|
boolean[] inFolder = this.inFolder;
|
||||||
|
Slot[] drawOrder = skeleton.drawOrder.items, allSlots = skeleton.slots.items;
|
||||||
|
int[] slots = this.slots;
|
||||||
|
for (int i = 0, found = 0, done = slots.length;; i++) {
|
||||||
|
if (inFolder[drawOrder[i].data.index]) {
|
||||||
|
drawOrder[i] = allSlots[slots[order[found]]];
|
||||||
|
if (++found == done) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static public interface ConstraintTimeline {
|
static public interface ConstraintTimeline {
|
||||||
/** The index of the constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is applied, or
|
/** The index of the constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is applied, or
|
||||||
* -1 if a specific constraint will not be changed. */
|
* -1 if a specific constraint will not be changed. */
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import com.badlogic.gdx.utils.Pool.Poolable;
|
|||||||
import com.badlogic.gdx.utils.SnapshotArray;
|
import com.badlogic.gdx.utils.SnapshotArray;
|
||||||
|
|
||||||
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||||
|
import com.esotericsoftware.spine.Animation.DrawOrderFolderTimeline;
|
||||||
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.MixBlend;
|
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||||
@ -807,7 +808,8 @@ public class AnimationState {
|
|||||||
if (!propertyIds.addAll(ids))
|
if (!propertyIds.addAll(ids))
|
||||||
timelineMode[i] = SUBSEQUENT;
|
timelineMode[i] = SUBSEQUENT;
|
||||||
else if (to == null || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline
|
else if (to == null || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline
|
||||||
|| timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) {
|
|| timeline instanceof DrawOrderFolderTimeline || timeline instanceof EventTimeline
|
||||||
|
|| !to.animation.hasTimeline(ids)) {
|
||||||
timelineMode[i] = FIRST;
|
timelineMode[i] = FIRST;
|
||||||
} else {
|
} else {
|
||||||
for (TrackEntry next = to.mixingTo; next != null; next = next.mixingTo) {
|
for (TrackEntry next = to.mixingTo; next != null; next = next.mixingTo) {
|
||||||
|
|||||||
@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
|
|||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
@ -47,6 +48,7 @@ import com.esotericsoftware.spine.Animation.BoneTimeline2;
|
|||||||
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.CurveTimeline1;
|
import com.esotericsoftware.spine.Animation.CurveTimeline1;
|
||||||
import com.esotericsoftware.spine.Animation.DeformTimeline;
|
import com.esotericsoftware.spine.Animation.DeformTimeline;
|
||||||
|
import com.esotericsoftware.spine.Animation.DrawOrderFolderTimeline;
|
||||||
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.IkConstraintTimeline;
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
@ -1160,34 +1162,26 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw order timeline.
|
// Draw order timeline.
|
||||||
|
int slotCount = skeletonData.slots.size;
|
||||||
int drawOrderCount = input.readInt(true);
|
int drawOrderCount = input.readInt(true);
|
||||||
if (drawOrderCount > 0) {
|
if (drawOrderCount > 0) {
|
||||||
var timeline = new DrawOrderTimeline(drawOrderCount);
|
var timeline = new DrawOrderTimeline(drawOrderCount);
|
||||||
int slotCount = skeletonData.slots.size;
|
for (int i = 0; i < drawOrderCount; i++)
|
||||||
for (int i = 0; i < drawOrderCount; i++) {
|
timeline.setFrame(i, input.readFloat(), readDrawOrder(input, slotCount));
|
||||||
float time = input.readFloat();
|
timelines.add(timeline);
|
||||||
int offsetCount = input.readInt(true);
|
}
|
||||||
var drawOrder = new int[slotCount];
|
|
||||||
for (int ii = slotCount - 1; ii >= 0; ii--)
|
// Draw order folder timelines.
|
||||||
drawOrder[ii] = -1;
|
int folderCount = input.readInt(true);
|
||||||
var unchanged = new int[slotCount - offsetCount];
|
for (int i = 0; i < folderCount; i++) {
|
||||||
int originalIndex = 0, unchangedIndex = 0;
|
int folderSlotCount = input.readInt(true);
|
||||||
for (int ii = 0; ii < offsetCount; ii++) {
|
var folderSlots = new int[folderSlotCount];
|
||||||
int slotIndex = input.readInt(true);
|
for (int ii = 0; ii < folderSlotCount; ii++)
|
||||||
// Collect unchanged items.
|
folderSlots[ii] = input.readInt(true);
|
||||||
while (originalIndex != slotIndex)
|
int keyCount = input.readInt(true);
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
var timeline = new DrawOrderFolderTimeline(keyCount, folderSlots, slotCount);
|
||||||
// Set changed items.
|
for (int ii = 0; ii < keyCount; ii++)
|
||||||
drawOrder[originalIndex + input.readInt(true)] = originalIndex++;
|
timeline.setFrame(ii, input.readFloat(), readDrawOrder(input, folderSlotCount));
|
||||||
}
|
|
||||||
// Collect remaining unchanged items.
|
|
||||||
while (originalIndex < slotCount)
|
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
|
||||||
// Fill in unchanged items.
|
|
||||||
for (int ii = slotCount - 1; ii >= 0; ii--)
|
|
||||||
if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
|
|
||||||
timeline.setFrame(i, time, drawOrder);
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1257,6 +1251,30 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @Null int[] readDrawOrder (SkeletonInput input, int slotCount) throws IOException {
|
||||||
|
int changeCount = input.readInt(true);
|
||||||
|
if (changeCount == 0) return null;
|
||||||
|
var drawOrder = new int[slotCount];
|
||||||
|
Arrays.fill(drawOrder, -1);
|
||||||
|
var unchanged = new int[slotCount - changeCount];
|
||||||
|
int originalIndex = 0, unchangedIndex = 0;
|
||||||
|
for (int i = 0; i < changeCount; i++) {
|
||||||
|
int slotIndex = input.readInt(true);
|
||||||
|
// Collect unchanged items.
|
||||||
|
while (originalIndex != slotIndex)
|
||||||
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
// Set changed items.
|
||||||
|
drawOrder[originalIndex + input.readInt(true)] = originalIndex++;
|
||||||
|
}
|
||||||
|
// Collect remaining unchanged items.
|
||||||
|
while (originalIndex < slotCount)
|
||||||
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
// Fill in unchanged items.
|
||||||
|
for (int i = slotCount - 1; i >= 0; i--)
|
||||||
|
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||||
|
return drawOrder;
|
||||||
|
}
|
||||||
|
|
||||||
void setBezier (SkeletonInput input, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2,
|
void setBezier (SkeletonInput input, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2,
|
||||||
float value1, float value2, float scale) throws IOException {
|
float value1, float value2, float scale) throws IOException {
|
||||||
timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(),
|
timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(),
|
||||||
|
|||||||
@ -32,6 +32,7 @@ package com.esotericsoftware.spine;
|
|||||||
import static com.esotericsoftware.spine.utils.SpineUtils.*;
|
import static com.esotericsoftware.spine.utils.SpineUtils.*;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
@ -50,6 +51,7 @@ import com.esotericsoftware.spine.Animation.BoneTimeline2;
|
|||||||
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.CurveTimeline1;
|
import com.esotericsoftware.spine.Animation.CurveTimeline1;
|
||||||
import com.esotericsoftware.spine.Animation.DeformTimeline;
|
import com.esotericsoftware.spine.Animation.DeformTimeline;
|
||||||
|
import com.esotericsoftware.spine.Animation.DrawOrderFolderTimeline;
|
||||||
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.IkConstraintTimeline;
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
@ -464,7 +466,7 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
skin.constraints.shrink();
|
skin.constraints.shrink();
|
||||||
for (JsonValue slotEntry = skinMap.getChild("attachments"); slotEntry != null; slotEntry = slotEntry.next) {
|
for (JsonValue slotEntry = skinMap.getChild("attachments"); slotEntry != null; slotEntry = slotEntry.next) {
|
||||||
SlotData slot = skeletonData.findSlot(slotEntry.name);
|
SlotData slot = skeletonData.findSlot(slotEntry.name);
|
||||||
if (slot == null) throw new SerializationException("Slot not found: " + slotEntry.name);
|
if (slot == null) throw new SerializationException("Skin slot not found: " + slotEntry.name);
|
||||||
for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) {
|
for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) {
|
||||||
try {
|
try {
|
||||||
Attachment attachment = readAttachment(entry, skin, slot.index, entry.name, skeletonData);
|
Attachment attachment = readAttachment(entry, skin, slot.index, entry.name, skeletonData);
|
||||||
@ -1136,7 +1138,7 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
if (skin == null) throw new SerializationException("Skin not found: " + attachmentsMap.name);
|
if (skin == null) throw new SerializationException("Skin not found: " + attachmentsMap.name);
|
||||||
for (JsonValue slotMap = attachmentsMap.child; slotMap != null; slotMap = slotMap.next) {
|
for (JsonValue slotMap = attachmentsMap.child; slotMap != null; slotMap = slotMap.next) {
|
||||||
SlotData slot = skeletonData.findSlot(slotMap.name);
|
SlotData slot = skeletonData.findSlot(slotMap.name);
|
||||||
if (slot == null) throw new SerializationException("Slot not found: " + slotMap.name);
|
if (slot == null) throw new SerializationException("Attachment slot not found: " + slotMap.name);
|
||||||
for (JsonValue attachmentMap = slotMap.child; attachmentMap != null; attachmentMap = attachmentMap.next) {
|
for (JsonValue attachmentMap = slotMap.child; attachmentMap != null; attachmentMap = attachmentMap.next) {
|
||||||
Attachment attachment = skin.getAttachment(slot.index, attachmentMap.name);
|
Attachment attachment = skin.getAttachment(slot.index, attachmentMap.name);
|
||||||
if (attachment == null) throw new SerializationException("Timeline attachment not found: " + attachmentMap.name);
|
if (attachment == null) throw new SerializationException("Timeline attachment not found: " + attachmentMap.name);
|
||||||
@ -1206,38 +1208,35 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
JsonValue drawOrderMap = map.get("drawOrder");
|
JsonValue drawOrderMap = map.get("drawOrder");
|
||||||
if (drawOrderMap != null) {
|
if (drawOrderMap != null) {
|
||||||
var timeline = new DrawOrderTimeline(drawOrderMap.size);
|
var timeline = new DrawOrderTimeline(drawOrderMap.size);
|
||||||
int slotCount = skeletonData.slots.size;
|
int slotCount = skeletonData.slots.size, frame = 0;
|
||||||
int frame = 0;
|
for (JsonValue keyMap = drawOrderMap.child; keyMap != null; keyMap = keyMap.next, frame++)
|
||||||
for (JsonValue keyMap = drawOrderMap.child; keyMap != null; keyMap = keyMap.next, frame++) {
|
timeline.setFrame(frame, keyMap.getFloat("time", 0), readDrawOrder(skeletonData, keyMap, slotCount, null));
|
||||||
int[] drawOrder = null;
|
|
||||||
JsonValue offsets = keyMap.get("offsets");
|
|
||||||
if (offsets != null) {
|
|
||||||
drawOrder = new int[slotCount];
|
|
||||||
for (int i = slotCount - 1; i >= 0; i--)
|
|
||||||
drawOrder[i] = -1;
|
|
||||||
var unchanged = new int[slotCount - offsets.size];
|
|
||||||
int originalIndex = 0, unchangedIndex = 0;
|
|
||||||
for (JsonValue offsetMap = offsets.child; offsetMap != null; offsetMap = offsetMap.next) {
|
|
||||||
SlotData slot = skeletonData.findSlot(offsetMap.getString("slot"));
|
|
||||||
if (slot == null) throw new SerializationException("Slot not found: " + offsetMap.getString("slot"));
|
|
||||||
// Collect unchanged items.
|
|
||||||
while (originalIndex != slot.index)
|
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
|
||||||
// Set changed items.
|
|
||||||
drawOrder[originalIndex + offsetMap.getInt("offset")] = originalIndex++;
|
|
||||||
}
|
|
||||||
// Collect remaining unchanged items.
|
|
||||||
while (originalIndex < slotCount)
|
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
|
||||||
// Fill in unchanged items.
|
|
||||||
for (int i = slotCount - 1; i >= 0; i--)
|
|
||||||
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
|
||||||
}
|
|
||||||
timeline.setFrame(frame, keyMap.getFloat("time", 0), drawOrder);
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw order folder timelines.
|
||||||
|
JsonValue drawOrderFoldersMap = map.get("drawOrderFolder");
|
||||||
|
if (drawOrderFoldersMap != null) {
|
||||||
|
for (JsonValue timelineMap = drawOrderFoldersMap.child; timelineMap != null; timelineMap = timelineMap.next) {
|
||||||
|
JsonValue slotEntry = timelineMap.get("slots");
|
||||||
|
var folderSlots = new int[slotEntry.size];
|
||||||
|
int ii = 0;
|
||||||
|
for (slotEntry = slotEntry.child; slotEntry != null; slotEntry = slotEntry.next, ii++) {
|
||||||
|
SlotData slot = skeletonData.findSlot(slotEntry.asString());
|
||||||
|
if (slot == null) throw new SerializationException("Draw order folder slot not found: " + slotEntry.asString());
|
||||||
|
folderSlots[ii] = slot.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue keyMap = timelineMap.get("keys");
|
||||||
|
var timeline = new DrawOrderFolderTimeline(keyMap.size, folderSlots, skeletonData.slots.size);
|
||||||
|
int frame = 0;
|
||||||
|
for (keyMap = keyMap.child; keyMap != null; keyMap = keyMap.next, frame++)
|
||||||
|
timeline.setFrame(frame, keyMap.getFloat("time", 0),
|
||||||
|
readDrawOrder(skeletonData, keyMap, folderSlots.length, folderSlots));
|
||||||
|
timelines.add(timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Event timeline.
|
// Event timeline.
|
||||||
JsonValue eventsMap = map.get("events");
|
JsonValue eventsMap = map.get("events");
|
||||||
if (eventsMap != null) {
|
if (eventsMap != null) {
|
||||||
@ -1314,6 +1313,45 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param folderSlots Slot names are resolved to positions within this array. If null, slot indices are used as positions. */
|
||||||
|
private @Null int[] readDrawOrder (SkeletonData skeletonData, JsonValue keyMap, int slotCount, @Null int[] folderSlots) {
|
||||||
|
JsonValue changes = keyMap.get("offsets");
|
||||||
|
if (changes == null) return null; // Setup draw order.
|
||||||
|
var drawOrder = new int[slotCount];
|
||||||
|
Arrays.fill(drawOrder, -1);
|
||||||
|
var unchanged = new int[slotCount - changes.size];
|
||||||
|
int originalIndex = 0, unchangedIndex = 0;
|
||||||
|
for (JsonValue offsetMap = changes.child; offsetMap != null; offsetMap = offsetMap.next) {
|
||||||
|
SlotData slot = skeletonData.findSlot(offsetMap.getString("slot"));
|
||||||
|
if (slot == null) throw new SerializationException("Draw order slot not found: " + offsetMap.getString("slot"));
|
||||||
|
int index;
|
||||||
|
if (folderSlots == null)
|
||||||
|
index = slot.index;
|
||||||
|
else {
|
||||||
|
index = -1;
|
||||||
|
for (int i = 0; i < slotCount; i++) {
|
||||||
|
if (folderSlots[i] == slot.index) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == -1) throw new SerializationException("Slot not in folder: " + offsetMap.getString("slot"));
|
||||||
|
}
|
||||||
|
// Collect unchanged items.
|
||||||
|
while (originalIndex != index)
|
||||||
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
// Set changed items.
|
||||||
|
drawOrder[originalIndex + offsetMap.getInt("offset")] = originalIndex++;
|
||||||
|
}
|
||||||
|
// Collect remaining unchanged items.
|
||||||
|
while (originalIndex < slotCount)
|
||||||
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
// Fill in unchanged items.
|
||||||
|
for (int i = slotCount - 1; i >= 0; i--)
|
||||||
|
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||||
|
return drawOrder;
|
||||||
|
}
|
||||||
|
|
||||||
int readCurve (JsonValue curve, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2,
|
int readCurve (JsonValue curve, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2,
|
||||||
float value1, float value2, float scale) {
|
float value1, float value2, float scale) {
|
||||||
if (curve.isString()) {
|
if (curve.isString()) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user