diff --git a/spine-as3/spine-as3-example/lib/spine-as3.swc b/spine-as3/spine-as3-example/lib/spine-as3.swc index 2839d51b4..e57853ed4 100644 Binary files a/spine-as3/spine-as3-example/lib/spine-as3.swc and b/spine-as3/spine-as3-example/lib/spine-as3.swc differ diff --git a/spine-as3/spine-as3/src/spine/IkConstraint.as b/spine-as3/spine-as3/src/spine/IkConstraint.as index 6656383ee..89b40305e 100644 --- a/spine-as3/spine-as3/src/spine/IkConstraint.as +++ b/spine-as3/spine-as3/src/spine/IkConstraint.as @@ -34,6 +34,7 @@ package spine { public var bones : Vector.; public var target : Bone; public var bendDirection : int; + public var compress: Boolean; public var stretch: Boolean; public var mix : Number; @@ -43,6 +44,7 @@ package spine { _data = data; mix = data.mix; bendDirection = data.bendDirection; + compress = data.compress; stretch = data.stretch; bones = new Vector.(); @@ -58,7 +60,7 @@ package spine { public function update() : void { switch (bones.length) { case 1: - apply1(bones[0], target.worldX, target.worldY, stretch, mix); + 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); @@ -80,7 +82,7 @@ package spine { /** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world * coordinate system. */ - static public function apply1(bone : Bone, targetX : Number, targetY : Number, stretch : Boolean, alpha : Number) : void { + static public function apply1(bone : Bone, targetX : Number, targetY : Number, compress: Boolean, stretch : Boolean, uniform: Boolean, alpha : Number) : void { if (!bone.appliedValid) bone.updateAppliedTransform(); var p : Bone = bone.parent; var id : Number = 1 / (p.a * p.d - p.b * p.c); @@ -92,11 +94,16 @@ package spine { rotationIK -= 360; else if (rotationIK < -180) rotationIK += 360; var sx : Number = bone.ascaleX; + var sy : Number = bone.ascaleY; if (stretch) { var b : Number = bone.data.length * sx, dd : Number = Math.sqrt(tx * tx + ty * ty); - if (dd > b && b > 0.0001) sx *= (dd / b - 1) * alpha + 1; + if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) { + var s : Number = (dd / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } } - bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, bone.ascaleY, bone.ashearX, bone.ashearY); + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); } /** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The diff --git a/spine-as3/spine-as3/src/spine/IkConstraintData.as b/spine-as3/spine-as3/src/spine/IkConstraintData.as index f1aae4df6..85d009676 100644 --- a/spine-as3/spine-as3/src/spine/IkConstraintData.as +++ b/spine-as3/spine-as3/src/spine/IkConstraintData.as @@ -36,7 +36,9 @@ package spine { public var target : BoneData; public var mix : Number = 1; public var bendDirection : int = 1; + public var compress : Boolean = false; public var stretch : Boolean = false; + public var uniform : Boolean = false; public function IkConstraintData(name : String) { if (name == null) throw new ArgumentError("name cannot be null."); diff --git a/spine-as3/spine-as3/src/spine/Skeleton.as b/spine-as3/spine-as3/src/spine/Skeleton.as index 9204b71e2..e39d387cd 100644 --- a/spine-as3/spine-as3/src/spine/Skeleton.as +++ b/spine-as3/spine-as3/src/spine/Skeleton.as @@ -290,9 +290,10 @@ package spine { bone.setToSetupPose(); for each (var ikConstraint : IkConstraint in ikConstraints) { - ikConstraint.bendDirection = ikConstraint._data.bendDirection; - ikConstraint.stretch = ikConstraint._data.stretch; ikConstraint.mix = ikConstraint._data.mix; + ikConstraint.bendDirection = ikConstraint._data.bendDirection; + ikConstraint.compress = ikConstraint._data.compress; + ikConstraint.stretch = ikConstraint._data.stretch; } for each (var transformConstraint : TransformConstraint in transformConstraints) { diff --git a/spine-as3/spine-as3/src/spine/SkeletonJson.as b/spine-as3/spine-as3/src/spine/SkeletonJson.as index 8ea2a2e33..390ce3e85 100644 --- a/spine-as3/spine-as3/src/spine/SkeletonJson.as +++ b/spine-as3/spine-as3/src/spine/SkeletonJson.as @@ -158,7 +158,9 @@ package spine { if (!ikConstraintData.target) throw new Error("Target bone not found: " + constraintMap["target"]); ikConstraintData.bendDirection = (!constraintMap.hasOwnProperty("bendPositive") || constraintMap["bendPositive"]) ? 1 : -1; - ikConstraintData.stretch = (!constraintMap.hasOwnProperty("stretch") || constraintMap["stretch"]); + ikConstraintData.compress = (constraintMap.hasOwnProperty("compress") && constraintMap["compress"]); + ikConstraintData.stretch = (constraintMap.hasOwnProperty("stretch") && constraintMap["stretch"]); + ikConstraintData.uniform = (constraintMap.hasOwnProperty("uniform") && constraintMap["uniform"]); ikConstraintData.mix = constraintMap.hasOwnProperty("mix") ? constraintMap["mix"] : 1; skeletonData.ikConstraints.push(ikConstraintData); @@ -532,8 +534,9 @@ package spine { for each (valueMap in values) { var mix : Number = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1; var bendDirection : int = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1; - var stretch : Boolean = (!valueMap.hasOwnProperty("stretch") || valueMap["stretch"]); - ikTimeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection, stretch); + var compress : Boolean = (valueMap.hasOwnProperty("compress") && valueMap["compress"]); + var stretch : Boolean = (valueMap.hasOwnProperty("stretch") && valueMap["stretch"]); + ikTimeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection, compress, stretch); readCurve(valueMap, ikTimeline, frameIndex); frameIndex++; } diff --git a/spine-as3/spine-as3/src/spine/animation/AnimationState.as b/spine-as3/spine-as3/src/spine/animation/AnimationState.as index 012540486..2ab546f56 100644 --- a/spine-as3/spine-as3/src/spine/animation/AnimationState.as +++ b/spine-as3/spine-as3/src/spine/animation/AnimationState.as @@ -314,10 +314,10 @@ package spine.animation { // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. var r1 : Number = blend == MixBlend.setup ? bone.data.rotation : bone.rotation; var total : Number, diff : Number = r2 - r1; + diff -= (16384 - int((16384.499999999996 - diff / 360))) * 360; if (diff == 0) { total = timelinesRotation[i]; - } else { - diff -= (16384 - int((16384.499999999996 - diff / 360))) * 360; + } else { var lastTotal : Number, lastDiff : Number; if (firstFrame) { lastTotal = 0; diff --git a/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as b/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as index 66b35379c..4c9dd80e3 100644 --- a/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as +++ b/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as @@ -34,11 +34,11 @@ package spine.animation { import spine.Skeleton; public class IkConstraintTimeline extends CurveTimeline { - static public const ENTRIES : int = 4; - static internal const PREV_TIME : int = -4, PREV_MIX : int = -3, PREV_BEND_DIRECTION : int = -2, PREV_STRETCH : int = -1; - static internal const MIX : int = 1, BEND_DIRECTION : int = 2, STRETCH : int = 3; + 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; public var ikConstraintIndex : int; - public var frames : Vector.; // time, mix, bendDirection, ... + public var frames : Vector.; // time, mix, bendDirection, compress, stretch, ... public function IkConstraintTimeline(frameCount : int) { super(frameCount); @@ -50,11 +50,12 @@ 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, stretch: Boolean) : void { + public function setFrame(frameIndex : int, time : Number, mix : Number, bendDirection : int, compress: Boolean, stretch: Boolean) : void { frameIndex *= ENTRIES; frames[frameIndex] = time; frames[int(frameIndex + MIX)] = mix; frames[int(frameIndex + BEND_DIRECTION)] = bendDirection; + frames[int(frameIndex + COMPRESS)] = compress ? 1 : 0; frames[int(frameIndex + STRETCH)] = stretch ? 1 : 0; } @@ -65,11 +66,13 @@ package spine.animation { case MixBlend.setup: constraint.mix = constraint.data.mix; 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.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; constraint.stretch = constraint.data.stretch; } return; @@ -81,15 +84,18 @@ package spine.animation { if (direction == MixDirection.Out) { constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; constraint.stretch = constraint.data.stretch; } else { constraint.bendDirection = int(frames[frames.length + PREV_BEND_DIRECTION]); + constraint.compress = int(frames[frames.length + PREV_COMPRESS]) != 0; constraint.stretch = int(frames[frames.length + PREV_STRETCH]) != 0; } } else { constraint.mix += (frames[frames.length + PREV_MIX] - constraint.mix) * alpha; if (direction == MixDirection.In) { constraint.bendDirection = int(frames[frames.length + PREV_BEND_DIRECTION]); + constraint.compress = int(frames[frames.length + PREV_COMPRESS]) != 0; constraint.stretch = int(frames[frames.length + PREV_STRETCH]) != 0; } } @@ -106,15 +112,18 @@ package spine.animation { constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; if (direction == MixDirection.Out) { constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; constraint.stretch = constraint.data.stretch; } else { constraint.bendDirection = int(frames[frame + PREV_BEND_DIRECTION]); + constraint.compress = int(frames[frame + PREV_COMPRESS]) != 0; constraint.stretch = int(frames[frame + PREV_STRETCH]) != 0; } } else { constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; if (direction == MixDirection.In) { constraint.bendDirection = int(frames[frame + PREV_BEND_DIRECTION]); + constraint.compress = int(frames[frame + PREV_COMPRESS]) != 0; constraint.stretch = int(frames[frame + PREV_STRETCH]) != 0; } } diff --git a/spine-starling/spine-starling-example/lib/spine-as3.swc b/spine-starling/spine-starling-example/lib/spine-as3.swc index 2839d51b4..e57853ed4 100644 Binary files a/spine-starling/spine-starling-example/lib/spine-as3.swc and b/spine-starling/spine-starling-example/lib/spine-as3.swc differ diff --git a/spine-starling/spine-starling-example/lib/spine-starling.swc b/spine-starling/spine-starling-example/lib/spine-starling.swc index f8a13aa78..24edf736a 100644 Binary files a/spine-starling/spine-starling-example/lib/spine-starling.swc and b/spine-starling/spine-starling-example/lib/spine-starling.swc differ diff --git a/spine-starling/spine-starling/lib/spine-as3.swc b/spine-starling/spine-starling/lib/spine-as3.swc index 2839d51b4..e57853ed4 100644 Binary files a/spine-starling/spine-starling/lib/spine-as3.swc and b/spine-starling/spine-starling/lib/spine-as3.swc differ