Animation.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  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_SEGMENTS = 10
  101. local self = {
  102. curves = {}
  103. }
  104. function self:setLinear (frameIndex)
  105. self.curves[frameIndex * 6] = LINEAR
  106. end
  107. function self:setStepped (frameIndex)
  108. self.curves[frameIndex * 6] = STEPPED
  109. end
  110. function self:setCurve (frameIndex, cx1, cy1, cx2, cy2)
  111. local subdiv_step = 1 / BEZIER_SEGMENTS
  112. local subdiv_step2 = subdiv_step * subdiv_step
  113. local subdiv_step3 = subdiv_step2 * subdiv_step
  114. local pre1 = 3 * subdiv_step
  115. local pre2 = 3 * subdiv_step2
  116. local pre4 = 6 * subdiv_step2
  117. local pre5 = 6 * subdiv_step3
  118. local tmp1x = -cx1 * 2 + cx2
  119. local tmp1y = -cy1 * 2 + cy2
  120. local tmp2x = (cx1 - cx2) * 3 + 1
  121. local tmp2y = (cy1 - cy2) * 3 + 1
  122. local i = frameIndex * 6
  123. local curves = self.curves
  124. curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3
  125. curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3
  126. curves[i + 2] = tmp1x * pre4 + tmp2x * pre5
  127. curves[i + 3] = tmp1y * pre4 + tmp2y * pre5
  128. curves[i + 4] = tmp2x * pre5
  129. curves[i + 5] = tmp2y * pre5
  130. end
  131. function self:getCurvePercent (frameIndex, percent)
  132. local curveIndex = frameIndex * 6
  133. local curves = self.curves
  134. local dfx = curves[curveIndex]
  135. if not dfx then return percent end -- linear
  136. if dfx == STEPPED then return 0 end
  137. local dfy = curves[curveIndex + 1]
  138. local ddfx = curves[curveIndex + 2]
  139. local ddfy = curves[curveIndex + 3]
  140. local dddfx = curves[curveIndex + 4]
  141. local dddfy = curves[curveIndex + 5]
  142. local x = dfx
  143. local y = dfy
  144. local i = BEZIER_SEGMENTS - 2
  145. while true do
  146. if x >= percent then
  147. local lastX = x - dfx
  148. local lastY = y - dfy
  149. return lastY + (y - lastY) * (percent - lastX) / (x - lastX)
  150. end
  151. if i == 0 then break end
  152. i = i - 1
  153. dfx = dfx + ddfx
  154. dfy = dfy + ddfy
  155. ddfx = ddfx + dddfx
  156. ddfy = ddfy + dddfy
  157. x = x + dfx
  158. y = y + dfy
  159. end
  160. return y + (1 - y) * (percent - x) / (1 - x) -- Last point is 1,1.
  161. end
  162. return self
  163. end
  164. Animation.RotateTimeline = {}
  165. function Animation.RotateTimeline.new ()
  166. local LAST_FRAME_TIME = -2
  167. local FRAME_VALUE = 1
  168. local self = Animation.CurveTimeline.new()
  169. self.frames = {}
  170. self.boneIndex = -1
  171. function self:getDuration ()
  172. return self.frames[#self.frames - 1]
  173. end
  174. function self:getFrameCount ()
  175. return (#self.frames + 1) / 2
  176. end
  177. function self:setFrame (frameIndex, time, value)
  178. frameIndex = frameIndex * 2
  179. self.frames[frameIndex] = time
  180. self.frames[frameIndex + 1] = value
  181. end
  182. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  183. local frames = self.frames
  184. if time < frames[0] then return end -- Time is before first frame.
  185. local bone = skeleton.bones[self.boneIndex]
  186. if time >= frames[#frames - 1] then -- Time is after last frame.
  187. local amount = bone.data.rotation + frames[#frames] - bone.rotation
  188. while amount > 180 do
  189. amount = amount - 360
  190. end
  191. while amount < -180 do
  192. amount = amount + 360
  193. end
  194. bone.rotation = bone.rotation + amount * alpha
  195. return
  196. end
  197. -- Interpolate between the last frame and the current frame.
  198. local frameIndex = binarySearch(frames, time, 2)
  199. local lastFrameValue = frames[frameIndex - 1]
  200. local frameTime = frames[frameIndex]
  201. local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime)
  202. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  203. percent = self:getCurvePercent(frameIndex / 2 - 1, percent)
  204. local amount = frames[frameIndex + FRAME_VALUE] - lastFrameValue
  205. while amount > 180 do
  206. amount = amount - 360
  207. end
  208. while amount < -180 do
  209. amount = amount + 360
  210. end
  211. amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation
  212. while amount > 180 do
  213. amount = amount - 360
  214. end
  215. while amount < -180 do
  216. amount = amount + 360
  217. end
  218. bone.rotation = bone.rotation + amount * alpha
  219. end
  220. return self
  221. end
  222. Animation.TranslateTimeline = {}
  223. function Animation.TranslateTimeline.new ()
  224. local LAST_FRAME_TIME = -3
  225. local FRAME_X = 1
  226. local FRAME_Y = 2
  227. local self = Animation.CurveTimeline.new()
  228. self.frames = {}
  229. self.boneIndex = -1
  230. function self:getDuration ()
  231. return self.frames[#self.frames - 2]
  232. end
  233. function self:getFrameCount ()
  234. return (#self.frames + 1) / 3
  235. end
  236. function self:setFrame (frameIndex, time, x, y)
  237. frameIndex = frameIndex * 3
  238. self.frames[frameIndex] = time
  239. self.frames[frameIndex + 1] = x
  240. self.frames[frameIndex + 2] = y
  241. end
  242. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  243. local frames = self.frames
  244. if time < frames[0] then return end -- Time is before first frame.
  245. local bone = skeleton.bones[self.boneIndex]
  246. if time >= frames[#frames - 2] then -- Time is after last frame.
  247. bone.x = bone.x + (bone.data.x + frames[#frames - 1] - bone.x) * alpha
  248. bone.y = bone.y + (bone.data.y + frames[#frames] - bone.y) * alpha
  249. return
  250. end
  251. -- Interpolate between the last frame and the current frame.
  252. local frameIndex = binarySearch(frames, time, 3)
  253. local lastFrameX = frames[frameIndex - 2]
  254. local lastFrameY = frames[frameIndex - 1]
  255. local frameTime = frames[frameIndex]
  256. local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime)
  257. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  258. percent = self:getCurvePercent(frameIndex / 3 - 1, percent)
  259. bone.x = bone.x + (bone.data.x + lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent - bone.x) * alpha
  260. bone.y = bone.y + (bone.data.y + lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent - bone.y) * alpha
  261. end
  262. return self
  263. end
  264. Animation.ScaleTimeline = {}
  265. function Animation.ScaleTimeline.new ()
  266. local LAST_FRAME_TIME = -3
  267. local FRAME_X = 1
  268. local FRAME_Y = 2
  269. local self = Animation.TranslateTimeline.new()
  270. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  271. local frames = self.frames
  272. if time < frames[0] then return end -- Time is before first frame.
  273. local bone = skeleton.bones[self.boneIndex]
  274. if time >= frames[#frames - 2] then -- Time is after last frame.
  275. bone.scaleX = bone.scaleX + (bone.data.scaleX * frames[#frames - 1] - bone.scaleX) * alpha
  276. bone.scaleY = bone.scaleY + (bone.data.scaleY * frames[#frames] - bone.scaleY) * alpha
  277. return
  278. end
  279. -- Interpolate between the last frame and the current frame.
  280. local frameIndex = binarySearch(frames, time, 3)
  281. local lastFrameX = frames[frameIndex - 2]
  282. local lastFrameY = frames[frameIndex - 1]
  283. local frameTime = frames[frameIndex]
  284. local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime)
  285. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  286. percent = self:getCurvePercent(frameIndex / 3 - 1, percent)
  287. bone.scaleX = bone.scaleX + (bone.data.scaleX * (lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent) - bone.scaleX) * alpha
  288. bone.scaleY = bone.scaleY + (bone.data.scaleY * (lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent) - bone.scaleY) * alpha
  289. end
  290. return self
  291. end
  292. Animation.ColorTimeline = {}
  293. function Animation.ColorTimeline.new ()
  294. local LAST_FRAME_TIME = -5
  295. local FRAME_R = 1
  296. local FRAME_G = 2
  297. local FRAME_B = 3
  298. local FRAME_A = 4
  299. local self = Animation.CurveTimeline.new()
  300. self.frames = {}
  301. self.slotIndex = -1
  302. function self:getDuration ()
  303. return self.frames[#self.frames - 4]
  304. end
  305. function self:getFrameCount ()
  306. return (#self.frames + 1) / 5
  307. end
  308. function self:setFrame (frameIndex, time, r, g, b, a)
  309. frameIndex = frameIndex * 5
  310. self.frames[frameIndex] = time
  311. self.frames[frameIndex + 1] = r
  312. self.frames[frameIndex + 2] = g
  313. self.frames[frameIndex + 3] = b
  314. self.frames[frameIndex + 4] = a
  315. end
  316. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  317. local frames = self.frames
  318. if time < frames[0] then return end -- Time is before first frame.
  319. local r, g, b, a
  320. if time >= frames[#frames - 4] then -- Time is after last frame.
  321. r = frames[#frames - 3]
  322. g = frames[#frames - 2]
  323. b = frames[#frames - 1]
  324. a = frames[#frames]
  325. else
  326. -- Interpolate between the last frame and the current frame.
  327. local frameIndex = binarySearch(frames, time, 5)
  328. local lastFrameR = frames[frameIndex - 4]
  329. local lastFrameG = frames[frameIndex - 3]
  330. local lastFrameB = frames[frameIndex - 2]
  331. local lastFrameA = frames[frameIndex - 1]
  332. local frameTime = frames[frameIndex]
  333. local percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime)
  334. if percent < 0 then percent = 0 elseif percent > 255 then percent = 255 end
  335. percent = self:getCurvePercent(frameIndex / 5 - 1, percent)
  336. r = lastFrameR + (frames[frameIndex + FRAME_R] - lastFrameR) * percent
  337. g = lastFrameG + (frames[frameIndex + FRAME_G] - lastFrameG) * percent
  338. b = lastFrameB + (frames[frameIndex + FRAME_B] - lastFrameB) * percent
  339. a = lastFrameA + (frames[frameIndex + FRAME_A] - lastFrameA) * percent
  340. end
  341. local slot = skeleton.slots[self.slotIndex]
  342. if alpha < 1 then
  343. 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)
  344. else
  345. slot:setColor(r, g, b, a)
  346. end
  347. end
  348. return self
  349. end
  350. Animation.AttachmentTimeline = {}
  351. function Animation.AttachmentTimeline.new ()
  352. local self = {
  353. frames = {},
  354. attachmentNames = {},
  355. slotName = nil
  356. }
  357. function self:getDuration ()
  358. return self.frames[#self.frames]
  359. end
  360. function self:getFrameCount ()
  361. return #self.frames + 1
  362. end
  363. function self:setFrame (frameIndex, time, attachmentName)
  364. self.frames[frameIndex] = time
  365. self.attachmentNames[frameIndex] = attachmentName
  366. end
  367. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  368. local frames = self.frames
  369. if time < frames[0] then return end -- Time is before first frame.
  370. local frameIndex
  371. if time >= frames[#frames] then -- Time is after last frame.
  372. frameIndex = #frames
  373. else
  374. frameIndex = binarySearch1(frames, time) - 1
  375. end
  376. local attachmentName = self.attachmentNames[frameIndex]
  377. local slot = skeleton.slotsByName[self.slotName]
  378. if attachmentName then
  379. if not slot.attachment then
  380. slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
  381. elseif slot.attachment.name ~= attachmentName then
  382. slot:setAttachment(skeleton:getAttachment(self.slotName, attachmentName))
  383. end
  384. else
  385. slot:setAttachment(nil)
  386. end
  387. end
  388. return self
  389. end
  390. Animation.EventTimeline = {}
  391. function Animation.EventTimeline.new ()
  392. local self = {
  393. frames = {},
  394. events = {}
  395. }
  396. function self:getDuration ()
  397. return self.frames[#self.frames]
  398. end
  399. function self:getFrameCount ()
  400. return #self.frames + 1
  401. end
  402. function self:setFrame (frameIndex, time, event)
  403. self.frames[frameIndex] = time
  404. self.events[frameIndex] = event
  405. end
  406. -- Fires events for frames > lastTime and <= time.
  407. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  408. if not firedEvents then return end
  409. local frames = self.frames
  410. local frameCount = #frames + 1
  411. if lastTime > time then -- Fire events after last time for looped animations.
  412. self:apply(skeleton, lastTime, 999999, firedEvents, alpha)
  413. lastTime = -1
  414. elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
  415. return
  416. end
  417. if time < frames[0] then return end -- Time is before first frame.
  418. local frameIndex
  419. if lastTime < frames[0] then
  420. frameIndex = 0
  421. else
  422. frameIndex = binarySearch1(frames, lastTime)
  423. local frame = frames[frameIndex]
  424. while frameIndex > 0 do -- Fire multiple events with the same frame.
  425. if frames[frameIndex - 1] ~= frame then break end
  426. frameIndex = frameIndex - 1
  427. end
  428. end
  429. local events = self.events
  430. while frameIndex < frameCount and time >= frames[frameIndex] do
  431. table.insert(firedEvents, events[frameIndex])
  432. frameIndex = frameIndex + 1
  433. end
  434. end
  435. return self
  436. end
  437. Animation.DrawOrderTimeline = {}
  438. function Animation.DrawOrderTimeline.new ()
  439. local self = {
  440. frames = {},
  441. drawOrders = {}
  442. }
  443. function self:getDuration ()
  444. return self.frames[#self.frames]
  445. end
  446. function self:getFrameCount ()
  447. return #self.frames + 1
  448. end
  449. function self:setFrame (frameIndex, time, drawOrder)
  450. self.frames[frameIndex] = time
  451. self.drawOrders[frameIndex] = drawOrder
  452. end
  453. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  454. local frames = self.frames
  455. if time < frames[0] then return end -- Time is before first frame.
  456. local frameIndex
  457. if time >= frames[#frames] then -- Time is after last frame.
  458. frameIndex = #frames
  459. else
  460. frameIndex = binarySearch1(frames, time) - 1
  461. end
  462. local drawOrder = skeleton.drawOrder
  463. local slots = skeleton.slots
  464. local drawOrderToSetupIndex = self.drawOrders[frameIndex]
  465. if not drawOrderToSetupIndex then
  466. for i,slot in ipairs(slots) do
  467. drawOrder[i] = slots[i]
  468. end
  469. else
  470. for i,setupIndex in ipairs(drawOrderToSetupIndex) do
  471. drawOrder[i] = skeleton.slots[setupIndex]
  472. end
  473. end
  474. end
  475. return self
  476. end
  477. Animation.FfdTimeline = {}
  478. function Animation.FfdTimeline.new ()
  479. local self = Animation.CurveTimeline.new()
  480. self.frames = {}
  481. self.frameVertices = {}
  482. self.slotIndex = -1
  483. function self:getDuration ()
  484. return self.frames[#self.frames]
  485. end
  486. function self:getFrameCount ()
  487. return #self.frames + 1
  488. end
  489. function self:setFrame (frameIndex, time, vertices)
  490. self.frames[frameIndex] = time
  491. self.frameVertices[frameIndex] = vertices
  492. end
  493. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  494. local slot = skeleton.slots[self.slotIndex]
  495. if slot.attachment ~= attachment then return end
  496. local frames = self.frames
  497. if time < frames[0] then -- Time is before first frame.
  498. slot.attachmentVerticesCount = 0
  499. return
  500. end
  501. local frameVertices = self.frameVertices
  502. local vertexCount = #frameVertices[0]
  503. local vertices = slot.attachmentVertices
  504. if #vertices < vertexCount then
  505. vertices = {}
  506. vertices[vertexCount] = 0
  507. slot.attachmentVertices = vertices
  508. elseif #vertices < vertexCount then
  509. alpha = 1 -- Don't mix from uninitialized slot vertices.
  510. end
  511. slot.attachmentVerticesCount = vertexCount
  512. if time >= frames[#frames] then -- Time is after last frame.
  513. local lastVertices = frameVertices[#frames.Length]
  514. if alpha < 1 then
  515. for i = 0, vertexCount do
  516. local vertex = vertices[i]
  517. vertices[i] = vertex + (lastVertices[i] - vertex) * alpha
  518. end
  519. else
  520. for i = 0, vertexCount do
  521. vertices[i] = lastVertices[i]
  522. end
  523. end
  524. return
  525. end
  526. -- Interpolate between the previous frame and the current frame.
  527. local frameIndex = binarySearch1(frames, time)
  528. local frameTime = frames[frameIndex]
  529. local percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime)
  530. if percent < 0 then percent = 0 elseif percent > 1 then percent = 1 end
  531. percent = self:getCurvePercent(frameIndex - 1, percent)
  532. local prevVertices = frameVertices[frameIndex - 1]
  533. local nextVertices = frameVertices[frameIndex]
  534. if alpha < 1 then
  535. for i = 0, vertexCount do
  536. local prev = prevVertices[i]
  537. local vertices = vertices[i]
  538. vertices[i] = vertices + (prev + (nextVertices[i] - prev) * percent - vertices) * alpha
  539. end
  540. else
  541. for i = 0, vertexCount do
  542. local prev = prevVertices[i]
  543. vertices[i] = prev + (nextVertices[i] - prev) * percent
  544. end
  545. end
  546. end
  547. return self
  548. end
  549. Animation.FlipXTimeline = {}
  550. function Animation.FlipXTimeline.new ()
  551. local self = {
  552. frames = {}, -- time, flip, ...
  553. boneIndex = -1
  554. }
  555. function self:getDuration ()
  556. return self.frames[#self.frames - 1]
  557. end
  558. function self:getFrameCount ()
  559. return (#self.frames + 1) / 2
  560. end
  561. function self:setFrame (frameIndex, time, flip)
  562. frameIndex = frameIndex * 2
  563. self.frames[frameIndex] = time
  564. self.frames[frameIndex + 1] = flip
  565. end
  566. function self:apply (skeleton, lastTime, time, firedEvents, alpha)
  567. local frames = self.frames
  568. if time < frames[0] then
  569. if lastTime > time then self:apply(skeleton, lastTime, 999999, null, 0) end
  570. return
  571. elseif lastTime > time then
  572. lastTime = -1
  573. end
  574. local frameIndex
  575. if time >= frames[#frames - 1] then
  576. frameIndex = #frames - 1
  577. else
  578. frameIndex = binarySearch(frames, time, 2) - 2
  579. end
  580. if frames[frameIndex] < lastTime then return end
  581. self:setFlip(skeleton.bones[self.boneIndex], frames[frameIndex + 1])
  582. end
  583. function self:setFlip (bone, flip)
  584. bone.flipX = flip
  585. end
  586. return self
  587. end
  588. Animation.FlipYTimeline = {}
  589. function Animation.FlipYTimeline.new ()
  590. local self = Animation.FlipXTimeline.new()
  591. function self:setFlip (bone, flip)
  592. bone.flipY = flip
  593. end
  594. return self
  595. end
  596. return Animation