AnimationState.lua 27 KB

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