animation.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. local animation = {}
  2. animation.__index = animation
  3. function animation.create(spine, config)
  4. local self = setmetatable({}, animation)
  5. self.spine = spine
  6. self.config = config
  7. if spine.atlas then
  8. self.atlas = lib.spine.Atlas.new(spine.atlas)
  9. self.atlasAttachmentLoader = lib.spine.AtlasAttachmentLoader.new(self.atlas)
  10. end
  11. self.skeletonJson = lib.spine.SkeletonJson.new(self.atlasAttachmentLoader)
  12. self.skeletonJson.scale = self.config.scale or 1
  13. self.skeletonData = self.skeletonJson:readSkeletonData(spine.data)
  14. self.skeleton = lib.spine.Skeleton.new(self.skeletonData)
  15. self.skeletonBounds = lib.spine.SkeletonBounds.new()
  16. self.skeleton.createImage = function(_, attachment)
  17. return spine.images[attachment.name]
  18. end
  19. self.skeleton.createAtlasImage = function(_, page)
  20. return spine.image
  21. end
  22. self.states = util.copy(self.config.states)
  23. self.animationStateData = lib.spine.AnimationStateData.new(self.skeletonData)
  24. self.animationState = lib.spine.AnimationState.new(self.animationStateData)
  25. self.skeleton:setToSetupPose()
  26. self.speed = 1
  27. self.flipped = false
  28. self:resetTo(self.config.default)
  29. self.events = lib.rx.Subject.create()
  30. self.completions = lib.rx.Subject.create()
  31. self.animationState.onEvent = function(_, event)
  32. self.events:onNext(event)
  33. end
  34. self.animationState.onComplete = function(track)
  35. local name = self.animationState.tracks[track].animation.name
  36. local state = self.states[name]
  37. self.completions:onNext(name)
  38. state.active = false
  39. if state.after then
  40. self:set(state.after)
  41. end
  42. end
  43. return self
  44. end
  45. function animation:draw(x, y)
  46. local skeleton = self.skeleton
  47. self:setPosition(x, y)
  48. skeleton.flipX = self.flipped
  49. if self.config.backwards then skeleton.flipX = not skeleton.flipX end
  50. skeleton:updateWorldTransform()
  51. skeleton:draw()
  52. end
  53. function animation:tick(delta)
  54. delta = delta or lib.tick.rate
  55. self.animationState.timeScale = self.speed or 1
  56. for i = 0, self.animationState.trackCount do
  57. local track = self.animationState.tracks[i]
  58. if track then
  59. local animation = track.animation
  60. local state = self.states[animation.name]
  61. if state.length then
  62. local speed = animation.duration / state.length
  63. self.animationState.tracks[i].timeScale = speed
  64. else
  65. if self.config.speedHack then
  66. self.animationState.tracks[i].timeScale = state.speed or 1
  67. else
  68. self.animationState.tracks[i].timeScale = 1
  69. end
  70. end
  71. end
  72. end
  73. if self.config.speedHack then
  74. self.animationState:update(delta)
  75. else
  76. self.animationState:update(delta * (self.active.speed or 1))
  77. end
  78. self.animationState:apply(self.skeleton)
  79. end
  80. function animation:setPosition(x, y)
  81. local skeleton = self.skeleton
  82. skeleton.x = x + (self.config.offset.x or 0)
  83. skeleton.y = y + (self.config.offset.y or 0)
  84. end
  85. function animation:resetTo(name)
  86. local state = self.states[name]
  87. if state then
  88. self:clear()
  89. local track = state.track or 0
  90. local loop = state.loop
  91. state.active = true
  92. self.active = state
  93. self.animationState:setAnimationByName(track, name, loop)
  94. end
  95. end
  96. function animation:set(name)
  97. local state = self.states[name]
  98. if state and self.active ~= state then
  99. local track = state.track or 0
  100. local loop = state.loop
  101. state.active = true
  102. self.active = state
  103. self.animationState:setAnimationByName(track, name, loop)
  104. end
  105. end
  106. function animation:contains(x, y)
  107. util.each(self.skeleton.slots, function(slot)
  108. slot:setAttachment(self.skeleton:getAttachment(slot.data.name, slot.data.name .. '_bb'))
  109. end)
  110. self.skeleton.flipY = true
  111. self.skeleton:updateWorldTransform()
  112. self.skeletonBounds:update(self.skeleton)
  113. self.skeleton.flipY = false
  114. local contains = self.skeletonBounds:containsPoint(x, y)
  115. util.each(self.skeleton.slots, function(slot)
  116. slot:setAttachment(self.skeleton:getAttachment(slot.data.name, slot.data.name))
  117. end)
  118. return contains
  119. end
  120. function animation:clear()
  121. self.animationState:clearTracks()
  122. end
  123. return animation