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 * The purpose of this file is to hold implementations for the tween.h file, s 27 * pecializing on the single value case. 28 */ 29 #ifndef TWEENY_TWEENONE_TCC 30 #define TWEENY_TWEENONE_TCC 31 32 #include "tween.h" 33 #include "dispatcher.h" 34 35 namespace tweeny { from(T t)36 template<typename T> inline tween<T> tween<T>::from(T t) { return tween<T>(t); } tween()37 template<typename T> inline tween<T>::tween() { } tween(T t)38 template<typename T> inline tween<T>::tween(T t) { 39 points.emplace_back(t); 40 } 41 to(T t)42 template<typename T> inline tween<T> & tween<T>::to(T t) { 43 points.emplace_back(t); 44 return *this; 45 } 46 47 template<typename T> 48 template<typename... Fs> via(Fs...vs)49 inline tween<T> & tween<T>::via(Fs... vs) { 50 points.at(points.size() - 2).via(vs...); 51 return *this; 52 } 53 54 template<typename T> 55 template<typename... Fs> via(int index,Fs...vs)56 inline tween<T> & tween<T>::via(int index, Fs... vs) { 57 points.at(static_cast<size_t>(index)).via(vs...); 58 return *this; 59 } 60 61 template<typename T> 62 template<typename... Ds> during(Ds...ds)63 inline tween<T> & tween<T>::during(Ds... ds) { 64 total = 0; 65 points.at(points.size() - 2).during(ds...); 66 for (detail::tweenpoint<T> & p : points) { 67 total += p.duration(); 68 p.stacked = total; 69 } 70 return *this; 71 } 72 73 template<typename T> step(int32_t dt,bool suppress)74 inline const T & tween<T>::step(int32_t dt, bool suppress) { 75 return step(static_cast<float>(dt * currentDirection)/static_cast<float>(total), suppress); 76 } 77 78 template<typename T> step(uint32_t dt,bool suppress)79 inline const T & tween<T>::step(uint32_t dt, bool suppress) { 80 return step(static_cast<int32_t>(dt), suppress); 81 } 82 83 template<typename T> step(float dp,bool suppress)84 inline const T & tween<T>::step(float dp, bool suppress) { 85 seek(currentProgress + dp, true); 86 if (!suppress) dispatch(onStepCallbacks); 87 return current; 88 } 89 90 template<typename T> seek(float p,bool suppress)91 inline const T & tween<T>::seek(float p, bool suppress) { 92 p = detail::clip(p, 0.0f, 1.0f); 93 currentProgress = p; 94 render(p); 95 if (!suppress) dispatch(onSeekCallbacks); 96 return current; 97 } 98 99 template<typename T> seek(int32_t t,bool suppress)100 inline const T & tween<T>::seek(int32_t t, bool suppress) { 101 return seek(static_cast<float>(t) / static_cast<float>(total), suppress); 102 } 103 104 template<typename T> seek(uint32_t t,bool suppress)105 inline const T & tween<T>::seek(uint32_t t, bool suppress) { 106 return seek(static_cast<float>(t) / static_cast<float>(total), suppress); 107 } 108 109 template<typename T> duration() const110 inline uint32_t tween<T>::duration() const { 111 return total; 112 } 113 114 template<typename T> interpolate(float prog,unsigned point,T & value) const115 inline void tween<T>::interpolate(float prog, unsigned point, T & value) const { 116 auto & p = points.at(point); 117 uint32_t pointDuration = p.duration() - (p.stacked - (prog * static_cast<float>(total))); 118 float pointTotal = static_cast<float>(pointDuration) / static_cast<float>(p.duration()); 119 if (pointTotal > 1.0f) pointTotal = 1.0f; 120 auto easing = std::get<0>(p.easings); 121 value = easing(pointTotal, std::get<0>(p.values), std::get<0>(points.at(point+1).values)); 122 } 123 124 template<typename T> render(float p)125 inline void tween<T>::render(float p) { 126 currentPoint = pointAt(p); 127 interpolate(p, currentPoint, current); 128 } 129 130 template<typename T> onStep(typename detail::tweentraits<T>::callbackType callback)131 tween<T> & tween<T>::onStep(typename detail::tweentraits<T>::callbackType callback) { 132 onStepCallbacks.push_back(callback); 133 return *this; 134 } 135 136 template<typename T> onStep(typename detail::tweentraits<T>::noValuesCallbackType callback)137 tween<T> & tween<T>::onStep(typename detail::tweentraits<T>::noValuesCallbackType callback) { 138 onStepCallbacks.push_back([callback](tween<T> & tween, T) { return callback(tween); }); 139 return *this; 140 } 141 142 template<typename T> onStep(typename detail::tweentraits<T>::noTweenCallbackType callback)143 tween<T> & tween<T>::onStep(typename detail::tweentraits<T>::noTweenCallbackType callback) { 144 onStepCallbacks.push_back([callback](tween<T> &, T v) { return callback(v); }); 145 return *this; 146 } 147 148 template<typename T> onSeek(typename detail::tweentraits<T>::callbackType callback)149 tween<T> & tween<T>::onSeek(typename detail::tweentraits<T>::callbackType callback) { 150 onSeekCallbacks.push_back(callback); 151 return *this; 152 } 153 154 template<typename T> onSeek(typename detail::tweentraits<T>::noValuesCallbackType callback)155 tween<T> & tween<T>::onSeek(typename detail::tweentraits<T>::noValuesCallbackType callback) { 156 onSeekCallbacks.push_back([callback](tween<T> & t, T) { return callback(t); }); 157 return *this; 158 } 159 160 template<typename T> onSeek(typename detail::tweentraits<T>::noTweenCallbackType callback)161 tween<T> & tween<T>::onSeek(typename detail::tweentraits<T>::noTweenCallbackType callback) { 162 onSeekCallbacks.push_back([callback](tween<T> &, T v) { return callback(v); }); 163 return *this; 164 } 165 166 template<typename T> dispatch(std::vector<typename traits::callbackType> & cbVector)167 void tween<T>::dispatch(std::vector<typename traits::callbackType> & cbVector) { 168 std::vector<size_t> dismissed; 169 for (size_t i = 0; i < cbVector.size(); ++i) { 170 auto && cb = cbVector[i]; 171 bool dismiss = cb(*this, current); 172 if (dismiss) dismissed.push_back(i); 173 } 174 175 if (dismissed.size() > 0) { 176 for (size_t i = 0; i < dismissed.size(); ++i) { 177 size_t index = dismissed[i]; 178 cbVector[index] = cbVector.at(cbVector.size() - 1 - i); 179 } 180 cbVector.resize(cbVector.size() - dismissed.size()); 181 } 182 } 183 184 template<typename T> peek() const185 const T & tween<T>::peek() const { 186 return current; 187 } 188 189 190 template<typename T> peek(float progress) const191 T tween<T>::peek(float progress) const { 192 T value; 193 interpolate(progress, pointAt(progress), value); 194 return value; 195 } 196 197 template<typename T> peek(uint32_t time) const198 T tween<T>::peek(uint32_t time) const { 199 T value; 200 float progress = static_cast<float>(time) / static_cast<float>(total); 201 interpolate(progress, pointAt(progress), value); 202 return value; 203 } 204 205 206 template<typename T> progress() const207 float tween<T>::progress() const { 208 return currentProgress; 209 } 210 211 template<typename T> forward()212 tween<T> & tween<T>::forward() { 213 currentDirection = 1; 214 return *this; 215 } 216 217 template<typename T> backward()218 tween<T> & tween<T>::backward() { 219 currentDirection = -1; 220 return *this; 221 } 222 223 template<typename T> direction() const224 int tween<T>::direction() const { 225 return currentDirection; 226 } 227 228 template<typename T> jump(int32_t p,bool suppress)229 inline const T & tween<T>::jump(int32_t p, bool suppress) { 230 p = detail::clip(p, 0, static_cast<int>(points.size() -1)); 231 return seek(points.at(p).stacked, suppress); 232 } 233 point() const234 template<typename T> inline uint16_t tween<T>::point() const { 235 return currentPoint; 236 } 237 238 239 pointAt(float progress) const240 template<typename T> inline uint16_t tween<T>::pointAt(float progress) const { 241 uint32_t t = static_cast<uint32_t>(progress * total); 242 uint16_t point = 0; 243 while (t > points.at(point).stacked) point++; 244 if (point > 0 && t <= points.at(point - 1u).stacked) point--; 245 return point; 246 } 247 } 248 #endif //TWEENY_TWEENONE_TCC 249