// MESHExportClass.cpp: implementation of the CMESHExportClass class.
//
//////////////////////////////////////////////////////////////////////

#include "MESHExportClass.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

#include "MESHCollectNodesTEP.h"
#include "MESHDumpMeshTEP.h"
#include "MESHDumpNodesTEP.h"

#include "..\MaxKernel.h"
#include "..\CountNodesTEP.h"

#define DEFAULT_EXT _T("MES")

CMESHExportClass::CMESHExportClass()
{
	m_pMeshFrame = NULL;
}

CMESHExportClass::~CMESHExportClass()
{
	Destroy();
}

void CMESHExportClass::Destroy()
{
	CMaxKernel::Destroy();

	ReleaseINodeIndex();
	if (m_pMeshFrame)
	{
		delete m_pMeshFrame;
		m_pMeshFrame = NULL;
	}
}

int CMESHExportClass::ExtCount()
{
	//TODO: Returns the number of file name extensions supported by the plug-in.
	return 1;
}

const TCHAR* CMESHExportClass::Ext(int n)
{
	//TODO: Return the 'i-th' file name extension (i.e. "3DS").
	return DEFAULT_EXT;
}

const TCHAR* CMESHExportClass::LongDesc()
{
	//TODO: Return long ASCII description (i.e. "Targa 2.0 Image File")
	return _T("Mesh File Export");
}

const TCHAR* CMESHExportClass::ShortDesc()
{
	//TODO: Return short ASCII description (i.e. "Targa")
	return _T("Mesh Export");
}

// ================================================== dummyFn()
// used by 3DS progress bar
DWORD WINAPI dummyFn(LPVOID arg)
{
    return 0;
}

int CMESHExportClass::DoExport(const TCHAR* lpszFileName, ExpInterface* lpEI, Interface* lpI, BOOL bSuppressPrompts, DWORD dwOptions)
{
	//TODO: Implement the actual file Export here and 
	//		return TRUE If the file is exported properly

	ExpInterface*	pExpInterface = lpEI;	// Hungarian
	Interface*		pInterface = lpI;		// Hungarian

    BOOL bSaveSelection = (dwOptions & SCENE_EXPORT_SELECTED);

	   // return failure if no filename provided
    if (lpszFileName == NULL)
        return FALSE;

	// Break up filename, re-assemble longer versions
	TSTR strPath, strFile, strExt;
	SplitFilename(TSTR(lpszFileName), &strPath, &strFile, &strExt);

	TCHAR szFile[MAX_PATH];
	sprintf(szFile, "%s\\%s.%s", (char*) strPath, (char*) strFile, DEFAULT_EXT);

	m_pMeshFrame = new CMaxMeshFrame;
	if (!m_pMeshFrame)
		return FALSE;

	// Get animation metrics
	m_IntervalOfAnimation = pInterface->GetAnimRange();

	m_tvStart = m_IntervalOfAnimation.Start();
	m_tvEnd   = m_IntervalOfAnimation.End();
    
	// Extract scene information
    pInterface->ProgressStart(_T("Extracting skinning data"), TRUE, dummyFn, NULL);
    pInterface->ProgressUpdate(0);

//////////////////////////////////////////////////////////////////////
// Start Exporting
//////////////////////////////////////////////////////////////////////

	// Reset the name-map property manager
	CreateINodeIndex();

	// Count nodes, label them, collect into array
	if (!CollectNodes(pExpInterface))
		return FALSE;

    pInterface->ProgressStart(_T("Exporting data"), TRUE, dummyFn, NULL);
    pInterface->ProgressUpdate(25);

	// Output nodes
	if (!DumpNodes(pExpInterface))
		return FALSE;

	m_pMeshFrame->BuildReference();


	// Output triangle meshes (first frame/all frames), if this is the reference frame MAX file
	DumpMesh(pExpInterface);

    pInterface->ProgressUpdate(50);

    pInterface->ProgressStart(_T("Saving data to file"), TRUE, dummyFn, NULL);
    pInterface->ProgressUpdate(75);

	m_pMeshFrame->Save(szFile);

	Destroy();

//////////////////////////////////////////////////////////////////////
// End Exporting
//////////////////////////////////////////////////////////////////////
    pInterface->ProgressUpdate(100);
    pInterface->ProgressEnd();

	return TRUE;
}

BOOL CMESHExportClass::CollectNodes(ExpInterface *lpExpInterface)
{
	// Count total nodes in the model, so I can alloc array
	// Also "brands" each node with node index, or with "skip me" marker.
	CCountNodesTEP procCountNodes;
	procCountNodes.m_nNodeCounts = 0;
	lpExpInterface->theScene->EnumTree(&procCountNodes);

	int nNumNodes = procCountNodes.m_nNodeCounts;
	if (nNumNodes == 0)
		return FALSE;

	if (!m_pMeshFrame->CreateNodes(nNumNodes))
		return FALSE;

	CMESHCollectNodesTEP procCollectNodes;
	procCollectNodes.m_pExportClass = this;
	lpExpInterface->theScene->EnumTree(&procCollectNodes);

	return TRUE;
}

BOOL CMESHExportClass::DumpNodes(ExpInterface *lpExpInterface)
{
	// Dump node names
	CMESHDumpNodesTEP procDumpNodes;
	procDumpNodes.m_pExportClass = this;
	procDumpNodes.m_tvToDump = m_tvStart;

	lpExpInterface->theScene->EnumTree(&procDumpNodes);

	return TRUE;
}

BOOL CMESHExportClass::DumpMesh(ExpInterface *lpExpInterface)
{
	// Dump mesh info: vertices, normals, UV texture map coords, bone assignments
	CMESHDumpMeshTEP procDumpMesh;
	procDumpMesh.m_pExportClass = this;
	procDumpMesh.m_tvToDump = m_tvStart;

	lpExpInterface->theScene->EnumTree(&procDumpMesh);

	return TRUE;
}

