-- | Run the game application.
module Dyna.Gloss.Run(
  -- * App execution
  Run,
  Spec(..),
  defSpec,
  runApp,
  -- * IO interface
  mouse,
  mouseV,
  isDrag,
  drag,
  dragV,
  mouseA,
  mouseRight,
  mouseLeft,
  mouseWheel,
  Click(..),
  getClicks,
  getFrames,
  getResize,
  keyUp, keyDown,
  charUp, charDown,
  -- * Re-exports
  Key(..),
  SpecialKey(..),
  MouseButton(..),
  KeyState(..),
  Modifiers(..),
) where

import Control.Exception.Lifted
import Control.Concurrent.Chan.Unagi qualified as U
import Control.Monad.Reader
import Data.IORef

import Graphics.Gloss
import Graphics.Gloss.Interface.IO.Game
import Dyna qualified as D
import Dyna.Gloss.Types
import Dyna.Gloss.Data.Vec

-- | Initial parameters for the Game.
data Spec = Spec
  { Spec -> Display
spec'display    :: Display   -- ^ display settings
  , Spec -> Color
spec'background :: Color     -- ^ background color to clear each frame
  , Spec -> Int
spec'steps      :: Int       -- ^ number of steps for simulation
  }

-- | Default settings. Runs in ullscreen mode.
defSpec :: Spec
defSpec :: Spec
defSpec = Display -> Color -> Int -> Spec
Spec Display
FullScreen Color
white Int
1

-- | Run the aplication. It accepts initial settings
-- and the dynamic value of pictures wrapped in the Run monad.
--
-- Note that to work properly we need to compile to executable with
-- options -O2 and -threaded. The function does not work in ghci or with runhaskell
-- because it requires support for multiple threads.
--
-- Define the application with the Main module. Then compie it:
--
-- > stack exec -- ghc -O2 -threaded dyna-gloss/examples/Ball.hs
--
-- And run the result:
--
-- > 	./dyna-gloss/examples/Ball
--
-- How it works? It runs the dynamic process at the background thread and
-- every time the gloss function requests new frame it takes a snapshot of the current
-- value of the main dynamic process which produces pictures. It's exactly what gloss
-- simulation function needs to render it on the screen.
runApp :: Spec -> Run (Dyn Picture) -> IO ()
runApp :: Spec -> Run (Dyn Picture) -> IO ()
runApp Spec{Int
Display
Color
spec'steps :: Int
spec'background :: Color
spec'display :: Display
spec'steps :: Spec -> Int
spec'background :: Spec -> Color
spec'display :: Spec -> Display
..} Run (Dyn Picture)
dynAct = do
  Env
env <- IO Env
newEnv
  DynRef Run Picture
ref <- ReaderT Env IO (DynRef Run Picture)
-> Env -> IO (DynRef Run Picture)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Run (DynRef Run Picture) -> ReaderT Env IO (DynRef Run Picture)
forall a. Run a -> ReaderT Env IO a
unRun (Run (DynRef Run Picture) -> ReaderT Env IO (DynRef Run Picture))
-> Run (DynRef Run Picture) -> ReaderT Env IO (DynRef Run Picture)
forall a b. (a -> b) -> a -> b
$ Dyn Run Picture -> Run (DynRef Run Picture)
forall (m :: * -> *) a. Frp m => Dyn m a -> m (DynRef m a)
D.runDyn (Dyn Run Picture -> Run (DynRef Run Picture))
-> (Dyn Picture -> Dyn Run Picture)
-> Dyn Picture
-> Run (DynRef Run Picture)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dyn Picture -> Dyn Run Picture
forall a. Dyn a -> Dyn Run a
unDyn (Dyn Picture -> Run (DynRef Run Picture))
-> Run (Dyn Picture) -> Run (DynRef Run Picture)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Run (Dyn Picture)
dynAct) Env
env
  Display
