{-# 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