-- MapCfg.hs; Mun Hon Cheong (mhch295@cse.unsw.edu.au) 2005 {- reads the level configuration files and map media files -} module MapCfg where import Camera import Object import System.IO import Prelude import Control.Exception ( bracket ) import ObjectBehavior import Object import MD3 import BSP import IdentityList import Data.List (find) import Data.Maybe import Data.IORef import Data.HashTable (HashTable,lookup,insert,fromList,hashString) 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 lines <- readLines handle print lines let objects = map lines2ObjectCons lines let iobjects = map objectCons2IntermediateObjects objects return iobjects readMapMedia :: FilePath -> IO (IORef BSPMap,(HashTable String Model)) readMapMedia filepath = withBinaryFile filepath $ \handle -> do lines <- readLines handle print lines let levelModels = lines2LevelModels lines 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 ("models/weapons/"++name++".md3") ("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 lines <- readLines handle return (line:lines) _ -> 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 anims = (ua,la) where (nm,ua,la) = fromJust $ find (\(x,y,z)->(x==name)) anims