-> Color
-> Int
-> DynRef Run Picture
-> (DynRef Run Picture -> IO Picture)
-> (Event -> DynRef Run Picture -> IO (DynRef Run Picture))
-> (Float -> DynRef Run Picture -> IO (DynRef Run Picture))
-> IO ()
forall world.
Display
-> Color
-> Int
-> world
-> (world -> IO Picture)
-> (Event -> world -> IO world)
-> (Float -> world -> IO world)
-> IO ()
playIO Display
spec'display Color
spec'background Int
spec'steps DynRef Run Picture
ref (Env -> DynRef Run Picture -> IO Picture
forall a. Env -> DynRef Run a -> IO a
draw Env
env) (Env -> Event -> DynRef Run Picture -> IO (DynRef Run Picture)
forall b. Env -> Event -> b -> IO b
onEvents Env
env) (Env -> Float -> DynRef Run Picture -> IO (DynRef Run Picture)
forall b. Env -> Float -> b -> IO b
onIterate Env
env)
    IO () -> IO () -> IO ()
forall (m :: * -> *) a b.
MonadBaseControl IO m =>
m a -> m b -> m a
`finally` (ReaderT Env IO () -> Env -> IO ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Run () -> ReaderT Env IO ()
forall a. Run a -> ReaderT Env IO a
unRun (Run () -> ReaderT Env IO ()) -> Run () -> ReaderT Env IO ()
forall a b. (a -> b) -> a -> b
$ DynRef Run Picture -> Run ()
forall (m :: * -> *) a. Frp m => DynRef m a -> m ()
D.cancelDyn DynRef Run Picture
ref) Env
env)
  where
    draw :: Env -> DynRef Run a -> IO a
draw Env
env DynRef Run a
ref = ReaderT Env IO a -> Env -> IO a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Run a -> ReaderT Env IO a
forall a. Run a -> ReaderT Env IO a
unRun (Run a -> ReaderT Env IO a) -> Run a -> ReaderT Env IO a
forall a b. (a -> b) -> a -> b
$ DynRef Run a -> Run a
forall (m :: * -> *) a. Frp m => DynRef m a -> m a
D.readDyn DynRef Run a
ref) Env
env

    onEvents :: Env -> Event -> b -> IO b
onEvents Env{UChan Float
UChan (Int, Int)
UChan Event
UChan Click
IORef Vec
env'mouseDif2 :: Env -> IORef Vec
env'mouseDif1 :: Env -> IORef Vec
env'mousePos :: Env -> IORef Vec
env'keyChan :: Env -> UChan Click
env'resizeChan :: Env -> UChan (Int, Int)
env'eventChan :: Env -> UChan Event
env'frameChan :: Env -> UChan Float
env'mouseDif2 :: IORef Vec
env'mouseDif1 :: IORef Vec
env'mousePos :: IORef Vec
env'keyChan :: UChan Click
env'resizeChan :: UChan (Int, Int)
env'eventChan :: UChan Event
env'frameChan :: UChan Float
..} Event
evt b
ref = do
      case Event
evt of
        EventResize (Int, Int)
sizes      -> InChan (Int, Int) -> (Int, Int) -> IO ()
forall a. InChan a -> a -> IO ()
U.writeChan (UChan (Int, Int) -> InChan (Int, Int)
forall a b. (a, b) -> a
fst UChan (Int, Int)
env'resizeChan) (Int, Int)
sizes
        EventMotion (Float
x, Float
y)     -> do
          let pos :: Vec
pos = Float -> Float -> Vec
Vec Float
x Float
y
          Vec
prevPos  <- IORef Vec -> IO Vec
forall a. IORef a -> IO a
readIORef IORef Vec
env'mousePos
          Vec
prevDif1 <- IORef Vec -> IO Vec
forall a. IORef a -> IO a
readIORef IORef Vec
env'mouseDif1
          let dif1 :: Vec
dif1 = Vec
pos Vec -> Vec -> Vec
forall a. Num a => a -> a -> a
- Vec
prevPos
          IORef Vec -> Vec -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Vec
env'mousePos Vec
pos
          IORef Vec -> Vec -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Vec
env'mouseDif1 Vec
dif1
          IORef Vec -> Vec -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Vec
env'mouseDif2 (Vec
dif1 Vec -> Vec -> Vec
forall a. Num a => a -> a -> a
- Vec
prevDif1)
        EventKey Key
