[lua] Ported additive blending, see #1060, see #1029

This commit is contained in:
badlogic 2018-01-29 15:37:13 +01:00
parent 713f43a247
commit 54e99f1454
4 changed files with 335 additions and 200 deletions

View File

@ -81,12 +81,12 @@ 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("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"))
-- table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-pro.json", 240, 300, 0.8, "walk", "goblin")) table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-pro.json", 240, 300, 0.8, "walk", "goblin"))
table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak")) table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak"))
-- table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive")) table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive"))
table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow")) table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow"))
local triangulator = spine.Triangulator.new() local triangulator = spine.Triangulator.new()

View File

@ -54,7 +54,7 @@ function Animation.new (name, timelines, duration)
duration = duration duration = duration
} }
function self:apply (skeleton, lastTime, time, loop, events, alpha, pose, direction) function self:apply (skeleton, lastTime, time, loop, events, alpha, blend, direction)
if not skeleton then error("skeleton cannot be nil.", 2) end if not skeleton then error("skeleton cannot be nil.", 2) end
if loop and duration > 0 then if loop and duration > 0 then
@ -63,7 +63,7 @@ function Animation.new (name, timelines, duration)
end end
for i,timeline in ipairs(self.timelines) do for i,timeline in ipairs(self.timelines) do
timeline:apply(skeleton, lastTime, time, events, alpha, pose, direction) timeline:apply(skeleton, lastTime, time, events, alpha, blend, direction)
end end
end end
@ -113,12 +113,13 @@ local function linearSearch (values, target, step)
return -1 return -1
end end
Animation.MixPose = { Animation.MixBlend = {
setup = 0, setup = 0,
current = 1, first = 1,
currentLayered = 2 replace = 2,
add = 3
} }
local MixPose = Animation.MixPose local MixBlend = Animation.MixBlend
Animation.MixDirection = { Animation.MixDirection = {
_in = 0, out = 1 _in = 0, out = 1
@ -255,28 +256,30 @@ function Animation.RotateTimeline.new (frameCount)
self.frames[frameIndex + ROTATION] = degrees self.frames[frameIndex + ROTATION] = degrees
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local bone = skeleton.bones[self.boneIndex] local bone = skeleton.bones[self.boneIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.rotation = bone.data.rotation bone.rotation = bone.data.rotation
elseif pose == MixPose.current then elseif blend == MixBlend.first then
local r = bone.data.rotation - bone.rotation local r = bone.data.rotation - bone.rotation
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180. bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
bone.rotation = bone.rotation + r * alpha
end end
return return
end end
if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
if pose == MixPose.setup then local r = frames[zlen(frames) + PREV_ROTATION]
bone.rotation = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] * alpha if blend == MixBlend.setup then
else bone.rotation = bone.data.rotation + r * alpha
local r = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] - bone.rotation elseif blend == MixBlend.first or blend == MixBlend.replace then
r = r + bone.data.rotation - bone.rotation
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
bone.rotation = bone.rotation + r * alpha; bone.rotation = bone.rotation + r * alpha;
elseif blend == MixBlend.add then
bone.rotation = bone.rotation + r * alpha;
end end
return; return;
end end
@ -288,15 +291,14 @@ function Animation.RotateTimeline.new (frameCount)
local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)) local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
local r = frames[frame + ROTATION] - prevRotation local r = frames[frame + ROTATION] - prevRotation
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 r = prevRotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * percent
r = prevRotation + r * percent if blend == MixBlend.setup then
if pose == MixPose.setup then bone.rotation = bone.data.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 elseif blend == MixBlend.first or blend == MixBlend.replace then
bone.rotation = bone.data.rotation + r * alpha r = r + bone.data.rotation - bone.rotation;
else bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
r = bone.data.rotation + r - bone.rotation; elseif blend == MixBlend.add then
r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 bone.rotation = bone.rotation + (r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360) * alpha
bone.rotation = bone.rotation + r * alpha
end end
end end
@ -329,15 +331,15 @@ function Animation.TranslateTimeline.new (frameCount)
self.frames[frameIndex + Y] = y self.frames[frameIndex + Y] = y
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local bone = skeleton.bones[self.boneIndex] local bone = skeleton.bones[self.boneIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.x = bone.data.x bone.x = bone.data.x
bone.y = bone.data.y bone.y = bone.data.y
elseif pose == MixPose.current then elseif blend == MixBlend.first then
bone.x = bone.x + (bone.data.x - bone.x) * alpha bone.x = bone.x + (bone.data.x - bone.x) * alpha
bone.y = bone.y + (bone.data.y - bone.y) * alpha bone.y = bone.y + (bone.data.y - bone.y) * alpha
end end
@ -361,12 +363,15 @@ function Animation.TranslateTimeline.new (frameCount)
x = x + (frames[frame + X] - x) * percent x = x + (frames[frame + X] - x) * percent
y = y + (frames[frame + Y] - y) * percent y = y + (frames[frame + Y] - y) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.x = bone.data.x + x * alpha bone.x = bone.data.x + x * alpha
bone.y = bone.data.y + y * alpha bone.y = bone.data.y + y * alpha
else elseif blend == MixBlend.first or blend == MixBlend.replace then
bone.x = bone.x + (bone.data.x + x - bone.x) * alpha bone.x = bone.x + (bone.data.x + x - bone.x) * alpha
bone.y = bone.y + (bone.data.y + y - bone.y) * alpha bone.y = bone.y + (bone.data.y + y - bone.y) * alpha
elseif blend == MixBlend.add then
bone.x = bone.x + x * alpha
bone.y = bone.y + y * alpha
end end
end end
@ -390,15 +395,15 @@ function Animation.ScaleTimeline.new (frameCount)
return TimelineType.scale * SHL_24 + self.boneIndex return TimelineType.scale * SHL_24 + self.boneIndex
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local bone = skeleton.bones[self.boneIndex] local bone = skeleton.bones[self.boneIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.scaleX = bone.data.scaleX bone.scaleX = bone.data.scaleX
bone.scaleY = bone.data.scaleY bone.scaleY = bone.data.scaleY
elseif pose == MixPose.current then elseif blend == MixBlend.first then
bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha
bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha
end end
@ -423,28 +428,51 @@ function Animation.ScaleTimeline.new (frameCount)
y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY
end end
if alpha == 1 then if alpha == 1 then
bone.scaleX = x if blend == MixBlend.add then
bone.scaleY = y bone.scaleX = bone.scaleX + x - bone.data.scaleX
bone.scaleY = bone.scaleY + y - bone.data.scaleY
else
bone.scaleX = x
bone.scaleY = y
end
else else
local bx = 0 local bx = 0
local by = 0 local by = 0
if pose == MixPose.setup then if direction == MixDirection.out then
bx = bone.data.scaleX if blend == MixBlend.setup then
by = bone.data.scaleY bx = bone.data.scaleX
by = bone.data.scaleY
bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bx) * alpha
bone.scaleY = by + (math_abs(y) * math_signum(by) - by) * alpha
elseif blend == MixBlend.first or blend == MixBlend.replace then
bx = bone.scaleX
by = bone.scaleY
bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bx) * alpha
bone.scaleY = by + (math_abs(y) * math_signum(by) - by) * alpha
elseif blend == MixBlend.add then
bx = bone.scaleX
by = bone.scaleY
bone.scaleX = bx + (math_abs(x) * math_signum(bx) - bone.data.scaleX) * alpha
bone.scaleY = by + (math_abs(y) * math_signum(by) - bone.data.scaleY) * alpha
end
else else
bx = bone.scaleX if blend == MixBlend.setup then
by = bone.scaleY bx = math_abs(bone.data.scaleX) * math_signum(x)
by = math_abs(bone.data.scaleY) * math_signum(y)
bone.scaleX = bx + (x - bx) * alpha
bone.scaleY = by + (y - by) * alpha
elseif blend == MixBlend.first or blend == MixBlend.replace then
bx = math_abs(bone.scaleX) * math_signum(x)
by = math_abs(bone.scaleY) * math_signum(y)
bone.scaleX = bx + (x - bx) * alpha
bone.scaleY = by + (y - by) * alpha
elseif blend == MixBlend.add then
bx = math_signum(x)
by = math_signum(y)
bone.scaleX = math_abs(bone.scaleX) * bx + (x - math_abs(bone.data.scaleX) * bx) * alpha
bone.scaleY = math_abs(bone.scaleY) * by + (y - math_abs(bone.data.scaleY) * by) * alpha
end
end end
-- Mixing out uses sign of setup or current pose, else use sign of key.
if direction == MixDirection.out then
x = math_abs(x) * math_signum(bx)
y = math_abs(y) * math_signum(by)
else
bx = math_abs(bx) * math_signum(x)
by = math_abs(by) * math_signum(y)
end
bone.scaleX = bx + (x - bx) * alpha
bone.scaleY = by + (y - by) * alpha
end end
end end
@ -468,15 +496,15 @@ function Animation.ShearTimeline.new (frameCount)
return TimelineType.shear * SHL_24 + self.boneIndex return TimelineType.shear * SHL_24 + self.boneIndex
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local bone = skeleton.bones[self.boneIndex] local bone = skeleton.bones[self.boneIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.shearX = bone.data.shearX bone.shearX = bone.data.shearX
bone.shearY = bone.data.shearY bone.shearY = bone.data.shearY
elseif pose == MixPose.current then elseif blend == MixBlend.first then
bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha
bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha
end end
@ -500,12 +528,15 @@ function Animation.ShearTimeline.new (frameCount)
x = x + (frames[frame + X] - x) * percent x = x + (frames[frame + X] - x) * percent
y = y + (frames[frame + Y] - y) * percent y = y + (frames[frame + Y] - y) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
bone.shearX = bone.data.shearX + x * alpha bone.shearX = bone.data.shearX + x * alpha
bone.shearY = bone.data.shearY + y * alpha bone.shearY = bone.data.shearY + y * alpha
else elseif blend == MixBlend.first or blend == MixBlend.replace then
bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha
bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha
elseif blend == MixBlend.add then
bone.shearX = bone.shearX + x * alpha
bone.shearY = bone.shearY + y * alpha
end end
end end
@ -544,13 +575,13 @@ function Animation.ColorTimeline.new (frameCount)
self.frames[frameIndex + A] = a self.frames[frameIndex + A] = a
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local slot = skeleton.slots[self.slotIndex] local slot = skeleton.slots[self.slotIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
slot.color:setFrom(slot.data.color) slot.color:setFrom(slot.data.color)
elseif pose == MixPose.current then elseif blend == MixBlend.first then
local color = slot.color local color = slot.color
local setup = slot.data.color local setup = slot.data.color
color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
@ -586,7 +617,7 @@ function Animation.ColorTimeline.new (frameCount)
slot.color:set(r, g, b, a) slot.color:set(r, g, b, a)
else else
local color = slot.color local color = slot.color
if pose == MixPose.setup then color:setFrom(slot.data.color) end if blend == MixBlend.setup then color:setFrom(slot.data.color) end
color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha) color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha)
end end
end end
@ -635,14 +666,14 @@ function Animation.TwoColorTimeline.new (frameCount)
self.frames[frameIndex + B2] = b2 self.frames[frameIndex + B2] = b2
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local slot = skeleton.slots[self.slotIndex] local slot = skeleton.slots[self.slotIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup then
slot.color:setFrom(slot.data.color) slot.color:setFrom(slot.data.color)
slot.darkColor:setFrom(slot.data.darkColor) slot.darkColor:setFrom(slot.data.darkColor)
elseif pose == MixPose.current then elseif blend == MixBlend.first then
local light = slot.color local light = slot.color
local dark = slot.darkColor local dark = slot.darkColor
local setupLight = slot.data.color local setupLight = slot.data.color
@ -692,7 +723,7 @@ function Animation.TwoColorTimeline.new (frameCount)
else else
local light = slot.color local light = slot.color
local dark = slot.darkColor local dark = slot.darkColor
if pose == MixPose.setup then if blend == MixBlend.setup then
light:setFrom(slot.data.color) light:setFrom(slot.data.color)
dark:setFrom(slot.data.darkColor) dark:setFrom(slot.data.darkColor)
end end
@ -726,10 +757,10 @@ function Animation.AttachmentTimeline.new (frameCount)
return TimelineType.attachment * SHL_24 + self.slotIndex return TimelineType.attachment * SHL_24 + self.slotIndex
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local slot = skeleton.slots[self.slotIndex] local slot = skeleton.slots[self.slotIndex]
local attachmentName local attachmentName
if direction == MixDirection.out and pose == MixPose.setup then if direction == MixDirection.out and blend == MixBlend.setup then
attachmentName = slot.data.attachmentName attachmentName = slot.data.attachmentName
if not attachmentName then if not attachmentName then
slot:setAttachment(nil) slot:setAttachment(nil)
@ -741,7 +772,7 @@ function Animation.AttachmentTimeline.new (frameCount)
local frames = self.frames local frames = self.frames
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup or blend == MixBlend.first then
attachmentName = slot.data.attachmentName attachmentName = slot.data.attachmentName
if not attachmentName then if not attachmentName then
slot:setAttachment(nil) slot:setAttachment(nil)
@ -788,7 +819,7 @@ function Animation.DeformTimeline.new (frameCount)
self.frameVertices[frameIndex] = vertices self.frameVertices[frameIndex] = vertices
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local slot = skeleton.slots[self.slotIndex] local slot = skeleton.slots[self.slotIndex]
local slotAttachment = slot.attachment local slotAttachment = slot.attachment
if not slotAttachment then return end if not slotAttachment then return end
@ -797,17 +828,17 @@ function Animation.DeformTimeline.new (frameCount)
local frames = self.frames local frames = self.frames
local verticesArray = slot.attachmentVertices local verticesArray = slot.attachmentVertices
if #(verticesArray) == 0 then alpha = 1 end if #(verticesArray) == 0 then blend = MixBlend.setup end
local frameVertices = self.frameVertices local frameVertices = self.frameVertices
local vertexCount = #(frameVertices[0]) local vertexCount = #(frameVertices[0])
if time < frames[0] then if time < frames[0] then
local vertexAttachment = slotAttachment; local vertexAttachment = slotAttachment;
if pose == MixPose.setup then if blend == MixBlend.setup then
slot.attachmentVertices = {} slot.attachmentVertices = {}
return; return;
elseif pose == MixPose.current then elseif blend == MixBlend.first then
if (alpha == 1) then if (alpha == 1) then
slot.attachmentVertices = {} slot.attachmentVertices = {}
return; return;
@ -837,37 +868,90 @@ function Animation.DeformTimeline.new (frameCount)
if time >= frames[zlen(frames) - 1] then -- Time is after last frame. if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
local lastVertices = frameVertices[zlen(frames) - 1] local lastVertices = frameVertices[zlen(frames) - 1]
if alpha == 1 then if alpha == 1 then
-- Vertex positions or deform offsets, no alpha. if blend == MixBlend.add then
local i = 1 local vertexAttachment = slotAttachment
while i <= vertexCount do if vertexAttachment.bones == nil then
vertices[i] = lastVertices[i] -- Unweighted vertex positions, with alpha.
i = i + 1 local setupVertices = vertexAttachment.vertices
end local i = 1
elseif pose == MixPose.setup then while i <= vertexCount do
local vertexAttachment = slotAttachment vertices[i] = vertices[i] + lastVertices[i] - setupVertices[i]
if vertexAttachment.bones == nil then i = i + 1
-- Unweighted vertex positions, with alpha. end
local setupVertices = vertexAttachment.vertices else
local i = 1 -- Weighted deform offsets, with alpha.
while i <= vertexCount do local i = 1
local setup = setupVertices[i] while i <= vertexCount do
vertices[i] = setup + (lastVertices[i] - setup) * alpha vertices[i] = vertices[i] + lastVertices[i]
i = i + 1 i = i + 1
end
end end
else else
-- Weighted deform offsets, with alpha.
local i = 1 local i = 1
while i <= vertexCount do while i <= vertexCount do
vertices[i] = lastVertices[i] * alpha vertices[i] = lastVertices[i]
i = i + 1 i = i + 1
end end
end end
else else
-- Vertex positions or deform offsets, with alpha. if blend == MixBlend.setup then
local i = 1 local vertexAttachment = slotAttachment
while i <= vertexCount do if vertexAttachment.bones == nil then
vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha -- Unweighted vertex positions, with alpha.
i = i + 1 local setupVertices = vertexAttachment.vertices
local i = 1
while i <= vertexCount do
local setup = setupVertices[i]
vertices[i] = setup + (lastVertices[i] - setup) * alpha
i = i + 1
end
else
-- Weighted deform offsets, with alpha.
local i = 1
while i <= vertexCount do
vertices[i] = lastVertices[i] * alpha
i = i + 1
end
end
elseif blend == MixBlend.first or blend == MixBlend.replace then
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha
i = i + 1
end
local vertexAttachment = slotAttachment
if vertexAttachment.bones == nil then
local setupVertices = vertexAttachment.vertices
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + (lastVertices[i] - setupVertices[i]) * alpha
i = i + 1
end
else
-- Weighted deform offsets, with alpha.
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + lastVertices[i] * alpha
i = i + 1
end
end
elseif blend == MixBlend.add then
local vertexAttachment = slotAttachment
if vertexAttachment.bones == nil then
local setupVertices = vertexAttachment.vertices
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + (lastVertices[i] - setupVertices[i]) * alpha
i = i + 1
end
else
-- Weighted deform offsets, with alpha.
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + lastVertices[i] * alpha
i = i + 1
end
end
end end
end end
return; return;
@ -881,41 +965,82 @@ function Animation.DeformTimeline.new (frameCount)
local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)) local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
if alpha == 1 then if alpha == 1 then
-- Vertex positions or deform offsets, no alpha. if blend == MixBlend.add then
local i = 1 local vertexAttachment = slotAttachment
while i <= vertexCount do if vertexAttachment.bones == nil then
local prev = prevVertices[i] -- Unweighted vertex positions, with alpha.
vertices[i] = prev + (nextVertices[i] - prev) * percent local setupVertices = vertexAttachment.vertices
i = i + 1 local i = 1
end while i <= vertexCount do
elseif pose == MixPose.setup then local prev = prevVertices[i]
local vertexAttachment = slotAttachment vertices[i] = vertices[i] + prev + (nextVertices[i] - prev) * precent - setupVertices[i]
if vertexAttachment.bones == nil then i = i + 1
-- Unweighted vertex positions, with alpha. end
local setupVertices = vertexAttachment.vertices else
local i = 1 -- Weighted deform offsets, with alpha.
while i <= vertexCount do local i = 1
local prev = prevVertices[i] while i <= vertexCount do
local setup = setupVertices[i] local prev = prevVertices[i]
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha vertices[i] = vertices[i] + prev + (nextVertices[i] - prev) * percent
i = i + 1 i = i + 1
end
end end
else else
-- Weighted deform offsets, with alpha.
local i = 1 local i = 1
while i <= vertexCount do while i <= vertexCount do
local prev = prevVertices[i] local prev = prevVertices[i]
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha vertices[i] = prev + (nextVertices[i] - prev) * percent
i = i + 1 i = i + 1
end end
end end
else else
-- Vertex positions or deform offsets, with alpha. if blend == MixBlend.setup then
local i = 1 local vertexAttachment = slotAttachment
while i <= vertexCount do if vertexAttachment.bones == nil then
local prev = prevVertices[i] -- Unweighted vertex positions, with alpha.
vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha local setupVertices = vertexAttachment.vertices
i = i + 1 local i = 1
while i <= vertexCount do
local prev = prevVertices[i]
local setup = setupVertices[i]
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha
i = i + 1
end
else
-- Weighted deform offsets, with alpha.
local i = 1
while i <= vertexCount do
local prev = prevVertices[i]
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha
i = i + 1
end
end
elseif blend == MixBlend.first or blend == MixBlend.replace then
local i = 1
while i <= vertexCount do
local prev = prevVertices[i]
vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha
i = i + 1
end
elseif blend == MixBlend.add then
local vertexAttachment = slotAttachment
if vertexAttachment.bones == nil then
local setupVertices = vertexAttachment.vertices
local i = 1
while i <= vertexCount do
local prev = prevVertices[i]
vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha
i = i + 1
end
else
-- Weighted deform offsets, with alpha.
local i = 1
while i <= vertexCount do
local prev = prevVertices[i]
vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent) * alpha
i = i + 1
end
end
end end
end end
end end
@ -945,14 +1070,14 @@ function Animation.EventTimeline.new (frameCount)
end end
-- Fires events for frames > lastTime and <= time. -- Fires events for frames > lastTime and <= time.
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
if not firedEvents then return end if not firedEvents then return end
local frames = self.frames local frames = self.frames
local frameCount = zlen(frames) local frameCount = zlen(frames)
if lastTime > time then -- Fire events after last time for looped animations. if lastTime > time then -- Fire events after last time for looped animations.
self:apply(skeleton, lastTime, 999999, firedEvents, alpha, pose, direction) self:apply(skeleton, lastTime, 999999, firedEvents, alpha, blend, direction)
lastTime = -1 lastTime = -1
elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame. elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
return return
@ -1001,18 +1126,19 @@ function Animation.DrawOrderTimeline.new (frameCount)
self.drawOrders[frameIndex] = drawOrder self.drawOrders[frameIndex] = drawOrder
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local drawOrder = skeleton.drawOrder local drawOrder = skeleton.drawOrder
local slots = skeleton.slots local slots = skeleton.slots
if mixingOut and setupPose then if direction == MixDirection.out and blend == MixBlend.setup then
for i,slot in ipairs(slots) do for i,slot in ipairs(slots) do
drawOrder[i] = slots[i] drawOrder[i] = slots[i]
end end
return; return;
end end
local frames = self.frames local frames = self.frames
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then if blend == MixBlend.setup or blend == MixBlend.first then
for i,slot in ipairs(slots) do for i,slot in ipairs(slots) do
drawOrder[i] = slots[i] drawOrder[i] = slots[i]
end end
@ -1068,15 +1194,15 @@ function Animation.IkConstraintTimeline.new (frameCount)
self.frames[frameIndex + BEND_DIRECTION] = bendDirection self.frames[frameIndex + BEND_DIRECTION] = bendDirection
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local constraint = skeleton.ikConstraints[self.ikConstraintIndex] local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.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
elseif pose == MixPose.current 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
end end
@ -1084,7 +1210,7 @@ function Animation.IkConstraintTimeline.new (frameCount)
end end
if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
if pose == MixPose.setup then if blend == MixBlend.setup then
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
@ -1105,7 +1231,7 @@ function Animation.IkConstraintTimeline.new (frameCount)
local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1, local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)) 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
if pose == MixPose.setup then if blend == MixBlend.setup then
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
@ -1153,18 +1279,18 @@ function Animation.TransformConstraintTimeline.new (frameCount)
self.frames[frameIndex + SHEAR] = shearMix self.frames[frameIndex + SHEAR] = shearMix
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local constraint = skeleton.transformConstraints[self.transformConstraintIndex] local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
if time < frames[0] then if time < frames[0] then
local data = constraint.data local data = constraint.data
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.rotateMix = data.rotateMix constraint.rotateMix = data.rotateMix
constraint.translateMix = data.translateMix constraint.translateMix = data.translateMix
constraint.scaleMix = data.scaleMix constraint.scaleMix = data.scaleMix
constraint.shearMix = data.shearMix constraint.shearMix = data.shearMix
elseif pose == MixPose.current then elseif blend == MixBlend.first then
constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha
constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha
constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha
@ -1199,7 +1325,7 @@ function Animation.TransformConstraintTimeline.new (frameCount)
scale = scale + (frames[frame + SCALE] - scale) * percent scale = scale + (frames[frame + SCALE] - scale) * percent
shear = shear + (frames[frame + SHEAR] - shear) * percent shear = shear + (frames[frame + SHEAR] - shear) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
local data = constraint.data local data = constraint.data
constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha
constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha
@ -1239,14 +1365,14 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
self.frames[frameIndex + VALUE] = value self.frames[frameIndex + VALUE] = value
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex] local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if (time < frames[0]) then if (time < frames[0]) then
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.position = constraint.data.position constraint.position = constraint.data.position
elseif pose == MixPose.current then elseif blend == MixBlend.first then
constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha
end end
return return
@ -1265,7 +1391,7 @@ function Animation.PathConstraintPositionTimeline.new (frameCount)
position = position + (frames[frame + VALUE] - position) * percent position = position + (frames[frame + VALUE] - position) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
else else
constraint.position = constraint.position + (position - constraint.position) * alpha constraint.position = constraint.position + (position - constraint.position) * alpha
@ -1298,14 +1424,14 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
self.frames[frameIndex + VALUE] = value self.frames[frameIndex + VALUE] = value
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex] local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if (time < frames[0]) then if (time < frames[0]) then
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.spacing = constraint.data.spacing constraint.spacing = constraint.data.spacing
elseif pose == MixPose.current then elseif blend == MixBlend.first then
constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha
end end
return return
@ -1325,7 +1451,7 @@ function Animation.PathConstraintSpacingTimeline.new (frameCount)
spacing = spacing + (frames[frame + VALUE] - spacing) * percent spacing = spacing + (frames[frame + VALUE] - spacing) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
else else
constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
@ -1361,15 +1487,15 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
self.frames[frameIndex + TRANSLATE] = translateMix self.frames[frameIndex + TRANSLATE] = translateMix
end end
function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction) function self:apply (skeleton, lastTime, time, firedEvents, alpha, blend, direction)
local frames = self.frames local frames = self.frames
local constraint = skeleton.pathConstraints[self.pathConstraintIndex] local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
if (time < frames[0]) then if (time < frames[0]) then
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.rotateMix = constraint.data.rotateMix constraint.rotateMix = constraint.data.rotateMix
constraint.translateMix = constraint.data.translateMix constraint.translateMix = constraint.data.translateMix
elseif pose == MixPose.current then elseif blend == MixBlend.first then
constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha
constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha
end end
@ -1394,7 +1520,7 @@ function Animation.PathConstraintMixTimeline.new (frameCount)
translate = translate + (frames[frame + TRANSLATE] - translate) * percent translate = translate + (frames[frame + TRANSLATE] - translate) * percent
end end
if pose == MixPose.setup then if blend == MixBlend.setup then
constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha
constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha
else else

