diff --git a/spine-as3/spine-as3-example/lib/spine-as3.swc b/spine-as3/spine-as3-example/lib/spine-as3.swc index 7a5a5bffd..0454bc1ec 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 32b9b1c53..06ab36498 100644 --- a/spine-as3/spine-as3/src/spine/IkConstraint.as +++ b/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; diff --git a/spine-as3/spine-as3/src/spine/IkConstraintData.as b/spine-as3/spine-as3/src/spine/IkConstraintData.as index bb7ef698a..104c955d1 100644 --- a/spine-as3/spine-as3/src/spine/IkConstraintData.as +++ b/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); diff --git a/spine-as3/spine-as3/src/spine/Skeleton.as b/spine-as3/spine-as3/src/spine/Skeleton.as index 6f5cd5d84..e64d94fad 100644 --- a/spine-as3/spine-as3/src/spine/Skeleton.as +++ b/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; diff --git a/spine-as3/spine-as3/src/spine/SkeletonBinary.as b/spine-as3/spine-as3/src/spine/SkeletonBinary.as index 75f549c66..1a46fd34d 100644 --- a/spine-as3/spine-as3/src/spine/SkeletonBinary.as +++ b/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); } diff --git a/spine-as3/spine-as3/src/spine/SkeletonJson.as b/spine-as3/spine-as3/src/spine/SkeletonJson.as index 5c75d6fef..3ffe5a9e6 100644 --- a/spine-as3/spine-as3/src/spine/SkeletonJson.as +++ b/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++; } diff --git a/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as b/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as index e15b8214d..f932e763f 100644 --- a/spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as +++ b/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.; // 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; diff --git a/spine-starling/spine-starling-example/lib/spine-as3.swc b/spine-starling/spine-starling-example/lib/spine-as3.swc index 7a5a5bffd..0454bc1ec 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/lib/spine-as3.swc b/spine-starling/spine-starling/lib/spine-as3.swc index 7a5a5bffd..0454bc1ec 100644 Binary files a/spine-starling/spine-starling/lib/spine-as3.swc and b/spine-starling/spine-starling/lib/spine-as3.swc differ