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.

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 !

Your refactoring





Format Copy from initial code

or Cancel