mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Merge branch '3.7-beta' into 3.7-beta-cpp
This commit is contained in:
commit
31ca0b7ce8
@ -81,6 +81,7 @@ function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
|
|||||||
return { skeleton = skeleton, state = animationState }
|
return { skeleton = skeleton, state = animationState }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-stretchy-ik.json", 40, 300, 0.5, "sneak"))
|
||||||
table.insert(skeletons, loadSkeleton("coin.atlas", "coin-pro.json", 240, 300, 0.4, "rotate"))
|
table.insert(skeletons, loadSkeleton("coin.atlas", "coin-pro.json", 240, 300, 0.4, "rotate"))
|
||||||
table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy-ess.json", 240, 300, 0.4, "walk"))
|
table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy-ess.json", 240, 300, 0.4, "walk"))
|
||||||
table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
|
table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
|
||||||
|
|||||||
@ -1169,14 +1169,16 @@ function Animation.DrawOrderTimeline.new (frameCount)
|
|||||||
end
|
end
|
||||||
|
|
||||||
Animation.IkConstraintTimeline = {}
|
Animation.IkConstraintTimeline = {}
|
||||||
Animation.IkConstraintTimeline.ENTRIES = 3
|
Animation.IkConstraintTimeline.ENTRIES = 4
|
||||||
function Animation.IkConstraintTimeline.new (frameCount)
|
function Animation.IkConstraintTimeline.new (frameCount)
|
||||||
local ENTRIES = Animation.IkConstraintTimeline.ENTRIES
|
local ENTRIES = Animation.IkConstraintTimeline.ENTRIES
|
||||||
local PREV_TIME = -3
|
local PREV_TIME = -4
|
||||||
local PREV_MIX = -2
|
local PREV_MIX = -3
|
||||||
local PREV_BEND_DIRECTION = -1
|
local PREV_BEND_DIRECTION = -2
|
||||||
|
local PREV_STRETCH = -1
|
||||||
local MIX = 1
|
local MIX = 1
|
||||||
local BEND_DIRECTION = 2
|
local BEND_DIRECTION = 2
|
||||||
|
local STRETCH = 1
|
||||||
|
|
||||||
local self = Animation.CurveTimeline.new(frameCount)
|
local self = Animation.CurveTimeline.new(frameCount)
|
||||||
self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, bendDirection, ...
|
self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, bendDirection, ...
|
||||||
@ -1187,11 +1189,16 @@ function Animation.IkConstraintTimeline.new (frameCount)
|
|||||||
return TimelineType.ikConstraint * SHL_24 + self.ikConstraintIndex
|
return TimelineType.ikConstraint * SHL_24 + self.ikConstraintIndex
|
||||||
end
|
end
|
||||||
|
|
||||||
function self:setFrame (frameIndex, time, mix, bendDirection)
|
function self:setFrame (frameIndex, time, mix, bendDirection, stretch)
|
||||||
frameIndex = frameIndex * ENTRIES
|
frameIndex = frameIndex * ENTRIES
|
||||||
self.frames[frameIndex] = time
|
self.frames[frameIndex] = time
|
||||||
self.frames[frameIndex + MIX] = mix
|
self.frames[frameIndex + MIX] = mix
|
||||||
self.frames[frameIndex + BEND_DIRECTION] = bendDirection
|
self.frames[frameIndex + BEND_DIRECTION] = bendDirection
|
||||||
|
if (stretch) then
|
||||||
|
self.frames[frameIndex + STRETCH] = 1
|
||||||
|
else
|
||||||
|
self.frames[frameIndex + STRETCH] = 0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
|
function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
|
||||||
@ -1202,9 +1209,11 @@ function Animation.IkConstraintTimeline.new (frameCount)
|
|||||||
if blend == MixBlend.setup then
|
if blend == MixBlend.setup then
|
||||||
constraint.mix = constraint.data.mix
|
constraint.mix = constraint.data.mix
|
||||||
constraint.bendDirection = constraint.data.bendDirection
|
constraint.bendDirection = constraint.data.bendDirection
|
||||||
|
constraint.stretch = constraint.data.stretch
|
||||||
elseif blend == MixBlend.first then
|
elseif blend == MixBlend.first then
|
||||||
constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
|
constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
|
||||||
constraint.bendDirection = constraint.data.bendDirection
|
constraint.bendDirection = constraint.data.bendDirection
|
||||||
|
constraint.stretch = constraint.data.stretch
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -1214,12 +1223,17 @@ function Animation.IkConstraintTimeline.new (frameCount)
|
|||||||
constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
|
constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
|
||||||
if direction == MixDirection.out then
|
if direction == MixDirection.out then
|
||||||
constraint.bendDirection = constraint.data.bendDirection
|
constraint.bendDirection = constraint.data.bendDirection
|
||||||
|
constraint.stretch = constraint.data.stretch
|
||||||
else
|
else
|
||||||
constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]);
|
constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]);
|
||||||
|
if (math_floor(frames[zlen(frames) + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
constraint.mix = constraint.mix + (frames[frames.length + PREV_MIX] - constraint.mix) * alpha;
|
constraint.mix = constraint.mix + (frames[frames.length + PREV_MIX] - constraint.mix) * alpha;
|
||||||
if direction == MixDirection._in then constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]) end
|
if direction == MixDirection._in then
|
||||||
|
constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION])
|
||||||
|
if (math_floor(frames[zlen(frames) + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -1235,12 +1249,17 @@ function Animation.IkConstraintTimeline.new (frameCount)
|
|||||||
constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
|
constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
|
||||||
if direction == MixDirection.out then
|
if direction == MixDirection.out then
|
||||||
constraint.bendDirection = constraint.data.bendDirection
|
constraint.bendDirection = constraint.data.bendDirection
|
||||||
|
constraint.stretch = constraint.data.stretch
|
||||||
else
|
else
|
||||||
constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
|
constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
|
||||||
|
if (math_floor(frames[frame + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
|
constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
|
||||||
if direction == MixDirection._in then constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION]) end
|
if direction == MixDirection._in then
|
||||||
|
constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
|
||||||
|
if (math_floor(frames[frame + PREV_STRETCH]) == 1) then constraint.stretch = true else constraint.stretch = false end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,7 @@ function IkConstraint.new (data, skeleton)
|
|||||||
bones = {},
|
bones = {},
|
||||||
target = nil,
|
target = nil,
|
||||||
mix = data.mix,
|
mix = data.mix,
|
||||||
|
stretch = data.stretch,
|
||||||
bendDirection = data.bendDirection,
|
bendDirection = data.bendDirection,
|
||||||
}
|
}
|
||||||
setmetatable(self, IkConstraint)
|
setmetatable(self, IkConstraint)
|
||||||
@ -74,13 +75,13 @@ function IkConstraint:update ()
|
|||||||
local bones = self.bones
|
local bones = self.bones
|
||||||
local boneCount = #bones
|
local boneCount = #bones
|
||||||
if boneCount == 1 then
|
if boneCount == 1 then
|
||||||
self:apply1(bones[1], target.worldX, target.worldY, self.mix)
|
self:apply1(bones[1], target.worldX, target.worldY, self.stretch, self.mix)
|
||||||
elseif boneCount == 2 then
|
elseif boneCount == 2 then
|
||||||
self:apply2(bones[1], bones[2], target.worldX, target.worldY, self.bendDirection, self.mix)
|
self:apply2(bones[1], bones[2], target.worldX, target.worldY, self.bendDirection, self.stretch, self.mix)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function IkConstraint:apply1 (bone, targetX, targetY, alpha)
|
function IkConstraint:apply1 (bone, targetX, targetY, stretch, alpha)
|
||||||
if not bone.appliedValid then bone:updateAppliedTransform() end
|
if not bone.appliedValid then bone:updateAppliedTransform() end
|
||||||
local p = bone.parent
|
local p = bone.parent
|
||||||
local id = 1 / (p.a * p.d - p.b * p.c)
|
local id = 1 / (p.a * p.d - p.b * p.c)
|
||||||
@ -95,10 +96,15 @@ function IkConstraint:apply1 (bone, targetX, targetY, alpha)
|
|||||||
elseif (rotationIK < -180) then
|
elseif (rotationIK < -180) then
|
||||||
rotationIK = rotationIK + 360
|
rotationIK = rotationIK + 360
|
||||||
end
|
end
|
||||||
bone:updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY)
|
local sx = bone.ascaleX
|
||||||
|
if stretch then
|
||||||
|
local dd = math_sqrt(tx * tx + ty * ty)
|
||||||
|
if dd > bone.data.length * sx then sx = sx * ((dd / (bone.data.length * sx) - 1) * alpha + 1) end
|
||||||
|
end
|
||||||
|
bone:updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, bone.ascaleY, bone.ashearX, bone.ashearY)
|
||||||
end
|
end
|
||||||
|
|
||||||
function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, stretch, alpha)
|
||||||
if alpha == 0 then
|
if alpha == 0 then
|
||||||
child:updateWorldTransform()
|
child:updateWorldTransform()
|
||||||
return
|
return
|
||||||
@ -108,6 +114,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
|||||||
local px = parent.ax
|
local px = parent.ax
|
||||||
local py = parent.ay
|
local py = parent.ay
|
||||||
local psx = parent.ascaleX
|
local psx = parent.ascaleX
|
||||||
|
local sx = psx
|
||||||
local psy = parent.ascaleY
|
local psy = parent.ascaleY
|
||||||
local csx = child.ascaleX
|
local csx = child.ascaleX
|
||||||
local os1 = 0
|
local os1 = 0
|
||||||
@ -159,6 +166,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
|||||||
local y = targetY - pp.worldY
|
local y = targetY - pp.worldY
|
||||||
local tx = (x * d - y * b) * id - px
|
local tx = (x * d - y * b) * id - px
|
||||||
local ty = (y * a - x * c) * id - py
|
local ty = (y * a - x * c) * id - py
|
||||||
|
local dd = tx * tx + ty * ty
|
||||||
x = cwx - pp.worldX
|
x = cwx - pp.worldX
|
||||||
y = cwy - pp.worldY
|
y = cwy - pp.worldY
|
||||||
local dx = (x * d - y * b) * id - px
|
local dx = (x * d - y * b) * id - px
|
||||||
@ -170,11 +178,12 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
|||||||
|
|
||||||
if u then
|
if u then
|
||||||
l2 = l2 * psx
|
l2 = l2 * psx
|
||||||
local cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2)
|
local cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2)
|
||||||
if cos < -1 then
|
if cos < -1 then
|
||||||
cos = -1
|
cos = -1
|
||||||
elseif cos > 1 then
|
elseif cos > 1 then
|
||||||
cos = 1
|
cos = 1
|
||||||
|
if stretch then sx = sx * ((math_sqrt(dd) / (l1 + l2) - 1) * alpha + 1) end
|
||||||
end
|
end
|
||||||
a2 = math_acos(cos) * bendDir
|
a2 = math_acos(cos) * bendDir
|
||||||
a = l1 + l2 * cos
|
a = l1 + l2 * cos
|
||||||
@ -186,7 +195,6 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
|||||||
b = psy * l2
|
b = psy * l2
|
||||||
local aa = a * a
|
local aa = a * a
|
||||||
local bb = b * b
|
local bb = b * b
|
||||||
local dd = tx * tx + ty * ty
|
|
||||||
local ta = math_atan2(ty, tx);
|
local ta = math_atan2(ty, tx);
|
||||||
c = bb * l1 * l1 + aa * dd - aa * bb
|
c = bb * l1 * l1 + aa * dd - aa * bb
|
||||||
local c1 = -2 * bb * l1
|
local c1 = -2 * bb * l1
|
||||||
@ -252,7 +260,7 @@ function IkConstraint:apply2 (parent, child, targetX, targetY, bendDir, alpha)
|
|||||||
elseif a1 < -180 then
|
elseif a1 < -180 then
|
||||||
a1 = a1 + 360
|
a1 = a1 + 360
|
||||||
end
|
end
|
||||||
parent:updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0)
|
parent:updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, parent.ascaleY, 0, 0)
|
||||||
rotation = child.rotation
|
rotation = child.rotation
|
||||||
a2 = (math_deg(a2 + os) - child.ashearX) * s2 + os2 - rotation
|
a2 = (math_deg(a2 + os) - child.ashearX) * s2 + os2 - rotation
|
||||||
if a2 > 180 then
|
if a2 > 180 then
|
||||||
|
|||||||
@ -38,6 +38,7 @@ function IkConstraintData.new (name)
|
|||||||
bones = {},
|
bones = {},
|
||||||
target = nil,
|
target = nil,
|
||||||
bendDirection = 1,
|
bendDirection = 1,
|
||||||
|
stretch = false,
|
||||||
mix = 1
|
mix = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -339,6 +339,7 @@ function Skeleton:setBonesToSetupPose ()
|
|||||||
|
|
||||||
for _,ikConstraint in ipairs(self.ikConstraints) do
|
for _,ikConstraint in ipairs(self.ikConstraints) do
|
||||||
ikConstraint.bendDirection = ikConstraint.data.bendDirection
|
ikConstraint.bendDirection = ikConstraint.data.bendDirection
|
||||||
|
ikConstraint.stretch = ikConstraint.data.stretch
|
||||||
ikConstraint.mix = ikConstraint.data.mix
|
ikConstraint.mix = ikConstraint.data.mix
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -165,6 +165,7 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
if not data.target then error("Target bone not found: " .. targetName) end
|
if not data.target then error("Target bone not found: " .. targetName) end
|
||||||
|
|
||||||
if constraintMap["bendPositive"] == false then data.bendDirection = -1 else data.bendDirection = 1 end
|
if constraintMap["bendPositive"] == false then data.bendDirection = -1 else data.bendDirection = 1 end
|
||||||
|
if constraintMap["stretch"] == false then data.stretch = false else data.stretch = true end
|
||||||
data.mix = getValue(constraintMap, "mix", 1)
|
data.mix = getValue(constraintMap, "mix", 1)
|
||||||
|
|
||||||
table_insert(skeletonData.ikConstraints, data)
|
table_insert(skeletonData.ikConstraints, data)
|
||||||
@ -612,7 +613,9 @@ function SkeletonJson.new (attachmentLoader)
|
|||||||
if valueMap["mix"] ~= nil then mix = valueMap["mix"] end
|
if valueMap["mix"] ~= nil then mix = valueMap["mix"] end
|
||||||
local bendPositive = 1
|
local bendPositive = 1
|
||||||
if valueMap["bendPositive"] == false then bendPositive = -1 end
|
if valueMap["bendPositive"] == false then bendPositive = -1 end
|
||||||
timeline:setFrame(frameIndex, valueMap["time"], mix, bendPositive)
|
local stretch = true
|
||||||
|
if valueMap["stretch"] == false then stretch = false end
|
||||||
|
timeline:setFrame(frameIndex, valueMap["time"], mix, bendPositive, stretch)
|
||||||
readCurve(valueMap, timeline, frameIndex)
|
readCurve(valueMap, timeline, frameIndex)
|
||||||
frameIndex = frameIndex + 1
|
frameIndex = frameIndex + 1
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user