1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
module Main where import Text.XML.HaXml import Text.XML.HaXml.Parse import Text.XML.HaXml.Posn import Text.XML.HaXml.Util import System.Environment (getArgs) import System.IO (IOMode(..), hClose, hGetContents, hPutStr, openFile) import Data.List main = do args <- getArgs case args of [collada, ma] -> process collada ma _ -> argError process :: String -> String -> IO () process collada ma = do colladah <- openFile collada ReadMode mah <- openFile ma ReadMode colladaStr <- hGetContents colladah maStr <- hGetContents mah -- Parse the COLLADA file and get the FOV animation data. let (Document _ _ root _) = xmlParse collada colladaStr let rootElem = CElem root noPos let animations = tag "COLLADA" /> tag "library_animations" /> tag "animation" $ rootElem let fovAnimation = (filter isFovAnimation animations) !! 0 let sources = keep /> tag "source" /> tag "float_array" $ fovAnimation let times = map ((*24.0) . (read :: String -> Float)) $ words $ tagTextContent (sources !! 0) let values = map (yfovToFocalLength . (read :: String -> Float)) $ words $ tagTextContent (sources !! 1) let (CElem (Elem _ attributes _) _) = sources !! 0 let (_, AttValue (Left countVal:_)) = attributes !! 0 let count = read countVal :: Int --putStrLn $ show count --putStrLn $ show values -- Parse the ma file and get the name of the camera node. let createLine = (filter isCustomCameraCreate $ lines maStr) !! 0 let !cameraName = takeWhile isNotQuote $ drop 1 $ dropWhile isNotQuote createLine --putStrLn cameraName hClose mah -- Append the ma file with the FOV animation. mah2 <- openFile ma AppendMode let createNode = "createNode animCurveTU -n \"" ++ cameraName ++ "_focalLength\";\n\tsetAttr \".tan\" 10;\n\tsetAttr \".wgt\" no;\n\tsetAttr -s " ++ (show count) ++ " \".ktv[0:" ++ (show (count - 1)) ++ "]\" " hPutStr mah2 createNode hPutStr mah2 (concat $ map pairToString $ zip times values) hPutStr mah2 ";\n" let connectAttr = "connectAttr \"" ++ cameraName ++ "_focalLength.o\" \"" ++ cameraName ++ ".fl\";" hPutStr mah2 connectAttr hClose colladah hClose mah2 isFovAnimation animation = let (CElem (Elem _ attributes _) _) = animation in let (_, AttValue (Left idStr:_)) = attributes !! 0 in isSuffixOf "FOV" idStr yfovToFocalLength yfov = yAperture / (tan (yfov * 0.5 * pi / 180.0) * 2.0) where yAperture = 25.4 * 0.581 isCustomCameraCreate line = "createNode camera -n" `isPrefixOf` line isNotQuote char = char /= '"' pairToString pair = " " ++ (show . fst $ pair) ++ " " ++ (show . snd $ pair) argError = putStrLn "Usage: add_fov_to_ma.exe COLLADA_filename ma_filename\n"
Refactorings
No refactoring yet !
It's a simple command-line tool to read an XML file, get some data from it, convert them and append the converted data to a ma (Maya ascii) file.
This is the second program I've ever written in Haskell, so I think it would be far from good or ideal Haskell code. So I want some teachings from you about what can be improved & how things should be done in Haskell.