QuickTween 1.4.1
Loading...
Searching...
No Matches
EaseFunctions.h
1// Copyright 2025 Juan Pablo Hernandez Mosti. All Rights Reserved.
2#pragma once
3
4#include "CoreMinimal.h"
5
6enum class QUICKTWEEN_API EEasePath : uint8
7{
8 Default,
9 Shortest,
10 Longest
11};
12
13template <typename T>
15{
16 static FORCEINLINE T Lerp(const T& A, const T& B, float Alpha, EEasePath /*Path*/)
17 {
18 return FMath::Lerp(A, B, Alpha);
19 }
20};
21
22// --- Specialization for FRotator: supports Shortest/Longest/Default ---
23template <>
24struct TEaseLerp<FRotator>
25{
26 static FORCEINLINE FRotator Lerp(const FRotator& A, const FRotator& B, float Alpha, EEasePath Path)
27 {
28 Alpha = FMath::Clamp(Alpha, 0.f, 1.f);
29 if (Alpha <= 0.f) return A;
30 if (Alpha >= 1.f) return B;
31
32 const FQuat QA = A.Quaternion();
33 FQuat QB = B.Quaternion();
34
35 float Dot = QA | QB;
36
37 if (Dot > 1.f - UE_KINDA_SMALL_NUMBER)
38 {
39 // Quats are nearly the same: use a cheap lerp and normalize.
40 FQuat R = FQuat::FastLerp(QA, QB, Alpha);
41 R.Normalize();
42 return R.Rotator();
43 }
44
45 if (Path == EEasePath::Longest)
46 {
47 // Ensure we traverse the LONG arc: we want a NEGATIVE dot for FullPath.
48 if (Dot > 0.f) { QB = -QB; }
49 const FQuat R = FQuat::SlerpFullPath(QA, QB, Alpha);
50 return R.Rotator();
51 }
52
53 // Slerp picks the shortest arc internally (flips if dot < 0).
54 const FQuat R = FQuat::Slerp(QA, QB, Alpha);
55 return R.Rotator();
56
57 }
58};
59
69template <typename T>
70class QUICKTWEEN_API FEaseFunctions
71{
72public:
82 static T Ease(T Start, T End, float Alpha, EEaseType EaseType, EEasePath Path = EEasePath::Default)
83 {
84 switch (EaseType)
85 {
86 case EEaseType::Linear:
87 return TEaseLerp<T>::Lerp(Start, End, Alpha, Path);
88 case EEaseType::InSine:
89 return EaseInSine(Start, End, Alpha, Path);
90 case EEaseType::OutSine:
91 return EaseOutSine(Start, End, Alpha, Path);
92 case EEaseType::InOutSine:
93 return EaseInOutSine(Start, End, Alpha, Path);
94 case EEaseType::InQuad:
95 return EaseInQuad(Start, End, Alpha, Path);
96 case EEaseType::OutQuad:
97 return EaseOutQuad(Start, End, Alpha, Path);
98 case EEaseType::InOutQuad:
99 return EaseInOutQuad(Start, End, Alpha, Path);
100 case EEaseType::InCubic:
101 return EaseInCubic(Start, End, Alpha, Path);
102 case EEaseType::OutCubic:
103 return EaseOutCubic(Start, End, Alpha, Path);
104 case EEaseType::InOutCubic:
105 return EaseInOutCubic(Start, End, Alpha, Path);
106 case EEaseType::InQuart:
107 return EaseInQuart(Start, End, Alpha, Path);
108 case EEaseType::OutQuart:
109 return EaseOutQuart(Start, End, Alpha, Path);
110 case EEaseType::InOutQuart:
111 return EaseInOutQuart(Start, End, Alpha, Path);
112 case EEaseType::InQuint:
113 return EaseInQuint(Start, End, Alpha, Path);
114 case EEaseType::OutQuint:
115 return EaseOutQuint(Start, End, Alpha, Path);
116 case EEaseType::InOutQuint:
117 return EaseInOutQuint(Start, End, Alpha, Path);
118 case EEaseType::InExpo:
119 return EaseInExpo(Start, End, Alpha, Path);
120 case EEaseType::OutExpo:
121 return EaseOutExpo(Start, End, Alpha, Path);
122 case EEaseType::InOutExpo:
123 return EaseInOutExpo(Start, End, Alpha, Path);
124 default: // Circ
125 return TEaseLerp<T>::Lerp(Start, End,
126 1.f - FMath::Sqrt(1.f - FMath::Pow(Alpha * 2.f - 1.f, 2.f)), Path);
127 }
128 }
129
130 static T Ease(T Start, T End, float Alpha, const UCurveFloat* EaseCurve, EEasePath Path = EEasePath::Default)
131 {
132 ensureAlways(EaseCurve);
133 return TEaseLerp<T>::Lerp(Start, End, EaseCurve->GetFloatValue(Alpha), Path);
134 }
135 // ---------------------
136 // Sine
137 // ---------------------
138
142 static T EaseInSine(T Start, T End, float Alpha, EEasePath Path)
143 {
144 return TEaseLerp<T>::Lerp(Start, End, 1.f - FMath::Cos(Alpha * PI / 2.f), Path);
145 }
146
150 static T EaseOutSine(T Start, T End, float Alpha, EEasePath Path)
151 {
152 return TEaseLerp<T>::Lerp(Start, End, FMath::Sin(Alpha * PI / 2.f), Path);
153 }
154
158 static T EaseInOutSine(T Start, T End, float Alpha, EEasePath Path)
159 {
160 return TEaseLerp<T>::Lerp(Start, End, 0.5f * (1.f - FMath::Cos(Alpha * PI)), Path);
161 }
162
163 // ---------------------
164 // Quadratic
165 // ---------------------
166
170 static T EaseInQuad(T Start, T End, float Alpha, EEasePath Path)
171 {
172 return TEaseLerp<T>::Lerp(Start, End, Alpha * Alpha, Path);
173 }
174
178 static T EaseOutQuad(T Start, T End, float Alpha, EEasePath Path)
179 {
180 return TEaseLerp<T>::Lerp(Start, End, Alpha * (2.f - Alpha), Path);
181 }
182
186 static T EaseInOutQuad(T Start, T End, float Alpha, EEasePath Path)
187 {
188 float Result = (Alpha < 0.5f)
189 ? 2.f * Alpha * Alpha
190 : -1.f + (4.f - 2.f * Alpha) * Alpha;
191 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
192 }
193
194 // ---------------------
195 // Cubic
196 // ---------------------
197
201 static T EaseInCubic(T Start, T End, float Alpha, EEasePath Path)
202 {
203 return TEaseLerp<T>::Lerp(Start, End, Alpha * Alpha * Alpha, Path);
204 }
205
209 static T EaseOutCubic(T Start, T End, float Alpha, EEasePath Path)
210 {
211 return TEaseLerp<T>::Lerp(Start, End, 1.f - FMath::Pow(1.f - Alpha, 3), Path);
212 }
213
217 static T EaseInOutCubic(T Start, T End, float Alpha, EEasePath Path)
218 {
219 float Result = (Alpha < 0.5f)
220 ? 4.f * Alpha * Alpha * Alpha
221 : 1.f - FMath::Pow(-2.f * Alpha + 2.f, 3.f) / 2.f;
222 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
223 }
224
225 // ---------------------
226 // Quartic
227 // ---------------------
228
232 static T EaseInQuart(T Start, T End, float Alpha, EEasePath Path)
233 {
234 return TEaseLerp<T>::Lerp(Start, End, FMath::Pow(Alpha, 4.f), Path);
235 }
236
240 static T EaseOutQuart(T Start, T End, float Alpha, EEasePath Path)
241 {
242 return TEaseLerp<T>::Lerp(Start, End, 1.f - FMath::Pow(1.f - Alpha, 4.f), Path);
243 }
244
248 static T EaseInOutQuart(T Start, T End, float Alpha, EEasePath Path)
249 {
250 float Result = (Alpha < 0.5f)
251 ? 8.f * FMath::Pow(Alpha, 4.f)
252 : 1.f - FMath::Pow(-2.f * Alpha + 2.f, 4.f) / 2.f;
253 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
254 }
255
256 // ---------------------
257 // Quintic
258 // ---------------------
259
263 static T EaseInQuint(T Start, T End, float Alpha, EEasePath Path)
264 {
265 return TEaseLerp<T>::Lerp(Start, End, FMath::Pow(Alpha, 5.f), Path);
266 }
267
271 static T EaseOutQuint(T Start, T End, float Alpha, EEasePath Path)
272 {
273 return TEaseLerp<T>::Lerp(Start, End, 1.f - FMath::Pow(1.f - Alpha, 5.f), Path);
274 }
275
279 static T EaseInOutQuint(T Start, T End, float Alpha, EEasePath Path)
280 {
281 float Result = (Alpha < 0.5f)
282 ? 16.f * FMath::Pow(Alpha, 5.f)
283 : 1.f - FMath::Pow(-2.f * Alpha + 2.f, 5.f) / 2.f;
284 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
285 }
286
287 // ---------------------
288 // Exponential
289 // ---------------------
290
294 static T EaseInExpo(T Start, T End, float Alpha, EEasePath Path)
295 {
296 return TEaseLerp<T>::Lerp(Start, End, (Alpha == 0.f) ? 0.f : FMath::Pow(2.f, 10.f * Alpha - 10.f), Path);
297 }
298
302 static T EaseOutExpo(T Start, T End, float Alpha, EEasePath Path)
303 {
304 return TEaseLerp<T>::Lerp(Start, End, (Alpha == 1.f) ? 1.f : 1.f - FMath::Pow(2.f, -10.f * Alpha), Path);
305 }
306
310 static T EaseInOutExpo(T Start, T End, float Alpha, EEasePath Path)
311 {
312 if (Alpha == 0.f) return Start;
313 if (Alpha == 1.f) return End;
314
315 float Result = (Alpha < 0.5f)
316 ? FMath::Pow(2.f, 20.f * Alpha - 10.f) / 2.f
317 : (2.f - FMath::Pow(2.f, -20.f * Alpha + 10.f)) / 2.f;
318
319 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
320 }
321
322 // ---------------------
323 // Circular
324 // ---------------------
325
329 static T EaseInCirc(T Start, T End, float Alpha, EEasePath Path)
330 {
331 return TEaseLerp<T>::Lerp(Start, End, 1.f - FMath::Sqrt(1.f - Alpha * Alpha), Path);
332 }
333
337 static T EaseOutCirc(T Start, T End, float Alpha, EEasePath Path)
338 {
339 return TEaseLerp<T>::Lerp(Start, End, FMath::Sqrt(1.f - FMath::Pow(Alpha - 1.f, 2.f)), Path);
340 }
341
345 static T EaseInOutCirc(T Start, T End, float Alpha, EEasePath Path)
346 {
347 float Result = (Alpha < 0.5f)
348 ? (1.f - FMath::Sqrt(1.f - 4.f * Alpha * Alpha)) / 2.f
349 : (FMath::Sqrt(1.f - FMath::Pow(-2.f * Alpha + 2.f, 2.f)) + 1.f) / 2.f;
350
351 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
352 }
353
354 // ---------------------
355 // Back
356 // ---------------------
357
361 static T EaseInBack(T Start, T End, float Alpha, EEasePath Path)
362 {
363 constexpr float C1 = 1.70158f;
364 constexpr float C3 = C1 + 1.f;
365 return TEaseLerp<T>::Lerp(Start, End, Alpha * Alpha * (C3 * Alpha - C1), Path);
366 }
367
371 static T EaseOutBack(T Start, T End, float Alpha, EEasePath Path)
372 {
373 constexpr float C1 = 1.70158f;
374 constexpr float C3 = C1 + 1.f;
375 float Inv = 1.f - Alpha;
376 return TEaseLerp<T>::Lerp(Start, End, 1.f - Inv * Inv * (C3 * Inv - C1), Path);
377 }
378
382 static T EaseInOutBack(T Start, T End, float Alpha, EEasePath Path)
383 {
384 constexpr float C1 = 1.70158f;
385 constexpr float C2 = C1 * 1.525f;
386
387 float Result = (Alpha < 0.5f)
388 ? (FMath::Pow(2.f * Alpha, 2.f) * ((C2 + 1.f) * 2.f * Alpha - C2)) / 2.f
389 : (FMath::Pow(2.f * Alpha - 2.f, 2.f) * ((C2 + 1.f) * (Alpha * 2.f - 2.f) + C2) + 2.f) / 2.f;
390
391 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
392 }
393
394 // ---------------------
395 // Elastic
396 // ---------------------
397
401 static T EaseInElastic(T Start, T End, float Alpha, EEasePath Path)
402 {
403 if (Alpha == 0.f) return Start;
404 if (Alpha == 1.f) return End;
405
406 constexpr float C4 = (2.f * PI) / 3.f;
407 float Result = -FMath::Pow(2.f, 10.f * Alpha - 10.f) * FMath::Sin((Alpha * 10.f - 10.75f) * C4);
408
409 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
410 }
411
415 static T EaseOutElastic(T Start, T End, float Alpha, EEasePath Path)
416 {
417 if (Alpha == 0.f) return Start;
418 if (Alpha == 1.f) return End;
419
420 constexpr float C4 = (2.f * PI) / 3.f;
421 float Result = FMath::Pow(2.f, -10.f * Alpha) * FMath::Sin((Alpha * 10.f - 0.75f) * C4) + 1.f;
422
423 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
424 }
425
429 static T EaseInOutElastic(T Start, T End, float Alpha, EEasePath Path)
430 {
431 if (Alpha == 0.f) return Start;
432 if (Alpha == 1.f) return End;
433
434 constexpr float C5 = (2.f * PI) / 4.5f;
435
436 float Result = (Alpha < 0.5f)
437 ? -(FMath::Pow(2.f, 20.f * Alpha - 10.f) * FMath::Sin((20.f * Alpha - 11.125f) * C5)) / 2.f
438 : (FMath::Pow(2.f, -20.f * Alpha + 10.f) * FMath::Sin((20.f * Alpha - 11.125f) * C5)) / 2.f + 1.f;
439
440 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
441 }
442
443 // ---------------------
444 // Bounce
445 // ---------------------
446
450 static T EaseOutBounce(T Start, T End, float Alpha, EEasePath Path)
451 {
452 constexpr float N1 = 7.5625f;
453 constexpr float D1 = 2.75f;
454
455 float Result;
456
457 if (Alpha < 1.f / D1)
458 {
459 Result = N1 * Alpha * Alpha;
460 }
461 else if (Alpha < 2.f / D1)
462 {
463 Alpha -= 1.5f / D1;
464 Result = N1 * Alpha * Alpha + 0.75f;
465 }
466 else if (Alpha < 2.5f / D1)
467 {
468 Alpha -= 2.25f / D1;
469 Result = N1 * Alpha * Alpha + 0.9375f;
470 }
471 else
472 {
473 Alpha -= 2.625f / D1;
474 Result = N1 * Alpha * Alpha + 0.984375f;
475 }
476
477 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
478 }
479
483 static T EaseInBounce(T Start, T End, float Alpha, EEasePath Path)
484 {
485 return TEaseLerp<T>::Lerp(Start, End, 1.f - EaseOutBounce(0.f, 1.f, 1.f - Alpha), Path);
486 }
487
491 static T EaseInOutBounce(T Start, T End, float Alpha, EEasePath Path)
492 {
493 float Result = (Alpha < 0.5f)
494 ? (1.f - EaseOutBounce(0.f, 1.f, 1.f - 2.f * Alpha)) / 2.f
495 : (1.f + EaseOutBounce(0.f, 1.f, 2.f * Alpha - 1.f)) / 2.f;
496
497 return TEaseLerp<T>::Lerp(Start, End, Result, Path);
498 }
499};
Provides a collection of static easing functions for interpolation.
Definition EaseFunctions.h:71
static T EaseInBack(T Start, T End, float Alpha, EEasePath Path)
Back ease-in interpolation.
Definition EaseFunctions.h:361
static T EaseOutQuart(T Start, T End, float Alpha, EEasePath Path)
Quartic ease-out interpolation.
Definition EaseFunctions.h:240
static T EaseInCirc(T Start, T End, float Alpha, EEasePath Path)
Circular ease-in interpolation.
Definition EaseFunctions.h:329
static T EaseInOutElastic(T Start, T End, float Alpha, EEasePath Path)
Elastic ease-in-out interpolation.
Definition EaseFunctions.h:429
static T EaseInOutQuint(T Start, T End, float Alpha, EEasePath Path)
Quintic ease-in-out interpolation.
Definition EaseFunctions.h:279
static T EaseOutCubic(T Start, T End, float Alpha, EEasePath Path)
Cubic ease-out interpolation.
Definition EaseFunctions.h:209
static T EaseInQuint(T Start, T End, float Alpha, EEasePath Path)
Quintic ease-in interpolation.
Definition EaseFunctions.h:263
static T EaseOutElastic(T Start, T End, float Alpha, EEasePath Path)
Elastic ease-out interpolation.
Definition EaseFunctions.h:415
static T EaseInQuad(T Start, T End, float Alpha, EEasePath Path)
Quadratic ease-in interpolation.
Definition EaseFunctions.h:170
static T EaseOutQuad(T Start, T End, float Alpha, EEasePath Path)
Quadratic ease-out interpolation.
Definition EaseFunctions.h:178
static T EaseOutExpo(T Start, T End, float Alpha, EEasePath Path)
Exponential ease-out interpolation.
Definition EaseFunctions.h:302
static T EaseInOutCubic(T Start, T End, float Alpha, EEasePath Path)
Cubic ease-in-out interpolation.
Definition EaseFunctions.h:217
static T EaseOutBack(T Start, T End, float Alpha, EEasePath Path)
Back ease-out interpolation.
Definition EaseFunctions.h:371
static T EaseInSine(T Start, T End, float Alpha, EEasePath Path)
Sine ease-in interpolation.
Definition EaseFunctions.h:142
static T EaseInOutQuart(T Start, T End, float Alpha, EEasePath Path)
Quartic ease-in-out interpolation.
Definition EaseFunctions.h:248
static T EaseOutCirc(T Start, T End, float Alpha, EEasePath Path)
Circular ease-out interpolation.
Definition EaseFunctions.h:337
static T EaseOutBounce(T Start, T End, float Alpha, EEasePath Path)
Bounce ease-out interpolation.
Definition EaseFunctions.h:450
static T EaseInQuart(T Start, T End, float Alpha, EEasePath Path)
Quartic ease-in interpolation.
Definition EaseFunctions.h:232
static T EaseInOutQuad(T Start, T End, float Alpha, EEasePath Path)
Quadratic ease-in-out interpolation.
Definition EaseFunctions.h:186
static T EaseInCubic(T Start, T End, float Alpha, EEasePath Path)
Cubic ease-in interpolation.
Definition EaseFunctions.h:201
static T EaseInExpo(T Start, T End, float Alpha, EEasePath Path)
Exponential ease-in interpolation.
Definition EaseFunctions.h:294
static T EaseInOutBounce(T Start, T End, float Alpha, EEasePath Path)
Bounce ease-in-out interpolation.
Definition EaseFunctions.h:491
static T EaseInOutBack(T Start, T End, float Alpha, EEasePath Path)
Back ease-in-out interpolation.
Definition EaseFunctions.h:382
static T EaseInOutCirc(T Start, T End, float Alpha, EEasePath Path)
Circular ease-in-out interpolation.
Definition EaseFunctions.h:345
static T EaseInElastic(T Start, T End, float Alpha, EEasePath Path)
Elastic ease-in interpolation.
Definition EaseFunctions.h:401
static T EaseInBounce(T Start, T End, float Alpha, EEasePath Path)
Bounce ease-in interpolation.
Definition EaseFunctions.h:483
static T EaseOutQuint(T Start, T End, float Alpha, EEasePath Path)
Quintic ease-out interpolation.
Definition EaseFunctions.h:271
static T EaseInOutExpo(T Start, T End, float Alpha, EEasePath Path)
Exponential ease-in-out interpolation.
Definition EaseFunctions.h:310
static T EaseOutSine(T Start, T End, float Alpha, EEasePath Path)
Sine ease-out interpolation.
Definition EaseFunctions.h:150
static T Ease(T Start, T End, float Alpha, EEaseType EaseType, EEasePath Path=EEasePath::Default)
Interpolates between Start and End using the specified easing type.
Definition EaseFunctions.h:82
static T EaseInOutSine(T Start, T End, float Alpha, EEasePath Path)
Sine ease-in-out interpolation.
Definition EaseFunctions.h:158
Definition EaseFunctions.h:15