k KeyState
st Modifiers
mods (Float, Float)
pos -> InChan Click -> Click -> IO ()
forall a. InChan a -> a -> IO ()
U.writeChan (UChan Click -> InChan Click
forall a b. (a, b) -> a
fst UChan Click
env'keyChan) (Key -> KeyState -> Modifiers -> Vec -> Click
Click Key
k KeyState
st Modifiers
mods ((Float, Float) -> Vec
fromTuple (Float, Float)
pos))
      b -> IO b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
ref

    onIterate :: Env -> Float -> b -> IO b
onIterate Env{UChan Float
UChan (Int, Int)
UChan Event
UChan Click
IORef Vec
env'mouseDif2 :: IORef Vec
env'mouseDif1 :: IORef Vec
env'mousePos :: IORef Vec
env'keyChan :: UChan Click
env'resizeChan :: UChan (Int, Int)
env'eventChan :: UChan Event
env'frameChan :: UChan Float
env'mouseDif2 :: Env -> IORef Vec
env'mouseDif1 :: Env -> IORef Vec
env'mousePos :: Env -> IORef Vec
env'keyChan :: Env -> UChan Click
env'resizeChan :: Env -> UChan (Int, Int)
env'eventChan :: Env -> UChan Event
env'frameChan :: Env -> UChan Float
..} Float
time b
ref = do
      InChan Float -> Float -> IO ()
forall a. InChan a -> a -> IO ()
U.writeChan (UChan Float -> InChan Float
forall a b. (a, b) -> a
fst UChan Float
env'frameChan) Float
time
      b -> IO b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
ref

----------------------------------------------------------------

-- | Read mouse positions. It produces dynamic of vectors. @(0, 0)@ is a center of the screen.
mouse :: Dyn Vec
mouse :: Dyn Vec
mouse = Dyn Run Vec -> Dyn Vec
forall a. Dyn Run a -> Dyn a
Dyn (Dyn Run Vec -> Dyn Vec) -> Dyn Run Vec -> Dyn Vec
forall a b. (a -> b) -> a -> b
$ Run Vec -> Dyn Run Vec
forall (m :: * -> *) a. Frp m => m a -> Dyn m a
D.constDyn (Run Vec -> Dyn Run Vec) -> Run Vec -> Dyn Run Vec
forall a b. (a -> b) -> a -> b
$ do
  IORef Vec
ref <- (Env -> IORef Vec) -> Run (IORef Vec)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> IORef Vec
env'mousePos
  IO Vec -> Run Vec
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Vec -> Run Vec) -> IO Vec -> Run Vec
forall a b. (a -> b) -> a -> b
$ IORef Vec -> IO Vec
forall a. IORef a -> IO a
readIORef IORef Vec
ref

-- | Mouse velocity or displacement
mouseV :: Dyn Vec
mouseV :: Dyn Vec
mouseV = Dyn Run Vec -> Dyn Vec
forall a. Dyn Run a -> Dyn a
Dyn (Dyn Run Vec -> Dyn Vec) -> Dyn Run Vec -> Dyn Vec
forall a b. (a -> b) -> a -> b
$ Run Vec -> Dyn Run Vec
forall (m :: * -> *) a. Frp m => m a -> Dyn m a
D.constDyn (Run Vec -> Dyn Run Vec) -> Run Vec -> Dyn Run Vec
forall a b. (a -> b) -> a -> b
$ do
  IORef Vec
