// MLRExporter.cpp: implementation of the MLRExporter class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MLRExport.h"
#include "ExportUtil.h"
#include <GameOS\GameOS.hpp>
#include <GameOS\ToolOS.hpp>
#include <MaxProxies\MaxProxyHeaders.hpp>
#include <MLR\MLRShape.hpp>

#if !defined(DLLPLATFORM_DLLPLATFORM_HPP)
	#include "DLLPlatform\DLLPlatform.hpp"
#endif


//===========================================================================//


int	MLRExporter::DoExportWrap(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts)
{

	StartExport(i, CString("Exporting MLR data."), suppressPrompts?true:false);
	
	MAXProxies::MAXScene *scene = MAXProxies::MAXScene::MakeProxy(i,m_strHintFile);
	Register_Object(scene);

	//
	// fill in all the directories
	//
	if (!LoadPlugCfg(i))
		return false;

	// Check for errors   
    if (!CheckForErrors(scene,i))
    {
        return false;
    }

	// Load settings
	m_exportInfo.exportType = EXPORT_SHAPE;
	m_exportInfo.outputAmatureFile = false;
	m_exportInfo.overwriteTextures = true;
	SaveExportInfo(scene->GetProxiedScene());
	
	//
	// set up some name and path stuff
	//
	TSTR filename, extension;
	TSTR fullpath = _T(name);
    TSTR directoryPath;
	SplitFilename(fullpath,&directoryPath,&filename,&extension);
	directoryPath += "\\";

    //    
	// see if the erf file already exists
	//
	CString erf_file_name = directoryPath + m_erfPath + filename + ".mlr";
	bool file_exists = gos_DoesFileExist(erf_file_name);

	if (file_exists)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
				gos_DeleteFile(erf_file_name);
		/*
				int ret = AfxMessageBox("Overwrite " + filename + ".erf" + " ?", MB_YESNO);
		if (ret == IDYES)
		{
			gos_DeleteFile(erf_file_name);
		}
		else
		{
			return false;
		}
		*/
	}

	//
	// if we are exporting the character do the following
	// or fall threw and export a fused mesh called a shape
	//
	CString shape_filename = filename + extension;
	CString set_filename =	directoryPath + filename;
	CString path =  directoryPath;
	ExportShape(scene,i, path, shape_filename,suppressPrompts);
		TurnOffExceptions();
		return true;

	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// method exports the character mesh ie. a file for each group
