{-|
  Easing functions modify the rate of change in animations.
  More examples can be seen here: <https://easings.net/>.
-}
module Reanimate.Ease
  ( Signal
  , constantS
  , fromToS
  , reverseS
  , curveS
  , powerS
  , bellS
  , oscillateS
  , cubicBezierS
  ) where

-- | Signals are time-varying variables. Signals can be composed using function
--   composition.
type Signal = Double -> Double

-- | Constant signal.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('constantS' 0.5) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_constantS.gif>>
constantS :: Double -> Signal
constantS :: Double -> Signal
constantS = Double -> Signal
forall a b. a -> b -> a
const

-- | Signal with new starting and end values.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('fromToS' 0.8 0.2) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_fromToS.gif>>
fromToS :: Double -> Double -> Signal
fromToS :: Double -> Double -> Signal
fromToS Double
from Double
to Double
t = Double
from Double -> Signal
forall a. Num a => a -> a -> a
+ (Double
toDouble -> Signal
forall a. Num a => a -> a -> a
-Double
from)Double -> Signal
forall a. Num a => a -> a -> a
*Double
t

-- | Reverse signal order.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' 'reverseS' 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_reverseS.gif>>
reverseS :: Signal
reverseS :: Signal
reverseS Double
t = Double
1Double -> Signal
forall a. Num a => a -> a -> a
-Double
t

-- | S-curve signal. Takes a steepness parameter. 2 is a good default.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('curveS' 2) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_curveS.gif>>
curveS :: Double -> Signal
curveS :: Double -> Signal
curveS Double
steepness Double
s =
  if Double
s Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.5
    then Double
0.5 Double -> Signal
forall a. Num a => a -> a -> a
* (Double
2Double -> Signal
forall a. Num a => a -> a -> a
*Double
s)Double -> Signal
forall a. Floating a => a -> a -> a
**Double
steepness
    else Double
1Double -> Signal
forall a. Num a => a -> a -> a
-Double
0.5 Double -> Signal
forall a. Num a => a -> a -> a
* (Double
2 Double -> Signal
forall a. Num a => a -> a -> a
- Double
2Double -> Signal
forall a. Num a => a -> a -> a
*Double
s)Double -> Signal
forall a. Floating a => a -> a -> a
**Double
steepness

-- | Power curve signal. Takes a steepness parameter. 2 is a good default.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('powerS' 2) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_powerS.gif>>
powerS :: Double -> Signal
powerS :: Double -> Signal
powerS Double
steepness Double
s = Double
sDouble -> Signal
forall a. Floating a => a -> a -> a
**Double
steepness

-- | Oscillate signal.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' 'oscillateS' 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_oscillateS.gif>>
oscillateS :: Signal
oscillateS :: Signal
oscillateS Double
t =
  if Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1Double -> Signal
forall a. Fractional a => a -> a -> a
/Double
2
    then Double
tDouble -> Signal
forall a. Num a => a -> a -> a
*Double
2
    else Double
2Double -> Signal
forall a. Num a => a -> a -> a
-Double
tDouble -> Signal
forall a. Num a => a -> a -> a
*Double
2

-- | Bell-curve signal. Takes a steepness parameter. 2 is a good default.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('bellS' 2) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--
--   <<docs/gifs/doc_bellS.gif>>
bellS :: Double -> Signal
bellS :: Double -> Signal
bellS Double
steepness = Double -> Signal
curveS Double
steepness Signal -> Signal -> Signal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal
oscillateS

-- | Cubic Bezier signal. Gives you a fair amount of control over how the
--   signal will curve.
--
--   Example:
--
-- @
-- 'Reanimate.signalA' ('cubicBezierS' (0.0, 0.8, 0.9, 1.0)) 'Reanimate.Builtin.Documentation.drawProgress'
-- @
--   
--   <<docs/gifs/doc_cubicBezierS.gif>>
cubicBezierS :: (Double, Double, Double, Double) -> Signal
cubicBezierS :: (Double, Double, Double, Double) -> Signal
cubicBezierS (Double
x1, Double
x2, Double
x3, Double
x4) Double
s = 
  let ms :: Double
ms = Double
1Double -> Signal
forall a. Num a => a -> a -> a
-Double
s
  in Double
x1Double -> Signal
forall a. Num a => a -> a -> a
*Double
msDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3::Int) Double -> Signal
forall a. Num a => a -> a -> a
+ Double
3Double -> Signal
forall a. Num a => a -> a -> a
*Double
x2Double -> Signal
forall a. Num a => a -> a -> a
*Double
msDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2::Int)Double -> Signal
forall a. Num a => a -> a -> a
*Double
s Double -> Signal
forall a. Num a => a -> a -> a
+ Double
3Double -> Signal
forall a. Num a => a -> a -> a
*Double
x3Double -> Signal
forall a. Num a => a -> a -> a
*Double
msDouble -> Signal
forall a. Num a => a -> a -> a
*Double
sDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2::Int) Double -> Signal
forall a. Num a => a -> a -> a
+ Double
x4Double -> Signal
forall a. Num a => a -> a -> a
*Double
sDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3::Int)