mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
[libgdx] Added slider mix timeline, JSON/binary fixes.
This commit is contained in:
parent
26df02443f
commit
f0c61be159
@ -182,7 +182,8 @@ public class Animation {
|
||||
pathConstraintPosition, pathConstraintSpacing, pathConstraintMix, //
|
||||
physicsConstraintInertia, physicsConstraintStrength, physicsConstraintDamping, physicsConstraintMass, //
|
||||
physicsConstraintWind, physicsConstraintGravity, physicsConstraintMix, physicsConstraintReset, //
|
||||
sequence
|
||||
sequence, //
|
||||
sliderMix
|
||||
}
|
||||
|
||||
/** The base class for all timelines. */
|
||||
@ -1711,6 +1712,107 @@ public class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getSequenceIndex()} for an attachment's {@link Sequence}. */
|
||||
static public class SequenceTimeline extends Timeline implements SlotTimeline {
|
||||
static public final int ENTRIES = 3;
|
||||
static private final int MODE = 1, DELAY = 2;
|
||||
|
||||
final int slotIndex;
|
||||
final HasTextureRegion attachment;
|
||||
|
||||
public SequenceTimeline (int frameCount, int slotIndex, Attachment attachment) {
|
||||
super(frameCount,
|
||||
Property.sequence.ordinal() + "|" + slotIndex + "|" + ((HasTextureRegion)attachment).getSequence().getId());
|
||||
this.slotIndex = slotIndex;
|
||||
this.attachment = (HasTextureRegion)attachment;
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
public Attachment getAttachment () {
|
||||
return (Attachment)attachment;
|
||||
}
|
||||
|
||||
/** Sets the time, mode, index, and frame time for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time Seconds between frames. */
|
||||
public void setFrame (int frame, float time, SequenceMode mode, int index, float delay) {
|
||||
frame *= ENTRIES;
|
||||
frames[frame] = time;
|
||||
frames[frame + MODE] = mode.ordinal() | (index << 4);
|
||||
frames[frame + DELAY] = delay;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
Attachment slotAttachment = pose.attachment;
|
||||
if (slotAttachment != attachment) {
|
||||
if (!(slotAttachment instanceof VertexAttachment vertexAttachment)
|
||||
|| vertexAttachment.getTimelineAttachment() != attachment) return;
|
||||
}
|
||||
Sequence sequence = ((HasTextureRegion)slotAttachment).getSequence();
|
||||
if (sequence == null) return;
|
||||
|
||||
if (direction == out) {
|
||||
if (blend == setup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
if (blend == setup || blend == first) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = search(frames, time, ENTRIES);
|
||||
float before = frames[i];
|
||||
int modeAndIndex = (int)frames[i + MODE];
|
||||
float delay = frames[i + DELAY];
|
||||
|
||||
int index = modeAndIndex >> 4, count = sequence.getRegions().length;
|
||||
SequenceMode mode = SequenceMode.values[modeAndIndex & 0xf];
|
||||
if (mode != SequenceMode.hold) {
|
||||
index += (time - before) / delay + 0.0001f;
|
||||
switch (mode) {
|
||||
case once:
|
||||
index = Math.min(count - 1, index);
|
||||
break;
|
||||
case loop:
|
||||
index %= count;
|
||||
break;
|
||||
case pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : index % n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case onceReverse:
|
||||
index = Math.max(count - 1 - index, 0);
|
||||
break;
|
||||
case loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case pingpongReverse:
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
}
|
||||
}
|
||||
pose.setSequenceIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
/** Fires an {@link Event} when specific animation times are reached. */
|
||||
static public class EventTimeline extends Timeline {
|
||||
static private final String[] propertyIds = {Integer.toString(Property.event.ordinal())};
|
||||
@ -1827,6 +1929,7 @@ public class Animation {
|
||||
}
|
||||
|
||||
static public interface ConstraintTimeline {
|
||||
/** The index of the constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is applied. */
|
||||
public int getConstraintIndex ();
|
||||
}
|
||||
|
||||
@ -1848,8 +1951,6 @@ public class Animation {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** The index of the IK constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -1960,8 +2061,6 @@ public class Animation {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** The index of the transform constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -2075,8 +2174,6 @@ public class Animation {
|
||||
this.constraintIndex = constraintIndex;
|
||||
}
|
||||
|
||||
/** The index of the path constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -2101,8 +2198,6 @@ public class Animation {
|
||||
this.constraintIndex = constraintIndex;
|
||||
}
|
||||
|
||||
/** The index of the path constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -2135,8 +2230,6 @@ public class Animation {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
/** The index of the path constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -2223,8 +2316,8 @@ public class Animation {
|
||||
this.constraintIndex = constraintIndex;
|
||||
}
|
||||
|
||||
/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline
|
||||
* is applied, or -1 if all physics constraints in the skeleton will be changed. */
|
||||
/** The index of the physics constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
|
||||
* applied, or -1 if all physics constraints in the skeleton will be changed. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
@ -2404,7 +2497,7 @@ public class Animation {
|
||||
this.constraintIndex = constraintIndex;
|
||||
}
|
||||
|
||||
/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is
|
||||
/** The index of the physics constraint in {@link Skeleton#getConstraints()} that will be reset when this timeline is
|
||||
* applied, or -1 if all physics constraints in the skeleton will be reset. */
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
@ -2453,104 +2546,27 @@ public class Animation {
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes a slot's {@link SlotPose#getSequenceIndex()} for an attachment's {@link Sequence}. */
|
||||
static public class SequenceTimeline extends Timeline implements SlotTimeline {
|
||||
static public final int ENTRIES = 3;
|
||||
static private final int MODE = 1, DELAY = 2;
|
||||
/** Changes a slider's {@link SliderPose#getMix()}. */
|
||||
static public class SliderMixTimeline extends CurveTimeline1 implements ConstraintTimeline {
|
||||
final int constraintIndex;
|
||||
|
||||
final int slotIndex;
|
||||
final HasTextureRegion attachment;
|
||||
|
||||
public SequenceTimeline (int frameCount, int slotIndex, Attachment attachment) {
|
||||
super(frameCount,
|
||||
Property.sequence.ordinal() + "|" + slotIndex + "|" + ((HasTextureRegion)attachment).getSequence().getId());
|
||||
this.slotIndex = slotIndex;
|
||||
this.attachment = (HasTextureRegion)attachment;
|
||||
public SliderMixTimeline (int frameCount, int bezierCount, int constraintIndex) {
|
||||
super(frameCount, bezierCount, Property.sliderMix.ordinal() + "|" + constraintIndex);
|
||||
this.constraintIndex = constraintIndex;
|
||||
}
|
||||
|
||||
public int getFrameEntries () {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
public int getSlotIndex () {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
public Attachment getAttachment () {
|
||||
return (Attachment)attachment;
|
||||
}
|
||||
|
||||
/** Sets the time, mode, index, and frame time for the specified frame.
|
||||
* @param frame Between 0 and <code>frameCount</code>, inclusive.
|
||||
* @param time Seconds between frames. */
|
||||
public void setFrame (int frame, float time, SequenceMode mode, int index, float delay) {
|
||||
frame *= ENTRIES;
|
||||
frames[frame] = time;
|
||||
frames[frame + MODE] = mode.ordinal() | (index << 4);
|
||||
frames[frame + DELAY] = delay;
|
||||
public int getConstraintIndex () {
|
||||
return constraintIndex;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
|
||||
MixDirection direction, boolean appliedPose) {
|
||||
|
||||
Slot slot = skeleton.slots.items[slotIndex];
|
||||
if (!slot.bone.active) return;
|
||||
SlotPose pose = appliedPose ? slot.applied : slot.pose;
|
||||
|
||||
Attachment slotAttachment = pose.attachment;
|
||||
if (slotAttachment != attachment) {
|
||||
if (!(slotAttachment instanceof VertexAttachment vertexAttachment)
|
||||
|| vertexAttachment.getTimelineAttachment() != attachment) return;
|
||||
var constraint = (Slider)skeleton.constraints.items[constraintIndex];
|
||||
if (constraint.active) {
|
||||
SliderPose pose = appliedPose ? constraint.applied : constraint.pose;
|
||||
pose.mix = getAbsoluteValue(time, alpha, blend, pose.mix, constraint.data.setup.mix);
|
||||
}
|
||||
Sequence sequence = ((HasTextureRegion)slotAttachment).getSequence();
|
||||
if (sequence == null) return;
|
||||
|
||||
if (direction == out) {
|
||||
if (blend == setup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
if (blend == setup || blend == first) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = search(frames, time, ENTRIES);
|
||||
float before = frames[i];
|
||||
int modeAndIndex = (int)frames[i + MODE];
|
||||
float delay = frames[i + DELAY];
|
||||
|
||||
int index = modeAndIndex >> 4, count = sequence.getRegions().length;
|
||||
SequenceMode mode = SequenceMode.values[modeAndIndex & 0xf];
|
||||
if (mode != SequenceMode.hold) {
|
||||
index += (time - before) / delay + 0.0001f;
|
||||
switch (mode) {
|
||||
case once:
|
||||
index = Math.min(count - 1, index);
|
||||
break;
|
||||
case loop:
|
||||
index %= count;
|
||||
break;
|
||||
case pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : index % n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case onceReverse:
|
||||
index = Math.max(count - 1 - index, 0);
|
||||
break;
|
||||
case loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case pingpongReverse:
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
}
|
||||
}
|
||||
pose.setSequenceIndex(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ import com.esotericsoftware.spine.Animation.SequenceTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearXTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearYTimeline;
|
||||
import com.esotericsoftware.spine.Animation.SliderMixTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
|
||||
import com.esotericsoftware.spine.Animation.TranslateTimeline;
|
||||
@ -141,6 +142,7 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
static public final int CONSTRAINT_PATH = 1;
|
||||
static public final int CONSTRAINT_TRANSFORM = 2;
|
||||
static public final int CONSTRAINT_PHYSICS = 3;
|
||||
static public final int CONSTRAINT_SLIDER = 4;
|
||||
|
||||
static public final int ATTACHMENT_DEFORM = 0;
|
||||
static public final int ATTACHMENT_SEQUENCE = 1;
|
||||
@ -158,6 +160,8 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
static public final int PHYSICS_MIX = 7;
|
||||
static public final int PHYSICS_RESET = 8;
|
||||
|
||||
static public final int SLIDER_MIX = 0;
|
||||
|
||||
static public final int CURVE_LINEAR = 0;
|
||||
static public final int CURVE_STEPPED = 1;
|
||||
static public final int CURVE_BEZIER = 2;
|
||||
@ -259,12 +263,15 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// Constraints.
|
||||
o = skeletonData.constraints.setSize(n = input.readInt(true));
|
||||
for (int i = 0, nn; i < n; i++) {
|
||||
int constraintCount = input.readInt(true);
|
||||
ConstraintData[] constraints = skeletonData.constraints.setSize(constraintCount);
|
||||
for (int i = 0; i < constraintCount; i++) {
|
||||
String name = input.readString();
|
||||
int nn = input.readInt(true);
|
||||
switch (input.readByte()) {
|
||||
case CONSTRAINT_IK -> {
|
||||
var data = new IkConstraintData(input.readString());
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
var data = new IkConstraintData(name);
|
||||
BoneData[] constraintBones = data.bones.setSize(nn);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.target = bones[input.readInt(true)];
|
||||
@ -277,11 +284,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
setup.stretch = (flags & 16) != 0;
|
||||
if ((flags & 32) != 0) setup.mix = (flags & 64) != 0 ? input.readFloat() : 1;
|
||||
if ((flags & 128) != 0) setup.softness = input.readFloat() * scale;
|
||||
o[i] = data;
|
||||
constraints[i] = data;
|
||||
}
|
||||
case CONSTRAINT_TRANSFORM -> {
|
||||
var data = new TransformConstraintData(input.readString());
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
var data = new TransformConstraintData(name);
|
||||
BoneData[] constraintBones = data.bones.setSize(nn);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.source = bones[input.readInt(true)];
|
||||
@ -352,11 +359,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
if ((flags & 8) != 0) setup.mixScaleX = input.readFloat();
|
||||
if ((flags & 16) != 0) setup.mixScaleY = input.readFloat();
|
||||
if ((flags & 32) != 0) setup.mixShearY = input.readFloat();
|
||||
o[i] = data;
|
||||
constraints[i] = data;
|
||||
}
|
||||
case CONSTRAINT_PATH -> {
|
||||
var data = new PathConstraintData(input.readString());
|
||||
BoneData[] constraintBones = data.bones.setSize(nn = input.readInt(true));
|
||||
var data = new PathConstraintData(name);
|
||||
BoneData[] constraintBones = data.bones.setSize(nn);
|
||||
for (int ii = 0; ii < nn; ii++)
|
||||
constraintBones[ii] = bones[input.readInt(true)];
|
||||
data.slot = slots[input.readInt(true)];
|
||||
@ -374,11 +381,11 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
setup.mixRotate = input.readFloat();
|
||||
setup.mixX = input.readFloat();
|
||||
setup.mixY = input.readFloat();
|
||||
o[i] = data;
|
||||
constraints[i] = data;
|
||||
}
|
||||
case CONSTRAINT_PHYSICS -> {
|
||||
var data = new PhysicsConstraintData(input.readString());
|
||||
data.bone = bones[input.readInt(true)];
|
||||
var data = new PhysicsConstraintData(name);
|
||||
data.bone = bones[nn];
|
||||
int flags = input.read();
|
||||
data.skinRequired = (flags & 1) != 0;
|
||||
if ((flags & 2) != 0) data.x = input.readFloat();
|
||||
@ -404,7 +411,14 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
if ((flags & 32) != 0) data.gravityGlobal = true;
|
||||
if ((flags & 64) != 0) data.mixGlobal = true;
|
||||
setup.mix = (flags & 128) != 0 ? input.readFloat() : 1;
|
||||
o[i] = data;
|
||||
constraints[i] = data;
|
||||
}
|
||||
case CONSTRAINT_SLIDER -> {
|
||||
var data = new SliderData(name);
|
||||
data.skinRequired = (nn & 1) != 0;
|
||||
if ((nn & 2) != 0) data.setup.mix = (nn & 4) != 0 ? input.readFloat() : 1;
|
||||
if ((nn & 8) != 0) data.setup.time = input.readFloat();
|
||||
constraints[i] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -454,10 +468,12 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
|
||||
// Animations.
|
||||
o = skeletonData.animations.setSize(n = input.readInt(true));
|
||||
Animation[] animations = skeletonData.animations.setSize(n = input.readInt(true));
|
||||
for (int i = 0; i < n; i++)
|
||||
o[i] = readAnimation(input, input.readString(), skeletonData);
|
||||
animations[i] = readAnimation(input, input.readString(), skeletonData);
|
||||
|
||||
for (int i = 0; i < constraintCount; i++)
|
||||
if (constraints[i] instanceof SliderData data) data.animation = animations[input.readInt(true)];
|
||||
} catch (IOException ex) {
|
||||
throw new SerializationException("Error reading skeleton file.", ex);
|
||||
} finally {
|
||||
@ -1034,6 +1050,32 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
}
|
||||
}
|
||||
|
||||
// Slider timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
int index = input.readInt(true);
|
||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
||||
int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);
|
||||
switch (type) {
|
||||
case SLIDER_MIX -> {
|
||||
var timeline = new SliderMixTimeline(frameCount, bezierCount, index);
|
||||
float time = input.readFloat(), mix = input.readFloat();
|
||||
for (int frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1;; frame++) {
|
||||
timeline.setFrame(frame, time, mix);
|
||||
if (frame == frameLast) break;
|
||||
float time2 = input.readFloat(), mix2 = input.readFloat();
|
||||
switch (input.readByte()) {
|
||||
case CURVE_STEPPED -> timeline.setStepped(frame);
|
||||
case CURVE_BEZIER -> setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
||||
}
|
||||
time = time2;
|
||||
mix = mix2;
|
||||
}
|
||||
timelines.add(timeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attachment timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
Skin skin = skeletonData.skins.items[input.readInt(true)];
|
||||
|
||||
@ -77,6 +77,7 @@ import com.esotericsoftware.spine.Animation.SequenceTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearXTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ShearYTimeline;
|
||||
import com.esotericsoftware.spine.Animation.SliderMixTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
|
||||
import com.esotericsoftware.spine.Animation.TranslateTimeline;
|
||||
@ -217,10 +218,12 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
// Constraints.
|
||||
for (JsonValue constraintMap = root.getChild("constraints"); constraintMap != null; constraintMap = constraintMap.next) {
|
||||
String name = constraintMap.getString("name");
|
||||
boolean skinRequired = constraintMap.getBoolean("skin", false);
|
||||
switch (constraintMap.getString("type")) {
|
||||
case "ik" -> {
|
||||
var data = new IkConstraintData(constraintMap.getString("name"));
|
||||
data.skinRequired = constraintMap.getBoolean("skin", false);
|
||||
var data = new IkConstraintData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
|
||||
for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
|
||||
BoneData bone = skeletonData.findBone(entry.asString());
|
||||
@ -243,8 +246,8 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
case "transform" -> {
|
||||
var data = new TransformConstraintData(constraintMap.getString("name"));
|
||||
data.skinRequired = constraintMap.getBoolean("skin", false);
|
||||
var data = new TransformConstraintData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
|
||||
for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
|
||||
BoneData bone = skeletonData.findBone(entry.asString());
|
||||
@ -340,8 +343,8 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
case "path" -> {
|
||||
var data = new PathConstraintData(constraintMap.getString("name"));
|
||||
data.skinRequired = constraintMap.getBoolean("skin", false);
|
||||
var data = new PathConstraintData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
|
||||
for (JsonValue entry = constraintMap.getChild("bones"); entry != null; entry = entry.next) {
|
||||
BoneData bone = skeletonData.findBone(entry.asString());
|
||||
@ -369,8 +372,8 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
case "physics" -> {
|
||||
var data = new PhysicsConstraintData(constraintMap.getString("name"));
|
||||
data.skinRequired = constraintMap.getBoolean("skin", false);
|
||||
var data = new PhysicsConstraintData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
|
||||
String boneName = constraintMap.getString("bone");
|
||||
data.bone = skeletonData.findBone(boneName);
|
||||
@ -384,9 +387,9 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
data.limit = constraintMap.getFloat("limit", 5000) * scale;
|
||||
data.step = 1f / constraintMap.getInt("fps", 60);
|
||||
PhysicsConstraintPose setup = data.setup;
|
||||
setup.inertia = constraintMap.getFloat("inertia", 1);
|
||||
setup.inertia = constraintMap.getFloat("inertia", 0.5f);
|
||||
setup.strength = constraintMap.getFloat("strength", 100);
|
||||
setup.damping = constraintMap.getFloat("damping", 1);
|
||||
setup.damping = constraintMap.getFloat("damping", 0.85f);
|
||||
setup.massInverse = 1 / constraintMap.getFloat("mass", 1);
|
||||
setup.wind = constraintMap.getFloat("wind", 0);
|
||||
setup.gravity = constraintMap.getFloat("gravity", 0);
|
||||
@ -401,7 +404,13 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
// BOZO! - Sliders.
|
||||
case "slider" -> {
|
||||
var data = new SliderData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
data.setup.time = constraintMap.getFloat("time", 0);
|
||||
data.setup.mix = constraintMap.getFloat("mix", 1);
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,6 +501,16 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
}
|
||||
}
|
||||
|
||||
// Slider animations.
|
||||
for (JsonValue constraintMap = root.getChild("constraints"); constraintMap != null; constraintMap = constraintMap.next) {
|
||||
if (constraintMap.getString("type").equals("slider")) {
|
||||
SliderData data = skeletonData.findConstraint(constraintMap.getString("name"), SliderData.class);
|
||||
String animationName = constraintMap.getString("animation");
|
||||
data.animation = skeletonData.findAnimation(animationName);
|
||||
if (data.animation == null) throw new SerializationException("Slider animation not found: " + animationName);
|
||||
}
|
||||
}
|
||||
|
||||
skeletonData.bones.shrink();
|
||||
skeletonData.slots.shrink();
|
||||
skeletonData.skins.shrink();
|
||||
@ -1032,6 +1051,7 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
int frames = timelineMap.size;
|
||||
CurveTimeline1 timeline;
|
||||
float defaultValue = 0;
|
||||
switch (timelineMap.name) {
|
||||
case "reset" -> {
|
||||
var resetTimeline = new PhysicsConstraintResetTimeline(frames, index);
|
||||
@ -1046,12 +1066,31 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
case "mass" -> timeline = new PhysicsConstraintMassTimeline(frames, frames, index);
|
||||
case "wind" -> timeline = new PhysicsConstraintWindTimeline(frames, frames, index);
|
||||
case "gravity" -> timeline = new PhysicsConstraintGravityTimeline(frames, frames, index);
|
||||
case "mix" -> timeline = new PhysicsConstraintMixTimeline(frames, frames, index);
|
||||
case "mix" -> {
|
||||
defaultValue = 1;
|
||||
timeline = new PhysicsConstraintMixTimeline(frames, frames, index);
|
||||
}
|
||||
default -> {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
timelines.add(readTimeline(keyMap, timeline, 0, 1));
|
||||
timelines.add(readTimeline(keyMap, timeline, defaultValue, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Slider timelines.
|
||||
for (JsonValue constraintMap = map.getChild("slider"); constraintMap != null; constraintMap = constraintMap.next) {
|
||||
SliderData constraint = skeletonData.findConstraint(constraintMap.name, SliderData.class);
|
||||
if (constraint == null) throw new SerializationException("Slider not found: " + constraintMap.name);
|
||||
int index = skeletonData.constraints.indexOf(constraint, true);
|
||||
for (JsonValue timelineMap = constraintMap.child; timelineMap != null; timelineMap = timelineMap.next) {
|
||||
JsonValue keyMap = timelineMap.child;
|
||||
if (keyMap == null) continue;
|
||||
|
||||
int frames = timelineMap.size;
|
||||
switch (timelineMap.name) {
|
||||
case "mix" -> timelines.add(readTimeline(keyMap, new SliderMixTimeline(frames, frames, index), 1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user