// 
int MLRExporter::ExportShape(MAXProxies::MAXScene *scene,
						   Interface *i,
                           const CString& path,
						   const CString& name,
						   BOOL suppressPrompts) 
{
	//
	// create an empty scene
	//
	UpdateProgress(i,++m_progress,CString("Preparing to copy."));

	#undef new
		ElementRenderer::GroupElement *root = new ElementRenderer::GroupElement;
	#if defined (_DEBUG)
		#define new DEBUG_NEW
	#endif

	Register_Object(root);
	Check_Object(Stuff::FileStreamManager::Instance);
	
    // Make sure that texture and erf paths exist
	bool texture_dir_exists = gos_CreateDirectory(m_texturePath);
	bool erf_dir_exists = gos_CreateDirectory(path + m_erfPath);
	
	ElementProxies::ElementSceneProxy *element_scene =
		ElementProxies::ElementSceneProxy::MakeProxy(
			root,
			m_texturePath
		);

	Register_Object(element_scene);


	Stuff::NotationFile config_file(Stuff::MString(m_maxDataPath)+"\\PlugIns.ini");
	MAXProxies::MAXCopyProcess copy_process(&config_file,i,m_progress,m_suppress,(LPVOID)&ReportError);
	element_scene->Copy(&copy_process, scene);
	int ref_count = element_scene->GetReferenceCount();

	if (!suppressPrompts)
	{
		m_progress = 20;
	}

	MAXProxies::MAXFlattenHierarchyProcess flatten_hierarchy(&config_file,i, m_progress, m_suppress);
	element_scene->FlattenHierarchy(&flatten_hierarchy);
	Verify(element_scene->GetReferenceCount() == ref_count);

	UpdateProgress(i,30,CString("Hierarchy flattened."));
	//
	// See if there are any meshes to fuse.  If there are no meshes, don't save
	// anything
	//
	Proxies::ChildProxy *first_child = element_scene->UseFirstChildProxy();
	if (!first_child)
	{
		Verify(element_scene->GetReferenceCount() == 1);
		EndExport(i);
		TurnOnExceptions();
		element_scene->Destroy();
		return 1;
	}

	UpdateProgress(i,40,CString("Preparing to fuse meshes."));
	//
	// Look for any meshes after the first.  These will be merged with the
	// first one
	//
	ElementProxies::ElementPolygonMeshProxy *first_mesh =
		Cast_Object(ElementProxies::ElementPolygonMeshProxy*, first_child);

	ElementProxies::ElementPolygonMeshProxy *mesh =
		static_cast<ElementProxies::ElementPolygonMeshProxy*>(
			first_mesh->UseNextSiblingProxy()
		);
	//
	// First count up the number of children and make an array for the meshes
	//
	if (mesh)
	{
		unsigned child_count = element_scene->GetChildCount() - 1;
		Verify(child_count > 0);

		Stuff::DynamicArrayOf<ElementProxies::ElementPolygonMeshProxy *>
			fused_children(child_count);
		Stuff::DynamicArrayOf<Stuff::DynamicArrayOf<Proxies::PolygonProxy *> >
			polys_array(child_count);
		//
		// Make the array for the polygons to add, then start spinning through
		// the children
		//
		Stuff::DynamicArrayOf<Proxies::PolygonProxy *> new_polys;
		unsigned poly_count = 0;
		child_count = 0;
		
		do {
			UpdateProgress(i,++m_progress,CString("Fusing meshes."));

			Check_Object(mesh);

			ElementProxies::ElementPolygonMeshProxy *next =
				static_cast<ElementProxies::ElementPolygonMeshProxy*>(
					mesh->UseNextSiblingProxy()
				);
			fused_children[child_count] = mesh;
			//
			// Get its polys and copy them into the large array
			//
			unsigned start = poly_count;
			unsigned len = mesh->UsePolygonArray(&polys_array[child_count]);
			poly_count += len;
			new_polys.SetLength(poly_count);
			for (unsigned i=0; i<len; ++i)
				new_polys[start++] = polys_array[child_count][i];
			mesh = next;
			++child_count;
		} while (mesh);
		first_mesh->AddPolygons(&copy_process, new_polys);
		//
		// Now destroy the old meshes
		//
		for (child_count=0; child_count<fused_children.GetLength(); ++child_count)
		{
			mesh = fused_children[child_count];
			Check_Object(mesh);
			mesh->DetachArrayReferences(&polys_array[child_count]);
			Verify(mesh->GetReferenceCount() == 1);
			mesh->Destroy();
		}
	}
	UpdateProgress(i,65,CString("Building bounding sphere"));

	//
	// Build the bounding sphere around the now only child
	//
	ElementRenderer::Element *element = first_mesh->GetProxiedShape();
	ElementProxies::OptimizeSyncProcess optimize;
	if (optimize.OptimizeSync(first_mesh))
		first_mesh->DetachReference();
	UpdateProgress(i,75,CString("Preparing to save."));

	//
	// Open up the file to save the shape into, then save the child as the
	// root
	//
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream element_stream;

	UpdateProgress(i,85,CString("File open."));

	element_stream.Open(path + m_erfPath + name, Stuff::FileStream::WriteOnly);
	MidLevelRenderer::WriteMLRVersion(&element_stream);

	UpdateProgress(i,95,CString("Saving out MLR file."));
	ElementRenderer::ShapeElement *ElmShape=Cast_Object(ElementRenderer::ShapeElement *,element);
	element_stream << ElmShape->m_localOBB;
	ElmShape->GetMLRShape()->Save(&element_stream);
	
	//
	// Clean up
	//
	EndExport(i);
	TurnOnExceptions();

	Verify(element_scene->GetReferenceCount() == 1);
	element_scene->Destroy();
	
	return 1;
}

//===========================================================================//

int	MLRExp::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts,DWORD options)
{	
	int return_value;
	__try
	{
		return_value = m_Expt.DoExportWrap(name, ei, i, suppressPrompts);
		//return_value = true;
		GetSystemSetting(SYSSET_CLEAR_UNDO);
		Verify(!theHold.Holding());
	}
	__except(ProcessException(GetExceptionInformation()))
	{
	}

	return return_value;
}



