Tween.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "Tween.h"
  2. #include "Actor.h"
  3. #include "ColorRectSprite.h"
  4. #include <limits.h>
  5. namespace oxygine
  6. {
  7. Tween::Tween() : _duration(0),
  8. _loops(1),
  9. _percent(0),
  10. _status(status_not_started),
  11. _elapsed(0), _twoSides(false), _ease(ease_linear), _detach(false), _delay(0), _client(0)
  12. {
  13. }
  14. Tween::~Tween()
  15. {
  16. }
  17. void Tween::reset()
  18. {
  19. _elapsed = 0;
  20. _status = status_not_started;
  21. }
  22. void Tween::init(timeMS duration, int loops, bool twoSides, timeMS delay, EASE ease)
  23. {
  24. _duration = duration;
  25. _ease = ease;
  26. _loops = loops;
  27. _twoSides = twoSides;
  28. _delay = delay;
  29. if (_duration <= 0)
  30. {
  31. OX_ASSERT(!"Tweener duration should be more than ZERO");
  32. _duration = 1;
  33. }
  34. }
  35. void Tween::init2(const TweenOptions& opt)
  36. {
  37. _duration = opt._duration;
  38. _ease = opt._ease;
  39. _loops = opt._loops;
  40. _twoSides = opt._twoSides;
  41. _delay = opt._delay;
  42. if (_duration <= 0)
  43. {
  44. OX_ASSERT(!"Tweener duration should be more than ZERO");
  45. _duration = 1;
  46. }
  47. }
  48. void Tween::setDoneCallback(EventCallback cb)
  49. {
  50. _cbDone = cb;
  51. }
  52. void Tween::addDoneCallback(EventCallback cb)
  53. {
  54. addEventListener(TweenEvent::DONE, cb);
  55. }
  56. float Tween::_calcEase(float v)
  57. {
  58. if (_twoSides)
  59. {
  60. if (v > 0.5f)
  61. v = 1.0f - v;
  62. v *= 2.0f;
  63. }
  64. v = calcEase(_ease, v);
  65. return v;
  66. }
  67. void Tween::complete(timeMS deltaTime)
  68. {
  69. if (_loops == -1)
  70. return;
  71. //if already done
  72. if (_status >= status_done)
  73. return;
  74. OX_ASSERT(_client);
  75. //OX_ASSERT(!"not implemented");
  76. //not started yet because if delay
  77. if (_status == status_delayed)
  78. {
  79. _start(*_client);
  80. _status = status_started;
  81. }
  82. OX_ASSERT(_status == status_started);
  83. //while (_status != status_remove)
  84. {
  85. UpdateState us;
  86. us.dt = deltaTime;
  87. update(*_client, us);
  88. }
  89. OX_ASSERT(_status == status_done);
  90. //_client->removeTween(this);
  91. }
  92. void Tween::start(Actor& actor)
  93. {
  94. _client = &actor;
  95. _status = status_delayed;
  96. if (_delay == 0)
  97. {
  98. _status = status_started;
  99. _start(actor);
  100. }
  101. }
  102. void Tween::update(Actor& actor, const UpdateState& us)
  103. {
  104. _elapsed += us.dt;
  105. switch (_status)
  106. {
  107. case status_delayed:
  108. {
  109. if (_elapsed >= _delay)
  110. {
  111. _status = status_started;
  112. _start(*_client);
  113. }
  114. }
  115. break;
  116. case status_started:
  117. {
  118. if (_duration)
  119. {
  120. timeMS localElapsed = _elapsed - _delay;
  121. int loopsDone = localElapsed / _duration;
  122. _percent = _calcEase(((float)(localElapsed - loopsDone * _duration)) / _duration);
  123. if (_loops > 0 && int(loopsDone) >= _loops)
  124. {
  125. if (_twoSides)
  126. _percent = 0;
  127. else
  128. _percent = 1;
  129. _status = status_done;
  130. }
  131. }
  132. _update(*_client, us);
  133. }
  134. break;
  135. case status_done:
  136. {
  137. done(*_client, us);
  138. }
  139. break;
  140. }
  141. }
  142. void Tween::done(Actor& actor, const UpdateState& us)
  143. {
  144. _done(actor, us);
  145. if (_detach)
  146. {
  147. actor.detach();
  148. }
  149. TweenEvent ev(this, &us);
  150. ev.target = ev.currentTarget = &actor;
  151. ev.tween = this;
  152. if (_cbDone)
  153. _cbDone(&ev);
  154. dispatchEvent(&ev);
  155. _status = status_remove;
  156. }
  157. Actor* TweenEvent::getActor() const
  158. {
  159. return safeCast<Actor*>(currentTarget.get());
  160. }
  161. static float outBounce(float t)
  162. {
  163. if (t < 0.363636363636f)
  164. {
  165. return 7.5625f * t * t;
  166. }
  167. if (t < 0.727272727273f)
  168. {
  169. t = t - 0.545454545455f;
  170. return 7.5625f * t * t + 0.75f;
  171. }
  172. if (t < 0.909090909091f)
  173. {
  174. t = t - 0.818181818182f;
  175. return 7.5625f * t * t + 0.9375f;
  176. }
  177. t = t - 0.954545454545f;
  178. return 7.5625f * t * t + 0.984375f;
  179. }
  180. float Tween::calcEase(EASE ease, float t)
  181. {
  182. const float s = 1.70158f;
  183. switch (ease)
  184. {
  185. case ease_linear:
  186. return t;
  187. #define DEF_EASY_FROM_IN(EasyPost, formula) \
  188. case ease_in ## EasyPost: \
  189. return (formula); \
  190. case ease_out ## EasyPost: \
  191. return 1 - calcEase(ease_in ## EasyPost, 1 - t); \
  192. case ease_inOut ## EasyPost: \
  193. return t <= 0.5f ? calcEase(ease_in ## EasyPost, t * 2) / 2 : 1 - calcEase(ease_in ## EasyPost, 2 - t * 2) / 2; \
  194. case ease_outIn ## EasyPost: \
  195. return t <= 0.5f ? calcEase(ease_in ## EasyPost, t * 2) / 2 : 1 - calcEase(ease_in ## EasyPost, 2 - t * 2) / 2; \
  196. DEF_EASY_FROM_IN(Quad, t * t);
  197. DEF_EASY_FROM_IN(Cubic, t * t * t);
  198. DEF_EASY_FROM_IN(Quart, powf(t, 4));
  199. DEF_EASY_FROM_IN(Quint, powf(t, 5));
  200. DEF_EASY_FROM_IN(Sin, 1.0f - scalar::cos(t * (MATH_PI / 2.0f)));
  201. DEF_EASY_FROM_IN(Expo, powf(2, 10 * (t - 1)));
  202. DEF_EASY_FROM_IN(Circ, -1.0f * (sqrt(1 - t * t) - 1));
  203. DEF_EASY_FROM_IN(Back, t * t * ((s + 1) * t - s));
  204. DEF_EASY_FROM_IN(Bounce, 1 - outBounce(1 - t));
  205. default:
  206. OX_ASSERT(!"unsupported ease");
  207. break;
  208. }
  209. #undef DEF_EASY_FROM_IN
  210. return t;
  211. }
  212. std::string ease2String(Tween::EASE ease)
  213. {
  214. #define STRINGIFY(x) #x
  215. #define S(x) STRINGIFY(x)
  216. switch (ease)
  217. {
  218. case Tween::ease_linear:
  219. return "linear";
  220. #define DEF_EASY_FROM_IN(EasyPost) \
  221. case Tween::ease_in ## EasyPost: \
  222. return "in" S(EasyPost);\
  223. case Tween::ease_out ## EasyPost: \
  224. return "out" S(EasyPost); \
  225. case Tween::ease_inOut ## EasyPost: \
  226. return "inOut" S(EasyPost); \
  227. case Tween::ease_outIn ## EasyPost: \
  228. return "outIn" S(EasyPost);
  229. DEF_EASY_FROM_IN(Quad);
  230. DEF_EASY_FROM_IN(Cubic);
  231. DEF_EASY_FROM_IN(Quart);
  232. DEF_EASY_FROM_IN(Quint);
  233. DEF_EASY_FROM_IN(Sin);
  234. DEF_EASY_FROM_IN(Expo);
  235. DEF_EASY_FROM_IN(Circ);
  236. DEF_EASY_FROM_IN(Back);
  237. DEF_EASY_FROM_IN(Bounce);
  238. }
  239. return "unknown";
  240. }
  241. }