Animation.lua 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  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 Owelp,F
  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. -- FIXME
  31. -- All the indexing in this file is zero based. We use zlen()
  32. -- instead of the # operator. Initialization of number arrays
  33. -- is performed via utils.newNumberArrayZero. This needs
  34. -- to be rewritten using one-based indexing for better performance
  35. local utils = require "spine-lua.utils"
  36. local AttachmentType = require "spine-lua.attachments.AttachmentType"
  37. local math_floor = math.floor
  38. local math_abs = math.abs
  39. local math_signum = utils.signum
  40. local function zlen(array)
  41. return #array + 1
  42. end
  43. local Animation = {}
  44. function Animation.new (name, timelines, duration)
  45. if not timelines then error("timelines cannot be nil", 2) end
  46. local self = {
  47. name = name,
  48. timelines = timelines,
  49. duration = duration
  50. }
  51. function self:apply (skeleton, lastTime, time, loop, events, alpha, pose, direction)
  52. if not skeleton then error("skeleton cannot be nil.", 2) end
  53. if loop and duration > 0 then
  54. time = time % self.duration
  55. if lastTime > 0 then lastTime = lastTime % self.duration end
  56. end
  57. for i,timeline in ipairs(self.timelines) do
  58. timeline:apply(skeleton, lastTime, time, events, alpha, pose, direction)
  59. end
  60. end
  61. return self
  62. end
  63. local function binarySearch (values, target, step)
  64. local low = 0
  65. local high = math.floor(zlen(values) / step - 2)
  66. if high == 0 then return step end
  67. local current = math.floor(high / 2)
  68. while true do
  69. if values[(current + 1) * step] <= target then
  70. low = current + 1
  71. else
  72. high = current
  73. end
  74. if low == high then return (low + 1) * step end
  75. current = math.floor((low + high) / 2)
  76. end
  77. end
  78. Animation.binarySearch = binarySearch
  79. local function binarySearch1 (values, target)
  80. local low = 0
  81. local high = math.floor(zlen(values) - 2)
  82. if high == 0 then return 1 end
  83. local current = math.floor(high / 2)
  84. while true do
  85. if values[current + 1] <= target then
  86. low = current + 1
  87. else
  88. high = current
  89. end
  90. if low == high then return low + 1 end
  91. current = math.floor((low + high) / 2)
  92. end
  93. end
  94. local function linearSearch (values, target, step)
  95. local i = 0
  96. local last = zlen(values) - step
  97. while i <= last do
  98. if (values[i] > target) then return i end
  99. i = i + step
  100. end
  101. return -1
  102. end
  103. Animation.MixPose = {
  104. setup = 0,
  105. current = 1,
  106. currentLayered = 2
  107. }
  108. local MixPose = Animation.MixPose
  109. Animation.MixDirection = {
  110. _in = 0, out = 1
  111. }
  112. local MixDirection = Animation.MixDirection
  113. Animation.TimelineType = {
  114. rotate = 0, translate = 1, scale = 2, shear = 3,
  115. attachment = 4, color = 5, deform = 6,
  116. event = 7, drawOrder = 8,
  117. ikConstraint = 9, transformConstraint = 10,
  118. pathConstraintPosition = 11, pathConstraintSpacing = 12, pathConstraintMix = 13,
  119. twoColor = 14
  120. }
  121. local TimelineType = Animation.TimelineType
  122. local SHL_24 = 16777216
  123. local SHL_27 = 134217728
  124. Animation.CurveTimeline = {}
  125. function Animation.CurveTimeline.new (frameCount)
  126. local LINEAR = 0
  127. local STEPPED = 1
  128. local BEZIER = 2
  129. local BEZIER_SIZE = 10 * 2 - 1
  130. local self = {
  131. curves = utils.newNumberArrayZero((frameCount - 1) * BEZIER_SIZE) -- type, x, y, ...
  132. }
  133. function self:getFrameCount ()
  134. return math.floor(zlen(self.curves) / BEZIER_SIZE) + 1
  135. end
  136. function self:setStepped (frameIndex)
  137. self.curves[frameIndex * BEZIER_SIZE] = STEPPED
  138. end
  139. function self:getCurveType (frameIndex)
  140. local index = frameIndex * BEZIER_SIZE
  141. if index == zlen(self.curves) then return LINEAR end
  142. local type = self.curves[index]
  143. if type == LINEAR then return LINEAR end
  144. if type == STEPPED then return STEPPED end
  145. return BEZIER
  146. end
  147. function self:setCurve (frameIndex, cx1, cy1, cx2, cy2)
  148. local tmpx = (-cx1 * 2 + cx2) * 0.03
  149. local tmpy = (-cy1 * 2 + cy2) * 0.03
  150. local dddfx = ((cx1 - cx2) * 3 + 1) * 0.006
  151. local dddfy = ((cy1 - cy2) * 3 + 1) * 0.006
  152. local ddfx = tmpx * 2 + dddfx
  153. local ddfy = tmpy * 2 + dddfy
  154. local dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667
  155. local dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667
  156. local i = frameIndex * BEZIER_SIZE
  157. local curves = self.curves
  158. curves[i] = BEZIER
  159. i = i + 1
  160. local x = dfx
  161. local y = dfy
  162. local n = i + BEZIER_SIZE - 1
  163. while i < n do
  164. curves[i] = x
  165. curves[i + 1] = y
  166. dfx = dfx + ddfx
  167. dfy = dfy + ddfy
  168. ddfx = ddfx + dddfx
  169. ddfy = ddfy + dddfy
  170. x = x + dfx
  171. y = y + dfy
  172. i = i + 2
  173. end
  174. end
  175. function self:getCurvePercent (frameIndex, percent)
  176. percent = utils.clamp(percent, 0, 1)
  177. local curves = self.curves
  178. local i = frameIndex * BEZIER_SIZE
  179. local type = curves[i]
  180. if type == LINEAR then return percent end
  181. if type == STEPPED then return 0 end
  182. i = i + 1
  183. local x
  184. local n = i + BEZIER_SIZE - 1
  185. local start = i
  186. while i < n do
  187. x = curves[i]
  188. if x >= percent then
  189. local prevX, prevY
  190. if i == start then
  191. prevX = 0
  192. prevY = 0
  193. else
  194. prevX = curves[i - 2]
  195. prevY = curves[i - 1]
  196. end
  197. return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX)
  198. end
  199. i = i + 2
  200. end
  201. local y = curves[i - 1]
  202. return y + (1 - y) * (percent - x) / (1 - x) -- Last point is 1,1.
  203. end
  204. return self
  205. end
  206. Animation.RotateTimeline = {}
  207. Animation.RotateTimeline.ENTRIES = 2
  208. Animation.RotateTimeline.PREV_TIME = -2
  209. Animation.RotateTimeline.PREV_ROTATION = -1
  210. Animation.RotateTimeline.ROTATION = 1
  211. function Animation.RotateTimeline.new (frameCount)
  212. local ENTRIES = Animation.RotateTimeline.ENTRIES
  213. local PREV_TIME = Animation.RotateTimeline.PREV_TIME
  214. local PREV_ROTATION = Animation.RotateTimeline.PREV_ROTATION
  215. local ROTATION = Animation.RotateTimeline.ROTATION
  216. local self = Animation.CurveTimeline.new(frameCount)
  217. self.boneIndex = -1
  218. self.frames = utils.newNumberArrayZero(frameCount * 2)
  219. self.type = TimelineType.rotate
  220. function self:getPropertyId ()
  221. return TimelineType.rotate * SHL_24 + self.boneIndex
  222. end
  223. function self:setFrame (frameIndex, time, degrees)
  224. frameIndex = frameIndex * 2
  225. self.frames[frameIndex] = time
  226. self.frames[frameIndex + ROTATION] = degrees
  227. end
  228. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  229. local frames = self.frames
  230. local bone = skeleton.bones[self.boneIndex]
  231. if time < frames[0] then
  232. if pose == MixPose.setup then
  233. bone.rotation = bone.data.rotation
  234. elseif pose == MixPose.current then
  235. local r = bone.data.rotation - bone.rotation
  236. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
  237. bone.rotation = bone.rotation + r * alpha
  238. end
  239. return
  240. end
  241. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  242. if pose == MixPose.setup then
  243. bone.rotation = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] * alpha
  244. else
  245. local r = bone.data.rotation + frames[zlen(frames) + PREV_ROTATION] - bone.rotation
  246. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360 -- Wrap within -180 and 180.
  247. bone.rotation = bone.rotation + r * alpha;
  248. end
  249. return;
  250. end
  251. -- Interpolate between the last frame and the current frame.
  252. local frame = binarySearch(frames, time, ENTRIES)
  253. local prevRotation = frames[frame + PREV_ROTATION]
  254. local frameTime = frames[frame]
  255. local percent = self:getCurvePercent((math.floor(frame / 2)) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  256. local r = frames[frame + ROTATION] - prevRotation
  257. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
  258. r = prevRotation + r * percent
  259. if pose == MixPose.setup then
  260. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
  261. bone.rotation = bone.data.rotation + r * alpha
  262. else
  263. r = bone.data.rotation + r - bone.rotation;
  264. r = r - (16384 - math_floor(16384.499999999996 - r / 360)) * 360
  265. bone.rotation = bone.rotation + r * alpha
  266. end
  267. end
  268. return self
  269. end
  270. Animation.TranslateTimeline = {}
  271. Animation.TranslateTimeline.ENTRIES = 3
  272. function Animation.TranslateTimeline.new (frameCount)
  273. local ENTRIES = Animation.TranslateTimeline.ENTRIES
  274. local PREV_TIME = -3
  275. local PREV_X = -2
  276. local PREV_Y = -1
  277. local X = 1
  278. local Y = 2
  279. local self = Animation.CurveTimeline.new(frameCount)
  280. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  281. self.boneIndex = -1
  282. self.type = TimelineType.translate
  283. function self:getPropertyId ()
  284. return TimelineType.translate * SHL_24 + self.boneIndex
  285. end
  286. function self:setFrame (frameIndex, time, x, y)
  287. frameIndex = frameIndex * ENTRIES
  288. self.frames[frameIndex] = time
  289. self.frames[frameIndex + X] = x
  290. self.frames[frameIndex + Y] = y
  291. end
  292. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  293. local frames = self.frames
  294. local bone = skeleton.bones[self.boneIndex]
  295. if time < frames[0] then
  296. if pose == MixPose.setup then
  297. bone.x = bone.data.x
  298. bone.y = bone.data.y
  299. elseif pose == MixPose.current then
  300. bone.x = bone.x + (bone.data.x - bone.x) * alpha
  301. bone.y = bone.y + (bone.data.y - bone.y) * alpha
  302. end
  303. return
  304. end
  305. local x = 0
  306. local y = 0
  307. if time >= frames[zlen(frames) - ENTRIES] then -- // Time is after last frame.
  308. x = frames[zlen(frames) + PREV_X];
  309. y = frames[zlen(frames) + PREV_Y];
  310. else
  311. -- Interpolate between the previous frame and the current frame.
  312. local frame = binarySearch(frames, time, ENTRIES)
  313. x = frames[frame + PREV_X]
  314. y = frames[frame + PREV_Y]
  315. local frameTime = frames[frame]
  316. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  317. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
  318. x = x + (frames[frame + X] - x) * percent
  319. y = y + (frames[frame + Y] - y) * percent
  320. end
  321. if pose == MixPose.setup then
  322. bone.x = bone.data.x + x * alpha
  323. bone.y = bone.data.y + y * alpha
  324. else
  325. bone.x = bone.x + (bone.data.x + x - bone.x) * alpha
  326. bone.y = bone.y + (bone.data.y + y - bone.y) * alpha
  327. end
  328. end
  329. return self
  330. end
  331. Animation.ScaleTimeline = {}
  332. Animation.ScaleTimeline.ENTRIES = Animation.TranslateTimeline.ENTRIES
  333. function Animation.ScaleTimeline.new (frameCount)
  334. local ENTRIES = Animation.ScaleTimeline.ENTRIES
  335. local PREV_TIME = -3
  336. local PREV_X = -2
  337. local PREV_Y = -1
  338. local X = 1
  339. local Y = 2
  340. local self = Animation.TranslateTimeline.new(frameCount)
  341. self.type = TimelineType.scale
  342. function self:getPropertyId ()
  343. return TimelineType.scale * SHL_24 + self.boneIndex
  344. end
  345. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  346. local frames = self.frames
  347. local bone = skeleton.bones[self.boneIndex]
  348. if time < frames[0] then
  349. if pose == MixPose.setup then
  350. bone.scaleX = bone.data.scaleX
  351. bone.scaleY = bone.data.scaleY
  352. elseif pose == MixPose.current then
  353. bone.scaleX = bone.scaleX + (bone.data.scaleX - bone.scaleX) * alpha
  354. bone.scaleY = bone.scaleY + (bone.data.scaleY - bone.scaleY) * alpha
  355. end
  356. return
  357. end
  358. local x = 0
  359. local y = 0
  360. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  361. x = frames[zlen(frames) + PREV_X] * bone.data.scaleX
  362. y = frames[zlen(frames) + PREV_Y] * bone.data.scaleY
  363. else
  364. -- Interpolate between the previous frame and the current frame.
  365. local frame = binarySearch(frames, time, ENTRIES)
  366. x = frames[frame + PREV_X]
  367. y = frames[frame + PREV_Y]
  368. local frameTime = frames[frame]
  369. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  370. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  371. x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX
  372. y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY
  373. end
  374. if alpha == 1 then
  375. bone.scaleX = x
  376. bone.scaleY = y
  377. else
  378. local bx = 0
  379. local by = 0
  380. if pose == MixPose.setup then
  381. bx = bone.data.scaleX
  382. by = bone.data.scaleY
  383. else
  384. bx = bone.scaleX
  385. by = bone.scaleY
  386. end
  387. -- Mixing out uses sign of setup or current pose, else use sign of key.
  388. if direction == MixDirection.out then
  389. x = math_abs(x) * math_signum(bx)
  390. y = math_abs(y) * math_signum(by)
  391. else
  392. bx = math_abs(bx) * math_signum(x)
  393. by = math_abs(by) * math_signum(y)
  394. end
  395. bone.scaleX = bx + (x - bx) * alpha
  396. bone.scaleY = by + (y - by) * alpha
  397. end
  398. end
  399. return self
  400. end
  401. Animation.ShearTimeline = {}
  402. Animation.ShearTimeline.ENTRIES = Animation.TranslateTimeline.ENTRIES
  403. function Animation.ShearTimeline.new (frameCount)
  404. local ENTRIES = Animation.ShearTimeline.ENTRIES
  405. local PREV_TIME = -3
  406. local PREV_X = -2
  407. local PREV_Y = -1
  408. local X = 1
  409. local Y = 2
  410. local self = Animation.TranslateTimeline.new(frameCount)
  411. self.type = TimelineType.shear
  412. function self:getPropertyId ()
  413. return TimelineType.shear * SHL_24 + self.boneIndex
  414. end
  415. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  416. local frames = self.frames
  417. local bone = skeleton.bones[self.boneIndex]
  418. if time < frames[0] then
  419. if pose == MixPose.setup then
  420. bone.shearX = bone.data.shearX
  421. bone.shearY = bone.data.shearY
  422. elseif pose == MixPose.current then
  423. bone.shearX = bone.shearX + (bone.data.shearX - bone.shearX) * alpha
  424. bone.shearY = bone.shearX + (bone.data.shearY - bone.shearY) * alpha
  425. end
  426. return
  427. end
  428. local x = 0
  429. local y = 0
  430. if time >= frames[zlen(frames) - ENTRIES] then -- // Time is after last frame.
  431. x = frames[zlen(frames) + PREV_X]
  432. y = frames[zlen(frames) + PREV_Y]
  433. else
  434. -- Interpolate between the previous frame and the current frame.
  435. local frame = binarySearch(frames, time, ENTRIES)
  436. x = frames[frame + PREV_X]
  437. y = frames[frame + PREV_Y]
  438. local frameTime = frames[frame]
  439. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  440. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  441. x = x + (frames[frame + X] - x) * percent
  442. y = y + (frames[frame + Y] - y) * percent
  443. end
  444. if pose == MixPose.setup then
  445. bone.shearX = bone.data.shearX + x * alpha
  446. bone.shearY = bone.data.shearY + y * alpha
  447. else
  448. bone.shearX = bone.shearX + (bone.data.shearX + x - bone.shearX) * alpha
  449. bone.shearY = bone.shearY + (bone.data.shearY + y - bone.shearY) * alpha
  450. end
  451. end
  452. return self
  453. end
  454. Animation.ColorTimeline = {}
  455. Animation.ColorTimeline.ENTRIES = 5
  456. function Animation.ColorTimeline.new (frameCount)
  457. local ENTRIES = Animation.ColorTimeline.ENTRIES
  458. local PREV_TIME = -5
  459. local PREV_R = -4
  460. local PREV_G = -3
  461. local PREV_B = -2
  462. local PREV_A = -1
  463. local R = 1
  464. local G = 2
  465. local B = 3
  466. local A = 4
  467. local self = Animation.CurveTimeline.new(frameCount)
  468. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  469. self.slotIndex = -1
  470. self.type = TimelineType.color
  471. function self:getPropertyId ()
  472. return TimelineType.color * SHL_24 + self.slotIndex
  473. end
  474. function self:setFrame (frameIndex, time, r, g, b, a)
  475. frameIndex = frameIndex * ENTRIES
  476. self.frames[frameIndex] = time
  477. self.frames[frameIndex + R] = r
  478. self.frames[frameIndex + G] = g
  479. self.frames[frameIndex + B] = b
  480. self.frames[frameIndex + A] = a
  481. end
  482. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  483. local frames = self.frames
  484. local slot = skeleton.slots[self.slotIndex]
  485. if time < frames[0] then
  486. if pose == MixPose.setup then
  487. slot.color:setFrom(slot.data.color)
  488. elseif pose == MixPose.current then
  489. local color = slot.color
  490. local setup = slot.data.color
  491. color:add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
  492. (setup.a - color.a) * alpha)
  493. end
  494. return
  495. end
  496. local r, g, b, a
  497. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  498. local i = zlen(frames)
  499. r = frames[i + PREV_R]
  500. g = frames[i + PREV_G]
  501. b = frames[i + PREV_B]
  502. a = frames[i + PREV_A]
  503. else
  504. -- Interpolate between the last frame and the current frame.
  505. local frame = binarySearch(frames, time, ENTRIES)
  506. r = frames[frame + PREV_R]
  507. g = frames[frame + PREV_G]
  508. b = frames[frame + PREV_B]
  509. a = frames[frame + PREV_A]
  510. local frameTime = frames[frame]
  511. local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
  512. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  513. r = r + (frames[frame + R] - r) * percent
  514. g = g + (frames[frame + G] - g) * percent
  515. b = b + (frames[frame + B] - b) * percent
  516. a = a + (frames[frame + A] - a) * percent
  517. end
  518. if alpha == 1 then
  519. slot.color:set(r, g, b, a)
  520. else
  521. local color = slot.color
  522. if pose == MixPose.setup then color:setFrom(slot.data.color) end
  523. color:add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha)
  524. end
  525. end
  526. return self
  527. end
  528. Animation.TwoColorTimeline = {}
  529. Animation.TwoColorTimeline.ENTRIES = 8
  530. function Animation.TwoColorTimeline.new (frameCount)
  531. local ENTRIES = Animation.TwoColorTimeline.ENTRIES
  532. local PREV_TIME = -8
  533. local PREV_R = -7
  534. local PREV_G = -6
  535. local PREV_B = -5
  536. local PREV_A = -4
  537. local PREV_R2 = -3
  538. local PREV_G2 = -2
  539. local PREV_B2 = -1
  540. local R = 1
  541. local G = 2
  542. local B = 3
  543. local A = 4
  544. local R2 = 5
  545. local G2 = 6
  546. local B2 = 7
  547. local self = Animation.CurveTimeline.new(frameCount)
  548. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  549. self.slotIndex = -1
  550. self.type = TimelineType.twoColor
  551. function self:getPropertyId ()
  552. return TimelineType.twoColor * SHL_24 + self.slotIndex
  553. end
  554. function self:setFrame (frameIndex, time, r, g, b, a, r2, g2, b2)
  555. frameIndex = frameIndex * ENTRIES
  556. self.frames[frameIndex] = time
  557. self.frames[frameIndex + R] = r
  558. self.frames[frameIndex + G] = g
  559. self.frames[frameIndex + B] = b
  560. self.frames[frameIndex + A] = a
  561. self.frames[frameIndex + R2] = r2
  562. self.frames[frameIndex + G2] = g2
  563. self.frames[frameIndex + B2] = b2
  564. end
  565. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  566. local frames = self.frames
  567. local slot = skeleton.slots[self.slotIndex]
  568. if time < frames[0] then
  569. if pose == MixPose.setup then
  570. slot.color:setFrom(slot.data.color)
  571. slot.darkColor:setFrom(slot.data.darkColor)
  572. elseif pose == MixPose.current then
  573. local light = slot.color
  574. local dark = slot.darkColor
  575. local setupLight = slot.data.color
  576. local setupDark = slot.data.darkColor
  577. light:add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,
  578. (setupLight.a - light.a) * alpha)
  579. dark:add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0)
  580. end
  581. return
  582. end
  583. local r, g, b, a, r2, g2, b2
  584. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  585. local i = zlen(frames)
  586. r = frames[i + PREV_R]
  587. g = frames[i + PREV_G]
  588. b = frames[i + PREV_B]
  589. a = frames[i + PREV_A]
  590. r2 = frames[i + PREV_R2]
  591. g2 = frames[i + PREV_G2]
  592. b2 = frames[i + PREV_B2]
  593. else
  594. -- Interpolate between the last frame and the current frame.
  595. local frame = binarySearch(frames, time, ENTRIES)
  596. r = frames[frame + PREV_R]
  597. g = frames[frame + PREV_G]
  598. b = frames[frame + PREV_B]
  599. a = frames[frame + PREV_A]
  600. r2 = frames[frame + PREV_R2]
  601. g2 = frames[frame + PREV_G2]
  602. b2 = frames[frame + PREV_B2]
  603. local frameTime = frames[frame]
  604. local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
  605. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  606. r = r + (frames[frame + R] - r) * percent
  607. g = g + (frames[frame + G] - g) * percent
  608. b = b + (frames[frame + B] - b) * percent
  609. a = a + (frames[frame + A] - a) * percent
  610. r2 = r2 + (frames[frame + R2] - r2) * percent
  611. g2 = g2 + (frames[frame + G2] - g2) * percent
  612. b2 = b2 + (frames[frame + B2] - b2) * percent
  613. end
  614. if alpha == 1 then
  615. slot.color:set(r, g, b, a)
  616. slot.darkColor:set(r2, g2, b2, 1)
  617. else
  618. local light = slot.color
  619. local dark = slot.darkColor
  620. if pose == MixPose.setup then
  621. light:setFrom(slot.data.color)
  622. dark:setFrom(slot.data.darkColor)
  623. end
  624. light:add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha)
  625. dark:add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0)
  626. end
  627. end
  628. return self
  629. end
  630. Animation.AttachmentTimeline = {}
  631. function Animation.AttachmentTimeline.new (frameCount)
  632. local self = {
  633. frames = utils.newNumberArrayZero(frameCount), -- time, ...
  634. attachmentNames = {},
  635. slotIndex = -1,
  636. type = TimelineType.attachment
  637. }
  638. function self:getFrameCount ()
  639. return zlen(self.frames)
  640. end
  641. function self:setFrame (frameIndex, time, attachmentName)
  642. self.frames[frameIndex] = time
  643. self.attachmentNames[frameIndex] = attachmentName
  644. end
  645. function self:getPropertyId ()
  646. return TimelineType.attachment * SHL_24 + self.slotIndex
  647. end
  648. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  649. local slot = skeleton.slots[self.slotIndex]
  650. local attachmentName
  651. if direction == MixDirection.out and pose == MixPose.setup then
  652. attachmentName = slot.data.attachmentName
  653. if not attachmentName then
  654. slot:setAttachment(nil)
  655. else
  656. slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
  657. end
  658. return;
  659. end
  660. local frames = self.frames
  661. if time < frames[0] then
  662. if pose == MixPose.setup then
  663. attachmentName = slot.data.attachmentName
  664. if not attachmentName then
  665. slot:setAttachment(nil)
  666. else
  667. slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
  668. end
  669. end
  670. return
  671. end
  672. local frameIndex = 0
  673. if time >= frames[zlen(frames) - 1] then
  674. frameIndex = zlen(frames) - 1
  675. else
  676. frameIndex = binarySearch(frames, time, 1) - 1
  677. end
  678. attachmentName = self.attachmentNames[frameIndex]
  679. if not attachmentName then
  680. slot:setAttachment(nil)
  681. else
  682. slot:setAttachment(skeleton:getAttachmentByIndex(self.slotIndex, attachmentName))
  683. end
  684. end
  685. return self
  686. end
  687. Animation.DeformTimeline = {}
  688. function Animation.DeformTimeline.new (frameCount)
  689. local self = Animation.CurveTimeline.new(frameCount)
  690. self.frames = utils.newNumberArrayZero(frameCount)
  691. self.frameVertices = utils.newNumberArrayZero(frameCount)
  692. self.slotIndex = -1
  693. self.attachment = nil
  694. self.type = TimelineType.deform
  695. function self:getPropertyId ()
  696. return TimelineType.deform * SHL_27 + self.attachment.id + self.slotIndex
  697. end
  698. function self:setFrame (frameIndex, time, vertices)
  699. self.frames[frameIndex] = time
  700. self.frameVertices[frameIndex] = vertices
  701. end
  702. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  703. local slot = skeleton.slots[self.slotIndex]
  704. local slotAttachment = slot.attachment
  705. if not slotAttachment then return end
  706. if not (slotAttachment.type == AttachmentType.mesh or slotAttachment.type == AttachmentType.linkedmesh or slotAttachment.type == AttachmentType.path or slotAttachment.type == AttachmentType.boundingbox) then return end
  707. if not slotAttachment:applyDeform(self.attachment) then return end
  708. local frames = self.frames
  709. local verticesArray = slot.attachmentVertices
  710. local frameVertices = self.frameVertices
  711. local vertexCount = #(frameVertices[0])
  712. if (#verticesArray ~= vertexCount and not setupPose) then alpha = 1 end -- Don't mix from uninitialized slot vertices.
  713. local vertices = utils.setArraySize(verticesArray, vertexCount)
  714. if time < frames[0] then
  715. if pose == MixPose.setup then
  716. verticesArray = {}
  717. slot.attachmentVertices = verticesArray
  718. elseif pose == MixPose.current then
  719. alpha = 1 - alpha
  720. local i = 1
  721. while i <= vertexCount do
  722. vertices[i] = vertices[i] * alpha
  723. i = i + 1
  724. end
  725. end
  726. return
  727. end
  728. if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
  729. local lastVertices = frameVertices[zlen(frames) - 1]
  730. if alpha == 1 then
  731. -- Vertex positions or deform offsets, no alpha.
  732. local i = 1
  733. while i <= vertexCount do
  734. vertices[i] = lastVertices[i]
  735. i = i + 1
  736. end
  737. elseif pose == MixPose.setup then
  738. local vertexAttachment = slotAttachment
  739. if vertexAttachment.bones == nil then
  740. -- Unweighted vertex positions, with alpha.
  741. local setupVertices = vertexAttachment.vertices
  742. local i = 1
  743. while i <= vertexCount do
  744. local setup = setupVertices[i]
  745. vertices[i] = setup + (lastVertices[i] - setup) * alpha
  746. i = i + 1
  747. end
  748. else
  749. -- Weighted deform offsets, with alpha.
  750. local i = 1
  751. while i <= vertexCount do
  752. vertices[i] = lastVertices[i] * alpha
  753. i = i + 1
  754. end
  755. end
  756. else
  757. -- Vertex positions or deform offsets, with alpha.
  758. local i = 1
  759. while i <= vertexCount do
  760. vertices[i] = vertices[i] + (lastVertices[i] - vertices[i]) * alpha
  761. i = i + 1
  762. end
  763. end
  764. return;
  765. end
  766. -- Interpolate between the previous frame and the current frame.
  767. local frame = binarySearch(frames, time, 1)
  768. local prevVertices = frameVertices[frame - 1]
  769. local nextVertices = frameVertices[frame]
  770. local frameTime = frames[frame]
  771. local percent = self:getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime))
  772. if alpha == 1 then
  773. -- Vertex positions or deform offsets, no alpha.
  774. local i = 1
  775. while i <= vertexCount do
  776. local prev = prevVertices[i]
  777. vertices[i] = prev + (nextVertices[i] - prev) * percent
  778. i = i + 1
  779. end
  780. elseif pose == MixPose.setup then
  781. local vertexAttachment = slotAttachment
  782. if vertexAttachment.bones == nil then
  783. -- Unweighted vertex positions, with alpha.
  784. local setupVertices = vertexAttachment.vertices
  785. local i = 1
  786. while i <= vertexCount do
  787. local prev = prevVertices[i]
  788. local setup = setupVertices[i]
  789. vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha
  790. i = i + 1
  791. end
  792. else
  793. -- Weighted deform offsets, with alpha.
  794. local i = 1
  795. while i <= vertexCount do
  796. local prev = prevVertices[i]
  797. vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha
  798. i = i + 1
  799. end
  800. end
  801. else
  802. -- Vertex positions or deform offsets, with alpha.
  803. local i = 1
  804. while i <= vertexCount do
  805. local prev = prevVertices[i]
  806. vertices[i] = vertices[i] + (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha
  807. i = i + 1
  808. end
  809. end
  810. end
  811. return self
  812. end
  813. Animation.EventTimeline = {}
  814. function Animation.EventTimeline.new (frameCount)
  815. local self = {
  816. frames = utils.newNumberArrayZero(frameCount),
  817. events = {},
  818. type = TimelineType.event
  819. }
  820. function self:getPropertyId ()
  821. return TimelineType.event * SHL_24
  822. end
  823. function self:getFrameCount ()
  824. return zlen(self.frames)
  825. end
  826. function self:setFrame (frameIndex, event)
  827. self.frames[frameIndex] = event.time
  828. self.events[frameIndex] = event
  829. end
  830. -- Fires events for frames > lastTime and <= time.
  831. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  832. if not firedEvents then return end
  833. local frames = self.frames
  834. local frameCount = zlen(frames)
  835. if lastTime > time then -- Fire events after last time for looped animations.
  836. self:apply(skeleton, lastTime, 999999, firedEvents, alpha, pose, direction)
  837. lastTime = -1
  838. elseif lastTime >= frames[frameCount - 1] then -- Last time is after last frame.
  839. return
  840. end
  841. if time < frames[0] then return end -- Time is before first frame.
  842. local frame
  843. if lastTime < frames[0] then
  844. frame = 0
  845. else
  846. frame = binarySearch1(frames, lastTime)
  847. local frame = frames[frame]
  848. while frame > 0 do -- Fire multiple events with the same frame.
  849. if frames[frame - 1] ~= frame then break end
  850. frame = frame - 1
  851. end
  852. end
  853. local events = self.events
  854. while frame < frameCount and time >= frames[frame] do
  855. table.insert(firedEvents, events[frame])
  856. frame = frame + 1
  857. end
  858. end
  859. return self
  860. end
  861. Animation.DrawOrderTimeline = {}
  862. function Animation.DrawOrderTimeline.new (frameCount)
  863. local self = {
  864. frames = utils.newNumberArrayZero(frameCount),
  865. drawOrders = {},
  866. type = TimelineType.drawOrder
  867. }
  868. function self:getPropertyId ()
  869. return TimelineType.drawOrder * SHL_24
  870. end
  871. function self:getFrameCount ()
  872. return zlen(self.frames)
  873. end
  874. function self:setFrame (frameIndex, time, drawOrder)
  875. self.frames[frameIndex] = time
  876. self.drawOrders[frameIndex] = drawOrder
  877. end
  878. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  879. local drawOrder = skeleton.drawOrder
  880. local slots = skeleton.slots
  881. if mixingOut and setupPose then
  882. for i,slot in ipairs(slots) do
  883. drawOrder[i] = slots[i]
  884. end
  885. return;
  886. end
  887. local frames = self.frames
  888. if time < frames[0] then
  889. if pose == MixPose.setup then
  890. for i,slot in ipairs(slots) do
  891. drawOrder[i] = slots[i]
  892. end
  893. end
  894. return
  895. end
  896. local frame
  897. if time >= frames[zlen(frames) - 1] then -- Time is after last frame.
  898. frame = zlen(frames) - 1
  899. else
  900. frame = binarySearch1(frames, time) - 1
  901. end
  902. local drawOrderToSetupIndex = self.drawOrders[frame]
  903. if not drawOrderToSetupIndex then
  904. for i,slot in ipairs(slots) do
  905. drawOrder[i] = slots[i]
  906. end
  907. else
  908. for i,setupIndex in ipairs(drawOrderToSetupIndex) do
  909. drawOrder[i] = skeleton.slots[setupIndex]
  910. end
  911. end
  912. end
  913. return self
  914. end
  915. Animation.IkConstraintTimeline = {}
  916. Animation.IkConstraintTimeline.ENTRIES = 3
  917. function Animation.IkConstraintTimeline.new (frameCount)
  918. local ENTRIES = Animation.IkConstraintTimeline.ENTRIES
  919. local PREV_TIME = -3
  920. local PREV_MIX = -2
  921. local PREV_BEND_DIRECTION = -1
  922. local MIX = 1
  923. local BEND_DIRECTION = 2
  924. local self = Animation.CurveTimeline.new(frameCount)
  925. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES) -- time, mix, bendDirection, ...
  926. self.ikConstraintIndex = -1
  927. self.type = TimelineType.ikConstraint
  928. function self:getPropertyId ()
  929. return TimelineType.ikConstraint * SHL_24 + self.ikConstraintIndex
  930. end
  931. function self:setFrame (frameIndex, time, mix, bendDirection)
  932. frameIndex = frameIndex * ENTRIES
  933. self.frames[frameIndex] = time
  934. self.frames[frameIndex + MIX] = mix
  935. self.frames[frameIndex + BEND_DIRECTION] = bendDirection
  936. end
  937. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  938. local frames = self.frames
  939. local constraint = skeleton.ikConstraints[self.ikConstraintIndex]
  940. if time < frames[0] then
  941. if pose == MixPose.setup then
  942. constraint.mix = constraint.data.mix
  943. constraint.bendDirection = constraint.data.bendDirection
  944. elseif pose == MixPose.current then
  945. constraint.mix = constraint.mix + (constraint.data.mix - constraint.mix) * alpha
  946. constraint.bendDirection = constraint.data.bendDirection
  947. end
  948. return
  949. end
  950. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  951. if pose == MixPose.setup then
  952. constraint.mix = constraint.data.mix + (frames[zlen(frames) + PREV_MIX] - constraint.data.mix) * alpha
  953. if direction == MixDirection.out then
  954. constraint.bendDirection = constraint.data.bendDirection
  955. else
  956. constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]);
  957. end
  958. else
  959. constraint.mix = constraint.mix + (frames[frames.length + PREV_MIX] - constraint.mix) * alpha;
  960. if direction == MixDirection._in then constraint.bendDirection = math_floor(frames[zlen(frames) + PREV_BEND_DIRECTION]) end
  961. end
  962. return
  963. end
  964. -- Interpolate between the previous frame and the current frame.
  965. local frame = binarySearch(frames, time, ENTRIES)
  966. local mix = frames[frame + PREV_MIX]
  967. local frameTime = frames[frame]
  968. local percent = self:getCurvePercent(math.floor(frame / ENTRIES) - 1,
  969. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  970. if pose == MixPose.setup then
  971. constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha
  972. if direction == MixDirection.out then
  973. constraint.bendDirection = constraint.data.bendDirection
  974. else
  975. constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION])
  976. end
  977. else
  978. constraint.mix = constraint.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
  979. if direction == MixDirection._in then constraint.bendDirection = math_floor(frames[frame + PREV_BEND_DIRECTION]) end
  980. end
  981. end
  982. return self
  983. end
  984. Animation.TransformConstraintTimeline = {}
  985. Animation.TransformConstraintTimeline.ENTRIES = 5
  986. function Animation.TransformConstraintTimeline.new (frameCount)
  987. local ENTRIES = Animation.TransformConstraintTimeline.ENTRIES
  988. local PREV_TIME = -5
  989. local PREV_ROTATE = -4
  990. local PREV_TRANSLATE = -3
  991. local PREV_SCALE = -2
  992. local PREV_SHEAR = -1
  993. local ROTATE = 1
  994. local TRANSLATE = 2
  995. local SCALE = 3
  996. local SHEAR = 4
  997. local self = Animation.CurveTimeline.new(frameCount)
  998. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  999. self.transformConstraintIndex = -1
  1000. self.type = TimelineType.transformConstraint
  1001. function self:getPropertyId ()
  1002. return TimelineType.transformConstraint * SHL_24 + self.transformConstraintIndex
  1003. end
  1004. function self:setFrame (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix)
  1005. frameIndex = frameIndex * ENTRIES
  1006. self.frames[frameIndex] = time
  1007. self.frames[frameIndex + ROTATE] = rotateMix
  1008. self.frames[frameIndex + TRANSLATE] = translateMix
  1009. self.frames[frameIndex + SCALE] = scaleMix
  1010. self.frames[frameIndex + SHEAR] = shearMix
  1011. end
  1012. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  1013. local frames = self.frames
  1014. local constraint = skeleton.transformConstraints[self.transformConstraintIndex]
  1015. if time < frames[0] then
  1016. local data = constraint.data
  1017. if pose == MixPose.setup then
  1018. constraint.rotateMix = data.rotateMix
  1019. constraint.translateMix = data.translateMix
  1020. constraint.scaleMix = data.scaleMix
  1021. constraint.shearMix = data.shearMix
  1022. elseif pose == MixPose.current then
  1023. constraint.rotateMix = constraint.rotateMix + (data.rotateMix - constraint.rotateMix) * alpha
  1024. constraint.translateMix = constraint.translateMix + (data.translateMix - constraint.translateMix) * alpha
  1025. constraint.scaleMix = constraint.scaleMix + (data.scaleMix - constraint.scaleMix) * alpha
  1026. constraint.shearMix = constraint.shearMix + (data.shearMix - constraint.shearMix) * alpha
  1027. end
  1028. return
  1029. end
  1030. local rotate = 0
  1031. local translate = 0
  1032. local scale = 0
  1033. local shear = 0
  1034. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  1035. local i = zlen(frames.length)
  1036. rotate = frames[i + PREV_ROTATE]
  1037. translate = frames[i + PREV_TRANSLATE]
  1038. scale = frames[i + PREV_SCALE]
  1039. shear = frames[i + PREV_SHEAR]
  1040. else
  1041. -- Interpolate between the previous frame and the current frame.
  1042. local frame = binarySearch(frames, time, ENTRIES)
  1043. rotate = frames[frame + PREV_ROTATE]
  1044. translate = frames[frame + PREV_TRANSLATE]
  1045. scale = frames[frame + PREV_SCALE]
  1046. shear = frames[frame + PREV_SHEAR]
  1047. local frameTime = frames[frame]
  1048. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  1049. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
  1050. rotate = rotate + (frames[frame + ROTATE] - rotate) * percent
  1051. translate = translate + (frames[frame + TRANSLATE] - translate) * percent
  1052. scale = scale + (frames[frame + SCALE] - scale) * percent
  1053. shear = shear + (frames[frame + SHEAR] - shear) * percent
  1054. end
  1055. if pose == MixPose.setup then
  1056. local data = constraint.data
  1057. constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha
  1058. constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha
  1059. constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha
  1060. constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha
  1061. else
  1062. constraint.rotateMix = constraint.rotateMix + (rotate - constraint.rotateMix) * alpha
  1063. constraint.translateMix = constraint.translateMix + (translate - constraint.translateMix) * alpha
  1064. constraint.scaleMix = constraint.scaleMix + (scale - constraint.scaleMix) * alpha
  1065. constraint.shearMix = constraint.shearMix + (shear - constraint.shearMix) * alpha
  1066. end
  1067. end
  1068. return self
  1069. end
  1070. Animation.PathConstraintPositionTimeline = {}
  1071. Animation.PathConstraintPositionTimeline.ENTRIES = 2
  1072. function Animation.PathConstraintPositionTimeline.new (frameCount)
  1073. local ENTRIES = Animation.PathConstraintPositionTimeline.ENTRIES
  1074. local PREV_TIME = -2
  1075. local PREV_VALUE = -1
  1076. local VALUE = 1
  1077. local self = Animation.CurveTimeline.new(frameCount)
  1078. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  1079. self.pathConstraintIndex = -1
  1080. self.type = TimelineType.pathConstraintPosition
  1081. function self:getPropertyId ()
  1082. return TimelineType.pathConstraintPosition * SHL_24 + self.pathConstraintIndex
  1083. end
  1084. function self:setFrame (frameIndex, time, value)
  1085. frameIndex = frameIndex * ENTRIES
  1086. self.frames[frameIndex] = time
  1087. self.frames[frameIndex + VALUE] = value
  1088. end
  1089. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  1090. local frames = self.frames
  1091. local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
  1092. if (time < frames[0]) then
  1093. if pose == MixPose.setup then
  1094. constraint.position = constraint.data.position
  1095. elseif pose == MixPose.current then
  1096. constraint.position = constraint.position + (constraint.data.position - constraint.position) * alpha
  1097. end
  1098. return
  1099. end
  1100. local position = 0
  1101. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  1102. position = frames[zlen(frames) + PREV_VALUE]
  1103. else
  1104. -- Interpolate between the previous frame and the current frame.
  1105. local frame = binarySearch(frames, time, ENTRIES)
  1106. position = frames[frame + PREV_VALUE]
  1107. local frameTime = frames[frame]
  1108. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  1109. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  1110. position = position + (frames[frame + VALUE] - position) * percent
  1111. end
  1112. if pose == MixPose.setup then
  1113. constraint.position = constraint.data.position + (position - constraint.data.position) * alpha
  1114. else
  1115. constraint.position = constraint.position + (position - constraint.position) * alpha
  1116. end
  1117. end
  1118. return self
  1119. end
  1120. Animation.PathConstraintSpacingTimeline = {}
  1121. Animation.PathConstraintSpacingTimeline.ENTRIES = 2
  1122. function Animation.PathConstraintSpacingTimeline.new (frameCount)
  1123. local ENTRIES = Animation.PathConstraintSpacingTimeline.ENTRIES
  1124. local PREV_TIME = -2
  1125. local PREV_VALUE = -1
  1126. local VALUE = 1
  1127. local self = Animation.CurveTimeline.new(frameCount)
  1128. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  1129. self.pathConstraintIndex = -1
  1130. self.type = TimelineType.pathConstraintSpacing
  1131. function self:getPropertyId ()
  1132. return TimelineType.pathConstraintSpacing * SHL_24 + self.pathConstraintIndex
  1133. end
  1134. function self:setFrame (frameIndex, time, value)
  1135. frameIndex = frameIndex * ENTRIES
  1136. self.frames[frameIndex] = time
  1137. self.frames[frameIndex + VALUE] = value
  1138. end
  1139. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  1140. local frames = self.frames
  1141. local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
  1142. if (time < frames[0]) then
  1143. if pose == MixPose.setup then
  1144. constraint.spacing = constraint.data.spacing
  1145. elseif pose == MixPose.current then
  1146. constraint.spacing = constraint.spacing + (constraint.data.spacing - constraint.spacing) * alpha
  1147. end
  1148. return
  1149. end
  1150. local spacing = 0
  1151. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  1152. spacing = frames[zlen(frames) + PREV_VALUE]
  1153. else
  1154. -- Interpolate between the previous frame and the current frame.
  1155. local frame = binarySearch(frames, time, ENTRIES)
  1156. spacing = frames[frame + PREV_VALUE]
  1157. local frameTime = frames[frame]
  1158. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  1159. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  1160. spacing = spacing + (frames[frame + VALUE] - spacing) * percent
  1161. end
  1162. if pose == MixPose.setup then
  1163. constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha
  1164. else
  1165. constraint.spacing = constraint.spacing + (spacing - constraint.spacing) * alpha
  1166. end
  1167. end
  1168. return self
  1169. end
  1170. Animation.PathConstraintMixTimeline = {}
  1171. Animation.PathConstraintMixTimeline.ENTRIES = 3
  1172. function Animation.PathConstraintMixTimeline.new (frameCount)
  1173. local ENTRIES = Animation.PathConstraintMixTimeline.ENTRIES
  1174. local PREV_TIME = -3
  1175. local PREV_ROTATE = -2
  1176. local PREV_TRANSLATE = -1
  1177. local ROTATE = 1
  1178. local TRANSLATE = 2
  1179. local self = Animation.CurveTimeline.new(frameCount)
  1180. self.frames = utils.newNumberArrayZero(frameCount * ENTRIES)
  1181. self.pathConstraintIndex = -1
  1182. self.type = TimelineType.pathConstraintMix
  1183. function self:getPropertyId ()
  1184. return TimelineType.pathConstraintMix * SHL_24 + self.pathConstraintIndex
  1185. end
  1186. function self:setFrame (frameIndex, time, rotateMix, translateMix)
  1187. frameIndex = frameIndex * ENTRIES
  1188. self.frames[frameIndex] = time
  1189. self.frames[frameIndex + ROTATE] = rotateMix
  1190. self.frames[frameIndex + TRANSLATE] = translateMix
  1191. end
  1192. function self:apply (skeleton, lastTime, time, firedEvents, alpha, pose, direction)
  1193. local frames = self.frames
  1194. local constraint = skeleton.pathConstraints[self.pathConstraintIndex]
  1195. if (time < frames[0]) then
  1196. if pose == MixPose.setup then
  1197. constraint.rotateMix = constraint.data.rotateMix
  1198. constraint.translateMix = constraint.data.translateMix
  1199. elseif pose == MixPose.current then
  1200. constraint.rotateMix = constraint.rotateMix + (constraint.data.rotateMix - constraint.rotateMix) * alpha
  1201. constraint.translateMix = constraint.translateMix + (constraint.data.translateMix - constraint.translateMix) * alpha
  1202. end
  1203. return
  1204. end
  1205. local rotate = 0
  1206. local translate = 0
  1207. if time >= frames[zlen(frames) - ENTRIES] then -- Time is after last frame.
  1208. rotate = frames[zlen(frames) + PREV_ROTATE]
  1209. translate = frames[zlen(frames) + PREV_TRANSLATE]
  1210. else
  1211. -- Interpolate between the previous frame and the current frame.
  1212. local frame = binarySearch(frames, time, ENTRIES)
  1213. rotate = frames[frame + PREV_ROTATE]
  1214. translate = frames[frame + PREV_TRANSLATE]
  1215. local frameTime = frames[frame]
  1216. local percent = self:getCurvePercent(math_floor(frame / ENTRIES) - 1,
  1217. 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime))
  1218. rotate = rotate + (frames[frame + ROTATE] - rotate) * percent
  1219. translate = translate + (frames[frame + TRANSLATE] - translate) * percent
  1220. end
  1221. if pose == MixPose.setup then
  1222. constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha
  1223. constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha
  1224. else
  1225. constraint.rotateMix = constraint.rotateMix + (rotate - constraint.rotateMix) * alpha
  1226. constraint.translateMix = constraint.translateMix + (translate - constraint.translateMix) * alpha
  1227. end
  1228. end
  1229. return self
  1230. end
  1231. return Animation