easing_equations.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /**
  2. * Adapted from Penner Easing equations' C++ port.
  3. * Source: https://github.com/jesusgollonet/ofpennereasing
  4. * License: BSD-3-clause
  5. */
  6. #include "scene/animation/tween.h"
  7. const real_t pi = 3.1415926535898;
  8. ///////////////////////////////////////////////////////////////////////////
  9. // linear
  10. ///////////////////////////////////////////////////////////////////////////
  11. namespace linear {
  12. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  13. return c * t / d + b;
  14. }
  15. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  16. return c * t / d + b;
  17. }
  18. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  19. return c * t / d + b;
  20. }
  21. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  22. return c * t / d + b;
  23. }
  24. }; // namespace linear
  25. ///////////////////////////////////////////////////////////////////////////
  26. // sine
  27. ///////////////////////////////////////////////////////////////////////////
  28. namespace sine {
  29. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  30. return -c * cos(t / d * (pi / 2)) + c + b;
  31. }
  32. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  33. return c * sin(t / d * (pi / 2)) + b;
  34. }
  35. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  36. return -c / 2 * (cos(pi * t / d) - 1) + b;
  37. }
  38. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  39. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  40. }
  41. }; // namespace sine
  42. ///////////////////////////////////////////////////////////////////////////
  43. // quint
  44. ///////////////////////////////////////////////////////////////////////////
  45. namespace quint {
  46. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  47. return c * pow(t / d, 5) + b;
  48. }
  49. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  50. return c * (pow(t / d - 1, 5) + 1) + b;
  51. }
  52. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  53. t = t / d * 2;
  54. if (t < 1) return c / 2 * pow(t, 5) + b;
  55. return c / 2 * (pow(t - 2, 5) + 2) + b;
  56. }
  57. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  58. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  59. }
  60. }; // namespace quint
  61. ///////////////////////////////////////////////////////////////////////////
  62. // quart
  63. ///////////////////////////////////////////////////////////////////////////
  64. namespace quart {
  65. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  66. return c * pow(t / d, 4) + b;
  67. }
  68. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  69. return -c * (pow(t / d - 1, 4) - 1) + b;
  70. }
  71. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  72. t = t / d * 2;
  73. if (t < 1) return c / 2 * pow(t, 4) + b;
  74. return -c / 2 * (pow(t - 2, 4) - 2) + b;
  75. }
  76. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  77. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  78. }
  79. }; // namespace quart
  80. ///////////////////////////////////////////////////////////////////////////
  81. // quad
  82. ///////////////////////////////////////////////////////////////////////////
  83. namespace quad {
  84. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  85. return c * pow(t / d, 2) + b;
  86. }
  87. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  88. t = t / d;
  89. return -c * t * (t - 2) + b;
  90. }
  91. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  92. t = t / d * 2;
  93. if (t < 1) return c / 2 * pow(t, 2) + b;
  94. return -c / 2 * ((t - 1) * (t - 3) - 1) + b;
  95. }
  96. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  97. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  98. }
  99. }; // namespace quad
  100. ///////////////////////////////////////////////////////////////////////////
  101. // expo
  102. ///////////////////////////////////////////////////////////////////////////
  103. namespace expo {
  104. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  105. if (t == 0) return b;
  106. return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001;
  107. }
  108. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  109. if (t == d) return b + c;
  110. return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b;
  111. }
  112. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  113. if (t == 0) return b;
  114. if (t == d) return b + c;
  115. t = t / d * 2;
  116. if (t < 1) return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005;
  117. return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b;
  118. }
  119. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  120. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  121. }
  122. }; // namespace expo
  123. ///////////////////////////////////////////////////////////////////////////
  124. // elastic
  125. ///////////////////////////////////////////////////////////////////////////
  126. namespace elastic {
  127. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  128. if (t == 0) return b;
  129. if ((t /= d) == 1) return b + c;
  130. float p = d * 0.3f;
  131. float a = c;
  132. float s = p / 4;
  133. float postFix = a * pow(2, 10 * (t -= 1)); // this is a fix, again, with post-increment operators
  134. return -(postFix * sin((t * d - s) * (2 * pi) / p)) + b;
  135. }
  136. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  137. if (t == 0) return b;
  138. if ((t /= d) == 1) return b + c;
  139. float p = d * 0.3f;
  140. float a = c;
  141. float s = p / 4;
  142. return (a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b);
  143. }
  144. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  145. if (t == 0) return b;
  146. if ((t /= d / 2) == 2) return b + c;
  147. float p = d * (0.3f * 1.5f);
  148. float a = c;
  149. float s = p / 4;
  150. if (t < 1) {
  151. float postFix = a * pow(2, 10 * (t -= 1)); // postIncrement is evil
  152. return -0.5f * (postFix * sin((t * d - s) * (2 * pi) / p)) + b;
  153. }
  154. float postFix = a * pow(2, -10 * (t -= 1)); // postIncrement is evil
  155. return postFix * sin((t * d - s) * (2 * pi) / p) * 0.5f + c + b;
  156. }
  157. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  158. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  159. }
  160. }; // namespace elastic
  161. ///////////////////////////////////////////////////////////////////////////
  162. // cubic
  163. ///////////////////////////////////////////////////////////////////////////
  164. namespace cubic {
  165. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  166. return c * (t /= d) * t * t + b;
  167. }
  168. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  169. t = t / d - 1;
  170. return c * (t * t * t + 1) + b;
  171. }
  172. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  173. if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
  174. return c / 2 * ((t -= 2) * t * t + 2) + b;
  175. }
  176. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  177. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  178. }
  179. }; // namespace cubic
  180. ///////////////////////////////////////////////////////////////////////////
  181. // circ
  182. ///////////////////////////////////////////////////////////////////////////
  183. namespace circ {
  184. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  185. return -c * (sqrt(1 - (t /= d) * t) - 1) + b; // TODO: ehrich: operation with t is undefined
  186. }
  187. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  188. return c * sqrt(1 - (t = t / d - 1) * t) + b; // TODO: ehrich: operation with t is undefined
  189. }
  190. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  191. if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b;
  192. return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; // TODO: ehrich: operation with t is undefined
  193. }
  194. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  195. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  196. }
  197. }; // namespace circ
  198. ///////////////////////////////////////////////////////////////////////////
  199. // bounce
  200. ///////////////////////////////////////////////////////////////////////////
  201. namespace bounce {
  202. static real_t out(real_t t, real_t b, real_t c, real_t d);
  203. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  204. return c - out(d - t, 0, c, d) + b;
  205. }
  206. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  207. if ((t /= d) < (1 / 2.75f)) {
  208. return c * (7.5625f * t * t) + b;
  209. } else if (t < (2 / 2.75f)) {
  210. float postFix = t -= (1.5f / 2.75f);
  211. return c * (7.5625f * (postFix)*t + .75f) + b;
  212. } else if (t < (2.5 / 2.75)) {
  213. float postFix = t -= (2.25f / 2.75f);
  214. return c * (7.5625f * (postFix)*t + .9375f) + b;
  215. } else {
  216. float postFix = t -= (2.625f / 2.75f);
  217. return c * (7.5625f * (postFix)*t + .984375f) + b;
  218. }
  219. }
  220. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  221. return (t < d / 2) ? in(t * 2, b, c / 2, d) : out((t * 2) - d, b + c / 2, c / 2, d);
  222. }
  223. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  224. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  225. }
  226. }; // namespace bounce
  227. ///////////////////////////////////////////////////////////////////////////
  228. // back
  229. ///////////////////////////////////////////////////////////////////////////
  230. namespace back {
  231. static real_t in(real_t t, real_t b, real_t c, real_t d) {
  232. float s = 1.70158f;
  233. float postFix = t /= d;
  234. return c * (postFix)*t * ((s + 1) * t - s) + b;
  235. }
  236. static real_t out(real_t t, real_t b, real_t c, real_t d) {
  237. float s = 1.70158f;
  238. return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; // TODO: ehrich: operation with t is undefined
  239. }
  240. static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
  241. float s = 1.70158f;
  242. if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; // TODO: ehrich: operation with s is undefined
  243. float postFix = t -= 2;
  244. return c / 2 * ((postFix)*t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; // TODO: ehrich: operation with s is undefined
  245. }
  246. static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
  247. return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
  248. }
  249. }; // namespace back
  250. Tween::interpolater Tween::interpolaters[Tween::TRANS_COUNT][Tween::EASE_COUNT] = {
  251. { &linear::in, &linear::out, &linear::in_out, &linear::out_in },
  252. { &sine::in, &sine::out, &sine::in_out, &sine::out_in },
  253. { &quint::in, &quint::out, &quint::in_out, &quint::out_in },
  254. { &quart::in, &quart::out, &quart::in_out, &quart::out_in },
  255. { &quad::in, &quad::out, &quad::in_out, &quad::out_in },
  256. { &expo::in, &expo::out, &expo::in_out, &expo::out_in },
  257. { &elastic::in, &elastic::out, &elastic::in_out, &elastic::out_in },
  258. { &cubic::in, &cubic::out, &cubic::in_out, &cubic::out_in },
  259. { &circ::in, &circ::out, &circ::in_out, &circ::out_in },
  260. { &bounce::in, &bounce::out, &bounce::in_out, &bounce::out_in },
  261. { &back::in, &back::out, &back::in_out, &back::out_in },
  262. };
  263. real_t Tween::_run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d) {
  264. interpolater cb = interpolaters[p_trans_type][p_ease_type];
  265. ERR_FAIL_COND_V(cb == NULL, b);
  266. return cb(t, b, c, d);
  267. }