///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Controller export method.
 *	This method is called once for each exported controller.
 *	\param		controller		[in] a structure filled with current controller information.
 *	\return		true if success.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ASCIIFormat::ExportController(const ControllerDescriptor& controller)
{
	// Export database management information
	mControllers.StoreASCII("\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n").StoreASCII("Controller: ");
	mControllers
		.StoreASCII((const char*)controller.mField)
		.StoreASCII("\nController ID: ")	.StoreASCII(controller.mObjectID)
		.StoreASCII("\nOwner ID: ")			.StoreASCII(controller.mOwnerID);

	// Controller data
	ControllerData* cdata = controller.mData;

	mControllers
		.StoreASCII("\nController data: \n");

	// Number of values (used in sampling only!)
	udword NbValues = 0;

			if(cdata->mType==CTRL_FLOAT)		{	mControllers.StoreASCII("Float controller, ");		NbValues = 1;	}
	else	if(cdata->mType==CTRL_VECTOR)		{	mControllers.StoreASCII("Vector controller, ");		NbValues = 3;	}
	else	if(cdata->mType==CTRL_QUAT)			{	mControllers.StoreASCII("Quaternion controller, ");	NbValues = 4;	}
	else	if(cdata->mType==CTRL_PR)			{	mControllers.StoreASCII("PR controller, ");			NbValues = 7;	}
	else	if(cdata->mType==CTRL_PRS)			{	mControllers.StoreASCII("PRS controller, ");		NbValues = 10;	}
	else	if(cdata->mType==CTRL_VERTEXCLOUD)	{	mControllers.StoreASCII("Morph controller, ");						}
	else										{	mControllers.StoreASCII("Unknown controller, ");					}

			if(cdata->mMode==CTRL_SAMPLES)			mControllers.StoreASCII("sampling mode.\n\n");
	else	if(cdata->mMode==CTRL_KEYFRAMES)		mControllers.StoreASCII("keyframing mode.\n\n");
	else											mControllers.StoreASCII("Unknown mode.\n\n");

	// Dump the samples
	if(cdata->mMode==CTRL_SAMPLES)
	{
		// Sampling path
		if(cdata->mType==CTRL_VERTEXCLOUD)
		{
			// A morph controller
			MorphData* mdata = (MorphData*)cdata;
			mControllers
				.StoreASCII(mdata->mNbVertices).StoreASCII(" morphed vertices.\n")
				.StoreASCII(mdata->mNbSamples).StoreASCII(" samples, sampling rate = ").StoreASCII(mdata->mSamplingRate).StoreASCII("\n");

			// Dump morphed vertices as a list of floats
			float* Values = (float*)mdata->mSamples;
			for(udword i=0;i<3*mdata->mNbSamples*mdata->mNbVertices;i++)
			{
				mControllers.StoreASCII(*Values++).StoreASCII(" ");
				if((i&63)==63)	mControllers.StoreASCII("\n");
			}
		}
		else
		{
			// A standard controller
			SampleData* sdata = (SampleData*)cdata;
			mControllers.StoreASCII(sdata->mNbSamples).StoreASCII(" samples, sampling rate = ").StoreASCII(sdata->mSamplingRate).StoreASCII("\n");

			float* Values = (float*)sdata->mSamples;
			for(udword i=0;i<NbValues*sdata->mNbSamples;i++)
			{
				mControllers.StoreASCII(*Values++).StoreASCII(" ");
				if((i&63)==63)	mControllers.StoreASCII("\n");
			}
		}
	}
	else if(cdata->mMode==CTRL_KEYFRAMES)
	{
		// Keyframing path
		KeyframeData* kdata = (KeyframeData*)cdata;
		mControllers.StoreASCII(kdata->mNbKeyframes).StoreASCII(" keyframes, interpolation scheme = ");

		switch(kdata->mScheme)
		{
			case SCHEME_LINEAR:
			{
				mControllers.StoreASCII("LINEAR\n\n");
				// Not supported yet
			}
			break;

			case SCHEME_TCB:
			{
				mControllers.StoreASCII("TCB\n\n");
				if(controller.mField=="POSITION")
				{
					// TCB Point keyframes
					TCBPointKey* Keys = (TCBPointKey*)kdata->mKeyframes;
					for(udword i=0;i<kdata->mNbKeyframes;i++)
					{
						TCBPointKey* CurKey = &Keys[i];
						mControllers
							.StoreASCII("Key #")		.StoreASCII(i)					.StoreASCII(":\n")
							.StoreASCII("Time: ")		.StoreASCII(CurKey->mTime)		.StoreASCII("\n")
							.StoreASCII("Tension: ")	.StoreASCII(CurKey->mTens)		.StoreASCII("\n")
							.StoreASCII("Continuity: ")	.StoreASCII(CurKey->mCont)		.StoreASCII("\n")
							.StoreASCII("Bias: ")		.StoreASCII(CurKey->mBias)		.StoreASCII("\n")
							.StoreASCII("EaseIn: ")		.StoreASCII(CurKey->mEaseIn)	.StoreASCII("\n")
							.StoreASCII("EaseOut: ")	.StoreASCII(CurKey->mEaseOut)	.StoreASCII("\n")
							.StoreASCII("x: ")			.StoreASCII(CurKey->mVal.x)		.StoreASCII("\n")
							.StoreASCII("y: ")			.StoreASCII(CurKey->mVal.y)		.StoreASCII("\n")
							.StoreASCII("z: ")			.StoreASCII(CurKey->mVal.z)		.StoreASCII("\n\n");
					}
				}
				else if(controller.mField=="ROTATION")
				{
					// TCB Rot keyframes
					TCBRotKey* Keys = (TCBRotKey*)kdata->mKeyframes;
					for(udword i=0;i<kdata->mNbKeyframes;i++)
					{
						TCBRotKey* CurKey = &Keys[i];
						mControllers
							.StoreASCII("Key #")		.StoreASCII(i)					.StoreASCII(":\n")
							.StoreASCII("Time: ")		.StoreASCII(CurKey->mTime)		.StoreASCII("\n")
							.StoreASCII("Tension: ")	.StoreASCII(CurKey->mTens)		.StoreASCII("\n")
							.StoreASCII("Continuity: ")	.StoreASCII(CurKey->mCont)		.StoreASCII("\n")
							.StoreASCII("Bias: ")		.StoreASCII(CurKey->mBias)		.StoreASCII("\n")
							.StoreASCII("EaseIn: ")		.StoreASCII(CurKey->mEaseIn)	.StoreASCII("\n")
							.StoreASCII("EaseOut: ")	.StoreASCII(CurKey->mEaseOut)	.StoreASCII("\n")
							.StoreASCII("x: ")			.StoreASCII(CurKey->mVal.x)		.StoreASCII("\n")
							.StoreASCII("y: ")			.StoreASCII(CurKey->mVal.y)		.StoreASCII("\n")
							.StoreASCII("z: ")			.StoreASCII(CurKey->mVal.z)		.StoreASCII("\n")
							.StoreASCII("w: ")			.StoreASCII(CurKey->mVal.w)		.StoreASCII("\n\n");
					}
				}
			}
			break;

			case SCHEME_BEZIER:
			{
				mControllers.StoreASCII("BEZIER\n\n");
				// Not supported yet
			}
			break;

			default:
			{
				mControllers.StoreASCII("UNKNOWN\n\n");
			}
			break;
		}
	}

	return true;
}
