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

#include <io.h>
#include <direct.h>

#include "stdafx.h"
#include "MW4GameEd.h"
#include "DisplayWindow.h"
#include "OverviewWindow.h"
#include "InstanceWindow.h"
#include "ResourceWindow.h"
#include "MainFrm.h"
#include <MLR\MLR.hpp>
#include <MLR\MLRTexturePool.hpp>
#include <MLR\MLRLight.hpp>
#include <MFCPlatform\MFCPlatform.hpp>
#include <MW4\MWTool.hpp>
#include <MW4\MWApplication.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Map.hpp>
#include "selection.h"
#include "startdlg.h"
#include "OpenMapFileDlg.h"
#include "GenericTextDlg.h"
#include <direct.h>
#include <errno.h>
#include <io.h>
#include "Selection.h"
#include "MoveCommand.h"
#include "MW4GameEdApplication.hpp"
#include <MW4\MWMission.hpp>
#include <MW4\MWPlayer.hpp>
#include "NewMissionDlg.h"
#include "MsgDlg.h"
#include "FileDlg.h"
#include "tipDlg.h"
#include <Adept\resource.hpp>
#include <mw4\ai.hpp>
#include "AddCommand.h"
#include <Adept\NameTable.hpp>
#include <Stuff\MemoryStream.hpp>
#include "DeleteCommand.h"
#include <Adept\NameTable.hpp>
#include <Compost\TerrainTextureLogistic.hpp>
#include <MW4\Building.hpp>
#include <mw4\EffectGenerator.hpp>
#include <MW4\SearchLight.hpp>
#include <MW4\Turret.hpp>
#include <mw4\Cultural.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <mw4\mwmission.hpp>
#include <ElementRenderer\LightElement.hpp>
#include <Adept\ResourceEffectLibrary.hpp>
#include <MW4\MechLab.hpp>
#include <MW4\Rail_move.hpp>
#include "GlobalDefs.h"
#include "LightWnd.h"
#include "FogDlg.h"
#include "EditorWayPoint.h"
#include "mw4\mwmap.hpp"
#include <mw4\NavPoint.hpp>
#include <mw4\noncom.hpp>
#include <Adept\Entity.hpp>

#include "..\buildnum\buildnum.h" // current version and build number
#include <dos.h>

#include <MW4\rail_move.hpp>
#include "Splash.h"
#include "ProgDlg.h"
#include "dlgobjectproperties.h"
#include "dlgobjectbalance.h"

#define __mbsrchr(s,c) (char*)_mbsrchr((const unsigned char*)(s),(c))

using namespace MW4AI;
extern CMW4GameEdApp theApp;

void _stdcall TerminateGameEngine();

char* Command_Line;
char Working_Directory[128];

void AddToBuildFile(CString missionName,CString map_name);

bool TestFileWrite(char* filename)
{
	DWORD result = GetFileAttributes(filename);
	
	if (result == -1)
		return true;
	if (result & FILE_ATTRIBUTE_READONLY)	// is it marked READONLY?
	{
		MessageBox(NULL,"Unable to save file becuase some of the data files are marked READONLY","Save Error",MB_OK);
		return false;
	}
	
	return true;
}

CProgressDlg* ProgressDlg = NULL;

void CalcLinkProgress(float pct)
{
	ProgressDlg->SetPos(int(pct));
}

bool EditMissionScriptCallback(char* filename)
{
	MWMission *mission = Cast_Object (MWMission *,Mission::Instance);
	strncpy(mission->scriptName,filename,127);
	theApp.m_ScriptName = filename;
	return true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CMW4GameEdApp

BEGIN_MESSAGE_MAP(CMW4GameEdApp, CWinApp)
ON_COMMAND(CG_IDS_TIPOFTHEDAY, ShowTipOfTheDay)
ON_COMMAND_RANGE(ID_SET_CAMERA_POS_0, ID_SET_CAMERA_POS_9,   OnSetNumberedCameraPosition )
ON_COMMAND_RANGE(ID_GOTO_CAMERA_POS_0, ID_GOTO_CAMERA_POS_9, OnGotoNumberedCameraPosition)
ON_UPDATE_COMMAND_UI_RANGE(ID_TOOLS_DEF_ALIGNMENT_1, ID_TOOLS_DEF_ALIGNMENT_10, OnUpdateDefaultAlignmentMenu)
ON_COMMAND_RANGE(ID_TOOLS_DEF_ALIGNMENT_1, ID_TOOLS_DEF_ALIGNMENT_10, OnDefaultAlignmentMenu)
//{{AFX_MSG_MAP(CMW4GameEdApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_VIEW_OVERVIEWWINDOW, OnToggleOverviewWindow)
ON_COMMAND(ID_VIEW_RESOURCEWINDOW, OnToggleResourceWindow)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_COMMAND(ID_ADJUSTGRID, OnAdjustGrid)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_UPDATE_COMMAND_UI(ID_VIEW_OVERVIEWWINDOW, OnUpdateViewOverviewwindow)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESOURCEWINDOW, OnUpdateViewResourcewindow)
ON_COMMAND(ID_VIEW_DISPLAYWINDOW, OnViewDisplaywindow)
ON_UPDATE_COMMAND_UI(ID_VIEW_DISPLAYWINDOW, OnUpdateViewDisplaywindow)
ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
ON_COMMAND(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M, OnToolsCameraheightFourtimesmechheight40m)
ON_COMMAND(ID_TOOLS_CAMERAHEIGHT_GROUND, OnToolsCameraheightGround)
ON_COMMAND(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M, OnToolsCameraheightMechheight10m)
ON_COMMAND(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M, OnToolsCameraheightTwicemechheight20m)
ON_COMMAND(ID_TOOLS_CAMERASPEED_SLOW, OnToolsCameraspeedSlow)
ON_COMMAND(ID_TOOLS_CAMERASPEED_REGULAR, OnToolsCameraspeedRegular)
ON_COMMAND(ID_TOOLS_CAMERASPEED_FAST, OnToolsCameraspeedFast)
ON_COMMAND(ID_VIEW_INSTANCEWINDOW, OnViewInstancewindow)
ON_UPDATE_COMMAND_UI(ID_VIEW_INSTANCEWINDOW, OnUpdateViewInstancewindow)
ON_COMMAND(ID_TOOLS_BRIEFINGFILE, OnToolsBriefingfile)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
ON_COMMAND(ID_TOOLS_CAMERAFOLLOWING_GROUND, OnToolsCamerafollowingGround)
ON_COMMAND(ID_TOOLS_CAMERAFOLLOWING_HIGHESTPOINT, OnToolsCamerafollowingHighestpoint)
ON_COMMAND(ID_TOOLS_CAMERAFOLLOWING_NONE, OnToolsCamerafollowingNone)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERAFOLLOWING_GROUND, OnUpdateToolsCamerafollowingGround)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERAFOLLOWING_HIGHESTPOINT, OnUpdateToolsCamerafollowingHighestpoint)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERAFOLLOWING_NONE, OnUpdateToolsCamerafollowingNone)
ON_COMMAND(ID_TOOLS_CAMERAHEIGHT_USERDEFINED, OnToolsCameraheightUserdefined)
ON_COMMAND(ID_VIEW_RESIZE1024, OnViewResize1024)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE1024, OnUpdateViewResize1024)
ON_COMMAND(ID_VIEW_RESIZE1152, OnViewResize1152)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE1152, OnUpdateViewResize1152)
ON_COMMAND(ID_VIEW_RESIZE1280, OnViewResize1280)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE1280, OnUpdateViewResize1280)
ON_COMMAND(ID_VIEW_RESIZE1600, OnViewResize1600)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE1600, OnUpdateViewResize1600)
ON_COMMAND(ID_VIEW_RESIZE640, OnViewResize640)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE640, OnUpdateViewResize640)
ON_COMMAND(ID_VIEW_RESIZE800, OnViewResize800)
ON_UPDATE_COMMAND_UI(ID_VIEW_RESIZE800, OnUpdateViewResize800)
ON_COMMAND(ID_FILE_AUTOBACKUPONSAVE, OnFileAutobackuponsave)
ON_UPDATE_COMMAND_UI(ID_FILE_AUTOBACKUPONSAVE, OnUpdateFileAutobackuponsave)
ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
ON_COMMAND(ID_FILE_DELETE, OnFileDelete)
ON_COMMAND(ID_TOOLS_MOVEMENTLATTICE, OnToolsMovementlattice)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVEMENTLATTICE, OnUpdateToolsMovementlattice)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWLATTICELINKS, OnToolsMovmentlayerShowlatticelinks)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWLATTICELINKS, OnUpdateToolsMovmentlayerShowlatticelinks)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_RECALCLATTICELINKS, OnToolsMovmentlayerRecalclatticelinks)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWALL, OnToolsMovmentlayerShowall)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWNODERADII, OnToolsMovmentlayerShownoderadii)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWPATHS, OnToolsMovmentlayerShowpaths)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWALL, OnUpdateToolsMovmentlayerShowall)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWNODERADII, OnUpdateToolsMovmentlayerShownoderadii)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWPATHS, OnUpdateToolsMovmentlayerShowpaths)
ON_COMMAND(ID_TOOLS_MECHLAB, OnToolsMechlab)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWMISSIONBOUNDARY, OnToolsMovmentlayerShowmissionboundary)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWMISSIONBOUNDARY, OnUpdateToolsMovmentlayerShowmissionboundary)
ON_COMMAND(ID_TOOLS_VERIFYOBJECTPLACEMENT, OnToolsVerifyobjectplacement)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWDROPZONES, OnToolsMovmentlayerShowdropzones)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWDROPZONES, OnUpdateToolsMovmentlayerShowdropzones)
ON_COMMAND(ID_TOOLS_EDITMISSIONSCRIPT, OnToolsEditmissionscript)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_SHOWOBJECTIVES, OnToolsMovmentlayerShowobjectives)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MOVMENTLAYER_SHOWOBJECTIVES, OnUpdateToolsMovmentlayerShowobjectives)
ON_COMMAND(ID_VIEW_SHOWTILEBORDERS, OnViewShowtileborders)
ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWTILEBORDERS, OnUpdateViewShowtileborders)
ON_COMMAND(ID_TOOLS_SPECIFYMISSIONSCRIPT, OnToolsSpecifymissionscript)
ON_COMMAND(ID_TOOLS_CHECKSCRIPTS, OnToolsCheckscripts)
ON_COMMAND(ID_TOOLS_MOVMENTLAYER_CREATELATTICE, OnToolsMovmentlayerCreatelattice)
ON_COMMAND(ID_TOOLS_MOVEMENTLAYER_CREATERECTS, OnToolsMovmentlayerCreateRects)
ON_COMMAND(ID_TOOLS_MISSIONPARAMETERS_EDITFOG, OnToolsMissionparametersEditfog)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERASPEED_FAST, OnUpdateToolsCameraspeedFast)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERASPEED_REGULAR, OnUpdateToolsCameraspeedRegular)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERASPEED_SLOW, OnUpdateToolsCameraspeedSlow)
ON_COMMAND(ID_TOOLS_SNAPOBJECTSTOTERRAIN, OnToolsSnapobjectstoterrain)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_TOOLS_WEAPONSPROPERTIES, OnToolsWeaponsProperties)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MECHPROPERTIES, OnUpdateToolsMechProperties)
ON_COMMAND(ID_TOOLS_MECHPROPERTIES, OnToolsMechProperties)
ON_UPDATE_COMMAND_UI(ID_TOOLS_WEAPONSPROPERTIES, OnUpdateToolsWeaponsProperties)
ON_COMMAND(ID_TOOLS_WEAPONSBALANCING, OnToolsWeaponsBalancing)
ON_UPDATE_COMMAND_UI(ID_TOOLS_WEAPONSBALANCING, OnUpdateToolsWeaponsBalancing)
ON_COMMAND(ID_TOOLS_ARMORBALANCING, OnToolsArmorBalancing)
ON_UPDATE_COMMAND_UI(ID_TOOLS_ARMORBALANCING, OnUpdateToolsArmorBalancing)
ON_COMMAND(ID_TOOLS_PLACEWITHMAP, OnToolsPlacewithmap)
ON_COMMAND(ID_TOOLS_DISPERSECULTURALWITHBITMAP, OnToolsDisperseculturalwithbitmap)
ON_COMMAND(ID_TOOLS_REMOVECULTURALS, OnToolsRemoveculturals)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CMW4GameEdApp construction


CMW4GameEdApp::CMW4GameEdApp() :
culturalList(NULL),
undoChain(NULL),
dirtyGameModelResources(NULL)
{
	displayWindow = NULL;
	overviewWindow = NULL;
	resourceWindow = NULL;
	briefingWnd = NULL;
	didIdle = false;
	cameraFollowing = CAMERA_FOLLOW_GROUND;
	m_VideoResolution = 640;
	m_VersionString = VER_PRODUCTVERSION_STR;
	m_AutoBackupOnSave = false;
	
	m_WaitCursor = NULL;
	m_AllLoaded = false;
	m_MechLabActive = false;
	m_showTileBorder = false;
	
	m_NumObjectives = 0;
	
	lightDlg = NULL;
	fogDlg = NULL;
	
	memset((void *) m_4DCameraBookmark, 0, sizeof(m_4DCameraBookmark)) ;
	
	//
	// Initialize to where Enemy is in the list (constant right now)
	//            can be changed to a fixed location if necessary, but make sure
	//            that it is not set above LastAlignment value since that could
	//            cause an array out of bounds later on where used.
	//
	m_nDefaultAlignmentForPlacedObjects = (Entity::LastAlignment >= 2) ?  2 /*enemy*/ : 0; 
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CMW4GameEdApp::~CMW4GameEdApp()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The one and only CMW4GameEdApp object

CMW4GameEdApp theApp;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CMW4GameEdApp initialization

bool g_ScreenSaverFlag;

BOOL CMW4GameEdApp::InitInstance()
{
	// CG: The following block was added by the Splash Screen component.
	\
	{
		\
			CCommandLineInfo cmdInfo;
		\
			ParseCommandLine(cmdInfo);
		\
			
			\
			CSplashWnd::EnableSplashScreen(cmdInfo.m_bShowSplash);
		\
	}
	// 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
	
	{
		CString mutexstr;
		mutexstr.LoadString(AFX_IDS_APP_TITLE);
		CreateMutex(NULL,TRUE,mutexstr);
		if(ERROR_ALREADY_EXISTS==GetLastError())
		{	
			MessageBox(NULL,"Another Instance of this Application is Currently Running","Error...",MB_OK);
			exit(1);
		}	
	}
	
	__try
	{
		// 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("MechWarrior4 Mission Editor"));
		
		
		// Turn off the screen saver
		SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0,&g_ScreenSaverFlag,FALSE);
		SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,FALSE,NULL,FALSE);
		
		
		// To create the main window, this code creates a new frame window
		// object and then sets it as the application's main window object.
		
		m_ScriptName = "";
		CMDIFrameWnd* pFrame = new CMainFrame;
		m_pMainWnd = pFrame;
		
		// create main MDI frame window
		if (!pFrame->LoadFrame(IDR_MAINFRAME))
			return FALSE;
			/*
			CTitleWnd* m_TitleWnd = new CTitleWnd;
			m_TitleWnd->Invalidate();
		*/
		// 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_MW4GAMTYPE));
		m_hMDIAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MW4GAMTYPE));
		
		// Enable and disable the tools menu items instead of the root menu
		//		CMenu* m = theApp.m_pMainWnd->GetMenu();
		//		m->EnableMenuItem(3,MF_GRAYED | MF_BYPOSITION);
		
		displayWindow = new CDisplayWindow;
		ASSERT(displayWindow != NULL);
		
		overviewWindow = new COverviewWindow;
		ASSERT(overviewWindow != NULL);
		
		InitGameOS(m_hInstance,displayWindow->m_hWnd,m_lpCmdLine);
		
		_getcwd(Working_Directory, 128);
		
		resourceWindow = new CResourceWindow;
		ASSERT(resourceWindow != NULL);
		
		instanceWindow = new CInstanceWindow;
		ASSERT(instanceWindow != NULL);
		
		gridOn = false;
		gridValue = 15;
		
		m_MultiDrop = true;
		
		// The main window has been initialized, so show and update it.
		pFrame->ShowWindow(m_nCmdShow);
		pFrame->UpdateWindow();
		toolBar->EnableButton(ID_EDIT_UNDO,FALSE);
		toolBar->EnableButton(ID_FILE_SAVE,FALSE);
		
		OnToolsCameraheightMechheight10m();
		OnToolsCameraspeedRegular();
		
		LoadWindowStates();
		m_editorState = NoGameIdleState;
		CSelectionList::Instance = new CSelectionList();
		currentCommand = NULL;
		displayWindow->timer = displayWindow->SetTimer(1, 100, NULL);
		
		char Path[MAX_PATH];
		strcpy(Path,"Content\\Editor\\bMech.ani");
		//		theApp.m_WaitCursor = LoadCursorFromFile(Path);
		
		FILE* file;
		if ((file = fopen("Content\\Editor\\Autotrack.data","r")) == NULL)
		{
			nextDamageFileID = 0;
			nextSubsystemFileID = 0;
		}
		else
		{
			char buffer[32];
			
			fgets(buffer,31,file);
			nextDamageFileID = atoi(buffer);
			fgets(buffer,31,file);
			nextSubsystemFileID = atoi(buffer);
			fclose(file);
		}
		
		extern bool g_MMInitialized;
		g_MMInitialized = 0;
		//		delete m_TitleWnd;
		g_MMInitialized = 1;
	}
	__except(ProcessException(GetExceptionInformation()))
	{
	}
	
	ElementRenderer::Element::UseCallbackSet(ElementRenderer::Element::Callbacks);
	
	sprintf(m_title,"MechWarrior4 Mission Editor - Version: %s - []",VER_PRODUCTVERSION_STR);
	m_pMainWnd->SetWindowText(m_title);
	
	m_AllLoaded = true;
	
	// CG: This line inserted by 'Tip of the Day' component.
	ShowTipAtStartup();
	//	Compost::TerrainTextureLogistic::SetResolution(0);
	return TRUE;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CMW4GameEdApp message handlers

int CMW4GameEdApp::ExitInstance()
{
	
	if (lightDlg)
	{
		Unregister_Pointer(lightDlg);
		delete lightDlg;
		lightDlg = NULL;
	}
	if (fogDlg)
	{
		Unregister_Pointer(fogDlg);
		delete fogDlg;
		fogDlg = NULL;
	}
	
	m_ExtraDataList.SetLength(0);
	missionBoundary.SetLength(0);
	warningBoundary.SetLength(0);
	if(!undoChain.IsEmpty())
	{
		ChainIteratorOf<Command *> iterator(&undoChain);
		iterator.DeletePlugs();
	}
	
	
	if(!dirtyGameModelResources.IsEmpty())
	{
		ChainIteratorOf<PlugOf<Resource*>*> iterator(&dirtyGameModelResources);
		iterator.DeletePlugs();
	}
	
	//	if (m_WaitCursor)
	//		DestroyCursor(m_WaitCursor);
	
	TerminateGameEngine();
	
	
	// turn Screen saver back on
	SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,g_ScreenSaverFlag,NULL,FALSE);
	
	return CWinApp::ExitInstance();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnFileNew()
{
	StopMultiPlace();
	
	CNewMissionDlg	dlg;
	dlg.DoModal();
}

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

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
	
	// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	CStatic	m_VersionString;
	//}}AFX_DATA
	
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
public:
	virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult);
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	virtual BOOL OnInitDialog();
	//}}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)
	DDX_Control(pDX, IDC_ABOUTVERSIONSTRING, m_VersionString);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

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

