module LiveCoding.Gloss.PictureM
  ( module LiveCoding.Gloss.PictureM
  , module X
  ) where

-- transformers
import Control.Monad.Trans.Class
import Control.Monad.Trans.Reader as X
import Control.Monad.Trans.Writer.Strict

-- gloss
import Graphics.Gloss
import Graphics.Gloss.Interface.IO.Game

-- essence-of-live-coding
import LiveCoding

{- | The monad transformer that captures the effects of gloss,
which are reading events and writing pictures.

You can call these effects for example by...

* ...using 'ask' to read the events that occurred,
* ...composing a cell with 'addPicture' to paint a picture.
-}
type PictureT m = ReaderT [Event] (WriterT Picture m)

-- | 'PictureT' specialised to the 'IO' monad.
type PictureM = PictureT IO

-- | Run the effects of the gloss monad stack by explicitly passing events and pictures.
runPictureT
  :: Monad m
  => Cell (PictureT m) a b
  -> Cell m ([Event], a) (Picture, b)
runPictureT :: Cell (PictureT m) a b -> Cell m ([Event], a) (Picture, b)
runPictureT = Cell (WriterT Picture m) ([Event], a) b
-> Cell m ([Event], a) (Picture, b)
forall w (m :: * -> *) a b.
(Monoid w, Monad m) =>
Cell (WriterT w m) a b -> Cell m a (w, b)
runWriterC (Cell (WriterT Picture m) ([Event], a) b
 -> Cell m ([Event], a) (Picture, b))
-> (Cell (PictureT m) a b
    -> Cell (WriterT Picture m) ([Event], a) b)
-> Cell (PictureT m) a b
-> Cell m ([Event], a) (Picture, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cell (PictureT m) a b -> Cell (WriterT Picture m) ([Event], a) b
forall (m :: * -> *) r a b.
Monad m =>
Cell (ReaderT r m) a b -> Cell m (r, a) b
runReaderC'

addPicture :: Monad m => Cell (PictureT m) Picture ()
addPicture :: Cell (PictureT m) Picture ()
addPicture = (Picture -> ReaderT [Event] (WriterT Picture m) ())
-> Cell (PictureT m) Picture ()
forall a (m :: * -> *) b. (a -> m b) -> Cell m a b
arrM ((Picture -> ReaderT [Event] (WriterT Picture m) ())
 -> Cell (PictureT m) Picture ())
-> (Picture -> ReaderT [Event] (WriterT Picture m) ())
-> Cell (PictureT m) Picture ()
forall a b. (a -> b) -> a -> b
$ WriterT Picture m () -> ReaderT [Event] (WriterT Picture m) ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT Picture m () -> ReaderT [Event] (WriterT Picture m) ())
-> (Picture -> WriterT Picture m ())
-> Picture
-> ReaderT [Event] (WriterT Picture m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Picture -> WriterT Picture m ()
forall (m :: * -> *) w. Monad m => w -> WriterT w m ()
tell