-- | Render all queued storages
renderStorages :: LambdaCubeEnv t -> IO ()
renderStorages e@LambdaCubeEnv{..} = do
  renderings <- readIORef lambdaEnvRenderOrder
  mapM_ renderStorage renderings
  where
  renderStorage si = do
    ms <- getStorageInternal si e
    case ms of
      Nothing -> return ()
      Just storage -> do
        mr <- getRendererInternal (storageScheme si) e
        case mr of
          Nothing -> return ()
          Just renderer -> do
            mres <- liftIO $ LambdaCubeGL.setStorage renderer storage
            case mres of
              Just er -> throwM $! PipeLineIncompatible si (T.pack er)
              Nothing -> liftIO $ LambdaCubeGL.renderFrame renderer

-- | Implementation of 'MonadLambdaCube' API.
--
-- [@t@] FRP engine, you could ignore this parameter as it resolved only at main
-- function of your application.
--
-- [@m@] Underlying game modules, next layer in monad stack.
--
-- [@a@] Result of computation.
--
-- How to embed the monad into your app:
--
-- @
-- type AppStack t = LambdaCubeT t (LoggingT t (TimerT t (GameMonad t)))
--
-- newtype AppMonad t a = AppMonad { runAppMonad :: AppStack t a}
--   deriving (Functor, Applicative, Monad, MonadFix)
-- @
--
-- And you will need some boilerplate code for instance deriving, see
-- `examples/Example01.hs` for full example.
--
renderStorages :: LambdaCubeEnv t -> IO ()
renderStorages e@LambdaCubeEnv{..} = do
  renderings <- readIORef lambdaEnvRenderOrder
  mapM_ renderStorage renderings
  where
  renderStorage si = do
    ms <- getStorageInternal si e
    case ms of
      Nothing -> return ()
      Just storage -> do
        mr <- getRendererInternal (storageScheme si) e
        case mr of
          Nothing -> return ()
          Just renderer -> do
            mres <- liftIO $ LambdaCubeGL.setStorage renderer storage
            case mres of
              Just er -> throwM $! PipeLineIncompatible si (T.pack er)
              Nothing -> liftIO $ LambdaCubeGL.renderFrame renderer

-- | Implementation of 'MonadLambdaCube' API.
--
-- [@t@] FRP engine, you could ignore this parameter as it resolved only at main
-- function of your application.
--
-- [@m@] Underlying game modules, next layer in monad stack.
--
-- [@a@] Result of computation.
--
-- How to embed the monad into your app:
--
-- @
-- type AppStack t = LambdaCubeT t (LoggingT t (TimerT t (GameMonad t)))
--
-- newtype AppMonad t a = AppMonad { runAppMonad :: AppStack t a}
--   deriving (Functor, Applicative, Monad, MonadFix)
-- @
--
-- And you will need some boilerplate code for instance deriving, see
-- `examples/Example01.hs` for full example.
--
renderStorages e@LambdaCubeEnv{..} = do
  renderings <- readIORef lambdaEnvRenderOrder
  mapM_ renderStorage renderings
  where
  renderStorage si = do
    ms <- getStorageInternal si e
    case ms of
      Nothing -> return ()
      Just storage -> do
        mr <- getRendererInternal (storageScheme si) e
        case mr of
          Nothing -> return ()
          Just renderer -> do
            mres <- liftIO $ LambdaCubeGL.setStorage renderer storage
            case mres of
              Just er -> throwM $! PipeLineIncompatible si (T.pack er)
              Nothing -> liftIO $ LambdaCubeGL.renderFrame renderer

-- | Implementation of 'MonadLambdaCube' API.
--
-- [@t@] FRP engine, you could ignore this parameter as it resolved only at main
-- function of your application.
--
-- [@m@] Underlying game modules, next layer in monad stack.
--
-- [@a@] Result of computation.
--
-- How to embed the monad into your app:
--
-- @
-- type AppStack t = LambdaCubeT t (LoggingT t (TimerT t (GameMonad t)))
--
-- newtype AppMonad t a = AppMonad { runAppMonad :: AppStack t a}
--   deriving (Functor, Applicative, Monad, MonadFix)
-- @
--
-- And you will need some boilerplate code for instance deriving, see
-- `examples/Example01.hs` for full example.
--