extern bool Immediate_Draw;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall InitializeGameEngine()
{
	//
	//---------------------
	// Initialize libraries
	//---------------------
	//
	Stuff::ArmorLevel = 4;
	
	//	client=gos_CreateMemoryHeap("MFCHeap");
	//	gos_PushCurrentHeap(client);
	
	Stuff::InitializeClasses();
	MidLevelRenderer::InitializeClasses(NULL, 8192*16);
	Compost::InitializeClasses();
	gosFX::InitializeClasses();
	ElementRenderer::InitializeClasses();
	Adept::InitializeClasses();
	Map::LoadRadius = 8;
	MechWarrior4::InitializeClasses();
	MW4GameEdApplication::InitializeClass();
	EditorWaypoint::InitializeClass();
	EditorLatticeNode::InitializeClass();
	EditorPathNode::InitializeClass();
	EditorBoundaryNode::InitializeClass();
	EditorDropNode::InitializeClass();
	EditorDropZonePoint::InitializeClass();
	EditorObjectiveMarker::InitializeClass();
	EditorMovementPath::InitializeClass();
	EditorLight::InitializeClass();
	EditorAmbientLight::InitializeClass();
	EditorInfiniteLight::InitializeClass();
	EditorPointLight::InitializeClass();
	EditorSpotLight::InitializeClass();
	EditorCameraShip::InitializeClass();
	//
	//----------------------------------------------------------
	// Parse command line and verify that game name has been set
	//----------------------------------------------------------
	//
	Immediate_Draw=false;
	
	//
	//------------------------------------------------
	// If no path is provided, set the path to Content
	//------------------------------------------------
	//
	
#ifdef _DEBUG
#undef new
#endif
	
	
	MString game_name;
	MString game_file_name;
	
	
	
	Tool::Instance = new MWTool();
	Check_Object(Tool::Instance);
	MW4GameEdApplication *MW4GameEd_Application = new MW4GameEdApplication;
	Check_Object(MW4GameEd_Application);
	Adept::Application::Instance = MW4GameEd_Application;
	MW4GameEd_Application->Initialize();
	
	
	// Let's do a resource check so we can handle anomolies in a friendly way.
	
	//	MW4GameEd_Application->OpenResources(false, true);
	//	MW4GameEd_Application->BuildEffectsLibrary("Content\\Effects\\mw.effects");
	SetCurrentDirectory(Working_Directory);
	Stuff::NotationFile build_script("Content\\MechWarrior4.build");
	FileDependencies deps;
	gos_PushCurrentHeap(gosFX::Heap);
	gosFX::EffectLibrary::Instance = new ResourceEffectLibrary;
	gos_PopCurrentHeap();
	Tool::Instance->BuildResources(&build_script, VER_CONTENTVERSION, &deps);
	delete gosFX::EffectLibrary::Instance;
	Verify(!gosFX::EffectLibrary::Instance = NULL);
	
	Verify(!Network::Instance);
	Network::Instance = new Network;
	Check_Object(Network::Instance);
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall TerminateGameEngine()
{
	Check_Pointer(FileStreamManager::Instance);
	FileStreamManager::Instance->PurgeFileCompareCache();
	
	Check_Object(Adept::Application::Instance);
	Adept::Application::Instance->StopGame();
	//	Adept::Application::Instance->CloseGame();
	Adept::Application::Instance->Terminate();
	Check_Object(Adept::Application::Instance);
	delete Adept::Application::Instance;
	Adept::Application::Instance = NULL;
	
	//
	//------------------------------------------------------
	// If we are shutting down a tool run, kill off the tool
	//------------------------------------------------------
	//
	if (Tool::Instance)
	{
		Check_Object(Tool::Instance);
		delete Tool::Instance;
	}
	
	EditorCameraShip::TerminateClass();
	EditorSpotLight::TerminateClass();
	EditorPointLight::TerminateClass();
	EditorInfiniteLight::TerminateClass();
	EditorAmbientLight::TerminateClass();
	EditorLight::TerminateClass();
	EditorMovementPath::TerminateClass();
	EditorObjectiveMarker::TerminateClass();
	EditorDropZonePoint::TerminateClass();
	EditorDropNode::TerminateClass();
	EditorBoundaryNode::TerminateClass();
	EditorPathNode::TerminateClass();
	EditorLatticeNode::TerminateClass();
	EditorWaypoint::TerminateClass();
	
	MW4GameEdApplication::TerminateClass();
	MechWarrior4::TerminateClasses();
	Adept::TerminateClasses();
	ElementRenderer::TerminateClasses();
	gosFX::TerminateClasses();
	MidLevelRenderer::TerminateClasses();
	Stuff::TerminateClasses();
	
	//	gos_PopCurrentHeap();
	//	gos_DestroyMemoryHeap(client);
	ExitGameOS();
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Setup the GameOS structure
//
void __stdcall GetGameOSEnvironment(char* CommandLine)
{
	Command_Line = CommandLine;
	
	Environment.applicationName			= "MW4GameEd";
	Environment.directoryPath			= "code\\MW4GameEd;Binaries\\MW4";
	Environment.screenWidth				= 640;
	Environment.screenHeight			= 480;
	Environment.fullScreen				= FALSE;
	Environment.bitDepth				= 16;
	Environment.debugLog				= "DebugLog.txt";
	Environment.spew					= "GameOS_Memory"; //GROUP_ADEPT_RESOURCE;
	Environment.memoryTraceLevel		= 10;
	Environment.TimeStampSpew			= false;
	Environment.DoGameLogic				= &MWApplication::DoGameLogic;
	Environment.UpdateRenderers			= &Application::UpdateDisplay;
	Environment.InitializeGameEngine		= InitializeGameEngine;
	Environment.TerminateGameEngine		= TerminateGameEngine;
	
	Environment.Key_FullScreen			= 0;
	Environment.Key_SwitchMonitors		= 0; //KEY_F5;
	Environment.Key_Exit				= 0;
	
	Environment.Renderer				= 0;
	Environment.FullScreenDevice		= 0;
	
	Environment.AntiAlias				= 0;			// true/false - Enable full screen antialiasing
	Environment.NetworkGame				= false;
	Environment.NetworkMaxPlayers		= 2;
	
	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;
	
	Environment.soundChannels			= 32;
	Environment.soundDisable			= true;
	Environment.soundHiFi				= false;
	
	Environment.MaxTimeDelta = 0.25f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnToggleOverviewWindow()
{
	
	if (overviewWindow)
		overviewWindow->ToggleVisible();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnToggleResourceWindow()
{
	if (resourceWindow)
		resourceWindow->ToggleVisible();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnViewDisplaywindow()
{
	if (displayWindow)
		displayWindow->ToggleVisible();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnViewInstancewindow()
{
	if (instanceWindow)
		instanceWindow->ToggleVisible();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BOOL CMW4GameEdApp::OnIdle(LONG lCount)
{
	
	__try
	{
		if (theApp.m_editorState != CMW4GameEdApp::NoGameIdleState)
		{
			if(RunGameOSLogic())
				PostQuitMessage(0);
		}
	}
	__except(ProcessException(GetExceptionInformation()))
	{}
	
	didIdle = true;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BOOL CAboutDlg::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CDialog::OnChildNotify(message, wParam, lParam, pLResult);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BOOL CAboutDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CDialog::OnNotify(wParam, lParam, pResult);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnEditUndo()
{
	StopMultiPlace();
	//We need to undo the last thing on the chain!
	if(!undoChain.IsEmpty())
	{
		ChainIteratorOf<Command *>iterator(&undoChain);
		iterator.Last();
		Command *command;
		command = iterator.GetCurrent();
		command->Undo();
		
		undoChain.Remove(command);
		Check_Object(command);
		delete command;
	}
	if(undoChain.IsEmpty())
	{
		theApp.toolBar->EnableButton(ID_EDIT_UNDO, FALSE);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool CMW4GameEdApp::CreateNewScenario(char* missionName, char* mapPath, char* skyPath)
{
	CString missionInstance;
	CString missionPath = "Content\\Missions\\";
	missionPath += missionName;
	
	CString map_name=mapPath;
	map_name=map_name.Left(map_name.ReverseFind('.'));
	map_name=map_name.Mid(map_name.ReverseFind('\\')+1);
	
	AddToBuildFile(missionName,map_name);
	
	CString srcablname,destablname;
	missionPath += "\\";
	destablname = missionPath;
	destablname += "player.abl";
	missionPath += missionName;
	missionInstance = missionPath + ".instance";
	
	
	srcablname = "content\\ablscripts\\player.abl";
	if (CopyFile (srcablname,destablname,FALSE) == 0)
	{
		MessageBox (NULL,"Failed to create default player.abl file.  You will need to create your own for this mission","New Mission Error",MB_OK);
	}
	
	
	lightFileName = missionPath;
	lightFileName += ".Lights";
	
	audioFileName = missionPath;
	audioFileName += ".audio";
	
	CloseHandle(CreateFile(LPCTSTR(lightFileName),0,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL));
	CloseHandle(CreateFile(LPCTSTR(audioFileName),0,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL));
	
	//  m_ExtraDataList.SetLength(0); // Tom: should this be cleared too?
	missionBoundary.SetLength(0);
	warningBoundary.SetLength(0);
	
	CreateMissionInstanceFile(missionInstance.GetBuffer(MAX_PATH),mapPath,skyPath,true);
	
	CString missionData = missionPath + ".data";
	SaveMissionDataFile(missionData.GetBuffer(MAX_PATH));
	
	////////////////////////////////////////////////////////////
	//	Make the mission contents file
	
	CString contentData = missionPath + ".contents";
	
	{
		NotationFile contentFile;
		contentFile.SaveAs(contentData.GetBuffer(MAX_PATH));
	}
	
	////////////////////////////////////////////////////////////
	//	Make the mission audio file
	//
	// Leave empty for now
	//
	//CString audioData = missionPath + ".audio";
	//	
	//	{
	//    NotationFile audioFile;
	//		audioFile.AddPage("Audio");
	//		audioFile.SaveAs(audioData.GetBuffer(MAX_PATH));
	//	}
	
	/*
	Resource instanceResource(missionInstance);
	ReplicatorID baseID = ReplicatorID::Null;
	DynamicMemoryStream instanceStream;
	Check_Object(Tool::Instance);
	Tool::Instance->ConstructCreateMessage(
	&instanceStream,
	missionInstance,
	&baseID
	);
	instanceResource.Save(&instanceStream,NULL);
	
	  MissionNamePlug* newMissionName = new MissionNamePlug;
	  newMissionName->name = new char[strlen(missionName) + 1];
	  strcpy(newMissionName->name,missionName);
	*/
	//	CreateMissionResource(missionInstance.GetBuffer(MAX_PATH));
	
	////////////////////////////////////////////////////////////
	//	Make the mission movement graph
	
	return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::CreateMissionResource(char* missionInstance)
{
	Resource instance_resource(missionInstance);
	//	ReplicatorID baseID = ReplicatorID::Null;
	DynamicMemoryStream instance_stream;
	//	Check_Object(Tool::Instance);
	NotationFile instance_file(missionInstance);
	FileDependencies *parent = Resource::ParentFileDependencies;
	FileDependencies instance_deps(*instance_file.GetFileDependencies());
	Resource::ParentFileDependencies = &instance_deps;
	Check_Object(Mission::Instance);
	Mission::Instance->SaveMakeMessage(&instance_stream, NULL);
	//	Tool::Instance->ConstructCreateMessage(
	//		&instanceStream,
	//		&instance_file,
	//		&baseID
	//	);
	instance_resource.Save(&instance_stream, &instance_deps);
	
	char missionName[MAX_PATH],tmp[MAX_PATH];
	_splitpath(missionInstance,tmp,tmp,missionName,tmp);
	
	MissionNamePlug* newMissionName = new MissionNamePlug;
	newMissionName->name = new char[strlen(missionName) + 1];
	strcpy(newMissionName->name,missionName);
	Resource::ParentFileDependencies = parent;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool CMW4GameEdApp::CreateMissionInstanceFile(char* missionPath, char* mapPath, char* skyPath, bool create_new)
{
	char missionName[MAX_PATH],tmpString[MAX_PATH],tmpString2[MAX_PATH],tmpString3[MAX_PATH],tmpString4[MAX_PATH],tmpString5[MAX_PATH],*p;
	
	if (!TestFileWrite(missionPath))
		return false;
	
	_splitpath(missionPath,tmpString,tmpString,missionName,tmpString);
	
	NotationFile missionFile;
	Page *mission_page = missionFile.AddPage(missionName);
	Check_Object(mission_page);
	
	sprintf(tmpString,"%s.data",missionName);
	mission_page->AppendEntry("Model",tmpString);
	mission_page->AppendEntry("Map",strstr(mapPath,"Maps"));
	sprintf(tmpString,"%s.contents",missionName);
	mission_page->AppendEntry("Props",tmpString);
	mission_page->AppendEntry("ExecutionState","AlwaysExecuteState");
	
	mission_page->AppendEntry("MissionBounds","Mission.bounds");
	mission_page->AppendEntry("WarningBounds","Warning.bounds");
	
	
	FileStream bnds;
	CString mpath,str;
	mpath=missionPath;
	mpath=mpath.Left(mpath.ReverseFind('\\'));
	
	int i;
	if(Map::Instance)
	{
		for (i = 0; i < theApp.missionBoundary.GetLength(); i++)
		{
			theApp.missionBoundary[i].x+=theApp.overviewWindow->mapWidth*0.5f;
			theApp.missionBoundary[i].y+=theApp.overviewWindow->mapHeight*0.5f;
			theApp.missionBoundary[i].x *= Map::Instance->GetColumnZoneScale();
			theApp.missionBoundary[i].y *= Map::Instance->GetRowZoneScale();
		}
		
		for ( i = 0; i < theApp.warningBoundary.GetLength(); i++)
		{
			Vector2DOf<Scalar> origin;
			theApp.warningBoundary[i].x+=theApp.overviewWindow->mapWidth*0.5f;
			theApp.warningBoundary[i].y+=theApp.overviewWindow->mapHeight*0.5f;
			theApp.warningBoundary[i].x *= Map::Instance->GetColumnZoneScale();
			theApp.warningBoundary[i].y *= Map::Instance->GetRowZoneScale();
	}
		
		Mission::Instance->SetMissionPolygon(theApp.missionBoundary);
		Mission::Instance->SetWarningPolygon(theApp.warningBoundary);
	}
	
	str.Format("%s\\Mission.bounds",mpath);
	bnds.Open((LPCSTR)str,FileStream::WriteOnly);
	MemoryStreamIO_Write(&bnds, &theApp.missionBoundary);
	bnds.Close();
	
	str.Format("%s\\Warning.bounds",mpath);
	bnds.Open((LPCSTR)str,FileStream::WriteOnly);
	MemoryStreamIO_Write(&bnds, &theApp.warningBoundary);
	bnds.Close();
	
	if(Map::Instance)
	{
		for (i = 0; i < theApp.missionBoundary.GetLength(); i++)
		{
			theApp.missionBoundary[i].x /= Map::Instance->GetColumnZoneScale();
			theApp.missionBoundary[i].y /= Map::Instance->GetRowZoneScale();
			theApp.missionBoundary[i].x-=theApp.overviewWindow->mapWidth*0.5f;
			theApp.missionBoundary[i].y-=theApp.overviewWindow->mapHeight*0.5f;
		}
		
		for ( i = 0; i < theApp.warningBoundary.GetLength(); i++)
		{
			theApp.warningBoundary[i].x /= Map::Instance->GetColumnZoneScale();
			theApp.warningBoundary[i].y /= Map::Instance->GetRowZoneScale();
			theApp.warningBoundary[i].x-=theApp.overviewWindow->mapWidth*0.5f;
			theApp.warningBoundary[i].y-=theApp.overviewWindow->mapHeight*0.5f;
		}
	}
	
	
	
	char tmpPath[MAX_PATH],tmpName[MAX_PATH];
	strcpy(tmpPath,missionPath);
	
	if (!m_ScriptName.IsEmpty ())
	{
		mission_page->AppendEntry("Script",(LPCTSTR) m_ScriptName);
	}
	
	CString table_name=missionName;
	table_name+=".table";
	mission_page->AppendEntry("NameTable",(char *)(LPCSTR)table_name);
	
	if(create_new)
	{
		// create empty nametable file so we can load
		CString table_path;
		table_path.Format("Content\\Missions\\%s\\%s",missionName,table_name);
		FILE* newfile = fopen((LPCSTR)table_path,"w");
		ASSERT(newfile != NULL);
		fclose(newfile);
	}
	
	p = __mbsrchr(tmpPath,'\\');
	p++;
	*p = 0;
	strcpy(tmpString,tmpPath);
	p = strstr(tmpString,"mission");
	if (p)
	{
		*p = 0;
		p = __mbsrchr(tmpString,'\\');
		p++;
		sprintf(tmpString2,"%s%sGraph.data",tmpPath,p);
		sprintf(tmpString3,"%s%sMoveGrid.data",tmpPath,p);
		sprintf(tmpString4,"%s%sRectGrid.data",tmpPath,p);
		sprintf(tmpString5,"%s%sAirMoveGrid.data",tmpPath,p);
	}
	else
	{
		p = __mbsrchr(tmpPath,'\\');
		*p = 0;
		p = __mbsrchr(tmpPath,'\\');
		p++;
		strcpy(tmpName,p);
		sprintf(tmpString2,"%s%sGraph.data",tmpString,tmpName);
		sprintf(tmpString3,"%s%sMoveGrid.data",tmpString,tmpName);
		sprintf(tmpString4,"%s%sRectGrid.data",tmpString,tmpName);
		sprintf(tmpString5,"%s%sAirMoveGrid.data",tmpString,tmpName);
		p = NULL;
	}
	m_graphName = tmpString2;
	m_moveGridName = tmpString3;
	m_rectGridName = tmpString4;
	m_airMoveGridName = tmpString5;
	mission_page->AppendEntry("RailGraph",m_graphName);
	
	strcpy(tmpPath,tmpString2);
	p = strstr(tmpPath,"Graph");
	*p = 0;
	
	_finddata_t fileData;
	if (_findfirst(m_graphName,&fileData) == -1)	// create missiongraph file.
	{	
		int i = 0;
		
		NotationFile graphFile;
		Page *graph_page = graphFile.AddPage("Graph");
		Check_Object(graph_page);
		graph_page->AppendEntry("NumNodes",i);
		graph_page->AppendEntry("NumLinks",i);
		graphFile.SaveAs((LPCTSTR)m_graphName);
	}
	
	if (skyPath && strlen(skyPath))
	{
		p = strstr(skyPath,"Content");
		if (!p)				// Did they put the erf in the wrong place?  Handle it.
			p = skyPath;
		mission_page->AppendEntry("Sky",p);
	}
	
	missionFile.SaveAs(missionPath);
	return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnAdjustGrid()
{
	CGenericTextDlg dlg;
	char string[64];
	
	dlg.m_Title = "Construction Grid Resolution";
	dlg.m_MessageText = "Enter the grid size for the construction grid";
	dlg.m_EditText = itoa(theApp.gridValue,string,10);
	dlg.addStyle = ES_NUMBER;
	
	dlg.editRect.left = 10;
	dlg.editRect.right = 60;
	
	if (dlg.DoModal() == IDOK)
	{
		int val = atoi(dlg.m_EditText);
		
		if (val < 1)
			MessageBox(NULL,"Invalid entry","Error",MB_ICONSTOP);
		else if (theApp.gridValue != val)
		{
			theApp.gridValue = val;
			((CMainFrame*)(theApp.m_pMainWnd))->DestroyGridData();
			if (theApp.gridOn)
				((CMainFrame*)(theApp.m_pMainWnd))->CreateGridData();
		}
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int CMW4GameEdApp::Run()
{
	__try
	{
		return CWinApp::Run();
		
	}
	__except(ProcessException(GetExceptionInformation()))
	{
	}
	return 0;
}	
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnFileOpen()
{
	StopMultiPlace();
	SetCurrentDirectory(Working_Directory);
	CFileDlg dlg;
	if (dlg.DoModal() == IDOK)
	{
		CSelectionList::Instance->ClearSelectionList();
		
		if (theApp.m_editorState != CMW4GameEdApp::NoGameIdleState)
		{
			OnFileClose();
		}
		OpenFile(dlg.GetPathName());
	}	
}

void CMW4GameEdApp::OpenFile(char* filename)
{
	//	SetCursor(theApp.m_WaitCursor);
	
	RECT rect;
	int w = 280, h = 130;
	
	theApp.m_pMainWnd->GetWindowRect(&rect);
	CMsgDlg msgDlg("Loading...","Arial",240,theApp.m_pMainWnd,
		(rect.right - rect.left) / 2 + rect.left - w / 2,(rect.bottom - rect.top) / 2 + rect.top - h / 2,w,h);
	msgDlg.ShowWindow(SW_SHOW);
	msgDlg.UpdateWindow();
	
	
	Check_Object(ResourceManager::Instance);
	delete ResourceManager::Instance;
	ResourceManager::Instance = new ResourceManager;
	Check_Object(ResourceManager::Instance);
	
	if(gosFX::EffectLibrary::Instance)
	{
		delete gosFX::EffectLibrary::Instance;
		Verify(!gosFX::EffectLibrary::Instance);
	}
	gos_PushCurrentHeap(gosFX::Heap);
	gosFX::EffectLibrary::Instance = new ResourceEffectLibrary;
	gos_PopCurrentHeap();
	SetCurrentDirectory(Working_Directory);
	Stuff::NotationFile build_script("Content\\MechWarrior4.build");
	FileDependencies deps;
	Tool::Instance->BuildResources(&build_script, VER_CONTENTVERSION, &deps);
	delete gosFX::EffectLibrary::Instance;
	Verify(!gosFX::EffectLibrary::Instance);
	
	Check_Object(Application::Instance);
	missionFileName = filename;
	const char *game_name;
	if((game_name = strstr(missionFileName.GetBuffer(MAX_PATH), "Content")) != NULL)
	{
		memmove((void*)(LPCTSTR(missionFileName)),game_name,strlen(game_name) + 1);
		//
		//----------------------------------------------------------
		// Go ahead and put the load mission message into the stream
		//----------------------------------------------------------
		//
#ifdef _DEBUG
#undef new
#endif
		
		//
		//----------------------------------------------------------
		// Request our mech
		//----------------------------------------------------------
		//
		DynamicMemoryStream request_vehicle_stream;
		
		//
		//------------------------------------------------------------------------
		// Open up the resource files we are going to need to construct the player
		// message
		//------------------------------------------------------------------------
		//
		
		{
			
		

			bool custom = false;
			request_vehicle_stream.WriteBytes(&custom, 1);
			int file_id = 0;
			int record_id = 0;
			request_vehicle_stream.WriteBytes(&file_id,   4);
			request_vehicle_stream.WriteBytes(&record_id, 4);




		}
		
		//
		//----------------------------------------
		// Now, create the message for the mission
		//----------------------------------------
		//
		
		MWApplication::Instance->SetMissionName(missionFileName);
		
		
		//
		//-------------------------------------------------------------
		// We've requested our mech so we are ready
		// right now there is no double checking on the mech
		// status.  In the future we will send this and
		// wait for a reply before we send a ready message
		//-------------------------------------------------------------
		//
		
		request_vehicle_stream.Rewind();
		

		MWApplication::Instance->RequestPlayerVehicleMessageHandler(Connection::Server->GetID(), &request_vehicle_stream);
		MWApplication::Instance->ReadyToLaunchMessageHandler(Connection::Server->GetID(), NULL);
		

		// request our mech...
		//Network::Instance->SendNetMessage(Connection::Server->GetID(), MWApplication::RequestPlayerVehicleMessageID, &request_vehicle_stream, true);
		
		// technically we should wait for the server to accept our mech, but for right now it doesn't check anyway so
		// we just launch it...
		//Network::Instance->SendNetMessage(Connection::Server->GetID(), MWApplication::ReadyToLaunchMessageID, NULL, true);
		
		
		//
		//----------------------------------------
		// Time to launch the game
		//----------------------------------------
		//
		MWApplication::Instance->LaunchGame();
		


		RouteLocalPacketsTask route_task;
		while (Network::Instance->RouteLocalPacket())
		{
		}

		
		m_editorState = SelectingObjectState;
		Check_Object(EntityManager::Instance);
		EntityManager::Instance->SuspendExecution();
		
		Check_Object(Map::Instance);
		ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
		Entity* entity;
		
		CString game_base_path(game_name),contents_path;
		game_base_path=game_base_path.Left(game_base_path.ReverseFind('.'));
		contents_path=game_base_path+".contents";
		Stuff::NotationFile contentsfile((LPCSTR)contents_path);
		
		while((entity = iterator.ReadAndNext()) != NULL)
		{
			if (entity->IsDerivedFrom(NavPoint::DefaultData))
			{
				NavPoint*node = Cast_Object(NavPoint*,entity);
				node->SetToDisplay();
				
			}
			
			if(entity->GetPropType() == Entity::MapPropType)
			{
				EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
				theApp.resourceWindow->numEntitiesAdded++;
				Page *page = contentsfile.FindPage((char*)entity->instanceName);
				if(page)
				{
					CEditorEntityData *exdata=theApp.GetEntityData(entity);
					page->GetEntry("EDVOffset",&(exdata->VOffset));
				}
			}
		}
	}
	else
	{
		STOP(("You are not giving a game file in a correct content location"));
	}
	CString str,tmps;
	str="MechWarrior 4 Editor Version - ";
	tmps=VER_PRODUCTVERSION_STR;
	str+=tmps;
	m_pMainWnd->SetWindowText(str);
	MakeObjectsTileBased();
	NameTable::Instance->IsValid();
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnUpdateViewOverviewwindow(CCmdUI* pCmdUI)
{
	if (overviewWindow)
		pCmdUI->SetCheck(overviewWindow->IsWindowVisible());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnUpdateViewResourcewindow(CCmdUI* pCmdUI)
{
	if (resourceWindow)
		pCmdUI->SetCheck(resourceWindow->IsWindowVisible());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnUpdateViewDisplaywindow(CCmdUI* pCmdUI)
{
	if (displayWindow)
		pCmdUI->SetCheck(displayWindow->IsWindowVisible());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnUpdateViewInstancewindow(CCmdUI* pCmdUI)
{
	if (instanceWindow)
		pCmdUI->SetCheck(instanceWindow->IsWindowVisible());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::SaveWindowStates()
{
	CString keyname;
	keyname = "MUGEMainWnd_Placement";
	WINDOWPLACEMENT wp;
	theApp.m_pMainWnd->GetWindowPlacement(&wp);
	gos_SaveDataToRegistry((char *)(LPCSTR)keyname,&wp,sizeof(wp));
	
	displayWindow->SaveState();
	overviewWindow->SaveState();
	resourceWindow->SaveState();
	instanceWindow->SaveState();
	
	keyname = "MUGEBackupStatus";
	gos_SaveDataToRegistry((char *)(LPCSTR)keyname,&m_AutoBackupOnSave,sizeof(m_AutoBackupOnSave));
	
	keyname = "MUGECameraSpeed";
	gos_SaveDataToRegistry((char *)(LPCSTR)keyname,&cameraSpeed,sizeof(cameraSpeed));
	
	keyname = "MUGECameraFollowing";
	gos_SaveDataToRegistry((char *)(LPCSTR)keyname,&cameraFollowing,sizeof(cameraFollowing));
	
	keyname = "MUGECameraBookmarks";
	gos_SaveDataToRegistry((char *)(LPCSTR)keyname,&m_4DCameraBookmark,sizeof(m_4DCameraBookmark));
	
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::LoadWindowStates()
{
	CString keyname;
	keyname = "MUGEMainWnd_Placement";
	
	WINDOWPLACEMENT wp;
	DWORD size=sizeof(wp);
	gos_LoadDataFromRegistry((char *)(LPCSTR)keyname,&wp,&size);
	if (size == sizeof(wp))
	{
		theApp.m_pMainWnd->SetWindowPlacement(&wp);
	}
	
	displayWindow->LoadState();
	overviewWindow->LoadState();
	resourceWindow->LoadState();
	instanceWindow->LoadState();
	
	RECT r;
	displayWindow->GetClientRect(&r);
	if (r.right < 790)
		OnViewResize640();
	else if (r.right < 1142)
		OnViewResize800();
	else if (r.right < 1270)
		OnViewResize1152();
	else if (r.right < 1590)
		OnViewResize1280();
	else
		OnViewResize1600();
	
	keyname = "MUGEBackupStatus";
	size=sizeof(m_AutoBackupOnSave);
	gos_LoadDataFromRegistry((char *)(LPCSTR)keyname,&m_AutoBackupOnSave,&size);
	
	keyname = "MUGECameraSpeed";
	size=sizeof(cameraSpeed);
	gos_LoadDataFromRegistry((char *)(LPCSTR)keyname,&cameraSpeed,&size);
	
	keyname = "MUGECameraFollowing";
	size=sizeof(cameraFollowing);
	gos_LoadDataFromRegistry((char *)(LPCSTR)keyname,&cameraFollowing,&size);
	
	keyname = "MUGECameraBookmarks";
	size=sizeof(cameraFollowing);
	gos_LoadDataFromRegistry((char *)(LPCSTR)keyname,&m_4DCameraBookmark,&size);
	
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void RecursiveCopy(char* srcDir, char* destDir, char* oldName, char* newName)
{
	WIN32_FIND_DATA filedata;
	HANDLE handle;
	char oldFolder[MAX_PATH],tmp1[MAX_PATH],tmp2[MAX_PATH],newFilename[MAX_PATH],*p;
	
	GetCurrentDirectory(MAX_PATH - 1,oldFolder);
	CreateDirectory(destDir,NULL);
	SetCurrentDirectory(srcDir);
	
	handle = FindFirstFile("*.*",&filedata);
	
	do
	{
		if (!strcmp(filedata.cFileName,".") || !strcmp(filedata.cFileName,".."))
			continue;
		
		if (filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			char recurseDest[MAX_PATH];
			sprintf(recurseDest,"%s\\%s",destDir,filedata.cFileName);
			RecursiveCopy(filedata.cFileName,recurseDest,oldName,newName);
		}
		
		strcpy(tmp1,filedata.cFileName);
		p = strstr(strlwr(tmp1),strlwr(oldName));
		
		if (p)
		{
			*p = 0;
			p += strlen(oldName);
			sprintf(tmp2,"%s%s%s",tmp1,newName,p);
		}
		else
		{
			strcpy(tmp2,filedata.cFileName);
		}
		
		sprintf(newFilename,"%s\\%s",destDir,tmp2);
		CopyFile(filedata.cFileName,newFilename,FALSE);
		if (filedata.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
			SetFileAttributes(newFilename,filedata.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
		
		// let's replace any occurances of the mission name inside the file
		p = strrchr(newFilename,'.') + 1;
		if (strcmp(strlwr(p),"data") == 0 ||	// make sure it's a notation file we want to edit
			strcmp(strlwr(p),"instance") == 0)
		{
			NotationFile notFile(newFilename);
			
			NotationFile::PageIterator *pageList = notFile.MakePageIterator();
			Check_Object(pageList);
			Page *page;
			
			while ((page = pageList->ReadAndNext()) != NULL)
			{
				Check_Object(page);
				Page::NoteIterator *entryList = page->MakeNoteIterator();
				Check_Object(entryList);
				//				PAUSE(("Not alphabetized..."));
				//				entryList = notFile.MakeAlphaEntryList(page->GetName());
				
				Note *entry;
				
				while ((entry = entryList->ReadAndNext()) != NULL)
				{
					const char* entryString;
					entry->GetEntry(&entryString);
					//
					// There seem to be some empty entry strings in the mission that break this
					//
					if (entryString)
					{
						p = strstr(strlwr((char*)entryString),strlwr(oldName));
						
						if (p)
						{
							char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
							
							_splitpath(entryString,drive,dir,fname,ext);
							
							if (strlen(dir) == 0)				// no path we need to change the filename
							{
								*p = 0;
								p += strlen(oldName);
								sprintf(tmp2,"%s%s%s",entryString,newName,p);
								entry->SetEntry(tmp2);
							}
							else if (strstr(dir,"missions"))		// have to change the path too
							{
								*p = 0;
								p += strlen(oldName) * 2 + 1;	// major hack!!!  should be very temporary
								sprintf(tmp2,"%s%s\\%s%s",entryString,newName,newName,p);
								entry->SetEntry(tmp2);
							}
						} // if (p)
					} // if (entryString)
				}  // while
				Check_Object(entryList);
				delete entryList;
			}
			
			Check_Object(pageList);
			delete pageList;
			notFile.Save();
		}
	}
	while (FindNextFile(handle,&filedata));
	
	SetCurrentDirectory(oldFolder);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::OnFileSaveAs()
{
	StopMultiPlace();
	RemoveCulturals();
	
	if (!m_MissionSaved)
	{
		if (MessageBox(NULL,"Mission has not been saved.  Save now?","Unsaved Data",MB_YESNO) == IDYES)	// localize
		{
			OnFileSave();
		}
	}
	
Start_Save_As:;
			  
			  CGenericTextDlg dlg;
			  
			  dlg.m_Title = "Save As";
			  dlg.m_MessageText = "Enter the new name of the mission";
			  dlg.m_EditText = "";
			  
			  if (dlg.DoModal() == IDCANCEL)
				  return;
			  
			  CString mres,mis_name;
			  mis_name=dlg.m_EditText;
			  mres.Format("Content\\Resources\\Missions\\%s.mw4",dlg.m_EditText);
			  if(gos_DoesFileExist(mres))
			  {
				  MessageBox(NULL,"A mission with that name already exists. Please rename the mission.","Save As Error",MB_OK);	// Localize
				  goto Start_Save_As;
			  }
			  
			  char newMissionPath[MAX_PATH],oldMissionName[MAX_PATH];
			  const char* mapPath, *cskyPath;
			  
			  _splitpath(missionFileName,newMissionPath,newMissionPath,oldMissionName,newMissionPath);
			  sprintf(newMissionPath,"Content\\Missions\\%s",dlg.m_EditText);
			  
			  if (_mkdir(newMissionPath) != 0)
			  {
				  MessageBox(NULL,"Unable to create new folder","Save Error",MB_OK);	// Localize
				  return;
			  }
			  
			  
			  // Copy over everything
			  char tmpPath[MAX_PATH],oldFolder[MAX_PATH];
			  _getcwd(oldFolder,MAX_PATH - 1);
			  sprintf(tmpPath,"Content\\Missions\\%s",oldMissionName);
			  _chdir(tmpPath);
			  
			  sprintf(newMissionPath,"..\\%s",dlg.m_EditText);
			  
			  RecursiveCopy(tmpPath,newMissionPath,oldMissionName,dlg.m_EditText.GetBuffer(MAX_PATH));
			  
			  _chdir(oldFolder);
			  // Build the rest of the files
			  sprintf(newMissionPath,"Content\\Missions\\%s\\%s",dlg.m_EditText,dlg.m_EditText);
			  
			  char tmpString[MAX_PATH],tmpString2[MAX_PATH],tmpString3[MAX_PATH],tmpName[MAX_PATH];
			  strcpy(tmpPath,newMissionPath);
			  
			  char *p = __mbsrchr(tmpPath,'\\');
			  p++;
			  *p = 0;
			  strcpy(tmpString,tmpPath);
			  p = strstr(tmpString,"mission");
			  if (p)								// for bullshit with mission in the title
			  {
				  *p = 0;
				  p = __mbsrchr(tmpString,'\\');
				  p++;
				  sprintf(tmpString2,"%s%sGraph.data",tmpPath,p);
				  sprintf(tmpString3,"%s%sMoveGrid.data",tmpPath,p);
			  }
			  else
			  {
				  p = __mbsrchr(tmpPath,'\\');
				  *p = 0;
				  p = __mbsrchr(tmpPath,'\\');
				  p++;
				  strcpy(tmpName,p);
				  sprintf(tmpString2,"%s%sGraph.data",tmpString,tmpName);
				  sprintf(tmpString3,"%s%sMoveGrid.data",tmpString,tmpName);
				  p = NULL;
			  }
			  m_graphName = tmpString2;
			  m_moveGridName = tmpString3;
			  lightFileName = tmpString;
			  lightFileName += tmpName;
			  lightFileName += ".Lights";
			  
			  audioFileName = tmpString;
			  audioFileName += tmpName;
			  audioFileName += ".audio";
			  
			  
			  
			  CString filename = newMissionPath;
			  filename += ".data";
			  
			  SaveMissionDataFile(filename.GetBuffer(MAX_PATH));
			  
			  filename = newMissionPath;
			  filename += ".lights";
			  SaveLightFile(filename.GetBuffer(MAX_PATH));
			  
			  filename= newMissionPath;
			  filename += ".audio";
			  SaveAudioFile(filename.GetBuffer(MAX_PATH));
			  
			  CString map_name;
			  
			  {
				  NotationFile notFile(missionFileName.GetBuffer(MAX_PATH));
				  char skyPath[MAX_PATH];
				  
				  Page *old_mission_page = notFile.GetPage(oldMissionName);
				  Check_Object(old_mission_page);
				  
				  old_mission_page->GetEntry("Map",&mapPath);
				  if (old_mission_page->GetEntry("Sky",&cskyPath))
					  strcpy(skyPath,(char*)cskyPath);
				  else
					  skyPath[0] = 0;
				  
				  map_name=mapPath;
				  filename = newMissionPath;
				  filename += ".instance";
				  CreateMissionInstanceFile(filename.GetBuffer(MAX_PATH),(char*)mapPath,skyPath,false);
			  }
			  
			  // Append resource.build file
			  map_name=map_name.Left(map_name.ReverseFind('.'));
			  map_name=map_name.Mid(map_name.ReverseFind('\\')+1);
			  
			  AddToBuildFile(dlg.m_EditText,map_name);
			  
			  filename = newMissionPath;
			  filename += ".contents";
			  SaveMissionContentsFile(filename.GetBuffer(MAX_PATH));
			  
			  //			  CreateMissionResource(filename.GetBuffer(MAX_PATH));
			  
			  //
			  //----------------------
			  // Stop the current game
			  //----------------------
			  //
			  MWApplication::Instance->StopGame();
			  Verify(!Network::Instance);
			  Network::Instance = new Network;
			  Check_Object(Network::Instance);
			  
			  
			  OnFileClose();
			  filename = newMissionPath;
			  filename += ".instance";
			  OpenFile(filename.GetBuffer(MAX_PATH));
			  
			  m_MissionSaved = true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool CMW4GameEdApp::SaveMissionDataFile(char* missionData)
{
	if (!TestFileWrite(missionData))
		return false;
	
	NotationFile dataFile(missionData);
	
	if (Mission::Instance)
	{
		Resource gameModelResource;
		
		Entity::GetGameModelResourceFromDataListID(&gameModelResource,Mission::Instance->GetDataListResourceID());
		Entity__GameModel *model = Cast_Pointer(Entity__GameModel*,gameModelResource.GetPointer());
		
		Entity::ClassID class_id = Entity::GetClassIDFromDataListID(Mission::Instance->GetDataListResourceID());
		Entity__ClassData* class_data = (Entity__ClassData*)Entity::FindClassData(class_id);
		
		(*class_data->modelSaveToText)(model,&dataFile);
		
		Page *page = dataFile.SetPage("GameData");
		Check_Object(page);
		page->SetEntry("Lights",LPCTSTR(lightFileName));
		
		Page * page2 = dataFile.SetPage("Renderers");
		Check_Object(page2);
		page2->SetEntry("AudioRenderer", LPCTSTR(audioFileName));
		
	}
	else
	{
		dataFile.DeleteAllPages();
		dataFile.AddPage("GameData");
		
		Page *page = dataFile.SetPage("GameData");
		Check_Object(page);
		page->AppendEntry("Class","MechWarrior4::MWMission");
		page->AppendEntry("Cull",LPCTSTR(m_MissionData.m_Cull));
		page->AppendEntry("Fog","yes");
		char tmpString[64];
		sprintf(tmpString,"%f %f %f",m_MissionData.m_FogColor[0],m_MissionData.m_FogColor[1],m_MissionData.m_FogColor[2]);
		page->AppendEntry("FogColor",tmpString);
		page->AppendEntry("Lights",LPCTSTR(lightFileName));
		
		Page * page2 = dataFile.SetPage("Renderers");
		Check_Object(page2);
		page2->SetEntry("AudioRenderer", LPCTSTR(audioFileName));
	}
	
	WriteDirtyGameModels();
	dataFile.Save();
	
	return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::WriteDirtyGameModels()
{
	Resource* resource,gameModelResource;
	ResourceID resourceID;
	
	// Hack to make sure we're not in content directory for creating notFile
	// Things get yucky if it can't file includes
	char oldDir[MAX_PATH];
	_getcwd(oldDir,MAX_PATH - 1);
	if (strstr(oldDir,"Content"))
		chdir("..");
	
	ChainIteratorOf<PlugOf<Resource*>*> iterator(&dirtyGameModelResources);
	PlugOf<Resource*> *plug;
	while ((plug = iterator.ReadAndNext()) != NULL)
	{
		resource = (Resource*) plug->GetItem();
		{
			resourceID = resource->GetResourceID();
			Entity::GetGameModelResourceFromDataListID(&gameModelResource,resourceID);
			
			Entity__GameModel *model = Cast_Pointer(Entity__GameModel*,gameModelResource.GetPointer());
			
			Entity::ClassID class_id = Entity::GetClassIDFromDataListID(resourceID);
			Entity__ClassData* class_data = (Entity__ClassData*)Entity::FindClassData(class_id);
			
			char tmp[MAX_PATH],filename[MAX_PATH];
			strcpy(tmp,gameModelResource.GetName());
			char* p = strrchr(tmp,'{');
			*p = 0;
			sprintf(filename,"Content\\%s",tmp);
			
			while (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY)
			{
				char string[MAX_PATH];
				sprintf(string,"%s is marked READONLY.",filename);
				if (MessageBox(NULL,string,"File Error",MB_RETRYCANCEL) == IDCANCEL)
					return;
			}
			
			NotationFile notFile(filename);
			
			class_data->modelSaveToText(model, &notFile);
			
#if 0
			ModelAttributeEntry *attribute_entry;
			TableIteratorOf<ModelAttributeEntry *, Entity__GameModel::AttributeID> iterator(
				&class_data->gameModelAttributeTable.attributesByID);
			int num_attributes = iterator.GetSize();
			int i;
			
			for(i=Entity__GameModel::AnyAttributeID + 1;i<num_attributes;i++)
			{
				attribute_entry =
					class_data->gameModelAttributeTable.GetAttributeEntry(i);
				
				Check_Object(attribute_entry);
				
				char* data = new char [Entity__GameModel::MaxStringLength];
				Register_Pointer(data);
				
				class_data->modelWriteToText(model, attribute_entry, &data);
				
				notFile->SetEntry("GameData",attribute_entry->attributeName,data);
				
				Unregister_Pointer(data);
				delete [] data;
			}	
#endif
		}
	}
	iterator.DeletePlugs();
	
	chdir(oldDir);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool CMW4GameEdApp::SaveMissionContentsFile(char *prop_name)
{
	Check_Pointer(prop_name);
	if (!TestFileWrite(prop_name))
		return false;
	
	MakeObjectNamesUnique();
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	NotationFile notation_file(prop_name);
	notation_file.DeleteAllPages();
	
	iterator.First();
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		//		bool modified;
		
		if (entity->IsDerivedFrom(MechWarrior4::Path::DefaultData))
		{
			Page *page = notation_file.AddPage((char*)entity->instanceName);
			Check_Object(page);
			
			page->AppendEntry("Model","Misc\\Path.data");
			page->AppendEntry("ExecutionState","NeverExecuteState");
			page->AppendEntry("CollisionCallback","false");
			page->AppendEntry("CollideeType","Zone");
			page->AppendEntry("CollisionMask",-1);
			
			char pathFilename[MAX_PATH],tmpString[MAX_PATH],*p;
			strcpy(tmpString,prop_name);
			p = __mbsrchr(tmpString,'\\');
			p++; *p = 0;
			sprintf(pathFilename, "%s%s\\", tmpString, "Paths");
			gos_CreateDirectory(pathFilename);
			sprintf(pathFilename,"%s%s\\%s.contents",tmpString,"Paths", (char*)entity->instanceName);
			
			page->AppendEntry("PathPoints",pathFilename);
			
			NotationFile path_notation_file;
			
			page = path_notation_file.AddPage("Path");
			
			Point3D point;
			MechWarrior4::Path* path;
			path = Cast_Object(MechWarrior4::Path*,entity);
			
			for (int i = 0; i < path->pathPoints.size(); i++)
			{
				sprintf(tmpString,"Point%d",i + 1);
				point = path->pathPoints[i];
				page->AppendEntry(tmpString,point);
			}
			path_notation_file.SaveAs(pathFilename);
		}
		else if(entity->IsDerivedFrom(DropZone::DefaultData))
		{	
			Page *page = notation_file.AddPage((char*)entity->instanceName);
			Check_Object(page);
			
			page->AppendEntry("Model","Misc\\DropZone.data");
			page->AppendEntry("ExecutionState","NeverExecuteState");
			page->AppendEntry("TileBound","false");
			Point3D local_translation(entity->GetLocalToParent());
			page->SetEntry("Translation", local_translation);
			YawPitchRoll rotation_value(entity->GetLocalToParent());
			page->SetEntry("Rotation", rotation_value);
			const char *alignment_text;
			alignment_text = Entity::AlignmentAsciiToText(entity->alignment);
			page->SetEntry("Alignment", alignment_text);
			
			
			char pathFilename[MAX_PATH],tmpString[MAX_PATH],*p;
			strcpy(tmpString,prop_name);
			p = __mbsrchr(tmpString,'\\');
			p++; *p = 0;
			sprintf(pathFilename, "%s%s\\", tmpString, "DropZones");
			gos_CreateDirectory(pathFilename);
			sprintf(pathFilename,"%s%s\\%s.contents",tmpString,"DropZones", (char*)entity->instanceName);
			
			page->AppendEntry("DropPoints",pathFilename);
			
			NotationFile drop_notation_file;
			
			Page *drop_page = drop_notation_file.AddPage("DropPoints");
			Page *rot_page = drop_notation_file.AddPage("DropRots");
			
			Point3D point;
			YawPitchRoll rot;
			LinearMatrix4D mat;
			Adept::DropZone* drop;
			drop = Cast_Object(Adept::DropZone*,entity);
			
			ChainIteratorOf<Adept::DropZone::MatrixPlug *> iterator(&drop->dropMats);
			Adept::DropZone::MatrixPlug *drop_point;
			char entry_name[256];
			int count = 1;
			while((drop_point = iterator.ReadAndNext()) != NULL)
			{	
				Check_Object(drop_point);
				sprintf(entry_name, "Point%d", count);
				mat = drop_point->GetItem ();
				point = (Point3D) mat;
				rot = (YawPitchRoll) mat;
				drop_page->AppendEntry(entry_name, point);
				sprintf(entry_name, "Rot%d", count);
				rot_page->AppendEntry(entry_name, rot);
				count++;
			}
			drop_notation_file.SaveAs(pathFilename);
			
		}
		else if (entity->GetPropType() == Entity::MissionPropType &&
			!entity->IsDerivedFrom(AI::DefaultData) &&
			!entity->IsDerivedFrom(EditorWaypoint::DefaultData) &&
			!entity->IsDerivedFrom(EditorPathNode::DefaultData) &&
			!entity->IsDerivedFrom(EditorMovementPath::DefaultData) &&
			!entity->IsDerivedFrom(EditorLatticeNode::DefaultData) &&
			!entity->IsDerivedFrom(EditorBoundaryNode::DefaultData) &&
			!entity->IsDerivedFrom(EditorDropNode::DefaultData) &&
			!entity->IsDerivedFrom(EditorDropZonePoint::DefaultData) &&
			!entity->IsDerivedFrom(EditorObjectiveMarker::DefaultData) &&
			!entity->IsDerivedFrom(EditorLight::DefaultData) &&
			!entity->IsDerivedFrom(EditorCameraShip::DefaultData))
		{
			Page *page = notation_file.AddPage((char*)entity->instanceName);
			Check_Object(page);
			
			entity->SaveInstanceText(page);
			
			CEditorEntityData *exdata;
			exdata=theApp.GetEntityData(entity);
			
			if(exdata)
			{
				page->SetEntry("EDVOffset",exdata->VOffset);
			}
			
			
			
		}
	}
	// all AI Drivers must go last & waypoints go in different file
	
	MWMap *inst;
	AI *ai;
	inst = Cast_Object (MWMap *,Map::Instance);
	ChainIteratorOf<AI *> iterator2(&inst->m_executingAIs);
	iterator2.First ();
	while((ai = iterator2.ReadAndNext()) != NULL)
	{
		Check_Object(ai);
		//		bool modified;
		
		if (!ai->IsDerivedFrom (PlayerAI::DefaultData))
		{
			Page *page = notation_file.AddPage((char*)ai->instanceName);
			Check_Object(page);
			ai->SaveInstanceText(page);
			// Write out Editor only Data
			
		}
	}
	
	//
	//----------------------
	//Save off the NameTable
	//----------------------
	//
	MString table_name = prop_name;
	table_name.StripExtension();
	table_name += ".table";
	
	{
		
		NotationFile table_file(table_name);
		
		
		Check_Object(NameTable::Instance);
		//
		// BUGBUG:: This will clear the current contents of the file and overwrite it
		//          with the data in this structure. We shouldn't have to do this, but if the old
		//          data is kept around, items aren't being removed from the file. The name table module would have
		//          to be rewritten to work with the new NotationFile code that allows you to modify the
		//          existing data if we don't want to completely overwrite the file.
		//
		//
		table_file.DeleteAllPages();
		
		NameTable::Instance->IsValid();
		NameTable::Instance->SaveTable(&table_file);
		table_file.Save();
	}
	
	//
	//------------------
	//Save the RailGraph
	//------------------
	//
	char railString[MAX_PATH],tmp[MAX_PATH],*p;
	strcpy(tmp,prop_name);
	p = __mbsrchr(tmp,'\\') + 1;
	*p = 0;
	sprintf(railString,"%s",m_graphName);
	
	NotationFile railgraph_file(railString);
	Check_Object(NameTable::Instance);
	MW4AI::g_MissionGraph->DumpNotationFile (&railgraph_file,(LPCTSTR) m_moveGridName,(LPCTSTR) m_rectGridName,(LPCTSTR) m_airMoveGridName);
	railgraph_file.Save();
	
	notation_file.Save();
	
	return true;
}

void CMW4GameEdApp::OnToolsCameraheightGround()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_GROUND,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraHeight = 1.65f;
}

void CMW4GameEdApp::OnToolsCameraheightMechheight10m()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_GROUND,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_USERDEFINED,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraHeight = 10;
}

void CMW4GameEdApp::OnToolsCameraheightTwicemechheight20m()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_GROUND,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_USERDEFINED,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraHeight = 40;
}

void CMW4GameEdApp::OnToolsCameraheightFourtimesmechheight40m()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_GROUND,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_USERDEFINED,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraHeight = 80;
}

void CMW4GameEdApp::OnToolsCameraheightUserdefined()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_GROUND,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_MECHHEIGHT10M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_TWICEMECHHEIGHT20M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_FOURTIMESMECHHEIGHT40M,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERAHEIGHT_USERDEFINED,MF_BYCOMMAND | MF_CHECKED);
	
	CGenericTextDlg dlg;
	char string[64];
	
	dlg.m_Title = "User Defined Camera Height";
	dlg.m_MessageText = "Enter the height above the terrain you would like to set the camera.";
	dlg.m_EditText = itoa(int(cameraHeight),string,10);
	dlg.addStyle = ES_NUMBER;
	
	dlg.editRect.left = 10;
	dlg.editRect.right = 60;
	
	dlg.DoModal();
	
	cameraHeight = float(atof(dlg.m_EditText));
	if (cameraHeight < 1.0f)
		cameraHeight = 1.0f;
}

void CMW4GameEdApp::OnToolsCameraspeedSlow()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_SLOW,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_REGULAR,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_FAST,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraSpeed = 1;
}

void CMW4GameEdApp::OnToolsCameraspeedRegular()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_SLOW,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_REGULAR,MF_BYCOMMAND | MF_CHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_FAST,MF_BYCOMMAND | MF_UNCHECKED);
	
	cameraSpeed = 4;
}

void CMW4GameEdApp::OnToolsCameraspeedFast()
{
	CMenu* menu = m_pMainWnd->GetMenu();
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_SLOW,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_REGULAR,MF_BYCOMMAND | MF_UNCHECKED);
	menu->GetSubMenu(APP_MENU_TOOLS)->CheckMenuItem(ID_TOOLS_CAMERASPEED_FAST,MF_BYCOMMAND | MF_CHECKED);
	
	cameraSpeed = 16;
}

void CMW4GameEdApp::OnToolsBriefingfile()
{
	StopMultiPlace();
	if(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState)
	{
		if (!briefingWnd)
		{
			briefingWnd = new CEditWnd(briefingPath.GetBuffer(MAX_PATH));
			RECT r;
			r.left = 50;
			r.top = 50;
			r.right = 350;
			r.bottom = 250;
			briefingWnd->Create(NULL,"Mission Briefing",WS_VISIBLE,r);
		}
		else
			briefingWnd->ShowWindow(SW_SHOW);
	}
}

void CMW4GameEdApp::OnFileSave()
{
	StopMultiPlace();
	Check_Object(Mission::Instance);
	MakeObjectsTileBased();	
	RemoveCulturals();
	
	if(!missionFileName.IsEmpty())
	{
		RECT rect;
		int w = 280, h = 130;
		
		theApp.m_pMainWnd->GetWindowRect(&rect);
		CMsgDlg msgDlg("Saving...","Arial",240,theApp.m_pMainWnd,
			(rect.right - rect.left) / 2 + rect.left - w / 2,(rect.bottom - rect.top) / 2 + rect.top - h / 2,w,h);
		msgDlg.ShowWindow(SW_SHOW);
		msgDlg.UpdateWindow();
		
		// Should we backup the files first?
		
		if (theApp.m_AutoBackupOnSave)
		{
			char srcPath[MAX_PATH],destPath[MAX_PATH],oldPath[MAX_PATH],srcFile[MAX_PATH],destFile[MAX_PATH],*p;
			strcpy(srcPath,missionFileName.GetBuffer(MAX_PATH - 1));
			p = __mbsrchr(srcPath,'\\');
			*p = 0;
			strcpy(destPath,srcPath);
			strcat(destPath,"\\Backup");
			
			_getcwd(oldPath,MAX_PATH - 1);
			if (_chdir(destPath) != 0)		// = 0 if successful, !0 if failed
			{
				if (_mkdir(destPath) != 0)
				{
					MessageBox(NULL,"Unable to create backup directory","Save Error",MB_OK);
					return;
				}
			}
			_chdir(oldPath);
			
			sprintf(srcFile,"%s\\*.*",srcPath);
			
			struct _finddata_t fileinfo;
			long handle = _findfirst(srcFile,&fileinfo);
			if (handle != -1)
			{
				do
				{
					if (fileinfo.attrib & _A_SUBDIR)
						continue;
					
					sprintf(srcFile,"%s\\%s",srcPath,fileinfo.name);
					sprintf(destFile,"%s\\%s",destPath,fileinfo.name);
					CopyFile(srcFile,destFile,FALSE);
				}
				while (_findnext(handle,&fileinfo) == 0);
			}
		}
		const char* cmapPath, *cskyPath;
		
		char missionContentPath[MAX_PATH],missionName[MAX_PATH],mapPath[MAX_PATH],skyPath[MAX_PATH],*p;
		strcpy(missionContentPath,missionFileName.GetBuffer(MAX_PATH - 1));
		
		p = __mbsrchr(missionContentPath,'\\');
		p++;
		strcpy(missionName,p);
		p = __mbsrchr(missionName,'.');
		*p = 0;
		
		p = __mbsrchr(missionContentPath,'.');
		
		sprintf(p,".instance");
		
		NotationFile notFile(missionContentPath);
		Page *mission_page = notFile.GetPage(missionName);
		Check_Object(mission_page);
		mission_page->GetEntry("Map",&cmapPath,true);
		if (mission_page->GetEntry("Sky",&cskyPath))
			strcpy(skyPath,(char*)cskyPath);
		else
			skyPath[0] = 0;
		
		strcpy(mapPath,(char*)cmapPath);
		
		if (!CreateMissionInstanceFile(missionContentPath,(char*)mapPath,(char*)skyPath,false))
			return;
		
		sprintf(p,".contents");
		if (!SaveMissionContentsFile(missionContentPath))
			return;
		
		char missionData[MAX_PATH];
		_splitpath(missionFileName,missionData,missionData,missionName,missionData);
		sprintf(missionData,"Content\\Missions\\%s\\%s.data",missionName,missionName);
		SaveMissionDataFile(missionData);
		SaveLightFile();
		SaveAudioFile(); // doesn't do anything yet.
		
		//		CreateMissionResource(missionFileName.GetBuffer(MAX_PATH));
	}
	else
		OnFileSaveAs();
	
	m_MissionSaved = true;
}

void CMW4GameEdApp::OnToolsCamerafollowingGround()
{
	if (cameraFollowing == CAMERA_FOLLOW_NONE)
	{
		cameraFollowing = CAMERA_FOLLOW_GROUND;
		cameraHeight -= displayWindow->GetMapPointVertical();
	}
	cameraFollowing = CAMERA_FOLLOW_GROUND;
}

void CMW4GameEdApp::OnUpdateToolsCamerafollowingGround(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraFollowing == CAMERA_FOLLOW_GROUND);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
}

void CMW4GameEdApp::OnToolsCamerafollowingHighestpoint()
{
	if (cameraFollowing == CAMERA_FOLLOW_NONE)
	{
		// there is a special case if the camera is inside an object.
		
		cameraFollowing = CAMERA_FOLLOW_HIGHESTPOINT;
		cameraHeight -= displayWindow->GetMapPointVertical();
	}
	cameraFollowing = CAMERA_FOLLOW_HIGHESTPOINT;
}

void CMW4GameEdApp::OnUpdateToolsCamerafollowingHighestpoint(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraFollowing == CAMERA_FOLLOW_HIGHESTPOINT);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnToolsCamerafollowingNone()
{
	cameraHeight += displayWindow->GetMapPointVertical();
	cameraFollowing = CAMERA_FOLLOW_NONE;
}

void CMW4GameEdApp::OnUpdateToolsCamerafollowingNone(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraFollowing == CAMERA_FOLLOW_NONE);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

BOOL CAboutDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	
	m_VersionString.SetWindowText(LPCTSTR(theApp.m_VersionString)); // temporary version hack
	
	// CG: Following block was added by System Info Component.
	{
		CString strFreeDiskSpace;
		CString strFreeMemory;
		CString strFmt;
		
		// Fill available memory
		MEMORYSTATUS MemStat;
		MemStat.dwLength = sizeof(MEMORYSTATUS);
		GlobalMemoryStatus(&MemStat);
		strFmt.LoadString(CG_IDS_PHYSICAL_MEM);
		strFreeMemory.Format(strFmt, MemStat.dwTotalPhys / 1024L);
		
		//TODO: Add a static control to your About Box to receive the memory
		//      information.  Initialize the control with code like this:
		SetDlgItemText(IDC_PHYSICAL_MEM, strFreeMemory);
		
		// Fill disk free information
		struct _diskfree_t diskfree;
		int nDrive = _getdrive(); // use current default drive
		if (_getdiskfree(nDrive, &diskfree) == 0)
		{
			strFmt.LoadString(CG_IDS_DISK_SPACE);
			strFreeDiskSpace.Format(strFmt,
				(DWORD)diskfree.avail_clusters *
				(DWORD)diskfree.sectors_per_cluster *
				(DWORD)diskfree.bytes_per_sector / (DWORD)1024L,
				nDrive-1 + _T('A'));
		}
		else
			strFreeDiskSpace.LoadString(CG_IDS_DISK_SPACE_UNAVAIL);
		
		//TODO: Add a static control to your About Box to receive the memory
		//      information.  Initialize the control with code like this:
		SetDlgItemText(IDC_DISK_SPACE, strFreeDiskSpace);
	}
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CMW4GameEdApp::OnViewResize640()
{
	gos_SetScreenMode(640,480);
	RunGameOSLogic();
	m_VideoResolution = 640;
}

void CMW4GameEdApp::OnUpdateViewResize640(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 640);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,640,480));
}

void CMW4GameEdApp::OnViewResize800()
{
	gos_SetScreenMode(800,600);
	RunGameOSLogic();
	m_VideoResolution = 800;
}

void CMW4GameEdApp::OnUpdateViewResize800(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 800);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,800,600));
}

void CMW4GameEdApp::OnViewResize1024()
{
	gos_SetScreenMode(1024,768);
	RunGameOSLogic();
	m_VideoResolution = 1024;
}

void CMW4GameEdApp::OnUpdateViewResize1024(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 1024);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,1024,768));
}

void CMW4GameEdApp::OnViewResize1152()
{
	gos_SetScreenMode(1152,864);
	RunGameOSLogic();
	m_VideoResolution = 1152;
}

void CMW4GameEdApp::OnUpdateViewResize1152(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 1152);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,1152,864));
}

void CMW4GameEdApp::OnViewResize1280()
{
	gos_SetScreenMode(1280,1024);
	RunGameOSLogic();
	m_VideoResolution = 1280;
}

void CMW4GameEdApp::OnUpdateViewResize1280(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 1280);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,1280,1024));
}

void CMW4GameEdApp::OnViewResize1600()
{
	gos_SetScreenMode(1600,1200);
	RunGameOSLogic();
	m_VideoResolution = 1600;
}

void CMW4GameEdApp::OnUpdateViewResize1600(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_VideoResolution == 1600);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState &&
		gos_GetMachineInformation(gos_Info_ValidMode,0,1600,1200));
}

