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