Skip to content

Commit f846d1c

Browse files
committed
elevator style easing
1 parent fb11fee commit f846d1c

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System;
2+
using Freya;
3+
4+
public class ElevatorEase {
5+
6+
public enum Mode {
7+
FastStartPolynomial,
8+
Trigonometric
9+
}
10+
11+
public readonly Mode mode;
12+
public readonly float maxDistance;
13+
public readonly float contractSpeed;
14+
public readonly float accDuration;
15+
16+
public readonly float t1;
17+
public readonly float t2;
18+
public readonly float tEnd;
19+
public readonly float v;
20+
21+
// linear section
22+
float g_c0, g_c1;
23+
24+
// polynomial coefficients used by Mode.FastStartPolynomial
25+
float f_c3, f_c4, f_c5; // ease in
26+
float h_c4, h_c5; // ease out (relative)
27+
28+
// constants used by Mode.Trigonometric
29+
float c_xsq, c_trigScale, c_trigInner;
30+
31+
public ElevatorEase( Mode mode, float maxDistance, float contractSpeed, float accDuration ) {
32+
this.mode = mode;
33+
this.maxDistance = maxDistance;
34+
this.contractSpeed = contractSpeed;
35+
this.accDuration = accDuration;
36+
37+
// derived things
38+
t1 = accDuration;
39+
t2 = maxDistance / contractSpeed;
40+
tEnd = t1 + t2;
41+
v = contractSpeed;
42+
float tHalf = tEnd / 2;
43+
if( accDuration >= tHalf ) {
44+
// no linear section - adjust accordingly
45+
t1 = t2 = tHalf;
46+
v = 2 * ( maxDistance / tEnd );
47+
}
48+
49+
// calculate coefficients
50+
g_c1 = v;
51+
if( mode == Mode.FastStartPolynomial ) {
52+
g_c0 = -2 * v * t1 / 5;
53+
float t1_2 = t1 * t1;
54+
float t1_3 = t1_2 * t1;
55+
float t1_4 = t1_2 * t1_2;
56+
f_c3 = 2 * v / t1_2;
57+
f_c4 = 2 * v / -t1_3;
58+
f_c5 = 3 * v / ( 5 * t1_4 );
59+
h_c4 = v / -t1_3;
60+
h_c5 = -3 * v / ( 5 * t1_4 );
61+
} else if( mode == Mode.Trigonometric ) {
62+
g_c0 = -v * t1 / 2;
63+
c_xsq = v / ( 2 * t1 );
64+
c_trigScale = v * t1 / ( Mathfs.TAU * Mathfs.TAU );
65+
c_trigInner = Mathfs.TAU / t1;
66+
}
67+
}
68+
69+
float EaseIn( float t ) {
70+
float x2 = t * t;
71+
72+
if( mode == Mode.FastStartPolynomial ) {
73+
float x3 = x2 * t;
74+
float x4 = x2 * x2;
75+
float x5 = x3 * x2;
76+
return f_c3 * x3 + f_c4 * x4 + f_c5 * x5;
77+
} else if( mode == Mode.Trigonometric ) {
78+
return c_xsq * x2 + c_trigScale * ( MathF.Cos( c_trigInner * t ) - 1 );
79+
}
80+
throw new NotImplementedException();
81+
}
82+
83+
float Linear( float t ) => g_c0 + g_c1 * t;
84+
85+
float EaseOut( float t ) {
86+
if( mode == Mode.FastStartPolynomial ) {
87+
// this one is asymmetric, and needs special handling
88+
float x = t - tEnd; // remap to relative
89+
float x2 = x * x;
90+
float x4 = x2 * x2;
91+
float x5 = x4 * x;
92+
return h_c4 * x4 + h_c5 * x5 + maxDistance;
93+
}
94+
95+
// same as ease-in but reversed
96+
return maxDistance - EaseIn( tEnd - t );
97+
}
98+
99+
public float Eval( float t ) {
100+
// check extremes:
101+
if( t <= 0 )
102+
return 0;
103+
if( t >= tEnd )
104+
return maxDistance;
105+
// check functions:
106+
if( t < t1 )
107+
return EaseIn( t );
108+
if( t > t2 )
109+
return EaseOut( t );
110+
return Linear( t );
111+
}
112+
113+
}

Runtime/Splines/Multi-Segment Splines/ElevatorEase.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)