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