1 /* 2 This file is part of the Tweeny library. 3 4 Copyright (c) 2016-2018 Leonardo G. Lucena de Freitas 5 Copyright (c) 2016 Guilherme R. Costa 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy of 8 this software and associated documentation files (the "Software"), to deal in 9 the Software without restriction, including without limitation the rights to 10 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 the Software, and to permit persons to whom the Software is furnished to do so, 12 subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in all 15 copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 /** 26 * @file tween.h 27 * This file contains the core of tweeny: the main tween class. 28 */ 29 30 #ifndef TWEENY_TWEEN_H 31 #define TWEENY_TWEEN_H 32 33 #include <tuple> 34 #include <vector> 35 #include <functional> 36 37 #include "tweentraits.h" 38 #include "tweenpoint.h" 39 40 namespace tweeny { 41 /** 42 * @brief The tween class is the core class of tweeny. It controls the interpolation steps, easings and durations. 43 * 44 * It should not be constructed manually but rather from @p tweeny::from, to facilitate template argument 45 * deduction (and also to keep your code clean). 46 */ 47 template<typename T, typename... Ts> 48 class tween { 49 public: 50 /** 51 * @brief Instantiates a tween from a starting currentPoint. 52 * 53 * This is a static factory helper function to be used by @p tweeny::from. You should not use this directly. 54 * @p t The first value in the point 55 * @p vs The remaining values 56 */ 57 static tween<T, Ts...> from(T t, Ts... vs); 58 59 public: 60 /** 61 * @brief Default constructor for a tween 62 * 63 * This constructor is provided to facilitate the usage of containers of tweens (e.g, std::vector). It 64 * should not be used manually as the tweening created by it is invalid. 65 */ 66 tween(); 67 68 /** 69 * @brief Adds a new currentPoint in this tweening. 70 * 71 * This will add a new tweening currentPoint with the specified values. Next calls to @p via and @p during 72 * will refer to this currentPoint. 73 * 74 * **Example** 75 * 76 * @code 77 * auto t = tweeny::from(0).to(100).to(200); 78 * @endcode 79 * 80 * @param t, vs Point values 81 * @returns *this 82 */ 83 tween<T, Ts...> & to(T t, Ts... vs); 84 85 /** 86 * @brief Specifies the easing function for the last added currentPoint. 87 * 88 * This will specify the easing between the last tween currentPoint added by @p to and its previous step. You can 89 * use any callable object. Additionally, you can use the easing objects specified in the class @p easing. 90 * 91 * If it is a multi-value currentPoint, you can either specify a single easing function that will be used for 92 * every value or you can specify an easing function for each value. You can mix and match callable objects, 93 * lambdas and bundled easing objects. 94 * 95 * **Example**: 96 * 97 * @code 98 * // use bundled linear easing 99 * auto tween1 = tweeny::from(0).to(100).via(tweeny::easing::linear); 100 * 101 * // use custom lambda easing 102 * auto tween2 = tweeny::from(0).to(100).via([](float p, int a, int b) { return (b-a) * p + a; }); 103 * @endcode 104 * 105 * @param fs The functions 106 * @returns *this 107 * @see tweeny::easing 108 */ 109 template<typename... Fs> tween<T, Ts...> & via(Fs... fs); 110 111 /** 112 * @brief Specifies the easing function for a specific currentPoint. 113 * 114 * Points starts at index 0. The index 0 refers to the first @p to call. 115 * Using this function without adding a currentPoint with @p to leads to undefined 116 * behaviour. 117 * 118 * @param index The tween currentPoint index 119 * @param fs The functions 120 * @returns *this 121 * @see tweeny::easing 122 */ 123 template<typename... Fs> tween<T, Ts...> & via(int index, Fs... fs); 124 125 /** 126 * @brief Specifies the duration, typically in milliseconds, for the tweening of values in last currentPoint. 127 * 128 * You can either specify a single duration for all values or give every value its own duration. Value types 129 * must be convertible to the uint16_t type. 130 * 131 * **Example**: 132 * 133 * @code 134 * // Specify that the first currentPoint will be reached in 100 milliseconds and the first value in the second 135 * // currentPoint in 100, whereas the second value will be reached in 500. 136 * auto tween = tweeny::from(0, 0).to(100, 200).during(100).to(200, 300).during(100, 500); 137 * @endcode 138 * 139 * @param ds Duration values 140 * @returns *this 141 */ 142 template<typename... Ds> tween<T, Ts...> & during(Ds... ds); 143 144 /** 145 * @brief Steps the animation by the designated delta amount. 146 * 147 * You should call this every frame of your application, passing in the amount of delta time that 148 * you want to animate. 149 * 150 * **Example**: 151 * 152 * @code 153 * // tween duration is 100ms 154 * auto tween = tweeny::from(0).to(100).during(100); 155 * 156 * // steps for 16ms 157 * tween.step(16); 158 * @endcode 159 * 160 * @param dt Delta duration 161 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onStep() 162 * @returns std::tuple<Ts...> with the current tween values. 163 */ 164 const typename detail::tweentraits<T, Ts...>::valuesType & step(int32_t dt, bool suppressCallbacks = false); 165 166 /** 167 * @brief Steps the animation by the designated delta amount. 168 * 169 * You should call this every frame of your application, passing in the amount of delta time that 170 * you want to animate. This overload exists to match unsigned int arguments. 171 * 172 * @param dt Delta duration 173 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onStep() 174 * @returns std::tuple<Ts...> with the current tween values. 175 */ 176 const typename detail::tweentraits<T, Ts...>::valuesType & step(uint32_t dt, bool suppressCallbacks = false); 177 178 /** 179 * @brief Steps the animation by the designated percentage amount. 180 * 181 * You can use this function to step the tweening by a specified percentage delta. 182 183 * **Example**: 184 * 185 * @code 186 * // tween duration is 100ms 187 * auto tween = tweeny::from(0).to(100).during(100); 188 * 189 * // steps for 16ms 190 * tween.step(0.001f); 191 * @endcode 192 * 193 * @param dp Delta percentage, between `0.0f` and `1.0f` 194 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onStep() 195 * @returns std::tuple<Ts...> with the current tween values. 196 */ 197 const typename detail::tweentraits<T, Ts...>::valuesType & step(float dp, bool suppressCallbacks = false); 198 199 /** 200 * @brief Seeks to a specified currentPoint in time based on the currentProgress. 201 * 202 * This function sets the current animation time and currentProgress. Callbacks set by @p call will be triggered. 203 * 204 * @param p The percentage to seek to, between 0.0f and 1.0f, inclusive. 205 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onSeek() 206 * @returns std::tuple<Ts...> with the current tween values. 207 */ 208 const typename detail::tweentraits<T, Ts...>::valuesType & seek(float p, bool suppressCallbacks = false); 209 210 /** 211 * @brief Seeks to a specified currentPoint in time. 212 * 213 * This function sets the current animation time and currentProgress. Callbacks set by @p call will be triggered. 214 * 215 * @param d The duration to seek to, between 0 and the total duration. 216 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onSeek() 217 * @returns std::tuple<Ts...> with the current tween values. 218 * @see duration 219 */ 220 const typename detail::tweentraits<T, Ts...>::valuesType & seek(int32_t d, bool suppressCallbacks = false); 221 222 /** 223 * @brief Seeks to a specified currentPoint in time. 224 * 225 * This function sets the current animation time and currentProgress. Callbacks set by @p call will be triggered. 226 * 227 * @param d The duration to seek to, between 0 and the total duration. 228 * @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onSeek() 229 * @returns std::tuple<Ts...> with the current tween values. 230 * @see duration 231 */ 232 const typename detail::tweentraits<T, Ts...>::valuesType & seek(uint32_t d, bool suppressCallbacks = false); 233 234 /** 235 * @brief Adds a callback that will be called when stepping occurs, accepting both the tween and 236 * its values. 237 * 238 * You can add as many callbacks as you want. Its arguments types must be equal to the argument types 239 * of a tween instance, preceded by a variable of the tween type. Callbacks can be of any callable type. It will only be called 240 * via tween::step() functions. For seek callbacks, see tween::onSeek(). 241 * 242 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 243 * will also be copied with it. 244 * 245 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 246 * the callback queue. 247 * 248 * **Example**: 249 * 250 * @code 251 * auto t = tweeny:from(0).to(100).during(100); 252 * 253 * // pass a lambda 254 * t.onStep([](tweeny::tween<int> & t, int v) { printf("%d ", v); return false; }); 255 * 256 * // pass a functor instance 257 * struct ftor { void operator()(tweeny::tween<int> & t, int v) { printf("%d ", v); return false; } }; 258 * t.onStep(ftor()); 259 * @endcode 260 * @sa step 261 * @sa seek 262 * @sa onSeek 263 * @param callback A callback in with the prototype `bool callback(tween<Ts...> & t, Ts...)` 264 */ 265 tween<T, Ts...> & onStep(typename detail::tweentraits<T, Ts...>::callbackType callback); 266 267 /** 268 * @brief Adds a callback that will be called when stepping occurs, accepting only the tween. 269 * 270 * You can add as many callbacks as you want. It must receive the tween as an argument. 271 * Callbacks can be of any callable type. It will only be called 272 * via tween::step() functions. For seek callbacks, see tween::onSeek(). 273 * 274 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 275 * will also be copied with it. 276 * 277 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 278 * the callback queue. 279 * 280 * **Example**: 281 * 282 * @code 283 * auto t = tweeny:from(0).to(100).during(100); 284 * 285 * // pass a lambda 286 * t.onStep([](tweeny::tween<int> & t) { printf("%d ", t.value()); return false; }); 287 * 288 * // pass a functor instance 289 * struct ftor { void operator()(tweeny::tween<int> & t) { printf("%d ", t.values()); return false; } }; 290 * t.onStep(ftor()); 291 * @endcode 292 * @sa step 293 * @sa seek 294 * @sa onSeek 295 * @param callback A callback in the form `bool f(tween<Ts...> & t)` 296 */ 297 tween<T, Ts...> & onStep(typename detail::tweentraits<T, Ts...>::noValuesCallbackType callback); 298 299 /** 300 * @brief Adds a callback that will be called when stepping occurs, accepting only the tween values. 301 * 302 * You can add as many callbacks as you want. It must receive the tween values as an argument. 303 * Callbacks can be of any callable type. It will only be called 304 * via tween::step() functions. For seek callbacks, see tween::onSeek(). 305 * 306 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 307 * will also be copied with it. 308 * 309 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 310 * the callback queue. 311 * 312 * **Example**: 313 * 314 * @code 315 * auto t = tweeny:from(0).to(100).during(100); 316 * 317 * // pass a lambda 318 * t.onStep([](int v) { printf("%d ", v); return false; }); 319 * 320 * // pass a functor instance 321 * struct ftor { void operator()(int x) { printf("%d ", x); return false; } }; 322 * t.onStep(ftor()); 323 * @endcode 324 * @sa step 325 * @sa seek 326 * @sa onSeek 327 * @param callback A callback in the form `bool f(Ts...)` 328 */ 329 tween<T, Ts...> & onStep(typename detail::tweentraits<T, Ts...>::noTweenCallbackType callback); 330 331 /** 332 * @brief Adds a callback for that will be called when seeking occurs 333 * 334 * You can add as many callbacks as you want. Its arguments types must be equal to the argument types 335 * of a tween instance, preceded by a variable of the tween typve. Callbacks can be of any callable type. It will be called 336 * via tween::seek() functions. For step callbacks, see tween::onStep(). 337 * 338 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 339 * will also be copied with it. 340 * 341 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 342 * the callback queue. 343 * 344 * **Example**: 345 * 346 * @code 347 * auto t = t:from(0).to(100).during(100); 348 * 349 * // pass a lambda 350 * t.onSeek([](tweeny::tween<int> & t, int v) { printf("%d ", v); }); 351 * 352 * // pass a functor instance 353 * struct ftor { void operator()(tweeny::tween<int> & t, int v) { printf("%d ", v); } }; 354 * t.onSeek(ftor()); 355 * @endcode 356 * @param callback A callback in with the prototype `bool callback(tween<Ts...> & t, Ts...)` 357 */ 358 tween<T, Ts...> & onSeek(typename detail::tweentraits<T, Ts...>::callbackType callback); 359 360 /** 361 * @brief Adds a callback for that will be called when seeking occurs, accepting only the tween values. 362 * 363 * You can add as many callbacks as you want. It must receive the tween as an argument. 364 * Callbacks can be of any callable type. It will be called 365 * via tween::seek() functions. For step callbacks, see tween::onStep(). 366 * 367 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 368 * will also be copied again. 369 * 370 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 371 * the callback queue. 372 * 373 * **Example**: 374 * 375 * @code 376 * auto t = t:from(0).to(100).during(100); 377 * 378 * // pass a lambda 379 * t.onSeek([](int v) { printf("%d ", v); }); 380 * 381 * // pass a functor instance 382 * struct ftor { void operator()(int v) { printf("%d ", v); return false; } }; 383 * t.onSeek(ftor()); 384 * @endcode 385 * @param callback A callback in the form `bool f(Ts...)` 386 */ 387 tween<T, Ts...> & onSeek(typename detail::tweentraits<T, Ts...>::noTweenCallbackType callback); 388 389 /** 390 * @brief Adds a callback for that will be called when seeking occurs, accepting only the tween. 391 * 392 * You can add as many callbacks as you want. It must receive the tween as an argument. 393 * Callbacks can be of any callable type. It will be called 394 * via tween::seek() functions. For step callbacks, see tween::onStep(). 395 * 396 * Keep in mind that the function will be *copied* into an array, so any variable captured by value 397 * will also be copied again. 398 * 399 * If the callback returns false, it will be called next time. If it returns true, it will be removed from 400 * the callback queue. 401 * 402 * **Example**: 403 * 404 * @code 405 * auto t = t:from(0).to(100).during(100); 406 * 407 * // pass a lambda 408 * t.onSeek([](tweeny::tween<int> & t) { printf("%d ", t.value()); return false; }); 409 * 410 * // pass a functor instance 411 * struct ftor { void operator()(tweeny::tween<int> & t) { printf("%d ", t.value()); return false; } }; 412 * t.onSeek(ftor()); 413 * @endcode 414 * @param callback A callback in the form `bool f(tween<Ts...> & t)` 415 */ 416 tween<T, Ts...> & onSeek(typename detail::tweentraits<T, Ts...>::noValuesCallbackType callback); 417 418 /** 419 * @brief Returns the total duration of this tween 420 * 421 * @returns The duration of all the tween points. 422 */ 423 uint32_t duration() const; 424 425 /** 426 * @brief Returns the current tween values 427 * 428 * This returns the current tween value as returned by the 429 * tween::step() function, except that it does not perform a step. 430 * @returns std::tuple<Ts...> with the current tween values. 431 */ 432 const typename detail::tweentraits<T, Ts...>::valuesType & peek() const; 433 434 /** 435 * @brief Calculates and returns the tween values at a given progress 436 * 437 * This returns the tween value at the requested progress, without stepping 438 * or seeking. 439 * @returns std::tuple<Ts...> with the current tween values. 440 */ 441 const typename detail::tweentraits<T, Ts...>::valuesType peek(float progress) const; 442 443 444 /** 445 * @brief Calculates and return the tween values at a given time 446 * 447 * This returns the tween values at the requested time, without stepping 448 * or seeking. 449 * @returns std::tuple<Ts...> with the calculated tween values. 450 */ 451 const typename detail::tweentraits<T, Ts...>::valuesType peek(uint32_t time) const; 452 453 /** 454 * @brief Returns the current currentProgress of the interpolation. 455 * 456 * 0 means its at the values passed in the construction, 1 means the last step. 457 * @returns the current currentProgress between 0 and 1 (inclusive) 458 */ 459 float progress() const; 460 461 /** 462 * @brief Sets the direction of this tween forward. 463 * 464 * Note that this only affects tween::step() function. 465 * @returns *this 466 * @sa backward 467 */ 468 tween<T, Ts...> & forward(); 469 470 /** 471 * @brief Sets the direction of this tween backward. 472 * 473 * Note that this only affects tween::step() function. 474 * @returns *this 475 * @sa forward 476 */ 477 tween<T, Ts...> & backward(); 478 479 /** 480 * @brief Returns the current direction of this tween 481 * 482 * @returns -1 If it is mobin backwards in time, 1 if it is moving forward in time 483 */ 484 int direction() const; 485 486 /** 487 * @brief Jumps to a specific tween currentPoint 488 * 489 * This will seek the tween to a percentage matching the beginning of that step. 490 * 491 * @param point The currentPoint to seek to. 0 means the currentPoint passed in tweeny::from 492 * @param suppressCallbacks (optional) set to true to suppress seek() callbacks 493 * @returns current values 494 * @sa seek 495 */ 496 const typename detail::tweentraits<T, Ts...>::valuesType & jump(int32_t point, bool suppressCallbacks = false); 497 498 /** 499 * @brief Returns the current tween point 500 * 501 * @returns Current tween point 502 */ 503 uint16_t point() const; 504 505 private /* member types */: 506 using traits = detail::tweentraits<T, Ts...>; 507 508 private /* member variables */: 509 uint32_t total = 0; // total runtime 510 uint16_t currentPoint = 0; // current currentPoint 511 float currentProgress = 0; // current currentProgress 512 std::vector<detail::tweenpoint<T, Ts...>> points; 513 typename traits::valuesType current; 514 std::vector<typename traits::callbackType> onStepCallbacks; 515 std::vector<typename traits::callbackType> onSeekCallbacks; 516 int8_t currentDirection = 1; 517 518 private: 519 /* member functions */ 520 tween(T t, Ts... vs); 521 template<size_t I> void interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<I>) const; 522 void interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<0>) const; 523 void render(float p); 524 void dispatch(std::vector<typename traits::callbackType> & cbVector); 525 uint16_t pointAt(float progress) const; 526 }; 527 528 /** 529 * @brief Class specialization when a tween has a single value 530 * 531 * This class is preferred automatically by your compiler when your tween has only one value. It exists mainly 532 * so that you dont need to use std::get<0> to obtain a single value when using tween::step, tween::seek or any other 533 * value returning function. Other than that, you should look at the 534 * tweeny::tween documentation. 535 * 536 * Except for this little detail, this class methods and behaviours are exactly the same. 537 */ 538 template<typename T> 539 class tween<T> { 540 public: 541 static tween<T> from(T t); 542 543 public: 544 tween(); ///< @sa tween::tween 545 tween<T> & to(T t); ///< @sa tween::to 546 template<typename... Fs> tween<T> & via(Fs... fs); ///< @sa tween::via 547 template<typename... Fs> tween<T> & via(int index, Fs... fs); ///< @sa tween::via 548 template<typename... Ds> tween<T> & during(Ds... ds); ///< @sa tween::during 549 const T & step(int32_t dt, bool suppressCallbacks = false); ///< @sa tween::step(int32_t dt, bool suppressCallbacks) 550 const T & step(uint32_t dt, bool suppressCallbacks = false); ///< @sa tween::step(uint32_t dt, bool suppressCallbacks) 551 const T & step(float dp, bool suppressCallbacks = false); ///< @sa tween::step(float dp, bool suppressCallbacks) 552 const T & seek(float p, bool suppressCallbacks = false); ///< @sa tween::seek(float p, bool suppressCallbacks) 553 const T & seek(int32_t d, bool suppressCallbacks = false); ///< @sa tween::seek(int32_t d, bool suppressCallbacks) 554 const T & seek(uint32_t d, bool suppressCallbacks = false); ///< @sa tween::seek(uint32_t d, bool suppressCallbacks) 555 tween<T> & onStep(typename detail::tweentraits<T>::callbackType callback); ///< @sa tween::onStep 556 tween<T> & onStep(typename detail::tweentraits<T>::noValuesCallbackType callback); ///< @sa tween::onStep 557 tween<T> & onStep(typename detail::tweentraits<T>::noTweenCallbackType callback); ///< @sa tween::onStep 558 tween<T> & onSeek(typename detail::tweentraits<T>::callbackType callback); ///< @sa tween::onSeek 559 tween<T> & onSeek(typename detail::tweentraits<T>::noValuesCallbackType callback); ///< @sa tween::onSeek 560 tween<T> & onSeek(typename detail::tweentraits<T>::noTweenCallbackType callback); ///< @sa tween::onSeek 561 const T & peek() const; ///< @sa tween::peek 562 T peek(float progress) const; ///< @sa tween::peek 563 T peek(uint32_t time) const; ///< @sa tween::peek 564 uint32_t duration() const; ///< @sa tween::duration 565 float progress() const; ///< @sa tween::progress 566 tween<T> & forward(); ///< @sa tween::forward 567 tween<T> & backward(); ///< @sa tween::backward 568 int direction() const; ///< @sa tween::direction 569 const T & jump(int32_t point, bool suppressCallbacks = false); ///< @sa tween::jump 570 uint16_t point() const; ///< @sa tween::point 571 572 private /* member types */: 573 using traits = detail::tweentraits<T>; 574 575 private /* member variables */: 576 uint32_t total = 0; // total runtime 577 uint16_t currentPoint = 0; // current currentPoint 578 float currentProgress = 0; // current currentProgress 579 std::vector<detail::tweenpoint<T>> points; 580 T current; 581 std::vector<typename traits::callbackType> onStepCallbacks; 582 std::vector<typename traits::callbackType> onSeekCallbacks; 583 int8_t currentDirection = 1; 584 585 private: 586 /* member functions */ 587 tween(T t); 588 void interpolate(float prog, unsigned point, T & value) const; 589 void render(float p); 590 void dispatch(std::vector<typename traits::callbackType> & cbVector); 591 uint16_t pointAt(float progress) const; 592 }; 593 } 594 595 #include "tween.tcc" 596 #include "tweenone.tcc" 597 598 #endif //TWEENY_TWEEN_H 599