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;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
|
||||
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
@ -75,7 +76,8 @@ public class AttachmentTimelineTests {
|
||||
|
||||
Array<Timeline> timelines = new Array(true, 1, Timeline[]::new);
|
||||
timelines.add(timeline);
|
||||
Animation animation = new Animation("animation", timelines, 1);
|
||||
Animation animation = new Animation("animation");
|
||||
animation.setTimelines(timelines, new IntArray(0));
|
||||
animation.setDuration(1);
|
||||
|
||||
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.FloatArray;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import com.badlogic.gdx.utils.LongSet;
|
||||
import com.badlogic.gdx.utils.Null;
|
||||
|
||||
@ -54,41 +53,36 @@ public class Animation {
|
||||
final String name;
|
||||
float duration;
|
||||
Array<Timeline> timelines;
|
||||
final LongSet timelineIds;
|
||||
final IntArray bones;
|
||||
LongSet timelineIds;
|
||||
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.");
|
||||
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
|
||||
* indices and timeline property IDs. */
|
||||
* indices and timeline property IDs. Setting this property computes the unique {@link #bones}. */
|
||||
public Array<Timeline> getTimelines () {
|
||||
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 (bones == null) throw new IllegalArgumentException("bones cannot be null.");
|
||||
this.timelines = timelines;
|
||||
this.bones = bones;
|
||||
|
||||
int n = timelines.size;
|
||||
timelineIds.clear(n << 1);
|
||||
bones.clear();
|
||||
var boneSet = new IntSet();
|
||||
if (timelineIds == null)
|
||||
timelineIds = new LongSet(n << 1);
|
||||
else
|
||||
timelineIds.clear(n << 1);
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0; i < n; i++) {
|
||||
Timeline timeline = items[i];
|
||||
timelineIds.addAll(timeline.propertyIds);
|
||||
if (timeline instanceof BoneTimeline boneTimeline && boneSet.add(boneTimeline.getBoneIndex()))
|
||||
bones.add(boneTimeline.getBoneIndex());
|
||||
}
|
||||
bones.shrink();
|
||||
for (int i = 0; i < n; i++)
|
||||
timelineIds.addAll(items[i].propertyIds);
|
||||
}
|
||||
|
||||
/** 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
|
||||
* Runtimes Guide. */
|
||||
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 final Animation emptyAnimation = new Animation("<empty>");
|
||||
static {
|
||||
emptyAnimation.setTimelines(new Array(true, 0, Timeline[]::new), new IntArray(0));
|
||||
}
|
||||
|
||||
private AnimationStateData data;
|
||||
final Array<TrackEntry> tracks = new Array(true, 4, TrackEntry[]::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.utils.Array;
|
||||
import com.badlogic.gdx.utils.DataInput;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.Null;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
|
||||
@ -924,8 +925,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// 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);
|
||||
bones.add(boneIndex);
|
||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
||||
int type = input.readByte(), frameCount = input.readInt(true);
|
||||
if (type == BONE_INHERIT) {
|
||||
@ -1211,7 +1215,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0, n = timelines.size; i < n; i++)
|
||||
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)
|
||||
|
||||
@ -911,9 +911,12 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
JsonValue keyMap = timelineMap.child;
|
||||
if (keyMap == null) continue;
|
||||
@ -1265,7 +1268,11 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
Timeline[] items = timelines.items;
|
||||
for (int i = 0, n = timelines.size; i < n; i++)
|
||||
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user