// TCTb.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "TCTb.h"

#include "MainFrm.h"
#include "ChildFrm.h"
#include"ColorReduce.h"
#include "CamInfoTab.h"
#include "TarInfo.h"
#include "SplineControl.h"
#include "MiscCamProp.h"
#include "CamState.h"
#include "LimitedFileDialog.h"
#include "ExportOptions.h"
#include "TerrainDispOpts.h"
#include "OptimizeOptions.h"
#include "TNameBox.h"

CFinalBitmapWnd *Wnd2D;

extern DWORD RunGameOSLogic();

#include "CamInfoTabDlg.h"

#include <Stuff\StuffHeaders.hpp>
#include <MLR\MLRTexturePool.hpp>
#include <MFCPlatform\MFCPlatform.hpp>

char* Command_Line;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

void TerminateGameEngine();

/////////////////////////////////////////////////////////////////////////////
// CTCTbApp

BEGIN_MESSAGE_MAP(CTCTbApp, CWinApp)
//{{AFX_MSG_MAP(CTCTbApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_FILE_IMPORT_HEIGHTFIELD, OnFileImportHeightfield)
ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_COMMAND(ID_LAYER_SHOWALL, OnLayerShowall)
ON_COMMAND(ID_LAYER_DELETE, OnLayerDelete)
ON_COMMAND(ID_LAYER_ADD, OnLayerAdd)
ON_COMMAND(ID_LAYER_SHOWHEIGHTFIELD, OnLayerShowheightfield)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAMERA_FREEMODE, OnUpdateViewCameraFreemode)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAMERA_TRACKMODE, OnUpdateViewCameraTrackmode)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAMERA_USETARGET, OnUpdateViewCameraUsetarget)
ON_COMMAND(ID_VIEW_CAMERA_FREEMODE, OnViewCameraFreemode)
ON_COMMAND(ID_VIEW_CAMERA_TRACKMODE, OnViewCameraTrackmode)
ON_COMMAND(ID_VIEW_CAMERA_USETARGET, OnViewCameraUsetarget)
ON_COMMAND(ID_VIEW_RCURVE, OnViewRcurve)
ON_COMMAND(ID_OPTIONS_SETTEXTUREPATH, OnOptionsSettexturepath)
ON_COMMAND(ID_LAYER_SHOWBASETEXTURE, OnLayerShowbasetexture)
ON_COMMAND(ID_LAYER_SHOWDEPTHCOMPLEXITY, OnLayerShowdepthcomplexity)
ON_UPDATE_COMMAND_UI(ID_LAYER_SHOWHEIGHTFIELD, OnUpdateLayerShowheightfield)
ON_UPDATE_COMMAND_UI(ID_LAYER_SHOWDEPTHCOMPLEXITY, OnUpdateLayerShowdepthcomplexity)
ON_UPDATE_COMMAND_UI(ID_LAYER_SHOWBASETEXTURE, OnUpdateLayerShowbasetexture)
ON_UPDATE_COMMAND_UI(ID_LAYER_SHOWALL, OnUpdateLayerShowall)
ON_COMMAND(ID_VIEW_CAMERA_ANIMATEPATH, OnViewCameraAnimatepath)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAMERA_ANIMATEPATH, OnUpdateViewCameraAnimatepath)
ON_COMMAND(ID_WINDOW_CAMERACONTROLS, OnWindowCameracontrols)
ON_COMMAND(ID_WINDOW_FINALBITMAP, OnWindowFinalbitmap)
ON_COMMAND(ID_WINDOW_LAYERWINDOW, OnWindowLayerwindow)
ON_COMMAND(ID_WINDOW_RENDEREDVIEW, OnWindowRenderedview)
ON_UPDATE_COMMAND_UI(ID_WINDOW_CAMERACONTROLS, OnUpdateWindowCameracontrols)
ON_UPDATE_COMMAND_UI(ID_WINDOW_FINALBITMAP, OnUpdateWindowFinalbitmap)
ON_UPDATE_COMMAND_UI(ID_WINDOW_LAYERWINDOW, OnUpdateWindowLayerwindow)
ON_UPDATE_COMMAND_UI(ID_WINDOW_RENDEREDVIEW, OnUpdateWindowRenderedview)
ON_COMMAND(ID_FILE_IMPORT_BASETEXTURE, OnFileImportBasetexture)
ON_COMMAND(ID_FILE_IMPORT_DETAILTEXTURE, OnFileImportDetailtexture)
ON_COMMAND(ID_OPTIONS_EXPORTOPTIONS, OnOptionsExportoptions)
	ON_COMMAND(ID_WINDOW_FEATUREWINDOW, OnWindowFeaturewindow)
	ON_UPDATE_COMMAND_UI(ID_WINDOW_FEATUREWINDOW, OnUpdateWindowFeaturewindow)
	ON_COMMAND(ID_FILE_EXPORT, OnFileExport)
	ON_COMMAND(ID_OPTIONS_TERRAINDISPLAYOPTIONS, OnOptionsTerraindisplayoptions)
	ON_COMMAND(ID_FILE_IMPORT_MEGABASETEXTURE, OnFileImportMegabasetexture)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTCTbApp construction

