// DisplayWindow.cpp : implementation file
//

#include "stdafx.h"
#include "MW4GameEd.h"

#include "DisplayWindow.h"
#include "selection.h"
#include "EditorChildWnd.h"
#include "Mainfrm.h"
#include "MoveCommand.h"
#include "RotateCommand.h"
#include "RevolveCommand.h"
#include "DeleteCommand.h"
#include "GenericTextDlg.h"
#include "transDlg.h"
#include "AddCommand.h"
#include "AddLinkCommand.h"
#include "GenericListDlg.h"
#include "EditorWaypoint.h"
#include "LatticeLinkDlg.h"
#include "InsertPathNodeCommand.h"
#include "SprayCommand.h"
#include <MW4\MWMover.hpp>
#include <MW4\Vehicle.hpp>
#include <MW4\VehicleInterface.hpp>
#include <Adept\RendererManager.hpp>
#include <Adept\Player.hpp>
#include <Adept\Map.hpp>
#include <Adept\Player.hpp>
#include <Adept\Entity.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Mission.hpp>
#include <Adept\Connection.hpp>
#include <Adept\Application.hpp>
#include <Adept\ComponentWeb.hpp>
#include <Adept\CameraComponent.hpp>
#include <mw4\Cultural.hpp>
#include <Adept\NameTable.hpp>
#include <mw4\AI.hpp>
#include <Adept\DropZone.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <Adept\CollisionGrid.hpp>
#include <Adept\NameTable.hpp>
#include <MW4\Path.hpp>
#include <MW4\Building.hpp>
#include <direct.h>
#include "TransDlg.h"
#include "ResourceWindow.h"
#include "OverviewWindow.h"
#include "InstanceWindow.h"
#include "MainFrm.h"
#include "GlobalDefs.h"
#include <MW4\MWTool.hpp>
#include <mw4\noncom.hpp>
#include <mw4\navpoint.hpp>

//#include <stdlib.h>
//#include <stdio.h>

int objCounter = 0;

extern bool gActive;
extern bool gGotFocus;

Entity*	RightClickEntity;

extern CMW4GameEdApp theApp;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  CDisplayWindow

IMPLEMENT_DYNCREATE(CDisplayWindow, CEditorChildWnd)

CDisplayWindow::CDisplayWindow()
{
	CString title("OverViewWindow");

	RECT	rect;

	title.LoadString(IDS_OVERVIEWWINDOWTITLE);
	rect.top = 0; rect.left = 675; rect.bottom = 275; rect.right = 975;

	Create(NULL,title,
		   WS_CHILD|WS_VISIBLE|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,
		   rect);


	translationDlg = new CTransDlg;
	Register_Pointer(translationDlg);
	translationDlg->Create(CTransDlg::IDD,this);

	latticeLinkDlg = new CLatticeLinkDlg;
	Register_Pointer(latticeLinkDlg);
	latticeLinkDlg->Create(CLatticeLinkDlg::IDD,this);

	mouseLook = false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CDisplayWindow::~CDisplayWindow()
{
	Unregister_Pointer(translationDlg);
	delete translationDlg;
	translationDlg = NULL;

	Unregister_Pointer(latticeLinkDlg);
	delete latticeLinkDlg;
	latticeLinkDlg = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BEGIN_MESSAGE_MAP(CDisplayWindow, CEditorChildWnd)//CSnapWnd)
	//{{AFX_MSG_MAP(CDisplayWindow)
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_WM_TIMER()
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_OBJ_NAME, OnSetObjectName)
	ON_COMMAND(ID_OBJ_PARAMETERS, OnSetObjectParameters)
	ON_COMMAND(ID_OBJ_TRANSLATION, OnSetObjectTranslation)
	ON_COMMAND(ID_OBJ_EDITDRIVER, OnObjEditDriver)
	ON_COMMAND(ID_OBJ_EDITSCRIPT, OnObjEditScript)
	ON_WM_KEYUP()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	ON_WM_PAINT()
	ON_COMMAND(ID_OBJ_DAMAGEOBJARMOR, OnObjDamageArmor)
	ON_COMMAND(ID_OBJ_DAMAGEOBJINTERNAL, OnObjDamageInternal)
	ON_COMMAND(ID_OBJ_EDITLATTICELINKS, OnEditLatticeLinks)
	ON_COMMAND(ID_OBJ_SHOWRADIUS, OnShowRadius)
	ON_UPDATE_COMMAND_UI(ID_OBJ_SHOWRADIUS, OnUpdateShowRadius)
	ON_COMMAND(ID_OBJ_ADDNEWLINK, OnAddLink)
	ON_COMMAND(ID_OBJ_INSERTPATHNODE, OnInsertPathNode)
	ON_COMMAND(ID_OBJ_APPENDPATHNODE, OnAppendPathNode)
	ON_COMMAND(ID_OBJ_SPECIFYSCRIPT, OnObjSpecifyScript)
	ON_COMMAND(ID_OBJ_INSERTBOUNDARYNODE, OnInsertBoundaryNode)
	ON_COMMAND(ID_OBJ_REMOVEINSTANCE, OnObjRemoveinstance)
	ON_COMMAND(ID_OBJ_ALIGNMENT, OnObjAlignment)
	ON_COMMAND(ID_OBJ_SUBSYSTEM, OnObjSubsystem)
	ON_COMMAND(ID_OBJ_ADDDROPPOINT, OnAddDropPoint)
	ON_COMMAND(ID_OBJ_CLEARAI, OnClearAI)
	ON_COMMAND(ID_OBJ_ABLMEMORY, OnABLMemory)
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  CDisplayWindow message handlers

BOOL CDisplayWindow::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.cx = 640 + GetSystemMetrics(SM_CXSIZEFRAME) * 2;
	cs.cy = 480 + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
	cs.x = -1;
	cs.y = -1;
	cs.style = WS_CHILD|WS_VISIBLE|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU;

	return CEditorChildWnd::PreCreateWindow(cs);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int CDisplayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (!theApp.displayWindow)
	{
		if (CEditorChildWnd::OnCreate(lpCreateStruct) == -1)
			return -1;

		CString title;
		title.LoadString(IDS_DISPLAYWINDOWTITLE);
		SetWindowText(title);

		theApp.displayWindow = this;

		return 0;
	}
	else
		return -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LRESULT CDisplayWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	gActive = true;
	gGotFocus= true;
	switch(message)
	{
	case WM_ACTIVATE:
	case WM_CHAR:
	case WM_SETFOCUS:
	case WM_KEYDOWN:
	case WM_MOVE:
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
		{
			GameOSWinProc(m_hWnd, message, wParam, lParam);
			break;
		}
	case WM_PAINT:
		GameOSWinProc(m_hWnd, message, wParam, lParam);
		OnPaint();
		return 0;
	}
	return CEditorChildWnd::WindowProc(message, wParam, lParam);
}

unsigned int oldCollision;   // cheap but it works
Entity* justAddedEntity = NULL;
Point3D	dragAnchor;
ElementRenderer::LineCloudElement*
	GroupSelectLineCloud;
Stuff::Point3D
	GroupSelectPointData[8];
Stuff::RGBAColor
	GroupSelectColorData[8];