View File

@ -32,7 +32,7 @@ local setmetatable = setmetatable
local table_insert = table.insert local table_insert = table.insert
local utils = require "spine-lua.utils" local utils = require "spine-lua.utils"
local Animation = require "spine-lua.Animation" local Animation = require "spine-lua.Animation"
local MixPose = Animation.MixPose local MixBlend = Animation.MixBlend
local MixDirection = Animation.MixDirection local MixDirection = Animation.MixDirection
local AnimationStateData = require "spine-lua.AnimationStateData" local AnimationStateData = require "spine-lua.AnimationStateData"
local math_min = math.min local math_min = math.min
@ -175,6 +175,7 @@ function TrackEntry.new ()
animationStart = 0, animationEnd = 0, animationLast = 0, nextAnimationLast = 0, animationStart = 0, animationEnd = 0, animationLast = 0, nextAnimationLast = 0,
delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0, delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0,
alpha = 0, mixTime = 0, mixDuration = 0, interruptAlpha = 0, totalAlpha = 0, alpha = 0, mixTime = 0, mixDuration = 0, interruptAlpha = 0, totalAlpha = 0,
mixBlend = MixBlend.replace,
timelineData = {}, timelineData = {},
timelineDipMix = {}, timelineDipMix = {},
timelinesRotation = {} timelinesRotation = {}
@ -374,13 +375,13 @@ function AnimationState:apply (skeleton)
for i,current in pairs(tracks) do for i,current in pairs(tracks) do
if not (current == nil or current.delay > 0) then if not (current == nil or current.delay > 0) then
applied = true applied = true
local currrentPose = MixPose.currentLayered local blend = current.mixBlend
if i == 0 then currentPose = MixPose.current end if i == 0 then blend = MixBlend.first end
-- Apply mixing from entries first. -- Apply mixing from entries first.
local mix = current.alpha local mix = current.alpha
if current.mixingFrom then if current.mixingFrom then
mix = mix * self:applyMixingFrom(current, skeleton, currentPose) mix = mix * self:applyMixingFrom(current, skeleton, blend)
elseif current.trackTime >= current.trackEnd and current.next == nil then elseif current.trackTime >= current.trackEnd and current.next == nil then
mix = 0 mix = 0
end end
@ -389,9 +390,9 @@ function AnimationState:apply (skeleton)
local animationLast = current.animationLast local animationLast = current.animationLast
local animationTime = current:getAnimationTime() local animationTime = current:getAnimationTime()
local timelines = current.animation.timelines local timelines = current.animation.timelines
if mix == 1 then if mix == 1 or blend == MixBlend.add then
for i,timeline in ipairs(timelines) do for i,timeline in ipairs(timelines) do
timeline:apply(skeleton, animationLast, animationTime, events, 1, MixPose.setup, MixDirection._in) timeline:apply(skeleton, animationLast, animationTime, events, mix, blend, MixDirection._in)
end end
else else
local timelineData = current.timelineData local timelineData = current.timelineData
@ -399,14 +400,14 @@ function AnimationState:apply (skeleton)
local timelinesRotation = current.timelinesRotation local timelinesRotation = current.timelinesRotation
for i,timeline in ipairs(timelines) do for i,timeline in ipairs(timelines) do
local pose = MixPose.currentPose local timelineBlend = MixBlend.setup
if timelineData[i] >= FIRST then pose = MixPose.setup end if timelineData[i] == SUBSEQUENT then timelineBlend = blend end
if timeline.type == Animation.TimelineType.rotate then if timeline.type == Animation.TimelineType.rotate then
self:applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, i * 2, self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, i * 2,
firstFrame) -- FIXME passing ii * 2, indexing correct? firstFrame) -- FIXME passing ii * 2, indexing correct?
else else
timeline:apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection._in) timeline:apply(skeleton, animationLast, animationTime, events, mix, timelineBlend, MixDirection._in)
end end
end end
end end
@ -421,17 +422,18 @@ function AnimationState:apply (skeleton)
return applied return applied
end end
function AnimationState:applyMixingFrom (to, skeleton, currentPose) function AnimationState:applyMixingFrom (to, skeleton, blend)
local from = to.mixingFrom local from = to.mixingFrom
if from.mixingFrom then self:applyMixingFrom(from, skeleton, currentPose) end if from.mixingFrom then self:applyMixingFrom(from, skeleton, blend) end
local mix = 0 local mix = 0
if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes. if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes.
mix = 1 mix = 1
currentPose = MixPose.setup if blend == MixBlend.first then blend = MixBlend.setup end
else else
mix = to.mixTime / to.mixDuration mix = to.mixTime / to.mixDuration
if mix > 1 then mix = 1 end if mix > 1 then mix = 1 end
if blend ~= MixBlend.first then blend = from.mixBlend end
end end
local events = nil local events = nil
@ -441,44 +443,50 @@ function AnimationState:applyMixingFrom (to, skeleton, currentPose)
local animationLast = from.animationLast local animationLast = from.animationLast
local animationTime = from:getAnimationTime() local animationTime = from:getAnimationTime()
local timelines = from.animation.timelines local timelines = from.animation.timelines
local timelineData = from.timelineData
local timelineDipMix = from.timelineDipMix
local firstFrame = #from.timelinesRotation == 0
local timelinesRotation = from.timelinesRotation
local pose = MixPose.setup
local alphaDip = from.alpha * to.interruptAlpha local alphaDip = from.alpha * to.interruptAlpha
local alphaMix = alphaDip * (1 - mix) local alphaMix = alphaDip * (1 - mix)
local alpha = 0
from.totalAlpha = 0; if blend == MixBlend.add then
for i,timeline in ipairs(timelines) do
for i,timeline in ipairs(timelines) do timeline:apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.out)
local skipSubsequent = false;
if timelineData[i] == SUBSEQUENT then
if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
pose = currentPose
alpha = alphaMix
elseif timelineData[i] == FIRST then
pose = MixPose.setup
alpha = alphaMix
elseif timelineData[i] == DIP then
pose = MixPose.setup
alpha = alphaDip
else
pose = MixPose.setup
alpha = alphaDip
local dipMix = timelineDipMix[i]
alpha = alpha * math_max(0, 1 - dipMix.mixtime / dipMix.mixDuration)
end end
else
local timelineData = from.timelineData
local timelineDipMix = from.timelineDipMix
local firstFrame = #from.timelinesRotation == 0
local timelinesRotation = from.timelinesRotation
if not skipSubsequent then from.totalAlpha = 0;
from.totalAlpha = from.totalAlpha + alpha
if timeline.type == Animation.TimelineType.rotate then for i,timeline in ipairs(timelines) do
self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i * 2, firstFrame) local skipSubsequent = false;
local timelineBlend = MixBlend.setup
local alpha = 0
if timelineData[i] == SUBSEQUENT then
if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
timelineBlend = blend
alpha = alphaMix
elseif timelineData[i] == FIRST then
timelineBlend = MixBlend.setup
alpha = alphaMix
elseif timelineData[i] == DIP then
timelineBlend = MixBlend.setup
alpha = alphaDip
else else
timeline:apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.out) timelineBlend = MixBlend.setup
local dipMix = timelineDipMix[i]
alpha = alphaDip * math_max(0, 1 - dipMix.mixtime / dipMix.mixDuration)
end
if not skipSubsequent then
from.totalAlpha = from.totalAlpha + alpha
if timeline.type == Animation.TimelineType.rotate then
self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
else
timeline:apply(skeleton, animationLast, animationTime, events, alpha, timelineBlend, MixDirection.out)
end
end end
end end
end end
@ -491,14 +499,14 @@ function AnimationState:applyMixingFrom (to, skeleton, currentPose)
return mix return mix
end end
function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame) function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame)
if firstFrame then if firstFrame then
timelinesRotation[i] = 0 timelinesRotation[i] = 0
timelinesRotation[i+1] = 0 timelinesRotation[i+1] = 0
end end
if alpha == 1 then if alpha == 1 then
timeline:apply(skeleton, 0, time, nil, 1, pose, MixDirection._in) timeline:apply(skeleton, 0, time, nil, 1, blend, MixDirection._in)
return return
end end
@ -506,7 +514,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, po
local frames = rotateTimeline.frames local frames = rotateTimeline.frames
local bone = skeleton.bones[rotateTimeline.boneIndex] local bone = skeleton.bones[rotateTimeline.boneIndex]
if time < frames[0] then if time < frames[0] then
if pose == MixPose.setup then bone.rotation = bone.data.rotation end if blend == MixBlend.setup then bone.rotation = bone.data.rotation end
return return
end end
@ -529,7 +537,7 @@ function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, po
-- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. -- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
local r1 = bone.rotation local r1 = bone.rotation
if pose == MixPose.setup then r1 = bone.data.rotation end if blend == MixBlend.setup then r1 = bone.data.rotation end
local total = 0 local total = 0
local diff = r2 - r1 local diff = r2 - r1
if diff == 0 then if diff == 0 then
@ -797,6 +805,7 @@ function AnimationState:trackEntry (trackIndex, animation, loop, last)
else else
entry.mixDuration = data:getMix(last.animation, animation) entry.mixDuration = data:getMix(last.animation, animation)
end end
entry.mixBlend = MixBlend.replace
return entry return entry
end end
@ -818,7 +827,7 @@ function AnimationState:_animationsChanged ()
local mixingTo = self.mixingTo local mixingTo = self.mixingTo
for i, entry in pairs(self.tracks) do for i, entry in pairs(self.tracks) do
if entry then if entry and (i == 0 or entry.mixBlend ~= MixBlend.add) then
entry:setTimelineData(nil, mixingTo, propertyIDs) entry:setTimelineData(nil, mixingTo, propertyIDs)
end end
end end

View File

@ -833,7 +833,7 @@ module spine {
case MixBlend.first: case MixBlend.first:
case MixBlend.replace: case MixBlend.replace:
for (let i = 0; i < vertexCount; i++) for (let i = 0; i < vertexCount; i++)
vertices[i] += (lastVertices[i] - vertices[i]) * alpha; vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
case MixBlend.add: case MixBlend.add:
let vertexAttachment = slotAttachment as VertexAttachment; let vertexAttachment = slotAttachment as VertexAttachment;
if (vertexAttachment.bones == null) { if (vertexAttachment.bones == null) {