CTCTbApp::CTCTbApp()
{
	// Place all significant initialization in InitInstance
	GOSActive=false;
	FBmpWnd=NULL;
	RVWnd=NULL;
	DMode=DM_HFIELD;	
	UndoLevels=DEFAULT_UNDO_LEVELS;
	CamInfo.SetMode(CameraInfo::CM_TRACK);
	CamInfo.UseTarget=false;
	CamInfo.Dir=Stuff::Vector3D(0,0,1);
	CamInfo.CamTrackAlt=15.0;
	CamInfo.TarTrackAlt=15.0;
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CTCTbApp object

CTCTbApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CTCTbApp initialization

BOOL CTCTbApp::InitInstance()
{
	AfxEnableControlContainer();
	
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.
	
#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif
	
	// Change the registry key under which our settings are stored.
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));
	
	
	// To create the main window, this code creates a new frame window
	// object and then sets it as the application's main window object.
	
	CMDIFrameWnd* pFrame = new CMainFrame;
	m_pMainWnd = pFrame;
	
	// create main MDI frame window
	if (!pFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	
	// try to load shared MDI menus and accelerator table
	//TODO: add additional member variables and load calls for
	//	additional menu types your application may need. 
	
	HINSTANCE hInst = AfxGetResourceHandle();
	m_hMDIMenu  = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_TCTBTYPE));
	m_hMDIAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_TCTBTYPE));
	
	
	
	// The main window has been initialized, so show and update it.
	pFrame->ShowWindow(m_nCmdShow);
	pFrame->UpdateWindow();
	
	
    FBmpWnd=new CFinalBitmapWnd;
	RVWnd=new CRenderedViewWnd;
	LWnd=new CLayerDlg;
	FDlg=new CFeatureDlg("Features",pFrame);;
	CInfDlg=new    CCamInfoTabDlg("Camera Properties",pFrame);
	
    FBmpWnd->Create(  NULL,
		TITLEVIEW2D,
		WS_CHILD|WS_VISIBLE|
		WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_THICKFRAME|WS_SYSMENU
		//|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
		, 
		CRect(0,0,DEFAULTBMPSIZE,DEFAULTBMPSIZE),
		pFrame);
	
	FBmpWnd->SetIcon(LoadIcon(IDI_ICON2D),TRUE);
	FBmpWnd->DragAcceptFiles(TRUE);
	//ModifyStyleEx(NULL,WS_EX_ACCEPTFILES); 
	
	Wnd2D=FBmpWnd;

	FBmpWnd->MakeDisplayedBmp(&TData);
	
	RVWnd->Create(  NULL,
		TITLEVIEW3D,
		WS_CHILD|WS_VISIBLE|
		WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU
		//|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
		, 
		CRect(0,0,640,480+18),
		pFrame);
	
	RVWnd->SetIcon(LoadIcon(IDI_ICON3D),TRUE);
	
	LWnd->Create(IDD_LAYERWND,pFrame);
	/*
	LWnd->Create(  NULL,
	"Layers",
	WS_CHILD|WS_VISIBLE|
	WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU
	|WS_THICKFRAME|WS_MAXIMIZEBOX
	, 
	LWnd->rectDefault,
	pFrame);
	
	*/
	//	LWnd->LayList.SetItem(0,0,LVIF_TEXT,"Height Map",LVIF_TEXT0,0,0,NULL);
	
	
	
	CInfDlg->AddPage(new CCamInfoTab);
	CInfDlg->AddPage(new CTarInfo);
	CInfDlg->AddPage(new CSplineControl);
	CInfDlg->AddPage(new CMiscCamProp);
	CInfDlg->AddPage(new CCamState);		
	CInfDlg->Create(pFrame);
	CInfDlg->SetWindowText("Camera Properties");
	CInfDlg->SetCameraInfo(&CamInfo);
	/*
	CInfDlg->Create(IDD_CAMINFO,pFrame);
	CInfDlg->SetCamInfo(&CamInfo);
	CInfDlg->ShowWindow(SW_SHOW);
	*/
	//	pFrame->CreateNewChild(
	//		RUNTIME_CLASS(CFinalBitmapWnd), IDR_TCTBTYPE, m_hMDIMenu, m_hMDIAccel);
	
	InitGameOS(  m_hInstance , RVWnd->m_hWnd, m_lpCmdLine );

	FDlg->Create(pFrame);
	FDlg->Init();
	TexturePath=GetProfileString(APPNAME,"TexturePath");
	if(TexturePath.GetLength()==0) 
	{
		NewTexturePath();
	} // end if string in Registry
	
	GetSavedState();
	pFrame->MDICascade(MDITILE_SKIPDISABLED);
	
	CamInfo.State=*RVWnd->Camera_State;
	
	
	
	//	LWnd->ShowWindow(SW_SHOW);
	
	FBmpWnd->UpdateDims();
	CamInfo.TargetLoc=FBmpWnd->MapToGrid(FBmpWnd->crct.CenterPoint());
	
	GOSActive=true;
	if(RunGameOSLogic()) PostQuitMessage(0);
	//AfxBeginThread(ContinousUpdate,NULL);	
	//SetThreadPriority(THREAD_PRIORITY_HIGHEST); 

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CTCTbApp message handlers

int CTCTbApp::ExitInstance() 
{
	//TODO: handle additional resources you may have added
	if (m_hMDIMenu != NULL)
		FreeResource(m_hMDIMenu);
	if (m_hMDIAccel != NULL)
		FreeResource(m_hMDIAccel);
	

delete FDlg;	
delete LWnd;
delete CInfDlg;
undoqueue.UnInitalize();

	return CWinApp::ExitInstance();
}

void CTCTbApp::OnFileNew() 
{
	CMainFrame* pFrame = STATIC_DOWNCAST(CMainFrame, m_pMainWnd);
	
	// create a new MDI child window
	//	pFrame->CreateNewChild(
	//		RUNTIME_CLASS(CChildFrame), IDR_TCTBTYPE, m_hMDIMenu, m_hMDIAccel);
}



/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
	
	// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA
	
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	// No message handlers
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CTCTbApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CTCTbApp message handlers

CTCTbApp::~CTCTbApp()
{
	//if(FBmpWnd) delete FBmpWnd;
}

void CTCTbApp::OnFileImportHeightfield() 
{
	CFileDialog fdlg(TRUE,NULL,NULL,NULL,"Bitmap Images (*.tif,*.gif,*.tga)|*.tif;*.gif;*.tga||",NULL);	
	if(fdlg.DoModal()==IDOK) 
	{
		CExportOptions eopt;
		eopt.SetData(EInfo);
		if(eopt.DoModal()==IDOK)
		{
		eopt.GetData(&EInfo);
		}
		ImportBitmap(fdlg.GetPathName());
	}
}

