packages feed

frag-1.1: src/MapCfg.hs

-- MapCfg.hs; Mun Hon Cheong (mhch295@cse.unsw.edu.au) 2005

{-

reads the level configuration files and map media files

-}


module MapCfg where

import BSP
import Camera
import Control.Exception ( bracket )
import Data.HashTable (HashTable,lookup,insert,fromList,hashString)
import Data.IORef
import Data.List (find)
import Data.Maybe
import IdentityList
import MD3
import Object
import Object
import ObjectBehavior
import Prelude
import System.IO hiding (withBinaryFile)


data ObjectConstructor =
   ConsCamera Camera |
   ConsAICube {startPosition :: (Double,Double,Double),
               size          :: (Double,Double,Double),
               wayPoints     :: [(Double,Double,Double)],
               modlName      :: String}
               deriving (Read,Show)


readMapCfg :: FilePath -> IO [IntermediateObject]
readMapCfg filepath = withBinaryFile filepath $ \handle -> do
   lnes <- readLines handle
   print lnes
   let objects  = map lines2ObjectCons lnes
   return $ map objectCons2IntermediateObjects objects

readMapMedia :: FilePath -> IO (IORef BSPMap,(HashTable String Model))
readMapMedia filepath = withBinaryFile filepath $ \handle -> do
   lnes <- readLines handle
   print lnes
   let levelModels = lines2LevelModels lnes
   let (MMap lvlName) = head levelModels
   bsp <- readBSP lvlName
   hash <- fromList hashString []
   mapM_ (readLevelModels hash) (tail levelModels)
   return (bsp,hash)


readLevelModels :: HashTable String Model -> LevelModel -> IO ()
readLevelModels hash (MWeapon name) =
   getWeaponModel hash name
readLevelModels hash (MPlayerModel name weaponName) =
   getModel hash name weaponName


getModel :: HashTable String Model -> String -> String -> IO ()
getModel hash name weaponName = do
   getWeaponModel hash weaponName
   Just weapon <- Data.HashTable.lookup hash weaponName
   model       <- readModel name weapon
   insert hash name model


getWeaponModel :: HashTable String Model -> String -> IO ()
getWeaponModel hash name = do
   model <- Data.HashTable.lookup hash name
   case model of
      Just _ -> return ()
      Nothing -> do
                weaponModel <-
                  readWeaponModel
                    ("tga/models/weapons/"++name++".md3") ("tga/models/weapons/"++name++".shader")
                insert hash name weaponModel


readLines :: Handle -> IO [String]
readLines handle = do
         eof <- hIsEOF handle
         case (eof) of
           False -> do
                     line <- hGetLine handle
                     lnes <- readLines handle
                     return (line:lnes)
           _     -> return []

withBinaryFile :: FilePath -> (Handle -> IO a) -> IO a
withBinaryFile filePath = bracket (openBinaryFile filePath ReadMode) hClose


data LevelModel = MWeapon String |
                  MPlayerModel String String |
                  MMap String deriving (Read,Show)


data IntermediateObject =
   ICamera ([(String, AnimState, AnimState)] ->
      [(ILKey, Message)] -> ILKey -> Object) |
   IAICube ((AnimState,AnimState) -> ILKey -> Object) String


lines2ObjectCons :: String -> ObjectConstructor
lines2ObjectCons str
 | head (words str) == "ConsCamera" = read str :: ObjectConstructor
 | head (words str) == "ConsAICube" = read str :: ObjectConstructor


lines2LevelModels :: [String] -> [LevelModel]
lines2LevelModels [] = []
lines2LevelModels (str:strs) = (read str): (lines2LevelModels  strs)


objectCons2IntermediateObjects :: ObjectConstructor -> IntermediateObject
objectCons2IntermediateObjects (ConsCamera cam) =
   ICamera (camera cam)
objectCons2IntermediateObjects c@(ConsAICube {}) =
   IAICube
     (aicube (startPosition c) (size c) (wayPoints c)(modlName c)) (modlName c)


toCompleteObjects ::
   [(String, AnimState, AnimState)] ->
      [IntermediateObject] -> [ILKey->Object]
toCompleteObjects animList iobjs =
   map (toCompleteObject animList) iobjs


toCompleteObject ::
   [(String, AnimState, AnimState)] ->
      IntermediateObject -> (ILKey->Object)
toCompleteObject animList (ICamera func) =
   func animList []
toCompleteObject animList (IAICube func modelname) =
   func (findModelAnim modelname animList)


findModelAnim ::
   String ->
      [(String,AnimState,AnimState)] ->
          (AnimState,AnimState)
findModelAnim name anms = (ua,la)
   where
      (_,ua,la) =
          fromJust $ find (\(x,_,_)->(x==name)) anms