#include "stdafx.h"
#include <Stuff\StuffHeaders.hpp>
#include "EditorWaypoint.h"
#include <Adept\Mission.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <Adept\EntityManager.hpp>
#include "MW4GameEd.h"
#include <Adept\Map.hpp>
#include <Adept\LightManager.hpp>
#include "DisplayWindow.h"
#include "ResourceWindow.h"
#include <MW4\MWTool.hpp>
#include "LightWnd.h"


EditorWaypoint::ClassData*
	EditorWaypoint::DefaultData = NULL;

extern CMW4GameEdApp theApp;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorWaypoint::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorWaypointClassID,
			"EditorWaypoint",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorWaypoint::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorWaypoint*
	EditorWaypoint::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorWaypoint *new_entity = new EditorWaypoint(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorWaypoint::EditorWaypoint(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	Entity(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorWaypoint::~EditorWaypoint()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorWaypoint::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}


EditorPathNode::ClassData*
	EditorPathNode::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPathNode::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorPathNodeClassID,
			"EditorPathNode",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPathNode::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPathNode*
	EditorPathNode::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorPathNode *new_entity = new EditorPathNode(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPathNode::EditorPathNode(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element),
	pathSlot(NULL)
{
	Check_Pointer(this);
	Check_Object(message);

	m_PathLinkLineCloud = NULL;
	m_PathLinkPointCount = 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPathNode::~EditorPathNode()
{
	if (m_PathLinkLineCloud)
	{
		Unregister_Object(m_PathLinkLineCloud);
		delete m_PathLinkLineCloud;
		m_PathLinkLineCloud = NULL;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPathNode::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorPathNode::InsertNode(EditorPathNode* node)
{
	// node is inserted in front of this

	Point3D point,prevPoint;
	point = GetLocalToWorld();
	prevPoint = (prevnode) ? prevnode->GetLocalToWorld() : LinearMatrix4D::Identity;

	point.x += (point.x > prevPoint.x) ? -5.0f : 5.0f;
	point.z += (point.z > prevPoint.z) ? -5.0f : 5.0f;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z) + 1.0f;

	LinearMatrix4D matrix = LinearMatrix4D::Identity;
	matrix.BuildTranslation(point);
	node->SetNewLocalToParent(matrix);
	node->SyncMatrices(true);
	
	pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints.push_back(point);

	node->pathSlot.Remove();
	node->pathSlot.Add(pathSlot.GetCurrent());
	node->prevnode = prevnode;
	node->nextnode = this;
	if (prevnode)
		prevnode->nextnode = node;
	prevnode = node;

	EditorPathNode* n = node;
	int newIndex = index;
	while (n)
	{
		n->index = newIndex++;
		point = n->GetLocalToWorld();
		pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[n->index] = point;
		n = n->nextnode;
	}
	
	node->CreateLink();
	if (node->prevnode)
		node->prevnode->UpdateLinkPointData();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorPathNode::UpdateLinkPointData(bool calledFromOtherNode)
{
	m_PathLinkPointData[0] = pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[index];
	m_PathLinkPointData[0].y += 0.6f;
	if (nextnode)
		m_PathLinkPointData[1] = pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[index + 1];
	else
		m_PathLinkPointData[1] = pathSlot.GetCurrent()->pathSlot.GetCurrent()->pathPoints[index];
	m_PathLinkPointData[1].y += 0.65f;

	if (prevnode && !calledFromOtherNode)
		prevnode->UpdateLinkPointData(true);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorBoundaryNode::ClassData*
	EditorBoundaryNode::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorBoundaryNode::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorBoundaryNodeClassID,
			"EditorBoundaryNode",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorBoundaryNode::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorBoundaryNode*
	EditorBoundaryNode::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorBoundaryNode *new_entity = new EditorBoundaryNode(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorBoundaryNode::EditorBoundaryNode(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
myBoundary=NULL;
firstBoundaryNode=NULL;
	m_PathLinkLineCloud = NULL;
	m_PathLinkPointCount = 0;

	index = -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorBoundaryNode::~EditorBoundaryNode()
{
	if (m_PathLinkLineCloud)
	{
		Unregister_Object(m_PathLinkLineCloud);
		delete m_PathLinkLineCloud;
		m_PathLinkLineCloud = NULL;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorBoundaryNode::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorBoundaryNode::UpdateLinkPointData(bool calledFromOtherNode)
{
Verify(myBoundary);
	m_PathLinkPointData[0].x = (*myBoundary)[index].x;
	m_PathLinkPointData[0].z = (*myBoundary)[index].y;
	m_PathLinkPointData[0].y = theApp.displayWindow->GetMapPointVertical(m_PathLinkPointData[0].x,m_PathLinkPointData[0].z) + 0.6f;

	int i = nextnode->index;
	m_PathLinkPointData[1].x = (*myBoundary)[i].x;
	m_PathLinkPointData[1].z = (*myBoundary)[i].y;
	m_PathLinkPointData[1].y = theApp.displayWindow->GetMapPointVertical(m_PathLinkPointData[1].x,m_PathLinkPointData[1].z) + 0.6f;

//	Adept::Mission::Instance->SetMissionPolygon(theApp.missionBoundary);

	if (!calledFromOtherNode)
		prevnode->UpdateLinkPointData(true);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorBoundaryNode::InsertNode(EditorBoundaryNode* node)
{
	// node is inserted in front of this

	Point3D point,prevPoint;
	point = GetLocalToWorld();
	prevPoint = (prevnode) ? prevnode->GetLocalToWorld() : LinearMatrix4D::Identity;

	point.x += (point.x > prevPoint.x) ? -5.0f : 5.0f;
	point.z += (point.z > prevPoint.z) ? -5.0f : 5.0f;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z) + 1.0f;

	LinearMatrix4D matrix = LinearMatrix4D::Identity;
	matrix.BuildTranslation(point);
	node->SetNewLocalToParent(matrix);
	node->SyncMatrices(true);

	Verify(myBoundary);
	
	int length = myBoundary->GetLength();
	myBoundary->SetLength(length + 1);
	(*myBoundary)[length].x = point.x;
	(*myBoundary)[length].y = point.z;

	node->prevnode = prevnode;
	node->nextnode = this;
	prevnode->nextnode = node;
	prevnode = node;

	EditorBoundaryNode* n = node->firstBoundaryNode;

	for (int newIndex = 0; newIndex <= length; newIndex++)
	{
		n->index = newIndex;
		point = n->GetLocalToWorld();
		(*myBoundary)[n->index].x = point.x;
		(*myBoundary)[n->index].y = point.z;
		n = n->nextnode;
	}

	node->CheckValidPos();

//	Adept::Mission::Instance->SetMissionPolygon(theApp.missionBoundary);
	
	node->CreateLink();
	node->prevnode->UpdateLinkPointData();
}


bool EditorBoundaryNode::CheckValidPos()
{
	if (index < 0)
		return false;
	Verify(myBoundary);

	bool valid = true;
	Vector2DOf<Scalar> leg1, leg2;
	leg1.Subtract((*myBoundary)[index], (*myBoundary)[prevnode->index]);
	leg2.Subtract((*myBoundary)[nextnode->index], (*myBoundary)[index]);

	Scalar area = leg1.y*leg2.x - leg1.x*leg2.y;
	if (area < 0.0f)
		valid = false;

	leg1.Subtract((*myBoundary)[prevnode->index], (*myBoundary)[prevnode->prevnode->index]);
	leg2.Subtract((*myBoundary)[index], (*myBoundary)[prevnode->index]);

	area = leg1.y*leg2.x - leg1.x*leg2.y;
	if (area < 0.0f)
		valid = false;

	leg1.Subtract((*myBoundary)[nextnode->index], (*myBoundary)[index]);
	leg2.Subtract((*myBoundary)[nextnode->nextnode->index], (*myBoundary)[nextnode->index]);

	area = leg1.y*leg2.x - leg1.x*leg2.y;
	if (area < 0.0f)
		valid = false;

	if (valid)
	{
		GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawGreenBounds);
	}
	else
	{
		GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawRedBounds);
	}
	return (valid);
}




EditorLatticeNode::ClassData*
	EditorLatticeNode::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLatticeNode::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorLatticeNodeClassID,
			"EditorLatticeNode",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLatticeNode::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLatticeNode*
	EditorLatticeNode::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorLatticeNode *new_entity = new EditorLatticeNode(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLatticeNode::EditorLatticeNode(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	railNode = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLatticeNode::~EditorLatticeNode()
{
	railNode = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLatticeNode::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

void
	EditorPathNode::CreateLink()
{
	gos_PushCurrentHeap(ElementRenderer::g_Heap);

	m_PathLinkPointCount = 2;
	m_PathLinkLineCloud = new ElementRenderer::LineCloudElement(m_PathLinkPointCount);
	Register_Object(m_PathLinkLineCloud);
	UpdateLinkPointData();
	SetLinkColor(Stuff::RGBAColor(192,192,192,0));

	m_PathLinkLineCloud->SetDataPointers(&m_PathLinkPointCount, m_PathLinkPointData, m_PathLinkColorData);
	m_PathLinkLineCloud->m_localOBB.localToParent = LinearMatrix4D::Identity;

	Vector3D vector;
	Point3D point0(m_PathLinkPointData[0].x,m_PathLinkPointData[0].y,m_PathLinkPointData[0].z);
	Point3D point1(m_PathLinkPointData[1].x,m_PathLinkPointData[1].y,m_PathLinkPointData[1].z);
	vector.Subtract(point0,point1);

	Scalar length = vector.GetLength();

	m_PathLinkLineCloud->m_localOBB.sphereRadius = length;

	Check_Object(Mission::Instance);
	Mission::Instance->GetElement()->AttachChild(m_PathLinkLineCloud);

//	m_PathLinkLineCloud->SetName("Path Link Line Cloud");

	m_PathLinkLineCloud->m_localOBB.localToParent(3,0) = (m_PathLinkPointData[0].x + m_PathLinkPointData[1].x) / 2;
	m_PathLinkLineCloud->m_localOBB.localToParent(3,1) = (m_PathLinkPointData[0].y + m_PathLinkPointData[1].y) / 2;
	m_PathLinkLineCloud->m_localOBB.localToParent(3,2) = (m_PathLinkPointData[0].z + m_PathLinkPointData[1].z) / 2;
	m_PathLinkLineCloud->NeedNewBounds();
	m_PathLinkLineCloud->NeedMatrixSync();
	ShowLink(false);

	ElementRenderer::StateChange *state = new 	ElementRenderer::StateChange();
	Check_Object(state);

	state->DisableZBufferCompare();

	m_PathLinkLineCloud->AdoptStateChange(state);

	m_PathLinkLineCloud->Sync();

	gos_PopCurrentHeap();
}

void
	EditorBoundaryNode::CreateLink()
{
	gos_PushCurrentHeap(ElementRenderer::g_Heap);

	m_PathLinkPointCount = 2;
	m_PathLinkLineCloud = new ElementRenderer::LineCloudElement(m_PathLinkPointCount);
	Register_Object(m_PathLinkLineCloud);
	UpdateLinkPointData();
	SetLinkColor(Stuff::RGBAColor(192,192,192,0));

	m_PathLinkLineCloud->SetDataPointers(&m_PathLinkPointCount, m_PathLinkPointData, m_PathLinkColorData);
	m_PathLinkLineCloud->m_localOBB.localToParent = LinearMatrix4D::Identity;

	Vector3D vector;
	Point3D point0(m_PathLinkPointData[0].x,m_PathLinkPointData[0].y,m_PathLinkPointData[0].z);
	Point3D point1(m_PathLinkPointData[1].x,m_PathLinkPointData[1].y,m_PathLinkPointData[1].z);
	vector.Subtract(point0,point1);

	Scalar length = vector.GetLength();

	m_PathLinkLineCloud->m_localOBB.sphereRadius = length;

	Check_Object(Mission::Instance);
	Mission::Instance->GetElement()->AttachChild(m_PathLinkLineCloud);

//	m_PathLinkLineCloud->SetName("Path Link Line Cloud");

	m_PathLinkLineCloud->m_localOBB.localToParent(3,0) = (m_PathLinkPointData[0].x + m_PathLinkPointData[1].x) / 2;
	m_PathLinkLineCloud->m_localOBB.localToParent(3,1) = (m_PathLinkPointData[0].y + m_PathLinkPointData[1].y) / 2;
	m_PathLinkLineCloud->m_localOBB.localToParent(3,2) = (m_PathLinkPointData[0].z + m_PathLinkPointData[1].z) / 2;
	m_PathLinkLineCloud->NeedNewBounds();
	m_PathLinkLineCloud->NeedMatrixSync();
	ShowLink(false);

	ElementRenderer::StateChange *state = new ElementRenderer::StateChange();
	Check_Object(state);

	state->DisableZBufferCompare();

	m_PathLinkLineCloud->AdoptStateChange(state);

	m_PathLinkLineCloud->Sync();

	gos_PopCurrentHeap();
}




EditorDropNode::ClassData*
	EditorDropNode::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropNode::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorDropNodeClassID,
			"EditorDropNode",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropNode::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorDropNode*
	EditorDropNode::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorDropNode *new_entity = new EditorDropNode(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorDropNode::EditorDropNode(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element),
	pointChain(NULL)
{
	Check_Pointer(this);
	Check_Object(message);

	dropZone = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorDropNode::SetDropZone(Adept::DropZone* zone)
{
	if (zone)
	{
		Check_Object(zone);
		dropZone = zone;
	}
	else
	{
		Page *dropzone_page = theApp.resourceWindow->objectInformation->SetPage("DropZone");
		Check_Object(dropzone_page);
		dropzone_page->SetEntry("Model", "misc\\DropZone.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			dropzone_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);
		 NameTable::Instance->AddEntry(entity, NameTable::DropZoneArray);
		NameTable::Instance->IsValid();

		theApp.resourceWindow->numEntitiesAdded++;

		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		entity->SyncMatrices(true);

		entity->GetElement()->Sync();

		dropZone = Cast_Object(Adept::DropZone*,entity);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorDropNode::~EditorDropNode()
{
	dropZone = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropNode::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorDropNode::UpdatePoints()
{
	Check_Object(this);
	Check_Object(dropZone);

	EditorDropZonePoint* point;
	LinearMatrix4D loc;
	PlugOf<LinearMatrix4D> *plug;
	ChainIteratorOf<PlugOf<LinearMatrix4D>*> dropIterator(&dropZone->dropMats);
	ChainIteratorOf<EditorDropZonePoint*> pointIterator(&pointChain);
	dropIterator.DeletePlugs();

	while((point = pointIterator.ReadAndNext()) != NULL)
	{
		loc = point->GetLocalToWorld();
		plug = new PlugOf<LinearMatrix4D>(loc);
		dropZone->dropMats.Add(plug);
	}
	LinearMatrix4D new_position = GetLocalToWorld();
	dropZone->SetNewLocalToParent(new_position);
	dropZone->SyncMatrices(true);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
/*
void EditorDropNode::MakePointsResource(const char *resource_name)
{
	Check_Object(this);
	ChainIteratorOf<DropZone::PointPlug*> iterator(&dropZone->dropPoints);
	int num_points = iterator.GetSize();
	if(num_points > 0)
	{
		Resource drop_point_resource(resource_name);
		DynamicMemoryStream drop_stream;
		DropZone::PointPlug *drop_point;

		drop_stream << num_points;
		while((drop_point = iterator.ReadAndNext()) != NULL)
		{
			Check_Object(drop_point);
			drop_stream << drop_point->GetItem();
		}
		drop_point_resource.Save(&drop_stream, NULL);
		dropZone->dropPointsResourceID = drop_point_resource.GetResourceID();
	}
	else
	{
		dropZone->dropPointsResourceID = ResourceID::Null;
	}
}
*/


EditorDropZonePoint::ClassData*	EditorDropZonePoint::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorDropZonePoint::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorDropZonePointClassID,
			"EditorDropZonePoint",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropZonePoint::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	EditorDropZonePoint*
	EditorDropZonePoint::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorDropZonePoint *new_entity = new EditorDropZonePoint(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorDropZonePoint::EditorDropZonePoint(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	dropNode = NULL;

	m_PointLineCloud = NULL;
	m_PointCount = 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorDropZonePoint::~EditorDropZonePoint()
{
	dropNode = NULL;
	if (m_PointLineCloud)
	{
		Unregister_Object(m_PointLineCloud);
		delete m_PointLineCloud;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropZonePoint::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorDropZonePoint::CreateLink()
{
	gos_PushCurrentHeap(ElementRenderer::g_Heap);

	m_PointCount = 2;
	m_PointLineCloud = new ElementRenderer::LineCloudElement(m_PointCount);
	Register_Object(m_PointLineCloud);
	UpdateLinkPointData();
	SetLinkColor(Stuff::RGBAColor(255,0,0,0));

	m_PointLineCloud->SetDataPointers(&m_PointCount, m_PointData, m_PointColorData);
	m_PointLineCloud->m_localOBB.localToParent = LinearMatrix4D::Identity;

	Vector3D vector;
	Point3D point0(m_PointData[0].x,m_PointData[0].y,m_PointData[0].z);
	Point3D point1(m_PointData[1].x,m_PointData[1].y,m_PointData[1].z);
	vector.Subtract(point0,point1);

	Scalar length = vector.GetLength();

	m_PointLineCloud->m_localOBB.sphereRadius = length;

	Check_Object(Mission::Instance);
	Mission::Instance->GetElement()->AttachChild(m_PointLineCloud);

//	m_PointLineCloud->SetName("Drop Point Line Cloud");

	m_PointLineCloud->m_localOBB.localToParent(3,0) = (m_PointData[0].x + m_PointData[1].x) / 2;
	m_PointLineCloud->m_localOBB.localToParent(3,1) = (m_PointData[0].y + m_PointData[1].y) / 2;
	m_PointLineCloud->m_localOBB.localToParent(3,2) = (m_PointData[0].z + m_PointData[1].z) / 2;
	m_PointLineCloud->NeedNewBounds();
	m_PointLineCloud->NeedMatrixSync();
	ShowLink(true);

	ElementRenderer::StateChange *state = new ElementRenderer::StateChange();
	Check_Object(state);

	state->DisableZBufferCompare();

	m_PointLineCloud->AdoptStateChange(state);

	m_PointLineCloud->Sync();

	gos_PopCurrentHeap();
}

void EditorDropZonePoint::UpdateLinkPointData()
{
	m_PointData[0] = GetLocalToWorld();
	m_PointData[0].y += 0.3f;
	m_PointData[1] = dropNode->GetLocalToWorld();
	m_PointData[1].y += 0.3f;
}



EditorObjectiveMarker::ClassData*
	EditorObjectiveMarker::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorObjectiveMarker::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorObjectiveMarkerClassID,
			"EditorObjectiveMarker",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorObjectiveMarker::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorObjectiveMarker*
	EditorObjectiveMarker::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorObjectiveMarker *new_entity = new EditorObjectiveMarker(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorObjectiveMarker::EditorObjectiveMarker(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorWaypoint(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	objective = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void EditorObjectiveMarker::SetObjective(MechWarrior4::Objective* obj)
{
	if (obj)
	{
		Check_Object(obj);
		objective = obj;
	}
	else
	{
		Page *objective_page = theApp.resourceWindow->objectInformation->SetPage("Objective");
		Check_Object(objective_page);
		objective_page->SetEntry("Model", "Misc\\Objective.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			objective_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 = "Objective_";
		char string[32];
		entity->instanceName += itoa(theApp.resourceWindow->numEntitiesAdded,string,10);

//		EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
		 NameTable::Instance->AddEntry(entity, NameTable::ObjectiveArray);
		NameTable::Instance->IsValid();

		theApp.resourceWindow->numEntitiesAdded++;

		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		entity->SyncMatrices(true);

		entity->GetElement()->SetAlwaysCullMode();
		entity->GetElement()->Sync();

		objective = Cast_Object(MechWarrior4::Objective*,entity);
		objective->m_ObjectiveID = theApp.m_NumObjectives++;
		objective->SetName (entity->instanceName,true);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorObjectiveMarker::~EditorObjectiveMarker()
{
	objective = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorObjectiveMarker::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}



EditorMovementPath::ClassData*
	EditorMovementPath::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorMovementPath::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorMovementPathClassID,
			"EditorMovementPath",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorMovementPath::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorMovementPath*
	EditorMovementPath::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorMovementPath *new_entity = new EditorMovementPath(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorMovementPath::EditorMovementPath(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	Entity(class_data, message, base_id, element),
	pathNodes(NULL),
	pathSlot(NULL)
{
	Check_Pointer(this);
	Check_Object(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorMovementPath::~EditorMovementPath()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorMovementPath::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}


EditorLight::ClassData*
	EditorLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLight::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorLightClassID,
			"EditorLight",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLight*
	EditorLight::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorLight *new_entity = new EditorLight(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLight::EditorLight(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	Entity(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	lightInfo.m_color.red = 1.0f;
	lightInfo.m_color.green = 0.0f;
	lightInfo.m_color.blue = 0.0f;
	lightInfo.m_origin = LinearMatrix4D::Identity;
	lightInfo.m_intensity = 1.0f;
	lightInfo.m_inner = 25.0f;
	lightInfo.m_outer = 50.0f;
	lightInfo.m_spread = Radians_Per_Degree * 20.0f;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorLight::~EditorLight()
{
	if (theApp.lightDlg && theApp.lightDlg->GetLight() == this)
		theApp.lightDlg->ShowWindow(SW_HIDE);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}


EditorAmbientLight::ClassData*
	EditorAmbientLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorAmbientLight::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorAmbientLightClassID,
			"EditorAmbientLight",
			EditorLight::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorAmbientLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorAmbientLight*
	EditorAmbientLight::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorAmbientLight *new_entity = new EditorAmbientLight(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);

	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorAmbientLight::EditorAmbientLight(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorLight(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorAmbientLight::~EditorAmbientLight()
{
//	Adept::TiledLightManager::Instance->DeleteLight(light);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorAmbientLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}


EditorInfiniteLight::ClassData*
	EditorInfiniteLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorInfiniteLight::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorInfiniteLightClassID,
			"EditorInfiniteLight",
			EditorLight::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorInfiniteLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorInfiniteLight*
	EditorInfiniteLight::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorInfiniteLight *new_entity = new EditorInfiniteLight(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorInfiniteLight::EditorInfiniteLight(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorLight(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorInfiniteLight::~EditorInfiniteLight()
{
//	Adept::TiledLightManager::Instance->DeleteLight(light);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorInfiniteLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}


EditorPointLight::ClassData*
	EditorPointLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPointLight::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorPointLightClassID,
			"EditorPointLight",
			EditorLight::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPointLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPointLight*
	EditorPointLight::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorPointLight *new_entity = new EditorPointLight(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);

	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPointLight::EditorPointLight(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorLight(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorPointLight::~EditorPointLight()
{
//	Adept::TiledLightManager::Instance->DeleteLight(light);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorPointLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}



EditorSpotLight::ClassData*
	EditorSpotLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorSpotLight::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorSpotLightClassID,
			"EditorSpotLight",
			EditorLight::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorSpotLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorSpotLight*
	EditorSpotLight::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorSpotLight *new_entity = new EditorSpotLight(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorSpotLight::EditorSpotLight(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	EditorLight(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorSpotLight::~EditorSpotLight()
{
//	Adept::TiledLightManager::Instance->DeleteLight(light);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorSpotLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

void EditorLight::SetColor(Scalar Red, Scalar Green, Scalar Blue)
{
	lightInfo.m_color.red = Red;
	lightInfo.m_color.green = Green;
	lightInfo.m_color.blue = Blue;

	light->ChangeLight(&lightInfo);
}

void EditorLight::SetLightToWorldMatrix(LinearMatrix4D matrix)
{
	lightInfo.m_origin = matrix;

	light->ChangeLight(&lightInfo);
}

void EditorLight::UpdateLight()
{
	light->ChangeLight(&lightInfo);
}

void EditorLight::LightSwitch()
{
	if (lightInfo.m_intensity == 0)	// are we off?
	{
		lightInfo.m_intensity = lastIntensity;
	}
	else
	{
		lastIntensity = lightInfo.m_intensity;
		lightInfo.m_intensity = 0;
	}
	light->ChangeLight(&lightInfo);
}

void EditorLight::SetLight(gosFX::Light* gosLight)
{
	if (gosLight)
	{
		light = gosLight;
		return;
	}

	if (IsDerivedFrom(EditorAmbientLight::DefaultData))
		light = Adept::TiledLightManager::Instance->MakeAmbientLight();
	else if (IsDerivedFrom(EditorInfiniteLight::DefaultData))
		light = Adept::TiledLightManager::Instance->MakeInfiniteLight();
	else if (IsDerivedFrom(EditorPointLight::DefaultData))
		light = Adept::TiledLightManager::Instance->MakePointLight();
	else if (IsDerivedFrom(EditorSpotLight::DefaultData))
		light = Adept::TiledLightManager::Instance->MakeSpotLight();

	light->ChangeLight(&lightInfo);
}


EditorCameraShip::ClassData*
	EditorCameraShip::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorCameraShip::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorCameraShipClassID,
			"EditorCameraShip",
			Entity::DefaultData,
			NULL, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorCameraShip::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorCameraShip*
	EditorCameraShip::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	EditorCameraShip *new_entity = new EditorCameraShip(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorCameraShip::EditorCameraShip(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	Entity(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	cameraShip = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorCameraShip::~EditorCameraShip()
{
	cameraShip = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void 
	EditorCameraShip::SetCameraShip(MechWarrior4::CameraShip* ship)
{
	if (ship == NULL)
	{
		Page *camera_page = theApp.resourceWindow->objectInformation->SetPage("CameraShip");
		Check_Object(camera_page);
		camera_page->SetEntry("Model", "misc\\CameraShip.data");
		DynamicMemoryStream entity_stream;
		ReplicatorID entity_id = ReplicatorID::Null;
		Tool::Instance->ConstructCreateMessage(
			&entity_stream,
			camera_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);

		EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
		 NameTable::Instance->AddEntry(entity, NameTable::DefaultArray);
		NameTable::Instance->IsValid();

		theApp.resourceWindow->numEntitiesAdded++;

		Map::Instance->AddChild(entity);
		MLRTexturePool::Instance->LoadImages();
		entity->SetPropType(Entity::MissionPropType);
		entity->SyncMatrices(true);

		entity->GetElement()->Sync();

		cameraShip = Cast_Object(MechWarrior4::CameraShip*,entity);
	}
	else
	{
		Check_Object(ship);
		cameraShip = ship;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorCameraShip::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}
