2f9c571c7d57b6e2170eae9a372e24b8

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.

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 !

Your refactoring





Format Copy from initial code

or Cancel