content: {-|
    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 = 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 from to t = from + (to-from)*t
  
  -- | Reverse signal order.
  --
  --   Example:
  --
  -- @
  -- 'Reanimate.signalA' 'reverseS' 'Reanimate.Builtin.Documentation.drawProgress'
  -- @
  --
  --   <<docs/gifs/doc_reverseS.gif>>
  reverseS :: Signal
  reverseS t = 1-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 steepness s =
    if s < 0.5
      then 0.5 * (2*s)**steepness
      else 1-0.5 * (2 - 2*s)**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 steepness s = s**steepness
  
  -- | Oscillate signal.
  --
  --   Example:
  --
  -- @
  -- 'Reanimate.signalA' 'oscillateS' 'Reanimate.Builtin.Documentation.drawProgress'
  -- @
  --
  --   <<docs/gifs/doc_oscillateS.gif>>
  oscillateS :: Signal
  oscillateS t =
    if t < 1/2
      then t*2
      else 2-t*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 steepness = curveS steepness . 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 (x1, x2, x3, x4) s = 
    let ms = 1-s
    in x1*ms^(3::Int) + 3*x2*ms^(2::Int)*s + 3*x3*ms*s^(2::Int) + x4*s^(3::Int)
  