unsigned
	GroupSelectPointCount = 8;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
	if(Application::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState)
	{
		switch (theApp.m_editorState)
		{
			case CMW4GameEdApp::SprayingState:
			{
				CSelectionNode *selection_node;
				SprayCommand *spray_command;

				spray_command = (SprayCommand*)theApp.currentCommand;

				if (!spray_command->selectedEntities.IsEmpty())
				{
					ChainIteratorOf<CSelectionNode*> iterator(&spray_command->selectedEntities);
					while((selection_node = iterator.ReadAndNext()) != NULL)
					{
						if (selection_node->selectedEntity->GetCollisionMask() == Entity::EditorIsMovingFlag &&
							selection_node->selectedEntity->IsMultiZone())
						{
							MessageBeep(MB_OK);
							CEditorChildWnd::OnLButtonDown(nFlags, point);
							return;
						}
					}
				}

				theApp.undoChain.Add(theApp.currentCommand);

				if (!spray_command->selectedEntities.IsEmpty())
				{
					ChainIteratorOf<CSelectionNode*> iterator(&spray_command->selectedEntities);
					while((selection_node = iterator.ReadAndNext()) != NULL)
					{
						if(selection_node->selectedEntity->IsDerivedFrom(Vehicle::DefaultData))
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::VehicleArray);
						else if(selection_node->selectedEntity->IsDerivedFrom(Building::DefaultData) || selection_node->selectedEntity->IsDerivedFrom(Cultural::DefaultData) )
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::BuildingArray);
						else if(selection_node->IsDerivedFrom(NavPoint::DefaultData))
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::NavArray);
						else if(selection_node->selectedEntity->IsDerivedFrom(DropZone::DefaultData))
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::DropZoneArray);
						else if(selection_node->selectedEntity->IsDerivedFrom(AI::DefaultData))
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::AIArray);
						else if(selection_node->selectedEntity->IsDerivedFrom(NonCom::DefaultData))
							 NameTable::Instance->AddEntry(selection_node->selectedEntity, NameTable::BuildingArray);
						else
							 NameTable::Instance->AddEntry(selection_node->selectedEntity);
		NameTable::Instance->IsValid();

					}
				}

				theApp.currentCommand = NULL;
				CSelectionList::Instance->ClearSelectionList();
				theApp.toolBar->EnableButton(ID_EDIT_UNDO);

				if ((GetAsyncKeyState(KEY_LSHIFT) & 0x8000) || theApp.m_MultiDrop)
				{
					theApp.m_editorState = CMW4GameEdApp::WaitingToSprayState;
					theApp.resourceWindow->CreateNewInstance();
					theApp.didIdle = false;
				}
				else
				{
					theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
				}
				break;
			}
			case CMW4GameEdApp::AddingObjectState:
			{
//				theApp.VerifyWaypointRadius();
				Check_Object(NameTable::Instance);
				Entity *entity = NULL;

				AddCommand *add_command;
				add_command = (AddCommand*)theApp.currentCommand;
				entity = add_command->addedObject;

				if (entity->GetCollisionMask() == Entity::EditorIsMovingFlag && entity->IsMultiZone())
				{
					MessageBeep(MB_OK);
					break;
				}

				theApp.undoChain.Add(theApp.currentCommand);

				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(NonCom::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::BuildingArray);
				else if(entity->IsDerivedFrom(AI::DefaultData))
					 NameTable::Instance->AddEntry(entity, NameTable::AIArray);
		NameTable::Instance->IsValid();

				theApp.currentCommand = NULL;
				CSelectionList::Instance->ClearSelectionList();
				theApp.toolBar->EnableButton(ID_EDIT_UNDO);

				if (entity->IsDerivedFrom(EditorPathNode::DefaultData))
				{
					Point3D loc;
					loc = entity->GetLocalToWorld();
					if (!MW4AI::g_MissionGraph->FindClosestNode(loc))
					{
						MessageBeep(MB_OK);
					}
					if (theApp.m_MultiDrop)
					{
						AppendPathNode(entity);
						break;
					}
				}

				if ((GetAsyncKeyState(KEY_LSHIFT) & 0x8000) || theApp.m_MultiDrop)
				{
					theApp.m_editorState = CMW4GameEdApp::WaitingToAddState;
					theApp.resourceWindow->CreateNewInstance();
					theApp.didIdle = false;
				}
				else
				{
					theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
					theApp.resourceWindow->TLDlg->m_ObjList.EnableWindow();
					theApp.instanceWindow->TLDlg->m_ObjList.EnableWindow();
				}
				break;
			}
			case CMW4GameEdApp::MovingObjectState:
			{
				CSelectionNode* selNode;
				ChainIteratorOf<CSelectionNode*> iterator(&CSelectionList::Instance->selectionList);

				while ((selNode = iterator.ReadAndNext()) != NULL)
				{
					if (selNode->selectedEntity->GetCollisionMask() == Entity::EditorIsMovingFlag && selNode->selectedEntity->IsMultiZone())
					{
						MessageBeep(MB_OK);
						CEditorChildWnd::OnLButtonDown(nFlags, point);
						return;
					}
				}
				theApp.undoChain.Add(theApp.currentCommand);
				theApp.currentCommand = NULL;
				theApp.m_editorState = CMW4GameEdApp::AfterMovingState;//SelectingObjectState;
				CSelectionList::Instance->RestoreCollision();
				theApp.toolBar->EnableButton(ID_EDIT_UNDO);
				break;
			}
			case CMW4GameEdApp::AddingLinkState:
			{
				Check_Object(Player::Instance);
				Check_Object(Player::Instance->playerInterface);
				Entity *reticule;
				reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();

				if (!reticule->IsDerivedFrom(EditorLatticeNode::DefaultData))
					break;

				EditorLatticeNode* node;
				node = Cast_Object(EditorLatticeNode*,reticule);

				AddLinkCommand* addlink;
				addlink = Cast_Object(AddLinkCommand*,theApp.currentCommand);
				addlink->ConnectLink(node);
				theApp.undoChain.Add(theApp.currentCommand);
				theApp.currentCommand = NULL;
				CSelectionList::Instance->ClearSelectionList();
				theApp.toolBar->EnableButton(ID_EDIT_UNDO);
				theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
				break;
			}
			case CMW4GameEdApp::SelectingObjectState:
			{
				Check_Object(Player::Instance);
				Check_Object(Player::Instance->playerInterface);
				Entity *reticule;
				reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();
				if((reticule))// && (!reticule->IsDerivedFrom(Map::DefaultData)))
				{
					reticule = TraceToParent(reticule);
					Check_Object(reticule);
					if (reticule->IsDerivedFrom(Map::DefaultData))	// can't select the map.
					{
//						if (!(gos_GetKeyStatus(KEY_LCONTROL)) &&
//							!(gos_GetKeyStatus(KEY_RCONTROL)))
						{
							CSelectionList::Instance->ClearSelectionList();
						}
						theApp.m_editorState = CMW4GameEdApp::DragSelectState;
						GetPointOnMap(&dragAnchor);
						gos_PushCurrentHeap(ElementRenderer::g_Heap);
						GroupSelectLineCloud = new ElementRenderer::LineCloudElement(ELEMENTS(GroupSelectPointData));
						Check_Object(GroupSelectLineCloud);

						GroupSelectColorData[0] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[1] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[2] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[3] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[4] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[5] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[6] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);
						GroupSelectColorData[7] = Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 0.0f);

						GroupSelectLineCloud->SetDataPointers(&GroupSelectPointCount, GroupSelectPointData, GroupSelectColorData);
						GroupSelectLineCloud->m_localOBB.localToParent = LinearMatrix4D::Identity;
						GroupSelectLineCloud->m_localOBB.sphereRadius = Sqrt(3.0f);
						Mission::Instance->GetElement()->AttachChild(GroupSelectLineCloud);

						GroupSelectLineCloud->SetVolumeCullMode();
//						GroupSelectLineCloud->SetName("Line Cloud");
						GroupSelectLineCloud->Sync();
						gos_PopCurrentHeap();

						break;
					}
					if(((GetAsyncKeyState(KEY_LCONTROL)) & 0x8000) ||
						((GetAsyncKeyState(KEY_RCONTROL)) & 0x8000))
					{
						if(CSelectionList::Instance->FindSelection(reticule))
						{
							CSelectionList::Instance->RemoveSelection(reticule);
						}
						else
						{
							CSelectionList::Instance->AddSelection(reticule);
						}
					}
					else
					{
						if(!CSelectionList::Instance->FindSelection(reticule))
						{
							CSelectionList::Instance->ClearSelectionList();
							CSelectionList::Instance->AddSelection(reticule);
						}
					}
					if (translationDlg->IsWindowVisible())
					{
						translationDlg->SetObject(reticule,theApp.GetEntityData(reticule));
					}
					if (latticeLinkDlg->IsWindowVisible())
					{
						latticeLinkDlg->SetNode(reticule);
					}
					theApp.instanceWindow->ResetSel();
				}
				break;
			}
			case CMW4GameEdApp::IdleState:
			{
				Check_Object(Player::Instance);
				Check_Object(Player::Instance->playerInterface);
				Entity *reticule;
				reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();
				if(reticule)
				{
					reticule = TraceToParent(reticule);
					if(!reticule->IsDerivedFrom(Map::DefaultData))
					{
						theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
						CSelectionList::Instance->AddSelection(reticule);
					}
					else
					{
						CSelectionList::Instance->ClearSelectionList();
					}
				}
				break;
			}
		}	
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnMouseMove(UINT nFlags, CPoint point)
{

	static CPoint lastPoint;

	Check_Object(Application::Instance);

	if((theApp.m_editorState != CMW4GameEdApp::NoGameIdleState) &&
		(Application::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState))
	{
		Check_Object(VideoRenderer::Instance);
		VideoRenderer::Instance->ProjectMouseCursorIntoCameras();

		switch(theApp.m_editorState)
		{
			case CMW4GameEdApp::RotateState:
			{
				((RotateCommand*)theApp.currentCommand)->Rotate(0.0f,0.01f * float(point.x - lastPoint.x),0.0f);
				break;
			}
			case CMW4GameEdApp::RevolveState:
			{
				((RevolveCommand*)theApp.currentCommand)->Revolve(0.01f * float(point.x - lastPoint.x));
				break;
			}
			case CMW4GameEdApp::MovingObjectState:
			{
				theApp.currentCommand->Execute();
				if (translationDlg->IsWindowVisible())
					theApp.displayWindow->translationDlg->SetValues();
				break;
			}
			case CMW4GameEdApp::SprayingState:
			case CMW4GameEdApp::AddingObjectState:
			{
				Verify(theApp.currentCommand != NULL);
				if (theApp.currentCommand)
					theApp.currentCommand->Execute();
				break;
			}
			case CMW4GameEdApp::SelectingObjectState:
			{
				if (nFlags & MK_LBUTTON && CSelectionList::Instance->GetSelectionCount())
				{
					Entity *reticule;
					reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();
					if((reticule))// && (!reticule->IsDerivedFrom(Map::DefaultData)))
					{
						reticule = TraceToParent(reticule);
						Check_Object(reticule);
						theApp.m_editorState = CMW4GameEdApp::MovingObjectState;
						theApp.currentCommand = new MoveCommand(reticule);
						CSelectionList::Instance->RemoveCollision();
						Check_Object(theApp.currentCommand);

						if (CSelectionList::Instance->GetSelectionCount() > 1 &&
							translationDlg->IsWindowVisible())
							translationDlg->ShowWindow(SW_HIDE);

						if (CSelectionList::Instance->GetSelectionCount() > 1 &&
							latticeLinkDlg->IsWindowVisible())
							latticeLinkDlg->ShowWindow(SW_HIDE);
					}
				}
				break;
			}
			case CMW4GameEdApp::DragSelectState:
			{
				Point3D	dragTo;

				if (!GetPointOnMap(&dragTo))
				{
					theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
					Mission::Instance->GetElement()->DetachChild(GroupSelectLineCloud);
					delete GroupSelectLineCloud;
					GroupSelectLineCloud = NULL;
					break;
				}
				GroupSelectPointData[0].x = dragAnchor.x;
				GroupSelectPointData[0].y = dragAnchor.y + 0.5f;
				GroupSelectPointData[0].z = dragAnchor.z;

				GroupSelectPointData[1].x = dragTo.x;
				GroupSelectPointData[1].y = GetMapPointVertical(dragTo.x, dragAnchor.z) + 0.5f;
				GroupSelectPointData[1].z = dragAnchor.z;

				GroupSelectPointData[2].x = dragTo.x;
				GroupSelectPointData[2].y = GetMapPointVertical(dragTo.x, dragAnchor.z) + 0.5f;
				GroupSelectPointData[2].z = dragAnchor.z;

				GroupSelectPointData[3].x = dragTo.x;
				GroupSelectPointData[3].y = dragTo.y + 0.5f;
				GroupSelectPointData[3].z = dragTo.z;

				GroupSelectPointData[4].x = dragTo.x;
				GroupSelectPointData[4].y = dragTo.y + 0.5f;
				GroupSelectPointData[4].z = dragTo.z;

				GroupSelectPointData[5].x = dragAnchor.x;
				GroupSelectPointData[5].y = GetMapPointVertical(dragAnchor.x, dragTo.z) + 0.5f;
				GroupSelectPointData[5].z = dragTo.z;

				GroupSelectPointData[6].x = dragAnchor.x;
				GroupSelectPointData[6].y = GetMapPointVertical(dragAnchor.x, dragTo.z) + 0.5f;
				GroupSelectPointData[6].z = dragTo.z;

				GroupSelectPointData[7].x = dragAnchor.x;
				GroupSelectPointData[7].y = dragAnchor.y + 0.5f;
				GroupSelectPointData[7].z = dragAnchor.z;

				Vector3D vector[4];
				Point3D point((dragTo.x + dragAnchor.x) / 2,(dragTo.y + dragAnchor.y) / 2,(dragTo.z + dragAnchor.z) / 2),
						tmpPoint;

				tmpPoint = GroupSelectPointData[0];
				vector[0].Subtract(point,tmpPoint);
				tmpPoint = GroupSelectPointData[2];
				vector[1].Subtract(point,tmpPoint);
				tmpPoint = GroupSelectPointData[4];
				vector[2].Subtract(point,tmpPoint);
				tmpPoint = GroupSelectPointData[6];
				vector[3].Subtract(point,tmpPoint);

				int index = 0;
				for (int i = 1; i < 4; i++)
				{
					if (vector[i].GetLengthSquared() > vector[index].GetLengthSquared())
						index = i;
				}
				Scalar length = vector[index].GetLength();
				
				if (length > 0.0f)	// make sure we'll have a radius > 0
				{
					GroupSelectLineCloud->m_localOBB.sphereRadius = length;

					GroupSelectLineCloud->m_localOBB.localToParent(3,0) = (dragTo.x + dragAnchor.x) / 2;
					GroupSelectLineCloud->m_localOBB.localToParent(3,1) = (dragTo.y + dragAnchor.y) / 2;
					GroupSelectLineCloud->m_localOBB.localToParent(3,2) = (dragTo.z + dragAnchor.z) / 2;
					GroupSelectLineCloud->NeedNewBounds();
					GroupSelectLineCloud->NeedMatrixSync();

					GroupSelectLineCloud->Sync();

					Check_Object(Map::Instance);
					ChainIteratorOf<Entity *> iterator(&Map::Instance->childEntityChain);
					Entity* entity;

					LinearMatrix4D matrix;
					while((entity = iterator.ReadAndNext()) != NULL)
					{
						matrix = entity->GetLocalToWorld();
						tmpPoint = matrix;

						if (((tmpPoint.x >= dragAnchor.x && tmpPoint.x <= dragTo.x) ||
							 (tmpPoint.x <= dragAnchor.x && tmpPoint.x >= dragTo.x)) &&
							((tmpPoint.z >= dragAnchor.z && tmpPoint.z <= dragTo.z) ||
							 (tmpPoint.z <= dragAnchor.z && tmpPoint.z >= dragTo.z)))
						{
								CSelectionList::Instance->AddSelection(entity);
						}
						else
						{
							CSelectionList::Instance->RemoveSelection(entity);
						}
					}
				}
				theApp.instanceWindow->ResetSel();
				break;
			}
		}
	}
	if (mouseLook || nFlags & MK_MBUTTON)
	{
		Check_Object(Player::Instance);
		LinearMatrix4D new_local_to_parent;
		Point3D new_position;
		YawPitchRoll new_rotation;
		CPoint diff = point - lastPoint;

		new_position = Player::Instance->GetLocalToWorld();
		new_rotation = Player::Instance->GetLocalToWorld();
		new_rotation.yaw -= Radians_Per_Degree * diff.x;
		new_rotation.pitch += Radians_Per_Degree * diff.y;

		if (new_rotation.pitch > Radians_Per_Degree * 70)
			new_rotation.pitch = Radians_Per_Degree * 70;
		if (new_rotation.pitch < Radians_Per_Degree * -70)
			new_rotation.pitch = Radians_Per_Degree * -70;

		new_local_to_parent.BuildTranslation(new_position);
		new_local_to_parent.BuildRotation(new_rotation);
		Player::Instance->SetNewLocalToParent(new_local_to_parent);
		Player::Instance->SyncMatrices(true);

		Check_Pointer(theApp.overviewWindow);
		theApp.overviewWindow->SetCameraRot();
	}
	lastPoint = point;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(Application::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState)
	{
		switch(theApp.m_editorState)
		{
			case CMW4GameEdApp::AfterMovingState:
				theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
				break;
			case CMW4GameEdApp::DragSelectState:
			{
				theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
				Mission::Instance->GetElement()->DetachChild(GroupSelectLineCloud);
				delete GroupSelectLineCloud;
				GroupSelectLineCloud = NULL;
				break;
			}
			case CMW4GameEdApp::MovingObjectState:
			{
				CSelectionNode* selNode;
				ChainIteratorOf<CSelectionNode*> iterator(&CSelectionList::Instance->selectionList);

				while ((selNode = iterator.ReadAndNext()) != NULL)
				{
					if (selNode->selectedEntity->GetCollisionMask() == Entity::EditorIsMovingFlag && selNode->selectedEntity->IsMultiZone())
					{
						MessageBeep(MB_OK);
						CEditorChildWnd::OnLButtonUp(nFlags, point);
						return;
					}
					else if (selNode->selectedEntity->IsDerivedFrom(EditorBoundaryNode::DefaultData))
					{
						EditorBoundaryNode* node;
						node = Cast_Object(EditorBoundaryNode*,selNode->selectedEntity);
						if (!node->CheckValidPos())
						{
							MessageBeep(MB_OK);
							CEditorChildWnd::OnLButtonUp(nFlags, point);
							return;
						}
					}
				}
				theApp.undoChain.Add(theApp.currentCommand);
				theApp.currentCommand = NULL;
				theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
				CSelectionList::Instance->RestoreCollision();
				theApp.toolBar->EnableButton(ID_EDIT_UNDO);
				break;
			}
		}
		theApp.overviewWindow->DrawWindow();
	}
	CEditorChildWnd::OnLButtonUp(nFlags, point);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnRButtonDown(UINT nFlags, CPoint point)
{

	if(Application::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState)
	{
		if (theApp.m_editorState == CMW4GameEdApp::AddingObjectState ||
			theApp.m_editorState == CMW4GameEdApp::SprayingState)
		{
			theApp.StopMultiPlace();
			CEditorChildWnd::OnRButtonDown(nFlags, point);
			theApp.instanceWindow->ResetInstanceLists();
			return;
		}
		if (theApp.m_editorState == CMW4GameEdApp::AddingLinkState)
		{
			delete theApp.currentCommand;
			theApp.currentCommand = NULL;
			theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
			CSelectionList::Instance->ClearSelectionList();
			CEditorChildWnd::OnRButtonDown(nFlags, point);
			return;
		}
		Check_Object(Player::Instance);
		Check_Object(Player::Instance->playerInterface);
		Entity *reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();
		if (reticule)
		{
			reticule = TraceToParent(reticule);
			CSelectionList::Instance->ClearSelectionList();
			if(reticule && !reticule->IsDerivedFrom(Map::DefaultData))
			{
				RightClickEntity = reticule;
				CSelectionList::Instance->AddSelection(reticule);
				theApp.instanceWindow->ResetSel();

				CMenu menu;
				VERIFY(menu.LoadMenu(IDR_OBJECTPOPUP));
				CMenu* pPopup = menu.GetSubMenu(0);
				ASSERT(pPopup != NULL);

				if (reticule->IsDerivedFrom(Entity::DefaultData))
				{
					if ((!reticule->IsDerivedFrom(MechWarrior4::Path::DefaultData)) && 
						(!reticule->IsDerivedFrom(DropZone::DefaultData)) && 
						!reticule->IsDerivedFrom(EditorWaypoint::DefaultData) &&
						!reticule->IsDerivedFrom(EditorPathNode::DefaultData) &&
						!reticule->IsDerivedFrom(EditorLatticeNode::DefaultData) &&
						!reticule->IsDerivedFrom(EditorBoundaryNode::DefaultData) &&
						!reticule->IsDerivedFrom(EditorDropNode::DefaultData) &&
						!reticule->IsDerivedFrom(EditorDropZonePoint::DefaultData) &&
						!reticule->IsDerivedFrom(EditorCameraShip::DefaultData) )
					{
						pPopup->InsertMenu(-1,MF_BYPOSITION,ID_OBJ_EDITDRIVER,"Edit Driver...");
						pPopup->InsertMenu(-1,MF_BYPOSITION,ID_OBJ_SPECIFYSCRIPT,"Specify ABL Script...");
						pPopup->InsertMenu(-1,MF_BYPOSITION,ID_OBJ_CLEARAI,"Clear AI Info");
						pPopup->InsertMenu(-1,MF_SEPARATOR);
						pPopup->InsertMenu(-1,MF_BYPOSITION,ID_OBJ_ABLMEMORY,"Edit Memory Cells...");
//						pPopup->InsertMenu(-1,MF_BYPOSITION,ID_OBJ_EDITSCRIPT,"Edit ABL Script...");
					}
				}
				if (reticule->IsDerivedFrom(Vehicle::DefaultData))
				{
					pPopup->GetSubMenu(0)->InsertMenu(1,MF_BYPOSITION,ID_OBJ_DAMAGEOBJARMOR,"Armor...");
					pPopup->GetSubMenu(0)->InsertMenu(2,MF_BYPOSITION,ID_OBJ_DAMAGEOBJINTERNAL,"Internal...");
					pPopup->GetSubMenu(0)->InsertMenu(3,MF_BYPOSITION,ID_OBJ_SUBSYSTEM,"Subsystems...");
				}
				else if (reticule->IsDerivedFrom(EditorLatticeNode::DefaultData))
				{
					pPopup->InsertMenu(7,MF_BYPOSITION,ID_OBJ_EDITLATTICELINKS,"Edit Lattice Node...");
					pPopup->InsertMenu(8,MF_BYPOSITION,ID_OBJ_ADDNEWLINK,"Add Link");
					pPopup->InsertMenu(9,MF_BYPOSITION,ID_OBJ_SHOWRADIUS,"Show Radius");
				}
				else if (reticule->IsDerivedFrom(EditorPathNode::DefaultData))
				{
					pPopup->InsertMenu(7,MF_BYPOSITION,ID_OBJ_INSERTPATHNODE,"Insert Node");
					pPopup->InsertMenu(8,MF_BYPOSITION,ID_OBJ_APPENDPATHNODE,"Append Node(s)");
				}
				else if (reticule->IsDerivedFrom(EditorBoundaryNode::DefaultData))
				{
					pPopup->InsertMenu(7,MF_BYPOSITION,ID_OBJ_INSERTBOUNDARYNODE,"Insert Node");
				}
				else if (reticule->IsDerivedFrom(EditorDropNode::DefaultData))
				{
					pPopup->InsertMenu(7,MF_BYPOSITION,ID_OBJ_ADDDROPPOINT,"Add Drop Point");
				}

				ClientToScreen(&point);

				pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
			}
			theApp.instanceWindow->ResetSel();
		}
			theApp.instanceWindow->ResetInstanceLists();
	}
	CEditorChildWnd::OnRButtonDown(nFlags, point);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CDisplayWindow::ExecuteCamera()
{
	if(Application::Instance->GetApplicationState()
		== ApplicationStateEngine::RunningGameState)
	{

		Check_Object(Player::Instance);
		Check_Object(Player::Instance->playerInterface);
//		VehicleInterface *temp_interface =
//			Cast_Object(VehicleInterface *, Player::Instance->playerInterface);

			Check_Object(Player::Instance);
			Point3D new_position;
			YawPitchRoll new_rotation;

			new_position = Player::Instance->GetLocalToWorld();
			new_rotation = Player::Instance->GetLocalToWorld();

			if(GetAsyncKeyState(KEY_UP) & 0x8000)
			{
				if (GetAsyncKeyState(KEY_RMENU) & 0x8000)
				{
					if (new_rotation.pitch > Radians_Per_Degree * -70)
						new_rotation.pitch -= Radians_Per_Degree * theApp.cameraSpeed;
				}
				else if (GetAsyncKeyState(KEY_RCONTROL) & 0x8000)
				{
					theApp.cameraHeight += theApp.cameraSpeed;

					CMenu* menu = theApp.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);
				}
				else
				{
					new_position.z += Cos(new_rotation.yaw) * theApp.cameraSpeed;
					new_position.x += Sin(new_rotation.yaw) * theApp.cameraSpeed;
				}
				theApp.overviewWindow->InvalidateCamera();
			}

			if(GetAsyncKeyState(KEY_LEFT) & 0x8000)
			{
				if (GetAsyncKeyState(KEY_RMENU) & 0x8000)
				{
					new_position.x += Cos(new_rotation.yaw) * theApp.cameraSpeed;
					new_position.z -= Sin(new_rotation.yaw) * theApp.cameraSpeed;
				}
				else
					new_rotation.yaw += Radians_Per_Degree * theApp.cameraSpeed;

				theApp.overviewWindow->InvalidateCamera();
			}

			if(GetAsyncKeyState(KEY_RIGHT) & 0x8000)
			{
				if (GetAsyncKeyState(KEY_RMENU) & 0x8000)
				{
					new_position.x -= Cos(new_rotation.yaw) * theApp.cameraSpeed;
					new_position.z += Sin(new_rotation.yaw) * theApp.cameraSpeed;
				}
				else
					new_rotation.yaw -= Radians_Per_Degree * theApp.cameraSpeed;

				theApp.overviewWindow->InvalidateCamera();
			}

			if(GetAsyncKeyState(KEY_DOWN) & 0x8000)
			{
				if (GetAsyncKeyState(KEY_RMENU) & 0x8000)
				{
					if (new_rotation.pitch < Radians_Per_Degree * 70)
						new_rotation.pitch += Radians_Per_Degree * theApp.cameraSpeed;
				}
				else if (GetAsyncKeyState(KEY_RCONTROL) & 0x8000)
				{
					theApp.cameraHeight -= theApp.cameraSpeed;

					if (theApp.cameraFollowing == CAMERA_FOLLOW_NONE)
					{
//						theApp.cameraFollowing = CAMERA_FOLLOW_GROUND;
						Stuff::Scalar s = GetMapPointVertical(new_position.x,new_position.z);
						if (theApp.cameraHeight < s)
							theApp.cameraHeight = s + 1.0f;
//						theApp.cameraFollowing = CAMERA_FOLLOW_NONE;

						CMenu* menu = theApp.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);
					}
					else
					{
						if (theApp.cameraHeight < 1.0f)
							theApp.cameraHeight = 1.0f;
					}
				}
				else
				{
					new_position.z -= Cos(new_rotation.yaw) * theApp.cameraSpeed;
					new_position.x -= Sin(new_rotation.yaw) * theApp.cameraSpeed;
				}
				theApp.overviewWindow->InvalidateCamera();
			}

			if (new_position.x <= -(mapX*0.5f) || new_position.x >= (mapX*0.5f) ||
				new_position.z <= -(mapZ*0.5f) || new_position.z >= (mapZ*0.5f))
			{
				return;
			}

			if (theApp.cameraFollowing == CAMERA_FOLLOW_NONE)
			{
				new_position.y = theApp.cameraHeight;
			}
			else
			{
				Entity::CollisionMask collisionType = (theApp.cameraFollowing == CAMERA_FOLLOW_NONE) ? Entity::AlwaysCollidesMask : Entity::CanBeWalkedOnFlag;
				new_position.y = GetMapPointVertical(new_position.x,new_position.z,collisionType) + theApp.cameraHeight;
			}
			LinearMatrix4D new_local_to_parent;
			new_local_to_parent.BuildTranslation(new_position);
			new_local_to_parent.BuildRotation(new_rotation);
			Player::Instance->SetNewLocalToParent(new_local_to_parent);
			Player::Instance->SyncMatrices(true);
		((CMainFrame*)theApp.m_pMainWnd)->SetGridLocation();

		//temp_interface->cameraAttached = true;
//		temp_interface->cameraView = VehicleInterface::ExternalCameraAttachedView;
//		temp_interface->UpdateViews();
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::ProcessIO()
{
	if(GetAsyncKeyState(43) &  0x8000) //c
	{
	theApp.OnToolsCheckscripts();
	}
	
	if(GetAsyncKeyState(52) &  0x8000) //r
	{
	theApp.RotateSel90CW();

	}

	if(GetAsyncKeyState(45) &  0x8000) //e
	{
	theApp.RotateSel90CCW();
	}


	if(GetAsyncKeyState(KEY_DELETE) & 0x8000)
	{
		if (theApp.m_editorState == CMW4GameEdApp::MovingObjectState)
		{
			// I freaking hate special code!
			theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
			theApp.undoChain.Add(theApp.currentCommand);
			theApp.currentCommand = NULL;
		}

		if(theApp.m_editorState == CMW4GameEdApp::SelectingObjectState &&
		   CSelectionList::Instance->GetSelectionCount())
		{
			theApp.currentCommand = new DeleteCommand();	
			Check_Object(theApp.currentCommand);
			CSelectionList::Instance->ClearSelectionList(false);
//			theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
			theApp.undoChain.Add(theApp.currentCommand);
			theApp.currentCommand = NULL;
			theApp.toolBar->EnableButton(ID_EDIT_UNDO);
		}

	}

	if(GetAsyncKeyState(KEY_ESCAPE) & 0x8000)
	{
		if (theApp.m_editorState == CMW4GameEdApp::AddingObjectState ||
			theApp.m_editorState == CMW4GameEdApp::SprayingState)
		{
			theApp.StopMultiPlace();
			return;
		}
		else if (theApp.m_editorState == CMW4GameEdApp::AddingLinkState)
		{
			delete theApp.currentCommand;
			theApp.currentCommand = NULL;
			theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
			CSelectionList::Instance->ClearSelectionList();
			return;
		}


	}
  /*
  This code only works if the focus is on the display window
  To make the camera setting easier to do I moved these to accelerators

  if(GetAsyncKeyState(KEY_LCONTROL) & 0x8000)
	{
		for (int i = KEY_0; i < KEY_9; i++)
		{
			if (GetAsyncKeyState(i) & 0x8000)
			{
				int index = i - KEY_0;
				if (GetAsyncKeyState(KEY_LSHIFT) & 0x8000)
				{
          theApp.OnSetNumberedCameraPosition(index + ID_SET_CAMERA_POS_0);
				}
				else if (theApp.m_DefCameraPos[index] != Stuff::LinearMatrix4D::Identity)
				{
          theApp.OnGotoNumberedCameraPosition(index + ID_GOTO_CAMERA_POS_0);
				}
				break;	// out of for loop
			}
		}
	}
  */
	if(GetAsyncKeyState(KEY_LMENU) & 0x8000)
	{
		SHORT shift = SHORT(GetAsyncKeyState(KEY_LSHIFT) & 0x8000);

		if (CSelectionList::Instance->GetSelectionCount() &&
			(theApp.m_editorState == CMW4GameEdApp::SelectingObjectState ||
			(theApp.m_editorState == CMW4GameEdApp::RotateState && shift) ||
			(theApp.m_editorState == CMW4GameEdApp::RevolveState && !shift)))
		{
			if (theApp.m_editorState != CMW4GameEdApp::SelectingObjectState)
				theApp.undoChain.Add(theApp.currentCommand);

			if (CSelectionList::Instance->GetSelectionCount() > 1 && shift)
			{
				theApp.m_editorState = CMW4GameEdApp::RevolveState;
				theApp.currentCommand = new RevolveCommand();
				SetCapture();
			}
			else
			{
				theApp.m_editorState = CMW4GameEdApp::RotateState;
				theApp.currentCommand = new RotateCommand();
				SetCapture();
			}
		}


	}
	else if (theApp.m_editorState == CMW4GameEdApp::RevolveState || theApp.m_editorState == CMW4GameEdApp::RotateState)
	{
		ReleaseCapture();
		theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;
		theApp.undoChain.Add(theApp.currentCommand);
		theApp.currentCommand = NULL;
		theApp.toolBar->EnableButton(ID_EDIT_UNDO);
	}

	if(RunGameOSLogic())
		PostQuitMessage(0);

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnTimer(UINT nIDEvent)
{

	if (theApp.m_pMainWnd->IsChild(GetFocus()) && theApp.m_editorState != CMW4GameEdApp::NoGameIdleState)
	{
		ExecuteCamera();

//		if (theApp.didIdle)
		{
			ProcessIO();
			theApp.didIdle = false;
		}

		CEditorChildWnd::OnTimer(nIDEvent);
	}

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if(nChar == VK_TAB)
	{
		mouseLook = true;
		SetCapture();
	}
	CEditorChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity*
	CDisplayWindow::TraceToParent(Entity *entity)
{
	Check_Object(entity);

	if(entity->IsDerivedFrom(MWMover::DefaultData))
	{
		MWMover *mover;
		mover = Cast_Object(MWMover *, entity);

		if(mover->myParentVehicle)
			return mover->myParentVehicle;
	}
	return entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditAIDriver (Entity *);
void CDisplayWindow::OnObjEditDriver()
{
	EditAIDriver (RightClickEntity);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnSetObjectName()
{
	Entity *reticule;
	reticule = TraceToParent(Player::Instance->playerInterface->reticuleEntity.GetCurrent());
	if(reticule)
	{
		CGenericTextDlg dlg;

		dlg.m_Title = "Set Object Name";
		dlg.m_MessageText = "Enter the new name of this object";
		if (reticule->IsDerivedFrom(EditorDropNode::DefaultData))
		{
			EditorDropNode* node;
			node = Cast_Object(EditorDropNode*,reticule);
			dlg.m_EditText = node->dropZone->instanceName;
		}
		else if (reticule->IsDerivedFrom(EditorPathNode::DefaultData))
		{
			EditorPathNode* node;
			node = Cast_Object(EditorPathNode*,reticule);
			dlg.m_EditText = node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->instanceName;
		}
		else if (reticule->IsDerivedFrom(EditorCameraShip::DefaultData))
		{
		EditorCameraShip* node;
		node = Cast_Object(EditorCameraShip*,reticule);
		dlg.m_EditText = node->cameraShip->instanceName;
		}
/*
		else if (reticule->IsDerivedFrom(EditorObjectiveMarker::DefaultData))
		{
			EditorObjectiveMarker* node;
			node = Cast_Object(EditorObjectiveMarker*,reticule);
			dlg.m_EditText = node->objective->instanceName;
		}
*/
		else
			dlg.m_EditText = reticule->instanceName;

		if (dlg.DoModal() == IDOK)
		{
			Check_Object(NameTable::Instance);
			EntityManager::Instance->GetNameSocket()->Remove(reticule);
			if (reticule->IsDerivedFrom(EditorDropNode::DefaultData))
			{
				EditorDropNode* node;
				node = Cast_Object(EditorDropNode*,reticule);
				node->dropZone->instanceName = dlg.m_EditText;

				EntityManager::Instance->GetNameSocket()->AddValue(node->dropZone, node->dropZone->instanceName);
				NameTable::Instance->SetName(node->dropZone->objectID, node->dropZone->instanceName);
		NameTable::Instance->IsValid();
			}
			else if (reticule->IsDerivedFrom(EditorPathNode::DefaultData))
			{
				EditorPathNode* node;
				node = Cast_Object(EditorPathNode*,reticule);
				node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->instanceName = dlg.m_EditText;

				EntityManager::Instance->GetNameSocket()->AddValue(node->pathSlot.GetCurrent()->pathSlot.GetCurrent(), node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->instanceName);
				NameTable::Instance->SetName(node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->objectID, node->pathSlot.GetCurrent()->pathSlot.GetCurrent()->instanceName);
		NameTable::Instance->IsValid();
			}
			else if (reticule->IsDerivedFrom(EditorCameraShip::DefaultData))
			{
			EditorCameraShip* node;
			node = Cast_Object(EditorCameraShip*,reticule);
			node->cameraShip->instanceName = dlg.m_EditText;
	
			EntityManager::Instance->GetNameSocket()->AddValue(node->cameraShip, node->cameraShip->instanceName);
			NameTable::Instance->SetName(node->cameraShip->objectID, node->cameraShip->instanceName);
			}

/*
			else if (reticule->IsDerivedFrom(EditorObjectiveMarker::DefaultData))
			{
				EditorObjectiveMarker* node;
				node = Cast_Object(EditorObjectiveMarker*,reticule);
				node->objective->instanceName = dlg.m_EditText;
				node->instanceName = dlg.m_EditText;

				EntityManager::Instance->GetNameSocket()->AddValue(node->objective, node->objective->instanceName);
				NameTable::Instance->SetName(node->objective->objectID, node->objective->instanceName);
			}
*/
			{
				reticule->instanceName = dlg.m_EditText;
				EntityManager::Instance->GetNameSocket()->AddValue(reticule, reticule->instanceName);
				NameTable::Instance->SetName(reticule->objectID, reticule->instanceName);
		NameTable::Instance->IsValid();

			}
			theApp.instanceWindow->ResetInstanceLists();
		}		
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void CDisplayWindow::OnSetObjectParameters()
{
	Check_Object(RightClickEntity);
	EditEntityDlg edit_dialog(NULL, RightClickEntity);
	edit_dialog.DoModal();
}

void CDisplayWindow::OnSetObjectTranslation()
{
	Entity *reticule;

	Check_Object(Player::Instance);
	Check_Object(Player::Instance->playerInterface);
	reticule = TraceToParent(Player::Instance->playerInterface->reticuleEntity.GetCurrent());

	if(reticule)
	{
		translationDlg->SetObject(reticule,theApp.GetEntityData(reticule));
		translationDlg->ShowWindow(SW_SHOW);
	}
}

void CDisplayWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (nChar == VK_TAB)
	{
		mouseLook = false;
		ReleaseCapture();
	}
	CEditorChildWnd::OnKeyUp(nChar, nRepCnt, nFlags);
}

bool CDisplayWindow::GetPointOnMap(Point3D* point)
{
	//
	//----------------------
	// Ask gos for the mouse
	//----------------------
	//
	Vector2DOf<Scalar> cursor;
	gos_GetMouseInfo(&cursor.x, &cursor.y, NULL, NULL, NULL, NULL);

	//
	//-----------------------------
	// Clean out the interface data
	//-----------------------------
	//
	CameraComponent* sceneCamera = VideoRenderer::Instance->GetSceneCamera();
	Check_Object(sceneCamera);
	EntityComponentWeb *web =
		Cast_Object(EntityComponentWeb*, sceneCamera->GetComponentWeb());
	Interface *intface = Cast_Object(Interface*, web->GetEntity());
	intface->reticuleEntity.Remove();

	//
	//-----------------------
	// Figure out the eyeline
	//-----------------------
	//
	Line3D world_line;
	sceneCamera->ComputeEyeLine(&world_line, cursor);

	Stuff::Normal3D normal;
	Stuff::Line3D line;
	Entity::CollisionQuery query(&world_line, &intface->reticuleNormal, Entity::AlwaysCollidesMask, NULL);

	CollisionGrid::Instance->ProjectLine(&query);
	world_line.FindEnd(point);

	if (point->x < -5000 || point->y < -5000 || point->z < -5000)
		return false;
	
	return true;
}

Stuff::Scalar CDisplayWindow::GetMapPointVertical(Stuff::Scalar x, Stuff::Scalar z, Entity::CollisionMask collisionType,Entity *ignore_entity)
{
	Stuff::Line3D line;
	Point3D point;

	if (x <= -(mapX*0.5f))
	{
		point = Player::Instance->GetLocalToWorld();
		collisionType = (theApp.cameraFollowing == CAMERA_FOLLOW_NONE) ? Entity::AlwaysCollidesMask : Entity::CanBeWalkedOnFlag;
	}
	else
	{
		point.x = x;
		point.z = z;
	}
	point.y = 600.0f;

	line.m_length = 1000.0f;
	line.m_direction = Vector3D::Down;
	line.SetOrigin(point);

	//
	// Prepare query
	//	
	Stuff::Normal3D inormal;
	Stuff::Line3D iline;
	Stuff::Normal3D normal;
	Adept::Entity *entity_hit;

	Check_Object(CollisionGrid::Instance);
/*
	if (theApp.cameraFollowing == CAMERA_FOLLOW_GROUND)
	{
		Entity::CollisionQuery query(&line, &normal, Entity::CanBeWalkedOnFlag, NULL);
		entity_hit = CollisionGrid::Instance->ProjectLine(&query);
	}
	else
	{
		Entity::CollisionQuery query(&line, &normal, Entity::AlwaysCollidesMask, NULL);
		entity_hit = CollisionGrid::Instance->ProjectLine(&query);
	}
*/
	Entity::CollisionQuery query(&line, &normal, collisionType,ignore_entity);
	entity_hit = CollisionGrid::Instance->ProjectLine(&query);

	if(entity_hit != NULL)
	{
		line.FindEnd(&point);
	}
	return (point.y);
}

void CDisplayWindow::OnMButtonDown(UINT nFlags, CPoint point)
{
	SetCapture();	
	CEditorChildWnd::OnMButtonDown(nFlags, point);
}

void CDisplayWindow::OnMButtonUp(UINT nFlags, CPoint point)
{
	ReleaseCapture();
	CEditorChildWnd::OnMButtonUp(nFlags, point);
}

void CDisplayWindow::OnPaint()
{
CPaintDC dc(this); // device context for painting

	if(Application::Instance->GetApplicationState()
		!= ApplicationStateEngine::RunningGameState)
	{
		
		RECT r;

		GetClientRect(&r);
		dc.FillSolidRect(&r,RGB(0,0,0));
	}
	
	// Do not call CEditorChildWnd::OnPaint() for painting messages
}

void CDisplayWindow::OnObjDamageArmor()
{
	Entity *reticule;
	reticule = TraceToParent(Player::Instance->playerInterface->reticuleEntity.GetCurrent());
	Check_Object(reticule);

	EditEntityDlg edit_dialog(NULL,reticule,EDIT_DAMAGE_OBJECTARMOR);
	edit_dialog.DoModal();
}

void CDisplayWindow::OnObjDamageInternal()
{
	Entity *reticule;
	reticule = TraceToParent(Player::Instance->playerInterface->reticuleEntity.GetCurrent());
	Check_Object(reticule);

	EditEntityDlg edit_dialog(NULL,reticule,EDIT_DAMAGE_OBJECTINTERNAL);
	edit_dialog.DoModal();
}

void CDisplayWindow::OnEditLatticeLinks()
{
//	Entity *reticule;
//	reticule = TraceToParent(Player::Instance->playerInterface->reticuleEntity.GetCurrent());
	Check_Object(RightClickEntity);//reticule);

	EditorLatticeNode* node = Cast_Object(EditorLatticeNode*,RightClickEntity);//reticule);
	if (node->railNode->NumLinks())
	{
		latticeLinkDlg->SetNode(RightClickEntity);//reticule);
		latticeLinkDlg->ShowWindow(SW_SHOW);
	}
	else
	{
		MessageBox("This lattice node currently has no links attached to it.","No Links");	// localize
	}
}

void CDisplayWindow::OnShowRadius()
{
	EditorLatticeNode* node;
	node = Cast_Object(EditorLatticeNode*,RightClickEntity);

	node->railNode->ShowRadius(!node->railNode->m_RadiusIsShowing);
}

void CDisplayWindow::OnUpdateShowRadius(CCmdUI* pCmdUI)
{
	EditorLatticeNode* node;
	node = Cast_Object(EditorLatticeNode*,RightClickEntity);

	pCmdUI->SetCheck(node->railNode->m_RadiusIsShowing);
}

void CDisplayWindow::OnAddLink()
{
	if (theApp.m_editorState == CMW4GameEdApp::SelectingObjectState)
	{
		EditorLatticeNode* node;
		node = Cast_Object(EditorLatticeNode*,RightClickEntity);

		theApp.m_editorState = CMW4GameEdApp::AddingLinkState;
		theApp.currentCommand = new AddLinkCommand(node);
	}
}

void CDisplayWindow::OnObjEditScript()
{
	theApp.instanceWindow->ObjEditScript();
}

void CDisplayWindow::OnInsertPathNode()
{
	EditorPathNode* node;
	node = Cast_Object(EditorPathNode*, RightClickEntity);

	theApp.currentCommand = new InsertPathNodeCommand(node);
	theApp.undoChain.Add(theApp.currentCommand);
	theApp.currentCommand = NULL;
}

void CDisplayWindow::OnAppendPathNode()
{
	AppendPathNode(RightClickEntity);
}

void CDisplayWindow::AppendPathNode(Entity* appendTo)
{
	EditorPathNode* node;
	node = Cast_Object(EditorPathNode*,appendTo);

	while (node->nextnode)
		node = node->nextnode;

	theApp.m_CurPath = node->pathSlot.GetCurrent();

	Entity* entity = theApp.resourceWindow->CreateNewInstance("Content\\Editor\\Reserved\\PathNode\\PathNode.data",
									   "PathNode","PathNode");
	
	CSelectionList::Instance->ClearSelectionList(true);
	CSelectionList::Instance->AddSelection(entity);
	CSelectionList::Instance->RemoveCollision();

	Point3D point;
	point = entity->GetLocalToWorld();
	theApp.m_CurPath->pathSlot.GetCurrent()->pathPoints.push_back(point);

	EditorPathNode* pathNode;
	pathNode = Cast_Object(EditorPathNode*,entity);

	theApp.m_CurPath->pathNodes.Add(pathNode);

	pathNode->pathSlot.Remove();
	pathNode->pathSlot.Add(theApp.m_CurPath);
	pathNode->index = theApp.m_CurPath->pathSlot.GetCurrent()->pathPoints.size() - 1;
	pathNode->nextnode = NULL;
	pathNode->prevnode = node;
	node->nextnode = pathNode;
	
	pathNode->CreateLink();
	theApp.m_LastPathNode = pathNode;
	theApp.m_showPaths = false;
	theApp.OnToolsMovmentlayerShowpaths();

	node->UpdateLinkPointData();

	theApp.m_editorState = CMW4GameEdApp::AddingObjectState;
	theApp.m_MultiDrop = true;
	theApp.currentCommand = new AddCommand(entity);
	Check_Object(theApp.currentCommand);
}

void CDisplayWindow::OnObjSpecifyScript()
{
	theApp.instanceWindow->OnObjSpecifyScript(RightClickEntity);
}

void CDisplayWindow::OnInsertBoundaryNode()
{
	EditorBoundaryNode* node;
	node = Cast_Object(EditorBoundaryNode*, RightClickEntity);

	theApp.currentCommand = new InsertBoundaryNodeCommand(node);
	theApp.undoChain.Add(theApp.currentCommand);
	theApp.currentCommand = NULL;
	theApp.toolBar->EnableButton(ID_EDIT_UNDO);
}

void CDisplayWindow::OnObjRemoveinstance()
{
	theApp.instanceWindow->OnObjRemoveinstance();
}

void AlignmentFillCallback(CListBox* listbox)
{
	for (int i = 0; i < Entity::LastAlignment; i++)
	{
		listbox->AddString(RightClickEntity->AlignmentAsciiToText(i));
	}
	listbox->SelectString(0,RightClickEntity->AlignmentAsciiToText(RightClickEntity->alignment));
}

void CDisplayWindow::OnObjAlignment()
{
	OnObjAlignment(RightClickEntity);
}

void CDisplayWindow::OnObjAlignment(Entity* entity)
{
	RightClickEntity = entity;

	CGenericListDlg dlg;

	dlg.m_Title = "Select Alignment";
	dlg.m_Path = "";
	dlg.m_Extension = "";
	dlg.FillCallback = AlignmentFillCallback;

	if (dlg.DoModal() == IDOK)
	{
		RightClickEntity->alignment = entity->AlignmentTextToAscii(dlg.m_Name);
		theApp.overviewWindow->DrawWindow();
	}
}

void CDisplayWindow::OnObjSubsystem()
{
	char ssPath[MAX_PATH],oldDir[MAX_PATH];
	OPENFILENAME ofn;

	_getcwd(oldDir,MAX_PATH - 1);

	memset(&ssPath,0,MAX_PATH);
	memset(&ofn,0,sizeof(ofn));

	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = NULL;
	ofn.lpstrFilter = "Subsystem files {*.subsystems}\0*.subsystems\0All Files {*.*}\0*.*\0\0";
	ofn.lpstrFile = ssPath;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_FILEMUSTEXIST;
	ofn.lpstrDefExt = "subsystems";

	if (GetOpenFileName(&ofn))
	{
		//
		//------------------------------------------------------------
		// Create messages for the subsystem stream only if it's there
		//------------------------------------------------------------
		//
		char *filename = new char [strlen(ssPath) + 1] , *p;
		p = strstr(ssPath,"Content");
		strcpy(filename,p);
		const char *subsystems_filename = filename;
//		message->subsystemStreamResourceID = ResourceID::Null;
		ResourceID subsystemStreamResourceID = ResourceID::Null;

		Check_Pointer(subsystems_filename);

		//
		//---------------------------
		// Open up the subsystem file
		//---------------------------
		//
		_chdir(oldDir);

		NotationFile subsystems_file(subsystems_filename);
		subsystems_filename = subsystems_file.GetFileName();

		//
		//------------------------------------------------------------------
		// Look for the subsystem stream resource to see if it is up to date
		//------------------------------------------------------------------
		//
		Adept::ReplicatorID baseID = Connection::Local->GetNextReplicatorID();

		Resource subsystem_resource(subsystems_filename);
		if (subsystem_resource.DoesResourceExist() &&
			subsystem_resource.IsResourceUpToDate())
		{
			WORD span;
			subsystem_resource >> span;
			Verify(span > 0);
//			*script->baseID += span;
			baseID += span;
//			message->subsystemStreamResourceID = subsystem_resource.GetResourceID();
//			message->replicatorID += span;
			subsystemStreamResourceID = subsystem_resource.GetResourceID();
		}
		else
		{
			//
			//---------------------------------------
			// For each page, an entity will be built
			//---------------------------------------
			//
			Tool::Instance->PushFilePath(&subsystems_file);
			DynamicMemoryStream subsystem_stream(sizeof(WORD));
			subsystem_stream << static_cast<WORD>(0);
//			ReplicatorID starting_id = *script->baseID;
			ReplicatorID starting_id = baseID;
			NotationFile::PageIterator *instance_names = subsystems_file.MakePageIterator();
			Check_Object(instance_names);
			Page *instance;
			while ((instance = instance_names->ReadAndNext()) != NULL)
			{
				Check_Object(instance);

				//
				//--------------------------------
				// Create the entity for this page
				//--------------------------------
				//
				const char *child_name = instance->GetName();
				Check_Pointer(child_name);
				Entity::CreateMessage *message =
					Tool::Instance->ConstructCreateMessage(
						&subsystem_stream,
						instance,
//						script->baseID
						&baseID
					);
				Check_Object(message);
				subsystem_stream.AdvancePointer(message->messageLength);
			}

			//
			//-----------------------------------------
			// Only save out the stream if there is one
			//-----------------------------------------
			//
			if (subsystem_stream.GetBytesUsed() > sizeof(WORD))
			{
				subsystem_stream.Rewind();
//				Verify(*script->baseID != starting_id);
				Verify(baseID != starting_id);
				WORD span =
//					static_cast<WORD>(script->baseID->localID - starting_id.localID);
					static_cast<WORD>(baseID.localID - starting_id.localID);
				subsystem_stream << span;
				subsystem_resource.Save(
					&subsystem_stream,
					subsystems_file.GetFileDependencies()
				);
				Check_Object(&subsystem_resource);
//				message->subsystemStreamResourceID = subsystem_resource.GetResourceID();
//				message->replicatorID += span;
				subsystemStreamResourceID = subsystem_resource.GetResourceID();
			}
			else
//				message->subsystemStreamResourceID = ResourceID::Null;
				subsystemStreamResourceID = ResourceID::Null;
			
			//
			//------------------------
			// Clean up the tool stack
			//------------------------
			//
			delete [] filename;

			Check_Object(instance_names);
			delete instance_names;
			Tool::Instance->PopFilePath();
		}

		if (subsystemStreamResourceID == ResourceID::Null)
		{
			MessageBox("Unable to load subsystem file","Subsystem Load Error");
			return;
		}
		Vehicle* vehicle;
		vehicle = Cast_Object(Vehicle*, RightClickEntity);
		Stuff::ChainIteratorOf<Subsystem*> iterator(&vehicle->subsystemsInVehicle);
		iterator.DeletePlugs();
		vehicle->LoadSubsystemsFromResource(subsystemStreamResourceID,&baseID);
		vehicle->HookUpSubsystems();
		vehicle->subsystemStreamResourceID = subsystemStreamResourceID;
	}
}

void CDisplayWindow::OnAddDropPoint()
{
	theApp.resourceWindow->TLDlg->m_ObjList.EnableWindow(FALSE);
	theApp.instanceWindow->TLDlg->m_ObjList.EnableWindow(FALSE);
	theApp.m_MultiDrop = false;

	Entity* entity = theApp.resourceWindow->CreateNewInstance(
					"Content\\Editor\\Reserved\\DropZonePoint\\DropZonePoint.data",
					"DropZonePoint","DropZonePoint");

	EditorDropZonePoint* newPoint;
	EditorDropNode* node;

	newPoint = Cast_Object(EditorDropZonePoint*, entity);
	node = Cast_Object(EditorDropNode*, RightClickEntity);

	newPoint->dropNode = node;
	newPoint->dropNode->pointChain.Add(newPoint);
	newPoint->CreateLink();

//	node->dropZone->dropPointsResourceID = newPoint->GetGameModel()

	if (theApp.currentCommand != NULL)
	{
		theApp.undoChain.Add(theApp.currentCommand);
	}
	theApp.currentCommand = new AddCommand(entity);
	theApp.m_editorState = CMW4GameEdApp::AddingObjectState;

	theApp.m_showDropZones = false;
	theApp.OnToolsMovmentlayerShowdropzones();
}

void CDisplayWindow::OnClose()
{
	KillTimer(timer);
}

void CDisplayWindow::OnDestroy()
{
	KillTimer(timer);
}

void CDisplayWindow::OnClearAI()
{
	theApp.instanceWindow->OnClearAI(RightClickEntity);
}

void CDisplayWindow::OnABLMemory()
{
	theApp.instanceWindow->OnABLMemory(RightClickEntity);
}