void CMW4GameEdApp::OnFileAutobackuponsave()
{
	StopMultiPlace();
	m_AutoBackupOnSave = !m_AutoBackupOnSave;
}

void CMW4GameEdApp::OnUpdateFileAutobackuponsave(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_AutoBackupOnSave);
}

void CMW4GameEdApp::ShowTipAtStartup(void)
{
	// CG: This function added by 'Tip of the Day' component.
	
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);
	if (cmdInfo.m_bShowSplash)
	{
		CTipDlg dlg;
		if (dlg.m_bStartup)
			dlg.DoModal();
	}
	
}

void CMW4GameEdApp::ShowTipOfTheDay(void)
{
	// CG: This function added by 'Tip of the Day' component.
	
	CTipDlg dlg;
	dlg.DoModal();
	
}

void CMW4GameEdApp::OnFileClose()
{
	StopMultiPlace();
	if (theApp.m_editorState != CMW4GameEdApp::NoGameIdleState)
	{
		if (!m_MissionSaved)
		{
			if (MessageBox(NULL,"Mission has not been saved.  Save now?","Unsaved Data",MB_YESNO) == IDYES)	// localize
			{
				OnFileSave();
			}
		}
		
		if(!undoChain.IsEmpty())
		{
			ChainIteratorOf<Command *> iterator(&undoChain);
			iterator.DeletePlugs();
		}
		
		
		CSelectionList::Instance->ClearSelectionList();
		
		if (briefingWnd)
		{
			delete briefingWnd;
			briefingWnd = NULL;
		}
		if (instanceWindow->scriptWnd)
		{
			delete instanceWindow->scriptWnd;
			instanceWindow->scriptWnd = NULL;
		}
		instanceWindow->ClearInstanceLists();
		instanceWindow->FillTabBox();


		RemoveEditorObjects ();


		MWApplication::Instance->StopGame();
		
		//This call will eventually have to be before Stop Game
		//Right now this will construct the resource from text.  It should
		//eventually use the loaded mission to create the create message, but for now
		//it needs to be kept as the same version as the text that is saved.
		//		EditorConstructMissionCreateMessage();
		
		
		Verify(!Network::Instance);
		Network::Instance = new Network;
		Check_Object(Network::Instance);
		m_editorState = CMW4GameEdApp::NoGameIdleState;
		overviewWindow->DrawWindow();
		displayWindow->Invalidate();
		
		// Need this to clear the back buffer
		gos_SetupViewport(0,1.0,1,0xff000000,0.0,0.0,1.0,1.0);
		
		missionFileName.Empty();
		m_ScriptName.Empty();
	}
	
}

