mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 15:24:55 +08:00
Keyable draw order and other fixes.
This commit is contained in:
parent
9ffb689b49
commit
f174b1a3cb
@ -522,6 +522,10 @@ public class Animation {
|
||||
return frames;
|
||||
}
|
||||
|
||||
public Event[] getEvents () {
|
||||
return events;
|
||||
}
|
||||
|
||||
/** Sets the time of the specified keyframe. */
|
||||
public void setFrame (int frameIndex, float time, Event event) {
|
||||
frames[frameIndex] = time;
|
||||
@ -548,4 +552,49 @@ public class Animation {
|
||||
firedEvents.add(events[frameIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
static public class DrawOrderTimeline implements Timeline {
|
||||
private final float[] frames; // time, ...
|
||||
private final int[][] drawOrders;
|
||||
|
||||
public DrawOrderTimeline (int frameCount) {
|
||||
frames = new float[frameCount];
|
||||
drawOrders = new int[frameCount][];
|
||||
}
|
||||
|
||||
public int getFrameCount () {
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
public float[] getFrames () {
|
||||
return frames;
|
||||
}
|
||||
|
||||
public int[][] getDrawOrders () {
|
||||
return drawOrders;
|
||||
}
|
||||
|
||||
/** Sets the time of the specified keyframe. */
|
||||
public void setFrame (int frameIndex, float time, int[] drawOrder) {
|
||||
frames[frameIndex] = time;
|
||||
drawOrders[frameIndex] = drawOrder;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, float alpha, Array<Event> firedEvents) {
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
int frameIndex;
|
||||
if (time >= frames[frames.length - 1]) // Time is after last frame.
|
||||
frameIndex = frames.length - 1;
|
||||
else
|
||||
frameIndex = binarySearch(frames, time, 1) - 1;
|
||||
|
||||
Array<Slot> drawOrder = skeleton.drawOrder;
|
||||
Array<Slot> slots = skeleton.slots;
|
||||
int[] drawOrderToSetupIndex = drawOrders[frameIndex];
|
||||
for (int i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
|
||||
drawOrder.set(i, slots.get(drawOrderToSetupIndex[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ public class Skeleton {
|
||||
final SkeletonData data;
|
||||
final Array<Bone> bones;
|
||||
final Array<Slot> slots;
|
||||
final Array<Slot> drawOrder;
|
||||
Array<Slot> drawOrder;
|
||||
Skin skin;
|
||||
final Color color;
|
||||
float time;
|
||||
@ -112,6 +112,8 @@ public class Skeleton {
|
||||
}
|
||||
|
||||
public void setSlotsToSetupPose () {
|
||||
drawOrder.clear();
|
||||
drawOrder.addAll(slots);
|
||||
Array<Slot> slots = this.slots;
|
||||
for (int i = 0, n = slots.size; i < n; i++)
|
||||
slots.get(i).setToSetupPose(i);
|
||||
@ -180,6 +182,11 @@ public class Skeleton {
|
||||
return drawOrder;
|
||||
}
|
||||
|
||||
/** Sets the slots and the order they will be drawn. */
|
||||
public void setDrawOrder (Array<Slot> drawOrder) {
|
||||
this.drawOrder = drawOrder;
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Skin getSkin () {
|
||||
return skin;
|
||||
|
||||
@ -28,6 +28,7 @@ package com.esotericsoftware.spine;
|
||||
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ColorTimeline;
|
||||
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||
@ -46,6 +47,7 @@ import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.DataInput;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -57,6 +59,7 @@ public class SkeletonBinary {
|
||||
static public final int TIMELINE_ATTACHMENT = 3;
|
||||
static public final int TIMELINE_COLOR = 4;
|
||||
static public final int TIMELINE_EVENT = 5;
|
||||
static public final int TIMELINE_DRAWORDER = 6;
|
||||
|
||||
static public final int CURVE_LINEAR = 0;
|
||||
static public final int CURVE_STEPPED = 1;
|
||||
@ -96,11 +99,8 @@ public class SkeletonBinary {
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
String name = input.readString();
|
||||
BoneData parent = null;
|
||||
String parentName = input.readString();
|
||||
if (parentName != null) {
|
||||
parent = skeletonData.findBone(parentName);
|
||||
if (parent == null) throw new SerializationException("Parent bone not found: " + parentName);
|
||||
}
|
||||
int parentIndex = input.readInt(true) - 1;
|
||||
if (parentIndex != -1) parent = skeletonData.bones.get(parentIndex);
|
||||
BoneData boneData = new BoneData(name, parent);
|
||||
boneData.x = input.readFloat() * scale;
|
||||
boneData.y = input.readFloat() * scale;
|
||||
@ -116,9 +116,7 @@ public class SkeletonBinary {
|
||||
// Slots.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
String slotName = input.readString();
|
||||
String boneName = input.readString();
|
||||
BoneData boneData = skeletonData.findBone(boneName);
|
||||
if (boneData == null) throw new SerializationException("Bone not found: " + boneName);
|
||||
BoneData boneData = skeletonData.bones.get(input.readInt(true));
|
||||
SlotData slotData = new SlotData(slotName, boneData);
|
||||
Color.rgba8888ToColor(slotData.getColor(), input.readInt());
|
||||
slotData.attachmentName = input.readString();
|
||||
@ -215,9 +213,7 @@ public class SkeletonBinary {
|
||||
try {
|
||||
int boneCount = input.readInt(true);
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
String boneName = input.readString();
|
||||
int boneIndex = skeletonData.findBoneIndex(boneName);
|
||||
if (boneIndex == -1) throw new SerializationException("Bone not found: " + boneName);
|
||||
int boneIndex = input.readInt(true);
|
||||
int itemCount = input.readInt(true);
|
||||
for (int ii = 0; ii < itemCount; ii++) {
|
||||
int timelineType = input.readByte();
|
||||
@ -253,16 +249,13 @@ public class SkeletonBinary {
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[keyCount * 3 - 3]);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Invalid timeline type for a bone: " + timelineType + " (" + boneName + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int slotCount = input.readInt(true);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
String slotName = input.readString();
|
||||
int slotIndex = skeletonData.findSlotIndex(slotName);
|
||||
int slotIndex = input.readInt(true);
|
||||
int itemCount = input.readInt(true);
|
||||
for (int ii = 0; ii < itemCount; ii++) {
|
||||
int timelineType = input.readByte();
|
||||
@ -289,8 +282,6 @@ public class SkeletonBinary {
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[keyCount - 1]);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Invalid timeline type for a slot: " + timelineType + " (" + slotName + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,15 +291,37 @@ public class SkeletonBinary {
|
||||
EventTimeline timeline = new EventTimeline(eventCount);
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
float time = input.readFloat();
|
||||
String eventName = input.readString();
|
||||
EventData eventData = skeletonData.findEvent(eventName);
|
||||
if (eventData == null) throw new SerializationException("Event not found: " + eventName);
|
||||
EventData eventData = skeletonData.eventDatas.get(input.readInt(true));
|
||||
Event event = new Event(eventData);
|
||||
event.intValue = input.readInt(false);
|
||||
event.floatValue = input.readFloat();
|
||||
event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue;
|
||||
timeline.setFrame(i, time, event);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[eventCount - 1]);
|
||||
}
|
||||
|
||||
int drawOrderCount = input.readInt(true);
|
||||
if (drawOrderCount > 0) {
|
||||
Array<SlotData> slots = skeletonData.slots;
|
||||
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
|
||||
for (int i = 0; i < drawOrderCount; i++) {
|
||||
IntArray drawOrder = new IntArray(slots.size);
|
||||
for (int ii = 0, n = slots.size; ii < n; ii++)
|
||||
drawOrder.add(ii);
|
||||
|
||||
int offsetCount = input.readInt(true);
|
||||
for (int ii = 0; ii < offsetCount; ii++) {
|
||||
int slotIndex = input.readInt(true);
|
||||
int index = drawOrder.indexOf(slotIndex);
|
||||
drawOrder.removeIndex(index);
|
||||
drawOrder.insert(index + input.readInt(true), slotIndex);
|
||||
}
|
||||
timeline.setFrame(i, input.readFloat(), drawOrder.toArray());
|
||||
}
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[drawOrderCount - 1]);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new SerializationException("Error reading skeleton file.", ex);
|
||||
|
||||
@ -28,6 +28,7 @@ package com.esotericsoftware.spine;
|
||||
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ColorTimeline;
|
||||
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||
@ -45,6 +46,7 @@ import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.JsonReader;
|
||||
import com.badlogic.gdx.utils.JsonValue;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
@ -127,6 +129,7 @@ public class SkeletonJson {
|
||||
Skin skin = new Skin(skinMap.name());
|
||||
for (JsonValue slotEntry = skinMap.child(); slotEntry != null; slotEntry = slotEntry.next()) {
|
||||
int slotIndex = skeletonData.findSlotIndex(slotEntry.name());
|
||||
if (slotIndex == -1) throw new SerializationException("Slot not found: " + slotEntry.name());
|
||||
for (JsonValue entry = slotEntry.child(); entry != null; entry = entry.next()) {
|
||||
Attachment attachment = readAttachment(skin, entry.name(), entry);
|
||||
if (attachment != null) skin.addAttachment(slotIndex, entry.name(), attachment);
|
||||
@ -240,6 +243,7 @@ public class SkeletonJson {
|
||||
|
||||
for (JsonValue slotMap = map.getChild("slots"); slotMap != null; slotMap = slotMap.next()) {
|
||||
int slotIndex = skeletonData.findSlotIndex(slotMap.name());
|
||||
if (slotIndex == -1) throw new SerializationException("Slot not found: " + slotMap.name());
|
||||
|
||||
for (JsonValue timelineMap = slotMap.child(); timelineMap != null; timelineMap = timelineMap.next()) {
|
||||
String timelineName = timelineMap.name();
|
||||
@ -292,6 +296,28 @@ public class SkeletonJson {
|
||||
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() - 1]);
|
||||
}
|
||||
|
||||
JsonValue drawOrdersMap = map.get("draworder");
|
||||
if (drawOrdersMap != null) {
|
||||
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrdersMap.size);
|
||||
Array<SlotData> slots = skeletonData.slots;
|
||||
int frameIndex = 0;
|
||||
for (JsonValue drawOrderMap = drawOrdersMap.child; drawOrderMap != null; drawOrderMap = drawOrderMap.next()) {
|
||||
IntArray drawOrder = new IntArray(slots.size);
|
||||
for (int i = 0, n = slots.size; i < n; i++)
|
||||
drawOrder.add(i);
|
||||
for (JsonValue offsetMap = drawOrderMap.getChild("offsets"); offsetMap != null; offsetMap = offsetMap.next()) {
|
||||
int slotIndex = skeletonData.findSlotIndex(offsetMap.getString("slot"));
|
||||
if (slotIndex == -1) throw new SerializationException("Slot not found: " + offsetMap.getString("slot"));
|
||||
int index = drawOrder.indexOf(slotIndex);
|
||||
drawOrder.removeIndex(index);
|
||||
drawOrder.insert(index + offsetMap.getInt("offset"), slotIndex);
|
||||
}
|
||||
timeline.setFrame(frameIndex++, drawOrderMap.getFloat("time"), drawOrder.toArray());
|
||||
}
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() - 1]);
|
||||
}
|
||||
|
||||
timelines.shrink();
|
||||
skeletonData.addAnimation(new Animation(name, timelines, duration));
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ public class Skin {
|
||||
|
||||
public void addAttachment (int slotIndex, String name, Attachment attachment) {
|
||||
if (attachment == null) throw new IllegalArgumentException("attachment cannot be null.");
|
||||
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
|
||||
Key key = new Key();
|
||||
key.set(slotIndex, name);
|
||||
attachments.put(key, attachment);
|
||||
@ -52,18 +53,21 @@ public class Skin {
|
||||
|
||||
/** @return May be null. */
|
||||
public Attachment getAttachment (int slotIndex, String name) {
|
||||
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
|
||||
lookup.set(slotIndex, name);
|
||||
return attachments.get(lookup);
|
||||
}
|
||||
|
||||
public void findNamesForSlot (int slotIndex, Array<String> names) {
|
||||
if (names == null) throw new IllegalArgumentException("names cannot be null.");
|
||||
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
|
||||
for (Key key : attachments.keys())
|
||||
if (key.slotIndex == slotIndex) names.add(key.name);
|
||||
}
|
||||
|
||||
public void findAttachmentsForSlot (int slotIndex, Array<Attachment> attachments) {
|
||||
if (attachments == null) throw new IllegalArgumentException("attachments cannot be null.");
|
||||
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
|
||||
for (Entry<Key, Attachment> entry : this.attachments.entries())
|
||||
if (entry.key.slotIndex == slotIndex) attachments.add(entry.value);
|
||||
}
|
||||
|
||||
@ -75,10 +75,12 @@ public class SkeletonTest extends ApplicationAdapter {
|
||||
};
|
||||
|
||||
if (true) {
|
||||
System.out.println("JSON");
|
||||
SkeletonJson json = new SkeletonJson(atlas);
|
||||
// json.setScale(2);
|
||||
skeletonData = json.readSkeletonData(Gdx.files.internal(name + ".json"));
|
||||
} else {
|
||||
System.out.println("Binary");
|
||||
SkeletonBinary binary = new SkeletonBinary(atlas);
|
||||
// binary.setScale(2);
|
||||
skeletonData = binary.readSkeletonData(Gdx.files.internal(name + ".skel"));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user