mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 15:24:55 +08:00
Updated IK constraints.
This commit is contained in:
parent
059cc69a31
commit
ed55a831d7
@ -718,17 +718,16 @@ public class Animation {
|
||||
}
|
||||
|
||||
static public class IkConstraintTimeline extends CurveTimeline {
|
||||
static private final int PREV_FRAME_TIME = -2;
|
||||
static private final int FRAME_VALUE = 1;
|
||||
static private final int PREV_FRAME_TIME = -3;
|
||||
static private final int FRAME_MIX = 1;
|
||||
static private final int FRAME_BEND_DIRECTION = 2;
|
||||
|
||||
int ikConstraintIndex;
|
||||
private final float[] frames; // time, mix, ...
|
||||
private final int[] bendDirections;
|
||||
private final float[] frames; // time, mix, bendDirection, ...
|
||||
|
||||
public IkConstraintTimeline (int frameCount) {
|
||||
super(frameCount);
|
||||
frames = new float[frameCount * 2];
|
||||
bendDirections = new int[frameCount];
|
||||
frames = new float[frameCount * 3];
|
||||
}
|
||||
|
||||
public void setIkConstraintIndex (int ikConstraint) {
|
||||
@ -745,10 +744,10 @@ public class Animation {
|
||||
|
||||
/** Sets the time, mix and bend direction of the specified keyframe. */
|
||||
public void setFrame (int frameIndex, float time, float mix, int bendDirection) {
|
||||
bendDirections[frameIndex] = bendDirection;
|
||||
frameIndex *= 2;
|
||||
frameIndex *= 3;
|
||||
frames[frameIndex] = time;
|
||||
frames[frameIndex + 1] = mix;
|
||||
frames[frameIndex + 2] = bendDirection;
|
||||
}
|
||||
|
||||
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha) {
|
||||
@ -757,22 +756,22 @@ public class Animation {
|
||||
|
||||
IkConstraint ikConstraint = skeleton.ikConstraints.get(ikConstraintIndex);
|
||||
|
||||
if (time >= frames[frames.length - 2]) { // Time is after last frame.
|
||||
ikConstraint.mix += (frames[frames.length - 1] - ikConstraint.mix) * alpha;
|
||||
ikConstraint.bendDirection = bendDirections[bendDirections.length - 1];
|
||||
if (time >= frames[frames.length - 3]) { // Time is after last frame.
|
||||
ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha;
|
||||
ikConstraint.bendDirection = (int)frames[frames.length - 1];
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
int frameIndex = binarySearch(frames, time, 2);
|
||||
float prevFrameValue = frames[frameIndex - 1];
|
||||
int frameIndex = binarySearch(frames, time, 3);
|
||||
float prevFrameMix = frames[frameIndex - 2];
|
||||
float frameTime = frames[frameIndex];
|
||||
float percent = MathUtils.clamp(1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime), 0, 1);
|
||||
percent = getCurvePercent((frameIndex >> 1) - 1, percent);
|
||||
percent = getCurvePercent(frameIndex / 3 - 1, percent);
|
||||
|
||||
float mix = prevFrameValue + (frames[frameIndex + FRAME_VALUE] - prevFrameValue) * percent;
|
||||
float mix = prevFrameMix + (frames[frameIndex + FRAME_MIX] - prevFrameMix) * percent;
|
||||
ikConstraint.mix += (mix - ikConstraint.mix) * alpha;
|
||||
ikConstraint.bendDirection = bendDirections[(frameIndex - 2) >> 1];
|
||||
ikConstraint.bendDirection = (int)frames[frameIndex + FRAME_BEND_DIRECTION];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,12 +30,23 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.DataInput;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
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.FfdTimeline;
|
||||
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
@ -49,17 +60,6 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||
|
||||
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.DataInput;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.SerializationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SkeletonBinary {
|
||||
static public final int TIMELINE_SCALE = 0;
|
||||
static public final int TIMELINE_ROTATE = 1;
|
||||
@ -129,7 +129,18 @@ public class SkeletonBinary {
|
||||
boneData.inheritScale = input.readBoolean();
|
||||
boneData.inheritRotation = input.readBoolean();
|
||||
if (nonessential) Color.rgba8888ToColor(boneData.getColor(), input.readInt());
|
||||
skeletonData.getBones().add(boneData);
|
||||
skeletonData.bones.add(boneData);
|
||||
}
|
||||
|
||||
// IK constraints.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
IkConstraintData ikConstraint = new IkConstraintData(input.readString());
|
||||
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++)
|
||||
ikConstraint.bones.add(skeletonData.bones.get(input.readInt(true)));
|
||||
ikConstraint.target = skeletonData.bones.get(input.readInt(true));
|
||||
ikConstraint.mix = input.readFloat();
|
||||
ikConstraint.bendDirection = input.readByte();
|
||||
skeletonData.ikConstraints.add(ikConstraint);
|
||||
}
|
||||
|
||||
// Slots.
|
||||
@ -396,6 +407,20 @@ public class SkeletonBinary {
|
||||
}
|
||||
}
|
||||
|
||||
// IK timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
IkConstraintData ikConstraint = skeletonData.findIkConstraint(input.readString());
|
||||
int frameCount = input.readInt(true);
|
||||
IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
|
||||
timeline.setIkConstraintIndex(skeletonData.getIkConstraints().indexOf(ikConstraint, true));
|
||||
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
|
||||
timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readByte());
|
||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[frameCount * 3 - 3]);
|
||||
}
|
||||
|
||||
// FFD timelines.
|
||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||
Skin skin = skeletonData.getSkins().get(input.readInt(true) + 1);
|
||||
|
||||
@ -36,6 +36,7 @@ import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
||||
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
@ -48,7 +49,6 @@ import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
|
||||
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
@ -123,7 +123,7 @@ public class SkeletonJson {
|
||||
skeletonData.getBones().add(boneData);
|
||||
}
|
||||
|
||||
// IK.
|
||||
// IK constraints.
|
||||
for (JsonValue ikMap = root.getChild("ik"); ikMap != null; ikMap = ikMap.next) {
|
||||
IkConstraintData ikConstraintData = new IkConstraintData(ikMap.getString("name"));
|
||||
|
||||
@ -381,6 +381,22 @@ public class SkeletonJson {
|
||||
}
|
||||
}
|
||||
|
||||
// IK timelines.
|
||||
for (JsonValue ikMap = map.getChild("ik"); ikMap != null; ikMap = ikMap.next) {
|
||||
IkConstraintData ikConstraint = skeletonData.findIkConstraint(ikMap.name);
|
||||
IkConstraintTimeline timeline = new IkConstraintTimeline(ikMap.size);
|
||||
timeline.setIkConstraintIndex(skeletonData.getIkConstraints().indexOf(ikConstraint, true));
|
||||
int frameIndex = 0;
|
||||
for (JsonValue valueMap = ikMap.child; valueMap != null; valueMap = valueMap.next) {
|
||||
timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getFloat("mix"),
|
||||
valueMap.getBoolean("bendPositive") ? 1 : -1);
|
||||
readCurve(timeline, frameIndex, valueMap);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.add(timeline);
|
||||
duration = Math.max(duration, timeline.getFrames()[timeline.getFrameCount() * 3 - 3]);
|
||||
}
|
||||
|
||||
// FFD timelines.
|
||||
for (JsonValue ffdMap = map.getChild("ffd"); ffdMap != null; ffdMap = ffdMap.next) {
|
||||
Skin skin = skeletonData.findSkin(ffdMap.name);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user