Bläddra i källkod

Updated IK constraints.

NathanSweet 11 år sedan
förälder
incheckning
ed55a831d7

+ 15 - 16
spine-libgdx/src/com/esotericsoftware/spine/Animation.java

@@ -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];
 		}
 	}
 }

+ 37 - 12
spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java

@@ -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);

+ 18 - 2
spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java

@@ -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);