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)
8namespace ftxui::animation {
9
10namespace easing {
11
12namespace {
13constexpr float kPi = 3.14159265358979323846f;
14constexpr 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
30float Linear(float p) {
31 return p;
32}
33
34/// @brief Modeled after the parabola y = x^2
35float QuadraticIn(float p) {
36 return p * p;
37}
38
39// @brief Modeled after the parabola y = -x^2 + 2x
40float 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]
47float 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
52float CubicIn(float p) {
53 return p * p * p;
54}
55
56// @brief Modeled after the cubic y = (x - 1)^3 + 1
57float 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]
65float 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
74float QuarticIn(float p) {
75 return p * p * p * p;
76}
77
78// @brief Modeled after the quartic y = 1 - (x - 1)^4
79float 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]
87float 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
96float QuinticIn(float p) {
97 return p * p * p * p * p;
98}
99
100// @brief Modeled after the quintic y = (x - 1)^5 + 1
101float 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]
109float 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
118float 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)
123float SineOut(float p) {
124 return std::sin(p * kPi2);
125}
126
127// @brief Modeled after half sine wave
128float 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
133float 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
138float 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]
145float 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))
153float 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
158float 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]
165float 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))
178float 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
185float 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]
192float 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)
203float 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))
208float 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]
216float 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
225float BounceIn(float p) {
226 return 1.f - BounceOut(1.f - p);
227}
228
229float 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
245float 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
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