imj-base-0.1.0.2: src/Imj/Graphics/Class/DiscreteMorphing.hs
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleInstances #-}
module Imj.Graphics.Class.DiscreteMorphing
( DiscreteMorphing(..)
-- * Reexport
, module Imj.Graphics.Class.DiscreteDistance
, module Imj.Graphics.Class.Drawable
, module Imj.Graphics.Class.Draw
, MonadIO
, MonadReader
) where
import Imj.Prelude
import Control.Monad.IO.Class(MonadIO)
import Control.Monad.Reader.Class(MonadReader)
import Imj.Graphics.Class.DiscreteDistance
import Imj.Graphics.Class.Draw
import Imj.Graphics.Class.Drawable
{-| Morph between /drawn/ representations of 'Drawble's.
[Drawn representation of 'Drawable' x]
The visual result of IO rendering commands induced by a 'draw' @x@ call.
Instances should statisfy the following constraints:
* A morphing between /drawn/ representations of A and B starts at the /drawn/
representation of A and ends at the /drawn/ represntation of B:
\( \forall (\, from, to)\, \in v, \)
@
d = distance from to
drawMorphing from to 0 "is the same as" draw from
drawMorphing from to d "is the same as" draw to
@
* The morphing path is composed of strictly distinct /drawings/.
* The /drawings/, when seen in rapid succession, should visually produce a
/smooth/ transformation from the first to the last /drawing/. -}
class (DiscreteDistance v, Drawable v)
=> DiscreteMorphing v where
-- | Draws the morphing between the /drawn/ representations of 2 \(v\).
drawMorphing :: (Draw e, MonadReader e m, MonadIO m)
=> v -- ^ first value
-> v -- ^ last value
-> Int -- ^ the current step
-> m ()
-- | Draws the morphing between the /drawn/ representations of several \(v\).
{-# INLINABLE drawMorphingSuccessive #-}
drawMorphingSuccessive :: (Draw e, MonadReader e m, MonadIO m)
=> Successive v
-> Int
-> m ()
drawMorphingSuccessive (Successive []) _ = error "empty successive"
drawMorphingSuccessive (Successive [a]) _ = drawMorphing a a 0
drawMorphingSuccessive (Successive l@(a:b:_)) i
| i <= 0 = drawMorphing a a 0
| i >= lf = drawMorphingSuccessive (Successive $ tail l) $ i-lf
| otherwise = drawMorphing a b i
where lf = pred $ distance a b