gore-and-ash-lambdacube-0.2.0.0: src/Game/GoreAndAsh/LambdaCube/API.hs
{-|
Module : Game.GoreAndAsh.LambdaCube.API
Description : Monadic and arrow API for module
Copyright : (c) Anton Gushcha, 2016
License : BSD3
Maintainer : ncrashed@gmail.com
Stability : experimental
Portability : POSIX
-}
module Game.GoreAndAsh.LambdaCube.API(
MonadLambdaCube(..)
, LambdaCubeException(..)
) where
import Control.Monad.Catch (throwM, MonadThrow)
import Control.Monad.State.Strict
import Control.Monad.Writer (Writer)
import LambdaCube.Compiler as LambdaCube
import LambdaCube.GL as LambdaCubeGL
import Game.GoreAndAsh.LambdaCube.Module
import Game.GoreAndAsh.LambdaCube.State
-- | Low level monadic API for module.
class (MonadIO m, MonadThrow m) => MonadLambdaCube m where
-- | Update viewport size for rendering engine
-- Should be called when window size is changed (or every frame)
lambdacubeUpdateSize :: Word -- ^ Width of screen in pixels
-> Word -- ^ Height of screen in pixels
-> m ()
-- | Compile and register new pipeline.
--
-- Throws: 'PipeLineCompileFailed' or 'PipeLineAlreadyRegistered' when failed.
lambdacubeAddPipeline ::
[FilePath] -- ^ Where to find LC modules
-> String -- ^ Name of main module (without .lc)
-> PipelineId -- ^ Name of pipeline to register
-> Writer PipelineSchema a -- ^ Pipeline inputs description
-> m ()
-- | Removes pipeline from engine, deallocates all storages for rendering storages
--
-- Note: if pipeline with the name doesn't exists, do nothing.
lambdacubeDeletePipeline :: PipelineId -> m ()
-- | Creates new storage (corresponding to one game object)
--
-- Note: if pipeline not found, throws 'PipeLineNotFound'
lambdacubeCreateStorage :: PipelineId -> m (StorageId, GLStorage)
-- | Removes storage for pipeline, deallocates it
--
-- Note: if storage with the id doesn't exists, do nothing
lambdacubeDeleteStorage :: StorageId -> m ()
-- | Getting storage by ID
--
-- Throws 'StorageNotFound' if no storage found
lambdacubeGetStorage :: StorageId -> m GLStorage
-- | Adds storage to rendering queue
lambdacubeRenderStorageLast :: StorageId -> m ()
-- | Adds storage to rendering queue
lambdacubeRenderStorageFirst :: StorageId -> m ()
-- | Removes storage from rendering queue
lambdacubeStopRendering :: StorageId -> m ()
instance {-# OVERLAPPING #-} (MonadIO m, MonadThrow m) => MonadLambdaCube (LambdaCubeT s m) where
lambdacubeUpdateSize !w !h = do
s <- get
liftIO $ updateStateViewportSize w h s
lambdacubeAddPipeline !ps !mn !pid !pwr = do
s <- get
when (isPipelineRegisteredInternal pid s) . throwM . PipeLineAlreadyRegistered $! pid
mpd <- liftIO $ LambdaCube.compileMain ps OpenGL33 mn
case mpd of
Left err -> throwM . PipeLineCompileFailed mn pid $! "compile error:\n" ++ show err
Right pd -> do
let sch = makeSchema pwr
r <- liftIO $ LambdaCubeGL.allocRenderer pd
put $! registerPipelineInternal pid pd sch r s
lambdacubeDeletePipeline !i = do
s <- get
s' <- liftIO $ unregisterPipelineInternal i s
put s'
lambdacubeCreateStorage !i = do
s <- get
case getPipelineSchemeInternal i s of
Nothing -> throwM . PipeLineNotFound $! i
Just sch -> do
storage <- liftIO $ LambdaCubeGL.allocStorage sch
si <- state $ registerStorageInternal i storage
return (si, storage)
lambdacubeDeleteStorage !i = do
s <- get
s' <- liftIO $ unregisterStorageInternal i s
put s'
lambdacubeGetStorage !si = do
s <- get
case getStorageInternal si s of
Nothing -> throwM . StorageNotFound $! si
Just storage -> return storage
lambdacubeRenderStorageLast !si = do
s <- get
put $! renderStorageLastInternal si s
lambdacubeRenderStorageFirst !si = do
s <- get
put $! renderStorageFirstInternal si s
lambdacubeStopRendering !si = do
s <- get
put $! stopRenderingInternal si s
instance {-# OVERLAPPABLE #-} (MonadIO (mt m), MonadThrow (mt m), MonadLambdaCube m, MonadTrans mt) => MonadLambdaCube (mt m) where
lambdacubeUpdateSize a b = lift $ lambdacubeUpdateSize a b
lambdacubeAddPipeline a b c d = lift $ lambdacubeAddPipeline a b c d
lambdacubeDeletePipeline a = lift $ lambdacubeDeletePipeline a
lambdacubeCreateStorage a = lift $ lambdacubeCreateStorage a
lambdacubeDeleteStorage a = lift $ lambdacubeDeleteStorage a
lambdacubeGetStorage a = lift $ lambdacubeGetStorage a
lambdacubeRenderStorageLast a = lift $ lambdacubeRenderStorageLast a
lambdacubeRenderStorageFirst a = lift $ lambdacubeRenderStorageFirst a
lambdacubeStopRendering a = lift $ lambdacubeStopRendering a