void CMW4GameEdApp::EditorConstructMissionCreateMessage()
{
	
#if defined(_ARMOR)
	int stack_index = Tool::Instance->GetStackLevel();
#endif
	
	const char *instance_file_name = missionFileName.GetBuffer(MAX_PATH);
	ReplicatorID base_id = ReplicatorID::Null;
	Resource mission_resource(instance_file_name);
	//
	//---------------------------------------------------------
	// Open up the instance file and push the path on the stack
	//---------------------------------------------------------
	//
	NotationFile instance_file(instance_file_name, NotationFile::NonEmpty);
	instance_file_name = instance_file.GetFileName();
	Tool::Instance->PushFilePath(&instance_file);
	
	//
	//-----------------------------------------------------------------------
	// For instances, assume the first page is our instance, so take whatever
	// name it has
	//-----------------------------------------------------------------------
	//
	NotationFile::PageIterator *instance_pages = instance_file.MakePageIterator();
	Check_Object(instance_pages);
	Page *instance = instance_pages->GetCurrent();
	Check_Object(instance);
	
	//
	//------------------------------
	// Put the message into a stream
	//------------------------------
	//
	//	DynamicMemoryStream instance_stream;
	//	Tool::Instance->ConstructCreateMessage(
	//		&instance_stream,
	//		instance,
	//		&base_id
	//	);
	//	mission_resource.Save(&instance_stream, instance_file.GetFileDependencies());
	
	//
	//-------------
	// Now clean up
	//-------------
	//
	Tool::Instance->PopFilePath();
	Check_Object(instance_pages);
	delete instance_pages;
	Verify(stack_index == Tool::Instance->GetStackLevel());
}

void CMW4GameEdApp::OnUpdateFileSave(CCmdUI* pCmdUI)
{
	if (theApp.m_editorState == CMW4GameEdApp::NoGameIdleState)
		pCmdUI->Enable(FALSE);
	else
		pCmdUI->Enable();
}

void CMW4GameEdApp::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
{
	OnUpdateFileSave(pCmdUI);
}

