Bläddra i källkod

[as3] Added soft IK support. See #1383.

badlogic 6 år sedan
förälder
incheckning
442699238a

BIN
spine-as3/spine-as3-example/lib/spine-as3.swc


+ 26 - 7
spine-as3/spine-as3/src/spine/IkConstraint.as

@@ -36,6 +36,7 @@ package spine {
 		public var compress: Boolean;
 		public var stretch: Boolean;
 		public var mix : Number;
+		public var softness : Number = 0;
 		public var active : Boolean;
 
 		public function IkConstraint(data : IkConstraintData, skeleton : Skeleton) {
@@ -43,6 +44,7 @@ package spine {
 			if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
 			_data = data;
 			mix = data.mix;
+			softness = data.softness;
 			bendDirection = data.bendDirection;
 			compress = data.compress;
 			stretch = data.stretch;
@@ -67,7 +69,7 @@ package spine {
 					apply1(bones[0], target.worldX, target.worldY, compress, stretch, _data.uniform, mix);
 					break;
 				case 2:
-					apply2(bones[0], bones[1], target.worldX, target.worldY, bendDirection, stretch, mix);
+					apply2(bones[0], bones[1], target.worldX, target.worldY, bendDirection, stretch, softness, mix);
 					break;
 			}
 		}
@@ -109,7 +111,7 @@ package spine {
 		/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
 		 * target is specified in the world coordinate system.
 		 * @param child Any descendant bone of the parent. */
-		static public function apply2(parent : Bone, child : Bone, targetX : Number, targetY : Number, bendDir : int, stretch : Boolean, alpha : Number) : void {
+		static public function apply2(parent : Bone, child : Bone, targetX : Number, targetY : Number, bendDir : int, stretch : Boolean, softness: Number, alpha : Number) : void {
 			if (alpha == 0) {
 				child.updateWorldTransform();
 				return;
@@ -151,12 +153,29 @@ package spine {
 			b = pp.b;
 			c = pp.c;
 			d = pp.d;
-			var id : Number = 1 / (a * d - b * c), x : Number = targetX - pp.worldX, y : Number = targetY - pp.worldY;
-			var tx : Number = (x * d - y * b) * id - px, ty : Number = (y * a - x * c) * id - py, dd : Number = tx * tx + ty * ty;
-			x = cwx - pp.worldX;
-			y = cwy - pp.worldY;
+			var id : Number = 1 / (a * d - b * c), x : Number = cwx - pp.worldX, y : Number = cwy - pp.worldY;
 			var dx : Number = (x * d - y * b) * id - px, dy : Number = (y * a - x * c) * id - py;
 			var l1 : Number = Math.sqrt(dx * dx + dy * dy), l2 : Number = child.data.length * csx, a1 : Number, a2 : Number;
+			if (l1 < 0.0001) {
+				apply1(parent, targetX, targetY, false, stretch, false, alpha);
+				child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
+				return;
+			}
+			x = targetX - pp.worldX;
+			y = targetY - pp.worldY;
+			var tx : Number = (x * d - y * b) * id - px, ty : Number = (y * a - x * c) * id - py;
+			var dd : Number = tx * tx + ty * ty;
+			if (softness != 0) {
+				softness *= psx * (csx + 1) / 2;
+				var td : Number = Math.sqrt(dd), sd : Number = td - l1 - l2 * psx + softness;
+				if (sd > 0) {
+					var p : Number = Math.min(1, sd / (softness * 2)) - 1;
+					p = (sd - softness * (1 - p * p)) / td;
+					tx -= p * tx;
+					ty -= p * ty;
+					dd = tx * tx + ty * ty;
+				}
+			}
 			outer:
 			if (u) {
 				l2 *= psx;
@@ -165,7 +184,7 @@ package spine {
 					cos = -1;
 				else if (cos > 1) {
 					cos = 1;
-					if (stretch && l1 + l2 > 0.0001) sx *= (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
+					if (stretch) sx *= (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
 				}
 				a2 = Math.acos(cos) * bendDir;
 				a = l1 + l2 * cos;

+ 1 - 0
spine-as3/spine-as3/src/spine/IkConstraintData.as

@@ -36,6 +36,7 @@ package spine {
 		public var compress : Boolean = false;
 		public var stretch : Boolean = false;
 		public var uniform : Boolean = false;
+		public var softness : Number = 0;
 
 		public function IkConstraintData(name : String) {
 			super(name, 0, false);			

+ 1 - 0
spine-as3/spine-as3/src/spine/Skeleton.as

@@ -322,6 +322,7 @@ package spine {
 
 			for each (var ikConstraint : IkConstraint in ikConstraints) {
 				ikConstraint.mix = ikConstraint._data.mix;
+				ikConstraint.softness = ikConstraint._data.softness;
 				ikConstraint.bendDirection = ikConstraint._data.bendDirection;				
 				ikConstraint.compress = ikConstraint._data.compress;
 				ikConstraint.stretch = ikConstraint._data.stretch;				

+ 2 - 1
spine-as3/spine-as3/src/spine/SkeletonBinary.as

@@ -169,6 +169,7 @@ package spine {
 					ikData.bones.push(skeletonData.bones[input.readInt(true)]);
 				ikData.target = skeletonData.bones[input.readInt(true)];
 				ikData.mix = input.readFloat();
+				ikData.softness = input.readFloat();
 				ikData.bendDirection = input.readByte();
 				ikData.compress = input.readBoolean();
 				ikData.stretch = input.readBoolean();
@@ -656,7 +657,7 @@ package spine {
 				frameIndex = 0;
 				ikConstraintTimeline.ikConstraintIndex = index;
 				for (frameIndex = 0; frameIndex < frameCount; frameIndex++) {
-					ikConstraintTimeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readByte(), input.readBoolean(),
+					ikConstraintTimeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readFloat(), input.readByte(), input.readBoolean(),
 						input.readBoolean());
 					if (frameIndex < frameCount - 1) this.readCurve(input, frameIndex, ikConstraintTimeline);
 				}

+ 3 - 1
spine-as3/spine-as3/src/spine/SkeletonJson.as

@@ -169,6 +169,7 @@ package spine {
 				ikConstraintData.compress = (constraintMap.hasOwnProperty("compress") && constraintMap["compress"]);
 				ikConstraintData.stretch = (constraintMap.hasOwnProperty("stretch") && constraintMap["stretch"]);
 				ikConstraintData.uniform = (constraintMap.hasOwnProperty("uniform") && constraintMap["uniform"]);
+				ikConstraintData.softness = constraintMap.hasOwnProperty("softness") ? constraintMap["softness"] : 0;
 				ikConstraintData.mix = constraintMap.hasOwnProperty("mix") ? constraintMap["mix"] : 1;
 
 				skeletonData.ikConstraints.push(ikConstraintData);
@@ -588,7 +589,8 @@ package spine {
 					var bendDirection : int = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1;
 					var compress : Boolean = (valueMap.hasOwnProperty("compress") && valueMap["compress"]);
 					var stretch : Boolean = (valueMap.hasOwnProperty("stretch") && valueMap["stretch"]);
-					ikTimeline.setFrame(frameIndex, Number(valueMap["time"] || 0), mix, bendDirection, compress, stretch);
+					var softness : Number = valueMap.hasOwnProperty("softness") ? valueMap["softness"] : 0;
+					ikTimeline.setFrame(frameIndex, Number(valueMap["time"] || 0), mix, softness, bendDirection, compress, stretch);
 					readCurve(valueMap, ikTimeline, frameIndex);
 					frameIndex++;
 				}

+ 13 - 4
spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as

@@ -34,8 +34,8 @@ package spine.animation {
 
 	public class IkConstraintTimeline extends CurveTimeline {
 		static public const ENTRIES : int = 5;
-		static internal const PREV_TIME : int = -5, PREV_MIX : int = -4, PREV_BEND_DIRECTION : int = -3, PREV_COMPRESS : int = -2, PREV_STRETCH : int = -1;
-		static internal const MIX : int = 1, BEND_DIRECTION : int = 2, COMPRESS : int = 3, STRETCH : int = 4;
+		static internal const PREV_TIME : int = -6, PREV_MIX : int = -5, PREV_SOFTNESS : int = -4, PREV_BEND_DIRECTION : int = -3, PREV_COMPRESS : int = -2, PREV_STRETCH : int = -1;
+		static internal const MIX : int = 1, SOFTNESS : int = 2, BEND_DIRECTION : int = 3, COMPRESS : int = 4, STRETCH : int = 5;
 		public var ikConstraintIndex : int;
 		public var frames : Vector.<Number>; // time, mix, bendDirection, compress, stretch, ...
 
@@ -49,10 +49,11 @@ package spine.animation {
 		}
 
 		/** Sets the time, mix and bend direction of the specified keyframe. */
-		public function setFrame(frameIndex : int, time : Number, mix : Number, bendDirection : int, compress: Boolean, stretch: Boolean) : void {
+		public function setFrame(frameIndex : int, time : Number, mix : Number, softness: Number, bendDirection : int, compress: Boolean, stretch: Boolean) : void {
 			frameIndex *= ENTRIES;
 			frames[frameIndex] = time;
 			frames[int(frameIndex + MIX)] = mix;
+			frames[int(frameIndex + SOFTNESS)] = softness;
 			frames[int(frameIndex + BEND_DIRECTION)] = bendDirection;
 			frames[int(frameIndex + COMPRESS)] = compress ? 1 : 0;
 			frames[int(frameIndex + STRETCH)] = stretch ? 1 : 0;
@@ -65,12 +66,14 @@ package spine.animation {
 				switch (blend) {
 				case MixBlend.setup:
 					constraint.mix = constraint.data.mix;
+					constraint.softness = constraint.data.softness;
 					constraint.bendDirection = constraint.data.bendDirection;
 					constraint.compress = constraint.data.compress;
 					constraint.stretch = constraint.data.stretch;
 					return;
 				case MixBlend.first:
 					constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
+					constraint.softness += (constraint.data.softness - constraint.softness) * alpha;
 					constraint.bendDirection = constraint.data.bendDirection;
 					constraint.compress = constraint.data.compress;
 					constraint.stretch = constraint.data.stretch;
@@ -81,7 +84,8 @@ package spine.animation {
 			if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
 				if (blend == MixBlend.setup) {
 					constraint.mix = constraint.data.mix + (frames[frames.length + PREV_MIX] - constraint.data.mix) * alpha;
-					
+					constraint.softness = constraint.data.softness
+						+ (frames[frames.length + PREV_SOFTNESS] - constraint.data.softness) * alpha;
 					if (direction == MixDirection.Out) {
 						constraint.bendDirection = constraint.data.bendDirection;
 						constraint.compress = constraint.data.compress;
@@ -93,6 +97,7 @@ package spine.animation {
 					}					
 				} else {
 					constraint.mix += (frames[frames.length + PREV_MIX] - constraint.mix) * alpha;
+					constraint.softness += (frames[frames.length + PREV_SOFTNESS] - constraint.softness) * alpha;
 					if (direction == MixDirection.In) {
 						constraint.bendDirection = int(frames[frames.length + PREV_BEND_DIRECTION]);
 						constraint.compress = int(frames[frames.length + PREV_COMPRESS]) != 0;
@@ -105,11 +110,14 @@ package spine.animation {
 			// Interpolate between the previous frame and the current frame.
 			var frame : int = Animation.binarySearch(frames, time, ENTRIES);
 			var mix : Number = frames[int(frame + PREV_MIX)];
+			var softness : Number = frames[frame + PREV_SOFTNESS];
 			var frameTime : Number = frames[frame];
 			var percent : Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
 
 			if (blend == MixBlend.setup) {
 				constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha;
+				constraint.softness = constraint.data.softness
+					+ (softness + (frames[frame + SOFTNESS] - softness) * percent - constraint.data.softness) * alpha;
 				if (direction == MixDirection.Out) {
 					constraint.bendDirection = constraint.data.bendDirection;
 					constraint.compress = constraint.data.compress;
@@ -121,6 +129,7 @@ package spine.animation {
 				}				
 			} else {
 				constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
+				constraint.softness += (softness + (frames[frame + SOFTNESS] - softness) * percent - constraint.softness) * alpha;
 				if (direction == MixDirection.In) {
 					constraint.bendDirection = int(frames[frame + PREV_BEND_DIRECTION]);
 					constraint.compress = int(frames[frame + PREV_COMPRESS]) != 0;

BIN
spine-starling/spine-starling-example/lib/spine-as3.swc


BIN
spine-starling/spine-starling/lib/spine-as3.swc