twimer.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. --[===================================================================[--
  2. Copyright © 2016 Pedro Gimeno Fortea. All rights reserved.
  3. This library is work-in-progress. You may copy it but you may not
  4. use it in your projects.
  5. --]===================================================================]--
  6. local function pause(timer)
  7. timer.paused = true
  8. end
  9. local function resume(timer)
  10. timer.paused = false
  11. end
  12. local function cancel(timer)
  13. timer.cancelled = true
  14. end
  15. local function reset(timer)
  16. timer.time = timer.start
  17. end
  18. -- Tweening ancillary functions
  19. local function linear(t)
  20. return t
  21. end
  22. local function twimer_lerp(from, to, t)
  23. return t < 0.5 and from + (to-from)*t or to + (from-to)*(1-t)
  24. end
  25. -- Modes
  26. local function twimer_after(self, t, callback)
  27. local new = {
  28. mode = "after";
  29. time = t;
  30. start = t;
  31. cb = callback;
  32. pause = pause;
  33. resume = resume;
  34. reset = reset;
  35. cancel = cancel;
  36. cancelled = t == 0;
  37. }
  38. if t == 0 then
  39. if callback then callback(new, 0, "end") end
  40. else
  41. self[#self + 1] = new
  42. end
  43. return new
  44. end
  45. local function twimer_during(self, t, callback)
  46. local new = {
  47. mode = "during";
  48. time = t;
  49. start = t;
  50. cb = callback;
  51. pause = pause;
  52. resume = resume;
  53. reset = reset;
  54. cancel = cancel;
  55. cancelled = t == 0;
  56. }
  57. if t == 0 then
  58. if callback then callback(new, 0, "end") end
  59. else
  60. self[#self + 1] = new
  61. end
  62. return new
  63. end
  64. local function twimer_every(self, t, callback)
  65. local new = {
  66. mode = "every";
  67. time = t;
  68. start = t;
  69. cb = callback;
  70. pause = pause;
  71. resume = resume;
  72. reset = reset;
  73. cancel = cancel;
  74. cancelled = false;
  75. }
  76. if t == 0 then
  77. if callback then
  78. while not new.cancelled do callback(new, 0, "end") end
  79. else
  80. error("Interval is 0s and no callback is provided. This would cause an infinite loop.")
  81. end
  82. else
  83. self[#self + 1] = new
  84. end
  85. return new
  86. end
  87. local function twimer_tween(self, from, to, ease, t, callback, param)
  88. local new = {
  89. mode = "tween";
  90. time = t;
  91. start = t;
  92. from = from or 0;
  93. to = to or 1;
  94. ease = ease or linear;
  95. cb = callback or nil;
  96. param = param;
  97. val = twimer_lerp(from or 0, to or 1, (ease or linear)(0, param));
  98. pause = pause;
  99. resume = resume;
  100. reset = reset;
  101. cancel = cancel;
  102. cancelled = false;
  103. }
  104. self[#self + 1] = new
  105. return new
  106. end
  107. local function twimer_manual_tween(self, t, callback, obj)
  108. local new = {
  109. mode = "tween";
  110. time = t;
  111. start = t;
  112. from = 0;
  113. to = 1;
  114. ease = linear;
  115. cb = callback or nil;
  116. val = 0;
  117. obj = obj;
  118. pause = pause;
  119. resume = resume;
  120. reset = reset;
  121. cancel = cancel;
  122. cancelled = false;
  123. }
  124. self[#self + 1] = new
  125. return new
  126. end
  127. local function twimer_update(self, dt)
  128. for i = #self, 1, -1 do
  129. local timer = self[i]
  130. if timer.cancelled then
  131. table.remove(self, i)
  132. elseif not timer.paused then
  133. timer.time = timer.time - dt
  134. if timer.time <= 0 then
  135. -- timer expired
  136. if timer.mode ~= "every" then timer.cancelled = true end
  137. if timer.mode == "tween" then
  138. timer.val = twimer_lerp(timer.from, timer.to, timer.ease(1, timer.param))
  139. if timer.cb then timer:cb(timer.val) end
  140. else
  141. if timer.cb then timer:cb(dt, "end") end
  142. end
  143. if timer.mode == "every" then
  144. timer.time = timer.time + timer.start
  145. else
  146. table.remove(self, i)
  147. end
  148. -- not expired - send continuous callbacks/updates when needed
  149. elseif timer.mode == "during" then
  150. if timer.cb then timer:cb(dt, "update") end
  151. elseif timer.mode == "tween" then
  152. timer.val = twimer_lerp(timer.from, timer.to, timer.ease(math.min(1-timer.time/timer.start, 1), timer.param))
  153. if timer.cb then timer:cb(timer.val) end
  154. end
  155. end
  156. end
  157. end
  158. local function new()
  159. return {
  160. lerp = twimer_lerp;
  161. linear = linear;
  162. after = twimer_after;
  163. during = twimer_during;
  164. every = twimer_every;
  165. tween = twimer_tween;
  166. manual_tween = twimer_manual_tween;
  167. update = twimer_update;
  168. }
  169. end
  170. return new