1 /** 2 Grimoire 3 Copyright (c) 2017 Enalye 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising 7 from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute 11 it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; 14 you must not claim that you wrote the original software. 15 If you use this software in a product, an acknowledgment 16 in the product documentation would be appreciated but 17 is not required. 18 19 2. Altered source versions must be plainly marked as such, 20 and must not be misrepresented as being the original software. 21 22 3. This notice may not be removed or altered from any source distribution. 23 */ 24 25 module core.tween; 26 27 import std.math; 28 29 import common.all; 30 import core.util; 31 32 enum TimeMode { 33 Stopped, 34 Once, 35 Loop, 36 Bounce 37 } 38 39 struct Timer { 40 private { 41 float _time = 0f, _speed = 0f; 42 bool _isReversed = false; 43 } 44 45 TimeMode mode = TimeMode.Stopped; 46 47 @property { 48 float time() const { return _time; } 49 50 float duration() const { return _speed * nominalFps; } 51 float duration(float newDuration) { 52 if(newDuration <= 0f) { 53 _speed = 0f; 54 _time = 1f; 55 } 56 else 57 _speed = 1f / (nominalFps * newDuration); 58 return newDuration; 59 } 60 61 bool isRunning() const { return (mode != TimeMode.Stopped); } 62 63 bool isReversed() const { return _isReversed; } 64 bool isReversed(bool newIsReversed) { return _isReversed = newIsReversed; } 65 } 66 67 void start(float newDuration, TimeMode newTimeMode = TimeMode.Once) { 68 _time = 0f; 69 _isReversed = false; 70 duration(newDuration); 71 mode = newTimeMode; 72 } 73 74 void startReverse(float newDuration, TimeMode newTimeMode = TimeMode.Once) { 75 _time = 1f; 76 _isReversed = true; 77 duration(newDuration); 78 mode = newTimeMode; 79 } 80 81 void stop() { 82 mode = TimeMode.Stopped; 83 } 84 85 void update(float deltaTime) { 86 switch(mode) with(TimeMode) { 87 case Stopped: 88 break; 89 case Once: 90 if(_isReversed) { 91 if(_time > 0f) 92 _time -= _speed * deltaTime; 93 if(_time < 0f) { 94 _time = 0f; 95 mode = TimeMode.Stopped; 96 } 97 } 98 else { 99 if(_time < 1f) 100 _time += _speed * deltaTime; 101 if(_time > 1f) { 102 _time = 1f; 103 mode = TimeMode.Stopped; 104 } 105 } 106 break; 107 case Loop: 108 if(_time < 1f) 109 _time += _speed * deltaTime; 110 if(_time > 1f) 111 _time = (_time - 1f) + (_speed * deltaTime); 112 break; 113 case Bounce: 114 if(_isReversed) { 115 if(_time > 0f) 116 _time -= _speed * deltaTime; 117 if(_time < 0f) { 118 _time = -(_time - (_speed * deltaTime)); 119 _isReversed = false; 120 } 121 } 122 else { 123 if(_time < 1f) 124 _time += _speed * deltaTime; 125 if(_time > 1f) { 126 _time = 1f - ((_time - 1f) + (_speed * deltaTime)); 127 _isReversed = true; 128 } 129 } 130 break; 131 default: 132 throw new Exception("Invalid time mode"); 133 } 134 } 135 } 136 137 //Sine 138 float easeInSine(float t) { 139 return sin((t - 1f) * PI_2) + 1f; 140 } 141 142 float easeOutSine(float t) { 143 return sin(t * PI_2); 144 } 145 146 float easeInOutSine(float t) { 147 return (1f - cos(t * PI)) / 2f; 148 } 149 150 //Quad 151 float easeInQuad(float t) { 152 return t * t; 153 } 154 155 float easeOutQuad(float t) { 156 return -(t * (t - 2)); 157 } 158 159 float easeInOutQuad(float t) { 160 if(t < .5f) 161 return 2f * t * t; 162 else 163 return (-2f * t * t) + (4f * t) - 1f; 164 } 165 166 //Cubic 167 float easeInCubic(float t) { 168 return t * t * t; 169 } 170 171 float easeOutCubic(float t) { 172 t = (t - 1f); 173 t = (t * t * t + 1f); 174 return t; 175 } 176 177 float easeInOutCubic(float t) { 178 if(t < .5f) 179 return 4f * t * t * t; 180 else { 181 float f = ((2f * t) - 2f); 182 return .5f * f * f * f + 1f; 183 } 184 } 185 186 //Quart 187 float easeInQuart(float t) { 188 return t * t * t * t; 189 } 190 191 float easeOutQuart(float t) { 192 float f = (t - 1f); 193 return f * f * f * (1f - t) + 1f; 194 } 195 196 float easeInOutQuart(float t) { 197 if(t < .5f) 198 return 8f * t * t * t * t; 199 else { 200 float f = (t - 1f); 201 return -8f * f * f * f * f + 1f; 202 } 203 } 204 205 //Quint 206 float easeInQuint(float t) { 207 return t * t * t * t * t; 208 } 209 210 float easeOutQuint(float t) { 211 float f = (t - 1f); 212 return f * f * f * f * f + 1f; 213 } 214 215 float easeInOutQuint(float t) { 216 if(t < .5f) 217 return 16f * t * t * t * t * t; 218 else { 219 float f = ((2f * t) - 2f); 220 return .5f * f * f * f * f * f + 1f; 221 } 222 } 223 224 //Exp 225 float easeInExp(float t) { 226 return (t == 0f) ? t : pow(2f, 10f * (t - 1f)); 227 } 228 229 float easeOutExp(float t) { 230 return (t == 1f) ? t : 1f - pow(2f, -10f * t); 231 } 232 233 float easeInOutExp(float t) { 234 if(t == 0f || t == 1f) 235 return t; 236 if(t < .5f) 237 return .5f * pow(2f, (20f * t) - 10f); 238 else 239 return -.5f * pow(2f, (-20f * t) + 10f) + 1f; 240 } 241 242 //Circ 243 float easeInCirc(float t) { 244 return 1f - sqrt(1f - (t * t)); 245 } 246 247 float easeOutCirc(float t) { 248 return sqrt((2f - t) * t); 249 } 250 251 float easeInOutCirc(float t) { 252 if(t < .5f) 253 return .5f * (1f - sqrt(1f - 4f * (t * t))); 254 else 255 return .5f * (sqrt(-((2f * t) - 3f) * ((2f * t) - 1f)) + 1f); 256 } 257 258 //Back 259 float easeInBack(float t) { 260 return t * t * t - t * sin(t * PI); 261 } 262 263 float easeOutBack(float t) { 264 float f = (1f - t); 265 return 1f - (f * f * f - f * sin(f * PI)); 266 } 267 268 float easeInOutBack(float t) { 269 if(t < .5f) { 270 t *= 2f; 271 return (t * t * t - t * sin(t * PI)) / 2f; 272 } 273 t = (1f - (2f*t - 1f)); 274 return (1f - (t * t * t - t * sin(t * PI))) / 2f + .5f; 275 } 276 277 //Elastic 278 float easeInElastic(float t) { 279 return sin(13f * PI_2 * t) * pow(2f, 10f * (t - 1f)); 280 } 281 282 float easeOutElastic(float t) { 283 return sin(-13f * PI_2 * (t + 1)) * pow(2f, -10f * t) + 1f; 284 } 285 286 float easeInOutElastic(float t) { 287 if(t < .5f) 288 return .5f * sin(13f * PI_2 * (2f * t)) * pow(2f, 10f * ((2f * t) - 1f)); 289 else 290 return .5f * (sin(-13f * PI_2 * ((2f * t - 1f) + 1f)) * pow(2f, -10f * (2f * t - 1f)) + 2f); 291 } 292 293 //Bounce 294 float easeInBounce(float t) { 295 return 1f - easeOutBounce(1f - t); 296 } 297 298 float easeOutBounce(float t) { 299 if(t < 4f/11f) 300 return (121f * t * t)/16f; 301 else if(t < 8f/11f) 302 return (363f/40f * t * t) - (99f/10f * t) + 17f/5f; 303 else if(t < 9f/10f) 304 return (4356f/361f * t * t) - (35442f/1805f * t) + 16061f/1805f; 305 return (54f/5f * t * t) - (513f/25f * t) + 268f/25f; 306 } 307 308 float easeInOutBounce(float t) { 309 if(t < .5f) 310 return easeInBounce(t * 2f) / 2f; 311 else 312 return easeOutBounce(t * 2f - 1f) / 2f + .5f; 313 }