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

#include "stdafx.h"
#include "EBFExport.h"

#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	EBFExporter::DoExportWrap(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts)
{
		
	StartExport(i, CString("Exporting EBF 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());

	//
	// see if the EBF file already exists
	//
	//
	// set up some name and path stuff
	//
	TSTR filename, extension;
	TSTR fullpath = _T(name);
    TSTR directoryPath;
	SplitFilename(fullpath,&directoryPath,&filename,&extension);
	directoryPath += "\\";

    CString erf_file_name = directoryPath + m_erfPath + filename + ".EBF";
	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;

	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream element_stream(directoryPath + m_erfPath + shape_filename, Stuff::FileStream::WriteOnly);
	
	gosFX::WriteGFXVersion(&element_stream);
	MidLevelRenderer::WriteMLRVersion(&element_stream);
	
    CString path = directoryPath;
	ExportShape(scene, i, path, &element_stream, suppressPrompts);

	TurnOffExceptions();
	return true;
}

/*******************************************************************************
/* function name: ExportShape
/* description: Write out .ebf file for destroyed effect, every child 
/*	under root node is going be a separate piece when the object is blown up
/*******************************************************************************/
int EBFExporter::ExportShape(MAXProxies::MAXScene *scene,
							 Interface *i,
                             const CString& directoryPath,
							 Stuff::FileStream *stream,
							 BOOL suppressPrompts) 
{
	//
	// create an empty scene
	//
	UpdateProgress(i, ++m_progress,CString("Preparing to copy."));

	ElementRenderer::GroupElement *root = new ElementRenderer::GroupElement;
	Register_Object(root);
	
    // Make sure that texture and erf paths exist
    bool texture_dir_exists = gos_CreateDirectory(m_texturePath);
	bool erf_dir_exists = gos_CreateDirectory(directoryPath + 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();

	int nrOfChildren = element_scene->GetChildCount();
	*stream << nrOfChildren;

	Proxies::ChildProxy *child = element_scene->UseFirstChildProxy();
	for(int c=0;c<nrOfChildren;c++)
	{
		Check_Object(child);

		Stuff::LinearMatrix4D theMatrix;
		Stuff::Point3D position;

		Proxies::ChildProxy *next = child->UseNextSiblingProxy();

		MAXProxies::MAXFlattenHierarchyProcess flatten_hierarchy(&config_file,i, m_progress, m_suppress);

		child->FlattenHierarchy(&flatten_hierarchy);

		Proxies::CleanHierarchyProcess cleanMeUp;
		cleanMeUp.CleanHierarchyCallback(child);

		if(child->IsDerivedFrom(Proxies::GroupProxy::DefaultData))
		{
			child->GetLocalToWorld(&theMatrix);

			position = theMatrix;

			// Save position of the child
			*stream << position;

			//
			// See if there are any meshes to fuse.  If there are no meshes, don't save
			// anything
			//
			Proxies::GroupProxy *group = Cast_Object(Proxies::GroupProxy*, child);

			Proxies::ChildProxy *first_child = group->UseFirstChildProxy();
			if (!first_child)
			{
				Verify(group->GetReferenceCount() == 1);
				EndExport(i);
				TurnOnExceptions();
				group->Destroy();
				return 1;
			}

			//
			// 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);

			FusePolygonMeshProxy(first_mesh,group->GetChildCount(),i,m_progress,m_suppress);

			//
			// Build the bounding sphere around the now only child
			//
			ElementProxies::OptimizeSyncProcess optimize;
			if (optimize.OptimizeSync(first_mesh))
				first_mesh->DetachReference();

			//
			// Open up the file to save the shape into, then save the child as the
			// root
			//
			ElementRenderer::Element *element = first_mesh->GetProxiedShape();
			ElementRenderer::ShapeElement *ElmShape=Cast_Object(ElementRenderer::ShapeElement *,element);
			ElmShape->GetMLRShape()->Save(stream);
		}
		else if(child->IsDerivedFrom(Proxies::PolygonMeshProxy::DefaultData))
		{
			ElementProxies::ElementPolygonMeshProxy *mesh =
				Cast_Object(ElementProxies::ElementPolygonMeshProxy*, child);

			FusePolygonMeshProxy(mesh,1,i,m_progress,m_suppress);

			ElementProxies::OptimizeSyncProcess optimize;
			if (optimize.OptimizeSync(mesh))
			{

				Stuff::Sphere bsphere;
				mesh->GetBoundingSphere(&bsphere);

				// Save position of the child
				*stream << bsphere.center;

				// Save bounding sphere radius for controlling purposes
				*stream << bsphere.center << bsphere.radius;

				DynamicArrayOf<Proxies::VertexProxy*> vertices;
				unsigned vertex_count = mesh->UseVertexArray(&vertices);
				for (unsigned i=0; i<vertex_count; ++i)
				{
					Proxies::VertexProxy *vertex = vertices[i];

					Check_Object(vertex);
					Point3D old_position;
					vertex->GetPosition(&old_position);
					
					Point3D new_position;
					new_position.Subtract(old_position, bsphere.center);
					vertex->SetPosition(new_position);
				}
				mesh->DetachArrayReferences(&vertices);

				Stuff::LinearMatrix4D newMatrix;

				newMatrix = Stuff::LinearMatrix4D::Identity;
				newMatrix.BuildTranslation(bsphere.center);

				mesh->SetLocalToParent(newMatrix);
				
				//
				// Open up the file to save the shape into, then save the child as the
				// root
				//				
				ElementRenderer::Element *element = mesh->GetProxiedShape();
				ElementRenderer::ShapeElement *ElmShape = Cast_Object(ElementRenderer::ShapeElement*,element);
				ElmShape->GetMLRShape()->Save(stream);
			}
		}
		Check_Object(child);
		child->DetachReference();
		child = next;
	}

	if(child != NULL)
	{
		child->DetachReference();
	}

	//
	// Clean up
	//
	EndExport(i);
	TurnOnExceptions();

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

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

int	EBFExp::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;
}
