| 1 | module easing |
| 2 | |
| 3 | // Easing functions specify the value of a property, given a level of completeness from 0.0 to 1.0 . |
| 4 | // The names of the easing functions here, are based on the ones from https://easings.net/ and |
| 5 | // https://nicmulvaney.com/easing . |
| 6 | import math { cos, pow, sin, sqrt } |
| 7 | |
| 8 | const pi = math.pi |
| 9 | const pi_half = pi / 2.0 |
| 10 | const pi_double = pi * 2.0 |
| 11 | const c1 = 1.70158 |
| 12 | const c2 = c1 * 1.525 |
| 13 | const c3 = c1 + 1.0 |
| 14 | const c4 = pi_double / 3.0 |
| 15 | const c5 = pi_double / 4.5 |
| 16 | const n1 = 7.5625 |
| 17 | const d1 = 2.75 |
| 18 | |
| 19 | // EasingFN defines the common shape of an easing function, so that you can define your own, and pass them everywhere, |
| 20 | // that expects easing.EasingFN . It is just a function that accepts a floating point number and returns one too. |
| 21 | pub type EasingFN = fn (x f64) f64 |
| 22 | |
| 23 | // linear just returns the parameter x, without changes . |
| 24 | @[inline] |
| 25 | pub fn linear(x f64) f64 { |
| 26 | return x |
| 27 | } |
| 28 | |
| 29 | // in_sine returns the equivalent of https://easings.net/#easeInSine . |
| 30 | @[inline] |
| 31 | pub fn in_sine(x f64) f64 { |
| 32 | return 1.0 - cos(x * pi_half) |
| 33 | } |
| 34 | |
| 35 | // out_sine returns the equivalent of https://easings.net/#easeOutSine . |
| 36 | @[inline] |
| 37 | pub fn out_sine(x f64) f64 { |
| 38 | return sin(x * pi_half) |
| 39 | } |
| 40 | |
| 41 | // in_out_sine returns the equivalent of https://easings.net/#easeInOutSine . |
| 42 | @[inline] |
| 43 | pub fn in_out_sine(x f64) f64 { |
| 44 | return -(cos(pi * x) - 1.0) / 2.0 |
| 45 | } |
| 46 | |
| 47 | // in_quad returns the equivalent of https://easings.net/#easeInQuad . |
| 48 | @[inline] |
| 49 | pub fn in_quad(x f64) f64 { |
| 50 | return x * x |
| 51 | } |
| 52 | |
| 53 | // out_quad returns the equivalent of https://easings.net/#easeOutQuad . |
| 54 | @[inline] |
| 55 | pub fn out_quad(x f64) f64 { |
| 56 | return 1.0 - (1.0 - x) * (1.0 - x) |
| 57 | } |
| 58 | |
| 59 | // in_out_quad returns the equivalent of https://easings.net/#easeInOutQuad . |
| 60 | @[inline] |
| 61 | pub fn in_out_quad(x f64) f64 { |
| 62 | return if x < 0.5 { 2.0 * x * x } else { 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0 } |
| 63 | } |
| 64 | |
| 65 | // in_cubic returns the equivalent of https://easings.net/#easeInCubic . |
| 66 | @[inline] |
| 67 | pub fn in_cubic(x f64) f64 { |
| 68 | return x * x * x |
| 69 | } |
| 70 | |
| 71 | // out_cubic returns the equivalent of https://easings.net/#easeOutCubic . |
| 72 | @[inline] |
| 73 | pub fn out_cubic(x f64) f64 { |
| 74 | return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x) |
| 75 | } |
| 76 | |
| 77 | // in_out_cubic returns the equivalent of https://easings.net/#easeInOutCubic . |
| 78 | @[inline] |
| 79 | pub fn in_out_cubic(x f64) f64 { |
| 80 | return if x < .5 { |
| 81 | 4.0 * x * x * x |
| 82 | } else { |
| 83 | 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0 |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | // in_quart returns the equivalent of https://easings.net/#easeInQuart . |
| 88 | @[inline] |
| 89 | pub fn in_quart(x f64) f64 { |
| 90 | return x * x * x * x |
| 91 | } |
| 92 | |
| 93 | // out_quart returns the equivalent of https://easings.net/#easeOutQuart . |
| 94 | @[inline] |
| 95 | pub fn out_quart(x f64) f64 { |
| 96 | return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x) |
| 97 | } |
| 98 | |
| 99 | // in_out_quart returns the equivalent of https://easings.net/#easeInOutQuart . |
| 100 | @[inline] |
| 101 | pub fn in_out_quart(x f64) f64 { |
| 102 | return if x < 0.5 { |
| 103 | 8.0 * x * x * x * x |
| 104 | } else { |
| 105 | 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0 |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | // in_quint returns the equivalent of https://easings.net/#easeInQuint . |
| 110 | @[inline] |
| 111 | pub fn in_quint(x f64) f64 { |
| 112 | return x * x * x * x * x |
| 113 | } |
| 114 | |
| 115 | // out_quint returns the equivalent of https://easings.net/#easeOutQuint . |
| 116 | @[inline] |
| 117 | pub fn out_quint(x f64) f64 { |
| 118 | return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x) |
| 119 | } |
| 120 | |
| 121 | // in_out_quint returns the equivalent of https://easings.net/#easeInOutQuint . |
| 122 | @[inline] |
| 123 | pub fn in_out_quint(x f64) f64 { |
| 124 | return if x < 0.5 { |
| 125 | 16.0 * x * x * x * x * x |
| 126 | } else { |
| 127 | 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0 |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | // in_expo returns the equivalent of https://easings.net/#easeInExpo . |
| 132 | @[inline] |
| 133 | pub fn in_expo(x f64) f64 { |
| 134 | return if math.close(x, 0.0) { 0.0 } else { pow(2.0, 10.0 * x - 10.0) } |
| 135 | } |
| 136 | |
| 137 | // out_expo returns the equivalent of https://easings.net/#easeOutExpo . |
| 138 | @[inline] |
| 139 | pub fn out_expo(x f64) f64 { |
| 140 | return if math.close(x, 1.0) { 1.0 } else { 1.0 - pow(2, -10.0 * x) } |
| 141 | } |
| 142 | |
| 143 | // in_out_expo returns the equivalent of https://easings.net/#easeInOutExpo . |
| 144 | @[inline] |
| 145 | pub fn in_out_expo(x f64) f64 { |
| 146 | return if math.close(x, 0.0) { |
| 147 | 0.0 |
| 148 | } else if math.close(x, 1.0) { |
| 149 | 1.0 |
| 150 | } else if x < 0.5 { |
| 151 | pow(2.0, 20.0 * x - 10.0) / 2.0 |
| 152 | } else { |
| 153 | (2.0 - pow(2.0, 10.0 - 20.0 * x)) / 2.0 |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | // in_circ returns the equivalent of https://easings.net/#easeInCirc . |
| 158 | @[inline] |
| 159 | pub fn in_circ(x f64) f64 { |
| 160 | return 1.0 - sqrt(1.0 - x * x) |
| 161 | } |
| 162 | |
| 163 | // out_circ returns the equivalent of https://easings.net/#easeOutCirc . |
| 164 | @[inline] |
| 165 | pub fn out_circ(x f64) f64 { |
| 166 | return sqrt(1.0 - pow(x - 1.0, 2.0)) |
| 167 | } |
| 168 | |
| 169 | // in_out_circ returns the equivalent of https://easings.net/#easeInOutCirc . |
| 170 | @[inline] |
| 171 | pub fn in_out_circ(x f64) f64 { |
| 172 | return if x < 0.5 { |
| 173 | (1.0 - sqrt(1.0 - pow(2.0 * x, 2.0))) / 2.0 |
| 174 | } else { |
| 175 | (sqrt(1.0 - pow(-2.0 * x + 2.0, 2.0)) + 1.0) / 2.0 |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | // in_back returns the equivalent of https://easings.net/#easeInBack . |
| 180 | @[inline] |
| 181 | pub fn in_back(x f64) f64 { |
| 182 | return c3 * x * x * x - c1 * x * x |
| 183 | } |
| 184 | |
| 185 | // out_back returns the equivalent of https://easings.net/#easeOutBack . |
| 186 | @[inline] |
| 187 | pub fn out_back(x f64) f64 { |
| 188 | return 1.0 + c3 * pow(x - 1.0, 3.0) + c1 * pow(x - 1.0, 2.0) |
| 189 | } |
| 190 | |
| 191 | // in_out_back returns the equivalent of https://easings.net/#easeInOutBack . |
| 192 | @[inline] |
| 193 | pub fn in_out_back(x f64) f64 { |
| 194 | return if x < 0.5 { |
| 195 | (pow(2.0 * x, 2.0) * ((c2 + 1) * 2.0 * x - c2)) / 2.0 |
| 196 | } else { |
| 197 | (pow(2.0 * x - 2.0, 2.0) * ((c2 + 1.0) * (x * 2.0 - 2.0) + c2) + 2.0) / 2.0 |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | // in_elastic returns the equivalent of https://easings.net/#easeInElastic . |
| 202 | @[inline] |
| 203 | pub fn in_elastic(x f64) f64 { |
| 204 | return if math.close(x, 0.0) { |
| 205 | 0.0 |
| 206 | } else if math.close(x, 1.0) { |
| 207 | 1.0 |
| 208 | } else { |
| 209 | -pow(2.0, 10.0 * x - 10.0) * sin((x * 10.0 - 10.75) * c4) |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | // out_elastic returns the equivalent of https://easings.net/#easeOutElastic . |
| 214 | @[inline] |
| 215 | pub fn out_elastic(x f64) f64 { |
| 216 | return if math.close(x, 0.0) { |
| 217 | 0.0 |
| 218 | } else if math.close(x, 1.0) { |
| 219 | 1.0 |
| 220 | } else { |
| 221 | pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * c4) + 1.0 |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | // in_out_elastic returns the equivalent of https://easings.net/#easeInOutElastic . |
| 226 | @[inline] |
| 227 | pub fn in_out_elastic(x f64) f64 { |
| 228 | return if math.close(x, 0.0) { |
| 229 | 0.0 |
| 230 | } else if math.close(x, 1.0) { |
| 231 | 1.0 |
| 232 | } else if x < 0.5 { |
| 233 | -(pow(2.0, 20.0 * x - 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0 |
| 234 | } else { |
| 235 | (pow(2.0, -20.0 * x + 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0 + 1.0 |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | // in_bounce returns the equivalent of https://easings.net/#easeInBounce . |
| 240 | @[inline] |
| 241 | pub fn in_bounce(x f64) f64 { |
| 242 | return 1.0 - out_bounce(1.0 - x) |
| 243 | } |
| 244 | |
| 245 | // out_bounce returns the equivalent of https://easings.net/#easeOutBounce . |
| 246 | pub fn out_bounce(x f64) f64 { |
| 247 | xd1 := x * d1 |
| 248 | return if xd1 < 1.0 { |
| 249 | n1 * x * x |
| 250 | } else if xd1 < 2.0 { |
| 251 | n1 * pow(x - 1.5 / d1, 2.0) + 0.75 |
| 252 | } else if xd1 < 2.5 { |
| 253 | n1 * pow(x - 2.25 / d1, 2.0) + 0.9375 |
| 254 | } else { |
| 255 | n1 * pow(x - 2.625 / d1, 2.0) + 0.984375 |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | // in_out_bounce returns the equivalent of https://easings.net/#easeInOutBounce . |
| 260 | pub fn in_out_bounce(x f64) f64 { |
| 261 | return if x < 0.5 { |
| 262 | (1.0 - out_bounce(1.0 - 2.0 * x)) / 2.0 |
| 263 | } else { |
| 264 | (1.0 + out_bounce(2.0 * x - 1.0)) / 2.0 |
| 265 | } |
| 266 | } |
| 267 | |