1 /** 2 Tweening 3 4 Copyright: (c) Enalye 2017 5 License: Zlib 6 Authors: Enalye 7 */ 8 9 module atelier.core.tween; 10 11 import std.math; 12 13 import atelier.common; 14 import atelier.core.util; 15 16 alias EasingFunction = float function(float); 17 18 /// Easing behaviour. 19 enum Ease { 20 linear, 21 sineIn, 22 sineOut, 23 sineInOut, 24 quadIn, 25 quadOut, 26 quadInOut, 27 cubicIn, 28 cubicOut, 29 cubicInOut, 30 quartIn, 31 quartOut, 32 quartInOut, 33 quintIn, 34 quintOut, 35 quintInOut, 36 expIn, 37 expOut, 38 expInOut, 39 circIn, 40 circOut, 41 circInOut, 42 backIn, 43 backOut, 44 backInOut, 45 elasticIn, 46 elasticOut, 47 elasticInOut, 48 bounceIn, 49 bounceOut, 50 bounceInOut, 51 } 52 53 /// Returns an easing function. 54 EasingFunction getEasingFunction(Ease ease = Ease.linear) { 55 final switch (ease) with (Ease) { 56 case linear: 57 return &easeLinear; 58 case sineIn: 59 return &easeInSine; 60 case sineOut: 61 return &easeOutSine; 62 case sineInOut: 63 return &easeInOutSine; 64 case quadIn: 65 return &easeInQuad; 66 case quadOut: 67 return &easeOutQuad; 68 case quadInOut: 69 return &easeInOutQuad; 70 case cubicIn: 71 return &easeInCubic; 72 case cubicOut: 73 return &easeOutCubic; 74 case cubicInOut: 75 return &easeInOutCubic; 76 case quartIn: 77 return &easeInQuart; 78 case quartOut: 79 return &easeOutQuart; 80 case quartInOut: 81 return &easeInOutQuart; 82 case quintIn: 83 return &easeInQuint; 84 case quintOut: 85 return &easeOutQuint; 86 case quintInOut: 87 return &easeInOutQuint; 88 case expIn: 89 return &easeInExp; 90 case expOut: 91 return &easeOutExp; 92 case expInOut: 93 return &easeInOutExp; 94 case circIn: 95 return &easeInCirc; 96 case circOut: 97 return &easeOutCirc; 98 case circInOut: 99 return &easeInOutCirc; 100 case backIn: 101 return &easeInBack; 102 case backOut: 103 return &easeOutBack; 104 case backInOut: 105 return &easeInOutBack; 106 case elasticIn: 107 return &easeInElastic; 108 case elasticOut: 109 return &easeOutElastic; 110 case elasticInOut: 111 return &easeInOutElastic; 112 case bounceIn: 113 return &easeInBounce; 114 case bounceOut: 115 return &easeOutBounce; 116 case bounceInOut: 117 return &easeInOutBounce; 118 } 119 } 120 121 /// Linear 122 float easeLinear(float t) { 123 return t; 124 } 125 126 /// Sine 127 float easeInSine(float t) { 128 return sin((t - 1f) * PI_2) + 1f; 129 } 130 131 float easeOutSine(float t) { 132 return sin(t * PI_2); 133 } 134 135 float easeInOutSine(float t) { 136 return (1f - cos(t * PI)) / 2f; 137 } 138 139 //Quad 140 float easeInQuad(float t) { 141 return t * t; 142 } 143 144 float easeOutQuad(float t) { 145 return -(t * (t - 2)); 146 } 147 148 float easeInOutQuad(float t) { 149 if (t < .5f) 150 return 2f * t * t; 151 else 152 return (-2f * t * t) + (4f * t) - 1f; 153 } 154 155 //Cubic 156 float easeInCubic(float t) { 157 return t * t * t; 158 } 159 160 float easeOutCubic(float t) { 161 t = (t - 1f); 162 t = (t * t * t + 1f); 163 return t; 164 } 165 166 float easeInOutCubic(float t) { 167 if (t < .5f) 168 return 4f * t * t * t; 169 else { 170 float f = ((2f * t) - 2f); 171 return .5f * f * f * f + 1f; 172 } 173 } 174 175 //Quart 176 float easeInQuart(float t) { 177 return t * t * t * t; 178 } 179 180 float easeOutQuart(float t) { 181 float f = (t - 1f); 182 return f * f * f * (1f - t) + 1f; 183 } 184 185 float easeInOutQuart(float t) { 186 if (t < .5f) 187 return 8f * t * t * t * t; 188 else { 189 float f = (t - 1f); 190 return -8f * f * f * f * f + 1f; 191 } 192 } 193 194 //Quint 195 float easeInQuint(float t) { 196 return t * t * t * t * t; 197 } 198 199 float easeOutQuint(float t) { 200 float f = (t - 1f); 201 return f * f * f * f * f + 1f; 202 } 203 204 float easeInOutQuint(float t) { 205 if (t < .5f) 206 return 16f * t * t * t * t * t; 207 else { 208 float f = ((2f * t) - 2f); 209 return .5f * f * f * f * f * f + 1f; 210 } 211 } 212 213 //Exp 214 float easeInExp(float t) { 215 return (t == 0f) ? t : pow(2f, 10f * (t - 1f)); 216 } 217 218 float easeOutExp(float t) { 219 return (t == 1f) ? t : 1f - pow(2f, -10f * t); 220 } 221 222 float easeInOutExp(float t) { 223 if (t == 0f || t == 1f) 224 return t; 225 if (t < .5f) 226 return .5f * pow(2f, (20f * t) - 10f); 227 else 228 return -.5f * pow(2f, (-20f * t) + 10f) + 1f; 229 } 230 231 //Circ 232 float easeInCirc(float t) { 233 return 1f - sqrt(1f - (t * t)); 234 } 235 236 float easeOutCirc(float t) { 237 return sqrt((2f - t) * t); 238 } 239 240 float easeInOutCirc(float t) { 241 if (t < .5f) 242 return .5f * (1f - sqrt(1f - 4f * (t * t))); 243 else 244 return .5f * (sqrt(-((2f * t) - 3f) * ((2f * t) - 1f)) + 1f); 245 } 246 247 //Back 248 float easeInBack(float t) { 249 return t * t * t - t * sin(t * PI); 250 } 251 252 float easeOutBack(float t) { 253 float f = (1f - t); 254 return 1f - (f * f * f - f * sin(f * PI)); 255 } 256 257 float easeInOutBack(float t) { 258 if (t < .5f) { 259 t *= 2f; 260 return (t * t * t - t * sin(t * PI)) / 2f; 261 } 262 t = (1f - (2f * t - 1f)); 263 return (1f - (t * t * t - t * sin(t * PI))) / 2f + .5f; 264 } 265 266 //Elastic 267 float easeInElastic(float t) { 268 return sin(13f * PI_2 * t) * pow(2f, 10f * (t - 1f)); 269 } 270 271 float easeOutElastic(float t) { 272 return sin(-13f * PI_2 * (t + 1)) * pow(2f, -10f * t) + 1f; 273 } 274 275 float easeInOutElastic(float t) { 276 if (t < .5f) 277 return .5f * sin(13f * PI_2 * (2f * t)) * pow(2f, 10f * ((2f * t) - 1f)); 278 else 279 return .5f * (sin(-13f * PI_2 * ((2f * t - 1f) + 1f)) * pow(2f, -10f * (2f * t - 1f)) + 2f); 280 } 281 282 //bounce 283 float easeInBounce(float t) { 284 return 1f - easeOutBounce(1f - t); 285 } 286 287 float easeOutBounce(float t) { 288 if (t < 4f / 11f) 289 return (121f * t * t) / 16f; 290 else if (t < 8f / 11f) 291 return (363f / 40f * t * t) - (99f / 10f * t) + 17f / 5f; 292 else if (t < 9f / 10f) 293 return (4356f / 361f * t * t) - (35442f / 1805f * t) + 16061f / 1805f; 294 return (54f / 5f * t * t) - (513f / 25f * t) + 268f / 25f; 295 } 296 297 float easeInOutBounce(float t) { 298 if (t < .5f) 299 return easeInBounce(t * 2f) / 2f; 300 else 301 return easeOutBounce(t * 2f - 1f) / 2f + .5f; 302 }