mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +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 public class IkConstraintTimeline extends CurveTimeline {
|
||||||
static private final int PREV_FRAME_TIME = -2;
|
static private final int PREV_FRAME_TIME = -3;
|
||||||
static private final int FRAME_VALUE = 1;
|
static private final int FRAME_MIX = 1;
|
||||||
|
static private final int FRAME_BEND_DIRECTION = 2;
|
||||||
|
|
||||||
int ikConstraintIndex;
|
int ikConstraintIndex;
|
||||||
private final float[] frames; // time, mix, ...
|
private final float[] frames; // time, mix, bendDirection, ...
|
||||||
private final int[] bendDirections;
|
|
||||||
|
|
||||||
public IkConstraintTimeline (int frameCount) {
|
public IkConstraintTimeline (int frameCount) {
|
||||||
super(frameCount);
|
super(frameCount);
|
||||||
frames = new float[frameCount * 2];
|
frames = new float[frameCount * 3];
|
||||||
bendDirections = new int[frameCount];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIkConstraintIndex (int ikConstraint) {
|
public void setIkConstraintIndex (int ikConstraint) {
|
||||||
@ -745,10 +744,10 @@ public class Animation {
|
|||||||
|
|
||||||
/** Sets the time, mix and bend direction of the specified keyframe. */
|
/** Sets the time, mix and bend direction of the specified keyframe. */
|
||||||
public void setFrame (int frameIndex, float time, float mix, int bendDirection) {
|
public void setFrame (int frameIndex, float time, float mix, int bendDirection) {
|
||||||
bendDirections[frameIndex] = bendDirection;
|
frameIndex *= 3;
|
||||||
frameIndex *= 2;
|
|
||||||
frames[frameIndex] = time;
|
frames[frameIndex] = time;
|
||||||
frames[frameIndex + 1] = mix;
|
frames[frameIndex + 1] = mix;
|
||||||
|
frames[frameIndex + 2] = bendDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha) {
|
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);
|
IkConstraint ikConstraint = skeleton.ikConstraints.get(ikConstraintIndex);
|
||||||
|
|
||||||
if (time >= frames[frames.length - 2]) { // Time is after last frame.
|
if (time >= frames[frames.length - 3]) { // Time is after last frame.
|
||||||
ikConstraint.mix += (frames[frames.length - 1] - ikConstraint.mix) * alpha;
|
ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha;
|
||||||
ikConstraint.bendDirection = bendDirections[bendDirections.length - 1];
|
ikConstraint.bendDirection = (int)frames[frames.length - 1];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate between the previous frame and the current frame.
|
// Interpolate between the previous frame and the current frame.
|
||||||
int frameIndex = binarySearch(frames, time, 2);
|
int frameIndex = binarySearch(frames, time, 3);
|
||||||
float prevFrameValue = frames[frameIndex - 1];
|
float prevFrameMix = frames[frameIndex - 2];
|
||||||
float frameTime = frames[frameIndex];
|
float frameTime = frames[frameIndex];
|
||||||
float percent = MathUtils.clamp(1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime), 0, 1);
|
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.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;
|
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.AttachmentTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.ColorTimeline;
|
import com.esotericsoftware.spine.Animation.ColorTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
import com.esotericsoftware.spine.Animation.CurveTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
||||||
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.Timeline;
|
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.RegionAttachment;
|
||||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
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 {
|
public class SkeletonBinary {
|
||||||
static public final int TIMELINE_SCALE = 0;
|
static public final int TIMELINE_SCALE = 0;
|
||||||
static public final int TIMELINE_ROTATE = 1;
|
static public final int TIMELINE_ROTATE = 1;
|
||||||
@ -129,7 +129,18 @@ public class SkeletonBinary {
|
|||||||
boneData.inheritScale = input.readBoolean();
|
boneData.inheritScale = input.readBoolean();
|
||||||
boneData.inheritRotation = input.readBoolean();
|
boneData.inheritRotation = input.readBoolean();
|
||||||
if (nonessential) Color.rgba8888ToColor(boneData.getColor(), input.readInt());
|
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.
|
// 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.
|
// FFD timelines.
|
||||||
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
for (int i = 0, n = input.readInt(true); i < n; i++) {
|
||||||
Skin skin = skeletonData.getSkins().get(input.readInt(true) + 1);
|
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.DrawOrderTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.EventTimeline;
|
import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
import com.esotericsoftware.spine.Animation.FfdTimeline;
|
||||||
|
import com.esotericsoftware.spine.Animation.IkConstraintTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
import com.esotericsoftware.spine.Animation.ScaleTimeline;
|
||||||
import com.esotericsoftware.spine.Animation.Timeline;
|
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.MeshAttachment;
|
||||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||||
@ -123,7 +123,7 @@ public class SkeletonJson {
|
|||||||
skeletonData.getBones().add(boneData);
|
skeletonData.getBones().add(boneData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IK.
|
// IK constraints.
|
||||||
for (JsonValue ikMap = root.getChild("ik"); ikMap != null; ikMap = ikMap.next) {
|
for (JsonValue ikMap = root.getChild("ik"); ikMap != null; ikMap = ikMap.next) {
|
||||||
IkConstraintData ikConstraintData = new IkConstraintData(ikMap.getString("name"));
|
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.
|
// FFD timelines.
|
||||||
for (JsonValue ffdMap = map.getChild("ffd"); ffdMap != null; ffdMap = ffdMap.next) {
|
for (JsonValue ffdMap = map.getChild("ffd"); ffdMap != null; ffdMap = ffdMap.next) {
|
||||||
Skin skin = skeletonData.findSkin(ffdMap.name);
|
Skin skin = skeletonData.findSkin(ffdMap.name);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user