ref <- (Env -> IORef Vec) -> Run (IORef Vec)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> IORef Vec
env'mouseDif1
  IO Vec -> Run Vec
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Vec -> Run Vec) -> IO Vec -> Run Vec
forall a b. (a -> b) -> a -> b
$ IORef Vec -> IO Vec
forall a. IORef a -> IO a
readIORef IORef Vec
ref

-- | Mouse accelartion or speed of displacement
mouseA :: Dyn Vec
mouseA :: Dyn Vec
mouseA = Dyn Run Vec -> Dyn Vec
forall a. Dyn Run a -> Dyn a
Dyn (Dyn Run Vec -> Dyn Vec) -> Dyn Run Vec -> Dyn Vec
forall a b. (a -> b) -> a -> b
$ Run Vec -> Dyn Run Vec
forall (m :: * -> *) a. Frp m => m a -> Dyn m a
D.constDyn (Run Vec -> Dyn Run Vec) -> Run Vec -> Dyn Run Vec
forall a b. (a -> b) -> a -> b
$ do
  IORef Vec
ref <- (Env -> IORef Vec) -> Run (IORef Vec)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> IORef Vec
env'mouseDif2
  IO Vec -> Run Vec
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Vec -> Run Vec) -> IO Vec -> Run Vec
forall a b. (a -> b) -> a -> b
$ IORef Vec -> IO Vec
forall a. IORef a -> IO a
readIORef IORef Vec
ref

isDrag :: MouseButton -> Dyn Bool
isDrag :: MouseButton -> Dyn Bool
isDrag MouseButton
btn = Dyn Run Bool -> Dyn Bool
forall a. Dyn Run a -> Dyn a
Dyn (Dyn Run Bool -> Dyn Bool) -> Dyn Run Bool -> Dyn Bool
forall a b. (a -> b) -> a -> b
$ (KeyState -> Bool -> Bool)
-> Bool -> Evt Run KeyState -> Dyn Run Bool
forall (m :: * -> *) a b.
Frp m =>
(a -> b -> b) -> b -> Evt m a -> Dyn m b
D.scanD KeyState -> Bool -> Bool
forall p. KeyState -> p -> Bool
collect Bool
False (Evt Run KeyState -> Dyn Run Bool)
-> Evt Run KeyState -> Dyn Run Bool
forall a b. (a -> b) -> a -> b
$ (Click -> Maybe KeyState) -> Evt Run Click -> Evt Run KeyState
forall (m :: * -> *) a b.
Frp m =>
(a -> Maybe b) -> Evt m a -> Evt m b
D.mapMay Click -> Maybe KeyState
go (Evt Run Click -> Evt Run KeyState)
-> Evt Run Click -> Evt Run KeyState
forall a b. (a -> b) -> a -> b
$ Evt Click -> Evt Run Click
forall a. Evt a -> Evt Run a
unEvt Evt Click
getClicks
  where
    go :: Click -> Maybe KeyState
go (Click Key
key KeyState
st Modifiers
mods Vec
pos) = case Key
key of
      MouseButton MouseButton
mbtn | MouseButton
mbtn MouseButton -> MouseButton -> Bool
forall a. Eq a => a -> a -> Bool
== MouseButton
btn -> KeyState -> Maybe KeyState
forall a. a -> Maybe a
Just KeyState
st
      Key
_                              -> Maybe KeyState
forall a. Maybe a
Nothing

    collect :: KeyState -> p -> Bool
collect KeyState
a p
st = case KeyState
a of
      KeyState
Up   -> Bool
False
      KeyState
Down -> Bool
True


