AnimationState.lua 27 KB

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