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.