FTXUI  5.0.0
C++ functional terminal UI.
animation.cpp
Go to the documentation of this file.
1 #include <cmath> // for sin, pow, sqrt, cos
2 #include <ratio> // for ratio
3 #include <utility> // for move
4 
6 
7 // NOLINTBEGIN(*-magic-numbers)
8 namespace ftxui::animation {
9 
10 namespace easing {
11 
12 namespace {
13 constexpr float kPi = 3.14159265358979323846f;
14 constexpr float kPi2 = kPi / 2.f;
15 } // namespace
16 
17 // Easing function have been taken out of:
18 // https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
19 //
20 // Corresponding license:
21 // Copyright (c) 2011, Auerhaus Development, LLC
22 //
23 // This program is free software. It comes without any warranty, to
24 // the extent permitted by applicable law. You can redistribute it
25 // and/or modify it under the terms of the Do What The Fuck You Want
26 // To Public License, Version 2, as published by Sam Hocevar. See
27 // http://sam.zoy.org/wtfpl/COPYING for more details.
28 
29 /// @brief Modeled after the line y = x
30 float Linear(float p) {
31  return p;
32 }
33 
34 /// @brief Modeled after the parabola y = x^2
35 float QuadraticIn(float p) {
36  return p * p;
37 }
38 
39 // @brief Modeled after the parabola y = -x^2 + 2x
40 float QuadraticOut(float p) {
41  return -(p * (p - 2.f));
42 }
43 
44 // @brief Modeled after the piecewise quadratic
45 // y = (1/2)((2x)^2) ; [0, 0.5)
46 // y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
47 float QuadraticInOut(float p) {
48  return p < 0.5f ? 2.f * p * p : (-2.f * p * p) + (4.f * p) - 1.f;
49 }
50 
51 // @brief Modeled after the cubic y = x^3
52 float CubicIn(float p) {
53  return p * p * p;
54 }
55 
56 // @brief Modeled after the cubic y = (x - 1)^3 + 1
57 float CubicOut(float p) {
58  const float f = (p - 1.f);
59  return f * f * f + 1.f;
60 }
61 
62 // @brief Modeled after the piecewise cubic
63 // y = (1/2)((2x)^3) ; [0, 0.5)
64 // y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
65 float CubicInOut(float p) {
66  if (p < 0.5f) {
67  return 4.f * p * p * p;
68  }
69  const float f = ((2.f * p) - 2.f);
70  return 0.5f * f * f * f + 1.f;
71 }
72 
73 // @brief Modeled after the quartic x^4
74 float QuarticIn(float p) {
75  return p * p * p * p;
76 }
77 
78 // @brief Modeled after the quartic y = 1 - (x - 1)^4
79 float QuarticOut(float p) {
80  const float f = (p - 1.f);
81  return f * f * f * (1.f - p) + 1.f;
82 }
83 
84 // @brief Modeled after the piecewise quartic
85 // y = (1/2)((2x)^4) ; [0, 0.5)
86 // y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
87 float QuarticInOut(float p) {
88  if (p < 0.5f) {
89  return 8.f * p * p * p * p;
90  }
91  const float f = (p - 1.f);
92  return -8.f * f * f * f * f + 1.f;
93 }
94 
95 // @brief Modeled after the quintic y = x^5
96 float QuinticIn(float p) {
97  return p * p * p * p * p;
98 }
99 
100 // @brief Modeled after the quintic y = (x - 1)^5 + 1
101 float QuinticOut(float p) {
102  const float f = (p - 1.f);
103  return f * f * f * f * f + 1.f;
104 }
105 
106 // @brief Modeled after the piecewise quintic
107 // y = (1/2)((2x)^5) ; [0, 0.5)
108 // y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
109 float QuinticInOut(float p) {
110  if (p < 0.5f) {
111  return 16.f * p * p * p * p * p;
112  }
113  const float f = ((2.f * p) - 2.f);
114  return 0.5f * f * f * f * f * f + 1.f;
115 }
116 
117 // @brief Modeled after quarter-cycle of sine wave
118 float SineIn(float p) {
119  return std::sin((p - 1.f) * kPi2) + 1.f;
120 }
121 
122 // @brief Modeled after quarter-cycle of sine wave (different phase)
123 float SineOut(float p) {
124  return std::sin(p * kPi2);
125 }
126 
127 // @brief Modeled after half sine wave
128 float SineInOut(float p) {
129  return 0.5f * (1.f - std::cos(p * kPi));
130 }
131 
132 // @brief Modeled after shifted quadrant IV of unit circle
133 float CircularIn(float p) {
134  return 1.f - std::sqrt(1.f - (p * p));
135 }
136 
137 // @brief Modeled after shifted quadrant II of unit circle
138 float CircularOut(float p) {
139  return std::sqrt((2.f - p) * p);
140 }
141 
142 // @brief Modeled after the piecewise circular function
143 // y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
144 // y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
145 float CircularInOut(float p) {
146  if (p < 0.5f) {
147  return 0.5f * (1.f - std::sqrt(1.f - 4.f * (p * p)));
148  }
149  return 0.5f * (std::sqrt(-((2.f * p) - 3.f) * ((2.f * p) - 1.f)) + 1.f);
150 }
151 
152 // @brief Modeled after the exponential function y = 2^(10(x - 1))
153 float ExponentialIn(float p) {
154  return (p == 0.f) ? p : std::pow(2.f, 10.f * (p - 1.f));
155 }
156 
157 // @brief Modeled after the exponential function y = -2^(-10x) + 1
158 float ExponentialOut(float p) {
159  return (p == 1.f) ? p : 1.f - std::pow(2.f, -10.f * p);
160 }
161 
162 // @brief Modeled after the piecewise exponential
163 // y = (1/2)2^(10(2x - 1)) ; [0,0.5)
164 // y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
165 float ExponentialInOut(float p) {
166  if (p == 0.f || p == 1.f) {
167  return p;
168  }
169 
170  if (p < 0.5f) {
171  return 0.5f * std::pow(2.f, (20.f * p) - 10.f);
172  }
173  return -0.5f * std::pow(2.f, (-20.f * p) + 10.f) + 1.f;
174 }
175 
176 // @brief Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x -
177 // 1))
178 float ElasticIn(float p) {
179  return std::sin(13.f * kPi2 * p) * std::pow(2.f, 10.f * (p - 1.f));
180 }
181 
182 // @brief Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2,
183 // -10x) +
184 // 1
185 float ElasticOut(float p) {
186  return std::sin(-13.f * kPi2 * (p + 1.f)) * std::pow(2.f, -10.f * p) + 1.f;
187 }
188 
189 // @brief Modeled after the piecewise exponentially-damped sine wave:
190 // y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
191 // y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
192 float ElasticInOut(float p) {
193  if (p < 0.5f) {
194  return 0.5f * std::sin(13.f * kPi2 * (2.f * p)) *
195  std::pow(2.f, 10.f * ((2.f * p) - 1.f));
196  }
197  return 0.5f * (std::sin(-13.f * kPi2 * ((2.f * p - 1.f) + 1.f)) *
198  std::pow(2.f, -10.f * (2.f * p - 1.f)) +
199  2.f);
200 }
201 
202 // @brief Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
203 float BackIn(float p) {
204  return p * p * p - p * std::sin(p * kPi);
205 }
206 
207 // @brief Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
208 float BackOut(float p) {
209  const float f = (1.f - p);
210  return 1.f - (f * f * f - f * std::sin(f * kPi));
211 }
212 
213 // @brief Modeled after the piecewise overshooting cubic function:
214 // y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
215 // y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
216 float BackInOut(float p) {
217  if (p < 0.5f) {
218  const float f = 2.f * p;
219  return 0.5f * (f * f * f - f * std::sin(f * kPi));
220  }
221  const float f = (1.f - (2.f * p - 1.f));
222  return 0.5f * (1.f - (f * f * f - f * std::sin(f * kPi))) + 0.5f;
223 }
224 
225 float BounceIn(float p) {
226  return 1.f - BounceOut(1.f - p);
227 }
228 
229 float BounceOut(float p) {
230  if (p < 4.f / 11.f) {
231  return (121.f * p * p) / 16.f;
232  }
233 
234  if (p < 8.f / 11.f) {
235  return (363.f / 40.f * p * p) - (99.f / 10.f * p) + 17.f / 5.f;
236  }
237 
238  if (p < 9.f / 10.f) {
239  return (4356.f / 361.f * p * p) - (35442.f / 1805.f * p) + 16061.f / 1805.f;
240  }
241 
242  return (54.f / 5.f * p * p) - (513 / 25.f * p) + 268 / 25.f;
243 }
244 
245 float BounceInOut(float p) {
246  if (p < 0.5f) {
247  return 0.5f * BounceIn(p * 2.f);
248  }
249  return 0.5f * BounceOut(p * 2.f - 1.f) + 0.5f;
250 }
251 
252 } // namespace easing
253 
254 Animator::Animator(float* from,
255  float to,
256  Duration duration,
257  easing::Function easing_function,
258  Duration delay)
259  : value_(from),
260  from_(*from),
261  to_(to),
262  duration_(duration),
263  easing_function_(std::move(easing_function)),
264  current_(-delay) {
266 }
267 
269  current_ += params.duration();
270 
271  if (current_ >= duration_) {
272  *value_ = to_;
273  return;
274  }
275 
276  if (current_ <= Duration()) {
277  *value_ = from_;
278  } else {
279  *value_ = from_ + (to_ - from_) * easing_function_(current_ / duration_);
280  }
281 
283 }
284 
285 } // namespace ftxui::animation
286 
287 // NOLINTEND(*-magic-numbers)
Animator(float *from, float to=0.f, Duration duration=std::chrono::milliseconds(250), easing::Function easing_function=easing::Linear, Duration delay=std::chrono::milliseconds(0))
Definition: animation.cpp:254
void OnAnimation(Params &)
Definition: animation.cpp:268
Duration duration() const
The duration this animation step represents.
Definition: animation.hpp:32
float ElasticIn(float p)
Definition: animation.cpp:178
float CircularInOut(float p)
Definition: animation.cpp:145
float SineInOut(float p)
Definition: animation.cpp:128
float BounceInOut(float p)
Definition: animation.cpp:245
float CubicIn(float p)
Definition: animation.cpp:52
float CubicInOut(float p)
Definition: animation.cpp:65
float Linear(float p)
Modeled after the line y = x.
Definition: animation.cpp:30
float BounceIn(float p)
Definition: animation.cpp:225
float CircularOut(float p)
Definition: animation.cpp:138
float BackOut(float p)
Definition: animation.cpp:208
float BackInOut(float p)
Definition: animation.cpp:216
float ExponentialInOut(float p)
Definition: animation.cpp:165
float ElasticInOut(float p)
Definition: animation.cpp:192
float QuarticInOut(float p)
Definition: animation.cpp:87
float QuadraticInOut(float p)
Definition: animation.cpp:47
float QuarticOut(float p)
Definition: animation.cpp:79
float SineOut(float p)
Definition: animation.cpp:123
float CircularIn(float p)
Definition: animation.cpp:133
float ExponentialOut(float p)
Definition: animation.cpp:158
float QuadraticOut(float p)
Definition: animation.cpp:40
float QuinticOut(float p)
Definition: animation.cpp:101
float QuadraticIn(float p)
Modeled after the parabola y = x^2.
Definition: animation.cpp:35
float ExponentialIn(float p)
Definition: animation.cpp:153
float QuinticIn(float p)
Definition: animation.cpp:96
float BounceOut(float p)
Definition: animation.cpp:229
float CubicOut(float p)
Definition: animation.cpp:57
float ElasticOut(float p)
Definition: animation.cpp:185
std::function< float(float)> Function
Definition: animation.hpp:39
float BackIn(float p)
Definition: animation.cpp:203
float SineIn(float p)
Definition: animation.cpp:118
float QuarticIn(float p)
Definition: animation.cpp:74
float QuinticInOut(float p)
Definition: animation.cpp:109
std::chrono::duration< float > Duration
Definition: animation.hpp:24