{-# LANGUAGE RankNTypes #-}

-- We export this stuff separately so we don't clutter up the
-- API of the Brillo module.

{-| Simulate mode is for producing an animation of some model who's picture
  changes over finite time steps. The behavior of the model can also depent
  on the current `ViewPort`.
-}
module Brillo.Interface.Pure.Simulate (
  module Brillo.Data.Display,
  module Brillo.Data.Picture,
  module Brillo.Data.Color,
  simulate,
  ViewPort (..),
)
where

import Brillo.Data.Color
import Brillo.Data.Display
import Brillo.Data.Picture
import Brillo.Data.ViewPort
import Brillo.Internals.Interface.Backend
import Brillo.Internals.Interface.Simulate


{-| Run a finite-time-step simulation in a window. You decide how the model is represented,
     how to convert the model to a picture, and how to advance the model for each unit of time.
     This function does the rest.

  Once the window is open you can use the same commands as with `display`.
-}
simulate
  :: Display
  -- ^ Display mode.
  -> Color
  -- ^ Background color.
  -> Int
  -- ^ Number of simulation steps to take for each second of real time.
  -> model
  -- ^ The initial model.
  -> (model -> Picture)
  -- ^ A function to convert the model to a picture.
  -> (ViewPort -> Float -> model -> model)
  -- ^ A function to step the model one iteration. It is passed the
  --     current viewport and the amount of time for this simulation
  --     step (in seconds).
  -> IO ()
simulate :: forall model.
Display
-> Color
-> Int
-> model
-> (model -> Picture)
-> (ViewPort -> Float -> model -> model)
-> IO ()
simulate
  Display
display
  Color
backColor
  Int
simResolution
  model
modelStart
  model -> Picture
modelToPicture
  ViewPort -> Float -> model -> model
modelStep =
    do
      ()
_ <-
        GLFWState
-> Display
-> Color
-> Int
-> model
-> (model -> IO Picture)
-> (ViewPort -> Float -> model -> IO model)
-> IO ()
forall model a.
Backend a =>
a
-> Display
-> Color
-> Int
-> model
-> (model -> IO Picture)
-> (ViewPort -> Float -> model -> IO model)
-> IO ()
simulateWithBackendIO
          GLFWState
defaultBackendState
          Display
display
          Color
backColor
          Int
simResolution
          model
modelStart
          (Picture -> IO Picture
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Picture -> IO Picture)
-> (model -> Picture) -> model -> IO Picture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. model -> Picture
modelToPicture)
          (\ViewPort
view Float
time model
model -> model -> IO model
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (model -> IO model) -> model -> IO model
forall a b. (a -> b) -> a -> b
$ ViewPort -> Float -> model -> model
modelStep ViewPort
view Float
time model
model)
      () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()