-- | Displacement on drag, if no drag it becomes zero
dragV :: MouseButton -> Dyn Vec
dragV :: MouseButton -> Dyn Vec
dragV MouseButton
btn = (\Bool
x -> if Bool
x then Vec -> Vec
forall a. a -> a
id else Vec -> Vec -> Vec
forall a b. a -> b -> a
const Vec
0) (Bool -> Vec -> Vec) -> Dyn Bool -> Dyn (Vec -> Vec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MouseButton -> Dyn Bool
isDrag MouseButton
btn Dyn (Vec -> Vec) -> Dyn Vec -> Dyn Vec
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Dyn Vec
mouseV

-- | Position of the mouse during drag, if no drag it becomes zero
drag :: MouseButton -> Dyn Vec
drag :: MouseButton -> Dyn Vec
drag MouseButton
btn = (\Bool
x -> if Bool
x then Vec -> Vec
forall a. a -> a
id else Vec -> Vec -> Vec
forall a b. a -> b -> a
const Vec
0) (Bool -> Vec -> Vec) -> Dyn Bool -> Dyn (Vec -> Vec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MouseButton -> Dyn Bool
isDrag MouseButton
btn Dyn (Vec -> Vec) -> Dyn Vec -> Dyn Vec
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Dyn Vec
mouse

-- | Event stream of clicks of the mouse right button
mouseRight :: Evt Vec
mouseRight :: Evt Vec
mouseRight = Evt Run Vec -> Evt Vec
forall a. Evt Run a -> Evt a
Evt (Evt Run Vec -> Evt Vec) -> Evt Run Vec -> Evt Vec
forall a b. (a -> b) -> a -> b
$ (Click -> Maybe Vec) -> Evt Run Click -> Evt Run Vec
forall (m :: * -> *) a b.
Frp m =>
(a -> Maybe b) -> Evt m a -> Evt m b
D.mapMay Click -> Maybe Vec
go (Evt Run Click -> Evt Run Vec) -> Evt Run Click -> Evt Run Vec
forall a b. (a -> b) -> a -> b
$ Evt Click -> Evt Run Click
forall a. Evt a -> Evt Run a
unEvt Evt Click
getClicks
  where
    go :: Click -> Maybe Vec
go = \case
      Click (MouseButton MouseButton
RightButton) KeyState
Down Modifiers
mods Vec
pos -> Vec -> Maybe Vec
forall a. a -> Maybe a
Just Vec
pos
      Click
_                                             -> Maybe Vec
forall a. Maybe a
Nothing

-- | Event stream of key up actions
keyUp :: Key -> Evt Modifiers
keyUp :: Key -> Evt Modifiers
keyUp = KeyState -> Key -> Evt Modifiers
keyBy KeyState
Up

-- | Event stream of key down actions
keyDown :: Key -> Evt Modifiers
keyDown :: Key -> Evt Modifiers
keyDown = KeyState -> Key -> Evt Modifiers
keyBy KeyState
Down

-- | Event stream of char press up actions
charUp :: Char -> Evt Modifiers
charUp :: Char -> Evt Modifiers
charUp = Key -> Evt Modifiers
keyUp (Key -> Evt Modifiers) -> (Char -> Key) -> Char -> Evt Modifiers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Key
Char

-- | Event stream of char press down actions
charDown :: Char -> Evt Modifiers
charDown :: Char -> Evt Modifiers
charDown = Key -> Evt Modifiers
keyDown (Key -> Evt Modifiers) -> (Char -> Key) -> Char -> Evt Modifiers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Key
Char

keyBy :: KeyState -> Key -> Evt Modifiers
keyBy :: KeyState -> Key -> Evt Modifiers
keyBy KeyState
st' Key
key' = Evt Run Modifiers -> Evt Modifiers
forall a. Evt Run a -> Evt a
Evt (Evt Run Modifiers -> Evt Modifiers)
-> Evt Run Modifiers -> Evt Modifiers
forall a b. (a -> b) -> a -> b
$ (Click -> Maybe Modifiers) -> Evt Run Click -> Evt Run Modifiers
forall (m :: * -> *) a b.
Frp m =>
(a -> Maybe b) -> Evt m a -> Evt m b
D.mapMay Click -> Maybe Modifiers
go (Evt Run Click -> Evt Run Modifiers)
-> Evt Run Click -> Evt Run Modifiers
forall a b. (a -> b) -> a -> b
$ Evt Click -> Evt Run Click
forall a. Evt a -> Evt Run a
unEvt Evt Click
getClicks
  where
    go :: Click -> Maybe Modifiers
go (Click Key
key KeyState
st Modifiers
mods Vec
pos)
      | Key
key Key -> Key -> Bool
forall a. Eq a => a -> a -> Bool
== Key
key' Bool -> Bool -> Bool
&& KeyState
st KeyState -> KeyState -> Bool
forall a. Eq a => a -> a -> Bool
== KeyState
st' = Modifiers -> Maybe Modifiers
forall a. a -> Maybe a
Just Modifiers
mods
      | Bool
otherwise                = Maybe Modifiers
forall a. Maybe a
Nothing

-- | Event stream of clicks of the mouse left button
mouseLeft :: Evt Vec
mouseLeft :: Evt Vec
mouseLeft = Evt Run Vec -> Evt Vec
forall a. Evt Run a -> Evt a
Evt (Evt Run Vec -> Evt Vec) -> Evt Run Vec -> Evt Vec
forall a b. (a -> b) -> a -> b
$ (Click -> Maybe Vec) -> Evt Run Click -> Evt Run Vec
forall (m :: * -> *) a b.
Frp m =>
(a -> Maybe b) -> Evt m a -> Evt m b
D.mapMay Click -> Maybe Vec
go (Evt Run Click -> Evt Run Vec) -> Evt Run Click -> Evt Run Vec
forall a b. (a -> b) -> a -> b
$ Evt Click -> Evt Run Click
forall a. Evt a -> Evt Run a
unEvt Evt Click
getClicks
  where
    go :: Click -> Maybe Vec
go = \case
      Click (MouseButton MouseButton
LeftButton) KeyState
Down Modifiers
mods Vec
pos -> Vec -> Maybe Vec
forall a. a -> Maybe a
Just Vec
pos
      Click
_                                            -> Maybe Vec
forall a. Maybe a
Nothing

-- | Mouse wheel displacement.
-- If positive then it goes up, if negative then it goes down.
mouseWheel :: Evt Float
mouseWheel :: Evt Float
mouseWheel = Evt Run Float -> Evt Float
forall a. Evt Run a -> Evt a
Evt (Evt Run Float -> Evt Float) -> Evt Run Float -> Evt Float
forall a b. (a -> b) -> a -> b
$ (Click -> Maybe Float) -> Evt Run Click -> Evt Run Float
forall (m :: * -> *) a b.
Frp m =>
(a -> Maybe b) -> Evt m a -> Evt m b
D.mapMay Click -> Maybe Float
forall a. Num a => Click -> Maybe a
go (Evt Run Click -> Evt Run Float) -> Evt Run Click -> Evt Run Float
forall a b. (a -> b) -> a -> b
$ Evt Click -> Evt Run Click
forall a. Evt a -> Evt Run a
unEvt Evt Click
getClicks
  where
    go :: Click -> Maybe a
go (Click Key
key KeyState
st Modifiers
mods Vec
pos) = case Key
key of
      MouseButton MouseButton
WheelUp   -> a -> Maybe a
forall a. a -> Maybe a
Just a
1
      MouseButton MouseButton
WheelDown -> a -> Maybe a
forall a. a -> Maybe a
Just (-a
1)
      Key
_                     -> Maybe a
forall a. Maybe a
Nothing

-- | Reads generic click events
getClicks :: Evt Click
getClicks :: Evt Click
getClicks = Evt Run Click -> Evt Click
forall a. Evt Run a -> Evt a
Evt (Evt Run Click -> Evt Click) -> Evt Run Click -> Evt Click
forall a b. (a -> b) -> a -> b
$ ((Click -> Run ()) -> Run ()) -> Evt Run Click
forall (m :: * -> *) a. ((a -> m ()) -> m ()) -> Evt m a
D.Evt (((Click -> Run ()) -> Run ()) -> Evt Run Click)
-> ((Click -> Run ()) -> Run ()) -> Evt Run Click
forall a b. (a -> b) -> a -> b
$ \Click -> Run ()
go -> do
  UChan Click
keyChan <- (Env -> UChan Click) -> Run (UChan Click)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> UChan Click
env'keyChan
  Evt Run Click -> (Click -> Run ()) -> Run ()
forall (m :: * -> *) a. Evt m a -> (a -> m ()) -> m ()
D.runEvt (InChan Click -> Evt Run Click
forall (m :: * -> *) a. Frp m => InChan a -> Evt m a
D.uchanEvt (UChan Click -> InChan Click
forall a b. (a, b) -> a
fst UChan Click
keyChan)) Click -> Run ()
go

-- | Reads frame updates. Value of the event is a time that has passed since the previous frame.
--
-- Note that if we want to use the sort of event stream as a timeline for the game or simulation
-- we can also use time utilities from the FRP library: @clock@, @pulse@, @ticks@, @timer@.
getFrames :: Evt Float
getFrames :: Evt Float
getFrames = Evt Run Float -> Evt Float
forall a. Evt Run a -> Evt a
Evt (Evt Run Float -> Evt Float) -> Evt Run Float -> Evt Float
forall a b. (a -> b) -> a -> b
$ ((Float -> Run ()) -> Run ()) -> Evt Run Float
forall (m :: * -> *) a. ((a -> m ()) -> m ()) -> Evt m a
D.Evt (((Float -> Run ()) -> Run ()) -> Evt Run Float)
-> ((Float -> Run ()) -> Run ()) -> Evt Run Float
forall a b. (a -> b) -> a -> b
$ \Float -> Run ()
go -> do
  UChan Float
frameChan <- (Env -> UChan Float) -> Run (UChan Float)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> UChan Float
env'frameChan
  Evt Run Float -> (Float -> Run ()) -> Run ()
forall (m :: * -> *) a. Evt m a -> (a -> m ()) -> m ()
D.runEvt (InChan Float -> Evt Run Float
forall (m :: * -> *) a. Frp m => InChan a -> Evt m a
D.uchanEvt (UChan Float -> InChan Float
forall a b. (a, b) -> a
fst UChan Float
frameChan)) Float -> Run ()
go

-- | Reads window resize events
getResize :: Evt (Int, Int)
getResize :: Evt (Int, Int)
getResize = Evt Run (Int, Int) -> Evt (Int, Int)
forall a. Evt Run a -> Evt a
Evt (Evt Run (Int, Int) -> Evt (Int, Int))
-> Evt Run (Int, Int) -> Evt (Int, Int)
forall a b. (a -> b) -> a -> b
$ (((Int, Int) -> Run ()) -> Run ()) -> Evt Run (Int, Int)
forall (m :: * -> *) a. ((a -> m ()) -> m ()) -> Evt m a
D.Evt ((((Int, Int) -> Run ()) -> Run ()) -> Evt Run (Int, Int))
-> (((Int, Int) -> Run ()) -> Run ()) -> Evt Run (Int, Int)
forall a b. (a -> b) -> a -> b
$ \(Int, Int) -> Run ()
go -> do
  UChan (Int, Int)
resizeChan <- (Env -> UChan (Int, Int)) -> Run (UChan (Int, Int))
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> UChan (Int, Int)
env'resizeChan
  Evt Run (Int, Int) -> ((Int, Int) -> Run ()) -> Run ()
forall (m :: * -> *) a. Evt m a -> (a -> m ()) -> m ()
D.runEvt (InChan (Int, Int) -> Evt Run (Int, Int)
forall (m :: * -> *) a. Frp m => InChan a -> Evt m a
D.uchanEvt (InChan (Int, Int) -> Evt Run (Int, Int))
-> InChan (Int, Int) -> Evt Run (Int, Int)
forall a b. (a -> b) -> a -> b
$ UChan (Int, Int) -> InChan (Int, Int)
forall a b. (a, b) -> a
fst UChan (Int, Int)
resizeChan) (Int, Int) -> Run ()
go