void CMW4GameEdApp::OnFileDelete()
{
	StopMultiPlace();
	SetCurrentDirectory(Working_Directory);
	CFileDlg dlg;
	dlg.DoModal();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::GetGridCoords(Point3D& point)
{
	Scalar sign = (point.x < 0) ? -1.0f : 1.0f;
	int wholeGrid = abs(int(point.x / Scalar(theApp.gridValue)));
	Scalar gridFloor = Scalar(wholeGrid * theApp.gridValue);
	
	if ((fabs(point.x) - fabs(gridFloor)) >= (theApp.gridValue / 2))
		point.x = sign * (wholeGrid + 1) * theApp.gridValue;
	else
		point.x = sign * wholeGrid * theApp.gridValue;
	
	sign = (point.z < 0) ? -1.0f : 1.0f;
	wholeGrid = abs(int(point.z / Scalar(theApp.gridValue)));
	gridFloor = Scalar(wholeGrid * theApp.gridValue);
	
	if ((fabs(point.z) - fabs(gridFloor)) >= (theApp.gridValue / 2))
		point.z = sign * (wholeGrid + 1) * theApp.gridValue;
	else
		point.z = sign * wholeGrid * theApp.gridValue;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::VerifyWaypointRadius()
{
	// check if anything in the selection list is too close to a waypoint
	Entity* waypoint;
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	
	while ((waypoint = iterator.ReadAndNext()) != NULL)
	{
		if (waypoint->IsDerivedFrom(EditorWaypoint::DefaultData))
		{
			CSelectionNode* selected;
			ChainIteratorOf<CSelectionNode*> selections(&CSelectionList::Instance->selectionList);
			
			while ((selected = selections.ReadAndNext()) != NULL)
			{
				if (selected->selectedEntity->IsDerivedFrom(EditorWaypoint::DefaultData) ||
					selected->selectedEntity->IsDerivedFrom(EditorLatticeNode::DefaultData))
					continue;
				
				Stuff::Vector3D vector;
				Stuff::Point3D waypointPos,selectedPos;
				
				waypointPos = waypoint->GetLocalToWorld();
				selectedPos = selected->selectedEntity->GetLocalToWorld();
				vector.Subtract(waypointPos,selectedPos);
				
				//				if (fabs((double)vector.x) <= waypoint->radius || fabs((double)vector.z) <= waypoint->radius)
				if (fabs((double)vector.x) <= 50 || fabs((double)vector.z) <= 50)
				{
					MessageBox(NULL,"An object has been placed within the radius of a waypoint.  This is not illegal, however if too many objects are within the waypoint's bounding radius bad things can happen.",			// localize
						"Warning",MB_OK | MB_ICONWARNING);
					return;
				}
			}
		}
	}
}

void CMW4GameEdApp::LoadLattice()
{
	Check_Object(theApp.resourceWindow->objectInformation);
	Check_Object(EntityManager::Instance);
	Check_Object(Connection::Local);
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity* entity;
	
	CSelectionList::Instance->ClearSelectionList();
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData))
		{
			CSelectionList::Instance->AddSelection(entity);
		}
	}
	
	if (CSelectionList::Instance->GetSelectionCount())
	{
		Verify(theApp.currentCommand == NULL);
		theApp.currentCommand = new DeleteCommand();
		delete theApp.currentCommand;
		theApp.currentCommand = NULL;
	}
	
	Page *lattice_page = theApp.resourceWindow->objectInformation->GetPage("LatticeNode");
	Check_Object(lattice_page);
	
	for (int i = 0; i < MW4AI::g_MissionGraph->NumNodes(); i++)
	{
		if (!MW4AI::g_MissionGraph->Node(i))	// might be NULL
			continue;
		
		//		lattice_page->SetEntry("Model", "Editor\\Waypoints\\LatticeNode\\LatticeNode.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			lattice_page,
			&entity_id
			);
		
		entity_stream.Rewind();
		entity_id = Connection::Local->GetNextReplicatorID();
		Entity *entity = Entity::CreateEntity(
			&entity_stream,
			&entity_id,
			false
			);
		
		//
		//--------------------------------------------
		//Make some initial assignments for the entity
		//--------------------------------------------
		//
		Check_Object(entity);
		
		EntityManager::Instance->GetNameSocket()->Remove(entity);
		entity->instanceName = "LatticeNode_";
		char string[32];
		entity->instanceName += itoa(i,string,10);
		
		//		EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
		//		theApp.resourceWindow->numEntitiesAdded++;
		
		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		
		CSelectionList::Instance->AddSelection(entity);
		
		EditorLatticeNode* latticeNode = Cast_Object(EditorLatticeNode*,entity);
		latticeNode->railNode = MW4AI::g_MissionGraph->Node(i);
		
		LinearMatrix4D matrix = LinearMatrix4D::Identity;
		Point3D pos;
		
		pos = latticeNode->railNode->Location();
		
		Stuff::Scalar height = theApp.displayWindow->GetMapPointVertical(pos.x,pos.z);
		if (pos.y < height)
		{
			pos.y = height;
			latticeNode->railNode->Location(pos);
		}
		matrix.BuildTranslation(pos);
		
		entity->SetNewLocalToParent(matrix);
		entity->SyncMatrices(true);
		
		latticeNode->railNode->UpdateRadiusPointData();
		
		//		EntityManager::Instance->RequestPostCollisionExecution(entity);
		Map::Instance->UpdateZone(entity);
	}
	CSelectionList::Instance->ClearSelectionList();
	InitMovementLatticeData();
}

void CMW4GameEdApp::RemoveLattice()
{
	Check_Object(Map::Instance);
	
	CSelectionList::Instance->ClearSelectionList();
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *childEntity;
	
	while((childEntity = iterator.ReadAndNext()) != NULL)
	{
		if (childEntity->IsDerivedFrom(EditorLatticeNode::DefaultData))
		{
			Map::Instance->RemoveChild(childEntity);
			childEntity->SentenceToDeathRow();
		}
	}
}

void CMW4GameEdApp::LoadPaths()
{
	Check_Object(Map::Instance);
	Check_Object(theApp.resourceWindow->objectInformation);
	Check_Object(Connection::Local);
	Check_Object(EntityManager::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *childEntity;
	
	while((childEntity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(childEntity);
		if (childEntity->IsDerivedFrom(MechWarrior4::Path::DefaultData))
		{
			EditorPathNode* lastNode = NULL;
			MechWarrior4::Path* path;
			path = Cast_Object(MechWarrior4::Path*,childEntity);
			
			Page *path_page = theApp.resourceWindow->objectInformation->SetPage("Content\\Editor\\Waypoints\\MovementPath\\MovementPath.data");
			Check_Object(path_page);
			path_page->SetEntry("MovementPath","MovementPath");
			DynamicMemoryStream entity_stream;
			ReplicatorID entity_id = ReplicatorID::Null;
			path_page = theApp.resourceWindow->objectInformation->SetPage("MovementPath");
			Check_Object(path_page);
			Tool::Instance->ConstructCreateMessage(
				&entity_stream,
				path_page,
				&entity_id
				);
			
			entity_stream.Rewind();
			entity_id = Connection::Local->GetNextReplicatorID();
			Entity *entity = Entity::CreateEntity(
				&entity_stream,
				&entity_id,
				false
				);
			
			//
			//--------------------------------------------
			//Make some initial assignments for the entity
			//--------------------------------------------
			//
			Check_Object(entity);
			
			Map::Instance->AddChild(entity);
			MLRTexturePool::Instance->LoadImages();
			entity->SetPropType(Entity::MissionPropType);
			entity->instanceName = "EditorMovementPath_";
			char string[32];
			entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
			
			EditorMovementPath* movePath;
			movePath = Cast_Object(EditorMovementPath*, entity);
			
			movePath->GetElement()->SetAlwaysCullMode();
			movePath->GetElement()->Sync();
			
			for (int i = 0; i < path->pathPoints.size(); i++)
			{
				path_page = theApp.resourceWindow->objectInformation->SetPage("Content\\Editor\\Reserved\\PathNode\\PathNode.data");
				Check_Object(path_page);
				path_page->SetEntry("PathNode","PathNode");
				DynamicMemoryStream entity_stream;
				ReplicatorID entity_id = ReplicatorID::Null;
				path_page = theApp.resourceWindow->objectInformation->SetPage("PathNode");
				Check_Object(path_page);
				Tool::Instance->ConstructCreateMessage(
					&entity_stream,
					path_page,
					&entity_id
					);
				
				entity_stream.Rewind();
				entity_id = Connection::Local->GetNextReplicatorID();
				Entity *entity = Entity::CreateEntity(
					&entity_stream,
					&entity_id,
					false
					);
				
				//
				//--------------------------------------------
				//Make some initial assignments for the entity
				//--------------------------------------------
				//
				Check_Object(entity);
				
				EntityManager::Instance->GetNameSocket()->Remove(entity);
				entity->instanceName = "MovementPathNode_";
				char string[32];
				entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
				
				Map::Instance->AddChild(entity);
				MLRTexturePool::Instance->LoadImages();
				entity->SetPropType(Entity::MissionPropType);
				
				//				CSelectionList::Instance->AddSelection(entity);
				
				EditorPathNode* pathNode = Cast_Object(EditorPathNode*,entity);
				pathNode->pathSlot.Remove();
				pathNode->pathSlot.Add(movePath);
				pathNode->pathSlot.GetCurrent()->pathSlot.Remove();
				pathNode->pathSlot.GetCurrent()->pathSlot.Add(path);
				pathNode->pathSlot.GetCurrent()->pathNodes.Add(pathNode);
				pathNode->index = i;
				if (lastNode)
					lastNode->nextnode = pathNode;
				pathNode->prevnode = lastNode;
				pathNode->nextnode = NULL;
				lastNode = pathNode;
				
				LinearMatrix4D matrix = LinearMatrix4D::Identity;
				matrix.BuildTranslation(path->pathPoints[i]);
				
				entity->SetNewLocalToParent(matrix);
				entity->SyncMatrices(true);
				
				pathNode->CreateLink();
				pathNode->ShowLink(true);
				//				EntityManager::Instance->RequestPostCollisionExecution(pathNode);
				Map::Instance->UpdateZone(pathNode);
			}
		}
	}
	CSelectionList::Instance->ClearSelectionList();
}

void CMW4GameEdApp::LoadBoundary()
{
	//	return;
	Check_Object(EntityManager::Instance);
	Check_Object(Map::Instance);
	SetCurrentDirectory(Working_Directory);
	EditorBoundaryNode* lastNode = NULL;
	EditorBoundaryNode* firstBoundaryNode=NULL;
	int index;
	for(index = 0; index < theApp.missionBoundary.GetLength(); index++)
	{
		Page *page = theApp.resourceWindow->objectInformation->SetPage("BoundaryNode");
		Check_Object(page);
		page->SetEntry("Model", "Editor\\Reserved\\BoundaryNode\\BoundaryNode.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			page,
			&entity_id
			);
		
		entity_stream.Rewind();
		entity_id = Connection::Local->GetNextReplicatorID();
		Entity *entity = Entity::CreateEntity(
			&entity_stream,
			&entity_id,
			false
			);
		
		//
		//--------------------------------------------
		//Make some initial assignments for the entity
		//--------------------------------------------
		//
		Check_Object(entity);
		EditorBoundaryNode* boundaryNode = Cast_Object(EditorBoundaryNode*,entity);
		boundaryNode->myBoundary=&missionBoundary;
		
		EntityManager::Instance->GetNameSocket()->Remove(entity);
		entity->instanceName = "BoundaryNode_";
		char string[32];
		entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
		
		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		
		
		if (index == 0)
		{
			boundaryNode->prevnode = boundaryNode;
			boundaryNode->nextnode = boundaryNode;
			firstBoundaryNode=boundaryNode;
		}
		else
		{
			lastNode->nextnode = boundaryNode;
			boundaryNode->prevnode = lastNode;
			boundaryNode->nextnode = firstBoundaryNode;
		}
		boundaryNode->firstBoundaryNode = firstBoundaryNode;
		boundaryNode->firstBoundaryNode->prevnode=boundaryNode;
		
		boundaryNode->index = index;
		lastNode = boundaryNode;
		
		LinearMatrix4D matrix = LinearMatrix4D::Identity;
		Point3D pos;
		
		pos.x = theApp.missionBoundary[index].x;
		pos.z = theApp.missionBoundary[index].y;
		pos.y = theApp.displayWindow->GetMapPointVertical(pos.x,pos.z);
		
		matrix.BuildTranslation(pos);
		
		entity->SetNewLocalToParent(matrix);
		entity->SyncMatrices(true);
		
		boundaryNode->CreateLink();
		boundaryNode->ShowLink(true);
		
		
		//		EntityManager::Instance->RequestPostCollisionExecution(entity);
		Map::Instance->UpdateZone(entity);
		if (m_showBoundary)
			boundaryNode->GetElement()->SetVolumeCullMode();
		boundaryNode->GetElement()->Sync();
	}
	
	
	for(index = 0; index < theApp.warningBoundary.GetLength(); index++)
	{
		Page *page = theApp.resourceWindow->objectInformation->SetPage("BoundaryNode");
		Check_Object(page);
		page->SetEntry("Model", "Editor\\Reserved\\BoundaryNode\\BoundaryNode.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			page,
			&entity_id
			);
		
		entity_stream.Rewind();
		entity_id = Connection::Local->GetNextReplicatorID();
		Entity *entity = Entity::CreateEntity(
			&entity_stream,
			&entity_id,
			false
			);
		
		//
		//--------------------------------------------
		//Make some initial assignments for the entity
		//--------------------------------------------
		//
		Check_Object(entity);
		EditorBoundaryNode* boundaryNode = Cast_Object(EditorBoundaryNode*,entity);
		boundaryNode->myBoundary=&warningBoundary;
		
		EntityManager::Instance->GetNameSocket()->Remove(entity);
		entity->instanceName = "WarningNode_";
		char string[32];
		entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
		
		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		
		
		if (index == 0)
		{
			boundaryNode->prevnode = boundaryNode;
			boundaryNode->nextnode = boundaryNode;
			firstBoundaryNode=boundaryNode;
		}
		else
		{
			lastNode->nextnode = boundaryNode;
			boundaryNode->prevnode = lastNode;
			boundaryNode->nextnode = firstBoundaryNode;
		}
		
		boundaryNode->firstBoundaryNode = firstBoundaryNode;
		boundaryNode->firstBoundaryNode->prevnode=boundaryNode;
		boundaryNode->index = index;
		lastNode = boundaryNode;
		
		LinearMatrix4D matrix = LinearMatrix4D::Identity;
		Point3D pos;
		
		pos.x = theApp.warningBoundary[index].x;
		pos.z = theApp.warningBoundary[index].y;
		pos.y = theApp.displayWindow->GetMapPointVertical(pos.x,pos.z);
		
		matrix.BuildTranslation(pos);
		
		entity->SetNewLocalToParent(matrix);
		entity->SyncMatrices(true);
		
		
		boundaryNode->CreateLink();
		boundaryNode->ShowLink(true);
		
		
		//		EntityManager::Instance->RequestPostCollisionExecution(entity);
		Map::Instance->UpdateZone(entity);
		if (m_showBoundary)
			boundaryNode->GetElement()->SetVolumeCullMode();
		boundaryNode->GetElement()->Sync();
	}
	
	
	m_showBoundary = true;
	OnToolsMovmentlayerShowmissionboundary();
}

void CMW4GameEdApp::LoadDropZones()
{
	Check_Object(Map::Instance);
	Check_Object(theApp.resourceWindow->objectInformation);
	Check_Object(Connection::Local);
	Check_Object(EntityManager::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *childEntity;
	
	int count = 0;
	while((childEntity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(childEntity);
		if (childEntity->IsDerivedFrom(Adept::DropZone::DefaultData))
		{
			Adept::DropZone* dropZone;
			dropZone = Cast_Object(Adept::DropZone*,childEntity);
			
			Page *page = theApp.resourceWindow->objectInformation->SetPage("DropZone");
			Check_Object(page);
			page->SetEntry("Model", "Editor\\Waypoints\\DropZone\\DropZone.data");
			DynamicMemoryStream entity_stream;
			ReplicatorID entity_id = ReplicatorID::Null;
			Tool::Instance->ConstructCreateMessage(
				&entity_stream,
				page,
				&entity_id
				);
			
			entity_stream.Rewind();
			entity_id = Connection::Local->GetNextReplicatorID();
			Entity *entity = Entity::CreateEntity(
				&entity_stream,
				&entity_id,
				false
				);
			
			//
			//--------------------------------------------
			//Make some initial assignments for the entity
			//--------------------------------------------
			//
			Check_Object(entity);
			
			EntityManager::Instance->GetNameSocket()->Remove(entity);
			
			entity->instanceName = "DropZone_";
			char string[32];
			entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded,string,10);
			
			//			EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
			theApp.resourceWindow->numEntitiesAdded++;
			
			Map::Instance->AddChild(entity);
			MLRTexturePool::Instance->LoadImages();
			entity->SetPropType(Entity::MissionPropType);
			
			//			CSelectionList::Instance->AddSelection(entity);
			
			EditorDropNode* editorDropNode = Cast_Object(EditorDropNode*,entity);
			
			editorDropNode->SetDropZone(dropZone);
			
			LinearMatrix4D matrix = LinearMatrix4D::Identity;
			Point3D point;
			YawPitchRoll rot;
			point = dropZone->GetLocalToWorld();
			rot = (YawPitchRoll) dropZone->GetLocalToWorld ();
			// make sure drop zone is not below terrain
			Scalar terrain_y = displayWindow->GetMapPointVertical(point.x,point.z);
			if (point.y < terrain_y)
				point.y = terrain_y;
			
			matrix.BuildRotation (rot);
			matrix.BuildTranslation(point);
			
			entity->SetNewLocalToParent(matrix);
			entity->SyncMatrices(true);
			//	EntityManager::Instance->RequestPostCollisionExecution(entity);
			
			ChainIteratorOf<DropZone::MatrixPlug*> zoneIterator(&dropZone->dropMats);
			DropZone::MatrixPlug *drop_point;
			while((drop_point = zoneIterator.ReadAndNext()) != NULL)
			{
				Check_Object(drop_point);
				page = theApp.resourceWindow->objectInformation->SetPage("DropZonePoint");
				Check_Object(page);
				page->SetEntry("Model", "Editor\\Reserved\\DropZonePoint\\DropZonePoint.data");
				DynamicMemoryStream entity_stream;
				ReplicatorID entity_id = ReplicatorID::Null;
				Tool::Instance->ConstructCreateMessage(
					&entity_stream,
					page,
					&entity_id
					);
				
				entity_stream.Rewind();
				entity_id = Connection::Local->GetNextReplicatorID();
				Entity *entity = Entity::CreateEntity(
					&entity_stream,
					&entity_id,
					false
					);
				
				//
				//--------------------------------------------
				//Make some initial assignments for the entity
				//--------------------------------------------
				//
				Check_Object(entity);
				
				EntityManager::Instance->GetNameSocket()->Remove(entity);
				entity->instanceName = "DropZonePoint_";
				char string[32];
				entity->instanceName += itoa(count, string,10);
				
				//				EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
				theApp.resourceWindow->numEntitiesAdded++;
				
				Map::Instance->AddChild(entity);
				MLRTexturePool::Instance->LoadImages();
				entity->SetPropType(Entity::MissionPropType);
				
				EditorDropZonePoint* zonePoint = Cast_Object(EditorDropZonePoint*,entity);
				
				LinearMatrix4D matrix = LinearMatrix4D::Identity;
				matrix = drop_point->GetItem();
				
				entity->SetNewLocalToParent(matrix);
				entity->SyncMatrices(true);
				
				editorDropNode->pointChain.Add(zonePoint);
				zonePoint->dropNode = editorDropNode;
				zonePoint->offset = editorDropNode->GetLocalToWorld();
				zonePoint->offset -=  point;
				
				zonePoint->CreateLink();
				zonePoint->ShowLink(true);
				
				count++;
				//	EntityManager::Instance->RequestPostCollisionExecution(entity);
			}
			editorDropNode->UpdatePoints();
		}
	}
	CSelectionList::Instance->ClearSelectionList();
}

void CMW4GameEdApp::LoadLights()
{
	Check_Object(Mission::Instance);
	
	gosFX::Light* light;
	Entity* entity;
	EditorLight* editorLight;
	
	ChainIteratorOf<gosFX::Light*> iterator(&Mission::Instance->m_staticLights);
	
	while((light = iterator.ReadAndNext()) != NULL)
	{
		switch (light->m_light->GetLightType())
		{
		case MLRLight::AmbientLight:
			entity = theApp.resourceWindow->CreateNewInstance("Content\\Editor\\Waypoints\\AmbientLight\\AmbientLight.data",
				"AmbientLight","AmbientLight");
			break;
		case MLRLight::InfiniteLight:
			entity = theApp.resourceWindow->CreateNewInstance("Content\\Editor\\Waypoints\\InfiniteLight\\InfiniteLight.data",
				"InfiniteLight","InfiniteLight");
			break;
		case MLRLight::PointLight:
			entity = theApp.resourceWindow->CreateNewInstance("Content\\Editor\\Waypoints\\PointLight\\PointLight.data",
				"PointLight","PointLight");
			entity->SetNewLocalToParent(light->m_light->GetLightToWorldMatrix());
			entity->SyncMatrices(true);
			break;
		case MLRLight::SpotLight:
			entity = theApp.resourceWindow->CreateNewInstance("Content\\Editor\\Waypoints\\SpotLight\\SpotLight.data",
				"SpotLight","SpotLight");
			entity->SetNewLocalToParent(light->m_light->GetLightToWorldMatrix());
			entity->SyncMatrices(true);
			break;
		default:
			continue;
		}
		editorLight = Cast_Object(EditorLight*,entity);
		editorLight->instanceName = light->m_light->GetName();
		editorLight->SetLight(light);
	}
	
	char path[MAX_PATH],*p;
	strncpy(path,(LPCTSTR)missionFileName,MAX_PATH - 1);
	p = strrchr(path,'.');
	*p = 0;
	lightFileName = path;
	lightFileName += ".Lights";
	
	audioFileName = path;
	audioFileName += ".audio";
}


void CMW4GameEdApp::LoadCameras()
{
	Check_Object(Map::Instance);
	Check_Object(theApp.resourceWindow->objectInformation);
	Check_Object(Connection::Local);
	Check_Object(EntityManager::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *childEntity;
	
	while((childEntity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(childEntity);
		if (childEntity->IsDerivedFrom(MechWarrior4::CameraShip::DefaultData))
		{
			MechWarrior4::CameraShip* cameraShip;
			cameraShip = Cast_Object(MechWarrior4::CameraShip*,childEntity);
			
			Page *page = theApp.resourceWindow->objectInformation->SetPage("CameraShip");
			Check_Object(page);
			page->SetEntry("Model", "Content\\Editor\\Waypoints\\CameraShip\\CameraShip.data");
			
			
			Check_Object(page);
			DynamicMemoryStream entity_stream;
			ReplicatorID entity_id = ReplicatorID::Null;
			Tool::Instance->ConstructCreateMessage(
				&entity_stream,
				page,
				&entity_id
				);
			
			entity_stream.Rewind();
			entity_id = Connection::Local->GetNextReplicatorID();
			
			Entity *entity = Entity::CreateEntity(
				&entity_stream,
				&entity_id,
				false
				);
			
			//
			//--------------------------------------------
			//Make some initial assignments for the entity
			//--------------------------------------------
			//
			Check_Object(entity);
			
			EntityManager::Instance->GetNameSocket()->Remove(entity);
			
			entity->instanceName = "EditorCameraShip_";
			char string[32];
			entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
			
			
			Map::Instance->AddChild(entity);
			MLRTexturePool::Instance->LoadImages();
			entity->SetPropType(Entity::MissionPropType);
			
			
			EditorCameraShip* editorCameraShip = Cast_Object(EditorCameraShip*,entity);
			
			editorCameraShip->SetCameraShip(cameraShip);
			
			
			LinearMatrix4D matrix(true);
			Point3D point;
			point = cameraShip->GetLocalToWorld();
			// make sure drop zone is not below terrain
			Scalar terrain_y = displayWindow->GetMapPointVertical(point.x,point.z);
			if (point.y < terrain_y)
				point.y = terrain_y;
			
			matrix.BuildTranslation(point);
			
			editorCameraShip->SetNewLocalToParent(matrix);
			editorCameraShip->SyncMatrices(true);
			editorCameraShip->GetElement()->SetVolumeCullMode();
			editorCameraShip->GetElement()->Sync();
			editorCameraShip->cameraShip->SetNewLocalToParent(matrix);
			editorCameraShip->cameraShip->SyncMatrices(true);
			Map::Instance->UpdateZone(editorCameraShip);
			Map::Instance->UpdateZone(cameraShip);
		}
	}
	
	CSelectionList::Instance->ClearSelectionList();
	theApp.MakeObjectsTileBased();
	
}

void CMW4GameEdApp::OnToolsMovementlattice()
{
	m_showLattice = !m_showLattice;
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	if (m_showLattice)
	{
		while((entity = iterator.ReadAndNext()) != NULL)
		{
			if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData))
			{
				entity->GetElement()->SetVolumeCullMode();
				entity->GetElement()->Sync();
			}
		}
	}
	else
	{
		EditorLatticeNode* node;
		while((entity = iterator.ReadAndNext()) != NULL)
		{
			if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData))
			{
				entity->GetElement()->SetAlwaysCullMode();
				entity->GetElement()->Sync();
				
				node = Cast_Object(EditorLatticeNode*,entity);
				node->railNode->ShowRadius(false);
			}
		}
	}
	overviewWindow->DrawWindow();
	instanceWindow->ResetInstanceLists();
}

void CMW4GameEdApp::OnUpdateToolsMovementlattice(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showLattice);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::InitMovementLatticeData()
{
	Check_Object(MW4AI::g_MissionGraph);
	m_NumLinks = MW4AI::g_MissionGraph->NumLinks();
	
	gos_PushCurrentHeap(ElementRenderer::g_Heap);
	
	//	if (LatticeLinkChain.IsEmpty())
	{
		Check_Object(Map::Instance);
		ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
		Entity* entity;
		
		while((entity = iterator.ReadAndNext()) != NULL)
		{
			if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData))
			{
				EditorLatticeNode* node;
				node = Cast_Object(EditorLatticeNode*,entity);
				
				CreateLatticeNodeRadius(node);
			}
		}
	}
	gos_PopCurrentHeap();
}

