patat-0.10.0.0: lib/Patat/Transition/SlideLeft.hs
--------------------------------------------------------------------------------
{-# LANGUAGE TemplateHaskell #-}
module Patat.Transition.SlideLeft
( slideLeft
) where
--------------------------------------------------------------------------------
import qualified Data.Aeson.Extended as A
import qualified Data.Aeson.TH.Extended as A
import Data.Foldable (for_)
import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Maybe (fromMaybe)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import Patat.PrettyPrint.Matrix
import Patat.Size (Size (..))
import Patat.Transition.Internal
--------------------------------------------------------------------------------
data Config = Config
{ cDuration :: Maybe (A.FlexibleNum Double)
, cFrameRate :: Maybe (A.FlexibleNum Int)
}
--------------------------------------------------------------------------------
slideLeft :: Config -> TransitionGen
slideLeft config (Size rows cols) initial final _rgen =
fmap (\f -> (f, Duration delay)) $
frame 0 :| map frame [1 .. frames - 1]
where
duration = fromMaybe 1 $ A.unFlexibleNum <$> cDuration config
frameRate = fromMaybe 24 $ A.unFlexibleNum <$> cFrameRate config
frames = round $ duration * fromIntegral frameRate :: Int
delay = duration / fromIntegral (frames + 1)
frame :: Int -> Matrix
frame idx = V.create $ do
ini <- V.unsafeThaw initial
fin <- V.unsafeThaw final
mat <- VM.replicate (rows * cols) emptyCell
for_ [0 .. rows - 1] $ \y -> do
VM.copy
(VM.slice (y * cols) (cols - offset) mat)
(VM.slice (y * cols + offset) (cols - offset) ini)
VM.copy
(VM.slice (y * cols + cols - offset) offset mat)
(VM.slice (y * cols) offset fin)
pure mat
where
offset = max 0 . min cols . (round :: Double -> Int) $
fromIntegral (idx + 1) / fromIntegral frames * fromIntegral cols
--------------------------------------------------------------------------------
$(A.deriveFromJSON A.dropPrefixOptions ''Config)