void InitializeGameEngine()
{
	//
	//---------------------
	// Initialize libraries
	//---------------------
	//
	Stuff::InitializeClasses();
	MidLevelRenderer::InitializeClasses(32768*16);
	MidLevelRenderer::InitializeStatistics();
	//	gosFX::InitializeClasses();
	ElementRenderer::InitializeClasses();
	Proxies::InitializeClasses();
	ElementProxies::InitializeClasses();
	
	theApp.PostGOSInit();
	
	MLRTexturePool::Instance->LoadImages();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DoGameLogic()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void UpdateDisplay()
{
	theApp.UpdateScreen();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void TerminateGameEngine()
{
	//
	//-------------------
	// Turn off libraries
	//-------------------
	//
	ElementProxies::TerminateClasses();
	Proxies::TerminateClasses();
	ElementRenderer::TerminateClasses();
	//	gosFX::TerminateClasses();
	MidLevelRenderer::TerminateClasses();
	Stuff::TerminateClasses();
}

void
	DumpScene(const char* name)
{
	//
	//----------------------
	// Get the scene pointer
	//----------------------
	//

	ListElement *root = theApp.RVWnd->Scene;
	Check_Object(root);

	//
	//--------------------------
	// Open the file and save it
	//--------------------------
	//
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream *element_stream =
		Stuff::FileStream::MakeFileStream();

	Register_Object(element_stream);
	element_stream->Open(name, Stuff::FileStream::WriteOnly);
	ElementRenderer::WriteERFVersion(element_stream);
	root->Save(element_stream);

	//
	//---------
	// Clean up
	//---------
	//
	Unregister_Object(element_stream);
	delete element_stream;
}

//
// Setup the GameOS structure
//
void __stdcall GetGameOSEnvironment( char* CommandLine )
{
	CommandLine=CommandLine;
	Environment.applicationName			= "TCT";
	Environment.screenWidth				= 640;
	Environment.screenHeight			= 480;
	Environment.fullScreen				= FALSE;
	Environment.bitDepth				= 16;
	Environment.debugLog				= "";			//"DebugLog.txt";
	Environment.spew					= "";			//"GameOS*";

	Environment.UpdateRenderers			= UpdateDisplay;
	Environment.DoGameLogic				= DoGameLogic;
	Environment.InitializeGameEngine	= InitializeGameEngine;
	Environment.TerminateGameEngine		= TerminateGameEngine;

	Environment.SceneDump				= DumpScene;
	
	Environment.Renderer				= 0;
	Environment.FullScreenDevice		= 0;
	
	Environment.AntiAlias				= 0;			// true/false - Enable full screen antialiasing
	
	//
	// Texture infomation
	//
	Environment.Texture_S_256			= 13;
	Environment.Texture_S_128			= 12;
	Environment.Texture_S_64			= 1;
	Environment.Texture_S_32			= 1;
	Environment.Texture_S_16			= 1;
	
	Environment.Texture_K_256			= 1;
	Environment.Texture_K_128			= 1;
	Environment.Texture_K_64			= 1;
	Environment.Texture_K_32			= 1;
	Environment.Texture_K_16			= 1;
	
	Environment.Texture_A_256			= 1;
	Environment.Texture_A_128			= 1;
	Environment.Texture_A_64			= 1;
	Environment.Texture_A_32			= 1;
	Environment.Texture_A_16			= 1;
}


BOOL CTCTbApp::OnIdle(LONG lCount) 
{
	if(GOSActive)
	if(RunGameOSLogic()) PostQuitMessage(0);
	return 1;
	//	return CWinApp::OnIdle(lCount);
}


void CTCTbApp::PostGOSInit()
{
	
	RVWnd->PostGOSInit();
	TData.Initalize();
	undoqueue.Initalize(UndoLevels);
	RVWnd->UpdateHField(*TData.HField);
	Image HFBmp=TData.HFLayer.Img;
	CamInfo.ViewLoop=new SplineLoop(EDCPOINTS,((float)HFBmp.GetWidth()/2)*0.8f,Stuff::Point3D((float)HFBmp.GetWidth()/2,0.0f,(float)HFBmp.GetHeight()/2));
	ResetViewLoop();
	
	MLRTexturePool::Instance->LoadImages();
	
}

bool
	CTCTbApp::ImportBitmap(Image &timg, int iRBX, int optPolys, int bucketSize)
{
	undoqueue.SaveState(TData);		//Save The UndoInformation
	
	if(timg.GetWidth()!=timg.GetHeight()) 
	{
		MessageBox(NULL,"Bitmap Must Be Square","Dimension Error",MB_OK);
		return false;
	}
	
	if(timg.GetBpp()<8)
	{
		MessageBox(NULL,"Bitmap Must Be At Least 8 bit","Depth Error",MB_OK);
		return false;
	}
	else
	{
		if(timg.GetBpp()>8) //Not a Bitmapped Image Resolve
		{
/*
			timg.CreateDifferentialMap();
			timg.SaveTiff("test.tif");
*/
			if(iRBX==-1)
			{
				CColorReduce rbx;
				if(rbx.DoModal()!=IDOK)
				{
					return false;
				}
				timg.ReduceTo8Bit(rbx.rmd);
			}
			else
			{
				RMETHOD rmd;

				switch(iRBX)
				{
					case 0:
						rmd=RMD_REDC;
					break;
					case 1:
						rmd=RMD_GREENC;
					break;
					case 2:
						rmd=RMD_BLUEC;
					break;
					case 3:
						rmd=RMD_ALPHAC;
					break;
					case 4:
						rmd=RMD_MAX;
					break;
					case 5:
						rmd=RMD_BHT;
					break;
					default:
						rmd=RMD_MAX;
				}

				timg.ReduceTo8Bit(rmd);
			}
		}	
		
		EInfo.SetPixels(timg.GetWidth(),timg.GetHeight());
		TData.LoadHeightField(timg);
		TData.HField->SetPara(EInfo);
		FBmpWnd->MakeDisplayedBmp(&TData);
		FBmpWnd->UpdateDims();
		CamInfo.TargetLoc=FBmpWnd->MapToGrid(FBmpWnd->crct.CenterPoint());
		UpdateActiveHField();

		ResetViewLoop();

		if((optPolys > 0) && (bucketSize > 0))
		{
			RVWnd->ActiveHField->OptimizeHField(1, optPolys/2, bucketSize);
		}
		else
		{
			COptimizeOptions optdlg;
			optdlg.m_fpolys=RVWnd->ActiveHField->GetFullPolyCount()/4;
			optdlg.m_opolys.Format("%i",RVWnd->ActiveHField->GetFullPolyCount());
			
			if(optdlg.DoModal()!=IDOK) return false; 
			
			RVWnd->ActiveHField->OptimizeHField(1, optdlg.m_fpolys/2, atoi(optdlg.m_bsizetext));
		}

		ResetViewLoop();
	}
	return true;
}

bool
	CTCTbApp::ImportBitmap(CString &fname, int iRBX, int optPolys, int bucketSize)
{
	Image timg;
	char tfn[MAX_PATH];
	
	strcpy(tfn,fname);
	timg.Load(tfn);
	return ImportBitmap(timg, iRBX, optPolys, bucketSize);
}

bool
	CTCTbApp::ImportBitmap(CBitmap &bmp, int iRBX, int optPolys, int bucketSize)
{
	Image timg;
	unsigned char *dat;
	BITMAP binf;
	bmp.GetBitmap(&binf);			
	
	if(binf.bmBitsPixel==8)
		timg.CreateSolid(binf.bmWidth,binf.bmHeight,ImgRGBColor(0,0,0),ITYPE_INDEXED,binf.bmBitsPixel);	
	else
		timg.CreateSolid(binf.bmWidth,binf.bmHeight,ImgRGBColor(0,0,0),ITYPE_RGB,binf.bmBitsPixel);	
	
	int x,y;
	
	dat=timg.Lock();
	
	for(y=0;y<timg.GetHeight();y++)
		for(x=0;x<timg.GetWidth()*(binf.bmBitsPixel>>3);x++) 
			dat[x+y*timg.GetPitch()]=((unsigned char *)binf.bmBits)[x+y*binf.bmWidthBytes];
		
	timg.UnLock();
		
	return ImportBitmap(timg, iRBX, optPolys, bucketSize);
}

void CTCTbApp::UpdateActiveHField()
{
	if(RVWnd) 
		RVWnd->UpdateHField(*TData.HField);

	EInfo.SetScale_Offset(
		RVWnd->ActiveHField->GetXScale(),
		RVWnd->ActiveHField->GetYScale(),
		RVWnd->ActiveHField->GetZScale(),
		RVWnd->ActiveHField->GetOffset()
	);
}

void CTCTbApp::OnUpdateEditRedo(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(undoqueue.Redoable()>0);
}

void CTCTbApp::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(undoqueue.Undoable()>0);
}

void CTCTbApp::OnEditRedo() 
{
	TData=undoqueue.Redo();
	FBmpWnd->MakeDisplayedBmp(&TData);
	UpdateActiveHField();
}

void CTCTbApp::OnEditUndo() 
{
	TData=undoqueue.Undo(TData);
	FBmpWnd->MakeDisplayedBmp(&TData);
	UpdateActiveHField();
}

void CTCTbApp::UpdateScreen()
{
	Scalar now = (Scalar)gos_GetElapsedTime();
	Scalar step = now - Last_Frame;
	
	Last_Frame = now;
	
	CamInfo.AddTime(step*TSCALE);	 
	DrawRView();
	int fvis;
	for(fvis=0;fvis<MAX_LAYERS && LWnd->LayStatus[fvis]!=LS_VISIBLE;fvis++);
	
	if(TData.SetViewedLayer(fvis))
		FBmpWnd->MakeDisplayedBmp(&TData);
	
	
	if(FBmpWnd) FBmpWnd->ReDraw();
	CInfDlg->Refresh();
}

void CTCTbApp::DrawRView()
{
	if(RVWnd) RVWnd->ReDraw(CamInfo);
}

void CTCTbApp::GOSCleanUp()
{
	if(RVWnd) RVWnd->PreGosCleanUp();
	if(CamInfo.ViewLoop) delete CamInfo.ViewLoop;
	TData.UnInitalize();
	TerminateGameEngine();
	ExitGameOS();
	GOSActive=0;
	//	ExitGameOS();
	
}


void CTCTbApp::OnLayerShowall() 
{
	// TODO: Add your command handler code here
	if(LWnd) LWnd->Showall();	
}

void CTCTbApp::OnLayerDelete() 
{
	// TODO: Add your command handler code here
	
}

void CTCTbApp::OnLayerAdd() 
{
	// TODO: Add your command handler code here
	
}


void CTCTbApp::ResetViewLoop()
{
float Rad,xp,yp;
Rad=((TData.HFLayer.Img.GetWidth()*RVWnd->ActiveHField->GetXScale())/2)*0.8f;
xp=(TData.HFLayer.Img.GetWidth()*RVWnd->ActiveHField->GetXScale())/2;
yp=(TData.HFLayer.Img.GetHeight()*RVWnd->ActiveHField->GetZScale())/2;
	CamInfo.ViewLoop->ResetCurve(Rad,Stuff::Point3D(xp,0,yp));
	
	int i;
	Stuff::Vector3D tv3d;
	Stuff::Point3D tp3d;
	
	for(i=0;i<EDCPOINTS;i++)
	{
		CamInfo.ViewLoop->GetCPoint(i,&tp3d,&tv3d);
		tp3d.y=RVWnd->ActiveHField->GetHeight(tp3d.x,tp3d.z)+CamInfo.TarTrackAlt;
		CamInfo.ViewLoop->SetCPoint(i,tp3d,tv3d);
	}
	
	if(FBmpWnd)
	{
		FBmpWnd->BoundSpline(CamInfo.ViewLoop);
		FBmpWnd->ReDraw();
	}
}




void CTCTbApp::OnUpdateViewCameraFreemode(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(CamInfo.GetMode()==CameraInfo::CM_FREE);	
}

void CTCTbApp::OnUpdateViewCameraTrackmode(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(CamInfo.GetMode()==CameraInfo::CM_TRACK);	
}

void CTCTbApp::OnUpdateViewCameraUsetarget(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(CamInfo.UseTarget);
}

void CTCTbApp::OnViewCameraFreemode() 
{
	CamInfo.SetMode(CameraInfo::CM_FREE);
}

void CTCTbApp::OnViewCameraTrackmode() 
{
	CamInfo.SetMode(CameraInfo::CM_TRACK);
}

void CTCTbApp::OnViewCameraUsetarget() 
{
	CamInfo.UseTarget=!CamInfo.UseTarget;
}

void CTCTbApp::OnViewRcurve() 
{
	// TODO: Add your command handler code here
	ResetViewLoop();
}



void CTCTbApp::LoadTextureLayer(TextureLayer *lay)
{
	char buf[MAX_PATH];
	
	GetCurrentDirectory(MAX_PATH,buf);
	
	CString tstr,fname;
	
	
	do
	{
		SetCurrentDirectory(TexturePath);
		CLimitedFileDialog fdlg(TRUE,NULL,NULL,OFN_NOCHANGEDIR,"Textures (*.tga)|*.tga||",NULL);	
		fdlg.SetDir(TexturePath);
		//tstr.Format("Select Texture for layer %i...",lnum);
		fdlg.wstr="Open Texture...";
		
		if(fdlg.DoModal()!=IDOK) return;
		tstr=fdlg.GetPathName();
		tstr=tstr.Left(tstr.ReverseFind('\\')+1);
		if(tstr.CompareNoCase(TexturePath))
		{
			CString tst2;
			tst2.Format("Please Use Specified Texture Path...\nCurrent Path = %s",TexturePath);
			MessageBox(NULL,tst2,"Texture Path Error",MB_OK);
		}
		else
		{
			fname=fdlg.GetFileName();
		}
	}
	while(tstr.CompareNoCase(TexturePath));
	
	fname=fname.SpanExcluding(".");
	/*	
	if(TData.Lay[lnum]) delete TData.Lay[lnum]; 
	TData.Lay[lnum]=new TextureLayer; 
	*/	
	
	lay->Import((LPCTSTR)fname);
	
	
	
	/*	
	if(lnum>0)
	{
	TData.Lay[lnum]->State.SetZBufferWriteOff();
	TData.Lay[lnum]->State.SetAlphaMode(MLRState::OneOneMode);
	TData.Lay[lnum]->State.SetPriority(MLRState::DefaultPriority + lnum);
	}
	RVWnd->ActiveHField->SetState(TData.Lay[lnum]->State,lnum);
	*/	
	SetCurrentDirectory(buf);
	
}

void CTCTbApp::LoadBTexture()
{
	LoadTextureLayer(&TData.BaseTexture);
	RVWnd->ActiveHField->SetState(TData.BaseTexture.State,0);
}

void CTCTbApp::LoadDTexture()
{
	LoadTextureLayer(&TData.DetailTexture);
	TData.DetailTexture.State.SetZBufferWriteOff();
	TData.DetailTexture.State.SetAlphaMode(MLRState::OneOneMode);
	TData.DetailTexture.State.SetPriority(MLRState::DefaultPriority + 1);
	RVWnd->ActiveHField->SetState(TData.DetailTexture.State,1);
}


void CTCTbApp::SetStates()
{
	RVWnd->ActiveHField->SetState(TData.BaseTexture.State,0);
	RVWnd->ActiveHField->SetState(TData.DetailTexture.State,1);
}

void CTCTbApp::SetTextureDir()
{
	
}

void ILFree(LPITEMIDLIST pidl); 

void CTCTbApp::NewTexturePath()
{
	char pname[MAX_PATH];
	BROWSEINFO bi; 
	if(m_pMainWnd==NULL)
		bi.hwndOwner =NULL;
	else
		bi.hwndOwner = m_pMainWnd->m_hWnd; 
	
	bi.pidlRoot = NULL; 
	bi.pszDisplayName = NULL; 
	bi.lpszTitle = "Choose Texture Path..."; 
	bi.ulFlags = BIF_RETURNONLYFSDIRS; 
	bi.lpfn = NULL; 
	bi.lParam = (LPARAM)this; 
	
	LPITEMIDLIST pidl = SHBrowseForFolder(&bi); 
	
	if (SHGetPathFromIDList(pidl,pname))  
	{
		TexturePath=pname;
		TexturePath+="\\";
		
		
		WriteProfileString("TCT","TexturePath",TexturePath);
	}
	
	if (bi.pidlRoot) 
	{ 
		ILFree( const_cast< ITEMIDLIST* >( bi.pidlRoot ) );
	} 
	
}

void ILFree(LPITEMIDLIST pidl) 
{ 
	LPMALLOC pMalloc; 
	
    if (pidl) 
    { 
#ifdef DEBUG 
		UINT cbSize = ILGetSize(pidl); 
		VALIDATE_PIDL(pidl); 
		
		// Fill the memory with some bad value... 
		_fmemset(pidl, 0xE5, cbSize); 
		
		// If large enough try to save the call return address of who 
		// freed us in the 3-6 byte of the structure. 
		if (cbSize >= 6) 
			*((UINT*)((LPSTR)pidl + 2)) =  *(((UINT*)&pidl) - 1); 
		
#endif 
		SHGetMalloc(&pMalloc); 
		pMalloc->Free( pidl); 
		pMalloc->Release(); 
		
    } 
} 


void CTCTbApp::OnOptionsSettexturepath() 
{
	NewTexturePath();
	MessageBox(NULL,"These changes will not take effect until the program is restarted","Warning!!!",MB_OK|MB_ICONEXCLAMATION);   	
	
}

void CTCTbApp::OnLayerShowheightfield() 
{
	if(LWnd) LWnd->Showheight();	
	
	if(DMode!=DM_HFIELD && FBmpWnd)
	{
		DMode=DM_HFIELD;	
		FBmpWnd->MakeDisplayedBmp(&theApp.TData);
	}
	
}

void CTCTbApp::OnLayerShowbasetexture() 
{
	if(DMode!=DM_BASETEXTURE && FBmpWnd)
	{
		DMode=DM_BASETEXTURE;	
		FBmpWnd->MakeDisplayedBmp(&theApp.TData);
	}
	
}

void CTCTbApp::OnLayerShowdepthcomplexity() 
{
	
	if(DMode!=DM_DEPTHCOMPLEX &&FBmpWnd)
	{
		DMode=DM_DEPTHCOMPLEX;	
		FBmpWnd->MakeDisplayedBmp(&theApp.TData);
	}
	
	
}

void CTCTbApp::OnUpdateLayerShowheightfield(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(DMode==DM_HFIELD);
}

void CTCTbApp::OnUpdateLayerShowdepthcomplexity(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(DMode==DM_DEPTHCOMPLEX);
}

void CTCTbApp::OnUpdateLayerShowbasetexture(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(TData.BaseTexture.IsLoaded());
	pCmdUI->SetCheck(DMode==DM_BASETEXTURE);
}

void CTCTbApp::OnUpdateLayerShowall(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(FALSE);
	pCmdUI->SetCheck(FALSE);
}

void CTCTbApp::OnViewCameraAnimatepath() 
{
	CamInfo.Animate=!CamInfo.Animate;	
}

void CTCTbApp::OnUpdateViewCameraAnimatepath(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(CamInfo.Animate);	
}

void CTCTbApp::OnWindowCameracontrols() 
{
	
	if(CInfDlg)
	{
		CInfDlg->ShowWindow(CInfDlg->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}
	
	
}

void CTCTbApp::OnWindowFinalbitmap() 
{
	if(FBmpWnd)
	{
		FBmpWnd->ShowWindow(FBmpWnd->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}
	
}

void CTCTbApp::OnWindowLayerwindow() 
{
	
	if(LWnd)
	{
		LWnd->ShowWindow(LWnd->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}
	
}

void CTCTbApp::OnWindowFeaturewindow() 
{

	if(FDlg)
	{
		FDlg->ShowWindow(FDlg->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}
}

void CTCTbApp::OnWindowRenderedview() 
{
	
	if(RVWnd)
	{
		RVWnd->ShowWindow(RVWnd->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}
	
}

void CTCTbApp::OnUpdateWindowCameracontrols(CCmdUI* pCmdUI) 
{
	
	if(CInfDlg)
	{
		pCmdUI->SetCheck(CInfDlg->IsWindowVisible()?TRUE:FALSE);
	}
	
}

void CTCTbApp::OnUpdateWindowFinalbitmap(CCmdUI* pCmdUI) 
{
	if(FBmpWnd)
	{
		pCmdUI->SetCheck(FBmpWnd->IsWindowVisible()?TRUE:FALSE);
	}
	
	
}

void CTCTbApp::OnUpdateWindowFeaturewindow(CCmdUI* pCmdUI) 
{
	if(FDlg)
	{
		pCmdUI->SetCheck(FDlg->IsWindowVisible()?TRUE:FALSE);
	}
	
}

void CTCTbApp::OnUpdateWindowLayerwindow(CCmdUI* pCmdUI) 
{
	if(LWnd)
	{
		pCmdUI->SetCheck(LWnd->IsWindowVisible()?TRUE:FALSE);
	}
	
}

void CTCTbApp::OnUpdateWindowRenderedview(CCmdUI* pCmdUI) 
{
	
	if(RVWnd)
	{
		pCmdUI->SetCheck(RVWnd->IsWindowVisible()?TRUE:FALSE);
	}
	
	
}


void CTCTbApp::GetSavedState()
{
	RVWnd->ShowWindow(GetProfileInt(APPNAME,"RVWndState",TRUE)?SW_SHOW:SW_HIDE);
	FBmpWnd->ShowWindow(GetProfileInt(APPNAME,"FBmpWndState",TRUE)?SW_SHOW:SW_HIDE);
	LWnd->ShowWindow(GetProfileInt(APPNAME,"LWndState",TRUE)?SW_SHOW:SW_HIDE);
	CInfDlg->ShowWindow(GetProfileInt(APPNAME,"CInfDlgState",TRUE)?SW_SHOW:SW_HIDE);
	FDlg->ShowWindow(GetProfileInt(APPNAME,"FeatureDlg",TRUE)?SW_SHOW:SW_HIDE);

CString str,str2;
	//String too largefor framework other method required.
int i,plnum;
	plnum=GetProfileInt(APPNAME,"PathListNum",0);

for(i=0;i<plnum;i++)
	{
	str2.Format("PathList%i",i);
	str=GetProfileString(APPNAME,str2);
	FDlg->PList->AddPath(str);
	}

	FDlg->Update();

}

void CTCTbApp::PutSavedState()
{
	WriteProfileInt(APPNAME,"RVWndState",RVWnd->IsWindowVisible());
	WriteProfileInt(APPNAME,"FBmpWndState",FBmpWnd->IsWindowVisible());
	WriteProfileInt(APPNAME,"LWndState",LWnd->IsWindowVisible());
	WriteProfileInt(APPNAME,"CInfDlgState",CInfDlg->IsWindowVisible());
	WriteProfileInt(APPNAME,"FeatureDlg",FDlg->IsWindowVisible());

CString str;
int i,plnum=FDlg->PList->GetTotalPaths();
	WriteProfileInt(APPNAME,"PathListNum",plnum);

	for(i=0;i<plnum;i++)
	{
	str.Format("PathList%i",i);
	WriteProfileString(APPNAME,str,FDlg->PList->GetPath(i));
	}

}

void CTCTbApp::OnFileImportBasetexture() 
{
	LoadBTexture();
}

void CTCTbApp::OnFileImportDetailtexture() 
{
	LoadDTexture();
}

void CTCTbApp::OnFileImportMegabasetexture() 
{
	char buf[MAX_PATH];
	
	GetCurrentDirectory(MAX_PATH,buf);
	
	CString tstr,fname;
	
	do
	{
		SetCurrentDirectory(TexturePath);
		CLimitedFileDialog fdlg(
			TRUE,
			NULL,
			NULL,
			OFN_NOCHANGEDIR,
			"MegaTextures (*.mbt)|*.mbt||",
			NULL
		);	
		fdlg.SetDir(TexturePath);
		//tstr.Format("Select Texture for layer %i...",lnum);
		fdlg.wstr="Open Texture...";
		
		if(fdlg.DoModal()!=IDOK) return;

		tstr=fdlg.GetPathName();
		tstr=tstr.Left(tstr.ReverseFind('\\')+1);

		if(tstr.CompareNoCase(TexturePath))
		{
			CString tst2;
			tst2.Format("Please Use Specified Texture Path...\nCurrent Path = %s",TexturePath);
			MessageBox(NULL,tst2,"Texture Path Error",MB_OK);
		}
		else
		{
			fname=fdlg.GetFileName();
		}
	}
	while(tstr.CompareNoCase(TexturePath));

	Stuff::FileStream *read_file = Stuff::FileStream::MakeFileStream();
	Register_Object(read_file);
	read_file->Open(fname, FileStream::ReadOnly);

	NotationFile *mega_file = new NotationFile(read_file);
	Register_Object(mega_file);

	const char *hf_name;
	if(!mega_file->GetEntry("HeightField", "HeightField", &hf_name))
	{
		SetCurrentDirectory(buf);
		return;
	}
	int polyCount;
	if(!mega_file->GetEntry("HeightField", "PolyCount", &polyCount))
	{
		polyCount = 0;
	}
	int bucketSize;
	if(!mega_file->GetEntry("HeightField", "BucketSize", &bucketSize))
	{
		polyCount = 0;
	}
	CString hfName(hf_name);
	if(false==ImportBitmap(hfName, 4, polyCount, bucketSize))
	{
		return;
	}

	int nrOfLevels;
	if(!mega_file->GetEntry("BaseTexture", "NumberOfLevels", &nrOfLevels))
	{
		nrOfLevels = 1;
	}
	
	const char *mega_base_name;
	if(!mega_file->GetEntry("BaseTexture", "BaseName", &mega_base_name))
	{
		SetCurrentDirectory(buf);
		return;
	}

	const char *mega_detail_name;
	if(!mega_file->GetEntry("DetailTexture", "DetailTexture", &mega_detail_name))
	{
		SetCurrentDirectory(buf);
		return;
	}

	Scalar ratio;
	if(!mega_file->GetEntry("DetailTexture", "DetailRatio", &ratio))
	{
		ratio = 16.0f;
	}

	const char *mega_alpha_name;
	MLRState::AlphaMode alpha;

	if(mega_file->GetEntry("DetailTexture", "DetailAlphaMode", &mega_alpha_name))
	{
		if(!strncmp(mega_alpha_name, "OneOne", sizeof("OneOne")))
		{
			alpha = MLRState::OneZeroMode;
		} else
		if(!strncmp(mega_alpha_name, "AlphaOne", sizeof("AlphaOne")))
		{
			alpha = MLRState::OneZeroMode;
		} else
		if(!strncmp(mega_alpha_name, "OneAlpha", sizeof("OneAlpha")))
		{
			alpha = MLRState::OneZeroMode;
		} else
		if(!strncmp(mega_alpha_name, "AlphaInvAlpha", sizeof("AlphaInvAlpha")))
		{
			alpha = MLRState::OneZeroMode;
		} else
		if(!strncmp(mega_alpha_name, "OneInvAlpha", sizeof("OneInvAlpha")))
		{
			alpha = MLRState::OneZeroMode;
		} else {
			alpha = MLRState::AlphaOneMode;
		}
	}
	else
	{
		alpha = MLRState::AlphaOneMode;
	}

	RVWnd->ActiveHField->SetDetailTextureInfo(
		mega_detail_name,
		0.0f,
		0.0f,
		ratio,
		ratio,
		alpha
	);

#ifdef NON_DEBUG_BUG
	fprintf(stdout, "\nCalling SetMegaTexture (tctb)");
#endif
	if(true==RVWnd->ActiveHField->SetMegaTexture(nrOfLevels, mega_base_name))
	{
#ifdef NON_DEBUG_BUG
	fprintf(stdout, "\nCalling SetMegaTexture (tctb) (returned TRUE)");
#endif
		OnFileExport();
	}
#ifdef NON_DEBUG_BUG
	fprintf(stdout, "\nCalling SetMegaTexture (tctb) (done)");
#endif

	Unregister_Object(mega_file);
	delete mega_file;

	read_file->Close();
	Unregister_Object(read_file);
	delete read_file;

	SetCurrentDirectory(buf);
}

void CTCTbApp::OnOptionsExportoptions() 
{
	CExportOptions eopt;
	eopt.SetData(EInfo);
	if(eopt.DoModal()==IDOK)
	{
		eopt.GetData(&EInfo);
		if(EInfo.Display)
		{
			TData.HField->SetPara(EInfo);
			RVWnd->ActiveHField->SetPara(EInfo);
			SetStates();
			ResetViewLoop();
		}
	}
	
}

void CTCTbApp::OnFileExport() 
{
#if 0
	NotationFile *config_file = new NotationFile;
	Register_Object(config_file);
	FileStream *temp_output = Stuff::FileStream::MakeFileStream();
	Register_Object(temp_output);
	temp_output->Open("TCTb.ini", FileStream::ReadOnly);
	config_file = new NotationFile(temp_output);
	Register_Object(config_file);
	
	Check_Object(config_file);
#endif

	int i = 0;

	Check_Object(RVWnd->ActiveHField->GetGroup());
//	Check_Pointer(content_root);
//	Check_Pointer(set_filename);

	CTNameBox tbx1;
	tbx1.DoModal();

	Stuff::MString set_filename(tbx1.m_TName);
	bool export_optimized_terrain = tbx1.ExportOptimized;
	//
	//---------------------------------------------------
	// Analyze the set file and extract the useful pieces
	//---------------------------------------------------
	//

	Stuff::MString erf_name = set_filename;
	erf_name += ".erf";
	Stuff::MString path("\\");
	Check_Object(Stuff::FileStreamManager::Instance);
	IsolateDirectory(&path);
	Stuff::MString object_name = set_filename;
	StripDirectory(&object_name);

	//
	//----------------------------------------------------------------------
	// Walk through the interest zone children and convert each of them to a
	// list of boxes.  Only polygon mesh children are considered.
	//----------------------------------------------------------------------
	//
	Stuff::ExtentBox allBox;
	DynamicArrayOf<Stuff::ExtentBox> iZone(1);

	iZone[0] = RVWnd->ActiveHField->GetExtents();

	//
	//---------------------------------------------
	// Build a BSP structure for the extentbox list
	//---------------------------------------------
	//
/*
	Proxies::FindErrorsProcess sort_error_process(config_file);

	Proxies::BinSortProcess sort_bin_process(config_file);

	Proxies::SortInterestZonesProcess
		sort_process(config_file, path, iZone, &sort_bin_process, &sort_error_process);

	Proxies::InterestBSP *tree =
		Proxies::InterestBSP::CreateBSPTree(&sort_process);

	Check_Object(tree);

	ElementRenderer::GroupElement *tGrp = RVWnd->ActiveHField->GetTerrainWithInterestZones(tree);
*/

	//
	//----------------------
	// Build the armory zone
	//----------------------
	//
//	Verify(!sort_process.setContents);
	Stuff::NotationFile *contents = new Stuff::NotationFile;
	Register_Object(contents);
//	sort_process.setContents = contents;
	const char* page_name = "ArmoryZone";
	contents->SetEntry(page_name, "Model", "InterestZone.data");
	contents->SetEntry(
		page_name,
		"PreCollisionState",
		"AlwaysExecuteState"
	);
	contents->SetEntry(
		page_name,
		"PostCollisionState",
		"AlwaysExecuteState"
	);
	contents->SetEntry(page_name, "CollisionMask", "0");
	contents->SetEntry(page_name, "Cull", "AlwaysCull");
	contents->SetEntry(page_name, "ParentedToInterestGraphFlag", "no");
	contents->SetEntry(page_name, "CanInterestFlag", "yes");
	contents->SetEntry(page_name, "CulledInterestFlag", "no");
	contents->SetEntry(page_name, "ArmoryZoneFlag", "yes");
	contents->SetEntry(
		page_name,
		"Box",
		"1000000,1000000,1000000,1000100,1000100,1000100"
	);


	CString tstr1, tstr2, tstr3;

	Stuff::NotationFile **terrains = new Stuff::NotationFile * [RVWnd->ActiveHField->GetNrOfIZs()];
	Register_Pointer(terrains);

	for(i=0;i<RVWnd->ActiveHField->GetNrOfIZs();i++)
	{
		terrains[i] = new Stuff::NotationFile;
		Register_Object(terrains[i]);

		tstr1.Format("iz%d", i);

		const char* page_name2 = tstr1;
		contents->SetEntry(page_name2, "Model", "InterestZone.data");
		contents->SetEntry(
			page_name2,
			"PreCollisionState",
			"NeverExecuteState"
		);
		contents->SetEntry(
			page_name2,
			"PostCollisionState",
			"NeverExecuteState"
		);
		contents->SetEntry(page_name2, "ParentedToInterestGraphFlag", "no");
		contents->SetEntry(page_name2, "CanInterestFlag", "yes");
		contents->SetEntry(page_name2, "CulledInterestFlag", "no");

		tstr3 = "\"" + tstr1 + "\"";
		contents->SetEntry(page_name2, "Locator", tstr3);
		contents->SetEntry(page_name2, "ArmoryZoneFlag", "no");

		tstr2.Format("iz%d.contents", i);

		contents->SetEntry(page_name2, "Contents", tstr2);

		tstr2.Format("%f,%f,%f,%f,%f,%f",	iZone[i].minX,iZone[i].minY,iZone[i].minZ,
											iZone[i].maxX,iZone[i].maxY,iZone[i].maxZ);
		
		contents->SetEntry(page_name2, "Box", tstr2);

		tstr1 = "Floor";
		
		page_name2 = tstr1;

		terrains[i]->SetEntry(page_name2, "Model", "Floor.data");

#if 0
		tstr2.Format("%f %f %f",	iZone[i].minX + (iZone[i].maxX-iZone[i].minX)/2.0f,
									iZone[i].minY + (iZone[i].maxY-iZone[i].minY)/2.0f,
									iZone[i].minZ + (iZone[i].maxZ-iZone[i].minZ)/2.0f
					);
		terrains[i]->SetEntry(page_name2, "Translation", tstr2);
#else
		terrains[i]->SetEntry(page_name2, "Translation", "0.000000 0.000000 0.000000");
#endif


		terrains[i]->SetEntry(
			page_name2,
			"PreCollisionState",
			"NeverExecuteState"
		);
		terrains[i]->SetEntry(
			page_name2,
			"PostCollisionState",
			"NeverExecuteState"
		);

		terrains[i]->SetEntry(page_name2, "CollisionMask", "-1");
		terrains[i]->SetEntry(page_name2, "Collidee", "yes");
		terrains[i]->SetEntry(page_name2, "ParentedToInterestGraphFlag", "yes");
		terrains[i]->SetEntry(page_name2, "CanInterestFlag", "yes");
		terrains[i]->SetEntry(page_name2, "CulledInterestFlag", "yes");

		tstr2.Format("\"floor%d\"", i);
		terrains[i]->SetEntry(page_name2, "Locator", tstr2);
	}

	//
	//---------------------------------------------
	// Build the scene that we will be sorting into
	//---------------------------------------------
	//
#ifdef _DEBUG
#undef new 
#endif

	ElementRenderer::ListElement *root = new ElementRenderer::ListElement;
	Register_Object(root);
	root->SetSize(1);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

	int nrOfIZs = 0;
	char str[20];
	ElementRenderer::ListElement *MGrp = NULL;
	ElementRenderer::GroupElement *MTGrp = NULL;

	ElementRenderer::Element *terrain;
	bool terrainVisible;
	if(export_optimized_terrain==true)
	{
		terrain = RVWnd->ActiveHField->GetOptTerrain();
		terrainVisible = RVWnd->ActiveHField->IsOptDisplayed();
		RVWnd->ActiveHField->DisplayOpt(false);
	}
	else
	{
		terrain = RVWnd->ActiveHField->GetFullTerrain();
		terrainVisible = RVWnd->ActiveHField->IsFullDisplayed();
		RVWnd->ActiveHField->DisplayFull(false);
	}
#undef new 

#ifdef _DEBUG
#undef new 
#endif


	MGrp = new ElementRenderer::ListElement;
	Register_Object(MGrp);
	MGrp->SetSize(1);
	root->AttachIndexedChild(0, MGrp);

	sprintf(str, "iz%d", nrOfIZs);
	MGrp->SetName(str);

	MTGrp = new ElementRenderer::GroupElement;
	Register_Object(MTGrp);
	MGrp->AttachIndexedChild(0, MTGrp);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

	sprintf(str, "floor%d", nrOfIZs);
	MTGrp->SetName(str);

	MTGrp->AttachChild(terrain);

#if 0
	ElementProxies::ElementSceneProxy *element_scene =
		ElementProxies::ElementSceneProxy::MakeProxy( tGrp );
	Register_Object(element_scene);

	#if defined(_DEBUG)
		int ref_count =
	#endif
	element_scene->GetReferenceCount();

	//
	//---------------------------------------------------------------
	// Now, flatten the element_scene and then set up the contents file in
	// preparation for the BSP process
	//---------------------------------------------------------------
	//
	Proxies::FlattenHierarchyProcess flatten_hierarchy(config_file);
	element_scene->FlattenHierarchy(&flatten_hierarchy);
	Verify(element_scene->GetReferenceCount() == ref_count);


	//
	//-----------------
	// Cut up the scene
	//-----------------
	//
	tree->SplitScene(&sort_process, element_scene);
	Verify(element_scene->GetReferenceCount() == ref_count);

	//
	//-----------------------
	// Clean up the hierarchy
	//-----------------------
	//
	Proxies::CleanHierarchyProcess clean_process(config_file);
	element_scene->CleanHierarchy(&clean_process);
	Verify(element_scene->GetReferenceCount() == ref_count);


	//
	//---------------------------
	// Build the bounding spheres
	//---------------------------
	//
	ElementProxies::OptimizeSyncProcess optimize;
	optimize.OptimizeSync(element_scene);
	Verify(element_scene->GetReferenceCount() == ref_count);
#endif

	//
	//---------------------------------------------
	// Write out the element_scene, then close the scene
	//---------------------------------------------
	//
	Stuff::FileStream *element_stream =
		Stuff::FileStream::MakeFileStream();
	Register_Object(element_stream);

	Stuff::MString contents_name = path;
	contents_name += erf_name;

	element_stream->Open(contents_name, Stuff::FileStream::WriteOnly);

	ElementRenderer::WriteERFVersion(element_stream);
//	element_scene->GetProxiedScene()->Save(element_stream);

//	Verify(element_scene->GetReferenceCount() == 1);
//	element_scene->Destroy();
	root->Save(element_stream);

	Unregister_Object(element_stream);
	delete element_stream;

	MTGrp->DetachChild(terrain);

	if(export_optimized_terrain==true)
	{
		RVWnd->ActiveHField->DisplayOpt(terrainVisible);
	}
	else
	{
		RVWnd->ActiveHField->DisplayFull(terrainVisible);
	}

	delete root;

	//
	//--------------------------------
	// Now, save out the contents file
	//--------------------------------
	//
	Stuff::FileStream *file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += object_name;
	contents_name += ".contents";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;

#if 0
	sort_process.setContents = NULL;
#endif
	Unregister_Object(file);
	delete file;

	for(i=0;i<RVWnd->ActiveHField->GetNrOfIZs();i++)
	{
		file = Stuff::FileStream::MakeFileStream();
		Register_Object(file);

		CString terrains_name;
		terrains_name.Format("%siz%d.contents", (const char *)path, i);

		file->Open(terrains_name, Stuff::FileStream::WriteOnly);
		terrains[i]->Write(file);

		Unregister_Object(terrains[i]);
		delete terrains[i];

		Unregister_Object(file);
		delete file;
	}

	Unregister_Pointer(terrains);
	delete [] terrains;

	//
	//---------------------------------
	// Create the FloorEntity.data file
	//---------------------------------
	//
	contents = new Stuff::NotationFile;
	Register_Object(contents);

	contents->SetEntry("GameData", "Class", "Entity");

	file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += "Floor.data";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;
	Unregister_Object(file);
	delete file;

	//
	//----------------------------------
	// Create the InterestZone.data file
	//----------------------------------
	//
	contents = new Stuff::NotationFile;
	Register_Object(contents);

	contents->SetEntry("GameData", "Class", "InterestZone");
	contents->SetEntry(
		"Renderers",
		"VideoRenderer",
		"InterestZone.video"
	);

	file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += "InterestZone.data";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;
	Unregister_Object(file);
	delete file;

	//
	//-----------------------------------
	// Create the InterestZone.video file
	//-----------------------------------
	//
	contents = new Stuff::NotationFile;
	Register_Object(contents);
	contents->SetEntry("Controller", "Type", "LocatorController");

	contents->SetEntry("TurnOn", "Type", "StateWatcher");
	contents->SetEntry("TurnOn", "Output", "Controller");
	contents->SetEntry("TurnOn", "Command", "EnableLocator");
	contents->SetEntry("TurnOn", "Attribute", "PreCollisionState");
	contents->SetEntry("TurnOn", "NewState", "AlwaysExecuteState");

	contents->SetEntry("TurnOff", "Type", "StateWatcher");
	contents->SetEntry("TurnOff", "Output", "Controller");
	contents->SetEntry("TurnOff", "Command", "DisableLocator");
	contents->SetEntry("TurnOff", "Attribute", "PreCollisionState");
	contents->SetEntry("TurnOff", "NewState", "NeverExecuteState");

	file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += "InterestZone.video";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;
	Unregister_Object(file);
	delete file;

	//
	//------------------------------
	// Create the Terrain.video file
	//------------------------------
	//
	contents = new Stuff::NotationFile;
	Register_Object(contents);
	contents->SetEntry("Mesh_1", "Type", "VideoObject");

	contents->SetEntry("Mesh_1", "Geometry", erf_name);

	contents->SetEntry("Locator", "Child", "Mesh_1");

	file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += object_name;
	contents_name += ".video";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;
	Unregister_Object(file);
	delete file;

	//
	//-------------------------
	// Create the Set.data file
	//-------------------------
	//

	contents = new Stuff::NotationFile;
	Register_Object(contents);
	contents->SetEntry("GameData", "Class", "InterestGraph");

	contents_name = object_name;
	contents_name += ".video";
	contents->SetEntry("Renderers", "VideoRenderer", contents_name);

	file = Stuff::FileStream::MakeFileStream();
	Register_Object(file);
	contents_name = path;
	contents_name += object_name;
	contents_name += "Set.data";
	file->Open(contents_name, Stuff::FileStream::WriteOnly);
	contents->Write(file);
	Unregister_Object(contents);
	delete contents;
	Unregister_Object(file);
	delete file;

#if 0	// no height field collision right now
	contents_name = path;
	contents_name += object_name;
	contents_name += ".hff";

	RVWnd->ActiveHField->SaveHeightFieldInformations(contents_name);
#endif

	//
	//--------------------
	// We done, so go home
	//--------------------
	//

#if 0
	Unregister_Object(tree);
	delete tree;
	Unregister_Object(config_file);
	delete config_file;

	temp_output->Close();

	Unregister_Object(temp_output);
	delete temp_output;
#endif

} // end of export

void CTCTbApp::OnOptionsTerraindisplayoptions() 
{
	// TODO: Add your command handler code here
	CTerrainDispOpts optdlg;

	optdlg.m_FPCount.Format("%i",RVWnd->ActiveHField->GetFullPolyCount());
	optdlg.m_OPCount=RVWnd->ActiveHField->GetOptPolyCount();
	optdlg.m_DFull=RVWnd->ActiveHField->IsFullDisplayed();
	optdlg.m_DOpt=RVWnd->ActiveHField->IsOptDisplayed();

	if(optdlg.DoModal()==IDOK)
	{
		RVWnd->ActiveHField->DisplayFull(optdlg.m_DFull!=0);
		RVWnd->ActiveHField->DisplayOpt(optdlg.m_DOpt!=0);
		if(optdlg.m_OPCount!=RVWnd->ActiveHField->GetOptPolyCount())
		{
			RVWnd->ActiveHField->OptimizeHField(0, optdlg.m_OPCount/2);
		}
	}
}
