packages feed

roguestar-gl-0.2.1: src/Animation.lhs

\section{The Roguestar Animation Arrow}

\begin{code}
{-# LANGUAGE GeneralizedNewtypeDeriving, Arrows #-}

module Animation
    (RSAnimA,
     RSAnimA1,
     RSAnimAX,
     RoguestarAnimationObject,
     newRoguestarAnimationObject,
     runRoguestarAnimationObject,
     driverGetAnswerA,
     driverGetTableA,
     printTextA,
     printTextOnce,
     debugA,
     debugOnce,
     printMenuItemA,
     printMenuA,
     clearPrintTextA,
     clearPrintTextOnce,
     libraryA,
     libraryPointAtCamera,
     blockContinue,
     requestPrintTextMode)
    where

import RSAGL.FRP
import RSAGL.CoordinateSystems
import RSAGL.Scene
import RSAGL.AnimationExtras
import Control.Monad.State
import Control.Arrow
import Control.Arrow.Transformer hiding (lift)
import Control.Arrow.Transformer as Arrow
import Control.Arrow.Transformer.State as StateArrow
import Control.Arrow.Operations
import Driver
import Tables
import Control.Concurrent.MVar
import RSAGL.Time
import System.IO
import PrintText
import Models.Library
import Models.LibraryData
import Quality
import Data.Maybe
import Keymaps.Keymaps
import Keymaps.CommonKeymap
import Actions
import Data.List
import Data.Ord
import Strings
import Actions

data AnimationState = AnimationState {
    animstate_scene_accumulator :: SceneAccumulator,
    animstate_driver_object :: DriverObject,
    animstate_print_text_object :: PrintTextObject,
    animstate_library :: Library,
    animstate_block_continue :: Bool,
    animstate_print_text_mode :: PrintTextMode }

instance CoordinateSystemClass AnimationState where
    getCoordinateSystem = getCoordinateSystem . animstate_scene_accumulator
    storeCoordinateSystem cs as = as { 
        animstate_scene_accumulator = storeCoordinateSystem cs $ animstate_scene_accumulator as }

instance ScenicAccumulator AnimationState where
    accumulateScene sl so as = as { 
        animstate_scene_accumulator = accumulateScene sl so $ animstate_scene_accumulator as }

newtype IOGuard a = IOGuard { runIOGuard :: IO a } deriving (Functor,Monad)

type RSAnimAX k t i o j p = FRPX k t i o (StateArrow AnimationState (Kleisli IOGuard)) j p
type RSAnimA t i o j p = RSAnimAX Threaded t i o j p
type RSAnimA1 i o j p = RSAnimAX () () i o j p

type RSAnimA_ j p = StateArrow AnimationState (Kleisli IOGuard) j p

newtype RoguestarAnimationObject = RoguestarAnimationObject {
    rso_arrow :: MVar (FRPProgram (StateArrow AnimationState (Kleisli IOGuard)) () Camera) }

newRoguestarAnimationObject :: RSAnimA1 () Camera () Camera -> IO RoguestarAnimationObject
newRoguestarAnimationObject rs_anim = 
    liftM RoguestarAnimationObject $ newMVar $ newFRP1Program rs_anim

runRoguestarAnimationObject :: Library -> DriverObject -> PrintTextObject -> RoguestarAnimationObject -> IO Scene
runRoguestarAnimationObject lib driver_object print_text_object rso =
    do old_rso_program <- takeMVar $ rso_arrow rso
       t <- getTime
       ((result_camera,new_rso_program),result_animstate) <- runIOGuard $ (runKleisli $ StateArrow.runState $ updateFRPProgram old_rso_program) (((),t),
           AnimationState {
               animstate_scene_accumulator = null_scene_accumulator,
	       animstate_driver_object = driver_object,
	       animstate_print_text_object = print_text_object,
	       animstate_library = lib,
	       animstate_block_continue = False,
	       animstate_print_text_mode = Limited })
       putMVar (rso_arrow rso) new_rso_program
       when (not $ animstate_block_continue result_animstate) $ executeContinueAction $ ActionInput driver_object print_text_object
       setPrintTextMode print_text_object $ animstate_print_text_mode result_animstate
       assembleScene result_camera $ animstate_scene_accumulator result_animstate

ioA :: (j -> IO p) -> RSAnimAX any t i o j p
ioA action = Arrow.lift $ ioA_ action

ioA_ :: (j -> IO p) -> RSAnimA_ j p
ioA_ action = proc j -> Arrow.lift $ Kleisli (\x -> IOGuard $ action x) -< j

driverGetAnswerA :: RSAnimAX any t i o String (Maybe String)
driverGetAnswerA = proc query ->
    do driver_object <- arr animstate_driver_object <<< fetch -< ()
       ioA (\(driver_object_,query_) -> driverGetAnswer driver_object_ query_) -< (driver_object,query)

driverGetTableA :: RSAnimAX any t i o (String,String) (Maybe RoguestarTable)
driverGetTableA = proc query ->
    do driver_object <- arr animstate_driver_object <<< fetch -< ()
       ioA (\(driver_object_,(the_table_name,the_table_id)) -> 
           driverGetTable driver_object_ the_table_name the_table_id) -< (driver_object,query)

printTextA :: RSAnimAX any t i o (Maybe (TextType,String)) ()
printTextA = Arrow.lift printTextA_

printTextOnce :: RSAnimAX any t i o (Maybe (TextType,String)) ()
printTextOnce = onceA printTextA_ 

printTextA_ :: RSAnimA_ (Maybe (TextType,String)) ()
printTextA_ = proc pt_data ->
    do print_text_object <- arr animstate_print_text_object <<< fetch -< ()
       ioA_ (\(print_text_object,x) -> case x of
            Nothing -> return ()
	    Just (pt_type,pt_string) -> printText print_text_object pt_type pt_string) -< (print_text_object,pt_data)

debugA :: RSAnimAX any t i o (Maybe String) ()
debugA = Arrow.lift debugA_

debugA_ :: RSAnimA_ (Maybe String) ()
debugA_ = Arrow.lift $ Kleisli $ maybe (return ()) (IOGuard . hPutStrLn stderr)

debugOnce :: RSAnimAX any t i o (Maybe String) ()
debugOnce = onceA debugA_

actionNameToKeysA :: String -> RSAnimAX any t i o () [String]
actionNameToKeysA action_name = Arrow.lift $ proc () ->
    do animstate <- fetch -< ()
       let action_input = ActionInput (animstate_driver_object animstate)
                                      (animstate_print_text_object animstate)
       app -< (Arrow.lift $ Kleisli $ const $ IOGuard $ actionNameToKeys action_input common_keymap action_name,())

printMenuA :: [String] -> RSAnimAX any t i o () ()
printMenuA = foldr (>>>) (arr id) . map printMenuItemA

printMenuItemA :: String -> RSAnimAX any t i o () ()
printMenuItemA action_name = proc () ->
    do keys <- actionNameToKeysA action_name -< ()
       printTextA -< fmap (\s -> (Query,s ++ " - " ++ hrstring action_name)) $ listToMaybe $ sortBy (comparing length) keys

clearPrintTextA :: RSAnimAX any t i o () ()
clearPrintTextA = Arrow.lift clearPrintText_ <<< arr (const $ Just ())

clearPrintTextOnce :: RSAnimAX any t i o () ()
clearPrintTextOnce = onceA clearPrintText_ <<< arr (const $ Just ())

clearPrintText_ :: RSAnimA_ (Maybe ()) ()
clearPrintText_ = proc i ->
    do print_text_object <- arr (animstate_print_text_object) <<< fetch -< ()
       app -< maybe (arr $ const (),()) (const (Arrow.lift $ Kleisli $ const $ IOGuard $ clearOutputBuffer print_text_object,())) i

onceA :: StateArrow AnimationState (Kleisli IOGuard) (Maybe j) p -> RSAnimAX any t i o (Maybe j) p
onceA actionA = frp1Context onceA_
    where onceA_ = proc j -> 
              do p <- Arrow.lift actionA -< j
	         switchTerminate -< (if isJust j then (Just $ arr (const p)) else Nothing,p)

libraryA :: RSAnimAX any t i o (SceneLayer,LibraryModel) ()
libraryA = proc (layer,lm) ->
    do lib <- arr animstate_library <<< fetch -< ()
       accumulateSceneA -< (layer,sceneObject $ lookupModel lib lm Good)

libraryPointAtCamera :: RSAnimAX any t i o (SceneLayer,LibraryModel) ()
libraryPointAtCamera = proc (layer,lm) ->
    do lib <- arr animstate_library <<< fetch -< ()
       pointAtCameraA -< (layer,lookupModel lib lm Good)

blockContinue :: RSAnimAX any t i o Bool ()
blockContinue = Arrow.lift $ proc b ->
    do animstate <- fetch -< ()
       store -< animstate { animstate_block_continue = animstate_block_continue animstate || b }

requestPrintTextMode :: RSAnimAX any t i o PrintTextMode ()
requestPrintTextMode = Arrow.lift $ proc s ->
    do animstate <- fetch -< ()
       store -< animstate { animstate_print_text_mode = case (animstate_print_text_mode animstate,s) of
	   (_,Disabled) -> Disabled
	   (Limited,Unlimited) -> Unlimited
           (m,_) -> m }
\end{code}