Animation.lua 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. -------------------------------------------------------------------------------
  2. -- Spine Runtimes Software License
  3. -- Version 2.1
  4. --
  5. -- Copyright (c) 2013, Esoteric Software
  6. -- All rights reserved.
  7. --
  8. -- You are granted a perpetual, non-exclusive, non-sublicensable and
  9. -- non-transferable license to install, execute and perform the Spine Runtimes
  10. -- Software (the "Software") solely for internal use. Without the written
  11. -- permission of Esoteric Software (typically granted by licensing Spine), you
  12. -- may not (a) modify, translate, adapt or otherwise create derivative works,
  13. -- improvements of the Software or develop new applications using the Software
  14. -- or (b) remove, delete, alter or obscure any trademarks or any copyright,
  15. -- trademark, patent or other intellectual property or proprietary rights
  16. -- notices on or in the Software, including any copy thereof. Redistributions
  17. -- in binary or source 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 SOFTARE 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; LOSS OF USE, DATA, OR PROFITS;
  25. -- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26. -- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  27. -- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  28. -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. -------------------------------------------------------------------------------
  30. local Animation = {}
  31. function Animation.new (name, timelines, duration)
  32. if not timelines then error("timelines cannot be nil", 2) end
  33. local self = {
  34. name = name,
  35. timelines = timelines,
  36. duration = duration
  37. }
  38. function self:apply (skeleton, lastTime, time, loop, events)
  39. if not skeleton then error("skeleton cannot be nil.", 2) end
  40. if loop and duration > 0 then
  41. time = time % self.duration
  42. lastTime = lastTime % self.duration
  43. end
  44. for i,timeline in ipairs(self.timelines) do
  45. timeline:apply(skeleton, lastTime, time, events, 1)
  46. end
  47. end
  48. function self:mix (skeleton, lastTime, time, loop, events, alpha)
  49. if not skeleton then error("skeleton cannot be nil.", 2) end
  50. if loop and duration > 0 then
  51. time = time % self.duration
  52. lastTime = lastTime % self.duration
  53. end
  54. for i,timeline in ipairs(self.timelines) do
  55. timeline:apply(skeleton, lastTime, time, events, alpha)
  56. end
  57. end
  58. return self
  59. end
  60. local function binarySearch (values, target, step)
  61. local low = 0
  62. local high = math.floor((#values + 1) / step - 2)
  63. if high == 0 then return step end
  64. local current = math.floor(high / 2)
  65. while true do
  66. if values[(current + 1) * step] <= target then
  67. low = current + 1
  68. else
  69. high = current
  70. end
  71. if low == high then return (low + 1) * step end
  72. current = math.floor((low + high) / 2)
  73. end
  74. end
  75. local function binarySearch1 (values, target)
  76. local low = 0
  77. local high = math.floor(#values - 1)
  78. if high == 0 then return 1 end
  79. local current = math.floor(high / 2)
  80. while true do
  81. if values[current + 1] <= target then
  82. low = current + 1
  83. else
  84. high = current
  85. end
  86. if low == high then return low + 1 end
  87. current = math.floor((low + high) / 2)
  88. end
  89. end
  90. local function linearSearch (values, target, step)
  91. for i = 0, #values, step do
  92. if (values[i] > target) then return i end
  93. end
  94. return -1
  95. end
  96. Animation.CurveTimeline = {}
  97. function Animation.CurveTimeline.new ()
  98. local LINEAR = 0
  99. local STEPPED = 1
  100. local BEZIER = 2;
  101. local BEZIER_SEGMENTS = 10
  102. local BEZIER_SIZE = BEZIER_SEGMENTS * 2 - 1
  103. local self = {
  104. curves = {} -- type, x, y, ...
  105. }
  106. function self:setLinear (frameIndex)
  107. self.curves[frameIndex * BEZIER_SIZE] = LINEAR
  108. end
  109. function self:setStepped (frameIndex)
  110. self.curves[frameIndex * BEZIER_SIZE] = STEPPED
  111. end
  112. function self:setCurve (frameIndex, cx1, cy1, cx2, cy2)
  113. local subdiv1 = 1 / BEZIER_SEGMENTS
  114. local subdiv2 = subdiv1 * subdiv1
  115. local subdiv3 = subdiv2 * subdiv1;
  116. local pre1 = 3 * subdiv1
  117. local pre2 = 3 * subdiv2
  118. local pre4 = 6 * subdiv2
  119. local pre5 = 6 * subdiv3
  120. local tmp1x = -cx1 * 2 + cx2
  121. local tmp1y = -cy1 * 2 + cy2
  122. local tmp2x = (cx1 - cx2) * 3 + 1
  123. local tmp2y = (cy1 - cy2) * 3 + 1
  124. local dfx = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv3
  125. local dfy = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv3
  126. local ddfx = tmp1x * pre4 + tmp2x * pre5
  127. local ddfy = tmp1y * pre4 + tmp2y * pre5;
  128. local dddfx = tmp2x * pre5
  129. local dddfy = tmp2y * pre5
  130. local i = frameIndex * BEZIER_SIZE
  131. local curves = self.curves
  132. curves[i] = BEZIER
  133. i = i + 1
  134. local x = dfx
  135. local y = dfy
  136. local n = i + BEZIER_SIZE - 1
  137. while i < n do
  138. curves[i] = x
  139. curves[i + 1] = y
  140. dfx = dfx + ddfx
  141. dfy = dfy + ddfy
  142. ddfx = ddfx + dddfx
  143. ddfy = ddfy + dddfy
  144. x = x + dfx
  145. y = y + dfy
  146. i = i + 2
  147. end
  148. end
  149. function self:getCurvePercent (frameIndex, percent)
  150. local curves = self.curves
  151. local i = frameIndex * BEZIER_SIZE
  152. local type = curves[i]
  153. if type == LINEAR then return percent end
  154. if type == STEPPED then return 0 end
  155. i = i + 1
  156. local x
  157. local n = i + BEZIER_SIZE - 1
  158. local start = i
  159. while i < n do
  160. x = curves[i]
  161. if x >= percent then
  162. local prevX, prevY
  163. if i == start then
  164. prevX = 0
  165. prevY = 0
  166. else
  167. prevX = curves[i - 2]
  168. prevY = curves[i - 1]
  169. end
  170. return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX)
  171. end
  172. i = i + 2
  173. end
  174. local y = curves[i - 1]
  175. return y + (1 - y) * (percent - x) / (1 - x) -- Last point is 1,1.
  176. end
  177. return self
  178. end
  179. Animation.RotateTimeline = {}
  180. function Animation.RotateTimeline.new ()
  181. local PREV_FRAME_TIME = -2
  182. local FRAME_VALUE = 1
  183. local self = Animation.CurveTimeline.new()
  184. self.frames = {}
  185. self.boneIndex = -1
  186. function self:getDuration ()
  187. return self.frames[#self.frames - 1]
  188. end
  189. function self:getFrameCount ()
  190. return (#self.frames + 1) / 2
  191. end
  192. function self:setFrame (frameIndex, time, value)
  193. frameIndex = frameIndex * 2
  194. self.frames[frameIndex] = time
  195. self.frames[frameIndex + 1] = value
  196. end
  197. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  198. local frames = self.frames
  199. if time < frames[0] then return end -- Time is before first frame.
  200. local bone = skeleton.bones[self.boneIndex]
  201. if time >= frames[#frames - 1] then -- Time is after last frame.
  202. local amount = bone.data.rotation + frames[#frames] - bone.rotation
  203. while amount > 180 do
  204. amount = amount - 360
  205. end
  206. while amount < -180 do
  207. amount = amount + 360
  208. end
  209. bone.rotation = bone.rotation + amount * alpha
  210. return
  211. end
  212. -- Interpolate between the last frame and the current frame.
  213. local frameIndex = binarySearch(frames, time, 2)
  214. local prevFrameValue = frames[frameIndex - 1]
  215. local frameTime = frames[frameIndex]
  216. local percent = 1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime)
  217. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  218. percent = self:getCurvePercent(frameIndex / 2 - 1, percent)
  219. local amount = frames[frameIndex + FRAME_VALUE] - prevFrameValue
  220. while amount > 180 do
  221. amount = amount - 360
  222. end
  223. while amount < -180 do
  224. amount = amount + 360
  225. end
  226. amount = bone.data.rotation + (prevFrameValue + amount * percent) - bone.rotation
  227. while amount > 180 do
  228. amount = amount - 360
  229. end
  230. while amount < -180 do
  231. amount = amount + 360
  232. end
  233. bone.rotation = bone.rotation + amount * alpha
  234. end
  235. return self
  236. end
  237. Animation.TranslateTimeline = {}
  238. function Animation.TranslateTimeline.new ()
  239. local PREV_FRAME_TIME = -3
  240. local FRAME_X = 1
  241. local FRAME_Y = 2
  242. local self = Animation.CurveTimeline.new()
  243. self.frames = {}
  244. self.boneIndex = -1
  245. function self:getDuration ()
  246. return self.frames[#self.frames - 2]
  247. end
  248. function self:getFrameCount ()
  249. return (#self.frames + 1) / 3
  250. end
  251. function self:setFrame (frameIndex, time, x, y)
  252. frameIndex = frameIndex * 3
  253. self.frames[frameIndex] = time
  254. self.frames[frameIndex + 1] = x
  255. self.frames[frameIndex + 2] = y
  256. end
  257. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  258. local frames = self.frames
  259. if time < frames[0] then return end -- Time is before first frame.
  260. local bone = skeleton.bones[self.boneIndex]
  261. if time >= frames[#frames - 2] then -- Time is after last frame.
  262. bone.x = bone.x + (bone.data.x + frames[#frames - 1] - bone.x) * alpha
  263. bone.y = bone.y + (bone.data.y + frames[#frames] - bone.y) * alpha
  264. return
  265. end
  266. -- Interpolate between the last frame and the current frame.
  267. local frameIndex = binarySearch(frames, time, 3)
  268. local prevFrameX = frames[frameIndex - 2]
  269. local prevFrameY = frames[frameIndex - 1]
  270. local frameTime = frames[frameIndex]
  271. local percent = 1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime)
  272. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  273. percent = self:getCurvePercent(frameIndex / 3 - 1, percent)
  274. bone.x = bone.x + (bone.data.x + prevFrameX + (frames[frameIndex + FRAME_X] - prevFrameX) * percent - bone.x) * alpha
  275. bone.y = bone.y + (bone.data.y + prevFrameY + (frames[frameIndex + FRAME_Y] - prevFrameY) * percent - bone.y) * alpha
  276. end
  277. return self
  278. end
  279. Animation.ScaleTimeline = {}
  280. function Animation.ScaleTimeline.new ()
  281. local PREV_FRAME_TIME = -3
  282. local FRAME_X = 1
  283. local FRAME_Y = 2
  284. local self = Animation.TranslateTimeline.new()
  285. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  286. local frames = self.frames
  287. if time < frames[0] then return end -- Time is before first frame.
  288. local bone = skeleton.bones[self.boneIndex]
  289. if time >= frames[#frames - 2] then -- Time is after last frame.
  290. bone.scaleX = bone.scaleX + (bone.data.scaleX * frames[#frames - 1] - bone.scaleX) * alpha
  291. bone.scaleY = bone.scaleY + (bone.data.scaleY * frames[#frames] - bone.scaleY) * alpha
  292. return
  293. end
  294. -- Interpolate between the last frame and the current frame.
  295. local frameIndex = binarySearch(frames, time, 3)
  296. local prevFrameX = frames[frameIndex - 2]
  297. local prevFrameY = frames[frameIndex - 1]
  298. local frameTime = frames[frameIndex]
  299. local percent = 1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime)
  300. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  301. percent = self:getCurvePercent(frameIndex / 3 - 1, percent)
  302. bone.scaleX = bone.scaleX + (bone.data.scaleX * (prevFrameX + (frames[frameIndex + FRAME_X] - prevFrameX) * percent) - bone.scaleX) * alpha
  303. bone.scaleY = bone.scaleY + (bone.data.scaleY * (prevFrameY + (frames[frameIndex + FRAME_Y] - prevFrameY) * percent) - bone.scaleY) * alpha
  304. end
  305. return self
  306. end
  307. Animation.ColorTimeline = {}
  308. function Animation.ColorTimeline.new ()
  309. local PREV_FRAME_TIME = -5
  310. local FRAME_R = 1
  311. local FRAME_G = 2
  312. local FRAME_B = 3
  313. local FRAME_A = 4
  314. local self = Animation.CurveTimeline.new()
  315. self.frames = {}
  316. self.slotIndex = -1
  317. function self:getDuration ()
  318. return self.frames[#self.frames - 4]
  319. end
  320. function self:getFrameCount ()
  321. return (#self.frames + 1) / 5
  322. end
  323. function self:setFrame (frameIndex, time, r, g, b, a)
  324. frameIndex = frameIndex * 5
  325. self.frames[frameIndex] = time
  326. self.frames[frameIndex + 1] = r
  327. self.frames[frameIndex + 2] = g
  328. self.frames[frameIndex + 3] = b
  329. self.frames[frameIndex + 4] = a
  330. end
  331. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  332. local frames = self.frames
  333. if time < frames[0] then return end -- Time is before first frame.
  334. local r, g, b, a
  335. if time >= frames[#frames - 4] then -- Time is after last frame.
  336. r = frames[#frames - 3]
  337. g = frames[#frames - 2]
  338. b = frames[#frames - 1]
  339. a = frames[#frames]
  340. else
  341. -- Interpolate between the last frame and the current frame.
  342. local frameIndex = binarySearch(frames, time, 5)
  343. local prevFrameR = frames[frameIndex - 4]
  344. local prevFrameG = frames[frameIndex - 3]
  345. local prevFrameB = frames[frameIndex - 2]
  346. local prevFrameA = frames[frameIndex - 1]
  347. local frameTime = frames[frameIndex]
  348. local percent = 1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime)
  349. if percent < 0 then percent = 0 elseif percent > 255 then percent = 255 end
  350. percent = self:getCurvePercent(frameIndex / 5 - 1, percent)
  351. r = prevFrameR + (frames[frameIndex + FRAME_R] - prevFrameR) * percent
  352. g = prevFrameG + (frames[frameIndex + FRAME_G] - prevFrameG) * percent
  353. b = prevFrameB + (frames[frameIndex + FRAME_B] - prevFrameB) * percent
  354. a = prevFrameA + (frames[frameIndex + FRAME_A] - prevFrameA) * percent
  355. end
  356. local slot = skeleton.slots[self.slotIndex]
  357. if alpha < 1 then
  358. slot:setColor(slot.r + (r - slot.r) * alpha, slot.g + (g - slot.g) * alpha, slot.b + (b - slot.b) * alpha, slot.a + (a - slot.a) * alpha)
  359. else
  360. slot:setColor(r, g, b, a)
  361. end
  362. end
  363. return self
  364. end
  365. Animation.AttachmentTimeline = {}
  366. function Animation.AttachmentTimeline.new ()
  367. local self = {
  368. frames = {}, -- time, ...
  369. attachmentNames = {},
  370. slotName = nil
  371. }
  372. function self:getDuration ()
  373. return self.frames[#self.frames]
  374. end
  375. function self:getFrameCount ()
  376. return #self.frames + 1
  377. end
  378. function self:setFrame (frameIndex, time, attachmentName)
  379. self.frames[frameIndex] = time
  380. self.attachmentNames[frameIndex] = attachmentName
  381. end
  382. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  383. local frames = self.frames
  384. if time < frames[0] then
  385. if lastTime > time then self:apply(skeleton, lastTime, 999999, nil, 0) end
  386. return
  387. elseif lastTime > time then
  388. lastTime = -1
  389. end
  390. local frameIndex
  391. if time >= frames[#frames] then
  392. frameIndex = #frames
  393. else
  394. frameIndex = binarySearch1(frames, time) - 1
  395. end
  396. if frames[frameIndex] < lastTime then return end
  397. local attachmentName = self.attachmentNames[frameIndex]
  398. local slot = skeleton.slotsByName[self.slotName]
  399. if attachmentName then
  400. if not slot.attachment then
  401. slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
  402. elseif slot.attachment.name ~= attachmentName then
  403. slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
  404. end
  405. else
  406. slot:setAttachment(nil)
  407. end
  408. end
  409. return self
  410. end
  411. Animation.EventTimeline = {}
  412. function Animation.EventTimeline.new ()
  413. local self = {
  414. frames = {},
  415. events = {}
  416. }
  417. function self:getDuration ()
  418. return self.frames[#self.frames]
  419. end
  420. function self:getFrameCount ()
  421. return #self.frames + 1
  422. end
  423. function self:setFrame (frameIndex, time, event)
  424. self.frames[frameIndex] = time
  425. self.events[frameIndex] = event
  426. end
  427. -- Fires events for frames > lastTime and <= time.
  428. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  429. if not firedEvents then return end
  430. local frames = self.frames
  431. local frameCount = #frames + 1
  432. if lastTime > time then -- Fire events after last time for looped animations.
  433. --self:apply(skeleton, lastTime, 999999, firedEvents, alpha)
  434. lastTime = -1
  435. elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
  436. return
  437. end
  438. if time < frames[0] then return end -- Time is before first frame.
  439. local frameIndex
  440. if lastTime < frames[0] then
  441. frameIndex = 0
  442. else
  443. frameIndex = binarySearch1(frames, lastTime)
  444. local frame = frames[frameIndex]
  445. while frameIndex > 0 do -- Fire multiple events with the same frame.
  446. if frames[frameIndex - 1] ~= frame then break end
  447. frameIndex = frameIndex - 1
  448. end
  449. end
  450. local events = self.events
  451. while frameIndex < frameCount and time >= frames[frameIndex] do
  452. table.insert(firedEvents, events[frameIndex])
  453. frameIndex = frameIndex + 1
  454. end
  455. end
  456. return self
  457. end
  458. Animation.DrawOrderTimeline = {}
  459. function Animation.DrawOrderTimeline.new ()
  460. local self = {
  461. frames = {},
  462. drawOrders = {}
  463. }
  464. function self:getDuration ()
  465. return self.frames[#self.frames]
  466. end
  467. function self:getFrameCount ()
  468. return #self.frames + 1
  469. end
  470. function self:setFrame (frameIndex, time, drawOrder)
  471. self.frames[frameIndex] = time
  472. self.drawOrders[frameIndex] = drawOrder
  473. end
  474. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  475. local frames = self.frames
  476. if time < frames[0] then return end -- Time is before first frame.
  477. local frameIndex
  478. if time >= frames[#frames] then -- Time is after last frame.
  479. frameIndex = #frames
  480. else
  481. frameIndex = binarySearch1(frames, time) - 1
  482. end
  483. local drawOrder = skeleton.drawOrder
  484. local slots = skeleton.slots
  485. local drawOrderToSetupIndex = self.drawOrders[frameIndex]
  486. if not drawOrderToSetupIndex then
  487. for i,slot in ipairs(slots) do
  488. drawOrder[i] = slots[i]
  489. end
  490. else
  491. for i,setupIndex in ipairs(drawOrderToSetupIndex) do
  492. drawOrder[i] = skeleton.slots[setupIndex]
  493. end
  494. end
  495. end
  496. return self
  497. end
  498. Animation.FfdTimeline = {}
  499. function Animation.FfdTimeline.new ()
  500. local self = Animation.CurveTimeline.new()
  501. self.frames = {} -- time, ...
  502. self.frameVertices = {}
  503. self.slotIndex = -1
  504. function self:getDuration ()
  505. return self.frames[#self.frames]
  506. end
  507. function self:getFrameCount ()
  508. return #self.frames + 1
  509. end
  510. function self:setFrame (frameIndex, time, vertices)
  511. self.frames[frameIndex] = time
  512. self.frameVertices[frameIndex] = vertices
  513. end
  514. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  515. local slot = skeleton.slots[self.slotIndex]
  516. if slot.attachment ~= attachment then return end
  517. local frames = self.frames
  518. if time < frames[0] then return end -- Time is before first frame.
  519. local frameVertices = self.frameVertices
  520. local vertexCount = #frameVertices[0]
  521. local vertices = slot.attachmentVertices
  522. if #vertices < vertexCount then
  523. vertices = {}
  524. slot.attachmentVertices = vertices
  525. elseif #vertices < vertexCount then
  526. alpha = 1 -- Don't mix from uninitialized slot vertices.
  527. end
  528. slot.attachmentVerticesCount = vertexCount
  529. if time >= frames[#frames] then -- Time is after last frame.
  530. local lastVertices = frameVertices[#frames]
  531. if alpha < 1 then
  532. for i = 0, vertexCount do
  533. local vertex = vertices[i]
  534. vertices[i] = vertex + (lastVertices[i] - vertex) * alpha
  535. end
  536. else
  537. for i = 0, vertexCount do
  538. vertices[i] = lastVertices[i]
  539. end
  540. end
  541. return
  542. end
  543. -- Interpolate between the previous frame and the current frame.
  544. local frameIndex = binarySearch1(frames, time)
  545. local frameTime = frames[frameIndex]
  546. local percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime)
  547. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  548. percent = self:getCurvePercent(frameIndex - 1, percent)
  549. local prevVertices = frameVertices[frameIndex - 1]
  550. local nextVertices = frameVertices[frameIndex]
  551. if alpha < 1 then
  552. for i = 0, vertexCount do
  553. local prev = prevVertices[i]
  554. local vertices = vertices[i]
  555. vertices[i] = vertices + (prev + (nextVertices[i] - prev) * percent - vertices) * alpha
  556. end
  557. else
  558. for i = 0, vertexCount do
  559. local prev = prevVertices[i]
  560. vertices[i] = prev + (nextVertices[i] - prev) * percent
  561. end
  562. end
  563. end
  564. return self
  565. end
  566. Animation.IkConstraintTimeline = {}
  567. function Animation.IkConstraintTimeline.new ()
  568. local PREV_FRAME_TIME = -3
  569. local PREV_FRAME_MIX = -2
  570. local PREV_FRAME_BEND_DIRECTION = -1
  571. local FRAME_MIX = 1
  572. local self = Animation.CurveTimeline.new()
  573. self.frames = {} -- time, mix, bendDirection, ...
  574. self.ikConstraintIndex = -1
  575. function self:getDuration ()
  576. return self.frames[#self.frames - 2]
  577. end
  578. function self:getFrameCount ()
  579. return (#self.frames + 1) / 3
  580. end
  581. function self:setFrame (frameIndex, time, mix, bendDirection)
  582. frameIndex = frameIndex * 3
  583. self.frames[frameIndex] = time
  584. self.frames[frameIndex + 1] = mix
  585. self.frames[frameIndex + 2] = bendDirection
  586. end
  587. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  588. local frames = self.frames
  589. if time < frames[0] then return end -- Time is before first frame.
  590. local ikConstraint = skeleton.ikConstraints[self.ikConstraintIndex]
  591. if time >= frames[#frames - 2] then -- Time is after last frame.
  592. ikConstraint.mix = ikConstraint.mix + (frames[#frames - 1] - ikConstraint.mix) * alpha
  593. ikConstraint.bendDirection = frames[#frames]
  594. return
  595. end
  596. -- Interpolate between the previous frame and the current frame.
  597. local frameIndex = binarySearch(frames, time, 3);
  598. local prevFrameMix = frames[frameIndex + PREV_FRAME_MIX]
  599. local frameTime = frames[frameIndex]
  600. local percent = 1 - (time - frameTime) / (frames[frameIndex + PREV_FRAME_TIME] - frameTime)
  601. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  602. percent = self:getCurvePercent(frameIndex / 3 - 1, percent)
  603. local mix = prevFrameMix + (frames[frameIndex + FRAME_MIX] - prevFrameMix) * percent
  604. ikConstraint.mix = ikConstraint.mix + (mix - ikConstraint.mix) * alpha
  605. ikConstraint.bendDirection = frames[frameIndex + PREV_FRAME_BEND_DIRECTION]
  606. end
  607. return self
  608. end
  609. Animation.FlipXTimeline = {}
  610. function Animation.FlipXTimeline.new ()
  611. local self = {
  612. frames = {}, -- time, flip, ...
  613. boneIndex = -1
  614. }
  615. function self:getDuration ()
  616. return self.frames[#self.frames - 1]
  617. end
  618. function self:getFrameCount ()
  619. return (#self.frames + 1) / 2
  620. end
  621. function self:setFrame (frameIndex, time, flip)
  622. frameIndex = frameIndex * 2
  623. self.frames[frameIndex] = time
  624. self.frames[frameIndex + 1] = flip
  625. end
  626. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  627. local frames = self.frames
  628. if time < frames[0] then
  629. if lastTime > time then self:apply(skeleton, lastTime, 999999, nil, 0) end
  630. return
  631. elseif lastTime > time then
  632. lastTime = -1
  633. end
  634. local frameIndex
  635. if time >= frames[#frames - 1] then
  636. frameIndex = #frames - 1
  637. else
  638. frameIndex = binarySearch(frames, time, 2) - 2
  639. end
  640. if frames[frameIndex] < lastTime then return end
  641. self:setFlip(skeleton.bones[self.boneIndex], frames[frameIndex + 1])
  642. end
  643. function self:setFlip (bone, flip)
  644. bone.flipX = flip
  645. end
  646. return self
  647. end
  648. Animation.FlipYTimeline = {}
  649. function Animation.FlipYTimeline.new ()
  650. local self = Animation.FlipXTimeline.new()
  651. function self:setFlip (bone, flip)
  652. bone.flipY = flip
  653. end
  654. return self
  655. end
  656. return Animation