void CMW4GameEdApp::CreateLatticeNodeRadius(Entity* entity)
{
	EditorLatticeNode* node;
	node = Cast_Object(EditorLatticeNode*,entity);
	
	CreateLatticeNodeRadius(node);
}

void CMW4GameEdApp::CreateLatticeNodeRadius(EditorLatticeNode* node)
{
/*
gos_PushCurrentHeap(ElementRenderer::g_Heap);

  node->railNode->m_RadiusPointCount = 64;
  node->railNode->m_RadiusLineCloud = new ElementRenderer::LineCloudElement(node->railNode->m_RadiusPointCount);
  Check_Object(node->railNode->m_RadiusLineCloud);
  node->railNode->UpdateRadiusPointData();
  node->railNode->SetRadiusColor(Stuff::RGBAColor(192,0,0,0));
  
	node->railNode->m_RadiusLineCloud->SetDataPointers(&node->railNode->m_RadiusPointCount, node->railNode->m_RadiusPointData, node->railNode->m_RadiusColorData);
	node->railNode->m_RadiusLineCloud->localOBB.localToParent = LinearMatrix4D::Identity;
	
	  node->railNode->m_RadiusLineCloud->localOBB.sphereRadius = node->railNode->Radius() + 1;
	  
		Mission::Instance->GetElement()->AttachChild(node->railNode->m_RadiusLineCloud);
		
		  node->railNode->m_RadiusLineCloud->SetName("Line Cloud");
		  
			node->railNode->m_RadiusLineCloud->localOBB.localToParent(3,0) = node->railNode->Location().x;
			node->railNode->m_RadiusLineCloud->localOBB.localToParent(3,1) = node->railNode->Location().y;
			node->railNode->m_RadiusLineCloud->localOBB.localToParent(3,2) = node->railNode->Location().z;
			node->railNode->m_RadiusLineCloud->NeedNewBounds();
			node->railNode->m_RadiusLineCloud->NeedMatrixSync();
			node->railNode->ShowRadius(false);
			node->railNode->m_RadiusLineCloud->Sync();
			
			  gos_PopCurrentHeap();
	*/
}

void CMW4GameEdApp::OnToolsMovmentlayerShowlatticelinks()
{
	m_showLatticeLinks = !m_showLatticeLinks;
	MW4AI::g_MissionGraph->ShowLinks(m_showLatticeLinks);
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowlatticelinks(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showLatticeLinks);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnToolsMovmentlayerRecalclatticelinks()
{
	RECT rect;
	theApp.m_pMainWnd->GetWindowRect(&rect);
	
	// make sure only lattice nodes are selected
	CSelectionNode* selected;
	ChainIteratorOf<CSelectionNode*> iterator(&CSelectionList::Instance->selectionList);
	while (((selected = iterator.ReadAndNext()) != NULL))
	{
		if (!selected->selectedEntity->IsDerivedFrom (EditorLatticeNode::DefaultData))
		{
			CSelectionList::Instance->RemoveSelection(selected->selectedEntity,true);
		}
	}
	int count = CSelectionList::Instance->GetSelectionCount();
	if (count)
	{
		EditorLatticeNode* latticeNode;
		int* nodeIDArray = new int[count],i = 0;
		
		iterator.First();
		while (((selected = iterator.ReadAndNext()) != NULL) && i < count)
		{
			if (selected->selectedEntity->IsDerivedFrom (EditorLatticeNode::DefaultData))
			{
				latticeNode = Cast_Object(EditorLatticeNode*,selected->selectedEntity);
				nodeIDArray[i] = latticeNode->railNode->ID();
			}
			i++;
		}
		RemoveLattice();
		
		if (ProgressDlg)
			delete ProgressDlg;
		
		ProgressDlg = new CProgressDlg(IDS_CALCPROGRESSTITLE);
		ProgressDlg->Create();
		ProgressDlg->ShowWindow(SW_SHOW);
		
		MW4AI::g_MissionGraph->CalcLinks(nodeIDArray,count,MINLINKCALC,MAXLINKCALC,LINKDIST,CalcLinkProgress);
		
		delete ProgressDlg;
		ProgressDlg = NULL;
		
		delete nodeIDArray;
	}
	else
	{
		RemoveLattice();
		
		if (ProgressDlg)
			delete ProgressDlg;
		
		ProgressDlg = new CProgressDlg(IDS_CALCPROGRESSTITLE);
		ProgressDlg->Create();
		ProgressDlg->ShowWindow(SW_SHOW);
		
		MW4AI::g_MissionGraph->CalcLinks(MINLINKCALC,MAXLINKCALC,LINKDIST,CalcLinkProgress);
		
		delete ProgressDlg;
		ProgressDlg = NULL;
	}
	
	LoadLattice();
	//	InitMovementLatticeData();
	
	//	m_showLatticeLinks = false;
	//	OnToolsMovmentlayerShowlatticelinks();
	
	//	m_showRadii = false;
	//	OnToolsMovmentlayerShownoderadii();
}

void CMW4GameEdApp::StopMultiPlace()
{
	if (theApp.m_editorState == CMW4GameEdApp::AddingObjectState ||
		theApp.m_editorState == CMW4GameEdApp::SprayingState)
	{
		CSelectionList::Instance->ClearSelectionList();
		AddCommand *add_command = (AddCommand*)currentCommand;
		add_command->Undo();
		
		m_editorState = CMW4GameEdApp::SelectingObjectState;
		m_MultiDrop = false;
		theApp.m_CurPath = NULL;
		theApp.resourceWindow->TLDlg->m_ObjList.EnableWindow();
		theApp.instanceWindow->TLDlg->m_ObjList.EnableWindow();
	}
}



void CMW4GameEdApp::OnToolsMovmentlayerShowall()
{
	if (m_showLattice && m_showLatticeLinks && m_showRadii && m_showPaths)
		m_showLattice = m_showLatticeLinks = m_showRadii = m_showPaths = true;
	else
		m_showLattice = m_showLatticeLinks = m_showRadii = m_showPaths = false;
	
	OnToolsMovementlattice();
	OnToolsMovmentlayerShowlatticelinks();
	OnToolsMovmentlayerShownoderadii();
	OnToolsMovmentlayerShowpaths();
}

void CMW4GameEdApp::OnToolsMovmentlayerShownoderadii()
{
	m_showRadii = !m_showRadii;
	MW4AI::g_MissionGraph->ShowRadius(m_showRadii);
}

void CMW4GameEdApp::OnToolsMovmentlayerShowpaths()
{
	m_showPaths = !m_showPaths;
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	EditorPathNode* path;
	Entity *entity;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorPathNode::DefaultData))
		{
			path = Cast_Object(EditorPathNode*,entity);
			path->ShowLink(m_showPaths);
			if (m_showPaths)
				entity->GetElement()->SetVolumeCullMode();
			else
				entity->GetElement()->SetAlwaysCullMode();
			
			entity->GetElement()->Sync();
		}
	}
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowall(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showLattice && m_showLatticeLinks && m_showRadii && m_showPaths);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShownoderadii(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showRadii);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowpaths(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showPaths);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnToolsMechlab()
{
	StopMultiPlace();
	CMenu* m = theApp.m_pMainWnd->GetMenu();
	for (int i = 0; i < m->GetMenuItemCount(); i++)
	{
		m->EnableMenuItem(i,MF_GRAYED | MF_BYPOSITION);
	}
	m_pMainWnd->DrawMenuBar();
	resourceWindow->TLDlg->m_ObjList.EnableWindow(FALSE);
	instanceWindow->TLDlg->m_ObjList.EnableWindow(FALSE);
	resourceWindow->EnableWindow(FALSE);
	instanceWindow->EnableWindow(FALSE);
	overviewWindow->EnableWindow(FALSE);
	
	displayWindow->GetFocus();
	
	m_MechLabActive = true;
	
	MechLab	ml;
	
	ml.StartUp();
	//	ml.Execute();
	ml.ShutDown();
	
	for (i = 0; i < m->GetMenuItemCount(); i++)
	{
		m->EnableMenuItem(i,MF_ENABLED | MF_BYPOSITION);
	}
	m_pMainWnd->DrawMenuBar();
	resourceWindow->TLDlg->m_ObjList.EnableWindow(TRUE);
	instanceWindow->TLDlg->m_ObjList.EnableWindow(TRUE);
	resourceWindow->EnableWindow(TRUE);
	instanceWindow->EnableWindow(TRUE);
	overviewWindow->EnableWindow(TRUE);
	m_MechLabActive = false;
}

void CMW4GameEdApp::OnToolsMovmentlayerShowmissionboundary()
{
	m_showBoundary = !m_showBoundary;
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	EditorBoundaryNode* node;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorBoundaryNode::DefaultData))
		{
			if (m_showBoundary)
				entity->GetElement()->SetVolumeCullMode();
			else
				entity->GetElement()->SetAlwaysCullMode();
			
			entity->GetElement()->Sync();
			
			node = Cast_Object(EditorBoundaryNode*, entity);
			node->ShowLink(m_showBoundary);
		}
	}
	overviewWindow->DrawWindow();
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowmissionboundary(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showBoundary);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::VerifyObjectPlacement(bool feedback)		// Localize!!!
{
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	bool error = false;
	char string[256];
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->GetSolidVolume() == NULL)
			continue;
		
		if (entity->IsMultiZone())
		{
			error = true;
			sprintf(string,"%s, is placed on multiple Zones.  This is illegal.",(char*)entity->instanceName);
			if (MessageBox(NULL,string,"MultiZone Entity",MB_OKCANCEL) == IDCANCEL)
				return;
		}
		else if (entity->IsMultiTile())
		{
			error = true;
			sprintf(string,"%s, is placed on multiple Tiles.  This is not recommended.",(char*)entity->instanceName);
			if (MessageBox(NULL,string,"MultiTile Entity",MB_OKCANCEL) == IDCANCEL)
				return;
		}
	}
	if (feedback && !error)
		MessageBox(NULL,"Object placement verification complete. No misplaced objects.","Verification Results",MB_OK);
}

void CMW4GameEdApp::OnToolsVerifyobjectplacement()
{
	StopMultiPlace();
	VerifyObjectPlacement(true);
}

void CMW4GameEdApp::OnToolsMovmentlayerShowdropzones()
{
	m_showDropZones = !m_showDropZones;
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorDropNode::DefaultData) ||
			entity->IsDerivedFrom(EditorDropZonePoint::DefaultData))
		{
			if (m_showDropZones)
				entity->GetElement()->SetVolumeCullMode();
			else
				entity->GetElement()->SetAlwaysCullMode();
			
			entity->GetElement()->Sync();
		}
	}
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowdropzones(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showDropZones);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnToolsEditmissionscript()
{
	StopMultiPlace();
	if (!instanceWindow->scriptWnd)
	{
		instanceWindow->scriptWnd = new CEditWnd();
		RECT r;
		r.left = 50;
		r.top = 50;
		r.right = 690;
		r.bottom = 530;
		instanceWindow->scriptWnd->Create(NULL,"Mission Script",NULL,r);
	}
	
	char ssPath[MAX_PATH],oldDir[MAX_PATH],dir[MAX_PATH],*p;
	_getcwd(oldDir,MAX_PATH - 1);
	
	if (m_ScriptName)
		strcpy(ssPath,(char*)LPCTSTR(m_ScriptName));
	else
	{
		OnToolsSpecifymissionscript();
		
		if (m_ScriptName)
		{
			strcpy(ssPath,(char*)LPCTSTR(m_ScriptName));
		}
		else
		{
			_chdir(oldDir);
			_chdir(dir);
			p = __mbsrchr(dir,'\\');
			*p = 0;
			p = __mbsrchr(dir,'\\') + 1;
			sprintf(ssPath,"%s\\%s.abl",dir,p);
		}
	}
	
	instanceWindow->scriptWnd->LoadFile(ssPath);
	instanceWindow->scriptWnd->SetWindowText("Mission Script");
	instanceWindow->scriptWnd->ShowWindow(SW_SHOW);
	instanceWindow->scriptWnd->SetWindowPos (&instanceWindow->wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
	instanceWindow->scriptWnd->CloseCallback = EditMissionScriptCallback;
	_chdir(oldDir);
}

void CMW4GameEdApp::OnToolsMovmentlayerShowobjectives()
{
	m_showAI = !m_showAI;
	
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorDropNode::DefaultData) ||
			entity->IsDerivedFrom(EditorDropZonePoint::DefaultData))
		{
			if (m_showAI)
				entity->GetElement()->SetVolumeCullMode();
			else
				entity->GetElement()->SetAlwaysCullMode();
			
			entity->GetElement()->Sync();
		}
	}
}

void CMW4GameEdApp::OnUpdateToolsMovmentlayerShowobjectives(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_showAI);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}


void CMW4GameEdApp::OnViewShowtileborders()
{
	m_showTileBorder = !m_showTileBorder;
	
	if (m_showTileBorder)
	{
		Compost::TerrainTextureLogistic::Instance->TurnOnBorder(RGBAColor(1.0f,0.0f,0.0f,0.0f));
		
	}
	else
	{
		Compost::TerrainTextureLogistic::Instance->TurnOffBorder();
	}
}

void CMW4GameEdApp::OnUpdateViewShowtileborders(CCmdUI* pCmdUI)
{
	if (theApp.m_editorState == CMW4GameEdApp::NoGameIdleState)
		pCmdUI->Enable(FALSE);
	else
	{
		pCmdUI->Enable();
		pCmdUI->SetCheck(m_showTileBorder);
	}
}

BOOL CMW4GameEdApp::PreTranslateMessage(MSG* pMsg)
{
	// CG: The following lines were added by the Splash Screen component.
	if (CSplashWnd::PreTranslateAppMessage(pMsg))
		return TRUE;
	
	return CWinApp::PreTranslateMessage(pMsg);
}

void CMW4GameEdApp::OnToolsSpecifymissionscript()
{
	StopMultiPlace();
	OPENFILENAME ofn;
	char dir[MAX_PATH],oldDir[MAX_PATH],ssPath[MAX_PATH];
	
	strcpy(dir,missionFileName);
	char* p = __mbsrchr(dir,'\\') + 1;
	*p = 0;
	
	_getcwd(oldDir,MAX_PATH - 1);
	_chdir(dir);
	
	memset(&ssPath,0,MAX_PATH);
	memset(&ofn,0,sizeof(ofn));
	
	MWMission *mission = Cast_Object (MWMission *,Mission::Instance);
	if (mission->scriptName)
	{
		char *p,tmp[MAX_PATH];
		strncpy(tmp,mission->scriptName,MAX_PATH);
		p = __mbsrchr(tmp,'\\');
		if (p)
			strncpy(ssPath,++p,MAX_PATH);
	}
	
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = NULL;
	ofn.lpstrFilter = "ABL Scripts {*.abl}\0*.abl\0All Files {*.*}\0*.*\0\0";
	ofn.lpstrFile = ssPath;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_FILEMUSTEXIST;
	ofn.lpstrDefExt = "subsystems";
	
	if (GetOpenFileName(&ofn))
	{
		_chdir(oldDir);
		_chdir(dir);
		
		char path[MAX_PATH],cmpPath[MAX_PATH],misPath[MAX_PATH];
		
		strcpy(path,missionFileName);
		strcpy(cmpPath,ofn.lpstrFile);
		
		p = strrchr(path,'.');
		if (p) *p = 0;
		p = __mbsrchr(path,'\\');
		if (p) *p = 0;
		
		p = strrchr(cmpPath,'.');
		if (p) *p = 0;
		p = __mbsrchr(cmpPath,'\\');
		if (p) *p = 0;
		p = strstr(cmpPath,"Content");
		sprintf (misPath,"%s",path);
		
		if (strcmp(path,p) != 0)
		{
			strcpy(ssPath,ofn.lpstrFile);
			p = __mbsrchr(ssPath,'\\') + 1;
			sprintf(path,"%s",p);
			
			if (!CopyFile(ofn.lpstrFile,path,TRUE))
			{
				DWORD err = GetLastError();
				if (err == 80)	// file exists
				{
					if (MessageBox(NULL,"A file of that name already exists in the mission script folder.  Do you wish to overwrite that file?","File Error",MB_YESNO) == IDYES)
						CopyFile(ofn.lpstrFile,ssPath,FALSE);
				}
				else
				{
					sprintf(dir,"Could not copy ABL file to current mission folder. Error %d",err);
					MessageBox(NULL,dir,"File Error",MB_OK);	// localize
					_chdir(oldDir);
					return;
				}
			}
			if (!SetFileAttributes(ssPath,FILE_ATTRIBUTE_NORMAL))
			{
				DWORD err = GetLastError();
				sprintf(dir,"Could not clear readonly flag on ABL file in current mission folder, please do so yourself. Error %d",err);
				MessageBox(NULL,dir,"File Error",MB_OK);	// localize
				_chdir(oldDir);
				return;
			}
		}
		m_ScriptName = __mbsrchr(ofn.lpstrFile,'\\') + 1;
		sprintf (mission->scriptName,"%s\\%s",misPath,(char*)LPCTSTR(m_ScriptName));
		m_ScriptName = mission->scriptName;
		//		strcpy(mission->scriptName,(char*)LPCTSTR(m_ScriptName));
	}
	_chdir(oldDir);
}

