AnimationState.lua 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. -------------------------------------------------------------------------------
  2. -- Spine Runtimes License Agreement
  3. -- Last updated January 1, 2020. Replaces all prior versions.
  4. --
  5. -- Copyright (c) 2013-2020, Esoteric Software LLC
  6. --
  7. -- Integration of the Spine Runtimes into software or otherwise creating
  8. -- derivative works of the Spine Runtimes is permitted under the terms and
  9. -- conditions of Section 2 of the Spine Editor License Agreement:
  10. -- http://esotericsoftware.com/spine-editor-license
  11. --
  12. -- Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. -- or otherwise create derivative works of the Spine Runtimes (collectively,
  14. -- "Products"), provided that each user of the Products must obtain their own
  15. -- Spine Editor license and redistribution of the Products in any form must
  16. -- include this license and copyright notice.
  17. --
  18. -- THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. -- DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. -- BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. -- THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. -------------------------------------------------------------------------------
  29. local setmetatable = setmetatable
  30. local table_insert = table.insert
  31. local utils = require "spine-lua.utils"
  32. local Animation = require "spine-lua.Animation"
  33. local MixBlend = Animation.MixBlend
  34. local MixDirection = Animation.MixDirection
  35. local AnimationStateData = require "spine-lua.AnimationStateData"
  36. local math_min = math.min
  37. local math_max = math.max
  38. local math_abs = math.abs
  39. local math_signum = utils.signum
  40. local math_floor = math.floor
  41. local math_ceil = math.ceil
  42. local math_mod = utils.mod
  43. local testBit = utils.testBit
  44. local setBit = utils.setBit
  45. local clearBit = utils.clearBit
  46. local function zlen(array)
  47. return #array + 1
  48. end
  49. local EMPTY_ANIMATION = Animation.new("<empty>", {}, 0)
  50. local SUBSEQUENT = 0
  51. local FIRST = 1
  52. local HOLD_SUBSEQUENT = 2
  53. local HOLD_FIRST = 3
  54. local HOLD_MIX = 4
  55. local SETUP = 1
  56. local CURRENT = 2
  57. local EventType = {
  58. start = 0,
  59. interrupt = 1,
  60. _end = 2,
  61. dispose = 3,
  62. complete = 4,
  63. event = 5
  64. }
  65. local EventQueue = {}
  66. EventQueue.__index = EventQueue
  67. function EventQueue.new (animationState)
  68. local self = {
  69. objects = {},
  70. animationState = animationState,
  71. drainDisabled = false
  72. }
  73. setmetatable(self, EventQueue)
  74. return self
  75. end
  76. function EventQueue:start (entry)
  77. local objects = self.objects
  78. table_insert(objects, EventType.start)
  79. table_insert(objects, entry)
  80. self.animationState.animationsChanged = true
  81. end
  82. function EventQueue:interrupt (entry)
  83. local objects = self.objects
  84. table_insert(objects, EventType.interrupt)
  85. table_insert(objects, entry)
  86. end
  87. function EventQueue:_end (entry)
  88. local objects = self.objects
  89. table_insert(objects, EventType._end)
  90. table_insert(objects, entry)
  91. self.animationState.animationsChanged = true
  92. end
  93. function EventQueue:dispose (entry)
  94. local objects = self.objects
  95. table_insert(objects, EventType.dispose)
  96. table_insert(objects, entry)
  97. end
  98. function EventQueue:complete (entry)
  99. local objects = self.objects
  100. table_insert(objects, EventType.complete)
  101. table_insert(objects, entry)
  102. end
  103. function EventQueue:event (entry, event)
  104. local objects = self.objects
  105. table_insert(objects, EventType.event)
  106. table_insert(objects, entry)
  107. table_insert(objects, event)
  108. end
  109. function EventQueue:drain ()
  110. if self.drainDisabled then return end -- Not reentrant.
  111. self.drainDisabled = true
  112. local objects = self.objects
  113. local as = self.animationState
  114. local i = 1
  115. local n = #objects
  116. while i <= n do
  117. local _type = objects[i]
  118. local entry = objects[i + 1]
  119. if _type == EventType.start then
  120. if entry.onStart then entry.onStart(entry) end
  121. if as.onStart then as.onStart(entry) end
  122. elseif _type == EventType.interrupt then
  123. if entry.onInterrupt then entry.onInterrupt(entry) end
  124. if as.onInterrupt then as.onInterrupt(entry) end
  125. elseif _type == EventType._end then
  126. if entry.onEnd then entry.onEnd(entry) end
  127. if as.onEnd then as.onEnd(entry) end
  128. -- fall through in ref impl
  129. if entry.onDispose then entry.onDispose(entry) end
  130. if as.onDispose then as.onDispose(entry) end
  131. elseif _type == EventType._dispose then
  132. if entry.onDispose then entry.onDispose(entry) end
  133. if as.onDispose then as.onDispose(entry) end
  134. elseif _type == EventType.complete then
  135. if entry.onComplete then entry.onComplete(entry) end
  136. if as.onComplete then as.onComplete(entry) end
  137. elseif _type == EventType.event then
  138. local event = objects[i + 2]
  139. if entry.onEvent then entry.onEvent(entry, event) end
  140. if as.onEvent then as.onEvent(entry, event) end
  141. i = i + 1
  142. end
  143. i = i + 2
  144. end
  145. self:clear()
  146. self.drainDisabled = false;
  147. end
  148. function EventQueue:clear ()
  149. self.objects = {}
  150. end
  151. local TrackEntry = {}
  152. TrackEntry.__index = TrackEntry
  153. function TrackEntry.new ()
  154. local self = {
  155. animation = nil,
  156. next = nil, mixingFrom = nil, mixingTo = nil,
  157. onStart = nil, onInterrupt = nil, onEnd = nil, onDispose = nil, onComplete = nil, onEvent = nil,
  158. trackIndex = 0,
  159. loop = false, holdPrevious = false,
  160. eventThreshold = 0, attachmentThreshold = 0, drawOrderThreshold = 0,
  161. animationStart = 0, animationEnd = 0, animationLast = 0, nextAnimationLast = 0,
  162. delay = 0, trackTime = 0, trackLast = 0, nextTrackLast = 0, trackEnd = 0, timeScale = 0,
  163. alpha = 0, mixTime = 0, mixDuration = 0, interruptAlpha = 0, totalAlpha = 0,
  164. mixBlend = MixBlend.replace,
  165. timelineMode = {},
  166. timelineHoldMix = {},
  167. timelinesRotation = {}
  168. }
  169. setmetatable(self, TrackEntry)
  170. return self
  171. end
  172. function TrackEntry:getAnimationTime ()
  173. if self.loop then
  174. local duration = self.animationEnd - self.animationStart
  175. if duration == 0 then return self.animationStart end
  176. return (self.trackTime % duration) + self.animationStart
  177. end
  178. return math_min(self.trackTime + self.animationStart, self.animationEnd)
  179. end
  180. function TrackEntry:resetRotationDirections ()
  181. self.timelinesRotation = {}
  182. end
  183. local AnimationState = {}
  184. AnimationState.__index = AnimationState
  185. function AnimationState.new (data)
  186. if not data then error("data cannot be nil", 2) end
  187. local self = {
  188. data = data,
  189. tracks = {},
  190. events = {},
  191. onStart = nil, onInterrupt = nil, onEnd = nil, onDispose = nil, onComplete = nil, onEvent = nil,
  192. queue = nil,
  193. propertyIDs = {},
  194. animationsChanged = false,
  195. timeScale = 1,
  196. mixingTo = {},
  197. unkeyedState = 0
  198. }
  199. self.queue = EventQueue.new(self)
  200. setmetatable(self, AnimationState)
  201. return self
  202. end
  203. AnimationState.TrackEntry = TrackEntry
  204. function AnimationState:update (delta)
  205. delta = delta * self.timeScale
  206. local tracks = self.tracks
  207. local queue = self.queue
  208. local numTracks = getNumTracks(tracks)
  209. local i = 0
  210. while i <= numTracks do
  211. current = tracks[i]
  212. if current then
  213. current.animationLast = current.nextAnimationLast
  214. current.trackLast = current.nextTrackLast
  215. local currentDelta = delta * current.timeScale
  216. local skip = false
  217. if current.delay > 0 then
  218. current.delay = current.delay - currentDelta
  219. if current.delay <= 0 then
  220. skip = true
  221. currentDelta = -current.delay
  222. current.delay = 0
  223. end
  224. end
  225. if not skip then
  226. local _next = current.next
  227. if _next then
  228. -- When the next entry's delay is passed, change to the next entry, preserving leftover time.
  229. local nextTime = current.trackLast - _next.delay
  230. if nextTime >= 0 then
  231. _next.delay = 0
  232. if current.timeScale == 0 then
  233. _next.trackTime = _next.trackTime + 0
  234. else
  235. _next.trackTime = _next.trackTime + (nextTime / current.timeScale + delta) * _next.timeScale
  236. end
  237. current.trackTime = current.trackTime + currentDelta
  238. self:setCurrent(i, _next, true)
  239. while _next.mixingFrom do
  240. _next.mixTime = _next.mixTime + delta
  241. _next = _next.mixingFrom
  242. end
  243. skip = true
  244. end
  245. else
  246. -- Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom.
  247. if current.trackLast >= current.trackEnd and current.mixingFrom == nil then
  248. tracks[i] = nil
  249. queue:_end(current)
  250. self:disposeNext(current)
  251. skip = true
  252. end
  253. end
  254. if not skip then
  255. if current.mixingFrom and self:updateMixingFrom(current, delta) then
  256. -- End mixing from entries once all have completed.
  257. local from = current.mixingFrom
  258. current.mixingFrom = nil
  259. if from then from.mixingTo = nil end
  260. while from do
  261. queue:_end(from)
  262. from = from.mixingFrom
  263. end
  264. end
  265. current.trackTime = current.trackTime + currentDelta
  266. end
  267. end
  268. end
  269. i = i + 1
  270. end
  271. queue:drain()
  272. end
  273. function AnimationState:updateMixingFrom (to, delta)
  274. local from = to.mixingFrom
  275. if from == nil then return true end
  276. local finished = self:updateMixingFrom(from, delta)
  277. from.animationLast = from.nextAnimationLast
  278. from.trackLast = from.nextTrackLast
  279. -- Require mixTime > 0 to ensure the mixing from entry was applied at least once.
  280. if (to.mixTime > 0 and to.mixTime >= to.mixDuration) then
  281. -- Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
  282. if (from.totalAlpha == 0 or to.mixDuration == 0) then
  283. to.mixingFrom = from.mixingFrom
  284. if from.mixingFrom then from.mixingFrom.mixingTo = to end
  285. to.interruptAlpha = from.interruptAlpha
  286. self.queue:_end(from)
  287. end
  288. return finished
  289. end
  290. from.trackTime = from.trackTime + delta * from.timeScale
  291. to.mixTime = to.mixTime + delta
  292. return false;
  293. end
  294. function AnimationState:apply (skeleton)
  295. if skeleton == nil then error("skeleton cannot be null.", 2) end
  296. if self.animationsChanged then self:_animationsChanged() end
  297. local tracks = self.tracks
  298. local queue = self.queue
  299. local applied = false
  300. local numTracks = getNumTracks(tracks)
  301. local i = 0
  302. while i <= numTracks do
  303. current = tracks[i]
  304. if current then
  305. if not (current == nil or current.delay > 0) then
  306. applied = true
  307. local blend = current.mixBlend
  308. if i == 0 then blend = MixBlend.first end
  309. -- Apply mixing from entries first.
  310. local mix = current.alpha
  311. if current.mixingFrom then
  312. mix = mix * self:applyMixingFrom(current, skeleton, blend)
  313. elseif current.trackTime >= current.trackEnd and current.next == nil then
  314. mix = 0
  315. end
  316. -- Apply current entry.
  317. local animationLast = current.animationLast
  318. local animationTime = current:getAnimationTime()
  319. local timelines = current.animation.timelines
  320. if (i == 0 and mix == 1) or blend == MixBlend.add then
  321. for i,timeline in ipairs(timelines) do
  322. if timeline.type == Animation.TimelineType.attachment then
  323. self:applyAttachmentTimeline(timeline, skeleton, animationTime, blend, true)
  324. else
  325. timeline:apply(skeleton, animationLast, animationTime, self.events, mix, blend, MixDirection._in)
  326. end
  327. end
  328. else
  329. local timelineMode = current.timelineMode
  330. local firstFrame = #current.timelinesRotation == 0
  331. local timelinesRotation = current.timelinesRotation
  332. for ii,timeline in ipairs(timelines) do
  333. local timelineBlend = MixBlend.setup
  334. if timelineMode[ii] == SUBSEQUENT then timelineBlend = blend end
  335. if timeline.type == Animation.TimelineType.rotate then
  336. self:applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii * 2,
  337. firstFrame)
  338. elseif timeline.type == Animation.TimelineType.attachment then
  339. self:applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, true)
  340. else
  341. timeline:apply(skeleton, animationLast, animationTime, self.events, mix, timelineBlend, MixDirection._in)
  342. end
  343. end
  344. end
  345. self:queueEvents(current, animationTime)
  346. self.events = {};
  347. current.nextAnimationLast = animationTime
  348. current.nextTrackLast = current.trackTime
  349. end
  350. end
  351. i = i + 1
  352. end
  353. -- Set slots attachments to the setup pose, if needed. This occurs if an animation that is mixing out sets attachments so
  354. -- subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or
  355. -- the time is before the first key).
  356. local setupState = self.unkeyedState + SETUP
  357. local slots = skeleton.slots;
  358. for _, slot in ipairs(slots) do
  359. if slot.attachmentState == setupState then
  360. local attachmentName = slot.data.attachmentName
  361. if attachmentName == nil then
  362. slot.attachment = nil
  363. else
  364. slot.attachment = skeleton:getAttachmentByIndex(slot.data.index, attachmentName)
  365. end
  366. end
  367. end
  368. self.unkeyedState = self.unkeyedState + 2; -- Increasing after each use avoids the need to reset attachmentState for every slot.
  369. queue:drain()
  370. return applied
  371. end
  372. function AnimationState:applyMixingFrom (to, skeleton, blend)
  373. local from = to.mixingFrom
  374. if from.mixingFrom then self:applyMixingFrom(from, skeleton, blend) end
  375. local mix = 0
  376. if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes.
  377. mix = 1
  378. if blend == MixBlend.first then blend = MixBlend.setup end
  379. else
  380. mix = to.mixTime / to.mixDuration
  381. if mix > 1 then mix = 1 end
  382. if blend ~= MixBlend.first then blend = from.mixBlend end
  383. end
  384. local events = nil
  385. if mix < from.eventThreshold then events = self.events end
  386. local attachments = mix < from.attachmentThreshold
  387. local drawOrder = mix < from.drawOrderThreshold
  388. local animationLast = from.animationLast
  389. local animationTime = from:getAnimationTime()
  390. local timelines = from.animation.timelines
  391. local alphaHold = from.alpha * to.interruptAlpha
  392. local alphaMix = alphaHold * (1 - mix)
  393. if blend == MixBlend.add then
  394. for i,timeline in ipairs(timelines) do
  395. timeline:apply(skeleton, animationLast, animationTime, events, alphaMix, blend, MixDirection.out)
  396. end
  397. else
  398. local timelineMode = from.timelineMode
  399. local timelineHoldMix = from.timelineHoldMix
  400. local firstFrame = #from.timelinesRotation == 0
  401. local timelinesRotation = from.timelinesRotation
  402. from.totalAlpha = 0;
  403. for i,timeline in ipairs(timelines) do
  404. local skipSubsequent = false;
  405. local direction = MixDirection.out;
  406. local timelineBlend = MixBlend.setup
  407. local alpha = 0
  408. if timelineMode[i] == SUBSEQUENT then
  409. if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
  410. timelineBlend = blend
  411. alpha = alphaMix
  412. elseif timelineMode[i] == FIRST then
  413. timelineBlend = MixBlend.setup
  414. alpha = alphaMix
  415. elseif timelineMode[i] == HOLD_SUBSEQUENT then
  416. timelineBlend = blend
  417. alpha = alphaHold
  418. elseif timelineMode[i] == HOLD_FIRST then
  419. timelineBlend = MixBlend.setup
  420. alpha = alphaHold
  421. else
  422. timelineBlend = MixBlend.setup
  423. local holdMix = timelineHoldMix[i]
  424. alpha = alphaHold * math_max(0, 1 - holdMix.mixtime / holdMix.mixDuration)
  425. end
  426. if not skipSubsequent then
  427. from.totalAlpha = from.totalAlpha + alpha
  428. if timeline.type == Animation.TimelineType.rotate then
  429. self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i * 2, firstFrame)
  430. elseif timeline.type == Animation.TimelineType.attachment then
  431. self:applyAttachmentTimeline(timeline, skeleton, animationTime, timelineBlend, attachments)
  432. else
  433. if (drawOrder and timeline.type == Animation.TimelineType.drawOrder and timelineBlend == MixBlend.setup) then
  434. direction = MixDirection._in
  435. end
  436. timeline:apply(skeleton, animationLast, animationTime, self.events, alpha, timelineBlend, direction)
  437. end
  438. end
  439. end
  440. end
  441. if (to.mixDuration > 0) then
  442. self:queueEvents(from, animationTime)
  443. end
  444. self.events = {};
  445. from.nextAnimationLast = animationTime
  446. from.nextTrackLast = from.trackTime
  447. return mix
  448. end
  449. function AnimationState:applyAttachmentTimeline(timeline, skeleton, time, blend, attachments)
  450. local slot = skeleton.slots[timeline.slotIndex];
  451. if slot.bone.active == false then return end
  452. local frames = timeline.frames
  453. if time < frames[0] then -- Time is before first frame.
  454. if blend == MixBlend.setup or blend == MixBlend.first then
  455. self:setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
  456. end
  457. else
  458. local frameIndex = 0
  459. if (time >= frames[zlen(frames) - 1]) then -- Time is after last frame.
  460. frameIndex = zlen(frames) - 1;
  461. else
  462. frameIndex = Animation.binarySearch(frames, time, 1) - 1;
  463. end
  464. self:setAttachment(skeleton, slot, timeline.attachmentNames[frameIndex], attachments)
  465. end
  466. -- If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.
  467. if slot.attachmentState <= self.unkeyedState then slot.attachmentState = self.unkeyedState + SETUP end
  468. end
  469. function AnimationState:setAttachment(skeleton, slot, attachmentName, attachments)
  470. if (attachmentName == nil) then
  471. slot.attachment = nil
  472. else
  473. slot.attachment = skeleton:getAttachmentByIndex(slot.data.index, attachmentName)
  474. end
  475. if attachments then slot.attachmentState = self.unkeyedState + CURRENT end
  476. end
  477. function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame)
  478. if firstFrame then
  479. timelinesRotation[i] = 0
  480. timelinesRotation[i+1] = 0
  481. end
  482. if alpha == 1 then
  483. timeline:apply(skeleton, 0, time, nil, 1, blend, MixDirection._in)
  484. return
  485. end
  486. local rotateTimeline = timeline
  487. local frames = rotateTimeline.frames
  488. local bone = skeleton.bones[rotateTimeline.boneIndex]
  489. if not bone.active then return end
  490. local r1 = 0
  491. local r2 = 0
  492. if time < frames[0] then
  493. if blend == MixBlend.setup then
  494. bone.rotation = bone.data.rotation
  495. return
  496. elseif blend == MixBlend.first then
  497. r1 = bone.rotation
  498. r2 = bone.data.rotation
  499. else
  500. return
  501. end
  502. else
  503. if blend == MixBlend.setup then
  504. r1 = bone.data.rotation
  505. else
  506. r1 = bone.rotation
  507. end
  508. if time >= frames[zlen(frames) - Animation.RotateTimeline.ENTRIES] then -- Time is after last frame.
  509. r2 = bone.data.rotation + frames[zlen(frames) + Animation.RotateTimeline.PREV_ROTATION]
  510. else
  511. -- Interpolate between the previous frame and the current frame.
  512. local frame = Animation.binarySearch(frames, time, Animation.RotateTimeline.ENTRIES)
  513. local prevRotation = frames[frame + Animation.RotateTimeline.PREV_ROTATION]
  514. local frameTime = frames[frame]
  515. local percent = rotateTimeline:getCurvePercent(math_floor(frame / 2) - 1,
  516. 1 - (time - frameTime) / (frames[frame + Animation.RotateTimeline.PREV_TIME] - frameTime))
  517. r2 = frames[frame + Animation.RotateTimeline.ROTATION] - prevRotation
  518. r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
  519. r2 = prevRotation + r2 * percent + bone.data.rotation
  520. r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
  521. end
  522. end
  523. -- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
  524. local total = 0
  525. local diff = r2 - r1
  526. diff = diff - (16384 - math_floor(16384.499999999996 - diff / 360)) * 360
  527. if diff == 0 then
  528. total = timelinesRotation[i]
  529. else
  530. local lastTotal = 0
  531. local lastDiff = 0
  532. if firstFrame then
  533. lastTotal = 0
  534. lastDiff = diff
  535. else
  536. lastTotal = timelinesRotation[i] -- Angle and direction of mix, including loops.
  537. lastDiff = timelinesRotation[i + 1] -- Difference between bones.
  538. end
  539. local current = diff > 0
  540. local dir = lastTotal >= 0
  541. -- Detect cross at 0 (not 180).
  542. if math_signum(lastDiff) ~= math_signum(diff) and math_abs(lastDiff) <= 90 then
  543. -- A cross after a 360 rotation is a loop.
  544. if math_abs(lastTotal) > 180 then lastTotal = lastTotal + 360 * math_signum(lastTotal) end
  545. dir = current
  546. end
  547. total = diff + lastTotal - math_mod(lastTotal, 360) -- FIXME used to be %360, store loops as part of lastTotal.
  548. if dir ~= current then total = total + 360 * math_signum(lastTotal) end
  549. timelinesRotation[i] = total
  550. end
  551. timelinesRotation[i + 1] = diff
  552. r1 = r1 + total * alpha
  553. bone.rotation = r1 - (16384 - math_floor(16384.499999999996 - r1 / 360)) * 360
  554. end
  555. function AnimationState:queueEvents (entry, animationTime)
  556. local animationStart = entry.animationStart
  557. local animationEnd = entry.animationEnd
  558. local duration = animationEnd - animationStart
  559. local trackLastWrapped = entry.trackLast % duration
  560. -- Queue events before complete.
  561. local events = self.events
  562. local queue = self.queue
  563. local i = 1
  564. local n = #events
  565. while i <= n do
  566. local event = events[i]
  567. if event.time < trackLastWrapped then break end
  568. if not (event.time > animationEnd) then -- Discard events outside animation start/end.
  569. queue:event(entry, event)
  570. end
  571. i = i + 1
  572. end
  573. -- Queue complete if completed a loop iteration or the animation.
  574. local queueComplete = false
  575. if entry.loop then
  576. queueComplete = duration == 0 or (trackLastWrapped > entry.trackTime % duration)
  577. else
  578. queueComplete = (animationTime >= animationEnd and entry.animationLast < animationEnd)
  579. end
  580. if queueComplete then
  581. queue:complete(entry)
  582. end
  583. -- Queue events after complete.
  584. while i <= n do
  585. local event = events[i]
  586. if not (event.time < animationStart) then --// Discard events outside animation start/end.
  587. queue:event(entry, event)
  588. end
  589. i = i + 1
  590. end
  591. end
  592. function AnimationState:clearTracks ()
  593. local queue = self.queue
  594. local tracks = self.tracks
  595. local oldDrainDisabled = queue.drainDisabled
  596. queue.drainDisabled = true;
  597. local numTracks = getNumTracks(tracks)
  598. local i = 0
  599. while i <= numTracks do
  600. self:clearTrack(i)
  601. end
  602. tracks = {}
  603. queue.drainDisabled = oldDrainDisabled
  604. queue:drain();
  605. end
  606. function AnimationState:clearTrack (trackIndex)
  607. local tracks = self.tracks
  608. local queue = self.queue
  609. local current = tracks[trackIndex]
  610. if current == nil then return end
  611. queue:_end(current)
  612. self:disposeNext(current)
  613. local entry = current;
  614. while (true) do
  615. local from = entry.mixingFrom
  616. if from == nil then break end
  617. queue:_end(from)
  618. entry.mixingFrom = nil
  619. entry.mixingTo = nil
  620. entry = from
  621. end
  622. tracks[current.trackIndex] = nil
  623. queue:drain()
  624. end
  625. function AnimationState:setCurrent (index, current, interrupt)
  626. local from = self:expandToIndex(index)
  627. local tracks = self.tracks
  628. local queue = self.queue
  629. tracks[index] = current
  630. if from then
  631. if interrupt then queue:interrupt(from) end
  632. current.mixingFrom = from
  633. from.mixingTo = current
  634. current.mixTime = 0
  635. if from.mixingFrom and from.mixDuration > 0 then
  636. current.interruptAlpha = current.interruptAlpha * math_min(1, from.mixTime / from.mixDuration)
  637. end
  638. from.timelinesRotation = {};
  639. end
  640. queue:start(current)
  641. end
  642. function AnimationState:setAnimationByName (trackIndex, animationName, loop)
  643. local animation = self.data.skeletonData:findAnimation(animationName)
  644. if not animation then error("Animation not found: " .. animationName, 2) end
  645. return self:setAnimation(trackIndex, animation, loop)
  646. end
  647. function AnimationState:setAnimation (trackIndex, animation, loop)
  648. if not animation then error("animation cannot be null.") end
  649. local interrupt = true;
  650. local current = self:expandToIndex(trackIndex)
  651. local queue = self.queue
  652. local tracks = self.tracks
  653. if current then
  654. if current.nextTrackLast == -1 then
  655. -- Don't mix from an entry that was never applied.
  656. tracks[trackIndex] = current.mixingFrom
  657. queue:interrupt(current)
  658. queue:_end(current)
  659. self:disposeNext(current)
  660. current = current.mixingFrom
  661. interrupt = false;
  662. else
  663. self:disposeNext(current)
  664. end
  665. end
  666. local entry = self:trackEntry(trackIndex, animation, loop, current)
  667. self:setCurrent(trackIndex, entry, interrupt)
  668. queue:drain()
  669. return entry
  670. end
  671. function AnimationState:addAnimationByName (trackIndex, animationName, loop, delay)
  672. local animation = self.data.skeletonData:findAnimation(animationName)
  673. if not animation then error("Animation not found: " + animationName) end
  674. return self:addAnimation(trackIndex, animation, loop, delay)
  675. end
  676. function AnimationState:addAnimation (trackIndex, animation, loop, delay)
  677. if not animation then error("animation cannot be null.") end
  678. local last = self:expandToIndex(trackIndex)
  679. if last then
  680. while last.next do
  681. last = last.next
  682. end
  683. end
  684. local entry = self:trackEntry(trackIndex, animation, loop, last)
  685. local queue = self.queue
  686. local data = self.data
  687. if not last then
  688. self:setCurrent(trackIndex, entry, true)
  689. queue:drain()
  690. else
  691. last.next = entry
  692. if delay <= 0 then
  693. local duration = last.animationEnd - last.animationStart
  694. if duration ~= 0 then
  695. if last.loop then
  696. delay = delay + duration * (1 + math_floor(last.trackTime / duration))
  697. else
  698. delay = delay + math_max(duration, last.trackTime)
  699. end
  700. delay = delay - data:getMix(last.animation, animation)
  701. else
  702. delay = last.trackTime
  703. end
  704. end
  705. end
  706. entry.delay = delay
  707. return entry
  708. end
  709. function AnimationState:setEmptyAnimation (trackIndex, mixDuration)
  710. local entry = self:setAnimation(trackIndex, EMPTY_ANIMATION, false)
  711. entry.mixDuration = mixDuration
  712. entry.trackEnd = mixDuration
  713. return entry
  714. end
  715. function AnimationState:addEmptyAnimation (trackIndex, mixDuration, delay)
  716. if delay <= 0 then delay = delay - mixDuration end
  717. local entry = self:addAnimation(trackIndex, EMPTY_ANIMATION, false, delay)
  718. entry.mixDuration = mixDuration
  719. entry.trackEnd = mixDuration
  720. return entry
  721. end
  722. function AnimationState:setEmptyAnimations (mixDuration)
  723. local queue = self.queue
  724. local oldDrainDisabled = queue.drainDisabled
  725. queue.drainDisabled = true
  726. local tracks = self.tracks
  727. local numTracks = getNumTracks(tracks)
  728. local i = 0
  729. while i <= numTracks do
  730. current = tracks[i]
  731. if current then self:setEmptyAnimation(current.trackIndex, mixDuration) end
  732. i = i + 1
  733. end
  734. queue.drainDisabled = oldDrainDisabled
  735. queue:drain()
  736. end
  737. function AnimationState:expandToIndex (index)
  738. return self.tracks[index]
  739. end
  740. function AnimationState:trackEntry (trackIndex, animation, loop, last)
  741. local data = self.data
  742. local entry = TrackEntry.new()
  743. entry.trackIndex = trackIndex
  744. entry.animation = animation
  745. entry.loop = loop
  746. entry.holdPrevious = false
  747. entry.eventThreshold = 0
  748. entry.attachmentThreshold = 0
  749. entry.drawOrderThreshold = 0
  750. entry.animationStart = 0
  751. entry.animationEnd = animation.duration
  752. entry.animationLast = -1
  753. entry.nextAnimationLast = -1
  754. entry.delay = 0
  755. entry.trackTime = 0
  756. entry.trackLast = -1
  757. entry.nextTrackLast = -1
  758. entry.trackEnd = 999999999
  759. entry.timeScale = 1
  760. entry.alpha = 1
  761. entry.interruptAlpha = 1
  762. entry.mixTime = 0
  763. if not last then
  764. entry.mixDuration = 0
  765. else
  766. entry.mixDuration = data:getMix(last.animation.name, animation.name)
  767. end
  768. entry.mixBlend = MixBlend.replace
  769. return entry
  770. end
  771. function AnimationState:disposeNext (entry)
  772. local _next = entry.next
  773. local queue = self.queue
  774. while _next do
  775. queue:dispose(_next)
  776. _next = _next.next
  777. end
  778. entry.next = nil
  779. end
  780. function getNumTracks(tracks)
  781. local numTracks = 0
  782. if tracks then
  783. for i, track in pairs(tracks) do
  784. if i > numTracks then
  785. numTracks = i
  786. end
  787. end
  788. end
  789. return numTracks
  790. end
  791. function AnimationState:_animationsChanged ()
  792. self.animationsChanged = false
  793. self.propertyIDs = {}
  794. local highestIndex = -1
  795. local tracks = self.tracks
  796. local numTracks = getNumTracks(tracks)
  797. local i = 0
  798. while i <= numTracks do
  799. entry = tracks[i]
  800. if entry then
  801. if i > highestIndex then highestIndex = i end
  802. if entry then
  803. while entry.mixingFrom do
  804. entry = entry.mixingFrom
  805. end
  806. repeat
  807. if (entry.mixingTo == nil or entry.mixBlend ~= MixBlend.add) then
  808. self:computeHold(entry)
  809. end
  810. entry = entry.mixingTo
  811. until (entry == nil)
  812. end
  813. end
  814. i = i + 1
  815. end
  816. end
  817. function AnimationState:computeHold(entry)
  818. local to = entry.mixingTo
  819. local timelines = entry.animation.timelines
  820. local timelinesCount = #entry.animation.timelines
  821. local timelineMode = entry.timelineMode
  822. local timelineHoldMix = entry.timelineHoldMix
  823. local propertyIDs = self.propertyIDs
  824. if (to and to.holdPrevious) then
  825. local i = 1
  826. while i <= timelinesCount do
  827. local id = "" .. timelines[i]:getPropertyId()
  828. if propertyIDs[id] == nil then
  829. propertyIDs[id] = id
  830. timelineMode[i] = HOLD_FIRST
  831. else
  832. timelineMode[i] = HOLD_SUBSEQUENT
  833. end
  834. end
  835. return
  836. end
  837. local i = 1
  838. local skip
  839. while i <= timelinesCount do
  840. local id = "" .. timelines[i]:getPropertyId()
  841. if propertyIDs[id] then
  842. timelineMode[i] = SUBSEQUENT
  843. else
  844. propertyIDs[id] = id
  845. local timeline = timelines[i]
  846. if to == nil or timeline.type == Animation.TimelineType.attachment
  847. or timeline.type == Animation.TimelineType.drawOrder
  848. or timeline.type == Animation.TimelineType.event
  849. or not to.animation:hasTimeline(id) then
  850. timelineMode[i] = FIRST
  851. else
  852. local next = to.mixingTo
  853. skip = false
  854. while next do
  855. if not next.animation:hasTimeline(id) then
  856. if entry.mixDuration > 0 then
  857. timelineMode[i] = HOLD_MIX
  858. timelineHoldMix[i] = next
  859. skip = true
  860. break
  861. end
  862. end
  863. next = next.mixingTo
  864. end
  865. if not skip then timelineMode[i] = HOLD_FIRST end
  866. end
  867. end
  868. i = i + 1
  869. end
  870. end
  871. function AnimationState:getCurrent (trackIndex)
  872. return self.tracks[trackIndex]
  873. end
  874. function AnimationState:getLast (trackIndex)
  875. local lastEntry = self.tracks[trackIndex]
  876. while lastEntry.next do
  877. lastEntry = lastEntry.next
  878. end
  879. return lastEntry
  880. end
  881. function AnimationState:clearListeners ()
  882. self.onStart = nil
  883. self.onInterrupt = nil
  884. self.onEnd = nil
  885. self.onComplete = nil
  886. self.onDispose = nil
  887. self.onEvent = nil
  888. end
  889. function AnimationState:clearListenerNotificatin ()
  890. self.queue:clear()
  891. end
  892. return AnimationState