mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[libgdx] More efficient animation timeline loading.
This commit is contained in:
parent
96f0f34d78
commit
f2e622875e
@ -30,6 +30,7 @@
|
|||||||
package com.esotericsoftware.spine;
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
|
|
||||||
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.Timeline;
|
import com.esotericsoftware.spine.Animation.Timeline;
|
||||||
@ -75,7 +76,8 @@ public class AttachmentTimelineTests {
|
|||||||
|
|
||||||
Array<Timeline> timelines = new Array(true, 1, Timeline[]::new);
|
Array<Timeline> timelines = new Array(true, 1, Timeline[]::new);
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
Animation animation = new Animation("animation", timelines, 1);
|
Animation animation = new Animation("animation");
|
||||||
|
animation.setTimelines(timelines, new IntArray(0));
|
||||||
animation.setDuration(1);
|
animation.setDuration(1);
|
||||||
|
|
||||||
state = new AnimationState(new AnimationStateData(skeletonData));
|
state = new AnimationState(new AnimationStateData(skeletonData));
|
||||||
|
|||||||
@ -35,7 +35,6 @@ import com.badlogic.gdx.graphics.Color;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.FloatArray;
|
import com.badlogic.gdx.utils.FloatArray;
|
||||||
import com.badlogic.gdx.utils.IntArray;
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.badlogic.gdx.utils.IntSet;
|
|
||||||
import com.badlogic.gdx.utils.LongSet;
|
import com.badlogic.gdx.utils.LongSet;
|
||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
|
|
||||||
@ -54,41 +53,36 @@ public class Animation {
|
|||||||
final String name;
|
final String name;
|
||||||
float duration;
|
float duration;
|
||||||
Array<Timeline> timelines;
|
Array<Timeline> timelines;
|
||||||
final LongSet timelineIds;
|
LongSet timelineIds;
|
||||||
final IntArray bones;
|
IntArray bones;
|
||||||
|
|
||||||
public Animation (String name, Array<Timeline> timelines, float duration) {
|
/** Creates a new animation. {@link #timelines} must be set before use. */
|
||||||
|
public Animation (String name) {
|
||||||
if (name == null) throw new IllegalArgumentException("name cannot be null.");
|
if (name == null) throw new IllegalArgumentException("name cannot be null.");
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.duration = duration;
|
|
||||||
int n = timelines.size << 1;
|
|
||||||
timelineIds = new LongSet(n);
|
|
||||||
bones = new IntArray(n);
|
|
||||||
setTimelines(timelines);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If this list or the timelines it contains are modified, the timelines must be set again to recompute the animation's bone
|
/** If this list or the timelines it contains are modified, the timelines must be set again to recompute the animation's bone
|
||||||
* indices and timeline property IDs. */
|
* indices and timeline property IDs. Setting this property computes the unique {@link #bones}. */
|
||||||
public Array<Timeline> getTimelines () {
|
public Array<Timeline> getTimelines () {
|
||||||
return timelines;
|
return timelines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimelines (Array<Timeline> timelines) {
|
/** Sets the {@link #timelines} and {@link #bones}. It can be more efficient to determine the unique bones externally. */
|
||||||
|
public void setTimelines (Array<Timeline> timelines, IntArray bones) {
|
||||||
if (timelines == null) throw new IllegalArgumentException("timelines cannot be null.");
|
if (timelines == null) throw new IllegalArgumentException("timelines cannot be null.");
|
||||||
|
if (bones == null) throw new IllegalArgumentException("bones cannot be null.");
|
||||||
this.timelines = timelines;
|
this.timelines = timelines;
|
||||||
|
this.bones = bones;
|
||||||
|
|
||||||
int n = timelines.size;
|
int n = timelines.size;
|
||||||
timelineIds.clear(n << 1);
|
if (timelineIds == null)
|
||||||
bones.clear();
|
timelineIds = new LongSet(n << 1);
|
||||||
var boneSet = new IntSet();
|
else
|
||||||
|
timelineIds.clear(n << 1);
|
||||||
Timeline[] items = timelines.items;
|
Timeline[] items = timelines.items;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++)
|
||||||
Timeline timeline = items[i];
|
timelineIds.addAll(items[i].propertyIds);
|
||||||
timelineIds.addAll(timeline.propertyIds);
|
|
||||||
if (timeline instanceof BoneTimeline boneTimeline && boneSet.add(boneTimeline.getBoneIndex()))
|
|
||||||
bones.add(boneTimeline.getBoneIndex());
|
|
||||||
}
|
|
||||||
bones.shrink();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this animation contains a timeline with any of the specified property IDs.
|
/** Returns true if this animation contains a timeline with any of the specified property IDs.
|
||||||
|
|||||||
@ -50,9 +50,13 @@ import com.esotericsoftware.spine.Animation.Timeline;
|
|||||||
* See <a href='https://esotericsoftware.com/spine-applying-animations#AnimationState-API'>Applying Animations</a> in the Spine
|
* See <a href='https://esotericsoftware.com/spine-applying-animations#AnimationState-API'>Applying Animations</a> in the Spine
|
||||||
* Runtimes Guide. */
|
* Runtimes Guide. */
|
||||||
public class AnimationState {
|
public class AnimationState {
|
||||||
static final Animation emptyAnimation = new Animation("<empty>", new Array(true, 0, Timeline[]::new), 0);
|
|
||||||
static private final int SUBSEQUENT = 0, FIRST = 1, HOLD = 2, HOLD_FIRST = 3, SETUP = 1, CURRENT = 2;
|
static private final int SUBSEQUENT = 0, FIRST = 1, HOLD = 2, HOLD_FIRST = 3, SETUP = 1, CURRENT = 2;
|
||||||
|
|
||||||
|
static final Animation emptyAnimation = new Animation("<empty>");
|
||||||
|
static {
|
||||||
|
emptyAnimation.setTimelines(new Array(true, 0, Timeline[]::new), new IntArray(0));
|
||||||
|
}
|
||||||
|
|
||||||
private AnimationStateData data;
|
private AnimationStateData data;
|
||||||
final Array<TrackEntry> tracks = new Array(true, 4, TrackEntry[]::new);
|
final Array<TrackEntry> tracks = new Array(true, 4, TrackEntry[]::new);
|
||||||
private final Array<Event> events = new Array(true, 4, Event[]::new);
|
private final Array<Event> events = new Array(true, 4, Event[]::new);
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import com.badlogic.gdx.graphics.Color;
|
|||||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.DataInput;
|
import com.badlogic.gdx.utils.DataInput;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
import com.badlogic.gdx.utils.SerializationException;
|
import com.badlogic.gdx.utils.SerializationException;
|
||||||
|
|
||||||
@ -924,8 +925,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bone timelines.
|
// Bone timelines.
|
||||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
int boneCount = input.readInt(true);
|
||||||
|
var bones = new IntArray(boneCount);
|
||||||
|
for (int i = 0; i < boneCount; i++) {
|
||||||
int boneIndex = input.readInt(true);
|
int boneIndex = input.readInt(true);
|
||||||
|
bones.add(boneIndex);
|
||||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
||||||
int type = input.readByte(), frameCount = input.readInt(true);
|
int type = input.readByte(), frameCount = input.readInt(true);
|
||||||
if (type == BONE_INHERIT) {
|
if (type == BONE_INHERIT) {
|
||||||
@ -1211,7 +1215,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
|||||||
Timeline[] items = timelines.items;
|
Timeline[] items = timelines.items;
|
||||||
for (int i = 0, n = timelines.size; i < n; i++)
|
for (int i = 0, n = timelines.size; i < n; i++)
|
||||||
duration = Math.max(duration, items[i].getDuration());
|
duration = Math.max(duration, items[i].getDuration());
|
||||||
return new Animation(name, timelines, duration);
|
|
||||||
|
Animation animation = new Animation(name);
|
||||||
|
animation.setTimelines(timelines, bones);
|
||||||
|
animation.setDuration(duration);
|
||||||
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readTimeline (SkeletonInput input, Array<Timeline> timelines, CurveTimeline1 timeline, float scale)
|
private void readTimeline (SkeletonInput input, Array<Timeline> timelines, CurveTimeline1 timeline, float scale)
|
||||||
|
|||||||
@ -911,9 +911,12 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bone timelines.
|
// Bone timelines.
|
||||||
for (JsonValue boneMap = map.getChild("bones"); boneMap != null; boneMap = boneMap.next) {
|
JsonValue boneMap = map.getChild("bones");
|
||||||
|
var bones = new IntArray(boneMap.size);
|
||||||
|
for (; boneMap != null; boneMap = boneMap.next) {
|
||||||
BoneData bone = skeletonData.findBone(boneMap.name);
|
BoneData bone = skeletonData.findBone(boneMap.name);
|
||||||
if (bone == null) throw new SerializationException("Bone not found: " + boneMap.name);
|
if (bone == null) throw new SerializationException("Bone not found: " + boneMap.name);
|
||||||
|
bones.add(bone.index);
|
||||||
for (JsonValue timelineMap = boneMap.child; timelineMap != null; timelineMap = timelineMap.next) {
|
for (JsonValue timelineMap = boneMap.child; timelineMap != null; timelineMap = timelineMap.next) {
|
||||||
JsonValue keyMap = timelineMap.child;
|
JsonValue keyMap = timelineMap.child;
|
||||||
if (keyMap == null) continue;
|
if (keyMap == null) continue;
|
||||||
@ -1265,7 +1268,11 @@ public class SkeletonJson extends SkeletonLoader {
|
|||||||
Timeline[] items = timelines.items;
|
Timeline[] items = timelines.items;
|
||||||
for (int i = 0, n = timelines.size; i < n; i++)
|
for (int i = 0, n = timelines.size; i < n; i++)
|
||||||
duration = Math.max(duration, items[i].getDuration());
|
duration = Math.max(duration, items[i].getDuration());
|
||||||
skeletonData.animations.add(new Animation(name, timelines, duration));
|
|
||||||
|
Animation animation = new Animation(name);
|
||||||
|
animation.setTimelines(timelines, bones);
|
||||||
|
animation.setDuration(duration);
|
||||||
|
skeletonData.animations.add(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readTimeline (Array<Timeline> timelines, JsonValue keyMap, CurveTimeline1 timeline, float defaultValue,
|
private void readTimeline (Array<Timeline> timelines, JsonValue keyMap, CurveTimeline1 timeline, float defaultValue,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user