Easing.cs 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. using System;
  3. using static UnityEngine.Mathf;
  4. using NormalizedDelegate = System.Func<float, float>;
  5. namespace Animancer
  6. {
  7. /// <summary>A set of common <see href="https://easings.net">easing functions</see>.</summary>
  8. /// <remarks>
  9. /// There are several different types of functions:
  10. /// <list type="bullet">
  11. /// <item>In: accelerating from zero velocity.</item>
  12. /// <item>Out: decelerating to zero velocity.</item>
  13. /// <item>InOut: uses the corresponding In function until halfway, then the Out function after that.</item>
  14. /// <item>Normalized: methods with a single parameter (<see cref="float"/> value) expect values from 0 to 1.</item>
  15. /// <item>Ranged: methods with 3 parameters (<see cref="float"/> start, <see cref="float"/> end,
  16. /// <see cref="float"/> value) use the specified range instead ot 0 to 1.</item>
  17. /// <item>Derivative: calculates the gradient of their corresponding non-derivative function.
  18. /// The more complex derivative functions were made with 'https://www.derivative-calculator.net'.</item>
  19. /// </list>
  20. /// </remarks>
  21. /// https://kybernetik.com.au/animancer/api/Animancer/Easing
  22. ///
  23. public static class Easing
  24. {
  25. /************************************************************************************************************************/
  26. #region Delegates
  27. /************************************************************************************************************************/
  28. /// <summary>The natural log of 2.</summary>
  29. public const float Ln2 = 0.693147180559945f;
  30. /************************************************************************************************************************/
  31. /// <summary>A variant of a <see cref="NormalizedDelegate"/> with a custom range instead of 0 to 1.</summary>
  32. public delegate float RangedDelegate(float start, float end, float value);
  33. /************************************************************************************************************************/
  34. /// <summary>The name of an easing function.</summary>
  35. /// <remarks>The <see cref="Easing"/> class contains various extension methods for this enum.</remarks>
  36. /// https://kybernetik.com.au/animancer/api/Animancer/Function
  37. ///
  38. public enum Function
  39. {
  40. /// <summary><see cref="Easing.Linear(float)"/></summary>
  41. Linear,
  42. /// <summary><see cref="Quadratic.In(float)"/></summary>
  43. QuadraticIn,
  44. /// <summary><see cref="Quadratic.Out(float)"/></summary>
  45. QuadraticOut,
  46. /// <summary><see cref="Quadratic.InOut(float)"/></summary>
  47. QuadraticInOut,
  48. /// <summary><see cref="Cubic.In(float)"/></summary>
  49. CubicIn,
  50. /// <summary><see cref="Cubic.Out(float)"/></summary>
  51. CubicOut,
  52. /// <summary><see cref="Cubic.InOut(float)"/></summary>
  53. CubicInOut,
  54. /// <summary><see cref="Quartic.In(float)"/></summary>
  55. QuarticIn,
  56. /// <summary><see cref="Quartic.Out(float)"/></summary>
  57. QuarticOut,
  58. /// <summary><see cref="Quartic.InOut(float)"/></summary>
  59. QuarticInOut,
  60. /// <summary><see cref="Quintic.In(float)"/></summary>
  61. QuinticIn,
  62. /// <summary><see cref="Quintic.Out(float)"/></summary>
  63. QuinticOut,
  64. /// <summary><see cref="Quintic.InOut(float)"/></summary>
  65. QuinticInOut,
  66. /// <summary><see cref="Sine.In(float)"/></summary>
  67. SineIn,
  68. /// <summary><see cref="Sine.Out(float)"/></summary>
  69. SineOut,
  70. /// <summary><see cref="Sine.InOut(float)"/></summary>
  71. SineInOut,
  72. /// <summary><see cref="Exponential.In(float)"/></summary>
  73. ExponentialIn,
  74. /// <summary><see cref="Exponential.Out(float)"/></summary>
  75. ExponentialOut,
  76. /// <summary><see cref="Exponential.InOut(float)"/></summary>
  77. ExponentialInOut,
  78. /// <summary><see cref="Circular.In(float)"/></summary>
  79. CircularIn,
  80. /// <summary><see cref="Circular.Out(float)"/></summary>
  81. CircularOut,
  82. /// <summary><see cref="Circular.InOut(float)"/></summary>
  83. CircularInOut,
  84. /// <summary><see cref="Back.In(float)"/></summary>
  85. BackIn,
  86. /// <summary><see cref="Back.Out(float)"/></summary>
  87. BackOut,
  88. /// <summary><see cref="Back.InOut(float)"/></summary>
  89. BackInOut,
  90. /// <summary><see cref="Bounce.In(float)"/></summary>
  91. BounceIn,
  92. /// <summary><see cref="Bounce.Out(float)"/></summary>
  93. BounceOut,
  94. /// <summary><see cref="Bounce.InOut(float)"/></summary>
  95. BounceInOut,
  96. /// <summary><see cref="Elastic.In(float)"/></summary>
  97. ElasticIn,
  98. /// <summary><see cref="Elastic.Out(float)"/></summary>
  99. ElasticOut,
  100. /// <summary><see cref="Elastic.InOut(float)"/></summary>
  101. ElasticInOut,
  102. }
  103. /// <summary>The total number of <see cref="Function"/> values.</summary>
  104. public const int FunctionCount = (int)Function.ElasticInOut + 1;
  105. /************************************************************************************************************************/
  106. private static NormalizedDelegate[] _FunctionDelegates;
  107. /// <summary>[Animancer Extension]
  108. /// Returns a cached delegate representing the specified `function` with a normalized range.
  109. /// </summary>
  110. public static NormalizedDelegate GetDelegate(this Function function)
  111. {
  112. var i = (int)function;
  113. NormalizedDelegate del;
  114. if (_FunctionDelegates == null)
  115. {
  116. _FunctionDelegates = new NormalizedDelegate[FunctionCount];
  117. }
  118. else
  119. {
  120. del = _FunctionDelegates[i];
  121. if (del != null)
  122. return del;
  123. }
  124. switch (function)
  125. {
  126. case Function.Linear: del = Linear; break;
  127. case Function.QuadraticIn: del = Quadratic.In; break;
  128. case Function.QuadraticOut: del = Quadratic.Out; break;
  129. case Function.QuadraticInOut: del = Quadratic.InOut; break;
  130. case Function.CubicIn: del = Cubic.In; break;
  131. case Function.CubicOut: del = Cubic.Out; break;
  132. case Function.CubicInOut: del = Cubic.InOut; break;
  133. case Function.QuarticIn: del = Quartic.In; break;
  134. case Function.QuarticOut: del = Quartic.Out; break;
  135. case Function.QuarticInOut: del = Quartic.InOut; break;
  136. case Function.QuinticIn: del = Quintic.In; break;
  137. case Function.QuinticOut: del = Quintic.Out; break;
  138. case Function.QuinticInOut: del = Quintic.InOut; break;
  139. case Function.SineIn: del = Sine.In; break;
  140. case Function.SineOut: del = Sine.Out; break;
  141. case Function.SineInOut: del = Sine.InOut; break;
  142. case Function.ExponentialIn: del = Exponential.In; break;
  143. case Function.ExponentialOut: del = Exponential.Out; break;
  144. case Function.ExponentialInOut: del = Exponential.InOut; break;
  145. case Function.CircularIn: del = Circular.In; break;
  146. case Function.CircularOut: del = Circular.Out; break;
  147. case Function.CircularInOut: del = Circular.InOut; break;
  148. case Function.BackIn: del = Back.In; break;
  149. case Function.BackOut: del = Back.Out; break;
  150. case Function.BackInOut: del = Back.InOut; break;
  151. case Function.BounceIn: del = Bounce.In; break;
  152. case Function.BounceOut: del = Bounce.Out; break;
  153. case Function.BounceInOut: del = Bounce.InOut; break;
  154. case Function.ElasticIn: del = Elastic.In; break;
  155. case Function.ElasticOut: del = Elastic.Out; break;
  156. case Function.ElasticInOut: del = Elastic.InOut; break;
  157. default: throw new ArgumentOutOfRangeException(nameof(function));
  158. }
  159. _FunctionDelegates[i] = del;
  160. return del;
  161. }
  162. /************************************************************************************************************************/
  163. private static NormalizedDelegate[] _DerivativeDelegates;
  164. /// <summary>[Animancer Extension]
  165. /// Returns a cached delegate representing the derivative of the specified `function` with a normalized range.
  166. /// </summary>
  167. public static NormalizedDelegate GetDerivativeDelegate(this Function function)
  168. {
  169. var i = (int)function;
  170. NormalizedDelegate del;
  171. if (_DerivativeDelegates == null)
  172. {
  173. _DerivativeDelegates = new NormalizedDelegate[FunctionCount];
  174. }
  175. else
  176. {
  177. del = _DerivativeDelegates[i];
  178. if (del != null)
  179. return del;
  180. }
  181. switch (function)
  182. {
  183. case Function.Linear: del = LinearDerivative; break;
  184. case Function.QuadraticIn: del = Quadratic.InDerivative; break;
  185. case Function.QuadraticOut: del = Quadratic.OutDerivative; break;
  186. case Function.QuadraticInOut: del = Quadratic.InOutDerivative; break;
  187. case Function.CubicIn: del = Cubic.InDerivative; break;
  188. case Function.CubicOut: del = Cubic.OutDerivative; break;
  189. case Function.CubicInOut: del = Cubic.InOutDerivative; break;
  190. case Function.QuarticIn: del = Quartic.InDerivative; break;
  191. case Function.QuarticOut: del = Quartic.OutDerivative; break;
  192. case Function.QuarticInOut: del = Quartic.InOutDerivative; break;
  193. case Function.QuinticIn: del = Quintic.InDerivative; break;
  194. case Function.QuinticOut: del = Quintic.OutDerivative; break;
  195. case Function.QuinticInOut: del = Quintic.InOutDerivative; break;
  196. case Function.SineIn: del = Sine.InDerivative; break;
  197. case Function.SineOut: del = Sine.OutDerivative; break;
  198. case Function.SineInOut: del = Sine.InOutDerivative; break;
  199. case Function.ExponentialIn: del = Exponential.InDerivative; break;
  200. case Function.ExponentialOut: del = Exponential.OutDerivative; break;
  201. case Function.ExponentialInOut: del = Exponential.InOutDerivative; break;
  202. case Function.CircularIn: del = Circular.InDerivative; break;
  203. case Function.CircularOut: del = Circular.OutDerivative; break;
  204. case Function.CircularInOut: del = Circular.InOutDerivative; break;
  205. case Function.BackIn: del = Back.InDerivative; break;
  206. case Function.BackOut: del = Back.OutDerivative; break;
  207. case Function.BackInOut: del = Back.InOutDerivative; break;
  208. case Function.BounceIn: del = Bounce.InDerivative; break;
  209. case Function.BounceOut: del = Bounce.OutDerivative; break;
  210. case Function.BounceInOut: del = Bounce.InOutDerivative; break;
  211. case Function.ElasticIn: del = Elastic.InDerivative; break;
  212. case Function.ElasticOut: del = Elastic.OutDerivative; break;
  213. case Function.ElasticInOut: del = Elastic.InOutDerivative; break;
  214. default: throw new ArgumentOutOfRangeException(nameof(function));
  215. }
  216. _DerivativeDelegates[i] = del;
  217. return del;
  218. }
  219. /************************************************************************************************************************/
  220. private static RangedDelegate[] _RangedFunctionDelegates;
  221. /// <summary>[Animancer Extension]
  222. /// Returns a cached delegate representing the specified `function` with a custom range.
  223. /// </summary>
  224. public static RangedDelegate GetRangedDelegate(this Function function)
  225. {
  226. var i = (int)function;
  227. RangedDelegate del;
  228. if (_RangedFunctionDelegates == null)
  229. {
  230. _RangedFunctionDelegates = new RangedDelegate[FunctionCount];
  231. }
  232. else
  233. {
  234. del = _RangedFunctionDelegates[i];
  235. if (del != null)
  236. return del;
  237. }
  238. switch (function)
  239. {
  240. case Function.Linear: del = Linear; break;
  241. case Function.QuadraticIn: del = Quadratic.In; break;
  242. case Function.QuadraticOut: del = Quadratic.Out; break;
  243. case Function.QuadraticInOut: del = Quadratic.InOut; break;
  244. case Function.CubicIn: del = Cubic.In; break;
  245. case Function.CubicOut: del = Cubic.Out; break;
  246. case Function.CubicInOut: del = Cubic.InOut; break;
  247. case Function.QuarticIn: del = Quartic.In; break;
  248. case Function.QuarticOut: del = Quartic.Out; break;
  249. case Function.QuarticInOut: del = Quartic.InOut; break;
  250. case Function.QuinticIn: del = Quintic.In; break;
  251. case Function.QuinticOut: del = Quintic.Out; break;
  252. case Function.QuinticInOut: del = Quintic.InOut; break;
  253. case Function.SineIn: del = Sine.In; break;
  254. case Function.SineOut: del = Sine.Out; break;
  255. case Function.SineInOut: del = Sine.InOut; break;
  256. case Function.ExponentialIn: del = Exponential.In; break;
  257. case Function.ExponentialOut: del = Exponential.Out; break;
  258. case Function.ExponentialInOut: del = Exponential.InOut; break;
  259. case Function.CircularIn: del = Circular.In; break;
  260. case Function.CircularOut: del = Circular.Out; break;
  261. case Function.CircularInOut: del = Circular.InOut; break;
  262. case Function.BackIn: del = Back.In; break;
  263. case Function.BackOut: del = Back.Out; break;
  264. case Function.BackInOut: del = Back.InOut; break;
  265. case Function.BounceIn: del = Bounce.In; break;
  266. case Function.BounceOut: del = Bounce.Out; break;
  267. case Function.BounceInOut: del = Bounce.InOut; break;
  268. case Function.ElasticIn: del = Elastic.In; break;
  269. case Function.ElasticOut: del = Elastic.Out; break;
  270. case Function.ElasticInOut: del = Elastic.InOut; break;
  271. default: throw new ArgumentOutOfRangeException(nameof(function));
  272. }
  273. _RangedFunctionDelegates[i] = del;
  274. return del;
  275. }
  276. /************************************************************************************************************************/
  277. private static RangedDelegate[] _RangedDerivativeDelegates;
  278. /// <summary>[Animancer Extension]
  279. /// Returns a cached delegate representing the derivative of the specified `function` with a custom range.
  280. /// </summary>
  281. public static RangedDelegate GetRangedDerivativeDelegate(this Function function)
  282. {
  283. var i = (int)function;
  284. RangedDelegate del;
  285. if (_RangedDerivativeDelegates == null)
  286. {
  287. _RangedDerivativeDelegates = new RangedDelegate[FunctionCount];
  288. }
  289. else
  290. {
  291. del = _RangedDerivativeDelegates[i];
  292. if (del != null)
  293. return del;
  294. }
  295. switch (function)
  296. {
  297. case Function.Linear: del = LinearDerivative; break;
  298. case Function.QuadraticIn: del = Quadratic.InDerivative; break;
  299. case Function.QuadraticOut: del = Quadratic.OutDerivative; break;
  300. case Function.QuadraticInOut: del = Quadratic.InOutDerivative; break;
  301. case Function.CubicIn: del = Cubic.InDerivative; break;
  302. case Function.CubicOut: del = Cubic.OutDerivative; break;
  303. case Function.CubicInOut: del = Cubic.InOutDerivative; break;
  304. case Function.QuarticIn: del = Quartic.InDerivative; break;
  305. case Function.QuarticOut: del = Quartic.OutDerivative; break;
  306. case Function.QuarticInOut: del = Quartic.InOutDerivative; break;
  307. case Function.QuinticIn: del = Quintic.InDerivative; break;
  308. case Function.QuinticOut: del = Quintic.OutDerivative; break;
  309. case Function.QuinticInOut: del = Quintic.InOutDerivative; break;
  310. case Function.SineIn: del = Sine.InDerivative; break;
  311. case Function.SineOut: del = Sine.OutDerivative; break;
  312. case Function.SineInOut: del = Sine.InOutDerivative; break;
  313. case Function.ExponentialIn: del = Exponential.InDerivative; break;
  314. case Function.ExponentialOut: del = Exponential.OutDerivative; break;
  315. case Function.ExponentialInOut: del = Exponential.InOutDerivative; break;
  316. case Function.CircularIn: del = Circular.InDerivative; break;
  317. case Function.CircularOut: del = Circular.OutDerivative; break;
  318. case Function.CircularInOut: del = Circular.InOutDerivative; break;
  319. case Function.BackIn: del = Back.InDerivative; break;
  320. case Function.BackOut: del = Back.OutDerivative; break;
  321. case Function.BackInOut: del = Back.InOutDerivative; break;
  322. case Function.BounceIn: del = Bounce.InDerivative; break;
  323. case Function.BounceOut: del = Bounce.OutDerivative; break;
  324. case Function.BounceInOut: del = Bounce.InOutDerivative; break;
  325. case Function.ElasticIn: del = Elastic.InDerivative; break;
  326. case Function.ElasticOut: del = Elastic.OutDerivative; break;
  327. case Function.ElasticInOut: del = Elastic.InOutDerivative; break;
  328. default: throw new ArgumentOutOfRangeException(nameof(function));
  329. }
  330. _RangedDerivativeDelegates[i] = del;
  331. return del;
  332. }
  333. /************************************************************************************************************************/
  334. /// <summary>Returns a linearly interpolated value between the `start` and `end` based on a normalized `value`.</summary>
  335. /// <remarks>
  336. /// <list type="bullet">
  337. /// <item><c>value = 0</c> returns <c>start</c>.</item>
  338. /// <item><c>value = 0.5</c> returns <c>(start + end) / 2</c>.</item>
  339. /// <item><c>value = 1</c> returns <c>end</c>.</item>
  340. /// </list>
  341. /// This method is identical to <see cref="LerpUnclamped"/>.
  342. /// </remarks>
  343. public static float Lerp(float start, float end, float value) => start + (end - start) * value;
  344. /// <summary>Returns a normalized value indicating how far the `value` is between the `start` and `end`.</summary>
  345. /// <remarks>
  346. /// <list type="bullet">
  347. /// <item><c>value = start</c> returns <c>0</c>.</item>
  348. /// <item><c>value = (start + end) / 2</c> returns <c>0.5</c>.</item>
  349. /// <item><c>value = end</c> returns <c>1</c>.</item>
  350. /// <item><c>start = end</c> returns <c>0</c>.</item>
  351. /// </list>
  352. /// This method is like <see cref="InverseLerp"/> except that it doesn't clamp the result between 0 and 1.
  353. /// </remarks>
  354. public static float UnLerp(float start, float end, float value) => start == end ? 0 : (value - start) / (end - start);
  355. /************************************************************************************************************************/
  356. /// <summary>Re-scales the result of the `function` to use a custom range instead of 0 to 1.</summary>
  357. public static float ReScale(float start, float end, float value, NormalizedDelegate function)
  358. => Lerp(start, end, function(UnLerp(start, end, value)));
  359. /************************************************************************************************************************/
  360. #endregion
  361. /************************************************************************************************************************/
  362. #region Linear
  363. /************************************************************************************************************************/
  364. /// <summary>Directly returns the `value`. Interpolates the `value` based on the line <c>y = x</c>.</summary>
  365. public static float Linear(float value) => value;
  366. /************************************************************************************************************************/
  367. /// <summary>Returns 1. The derivative of <see cref="Linear(float)"/>.</summary>
  368. public static float LinearDerivative(float value) => 1;
  369. /************************************************************************************************************************/
  370. /// <summary>Directly returns the `value`. Interpolates the `value` based on the line <c>y = x</c>.</summary>
  371. public static float Linear(float start, float end, float value) => value;
  372. /************************************************************************************************************************/
  373. /// <summary>Returns <c>end - start</c>. The derivative of <see cref="Linear(float, float, float)"/>.</summary>
  374. public static float LinearDerivative(float start, float end, float value) => end - start;
  375. /************************************************************************************************************************/
  376. #endregion
  377. /************************************************************************************************************************/
  378. #region Quadratic
  379. /************************************************************************************************************************/
  380. /// <summary>Functions based on quadratic equations (<c>x^2</c>).</summary>
  381. /// https://kybernetik.com.au/animancer/api/Animancer/Quadratic
  382. ///
  383. public static class Quadratic
  384. {
  385. /************************************************************************************************************************/
  386. /// <summary>Interpolates the `value` based on the line <c>y = x^2</c>.</summary>
  387. /// <remarks><see href="https://easings.net/#easeInQuad">Easings.net has a graph of this function.</see></remarks>
  388. public static float In(float value) => value * value;
  389. /// <summary>Interpolates the `value` based on the line <c>y = 1 - (x - 1)^2</c>.</summary>
  390. /// <remarks><see href="https://easings.net/#easeOutQuad">Easings.net has a graph of this function.</see></remarks>
  391. public static float Out(float value)
  392. {
  393. value--;
  394. return -value * value + 1;
  395. }
  396. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  397. /// <remarks><see href="https://easings.net/#easeInOutQuad">Easings.net has a graph of this function.</see></remarks>
  398. public static float InOut(float value)
  399. {
  400. value *= 2;
  401. if (value <= 1)
  402. {
  403. return 0.5f * value * value;
  404. }
  405. else
  406. {
  407. value -= 2;
  408. return 0.5f * (-value * value + 2);
  409. }
  410. }
  411. /************************************************************************************************************************/
  412. /// <summary>Returns the derivative of <see cref="In(float)"/> (<c>y = 2x</c>).</summary>
  413. public static float InDerivative(float value) => 2 * value;
  414. /// <summary>Returns the derivative of <see cref="Out(float)"/> (<c>y = -2x + 2</c>).</summary>
  415. public static float OutDerivative(float value) => 2 - 2 * value;
  416. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  417. public static float InOutDerivative(float value)
  418. {
  419. value *= 2;
  420. if (value <= 1)
  421. {
  422. return 2 * value;
  423. }
  424. else
  425. {
  426. value--;
  427. return 2 - 2 * value;
  428. }
  429. }
  430. /************************************************************************************************************************/
  431. // Ranged Variants.
  432. /************************************************************************************************************************/
  433. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  434. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  435. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  436. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  437. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  438. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  439. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  440. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  441. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  442. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  443. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  444. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  445. /************************************************************************************************************************/
  446. }
  447. /************************************************************************************************************************/
  448. #endregion
  449. /************************************************************************************************************************/
  450. #region Cubic
  451. /************************************************************************************************************************/
  452. /// <summary>Functions based on cubic equations (<c>x^3</c>).</summary>
  453. /// https://kybernetik.com.au/animancer/api/Animancer/Cubic
  454. ///
  455. public static class Cubic
  456. {
  457. /************************************************************************************************************************/
  458. /// <summary>Interpolates the `value` based on the line <c>y = x^3</c>.</summary>
  459. /// <remarks><see href="https://easings.net/#easeInCubic">Easings.net has a graph of this function.</see></remarks>
  460. public static float In(float value) => value * value * value;
  461. /// <summary>Interpolates the `value` based on the line <c>y = 1 + (x - 1)^3</c>.</summary>
  462. /// <remarks><see href="https://easings.net/#easeOutCubic">Easings.net has a graph of this function.</see></remarks>
  463. public static float Out(float value)
  464. {
  465. value--;
  466. return value * value * value + 1;
  467. }
  468. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  469. /// <remarks><see href="https://easings.net/#easeInOutCubic">Easings.net has a graph of this function.</see></remarks>
  470. public static float InOut(float value)
  471. {
  472. value *= 2;
  473. if (value <= 1)
  474. {
  475. return 0.5f * value * value * value;
  476. }
  477. else
  478. {
  479. value -= 2;
  480. return 0.5f * (value * value * value + 2);
  481. }
  482. }
  483. /************************************************************************************************************************/
  484. /// <summary>Returns the derivative of <see cref="In(float)"/> (<c>y = 3x</c>).</summary>
  485. public static float InDerivative(float value) => 3 * value * value;
  486. /// <summary>Returns the derivative of <see cref="Out(float)"/> (<c>y = 3 * (x - 1)</c>).</summary>
  487. public static float OutDerivative(float value)
  488. {
  489. value--;
  490. return 3 * value * value;
  491. }
  492. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  493. public static float InOutDerivative(float value)
  494. {
  495. value *= 2;
  496. if (value <= 1)
  497. {
  498. return 3 * value * value;
  499. }
  500. else
  501. {
  502. value -= 2;
  503. return 3 * value * value;
  504. }
  505. }
  506. /************************************************************************************************************************/
  507. // Ranged Variants.
  508. /************************************************************************************************************************/
  509. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  510. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  511. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  512. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  513. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  514. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  515. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  516. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  517. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  518. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  519. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  520. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  521. /************************************************************************************************************************/
  522. }
  523. /************************************************************************************************************************/
  524. #endregion
  525. /************************************************************************************************************************/
  526. #region Quartic
  527. /************************************************************************************************************************/
  528. /// <summary>Functions based on quartic equations (<c>x^4</c>).</summary>
  529. /// https://kybernetik.com.au/animancer/api/Animancer/Quartic
  530. ///
  531. public static class Quartic
  532. {
  533. /************************************************************************************************************************/
  534. /// <summary>Interpolates the `value` based on the line <c>y = x^4</c>.</summary>
  535. /// <remarks><see href="https://easings.net/#easeInQuart">Easings.net has a graph of this function.</see></remarks>
  536. public static float In(float value) => value * value * value * value;
  537. /// <summary>Interpolates the `value` based on the line <c>y = 1 - (x - 1)^4</c>.</summary>
  538. /// <remarks><see href="https://easings.net/#easeOutQuart">Easings.net has a graph of this function.</see></remarks>
  539. public static float Out(float value)
  540. {
  541. value--;
  542. return -value * value * value * value + 1;
  543. }
  544. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  545. /// <remarks><see href="https://easings.net/#easeInOutQuart">Easings.net has a graph of this function.</see></remarks>
  546. public static float InOut(float value)
  547. {
  548. value *= 2;
  549. if (value <= 1)
  550. {
  551. return 0.5f * value * value * value * value;
  552. }
  553. else
  554. {
  555. value -= 2;
  556. return 0.5f * (-value * value * value * value + 2);
  557. }
  558. }
  559. /************************************************************************************************************************/
  560. /// <summary>Returns the derivative of <see cref="In(float)"/> (<c>y = 4x</c>).</summary>
  561. public static float InDerivative(float value) => 4 * value * value * value;
  562. /// <summary>Returns the derivative of <see cref="Out(float)"/> (<c>y = -4 * (x - 1)</c>).</summary>
  563. public static float OutDerivative(float value)
  564. {
  565. value--;
  566. return -4 * value * value * value;
  567. }
  568. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  569. public static float InOutDerivative(float value)
  570. {
  571. value *= 2;
  572. if (value <= 1)
  573. {
  574. return 4 * value * value * value;
  575. }
  576. else
  577. {
  578. value -= 2;
  579. return -4 * value * value * value;
  580. }
  581. }
  582. /************************************************************************************************************************/
  583. // Ranged Variants.
  584. /************************************************************************************************************************/
  585. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  586. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  587. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  588. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  589. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  590. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  591. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  592. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  593. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  594. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  595. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  596. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  597. /************************************************************************************************************************/
  598. }
  599. /************************************************************************************************************************/
  600. #endregion
  601. /************************************************************************************************************************/
  602. #region Quintic
  603. /************************************************************************************************************************/
  604. /// <summary>Functions based on quintic equations (<c>x^5</c>).</summary>
  605. /// https://kybernetik.com.au/animancer/api/Animancer/Quintic
  606. ///
  607. public static class Quintic
  608. {
  609. /************************************************************************************************************************/
  610. /// <summary>Interpolates the `value` based on the line <c>y = x^5</c>.</summary>
  611. /// <remarks><see href="https://easings.net/#easeInQuint">Easings.net has a graph of this function.</see></remarks>
  612. public static float In(float value) => value * value * value * value * value;
  613. /// <summary>Interpolates the `value` based on the line <c>y = 1 + (x - 1)^5</c>.</summary>
  614. /// <remarks><see href="https://easings.net/#easeOutQuint">Easings.net has a graph of this function.</see></remarks>
  615. public static float Out(float value)
  616. {
  617. value--;
  618. return value * value * value * value * value + 1;
  619. }
  620. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  621. /// <remarks><see href="https://easings.net/#easeInOutQuint">Easings.net has a graph of this function.</see></remarks>
  622. public static float InOut(float value)
  623. {
  624. value *= 2;
  625. if (value <= 1)
  626. {
  627. return 0.5f * value * value * value * value * value;
  628. }
  629. else
  630. {
  631. value -= 2;
  632. return 0.5f * (value * value * value * value * value + 2);
  633. }
  634. }
  635. /************************************************************************************************************************/
  636. /// <summary>Returns the derivative of <see cref="In(float)"/> (<c>y = 5x</c>).</summary>
  637. public static float InDerivative(float value) => 5 * value * value * value * value;
  638. /// <summary>Returns the derivative of <see cref="Out(float)"/> (<c>y = -5 * (x - 1)</c>).</summary>
  639. public static float OutDerivative(float value)
  640. {
  641. value--;
  642. return 5 * value * value * value * value;
  643. }
  644. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  645. public static float InOutDerivative(float value)
  646. {
  647. value *= 2;
  648. if (value <= 1)
  649. {
  650. return 5 * value * value * value * value;
  651. }
  652. else
  653. {
  654. value -= 2;
  655. return 5 * value * value * value * value;
  656. }
  657. }
  658. /************************************************************************************************************************/
  659. // Ranged Variants.
  660. /************************************************************************************************************************/
  661. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  662. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  663. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  664. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  665. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  666. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  667. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  668. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  669. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  670. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  671. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  672. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  673. /************************************************************************************************************************/
  674. }
  675. /************************************************************************************************************************/
  676. #endregion
  677. /************************************************************************************************************************/
  678. #region Sine
  679. /************************************************************************************************************************/
  680. /// <summary>Functions based on sinusoidal equations.</summary>
  681. /// https://kybernetik.com.au/animancer/api/Animancer/Sine
  682. ///
  683. public static class Sine
  684. {
  685. /************************************************************************************************************************/
  686. /// <summary>Interpolates the `value` based on a quarter-cycle of a sine wave.</summary>
  687. /// <remarks><see href="https://easings.net/#easeInSine">Easings.net has a graph of this function.</see></remarks>
  688. public static float In(float value) => -Cos(value * (PI * 0.5f)) + 1;
  689. /// <summary>Interpolates the `value` based on a quarter-cycle of a sine wave.</summary>
  690. /// <remarks><see href="https://easings.net/#easeOutSine">Easings.net has a graph of this function.</see></remarks>
  691. public static float Out(float value) => Sin(value * (PI * 0.5f));
  692. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  693. /// <remarks><see href="https://easings.net/#easeInOutSine">Easings.net has a graph of this function.</see></remarks>
  694. public static float InOut(float value) => -0.5f * (Cos(PI * value) - 1);
  695. /************************************************************************************************************************/
  696. /// <summary>Returns the derivative of <see cref="In(float)"/>.</summary>
  697. public static float InDerivative(float value) => 0.5f * PI * Sin(0.5f * PI * value);
  698. /// <summary>Returns the derivative of <see cref="Out(float)"/>.</summary>
  699. public static float OutDerivative(float value) => PI * 0.5f * Cos(value * (PI * 0.5f));
  700. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  701. public static float InOutDerivative(float value) => 0.5f * PI * Sin(PI * value);
  702. /************************************************************************************************************************/
  703. // Ranged Variants.
  704. /************************************************************************************************************************/
  705. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  706. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  707. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  708. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  709. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  710. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  711. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  712. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  713. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  714. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  715. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  716. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  717. /************************************************************************************************************************/
  718. }
  719. /************************************************************************************************************************/
  720. #endregion
  721. /************************************************************************************************************************/
  722. #region Exponential
  723. /************************************************************************************************************************/
  724. /// <summary>Functions based on exponential equations (<c>2^(10(x))</c>).</summary>
  725. /// https://kybernetik.com.au/animancer/api/Animancer/Exponential
  726. ///
  727. public static class Exponential
  728. {
  729. /************************************************************************************************************************/
  730. /// <summary>Interpolates the `value` based on the line (<c>y = 2^(10 * (x - 1))</c>).</summary>
  731. /// <remarks><see href="https://easings.net/#easeInExpo">Easings.net has a graph of this function.</see></remarks>
  732. public static float In(float value) => Pow(2, 10 * (value - 1));
  733. /// <summary>Interpolates the `value` based on the line (<c>y = -2^(-10x) + 1</c>).</summary>
  734. /// <remarks><see href="https://easings.net/#easeOutExpo">Easings.net has a graph of this function.</see></remarks>
  735. public static float Out(float value) => -Pow(2, -10 * value) + 1;
  736. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  737. /// <remarks><see href="https://easings.net/#easeInOutExpo">Easings.net has a graph of this function.</see></remarks>
  738. public static float InOut(float value)
  739. {
  740. value *= 2;
  741. if (value <= 1)
  742. {
  743. return 0.5f * Pow(2, 10 * (value - 1));
  744. }
  745. else
  746. {
  747. value--;
  748. return 0.5f * (-Pow(2, -10 * value) + 2);
  749. }
  750. }
  751. /************************************************************************************************************************/
  752. /// <summary>Returns the derivative of <see cref="In(float)"/> (<c>y = 10 * ln(2) * 2^(10 * (x - 1))</c>).</summary>
  753. public static float InDerivative(float value) => 10 * Ln2 * Pow(2, 10 * (value - 1));
  754. /// <summary>Returns the derivative of <see cref="Out(float)"/> (<c>y = 5 * ln(2) * 2^(-10 * (x - 1) + 1)</c>).</summary>
  755. public static float OutDerivative(float value) => 5 * Ln2 * Pow(2, 1 - 10 * value);
  756. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  757. public static float InOutDerivative(float value)
  758. {
  759. value *= 2;
  760. if (value <= 1)
  761. {
  762. return 10 * Ln2 * Pow(2, 10 * (value - 1));
  763. }
  764. else
  765. {
  766. value--;
  767. return 5 * Ln2 * Pow(2, 1 - 10 * value);
  768. }
  769. }
  770. /************************************************************************************************************************/
  771. // Ranged Variants.
  772. /************************************************************************************************************************/
  773. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  774. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  775. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  776. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  777. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  778. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  779. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  780. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  781. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  782. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  783. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  784. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  785. /************************************************************************************************************************/
  786. }
  787. /************************************************************************************************************************/
  788. #endregion
  789. /************************************************************************************************************************/
  790. #region Circular
  791. /************************************************************************************************************************/
  792. /// <summary>Functions based on circular equations.</summary>
  793. /// https://kybernetik.com.au/animancer/api/Animancer/Circular
  794. ///
  795. public static class Circular
  796. {
  797. /************************************************************************************************************************/
  798. /// <summary>Interpolates the `value` based on a shifted quadrant IV of a unit circle.</summary>
  799. /// <remarks><see href="https://easings.net/#easeInCirc">Easings.net has a graph of this function.</see></remarks>
  800. public static float In(float value) => -(Sqrt(1 - value * value) - 1);
  801. /// <summary>Interpolates the `value` based on a shifted quadrant II of a unit circle.</summary>
  802. /// <remarks><see href="https://easings.net/#easeOutCirc">Easings.net has a graph of this function.</see></remarks>
  803. public static float Out(float value)
  804. {
  805. value--;
  806. return Sqrt(1 - value * value);
  807. }
  808. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  809. /// <remarks><see href="https://easings.net/#easeInOutCirc">Easings.net has a graph of this function.</see></remarks>
  810. public static float InOut(float value)
  811. {
  812. value *= 2;
  813. if (value <= 1)
  814. {
  815. return -0.5f * (Sqrt(1 - value * value) - 1);
  816. }
  817. else
  818. {
  819. value -= 2;
  820. return 0.5f * (Sqrt(1 - value * value) + 1);
  821. }
  822. }
  823. /************************************************************************************************************************/
  824. /// <summary>Returns the derivative of <see cref="In(float)"/>.</summary>
  825. public static float InDerivative(float value) => value / Sqrt(1 - value * value);
  826. /// <summary>Returns the derivative of <see cref="Out(float)"/>.</summary>
  827. public static float OutDerivative(float value)
  828. {
  829. value--;
  830. return -value / Sqrt(1 - value * value);
  831. }
  832. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  833. public static float InOutDerivative(float value)
  834. {
  835. value *= 2;
  836. if (value <= 1)
  837. {
  838. return value / (2 * Sqrt(1 - value * value));
  839. }
  840. else
  841. {
  842. value -= 2;
  843. return -value / (2 * Sqrt(1 - value * value));
  844. }
  845. }
  846. /************************************************************************************************************************/
  847. // Ranged Variants.
  848. /************************************************************************************************************************/
  849. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  850. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  851. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  852. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  853. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  854. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  855. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  856. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  857. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  858. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  859. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  860. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  861. /************************************************************************************************************************/
  862. }
  863. /************************************************************************************************************************/
  864. #endregion
  865. /************************************************************************************************************************/
  866. #region Back
  867. /************************************************************************************************************************/
  868. /// <summary>Functions based on equations which go out of bounds then come back.</summary>
  869. /// https://kybernetik.com.au/animancer/api/Animancer/Back
  870. ///
  871. public static class Back
  872. {
  873. /************************************************************************************************************************/
  874. private const float C = 1.758f;
  875. /************************************************************************************************************************/
  876. /// <remarks><see href="https://easings.net/#easeInBack">Easings.net has a graph of this function.</see></remarks>
  877. public static float In(float value) => value * value * ((C + 1) * value - C);
  878. /// <remarks><see href="https://easings.net/#easeOutBack">Easings.net has a graph of this function.</see></remarks>
  879. public static float Out(float value)
  880. {
  881. value -= 1;
  882. return value * value * ((C + 1) * value + C) + 1;
  883. }
  884. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  885. /// <remarks><see href="https://easings.net/#easeInOutBack">Easings.net has a graph of this function.</see></remarks>
  886. public static float InOut(float value)
  887. {
  888. value *= 2;
  889. if (value <= 1)
  890. {
  891. return 0.5f * value * value * ((C + 1) * value - C);
  892. }
  893. else
  894. {
  895. value -= 2;
  896. return 0.5f * (value * value * ((C + 1) * value + C) + 2);
  897. }
  898. }
  899. /************************************************************************************************************************/
  900. /// <summary>Returns the derivative of <see cref="In(float)"/>.</summary>
  901. public static float InDerivative(float value) => 3 * (C + 1) * value * value - 2 * C * value;
  902. /// <summary>Returns the derivative of <see cref="Out(float)"/>.</summary>
  903. public static float OutDerivative(float value)
  904. {
  905. value -= 1;
  906. return (C + 1) * value * value + 2 * value * ((C + 1) * value + C);
  907. }
  908. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  909. public static float InOutDerivative(float value)
  910. {
  911. value *= 2;
  912. if (value <= 1)
  913. {
  914. return 3 * (C + 1) * value * value - 2 * C * value;
  915. }
  916. else
  917. {
  918. value -= 2;
  919. return (C + 1) * value * value + 2 * value * ((C + 1) * value + C);
  920. }
  921. }
  922. /************************************************************************************************************************/
  923. // Ranged Variants.
  924. /************************************************************************************************************************/
  925. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  926. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  927. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  928. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  929. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  930. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  931. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  932. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  933. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  934. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  935. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  936. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  937. /************************************************************************************************************************/
  938. }
  939. /************************************************************************************************************************/
  940. #endregion
  941. /************************************************************************************************************************/
  942. #region Bounce
  943. /************************************************************************************************************************/
  944. /// <summary>Functions based on equations with sharp bounces.</summary>
  945. /// https://kybernetik.com.au/animancer/api/Animancer/Bounce
  946. ///
  947. public static class Bounce
  948. {
  949. /************************************************************************************************************************/
  950. /// <remarks><see href="https://easings.net/#easeInBounce">Easings.net has a graph of this function.</see></remarks>
  951. public static float In(float value)
  952. {
  953. return 1 - Out(1 - value);
  954. }
  955. /// <remarks><see href="https://easings.net/#easeOutBounce">Easings.net has a graph of this function.</see></remarks>
  956. public static float Out(float value)
  957. {
  958. switch (value)
  959. {
  960. case 0: return 0;
  961. case 1: return 1;
  962. }
  963. if (value < (1f / 2.75f))
  964. {
  965. return 7.5625f * value * value;
  966. }
  967. else if (value < (2f / 2.75f))
  968. {
  969. value -= 1.5f / 2.75f;
  970. return 7.5625f * value * value + 0.75f;
  971. }
  972. else if (value < (2.5f / 2.75f))
  973. {
  974. value -= 2.25f / 2.75f;
  975. return 7.5625f * value * value + 0.9375f;
  976. }
  977. else
  978. {
  979. value -= 2.625f / 2.75f;
  980. return 7.5625f * value * value + 0.984375f;
  981. }
  982. }
  983. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  984. /// <remarks><see href="https://easings.net/#easeInOutBounce">Easings.net has a graph of this function.</see></remarks>
  985. public static float InOut(float value)
  986. {
  987. if (value < 0.5f)
  988. return 0.5f * In(value * 2);
  989. else
  990. return 0.5f + 0.5f * Out(value * 2 - 1);
  991. }
  992. /************************************************************************************************************************/
  993. /// <summary>Returns the derivative of <see cref="In(float)"/>.</summary>
  994. public static float InDerivative(float value) => OutDerivative(1 - value);
  995. /// <summary>Returns the derivative of <see cref="Out(float)"/>.</summary>
  996. public static float OutDerivative(float value)
  997. {
  998. if (value < (1f / 2.75f))
  999. {
  1000. return 2 * 7.5625f * value;
  1001. }
  1002. else if (value < (2f / 2.75f))
  1003. {
  1004. value -= 1.5f / 2.75f;
  1005. return 2 * 7.5625f * value;
  1006. }
  1007. else if (value < (2.5f / 2.75f))
  1008. {
  1009. value -= 2.25f / 2.75f;
  1010. return 2 * 7.5625f * value;
  1011. }
  1012. else
  1013. {
  1014. value -= 2.625f / 2.75f;
  1015. return 2 * 7.5625f * value;
  1016. }
  1017. }
  1018. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  1019. public static float InOutDerivative(float value)
  1020. {
  1021. value *= 2;
  1022. if (value <= 1)
  1023. return OutDerivative(1 - value);
  1024. else
  1025. return OutDerivative(value - 1);
  1026. }
  1027. /************************************************************************************************************************/
  1028. // Ranged Variants.
  1029. /************************************************************************************************************************/
  1030. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  1031. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  1032. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  1033. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  1034. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  1035. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  1036. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1037. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  1038. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1039. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  1040. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1041. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  1042. /************************************************************************************************************************/
  1043. }
  1044. /************************************************************************************************************************/
  1045. #endregion
  1046. /************************************************************************************************************************/
  1047. #region Elastic
  1048. /************************************************************************************************************************/
  1049. /// <summary>Functions based on equations with soft bounces.</summary>
  1050. /// https://kybernetik.com.au/animancer/api/Animancer/Elastic
  1051. ///
  1052. public static class Elastic
  1053. {
  1054. /************************************************************************************************************************/
  1055. /// <summary><c>2 / 3 * pi</c></summary>
  1056. public const float TwoThirdsPi = 2f / 3f * PI;
  1057. /************************************************************************************************************************/
  1058. /// <remarks><see href="https://easings.net/#easeInElastic">Easings.net has a graph of this function.</see></remarks>
  1059. public static float In(float value)
  1060. {
  1061. switch (value)
  1062. {
  1063. case 0: return 0;
  1064. case 1: return 1;
  1065. }
  1066. return -Pow(2, 10 * value - 10) * Sin((value * 10 - 10.75f) * TwoThirdsPi);
  1067. }
  1068. /// <remarks><see href="https://easings.net/#easeOutElastic">Easings.net has a graph of this function.</see></remarks>
  1069. public static float Out(float value)
  1070. {
  1071. switch (value)
  1072. {
  1073. case 0: return 0;
  1074. case 1: return 1;
  1075. }
  1076. return 1 + Pow(2, -10 * value) * Sin((value * -10 - 0.75f) * TwoThirdsPi);
  1077. }
  1078. /// <summary>Interpolate using <see cref="In"/> (0 to 0.5) or <see cref="Out"/> (0.5 to 1).</summary>
  1079. /// <remarks><see href="https://easings.net/#easeInOutElastic">Easings.net has a graph of this function.</see></remarks>
  1080. public static float InOut(float value)
  1081. {
  1082. switch (value)
  1083. {
  1084. case 0: return 0;
  1085. case 0.5f: return 0.5f;
  1086. case 1: return 1;
  1087. }
  1088. value *= 2;
  1089. if (value <= 1)
  1090. {
  1091. return 0.5f * (-Pow(2, 10 * value - 10) * Sin((value * 10 - 10.75f) * TwoThirdsPi));
  1092. }
  1093. else
  1094. {
  1095. value--;
  1096. return 0.5f + 0.5f * (1 + Pow(2, -10 * value) * Sin((value * -10 - 0.75f) * TwoThirdsPi));
  1097. }
  1098. }
  1099. /************************************************************************************************************************/
  1100. /// <summary>Returns the derivative of <see cref="In(float)"/>.</summary>
  1101. public static float InDerivative(float value)
  1102. {
  1103. return -(5 * Pow(2, 10 * value - 9) *
  1104. (3 * Ln2 * Sin(PI * (40 * value - 43) / 6) +
  1105. 2 * PI * Cos(PI * (40 * value - 43) / 6))) / 3;
  1106. }
  1107. /// <summary>Returns the derivative of <see cref="Out(float)"/>.</summary>
  1108. public static float OutDerivative(float value)
  1109. {
  1110. return -(30 * Ln2 * Sin(2 * PI * (10 * value - 3f / 4f) / 3) -
  1111. 20 * PI * Cos(2 * PI * (10 * value - 3f / 4f) / 3)) /
  1112. (3 * Pow(2, 10 * value));
  1113. }
  1114. /// <summary>Returns the derivative of <see cref="InOut(float)"/>.</summary>
  1115. public static float InOutDerivative(float value)
  1116. {
  1117. value *= 2;
  1118. if (value <= 1)
  1119. return OutDerivative(1 - value);
  1120. else
  1121. return OutDerivative(value - 1);
  1122. }
  1123. /************************************************************************************************************************/
  1124. // Ranged Variants.
  1125. /************************************************************************************************************************/
  1126. /// <summary>A variant of <see cref="In(float)"/> with a custom range instead of 0 to 1.</summary>
  1127. public static float In(float start, float end, float value) => Lerp(start, end, In(UnLerp(start, end, value)));
  1128. /// <summary>A variant of <see cref="Out(float)"/> with a custom range instead of 0 to 1.</summary>
  1129. public static float Out(float start, float end, float value) => Lerp(start, end, Out(UnLerp(start, end, value)));
  1130. /// <summary>A variant of <see cref="InOut(float)"/> with a custom range instead of 0 to 1.</summary>
  1131. public static float InOut(float start, float end, float value) => Lerp(start, end, InOut(UnLerp(start, end, value)));
  1132. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1133. public static float InDerivative(float start, float end, float value) => InDerivative(UnLerp(start, end, value)) * (end - start);
  1134. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1135. public static float OutDerivative(float start, float end, float value) => OutDerivative(UnLerp(start, end, value)) * (end - start);
  1136. /// <summary>A variant of <see cref="InDerivative(float)"/> with a custom range instead of 0 to 1.</summary>
  1137. public static float InOutDerivative(float start, float end, float value) => InOutDerivative(UnLerp(start, end, value)) * (end - start);
  1138. /************************************************************************************************************************/
  1139. }
  1140. /************************************************************************************************************************/
  1141. #endregion
  1142. /************************************************************************************************************************/
  1143. }
  1144. }