void CMW4GameEdApp::OnToolsCheckscripts()
{
	Check_Object(Map::Instance);
	//	Entity *entity;
	
	MWMission *mission = Cast_Object (MWMission *,Mission::Instance);
	mission->UnloadScript ();
	
	MWMap *inst;
	AI *ai;
	inst = Cast_Object (MWMap *,Map::Instance);
	ChainIteratorOf<AI *> iterator2(&inst->m_executingAIs);
	iterator2.First ();
	while((ai = iterator2.ReadAndNext()) != NULL)
	{
		Check_Object(ai);
		
		ai->UnloadScript ();
	}
	
	ABL::ABLError error;
	CString errstr;
	CString filename;
	CString cmdline,line;
	char errMessage[500];
	
	if (!mission->ReloadABL (&error))
	{
		sprintf(errMessage, "SYNTAX ERROR %s [line %d] - (type %d) %s\n", error.File (), error.Line (),error.Code (), error.String ());
		
		MessageBox (NULL,errMessage,"ABL Error",MB_OK);
		
		filename = error.File ();
		
		//		cmdline = "c:\\vslick\\win\\vs ";
		cmdline = "vs ";
		cmdline += "\"";
		_getcwd (errMessage,500);
		if (filename[1] != ':')
		{
			cmdline += errMessage;
			cmdline += "\\";
		}
		cmdline += filename;
		cmdline += "\"";
		cmdline += " -#";
		itoa (error.Line (),errMessage,10);
		cmdline += errMessage;	
		
		//		system ((LPCTSTR) cmdline);
		if (WinExec ((LPCTSTR) cmdline,SW_SHOW) <= 31)			// old function but it works
			MessageBox (NULL,"Unable to start slickedit, make sure it's in your path","error",MB_OK);
		//		CreateProcess (NULL,cmdline,NULL,NULL,FALSE,0,NULL,NULL,NULL,NULL);
		return;
	}
	
	if (!mission->ReloadScript (&error))
	{
		sprintf(errMessage, "SYNTAX ERROR %s [line %d] - (type %d) %s\n", error.File (), error.Line (),error.Code (), error.String ());
		
		MessageBox (NULL,errMessage,"ABL Error",MB_OK);
		
		filename = error.File ();
		
		//		cmdline = "c:\\vslick\\win\\vs ";
		cmdline = "vs ";
		cmdline += "\"";
		_getcwd (errMessage,500);
		if (filename[1] != ':')
		{
			cmdline += errMessage;
			cmdline += "\\";
		}
		cmdline += filename;
		cmdline += "\"";
		cmdline += " -#";
		itoa (error.Line (),errMessage,10);
		cmdline += errMessage;	
		
		//		system ((LPCTSTR) cmdline);
		if (WinExec ((LPCTSTR) cmdline,SW_SHOW) <= 31)			// old function but it works
			MessageBox (NULL,"Unable to start slickedit, make sure it's in your path","error",MB_OK);
		//		CreateProcess (NULL,cmdline,NULL,NULL,FALSE,0,NULL,NULL,NULL,NULL);
		return;
	}
	iterator2.First ();
	while((ai = iterator2.ReadAndNext()) != NULL)
	{
		{
			
			if (!ai->ReloadScript (&error))
			{
				sprintf(errMessage, "SYNTAX ERROR %s [line %d] - (type %d) %s\n", error.File (), error.Line (),error.Code (), error.String ());
				
				MessageBox (NULL,errMessage,"ABL Error",MB_OK);
				
				filename = error.File ();
				
				cmdline = "vs ";
				//				cmdline = "c:\\vslick\\win\\vs ";
				cmdline += "\"";
				_getcwd (errMessage,500);
				if (filename[1] != ':')
				{
					cmdline += errMessage;
					cmdline += "\\";
				}
				cmdline += filename;
				cmdline += "\"";
				cmdline += " -#";
				itoa (error.Line (),errMessage,10);
				cmdline += errMessage;	
				
				//		system ((LPCTSTR) cmdline);
				if (WinExec ((LPCTSTR) cmdline,SW_SHOW) <= 31)			// old function but it works
					MessageBox (NULL,"Unable to start slickedit, make sure it's in your path","error",MB_OK);
				//		CreateProcess (NULL,cmdline,NULL,NULL,FALSE,0,NULL,NULL,NULL,NULL);
				return;
			}
		}
	}
}

void CMW4GameEdApp::CreateLightDlg()
{
	if (!lightDlg)
	{
		lightDlg = new CLightWnd;
		Register_Pointer(lightDlg);
		lightDlg->Create(IDD_LIGHTDLG);
	}
}

void CMW4GameEdApp::OnToolsMovmentlayerCreatelattice()
{
	if (MessageBox(NULL,"This action will remove all currently existing lattice node and links.  This action cannot be undone.  Are you sure you want to continue?","Create Movement Lattice Confirm",MB_ICONQUESTION | MB_YESNO) == IDNO)
		return;
	
	RemoveLattice();
	
	if (ProgressDlg)
		delete ProgressDlg;
	
	ProgressDlg = new CProgressDlg(IDS_CREATERECTSPROGRESSTITLE);
	ProgressDlg->Create();
	ProgressDlg->ShowWindow(SW_SHOW);
	
	MW4AI::g_MissionGraph->CreateBasicNodes(theApp.overviewWindow->mapHeight * theApp.overviewWindow->mapWidth / 10000,CalcLinkProgress);
	
	delete ProgressDlg;
	ProgressDlg = NULL;
	
	LoadLattice();
	
	m_showLattice = false;
	OnToolsMovementlattice();
	
	m_showLatticeLinks = false;
	OnToolsMovmentlayerShowlatticelinks();
	
	m_showRadii = false;
	OnToolsMovmentlayerShownoderadii();
}

void CMW4GameEdApp::OnToolsMovmentlayerCreateRects()
{
	if (ProgressDlg)
		delete ProgressDlg;
	
	ProgressDlg = new CProgressDlg(IDS_CREATELATTICEPROGRESSTITLE);
	ProgressDlg->Create();
	ProgressDlg->ShowWindow(SW_SHOW);
	
	MW4AI::g_MissionGraph->CreateRectData(CalcLinkProgress);
	
	delete ProgressDlg;
	ProgressDlg = NULL;
}

void CMW4GameEdApp::OnToolsMissionparametersEditfog()
{
	if (!fogDlg)
	{
		fogDlg = new FogDlg;
		Register_Pointer(fogDlg);
		fogDlg->Create(IDD_FOGDLG);
	}
	fogDlg->ShowWindow(SW_SHOW);
}

void CMW4GameEdApp::OnUpdateToolsCameraspeedFast(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraSpeed == 16);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnUpdateToolsCameraspeedRegular(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraSpeed == 4);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

void CMW4GameEdApp::OnUpdateToolsCameraspeedSlow(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(cameraSpeed == 1);
	pCmdUI->Enable(MWApplication::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState);
	
}

bool CMW4GameEdApp::SaveAudioFile(char *fname)
{
	//
	// Need to fill this in with the right data to support audio files
	// Currently the editor does not have a way to edit the .audio files.
	// TODO
	//
	if (fname)
	{
		audioFileName = fname;
	}
	
	return TRUE;
}

bool CMW4GameEdApp::SaveLightFile(char* fname)
{
	Check_Object(Map::Instance);
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity*			entity;
	EditorLight*	editorLight;
	
	if (fname)
	{
		lightFileName = fname;
	}
	
	NotationFile*	dataFile = new NotationFile(LPCTSTR(lightFileName));
	DWORD result = GetFileAttributes(LPCTSTR(lightFileName));
	
	if (result == -1)
		CloseHandle(CreateFile(LPCTSTR(lightFileName),0,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL));
	else if (result & FILE_ATTRIBUTE_READONLY)	// is it marked READONLY?
	{
		MessageBox(NULL,"Unable to save file becuase some of the data files are marked READONLY","Save Error",MB_OK);
		return false;
	}
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom(EditorLight::DefaultData))
		{
			editorLight = Cast_Object(EditorLight*, entity);
			Page *page = dataFile->SetPage((char*)entity->instanceName);
			Check_Object(page);
			editorLight->light->m_light->Write(page);
		}
	}
	
	dataFile->Save();
	delete dataFile;
	
	return true;
}

void CMW4GameEdApp::LoadObjectives()
{
	Check_Object(Map::Instance);
	Check_Object(theApp.resourceWindow->objectInformation);
	Check_Object(Connection::Local);
	Check_Object(EntityManager::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *childEntity;
	
	while((childEntity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(childEntity);
		if (childEntity->IsDerivedFrom(MechWarrior4::Objective::DefaultData))
		{
			MechWarrior4::Objective* obj;
			obj = Cast_Object(MechWarrior4::Objective*,childEntity);
			
			Page *page = theApp.resourceWindow->objectInformation->SetPage("Content\\Editor\\Waypoints\\ObjectiveMarker\\ObjectiveMarker.data");
			Check_Object(page);
			page->SetEntry("ObjectiveMarker", "ObjectiveMarker");
			page = theApp.resourceWindow->objectInformation->GetPage("ObjectiveMarker");
			Check_Object(page);
			DynamicMemoryStream entity_stream;
			ReplicatorID entity_id = ReplicatorID::Null;
			Tool::Instance->ConstructCreateMessage(
				&entity_stream,
				page,
				&entity_id
				);
			
			entity_stream.Rewind();
			entity_id = Connection::Local->GetNextReplicatorID();
			Entity *entity = Entity::CreateEntity(
				&entity_stream,
				&entity_id,
				false
				);
			
			//
			//--------------------------------------------
			//Make some initial assignments for the entity
			//--------------------------------------------
			//
			Check_Object(entity);
			
			Map::Instance->AddChild(entity);
			MLRTexturePool::Instance->LoadImages();
			entity->SetPropType(Entity::MissionPropType);
			entity->instanceName = "EditorObjectiveMarker_";
			char string[32];
			entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded++,string,10);
			
			EditorObjectiveMarker* objMarker;
			objMarker = Cast_Object(EditorObjectiveMarker*, entity);
			
			objMarker->objective = obj;
			objMarker->GetElement()->SetAlwaysCullMode();
			objMarker->GetElement()->Sync();
			
			Map::Instance->UpdateZone(objMarker);
		}
	}
	CSelectionList::Instance->ClearSelectionList();
}

void CMW4GameEdApp::OnToolsSnapobjectstoterrain()
{
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	Point3D point;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		LinearMatrix4D matrix(true);
		Point3D target_in_world;
		
		matrix=entity->GetLocalToParent();
		point = entity->GetLocalToWorld();
		point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z,Entity::CanBeWalkedOnFlag,entity);
		//		point.y= GetMapY(point.x,point.z);
		CEditorEntityData *exdata=theApp.GetEntityData(entity);
		Verify(exdata);
		point.y+=exdata->VOffset;
		
		matrix.BuildTranslation(point);
		entity->SetNewLocalToParent(matrix);
		entity->SyncMatrices(true);
		
		target_in_world = entity->GetLocalToWorld();
		
		if (entity->IsDerivedFrom(EditorPathNode::DefaultData))
		{
			EditorPathNode* node;
			node = Cast_Object(EditorPathNode*,entity);
			node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[node->index] = target_in_world;
			node->UpdateLinkPointData();
		}
		else if (entity->IsDerivedFrom(EditorBoundaryNode::DefaultData))
		{
			EditorBoundaryNode* node;
			node = Cast_Object(EditorBoundaryNode*,entity);
			theApp.missionBoundary[node->index].x = target_in_world.x;
			theApp.missionBoundary[node->index].y = target_in_world.z;
			node->UpdateLinkPointData();
		}
		else if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData))
		{
			EditorLatticeNode* node;
			node = Cast_Object(EditorLatticeNode*,entity);
			node->railNode->Location(target_in_world);
			node->railNode->UpdateRadiusPointData();
		}
		
	}
}

CEditorEntityData *
CMW4GameEdApp::GetEntityData(Entity *entity)

{
	int i;
	int lastspot=m_ExtraDataList.GetLength();
	
	for(i=0;i<lastspot;i++)
	{
		if(m_ExtraDataList[i]->entity==entity) return m_ExtraDataList[i];
	}
	
	CEditorEntityData *tmpdat=new CEditorEntityData;
	Register_Pointer(tmpdat);
	tmpdat->entity=entity;
	m_ExtraDataList.SetLength(lastspot+1);
	m_ExtraDataList[lastspot]=tmpdat;
	
	return tmpdat;
}


//
// These two functions are to allow hot keys for setting/recalling camera positions
// They are currently setup for Ctrl-0 thru Ctrl-9 to set and 0 - 9 to recall.
//
void CMW4GameEdApp::OnSetNumberedCameraPosition (UINT nID)
{
	ASSERT(nID >= ID_SET_CAMERA_POS_0);
	ASSERT(nID <= ID_SET_CAMERA_POS_9);
	if (nID > ID_SET_CAMERA_POS_9 || nID < ID_SET_CAMERA_POS_0)
		return;
	// Since we do math on these they have to be sequential
	ASSERT(
        (ID_SET_CAMERA_POS_0 == (ID_SET_CAMERA_POS_1 - 1)) &&
        (ID_SET_CAMERA_POS_1 == (ID_SET_CAMERA_POS_2 - 1)) &&
        (ID_SET_CAMERA_POS_2 == (ID_SET_CAMERA_POS_3 - 1)) &&
        (ID_SET_CAMERA_POS_3 == (ID_SET_CAMERA_POS_4 - 1)) &&
        (ID_SET_CAMERA_POS_4 == (ID_SET_CAMERA_POS_5 - 1)) &&
        (ID_SET_CAMERA_POS_5 == (ID_SET_CAMERA_POS_6 - 1)) &&
        (ID_SET_CAMERA_POS_6 == (ID_SET_CAMERA_POS_7 - 1)) &&
        (ID_SET_CAMERA_POS_7 == (ID_SET_CAMERA_POS_8 - 1)) &&
        (ID_SET_CAMERA_POS_8 == (ID_SET_CAMERA_POS_9 - 1)));
	
	m_4DCameraBookmark[nID - ID_SET_CAMERA_POS_0] = Player::Instance->GetLocalToWorld();
	
}

void CMW4GameEdApp::OnGotoNumberedCameraPosition(UINT nID)
{
	ASSERT(nID >= ID_GOTO_CAMERA_POS_0);
	ASSERT(nID <= ID_GOTO_CAMERA_POS_9);
	if (nID > ID_GOTO_CAMERA_POS_9 || nID < ID_GOTO_CAMERA_POS_0)
		return;
	// Since we do math on these they have to be sequential
	ASSERT(
        (ID_GOTO_CAMERA_POS_0 == (ID_GOTO_CAMERA_POS_1 - 1)) &&
        (ID_GOTO_CAMERA_POS_1 == (ID_GOTO_CAMERA_POS_2 - 1)) &&
        (ID_GOTO_CAMERA_POS_2 == (ID_GOTO_CAMERA_POS_3 - 1)) &&
        (ID_GOTO_CAMERA_POS_3 == (ID_GOTO_CAMERA_POS_4 - 1)) &&
        (ID_GOTO_CAMERA_POS_4 == (ID_GOTO_CAMERA_POS_5 - 1)) &&
        (ID_GOTO_CAMERA_POS_5 == (ID_GOTO_CAMERA_POS_6 - 1)) &&
        (ID_GOTO_CAMERA_POS_6 == (ID_GOTO_CAMERA_POS_7 - 1)) &&
        (ID_GOTO_CAMERA_POS_7 == (ID_GOTO_CAMERA_POS_8 - 1)) &&
        (ID_GOTO_CAMERA_POS_8 == (ID_GOTO_CAMERA_POS_9 - 1)));
	
	Point3D newCameraPosition;
	YawPitchRoll newCameraOrientation;
	
	newCameraOrientation = m_4DCameraBookmark[nID - ID_GOTO_CAMERA_POS_0];
	newCameraPosition = m_4DCameraBookmark[nID - ID_GOTO_CAMERA_POS_0];
	
	if (newCameraPosition.x < -(theApp.displayWindow->mapX*0.5f))
		newCameraPosition.x = -(theApp.displayWindow->mapX*0.5f)+1.0f;
	else if (newCameraPosition.x > (theApp.displayWindow->mapX*0.5f))
		newCameraPosition.x = (theApp.displayWindow->mapX*0.5f) - 1.0f;
	
	if (newCameraPosition.z < -(theApp.displayWindow->mapZ*0.5f))
		newCameraPosition.z =  -(theApp.displayWindow->mapZ*0.5f)+1.0f;
	else if (newCameraPosition.z >  (theApp.displayWindow->mapZ*0.5f))
		newCameraPosition.z =  (theApp.displayWindow->mapZ*0.5f) - 1.0f;
	
	m_4DCameraBookmark[nID - ID_GOTO_CAMERA_POS_0].BuildTranslation(newCameraPosition);
	m_4DCameraBookmark[nID - ID_GOTO_CAMERA_POS_0].BuildRotation(newCameraOrientation);
	
	Player::Instance->SetNewLocalToParent(m_4DCameraBookmark[nID - ID_GOTO_CAMERA_POS_0]);
	Player::Instance->SyncMatrices(true);
	theApp.overviewWindow->DrawWindow();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CMW4GameEdApp::UpdateCameraMenus(int index)
{
	CString strFormatString, strMenuString;
	strFormatString.LoadString(IDS_CAMERA_NAME_FORMAT);
	
	HMENU hMenu = GetMenu(theApp.m_pMainWnd->GetSafeHwnd());
	ASSERT(hMenu);
	
	if (hMenu)
	{
		
		//
		// If this assert goes off, you have to make sure that the call to GetSubMenu below has the proper position for the
		// tools menu
		//
		ASSERT(GetMenuItemCount(hMenu) == 6);
		HMENU hMenuTools = GetSubMenu(hMenu, APP_MENU_TOOLS);
		ASSERT(hMenuTools);
		if (hMenuTools)
		{
			//
			// If this assert goes off change the nPosition parameter below to point to the CameraSavedPositions item in the menu
			// Don't forget separators
			ASSERT(GetMenuItemCount(hMenuTools) == 18);
			HMENU hMenuCameraPositions = GetSubMenu(hMenuTools, TOOLS_MENU_CAMERA_POSITIONS);
			ASSERT(hMenuCameraPositions);
			ASSERT(GetMenuItemCount(hMenuCameraPositions)== 3);
			HMENU hMenuSave, hMenuGoto, hMenuName;
			hMenuGoto = GetSubMenu(hMenuCameraPositions, 0);
			hMenuSave = GetSubMenu(hMenuCameraPositions, 1);
			hMenuName = GetSubMenu(hMenuCameraPositions, 2);
			ASSERT(hMenuName && hMenuSave && hMenuName);
			if (hMenuGoto && hMenuSave && hMenuName)
			{
				int i = 0;
				// See if we are doing the whole list (index == -1) or just a single one
				ASSERT(index >= -1 && index <= 9);
				if (index >= 0)
				{
					i = index;  // count from index and only do one
					index++;
				}
				else
				{
					index = 10; // count from 0 to 9
				}
				//
				// Now change the camera menus that are displayed in order to make them more usable
				//
				for (; i < index; i++) // index is now the max slot to count to
				{
					strMenuString.Format((LPCSTR) strFormatString, i, m_DefCameraName[i]);
					
					ModifyMenu(hMenuSave, ID_SET_CAMERA_POS_0 + i,  MF_BYCOMMAND | MF_STRING ,ID_SET_CAMERA_POS_0 + i,  (LPCSTR) strMenuString);
					ModifyMenu(hMenuGoto, ID_GOTO_CAMERA_POS_0 + i, MF_BYCOMMAND | MF_STRING ,ID_GOTO_CAMERA_POS_0 + i,  (LPCSTR) strMenuString);
					ModifyMenu(hMenuName, ID_NAME_CAMERA_POS_0 + i, MF_BYCOMMAND | MF_STRING ,ID_NAME_CAMERA_POS_0 + i,  (LPCSTR) strMenuString);
				}
				if (theApp.m_pMainWnd)
					theApp.m_pMainWnd->DrawMenuBar();
			}
		}
	}
	
}


void CMW4GameEdApp::FixPaths()
{
	
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Adept::Entity *entity;
	
	Point3D target_in_world;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		
		target_in_world = entity->GetLocalToWorld();
		
		if (entity->IsDerivedFrom(EditorPathNode::DefaultData))
		{
			EditorPathNode* node;
			node = Cast_Object(EditorPathNode*,entity);
			node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[node->index] = target_in_world;
			node->UpdateLinkPointData();
		}
		else if (entity->IsDerivedFrom(EditorBoundaryNode::DefaultData))
		{
			EditorBoundaryNode* node;
			node = Cast_Object(EditorBoundaryNode*,entity);
			theApp.missionBoundary[node->index].x = target_in_world.x;
			theApp.missionBoundary[node->index].y = target_in_world.z;
			node->UpdateLinkPointData();
		}
		
	}
	
}

void CMW4GameEdApp::MakeObjectsTileBased()
{
	
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Adept::Entity *entity;
	
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		if (entity->IsDerivedFrom(Building::DefaultData) || 
			entity->IsDerivedFrom(Turret::DefaultData) ||
			entity->IsDerivedFrom(Cultural::DefaultData) )			
		{
			if(entity->IsDerivedFrom(Cultural::DefaultData) || !entity->IsMultiTile() )
			{
				entity->BindToTile();
			}
		}
	}
	
}

void CMW4GameEdApp::DeleteBoundaryNodes()
{
	
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Adept::Entity *entity;
	
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		if (entity->IsDerivedFrom(EditorBoundaryNode::DefaultData))
		{
			Map::Instance->RemoveChild(entity);
			NameTable::Instance->RemoveEntry(entity->objectID);
		NameTable::Instance->IsValid();
			delete Cast_Object(Stuff::Plug *, entity);
		}
	}
	
}


void CMW4GameEdApp::MakeObjectsZoneBased()
{
	Check_Object(Map::Instance);
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Adept::Entity *entity;
	
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		
		if (entity->IsDerivedFrom(Building::DefaultData) || 
			entity->IsDerivedFrom(Turret::DefaultData) ||
			entity->IsDerivedFrom(Cultural::DefaultData)
			)
		{
			entity->BindToZone();
		}
	}
	
}

