AnimationState.lua 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  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 MixPose = Animation.MixPose
  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 DIP = 2
  51. local DIP_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,
  152. onStart = nil, onInterrupt = nil, onEnd = nil, onDispose = nil, onComplete = nil, onEvent = nil,
  153. trackIndex = 0,
  154. loop = 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. timelineData = {},
  160. timelineDipMix = {},
  161. timelinesRotation = {}
  162. }
  163. setmetatable(self, TrackEntry)
  164. return self
  165. end
  166. function TrackEntry:setTimelineData(to, mixingToArray, propertyIDs)
  167. if to then table_insert(mixingToArray, to) end
  168. local lastEntry = self
  169. if self.mixingFrom then lastEntry = self.mixingFrom:setTimelineData(self, mixingToArray, propertyIDs) end
  170. if to then mixingToArray[#mixingToArray] = nil end
  171. local mixingTo = mixingToArray
  172. local mixingToLast = #mixingToArray
  173. local timelines = self.animation.timelines
  174. local timelinesCount = #self.animation.timelines
  175. local timelineData = self.timelineData
  176. local timelineDipMix = self.timelineDipMix
  177. local i = 1
  178. while i <= timelinesCount do
  179. local id = "" .. timelines[i]:getPropertyId()
  180. if not (propertyIDs[id] == nil) then
  181. timelineData[i] = SUBSEQUENT
  182. elseif (to == nil or not to:hasTimeline(id)) then
  183. timelineData[i] = FIRST
  184. else
  185. local ii = mixingToLast
  186. while ii > 0 do
  187. local entry = mixingTo[ii]
  188. local skip = false
  189. if not entry:hasTimeline(id) then
  190. if entry.mixDuration > 0 then
  191. timelineData[i] = DIP_MIX
  192. timelineDipMix[i] = entry
  193. skip = true
  194. break
  195. end
  196. break;
  197. end
  198. ii = ii - 1
  199. end
  200. if not skip then timelineData[i] = DIP end
  201. end
  202. i = i + 1
  203. end
  204. return lastEntry
  205. end
  206. function TrackEntry:hasTimeline(id)
  207. local timelines = self.animation.timelines
  208. for i,timeline in ipairs(timelines) do
  209. if timeline:getPropertyId() == id then return true end
  210. end
  211. return false
  212. end
  213. function TrackEntry:getAnimationTime ()
  214. if self.loop then
  215. local duration = self.animationEnd - self.animationStart
  216. if duration == 0 then return self.animationStart end
  217. return (self.trackTime % duration) + self.animationStart
  218. end
  219. return math_min(self.trackTime + self.animationStart, self.animationEnd)
  220. end
  221. function TrackEntry:resetRotationDirections ()
  222. self.timelinesRotation = {}
  223. end
  224. local AnimationState = {}
  225. AnimationState.__index = AnimationState
  226. function AnimationState.new (data)
  227. if not data then error("data cannot be nil", 2) end
  228. local self = {
  229. data = data,
  230. tracks = {},
  231. events = {},
  232. onStart = nil, onInterrupt = nil, onEnd = nil, onDispose = nil, onComplete = nil, onEvent = nil,
  233. queue = nil,
  234. propertyIDs = {},
  235. animationsChanged = false,
  236. timeScale = 1,
  237. mixingTo = {}
  238. }
  239. self.queue = EventQueue.new(self)
  240. setmetatable(self, AnimationState)
  241. return self
  242. end
  243. AnimationState.TrackEntry = TrackEntry
  244. function AnimationState:update (delta)
  245. delta = delta * self.timeScale
  246. local tracks = self.tracks
  247. local queue = self.queue
  248. for i,current in pairs(tracks) do
  249. if current then
  250. current.animationLast = current.nextAnimationLast
  251. current.trackLast = current.nextTrackLast
  252. local currentDelta = delta * current.timeScale
  253. local skip = false
  254. if current.delay > 0 then
  255. current.delay = current.delay - currentDelta
  256. if current.delay <= 0 then
  257. skip = true
  258. currentDelta = -current.delay
  259. current.delay = 0
  260. end
  261. end
  262. if not skip then
  263. local _next = current.next
  264. if _next then
  265. -- When the next entry's delay is passed, change to the next entry, preserving leftover time.
  266. local nextTime = current.trackLast - _next.delay
  267. if nextTime >= 0 then
  268. _next.delay = 0
  269. _next.trackTime = nextTime + delta * _next.timeScale
  270. current.trackTime = current.trackTime + currentDelta
  271. self:setCurrent(i, _next, true)
  272. while _next.mixingFrom do
  273. _next.mixTime = _next.mixTime + currentDelta
  274. _next = _next.mixingFrom
  275. end
  276. skip = true
  277. end
  278. else
  279. -- Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom.
  280. if current.trackLast >= current.trackEnd and current.mixingFrom == nil then
  281. tracks[i] = nil
  282. queue:_end(current)
  283. self:disposeNext(current)
  284. skip = true
  285. end
  286. end
  287. if not skip then
  288. if current.mixingFrom and self:updateMixingFrom(current, delta) then
  289. -- End mixing from entries once all have completed.
  290. local from = current.mixingFrom
  291. current.mixingFrom = nil
  292. while from do
  293. queue:_end(from)
  294. from = from.mixingFrom
  295. end
  296. end
  297. current.trackTime = current.trackTime + currentDelta
  298. end
  299. end
  300. end
  301. end
  302. queue:drain()
  303. end
  304. function AnimationState:updateMixingFrom (to, delta)
  305. local from = to.mixingFrom
  306. if from == nil then return true end
  307. local finished = self:updateMixingFrom(from, delta)
  308. -- Require mixTime > 0 to ensure the mixing from entry was applied at least once.
  309. if (to.mixTime > 0 and (to.mixTime >= to.mixDuration or to.timeScale == 0)) then
  310. if (from.totalAlpha == 0) then
  311. to.mixingFrom = from.mixingFrom
  312. to.interruptAlpha = from.interruptAlpha
  313. self.queue:_end(from)
  314. end
  315. return finished
  316. end
  317. from.animationLast = from.nextAnimationLast
  318. from.trackLast = from.nextTrackLast
  319. from.trackTime = from.trackTime + delta * from.timeScale
  320. to.mixTime = to.mixTime + delta * to.timeScale
  321. return false;
  322. end
  323. function AnimationState:apply (skeleton)
  324. if skeleton == nil then error("skeleton cannot be null.", 2) end
  325. if self.animationsChanged then self:_animationsChanged() end
  326. local events = self.events
  327. local tracks = self.tracks
  328. local queue = self.queue
  329. local applied = false
  330. for i,current in pairs(tracks) do
  331. if not (current == nil or current.delay > 0) then
  332. applied = true
  333. local currrentPose = MixPose.currentLayered
  334. if i == 0 then currentPose = MixPose.current end
  335. -- Apply mixing from entries first.
  336. local mix = current.alpha
  337. if current.mixingFrom then
  338. mix = mix * self:applyMixingFrom(current, skeleton, currentPose)
  339. elseif current.trackTime >= current.trackEnd and current.next == nil then
  340. mix = 0
  341. end
  342. -- Apply current entry.
  343. local animationLast = current.animationLast
  344. local animationTime = current:getAnimationTime()
  345. local timelines = current.animation.timelines
  346. if mix == 1 then
  347. for i,timeline in ipairs(timelines) do
  348. timeline:apply(skeleton, animationLast, animationTime, events, 1, MixPose.setup, MixDirection._in)
  349. end
  350. else
  351. local timelineData = current.timelineData
  352. local firstFrame = #current.timelinesRotation == 0
  353. local timelinesRotation = current.timelinesRotation
  354. for i,timeline in ipairs(timelines) do
  355. local pose = MixPose.currentPose
  356. if timelineData[i] >= FIRST then pose = MixPose.setup end
  357. if timeline.type == Animation.TimelineType.rotate then
  358. self:applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, i * 2,
  359. firstFrame) -- FIXME passing ii * 2, indexing correct?
  360. else
  361. timeline:apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection._in)
  362. end
  363. end
  364. end
  365. self:queueEvents(current, animationTime)
  366. self.events = {};
  367. current.nextAnimationLast = animationTime
  368. current.nextTrackLast = current.trackTime
  369. end
  370. end
  371. queue:drain()
  372. return applied
  373. end
  374. function AnimationState:applyMixingFrom (to, skeleton, currentPose)
  375. local from = to.mixingFrom
  376. if from.mixingFrom then self:applyMixingFrom(from, skeleton, currentPose) end
  377. local mix = 0
  378. if to.mixDuration == 0 then -- Single frame mix to undo mixingFrom changes.
  379. mix = 1
  380. else
  381. mix = to.mixTime / to.mixDuration
  382. if mix > 1 then mix = 1 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 timelineData = from.timelineData
  392. local timelineDipMix = from.timelineDipMix
  393. local firstFrame = #from.timelinesRotation == 0
  394. local timelinesRotation = from.timelinesRotation
  395. local pose = MixPose.setup
  396. local alphaDip = from.alpha * to.interruptAlpha
  397. local alphaMix = alphaDip * (1 - mix)
  398. local alpha = 0
  399. from.totalAlpha = 0;
  400. for i,timeline in ipairs(timelines) do
  401. local skipSubsequent = false;
  402. if timelineData[i] == SUBSEQUENT then
  403. if not attachments and timeline.type == Animation.TimelineType.attachment then skipSubsequent = true end
  404. if not drawOrder and timeline.type == Animation.TimelineType.drawOrder then skipSubsequent = true end
  405. pose = currentPose
  406. alpha = alphaMix
  407. elseif timelineData[i] == FIRST then
  408. pose = MixPose.setup
  409. alpha = alphaMix
  410. elseif timelineData[i] == DIP then
  411. pose = MixPose.setup
  412. alpha = alphaDip
  413. else
  414. pose = MixPose.setup
  415. alpha = alphaDip
  416. local dipMix = timelineDipMix[i]
  417. alpha = alpha * math_max(0, 1 - dipMix.mixtime / dipMix.mixDuration)
  418. end
  419. if not skipSubsequent then
  420. from.totalAlpha = from.totalAlpha + alpha
  421. if timeline.type == Animation.TimelineType.rotate then
  422. self:applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i * 2, firstFrame)
  423. else
  424. timeline:apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.out)
  425. end
  426. end
  427. end
  428. if (to.mixDuration > 0) then self:queueEvents(from, animationTime) end
  429. self.events = {};
  430. from.nextAnimationLast = animationTime
  431. from.nextTrackLast = from.trackTime
  432. return mix
  433. end
  434. function AnimationState:applyRotateTimeline (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame)
  435. if firstFrame then
  436. timelinesRotation[i] = 0
  437. timelinesRotation[i+1] = 0
  438. end
  439. if alpha == 1 then
  440. timeline:apply(skeleton, 0, time, nil, 1, pose, MixDirection._in)
  441. return
  442. end
  443. local rotateTimeline = timeline
  444. local frames = rotateTimeline.frames
  445. local bone = skeleton.bones[rotateTimeline.boneIndex]
  446. if time < frames[0] then
  447. if pose == MixPose.setup then bone.rotation = bone.data.rotation end
  448. return
  449. end
  450. local r2 = 0
  451. if time >= frames[zlen(frames) - Animation.RotateTimeline.ENTRIES] then -- Time is after last frame.
  452. r2 = bone.data.rotation + frames[zlen(frames) + Animation.RotateTimeline.PREV_ROTATION]
  453. else
  454. -- Interpolate between the previous frame and the current frame.
  455. local frame = Animation.binarySearch(frames, time, Animation.RotateTimeline.ENTRIES)
  456. local prevRotation = frames[frame + Animation.RotateTimeline.PREV_ROTATION]
  457. local frameTime = frames[frame]
  458. local percent = rotateTimeline:getCurvePercent(math_floor(frame / 2) - 1,
  459. 1 - (time - frameTime) / (frames[frame + Animation.RotateTimeline.PREV_TIME] - frameTime))
  460. r2 = frames[frame + Animation.RotateTimeline.ROTATION] - prevRotation
  461. r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
  462. r2 = prevRotation + r2 * percent + bone.data.rotation
  463. r2 = r2 - (16384 - math_floor(16384.499999999996 - r2 / 360)) * 360
  464. end
  465. -- Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
  466. local r1 = bone.rotation
  467. if pose == MixPose.setup then r1 = bone.data.rotation end
  468. local total = 0
  469. local diff = r2 - r1
  470. if diff == 0 then
  471. total = timelinesRotation[i]
  472. else
  473. diff = diff - (16384 - math_floor(16384.499999999996 - diff / 360)) * 360
  474. local lastTotal = 0
  475. local lastDiff = 0
  476. if firstFrame then
  477. lastTotal = 0
  478. lastDiff = diff
  479. else
  480. lastTotal = timelinesRotation[i] -- Angle and direction of mix, including loops.
  481. lastDiff = timelinesRotation[i + 1] -- Difference between bones.
  482. end
  483. local current = diff > 0
  484. local dir = lastTotal >= 0
  485. -- Detect cross at 0 (not 180).
  486. if math_signum(lastDiff) ~= math_signum(diff) and math_abs(lastDiff) <= 90 then
  487. -- A cross after a 360 rotation is a loop.
  488. if math_abs(lastTotal) > 180 then lastTotal = lastTotal + 360 * math_signum(lastTotal) end
  489. dir = current
  490. end
  491. total = diff + lastTotal - math_mod(lastTotal, 360) -- FIXME used to be %360, store loops as part of lastTotal.
  492. if dir ~= current then total = total + 360 * math_signum(lastTotal) end
  493. timelinesRotation[i] = total
  494. end
  495. timelinesRotation[i + 1] = diff
  496. r1 = r1 + total * alpha
  497. bone.rotation = r1 - (16384 - math_floor(16384.499999999996 - r1 / 360)) * 360
  498. end
  499. function AnimationState:queueEvents (entry, animationTime)
  500. local animationStart = entry.animationStart
  501. local animationEnd = entry.animationEnd
  502. local duration = animationEnd - animationStart
  503. local trackLastWrapped = entry.trackLast % duration
  504. -- Queue events before complete.
  505. local events = self.events
  506. local queue = self.queue
  507. local i = 1
  508. local n = #events
  509. while i <= n do
  510. local event = events[i]
  511. if event.time < trackLastWrapped then break end
  512. if not (event.time > animationEnd) then -- Discard events outside animation start/end.
  513. queue:event(entry, event)
  514. end
  515. i = i + 1
  516. end
  517. -- Queue complete if completed a loop iteration or the animation.
  518. local queueComplete = false
  519. if entry.loop then
  520. queueComplete = (trackLastWrapped > entry.trackTime % duration)
  521. else
  522. queueComplete = (animationTime >= animationEnd and entry.animationLast < animationEnd)
  523. end
  524. if queueComplete then
  525. queue:complete(entry)
  526. end
  527. -- Queue events after complete.
  528. while i <= n do
  529. local event = events[i]
  530. if not (event.time < animationStart) then --// Discard events outside animation start/end.
  531. queue:event(entry, event)
  532. end
  533. i = i + 1
  534. end
  535. end
  536. function AnimationState:clearTracks ()
  537. local queue = self.queue
  538. local tracks = self.tracks
  539. local oldDrainDisabled = queue.drainDisabled
  540. queue.drainDisabled = true;
  541. for i,track in pairs(tracks) do
  542. self:clearTrack(i)
  543. end
  544. tracks = {}
  545. queue.drainDisabled = oldDrainDisabled
  546. queue:drain();
  547. end
  548. function AnimationState:clearTrack (trackIndex)
  549. local tracks = self.tracks
  550. local queue = self.queue
  551. local current = tracks[trackIndex]
  552. if current == nil then return end
  553. queue:_end(current)
  554. self:disposeNext(current)
  555. local entry = current;
  556. while (true) do
  557. local from = entry.mixingFrom
  558. if from == nil then break end
  559. queue:_end(from)
  560. entry.mixingFrom = nil
  561. entry = from
  562. end
  563. tracks[current.trackIndex] = nil
  564. queue:drain()
  565. end
  566. function AnimationState:setCurrent (index, current, interrupt)
  567. local from = self:expandToIndex(index)
  568. local tracks = self.tracks
  569. local queue = self.queue
  570. tracks[index] = current
  571. if from then
  572. if interrupt then queue:interrupt(from) end
  573. current.mixingFrom = from
  574. current.mixTime = 0
  575. if from.mixingFrom and from.mixDuration > 0 then
  576. current.interruptAlpha = current.interruptAlpha * math_min(1, from.mixTime / from.mixDuration)
  577. end
  578. from.timelinesRotation = {};
  579. end
  580. queue:start(current)
  581. end
  582. function AnimationState:setAnimationByName (trackIndex, animationName, loop)
  583. local animation = self.data.skeletonData:findAnimation(animationName)
  584. if not animation then error("Animation not found: " .. animationName, 2) end
  585. return self:setAnimation(trackIndex, animation, loop)
  586. end
  587. function AnimationState:setAnimation (trackIndex, animation, loop)
  588. if not animation then error("animation cannot be null.") end
  589. local interrupt = true;
  590. local current = self:expandToIndex(trackIndex)
  591. local queue = self.queue
  592. local tracks = self.tracks
  593. if current then
  594. if current.nextTrackLast == -1 then
  595. -- Don't mix from an entry that was never applied.
  596. tracks[trackIndex] = current.mixingFrom
  597. queue:interrupt(current)
  598. queue:_end(current)
  599. self:disposeNext(current)
  600. current = current.mixingFrom
  601. interrupt = false;
  602. else
  603. self:disposeNext(current)
  604. end
  605. end
  606. local entry = self:trackEntry(trackIndex, animation, loop, current)
  607. self:setCurrent(trackIndex, entry, interrupt)
  608. queue:drain()
  609. return entry
  610. end
  611. function AnimationState:addAnimationByName (trackIndex, animationName, loop, delay)
  612. local animation = self.data.skeletonData:findAnimation(animationName)
  613. if not animation then error("Animation not found: " + animationName) end
  614. return self:addAnimation(trackIndex, animation, loop, delay)
  615. end
  616. function AnimationState:addAnimation (trackIndex, animation, loop, delay)
  617. if not animation then error("animation cannot be null.") end
  618. local last = self:expandToIndex(trackIndex)
  619. if last then
  620. while last.next do
  621. last = last.next
  622. end
  623. end
  624. local entry = self:trackEntry(trackIndex, animation, loop, last)
  625. local queue = self.queue
  626. local data = self.data
  627. if not last then
  628. self:setCurrent(trackIndex, entry, true)
  629. queue:drain()
  630. else
  631. last.next = entry
  632. if delay <= 0 then
  633. local duration = last.animationEnd - last.animationStart
  634. if duration ~= 0 then
  635. delay = delay + duration * (1 + math_floor(last.trackTime / duration)) - data:getMix(last.animation, animation)
  636. else
  637. delay = 0
  638. end
  639. end
  640. end
  641. entry.delay = delay
  642. return entry
  643. end
  644. function AnimationState:setEmptyAnimation (trackIndex, mixDuration)
  645. local entry = self:setAnimation(trackIndex, EMPTY_ANIMATION, false)
  646. entry.mixDuration = mixDuration
  647. entry.trackEnd = mixDuration
  648. return entry
  649. end
  650. function AnimationState:addEmptyAnimation (trackIndex, mixDuration, delay)
  651. if delay <= 0 then delay = delay - mixDuration end
  652. local entry = self:addAnimation(trackIndex, EMPTY_ANIMATION, false, delay)
  653. entry.mixDuration = mixDuration
  654. entry.trackEnd = mixDuration
  655. return entry
  656. end
  657. function AnimationState:setEmptyAnimations (mixDuration)
  658. local queue = self.queue
  659. local oldDrainDisabled = queue.drainDisabled
  660. queue.drainDisabled = true
  661. for i,current in pairs(self.tracks) do
  662. if current then self:setEmptyAnimation(current.trackIndex, mixDuration) end
  663. end
  664. queue.drainDisabled = oldDrainDisabled
  665. queue:drain()
  666. end
  667. function AnimationState:expandToIndex (index)
  668. return self.tracks[index]
  669. end
  670. function AnimationState:trackEntry (trackIndex, animation, loop, last)
  671. local data = self.data
  672. local entry = TrackEntry.new()
  673. entry.trackIndex = trackIndex
  674. entry.animation = animation
  675. entry.loop = loop
  676. entry.eventThreshold = 0
  677. entry.attachmentThreshold = 0
  678. entry.drawOrderThreshold = 0
  679. entry.animationStart = 0
  680. entry.animationEnd = animation.duration
  681. entry.animationLast = -1
  682. entry.nextAnimationLast = -1
  683. entry.delay = 0
  684. entry.trackTime = 0
  685. entry.trackLast = -1
  686. entry.nextTrackLast = -1
  687. entry.trackEnd = 999999999
  688. entry.timeScale = 1
  689. entry.alpha = 1
  690. entry.interruptAlpha = 1
  691. entry.mixTime = 0
  692. if not last then
  693. entry.mixDuration = 0
  694. else
  695. entry.mixDuration = data:getMix(last.animation, animation)
  696. end
  697. return entry
  698. end
  699. function AnimationState:disposeNext (entry)
  700. local _next = entry.next
  701. local queue = self.queue
  702. while _next do
  703. queue:dispose(_next)
  704. _next = _next.next
  705. end
  706. entry.next = nil
  707. end
  708. function AnimationState:_animationsChanged ()
  709. self.animationsChanged = false
  710. self.propertyIDs = {}
  711. local propertyIDs = self.propertyIDs
  712. local mixingTo = self.mixingTo
  713. local lastEntry = nil
  714. for i, entry in pairs(self.tracks) do
  715. if entry then
  716. entry:setTimelineData(lastEntry, mixingTo, propertyIDs)
  717. lastEntry = entry
  718. end
  719. end
  720. end
  721. function AnimationState:getCurrent (trackIndex)
  722. return self.tracks[trackIndex]
  723. end
  724. function AnimationState:clearListeners ()
  725. self.onStart = nil
  726. self.onInterrupt = nil
  727. self.onEnd = nil
  728. self.onComplete = nil
  729. self.onDispose = nil
  730. self.onEvent = nil
  731. end
  732. function AnimationState:clearListenerNotificatin ()
  733. self.queue:clear()
  734. end
  735. return AnimationState