////////////////////////////////////////////////////////////////////////////////
// paramlist.cpp
// Author     : Francesco Giordana
// Start Date : January 13, 2005
// Copyright  : (C) 2006 by Francesco Giordana
// Email      : fra.giordana@tiscali.it
////////////////////////////////////////////////////////////////////////////////

/*********************************************************************************
*                                                                                *
*   This program is free software; you can redistribute it and/or modify         *
*   it under the terms of the GNU Lesser General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or            *
*   (at your option) any later version.                                          *
*                                                                                *
**********************************************************************************/

#include "paramlist.h"
#include <maya/MGlobal.h>

/***** Class ParamList *****/
// method to parse arguments from command line
namespace OgreMayaExporter
{
	void ParamList::parseArgs(const MArgList &args)
	{
		MStatus stat;
		// Parse arguments from command line
		for (unsigned int i = 0; i < args.length(); i++ )
		{
			if ((MString("-all") == args.asString(i,&stat)) && (MS::kSuccess == stat))
				exportAll = true;
			else if ((MString("-world") == args.asString(i,&stat)) && (MS::kSuccess == stat))
				exportWorldCoords = true;
			else if ((MString("-lu") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				MString lengthUnit = args.asString(++i,&stat);
				if (MString("pref") == lengthUnit)
				{
					MGlobal::executeCommand("currentUnit -q -l",lengthUnit,false);
				}
				if (MString("mm") == lengthUnit)
					lum = CM2MM;
				else if (MString("cm") == lengthUnit)
					lum = CM2CM;
				else if (MString("m") == lengthUnit)
					lum = CM2M;
				else if (MString("in") == lengthUnit)
					lum = CM2IN;
				else if (MString("ft") == lengthUnit)
					lum = CM2FT;
				else if (MString("yd") == lengthUnit)
					lum = CM2YD;
			}
			else if ((MString("-scale") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				float s = args.asDouble(++i,&stat);
				lum *= s;
			}
			else if ((MString("-mesh") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportMesh = true;
				meshFilename = args.asString(++i,&stat);
			}
			else if ((MString("-mat") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportMaterial = true;
				materialFilename = args.asString(++i,&stat);
			}
			else if ((MString("-matPrefix") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				matPrefix = args.asString(++i,&stat);
			}
			else if ((MString("-copyTex") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				copyTextures = true;
				texOutputDir = args.asString(++i,&stat);
			}
			else if ((MString("-lightOff") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				lightingOff = true;
			}
			else if ((MString("-skel") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportSkeleton = true;
				skeletonFilename = args.asString(++i,&stat);
			}
			else if ((MString("-skeletonAnims") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportSkelAnims = true;
			}
			else if ((MString("-vertexAnims") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportVertAnims = true;
			}
			else if ((MString("-blendShapes") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportBlendShapes = true;
			}
			else if ((MString("-BSAnims") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportBSAnims = true;
			}
			else if ((MString("-skelBB") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				skelBB = true;
			}
			else if ((MString("-bsBB") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				bsBB = true;
			}
			else if ((MString("-vertBB") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				vertBB = true;
			}
			else if ((MString("-animCur") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportAnimCurves = true;
				animFilename = args.asString(++i,&stat);
			}
			else if ((MString("-cam") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportCameras = true;
				camerasFilename = args.asString(++i,&stat);
			}
			else if ((MString("-v") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportVBA = true;
			}
			else if ((MString("-n") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportVertNorm = true;
			}
			else if ((MString("-c") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportVertCol = true;
			}
			else if ((MString("-t") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportTexCoord = true;
			}
			else if ((MString("-edges") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				buildEdges = true;
			}
			else if ((MString("-tangents") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				buildTangents = true;
				MString tanSem = args.asString(++i,&stat);
				if (tanSem == "TEXCOORD")
					tangentSemantic = TS_TEXCOORD;
				else if (tanSem == "TANGENT")
					tangentSemantic = TS_TANGENT;
			}
			else if ((MString("-tangentsplitmirrored") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				tangentsSplitMirrored = true;
			}
			else if ((MString("-tangentsplitrotated") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				tangentsSplitRotated = true;
			}
			else if ((MString("-tangentuseparity") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				tangentsUseParity = true;
			}
			else if ((MString("-camAnim") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportCamerasAnim = true;
			}
			else if ((MString("-particles") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				exportParticles = true;
				particlesFilename = args.asString(++i,&stat);
			}
			else if ((MString("-shared") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				useSharedGeom = true;
			}
			else if ((MString("-np") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				MString npType = args.asString(++i,&stat);
				if (npType == "curFrame")
					neutralPoseType = NPT_CURFRAME;
				else if (npType == "bindPose")
					neutralPoseType = NPT_BINDPOSE;
			}
			else if ((MString("-skeletonClip") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				//get clip name
				MString clipName = args.asString(++i,&stat);
				//check if name is unique, otherwise skip the clip
				int k;
				bool uniqueName = true;
				for (k=0; k<skelClipList.size() && uniqueName; k++)
				{
					if (clipName == skelClipList[k].name)
						uniqueName = false;
				}
				//if the name is uniue, load the clip info
				if (uniqueName)
				{
					//get clip range
					MString clipRangeType = args.asString(++i,&stat);
					float startTime, stopTime;
					if (clipRangeType == "startEnd")
					{
						startTime = args.asDouble(++i,&stat);
						stopTime = args.asDouble(++i,&stat);
						MString rangeUnits = args.asString(++i,&stat);
						if (rangeUnits == "frames")
						{
							//range specified in frames => convert to seconds
							MTime t1(startTime, MTime::uiUnit());
							MTime t2(stopTime, MTime::uiUnit());
							startTime = t1.as(MTime::kSeconds);
							stopTime = t2.as(MTime::kSeconds);
						}
					}
					else
					{
						//range specified by time slider
						MTime t1 = MAnimControl::minTime();
						MTime t2 = MAnimControl::maxTime();
						startTime = t1.as(MTime::kSeconds);
						stopTime = t2.as(MTime::kSeconds);
					}
					// get sample rate
					float rate;
					MString sampleRateType = args.asString(++i,&stat);
					if (sampleRateType == "sampleByFrames")
					{
						// rate specified in frames
						int intRate = args.asInt(++i,&stat);
						MTime t = MTime(intRate, MTime::uiUnit());
						rate = t.as(MTime::kSeconds);
					}
					else
					{
						// rate specified in seconds
						rate = args.asDouble(++i,&stat);
					}
					//add clip info
					clipInfo clip;
					clip.name = clipName;
					clip.start = startTime;
					clip.stop = stopTime;
					clip.rate = rate;
					skelClipList.push_back(clip);
					std::cout << "skeleton clip " << clipName.asChar() << "\n";
					std::cout << "start: " << startTime << ", stop: " << stopTime << "\n";
					std::cout << "rate: " << rate << "\n";
					std::cout << "-----------------\n";
					std::cout.flush();
				}
				//warn of duplicate clip name
				else
				{
					std::cout << "Warning! A skeleton clip with name \"" << clipName.asChar() << "\" already exists\n";
					std::cout.flush();
				}
			}
			else if ((MString("-BSClip") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				//get clip name
				MString clipName = args.asString(++i,&stat);
				//check if name is unique, otherwise skip the clip
				int k;
				bool uniqueName = true;
				for (k=0; k<BSClipList.size() && uniqueName; k++)
				{
					if (clipName == BSClipList[k].name)
						uniqueName = false;
				}
				//if the name is uniue, load the clip info
				if (uniqueName)
				{
					//get clip range
					MString clipRangeType = args.asString(++i,&stat);
					float startTime, stopTime;
					if (clipRangeType == "startEnd")
					{
						startTime = args.asDouble(++i,&stat);
						stopTime = args.asDouble(++i,&stat);
						MString rangeUnits = args.asString(++i,&stat);
						if (rangeUnits == "frames")
						{
							//range specified in frames => convert to seconds
							MTime t1(startTime, MTime::uiUnit());
							MTime t2(stopTime, MTime::uiUnit());
							startTime = t1.as(MTime::kSeconds);
							stopTime = t2.as(MTime::kSeconds);
						}
					}
					else
					{
						//range specified by time slider
						MTime t1 = MAnimControl::minTime();
						MTime t2 = MAnimControl::maxTime();
						startTime = t1.as(MTime::kSeconds);
						stopTime = t2.as(MTime::kSeconds);
					}
					// get sample rate
					float rate;
					MString sampleRateType = args.asString(++i,&stat);
					if (sampleRateType == "sampleByFrames")
					{
						// rate specified in frames
						int intRate = args.asInt(++i,&stat);
						MTime t = MTime(intRate, MTime::uiUnit());
						rate = t.as(MTime::kSeconds);
					}
					else
					{
						// rate specified in seconds
						rate = args.asDouble(++i,&stat);
					}
					//add clip info
					clipInfo clip;
					clip.name = clipName;
					clip.start = startTime;
					clip.stop = stopTime;
					clip.rate = rate;
					BSClipList.push_back(clip);
					std::cout << "blend shape clip " << clipName.asChar() << "\n";
					std::cout << "start: " << startTime << ", stop: " << stopTime << "\n";
					std::cout << "rate: " << rate << "\n";
					std::cout << "-----------------\n";
					std::cout.flush();
				}
				//warn of duplicate clip name
				else
				{
					std::cout << "Warning! A blend shape clip with name \"" << clipName.asChar() << "\" already exists\n";
					std::cout.flush();
				}
			}
			else if ((MString("-vertexClip") == args.asString(i,&stat)) && (MS::kSuccess == stat))
			{
				//get clip name
				MString clipName = args.asString(++i,&stat);
				//check if name is unique, otherwise skip the clip
				int k;
				bool uniqueName = true;
				for (k=0; k<vertClipList.size() && uniqueName; k++)
				{
					if (clipName == vertClipList[k].name)
						uniqueName = false;
				}
				//if the name is uniue, load the clip info
				if (uniqueName)
				{
				//get clip range
					MString clipRangeType = args.asString(++i,&stat);
					float startTime, stopTime;
					if (clipRangeType == "startEnd")
					{
						startTime = args.asDouble(++i,&stat);
						stopTime = args.asDouble(++i,&stat);
						MString rangeUnits = args.asString(++i,&stat);
						if (rangeUnits == "frames")
						{
							//range specified in frames => convert to seconds
							MTime t1(startTime, MTime::uiUnit());
							MTime t2(stopTime, MTime::uiUnit());
							startTime = t1.as(MTime::kSeconds);
							stopTime = t2.as(MTime::kSeconds);
						}
					}
					else
					{
						//range specified by time slider
						MTime t1 = MAnimControl::minTime();
						MTime t2 = MAnimControl::maxTime();
						startTime = t1.as(MTime::kSeconds);
						stopTime = t2.as(MTime::kSeconds);
					}
					// get sample rate
					float rate;
					MString sampleRateType = args.asString(++i,&stat);
					if (sampleRateType == "sampleByFrames")
					{
						// rate specified in frames
						int intRate = args.asInt(++i,&stat);
						MTime t = MTime(intRate, MTime::uiUnit());
						rate = t.as(MTime::kSeconds);
					}
					else
					{
						// rate specified in seconds
						rate = args.asDouble(++i,&stat);
					}
					//add clip info
					clipInfo clip;
					clip.name = clipName;
					clip.start = startTime;
					clip.stop = stopTime;
					clip.rate = rate;
					vertClipList.push_back(clip);
					std::cout << "vertex clip " << clipName.asChar() << "\n";
					std::cout << "start: " << startTime << ", stop: " << stopTime << "\n";
					std::cout << "rate: " << rate << "\n";
					std::cout << "-----------------\n";
					std::cout.flush();
				}
				//warn of duplicate clip name
				else
				{
					std::cout << "Warning! A vertex animation clip with name \"" << clipName.asChar() << "\" already exists\n";
					std::cout.flush();
				}
			}
		}
	}


	// method to open output files for writing
	MStatus ParamList::openFiles()
	{
		MString msg;
		if (exportMaterial)
		{
			outMaterial.open(materialFilename.asChar());
			if (!outMaterial)
			{
				std::cout << "Error opening file: " << materialFilename.asChar() << "\n";
				return MS::kFailure;
			}
		}
		if (exportAnimCurves)
		{
			outAnim.open(animFilename.asChar());
			if (!outAnim)
			{
				std::cout << "Error opening file: " << animFilename.asChar() << "\n";
				return MS::kFailure;
			}
		}
		if (exportCameras)
		{
			outCameras.open(camerasFilename.asChar());
			if (!outCameras)
			{
				std::cout << "Error opening file: " << camerasFilename.asChar() << "\n";
				return MS::kFailure;
			}
		}
		if (exportParticles)
		{
			outParticles.open(particlesFilename.asChar());
			if (!outParticles)
			{
				std::cout << "Error opening file: " << particlesFilename.asChar() << "\n";
				return MS::kFailure;
			}
		}
		return MS::kSuccess;
	}

	// method to close open output files
	MStatus ParamList::closeFiles()
	{
		if (exportMaterial)
			outMaterial.close();
	
		if (exportAnimCurves)
			outAnim.close();
			
		if (exportCameras)
			outCameras.close();
		
		return MS::kSuccess;
	}

}	//end namespace