void CMW4GameEdApp::OnEditPaste()
{
	
	StopMultiPlace();
	
	Stuff::NotationFile clipboard("Content\\MW4Editor.clipboard");
	
	Stuff::NotationFile::PageIterator *pageit=clipboard.MakePageIterator();
	Stuff::Page *page;
	
	CSelectionList::Instance->ClearSelectionList();
	
	while((page=pageit->ReadAndNext())!=NULL)
	{
		Stuff::DynamicMemoryStream stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		
		FileDependencies dummy;
		FileDependencies *parent = Resource::ParentFileDependencies;
		Resource::ParentFileDependencies = &dummy;
		
		Tool::Instance->ConstructCreateMessage(&stream,page,&entity_id);
		stream.Rewind();
		
		Entity::CreateMessage *message = Cast_Pointer(Entity::CreateMessage *, stream.GetPointer());
		int array_index = NameTable::DefaultArray;
		page->GetEntry("ArrayIndex", &array_index);	
		MString namestr(page->GetName());
		MakeNameUnique(&namestr);
		message->nameID = NameTable::Instance->AddEntry(namestr, array_index);
		NameTable::Instance->IsValid();
		entity_id = Connection::Local->GetNextReplicatorID();
		
		Entity *entity = Entity::CreateEntity(
			&stream,
			&entity_id,
			false
			);
		Check_Object(entity);
		
		
		Check_Object(EntityManager::Instance);
		EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
		
		
		entity->SetPropType(Entity::MissionPropType);
		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		
		Resource::ParentFileDependencies = parent;
		CSelectionList::Instance->AddSelection(entity);
		
	}
	theApp.instanceWindow->ResetInstanceLists();
}

void CMW4GameEdApp::OnEditCopy()
{
	
	StopMultiPlace();
	Stuff::NotationFile clipboard("Content\\MW4Editor.clipboard");
	clipboard.DeleteAllPages();
	
	CSelectionNode* selected;
	ChainIteratorOf<CSelectionNode*> selections(&CSelectionList::Instance->selectionList);
	
	while ((selected = selections.ReadAndNext()) != NULL)
	{
		if (!(selected->IsDerivedFrom(EditorWaypoint::DefaultData) ||
			selected->IsDerivedFrom(EditorPathNode::DefaultData) ||
			selected->IsDerivedFrom(EditorLatticeNode::DefaultData)))
		{
			Page *page=clipboard.AddPage(selected->selectedEntity->instanceName);
			selected->selectedEntity->SaveInstanceText(page);
			page->SetEntry("ArrayIndex", NameTableEntry::GetArrayIndex(selected->selectedEntity->objectID));
		}
	}
	theApp.toolBar->EnableButton(ID_EDIT_PASTE);
	
	clipboard.Save();
}

void CMW4GameEdApp::OnEditCut()
{
	OnEditCopy();
	theApp.instanceWindow->OnObjRemoveinstance();
	
}


void CMW4GameEdApp::MakeObjectNamesUnique()
{
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		
		
		if(		entity->IsDerivedFrom(Vehicle::DefaultData)	||
			entity->IsDerivedFrom(Building::DefaultData)	||	
			entity->IsDerivedFrom(AI::DefaultData)			||
			entity->IsDerivedFrom(DropZone::DefaultData)	||
			entity->IsDerivedFrom(EditorMovementPath::DefaultData)	||
			entity->IsDerivedFrom(Objective::DefaultData)
			)
			if(!IsNameUnique(entity->instanceName,entity))
			{
				NameTable::Instance->RemoveEntry(entity->objectID);	
		NameTable::Instance->IsValid();
				MakeNameUnique(&entity->instanceName);
				
				if(entity->IsDerivedFrom(Vehicle::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::VehicleArray);
				else if(entity->IsDerivedFrom(Building::DefaultData) || entity->IsDerivedFrom(Cultural::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::BuildingArray);
				else if(entity->IsDerivedFrom(NavPoint::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::NavArray);
				else if(entity->IsDerivedFrom(AI::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::AIArray);
				else if(entity->IsDerivedFrom(DropZone::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::DropZoneArray);
				else if(entity->IsDerivedFrom(EditorMovementPath::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::PathArray);
				else if(entity->IsDerivedFrom(Objective::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::ObjectiveArray);
				else if(entity->IsDerivedFrom(NonCom::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::BuildingArray);
				else STOP(("Unknown Array"));
				NameTable::Instance->IsValid();
	}
	}
	
}


bool CMW4GameEdApp::IsNameUnique(char *name,Entity *ignore)
{
	if(name==NULL) return false;
	
	ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
	Entity *entity;
	
	ChainIteratorOf<Entity *> subiterator(&Map::Instance->childEntityChain);
	
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		if(entity!=ignore &&  entity->instanceName && entity->instanceName==name)
		{
			return false;	
		}
		
	}
	
	return true;
}

void CMW4GameEdApp::MakeNameUnique(MString *str)
{
	
	CString full_name((char *)*str);
	CString base_name,final_name,numstr;
	
	int idx;
	
	idx=full_name.ReverseFind('_');
	
	if(idx==-1)
	{
		base_name=full_name;
	}
	else
	{
		base_name=full_name.Left(idx);
	}
	
	final_name=full_name;
	
	while(!IsNameUnique((char *)(LPCSTR)final_name))
	{
		final_name.Format("%s_%04i",base_name,(rand()*10000)/RAND_MAX);
	}
	
	*str=(char *)(LPCSTR)final_name;
}

void CMW4GameEdApp::RotateSel90CCW()
{
	CSelectionNode* selected;
	ChainIteratorOf<CSelectionNode*> selections(&CSelectionList::Instance->selectionList);
	
	while ((selected = selections.ReadAndNext()) != NULL)
	{
		
		LinearMatrix4D matrix(true);
		
		Point3D pos;
		YawPitchRoll rot;
		
		matrix = selected->selectedEntity->GetLocalToParent();
		rot = matrix;
		rot.yaw -= 90.0f/Degrees_Per_Radian;
		matrix.BuildRotation(rot);	
		selected->selectedEntity->SetNewLocalToParent(matrix);
		selected->selectedEntity->SyncMatrices(true);	
	}
	
	
}

void CMW4GameEdApp::RotateSel90CW()
{
	
	CSelectionNode* selected;
	ChainIteratorOf<CSelectionNode*> selections(&CSelectionList::Instance->selectionList);
	
	while ((selected = selections.ReadAndNext()) != NULL)
	{
		
		LinearMatrix4D matrix(true);
		
		Point3D pos;
		YawPitchRoll rot;
		
		matrix = selected->selectedEntity->GetLocalToParent();
		rot = matrix;
		rot.yaw += 90.0f/Degrees_Per_Radian;
		matrix.BuildRotation(rot);	
		selected->selectedEntity->SetNewLocalToParent(matrix);
		selected->selectedEntity->SyncMatrices(true);	
	}
	
	
}

//*******************************************************************************************
//
//*******************************************************************************************
// This function is called while searching for mech property notation files. Since
// .data is not used exclusively for these, I wanted to add filter out basic.data and similar files
// also not that you can not use the allsubdirectories flag with mechs since they have .data
// files in the armaturedata subdirectories
BOOL _stdcall MechPropertyFilesFilter(LPCSTR szCurrentFileName)
{
	if (!stricmp(szCurrentFileName, "basic.data"))
	{
		return FALSE;
	}
	// also don't allow .data files from _destroyed mechs
	
	LPCSTR pszTemp = strrchr(szCurrentFileName, '_');
	if (pszTemp && !stricmp(pszTemp, "_destroyed.data"))
	{
		return FALSE;
	}
	return TRUE;
}



void CMW4GameEdApp::OnToolsMechProperties()
{
	
	CDlgObjectProperties dlgOP;
	
	CDOPPROPERTIES_TO_EDIT_ARRAY * pPropertiesToEdit = 
		dlgOP.CreatePropertiesToEditArray(13, 
		efloat    , "gamedata\\TiltDegree", "",
		efloat    , "gamedata\\TiltSpeed", "",
		efloat    , "gamedata\\MinStandTransitionSpeed", "",
		efloat    , "gamedata\\MaxGimpSpeed", "",
		efloat    , "gamedata\\Acceleration", "",
		efloat    , "gamedata\\Decceleration", "",
		efloat    , "gamedata\\MaxSpeed", "",
		efloat    , "gamedata\\MinSpeed", "",
		efloat    , "gamedata\\MaxReverseSpeed", "",
		efloat    , "gamedata\\MinReverseSpeed", "",
		efloat    , "gamedata\\FullStopTurnRate", "",
		efloat    , "gamedata\\TopSpeedTurnRate", "",
		efloat    , "gamedata\\MaxHeat", ""
		
		);
	dlgOP.SetFileNameToSearchSubdirectoriesFor("*.data");
	dlgOP.SetFileFilterCallBack(MechPropertyFilesFilter);
	dlgOP.SetObjectFilesDirectory("content\\mechs");
	dlgOP.SetPropertyListToEdit(pPropertiesToEdit);
	dlgOP.ShowFullObjectNames(TRUE);
	dlgOP.ShowFullPropertyName(FALSE);
	
	dlgOP.DoModal();
	free(pPropertiesToEdit);
}


void CMW4GameEdApp::OnUpdateToolsMechProperties(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(TRUE);
}


//*******************************************************************************************
//
//*******************************************************************************************
void CMW4GameEdApp::OnToolsWeaponsProperties()
{
	
	CDlgObjectProperties dlgOP;
	
	CDOPPROPERTIES_TO_EDIT_ARRAY * pPropertiesToEdit = 
		dlgOP.CreatePropertiesToEditArray(11, 
		eint		 , "gamedata\\AmmoPerShot", "",
		efloat	 , "gamedata\\DamageAmount", "",
		efloat	 , "gamedata\\Heat", "",
		eVector3D, "gamedata\\InitialLinearAcceleration", "",
		eVector3D, "gamedata\\InitialLinearVelocity", "",
		eint		 , "gamedata\\MaxAmmo", "",
		efloat	 , "gamedata\\MaxDistance", "",
		efloat	 , "gamedata\\NumFire", "",
		efloat	 , "gamedata\\ReloadTime", "",
		efloat	 , "gamedata\\Tonage", "",
		eint		 , "gamedata\\TotalSlotsTaken", ""); 
	dlgOP.SetFileNameToSearchSubdirectoriesFor("*.data");
	dlgOP.SetFileFilterCallBack(NULL);
	dlgOP.SetObjectFilesDirectory("content\\weaponsubsystems");
	dlgOP.SetPropertyListToEdit(pPropertiesToEdit);
	dlgOP.ShowFullObjectNames(FALSE);
	dlgOP.ShowFullPropertyName(FALSE);
	
	dlgOP.DoModal();
	free(pPropertiesToEdit);
}

void CMW4GameEdApp::OnUpdateToolsWeaponsProperties(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(TRUE);
}

//*******************************************************************************************
//
//*******************************************************************************************
// This function is called while searching for mech property notation files. Since
// .data is not used exclusively for these, I wanted to add filter out basic.data and similar files
// also not that you can not use the allsubdirectories flag with mechs since they have .data
// files in the armaturedata subdirectories
BOOL _stdcall MechPropertyFilesFilter2(LPCSTR szCurrentFileName)
{
	// also don't allow .data files from _destroyed mechs
	
	LPCSTR pszTemp = strrchr(szCurrentFileName, '_');
	if (pszTemp && !stricmp(pszTemp, "_destroyed.damage"))
	{
		return FALSE;
	}
	return TRUE;
}
//*******************************************************************************************
//
//*******************************************************************************************
void CMW4GameEdApp::OnToolsArmorBalancing()
{
	
	CDlgObjectBalance dlgOB;
	
	CDOPPROPERTIES_TO_EDIT_ARRAY * pPropertiesToEdit = 
		dlgOB.CreatePropertiesToEditArray(13, 
		efloat	 , "joint_luarm\\MaxArmorValue", "L.Arm",
		efloat	 , "joint_ruarm\\MaxArmorValue", "R.Arm",
		efloat	 , "joint_luleg\\MaxArmorValue", "L.Leg",
		efloat	 , "joint_ruleg\\MaxArmorValue", "R.Leg",
		efloat	 , "joint_head\\MaxArmorValue", "Head",
		efloat	 , "joint_righttorsofront\\MaxArmorValue", "R.T.F.",
		efloat	 , "joint_righttorsorear\\MaxArmorValue", "R.T.R.",
		efloat	 , "joint_lefttorsofront\\MaxArmorValue", "L.T.F.",
		efloat	 , "joint_lefttorsorear\\MaxArmorValue", "L.T.R.",
		efloat	 , "joint_hipbelow\\MaxArmorValue", "C.T.F.",
		efloat	 , "joint_centertorsorear\\MaxArmorValue",  "C.T.R.",
		efloat	 , "joint_specialone\\MaxArmorValue", "Sp. 1",
		efloat	 , "joint_specialtwo\\MaxArmorValue", "Sp. 2"
    );

    
	dlgOB.SetFileNameToSearchSubdirectoriesFor("*.damage");
	dlgOB.SetFileFilterCallBack(MechPropertyFilesFilter2);
	dlgOB.SetObjectFilesDirectory("content\\mechs");
 
  dlgOB.SetHorizontalControlSize(60);
  dlgOB.ShowPageOnly();
	dlgOB.SetPropertyListToEdit(pPropertiesToEdit);
  dlgOB.SetAllowPresentToChange(FALSE);
	dlgOB.ShowFullObjectNames(FALSE);
	dlgOB.ShowFullPropertyName(FALSE);
	
	dlgOB.DoModal();
	free(pPropertiesToEdit);
}

void CMW4GameEdApp::OnUpdateToolsArmorBalancing(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(TRUE);
}



//*******************************************************************************************
//
//*******************************************************************************************
void CMW4GameEdApp::OnToolsWeaponsBalancing()
{
	
	CDlgObjectBalance dlgOB;
	
	CDOPPROPERTIES_TO_EDIT_ARRAY * pPropertiesToEdit = 
		dlgOB.CreatePropertiesToEditArray(6, 
		efloat	 , "gamedata\\DamageAmount", "",
    efloat   , "gamedata\\HeatToDeal", "",
    efloat   , "gamedata\\SplashRadius", "",
		efloat	 , "gamedata\\ReloadTime", "",
		efloat	 , "gamedata\\Heat", "",
		efloat	 , "gamedata\\Tonage", "");

    
	dlgOB.SetFileNameToSearchSubdirectoriesFor("*.data");
	dlgOB.SetFileFilterCallBack(NULL);
	dlgOB.SetObjectFilesDirectory("content\\weaponsubsystems");
	dlgOB.SetPropertyListToEdit(pPropertiesToEdit);
	dlgOB.ShowFullObjectNames(FALSE);
	dlgOB.ShowFullPropertyName(FALSE);
	
	dlgOB.DoModal();
	free(pPropertiesToEdit);
}

void CMW4GameEdApp::OnUpdateToolsWeaponsBalancing(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(TRUE);
}


//
//
// Alignment menu is setup whenever it is shown
//
//
void CMW4GameEdApp::OnUpdateDefaultAlignmentMenu(CCmdUI* pCmdUI)
{
#define OUDAM_MAX_MENU_ITEMS_FOR_ALIGNMENT 10
	
	// determine if this is the popup menu
	if (pCmdUI->m_pSubMenu) 
	{
		// if so then we need to reinitialize the menu contents
		// I have seen the removemenu calls fail and this can create an infinite loop if
		// we don't protect against it.
		int nMax = OUDAM_MAX_MENU_ITEMS_FOR_ALIGNMENT;
		
		while (pCmdUI->m_pSubMenu->GetMenuItemCount() && nMax--)
		{
			pCmdUI->m_pSubMenu->RemoveMenu(0, MF_BYPOSITION);
		}
		for (int i = 0; i < Entity::LastAlignment && i < OUDAM_MAX_MENU_ITEMS_FOR_ALIGNMENT; i++)
		{
			pCmdUI->m_pSubMenu->AppendMenu(0, ID_TOOLS_DEF_ALIGNMENT_1 + i, Entity::AlignmentAsciiToText(i));
			//
			// Set the appropriate check
			//
		}
		pCmdUI->m_pSubMenu->CheckMenuItem(ID_TOOLS_DEF_ALIGNMENT_1 + m_nDefaultAlignmentForPlacedObjects, MF_BYCOMMAND | MF_CHECKED);
		
	}
	
	
}

//
// Changes the current alignment default for newly placed items
//
void CMW4GameEdApp::OnDefaultAlignmentMenu(UINT uiID)
{
	if (uiID >= ID_TOOLS_DEF_ALIGNMENT_1 && uiID <= ID_TOOLS_DEF_ALIGNMENT_10)
	{
		int nTemp = uiID - ID_TOOLS_DEF_ALIGNMENT_1;
		if (nTemp < Entity::LastAlignment)
		{
			m_nDefaultAlignmentForPlacedObjects = nTemp;
		}
	}
}
void CMW4GameEdApp::OnToolsPlacewithmap() 
{
	resourceWindow->DisperseWithBitmap();
}

void AddToBuildFile(CString missionName,CString map_name)
{
	SetCurrentDirectory(Working_Directory);
	
	CString missionPath = "Content\\Missions\\";
	missionPath += missionName;
	
	CString map_buildpath;
	CString map_shortpath;
	CString map_longpath;
	CString mission_instancepath;
	CString mission_buildpath;
	map_shortpath.Format("Maps\\%s\\%s.build",map_name,map_name);	
	mission_buildpath.Format("Missions\\%s\\%s.build",missionName,missionName);	
	mission_instancepath.Format("Missions\\%s\\%s.instance",missionName,missionName);	
	map_longpath="Content\\"+map_shortpath;
	
	if(!gos_DoesFileExist(map_shortpath))
	{
		CString str;
		str.Format("Resources\\Maps\\%s.mw4",map_name);
		NotationFile mapfile(map_longpath);
		Page *page=mapfile.AddPage(str);
		str.Format("maps\\%s\\%s.data",map_name,map_name);
		page->SetEntry("data",str);
		str.Format("%s was missing and was created",map_longpath);
		MessageBox(NULL,str,"Missing File",MB_OK);
		mapfile.Save();
	}
	
	////////////////////////////////////////////////////////////
	//	Enter the data in the build file
	Verify(gos_DoesFileExist("Content\\MechWarrior4.build"));
	
	if(gos_FileReadOnly("Content\\MechWarrior4.build"))
	{
		gos_FileSetReadWrite("Content\\MechWarrior4.build");
		MessageBox(NULL,"MechWarrior4.build has been made writeable and modified","File Modification",MB_OK);
	}
	
	_mkdir(LPCTSTR(missionPath));
	
	SPEW(("scottjan","Make sure I never get to touch any code again okay?"));
	
	Stuff::NotationFile build_file("Content\\MechWarrior4.build");
	Page *core_page = build_file.FindPage("");
	if (core_page)
	{
		Check_Object(core_page);
		Page::NoteIterator *core_notes = core_page->MakeNoteIterator();
		Check_Object(core_notes);
		Note *core_note;
		while ((core_note = core_notes->ReadAndNext()) != NULL)
		{
			Check_Object(core_note);
			NotationFile map_file;
			core_note->GetEntry(&map_file);
			Page *maps_page = map_file.FindPage("");
			Check_Object(maps_page);
			Page::NoteIterator *map_notes = maps_page->MakeNoteIterator();
			Check_Object(map_notes);
			Note *map_note;
			
			NotationFile mission_file;
			map_note=maps_page->FindNote(map_shortpath);
			if(!map_note)
			{
				map_note=maps_page->AddNote(map_shortpath);
				Check_Object(map_note);
			}
			else
			{
				map_note->GetEntry(&mission_file);
			}
			
			Page *mission_page = mission_file.SetPage(NULL);
			NotationFile mission_note;
			mission_page->SetEntry(mission_buildpath,&mission_note);
			
			map_note->SetEntry(&mission_file);
			core_note->SetEntry(&map_file);
		}
	}
	
	build_file.Save();
	
	
	mission_buildpath="Content\\"+mission_buildpath;
	NotationFile  mission_build(mission_buildpath);
	Page *mission_page;
	CString misrespath;
	misrespath.Format("Resources\\Missions\\%s.mw4",missionName);
	mission_build.DeleteAllPages();
	mission_page=mission_build.AddPage(misrespath);
	mission_page->SetEntry("instance",mission_instancepath);
	mission_build.Save();
	
}

void CMW4GameEdApp::DisperseCulturals()
{
	RemoveCulturals();
	resourceWindow->DisperseWithBitmap(true);
}

void CMW4GameEdApp::RemoveCulturals()
{
	Adept::Entity *entity;
	ChainIteratorOf<Entity*> iterator(&culturalList);
	iterator.First();
	while((entity = iterator.ReadAndNext()) != NULL)
	{
		Map::Instance->RemoveChild(entity);
		NameTable::Instance->RemoveEntry(entity->objectID);
		NameTable::Instance->IsValid();
		delete Cast_Object(Stuff::Plug *, entity);
	}
	theApp.instanceWindow->ResetInstanceLists();
}

void CMW4GameEdApp::OnToolsDisperseculturalwithbitmap() 
{
	DisperseCulturals();	
}

void CMW4GameEdApp::OnToolsRemoveculturals() 
{
	RemoveCulturals();
	
}

void CMW4GameEdApp::RemoveEditorObjects (void)
{
	ChainIteratorOf<Entity*> entities(&Map::Instance->childEntityChain);
	Entity *entity;
	Point3D loc1(20,0,20),loc2(0,0,0);
	LinearMatrix4D matrix1 = LinearMatrix4D::Identity;
	LinearMatrix4D matrix2 = LinearMatrix4D::Identity;
	matrix1.BuildTranslation(loc1);
	matrix2.BuildTranslation(loc2);

	while ((entity = entities.ReadAndNext()) != NULL)
	{
		if (entity->IsDerivedFrom (EditorMovementPath::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
		else if (entity->IsDerivedFrom (EditorPathNode::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
		else if (entity->IsDerivedFrom (EditorBoundaryNode::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
		else if (entity->IsDerivedFrom (EditorDropNode::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
		else if (entity->IsDerivedFrom (EditorLight::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
		else if (entity->IsDerivedFrom (EditorObjectiveMarker::DefaultData))
		{
			entity->GetElement()->SetNeverCullMode ();
			entity->SetNewLocalToParent(matrix1);
			entity->SyncMatrices(true);
			entity->SetCollisionMask (Entity::NeverCollidesMask);
			Map::Instance->UpdateZone(entity);
//			Map::Instance->RemoveChild (entity);
		}
	}

}
