diff --git a/spine-love/main.lua b/spine-love/main.lua index 5db0f8cb1..88cf4c5e8 100644 --- a/spine-love/main.lua +++ b/spine-love/main.lua @@ -53,6 +53,12 @@ function loadSkeleton (jsonFile, atlasFile, animation, skin, scale, x, y) local stateData = spine.AnimationStateData.new(skeletonData) local state = spine.AnimationState.new(stateData) state:setAnimationByName(0, animation, true) + if (jsonFile == "spineboy") then + stateData:setMix("walk", "jump", 0.5) + stateData:setMix("jump", "run", 0.5) + state:addAnimationByName(0, "jump", false, 3) + state:addAnimationByName(0, "run", true, 0) + end -- set some event callbacks state.onStart = function (entry) @@ -82,14 +88,13 @@ end function love.load(arg) if arg[#arg] == "-debug" then require("mobdebug").start() end - table.insert(skeletons, loadSkeleton("test", "test", "animation", nil, 0.5, 400, 300)) - table.insert(skeletons, loadSkeleton("TwoColorTest", "TwoColorTest", "animation", nil, 0.3, 400, 300)) + -- table.insert(skeletons, loadSkeleton("test", "test", "animation", nil, 0.5, 400, 300)) table.insert(skeletons, loadSkeleton("spineboy", "spineboy", "walk", nil, 0.5, 400, 500)) - table.insert(skeletons, loadSkeleton("raptor", "raptor", "walk", nil, 0.3, 400, 500)) +--[[ table.insert(skeletons, loadSkeleton("raptor", "raptor", "walk", nil, 0.3, 400, 500)) table.insert(skeletons, loadSkeleton("goblins-mesh", "goblins", "walk", "goblin", 1, 400, 500)) table.insert(skeletons, loadSkeleton("tank", "tank", "drive", nil, 0.2, 600, 500)) table.insert(skeletons, loadSkeleton("vine", "vine", "animation", nil, 0.3, 400, 500)) - table.insert(skeletons, loadSkeleton("stretchyman", "stretchyman", "sneak", nil, 0.3, 200, 500)) + table.insert(skeletons, loadSkeleton("stretchyman", "stretchyman", "sneak", nil, 0.3, 200, 500))]]-- skeletonRenderer = spine.SkeletonRenderer.new(true) end diff --git a/spine-lua/AnimationState.lua b/spine-lua/AnimationState.lua index a74d67790..d015b5cba 100644 --- a/spine-lua/AnimationState.lua +++ b/spine-lua/AnimationState.lua @@ -169,6 +169,7 @@ function TrackEntry.new () delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0, alpha = 0, mixTime = 0, mixDuration = 0, mixAlpha = 0, timelinesFirst = {}, + timelinesLast = {}, timelinesRotation = {} } setmetatable(self, TrackEntry) @@ -202,7 +203,8 @@ function AnimationState.new (data) queue = nil, propertyIDs = {}, animationsChanged = false, - timeScale = 1 + timeScale = 1, + mixingMultiple = false } self.queue = EventQueue.new(self) setmetatable(self, AnimationState) @@ -356,8 +358,11 @@ function AnimationState:applyMixingFrom (entry, skeleton) local animationLast = from.animationLast local animationTime = from:getAnimationTime() local timelines = from.animation.timelines - local timelinesFirst = from.timelinesFirst; - local alpha = from.alpha * entry.mixAlpha * (1 - mix) + local timelinesFirst = from.timelinesFirst + local timelinesLast = nil + if (self.multipleMixing == false) then timelinesLast = from.timelinesLast end + local alphaBase = from.alpha * entry.mixAlpha + local alphaMix = alphaBase * (1 - mix) local firstFrame = #from.timelinesRotation == 0 local timelinesRotation = from.timelinesRotation @@ -365,6 +370,12 @@ function AnimationState:applyMixingFrom (entry, skeleton) local skip = false for i,timeline in ipairs(timelines) do local setupPose = timelinesFirst[i] + local alpha = 1; + if (timelinesLast ~= nil and setupPose and not timlinesLast[i]) then + alpha = alphaBase + else + alpha = alphaMix + end if timeline.type == Animation.TimelineType.rotate then self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, setupPose, timelinesRotation, i * 2, firstFrame) -- FIXME passing i * 2, correct indexing? else @@ -541,10 +552,27 @@ function AnimationState:setCurrent (index, current, interrupt) current.mixingFrom = from current.mixTime = 0 - from.timelinesRotation = {}; + local mixingFrom = from.mixingFrom + if (mixingFrom ~= nil and from.mixDuration > 0) then + if (not self.multipleMixing and from.mixTime / from.mixDuration < 0.5 and mixingFrom.animation ~= EMPTY_ANIMATION) then + current.mixingFrom = mixingFrom + mixingFrom.mixingFrom = from + mixingFrom.mixTime = from.mixDuration - from.mixTime + mixingFrom.mixDuration = from.mixDuration + from.mixingFrom = nil + from = mixingFrom + end - -- If not completely mixed in, set mixAlpha so mixing out happens from current mix to zero. - if from.mixingFrom and from.mixDuration > 0 then current.mixAlpha = current.mixAlpha * math_min(from.mixTime / from.mixDuration, 1) end + current.mixAlpha = current.mixAlpha * math_min(from.mixTime / from.mixDuration, 1) + + if (not self.multipleMixing) then + from.mixAlpha = 0; + from.mixTime = 0; + from.mixDuration = 0; + end + end + + from.timelinesRotation = {}; end queue:start(current) @@ -724,6 +752,42 @@ function AnimationState:_animationsChanged () if entry then self:checkTimelinesFirst(entry) end i = i + 1 end + + if (self.multipleMixing) then return end + + self.propertyIDs = {} + local lowestMixingFrom = n + i = 0; + while i < n do + entry = self.tracks[i] + if not (entry == nil or entry.mixingFrom == nil) then + lowestMixingFrom = i + i = n + 1 -- break + end + i = i + 1 + end + i = n - 1 + while i >= lowestMixingFrom do + local entry = self.tracks[i] + if (entry) then + local propertyIDs = self.propertyIDs + local timelines = entry.animation.timelines + local ii = 1 + local nn = #entry.animation.timelines; + while ii <= nn do + local id = "" .. timelines[ii]:getPropertyId() + propertyIDs[id] = id + ii = ii + 1 + end + + entry = entry.mixingFrom + while (entry) do + self:checkTimelinesUsage(entry, entry.timelinesLast) + entry = entry.mixingFrom; + end + end + i = i - 1 + end end function AnimationState:setTimelinesFirst (entry)