#include "ProxyHeaders.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	TextureProxy::Copy(
		CopyProcess *process,
		TextureProxy *texture
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(texture);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(texture);
	if (!process->continueProcess)
		return;

	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (texture->GetName(&name))
		SetName(name);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	StateProxy::Copy(
		CopyProcess *process,
		StateProxy *state
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(state);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(state);
	if (!process->continueProcess)
		return;

	bool onOff;
	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (state->GetName(&name))
		SetName(name);

	AlphaMode alphaMode;

	if(state->GetAlpha(&alphaMode))
		SetAlpha(alphaMode);

	SetAlphaChildPermission(state->GetAlphaChildPermission());

	FilterMode filterMode;

	if(state->GetFilter(&filterMode))
		SetFilter(filterMode);

	SetFilterChildPermission(state->GetFilterChildPermission());

	FogMode fogMode;
	if(state->GetFog(&fogMode))
		SetFog(fogMode);

	SetFogChildPermission(state->GetFogChildPermission());

	if(state->GetDither(&onOff))
		SetDither(onOff);

	SetDitherChildPermission(state->GetDitherChildPermission());

	if(state->GetSpecular(&onOff))
		SetSpecular(onOff);

	SetSpecularChildPermission(state->GetSpecularChildPermission());

	if(state->GetTextureCorrection(&onOff))
		SetTextureCorrection(onOff);

	SetTextureCorrectionChildPermission(state->GetTextureCorrectionChildPermission());

	TextureWrapMode textureWrapMode;

	if(state->GetTextureWrap(&textureWrapMode))
		SetTextureWrap(textureWrapMode);

	SetTextureWrapChildPermission(state->GetTextureWrapChildPermission());

	WireFrameMode wireFrameMode;

	if(state->GetWireFrame(&wireFrameMode))
		SetWireFrame(wireFrameMode);

	SetWireFrameChildPermission(state->GetWireFrameChildPermission());

	if(state->GetZBufferCompare(&onOff))
		SetZBufferCompare(onOff);

	SetZBufferCompareChildPermission(state->GetZBufferCompareChildPermission());

	if(state->GetZBufferWrite(&onOff))
		SetZBufferWrite(onOff);

	SetZBufferWriteChildPermission(state->GetZBufferWriteChildPermission());

	if(state->GetFlatColoring(&onOff))
		SetFlatColoring(onOff);

	SetFlatColoringChildPermission(state->GetFlatColoringChildPermission());

	if(state->GetBackface(&onOff))
		SetBackface(onOff);

	SetBackfaceChildPermission(state->GetBackfaceChildPermission());

	int priority;

	if(state->GetPriority(&priority))
		SetPriority(priority);

	SetPriorityChildPermission(state->GetPriorityChildPermission());

	int lightingMode;

	if(state->GetLighting(&lightingMode))
		SetLighting(lightingMode);

	SetLightingChildPermission(state->GetLightingChildPermission());

	bool bFlatColor;
	if (state->GetFlatColoring(&bFlatColor))
		SetFlatColoring(bFlatColor);

	//
	//------------------------
	// Copy the specular color
	//------------------------
	//
	RGBColor color;
	if (state->GetSpecularColor(&color))
	{
		SetSpecularColor(color);
		SetSpecularShininess(state->GetSpecularShininess());
	}

	//
	//-----------------
	// Copy the texture
	//-----------------
	//
	TextureProxy *texture = state->UseTextureProxy();
	if (texture)
	{
		TextureProxy *our_texture = SetToMatchTextureProxy(texture);
		our_texture->DetachReference();
		texture->DetachReference();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GroupProxy::Copy(
		CopyProcess *process,
		GroupProxy *group
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(group);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(group);
	if (!process->continueProcess)
		return;

	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (group->GetName(&name))
		SetName(name);

	//
	//-------------------
	// Copy the transform
	//-------------------
	//
	LinearMatrix4D matrix;
	if (group->GetLocalToParent(&matrix))
		SetLocalToParent(matrix);

	//
	//---------------------------------------------------------
	// For each child in the source, copy it to the destination
	//---------------------------------------------------------
	//
	ChildProxy *child = group->UseFirstChildProxy();
	while (child)
	{
		Check_Object(child);
		ChildProxy *proxy = AppendMatchingChildProxy(process, child);
		if (proxy)
			proxy->DetachReference();
		ChildProxy *next = child->UseNextSiblingProxy();
		child->DetachReference();
		if (process->continueProcess)
			child = next;
		else if (next)
		{
			Check_Object(next);
			next->DetachReference();
			break;
		}
		else
			break;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	LightProxy::Copy(
		CopyProcess *process,
		LightProxy *light
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(light);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(light);
	if (!process->continueProcess)
		return;

	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (light->GetName(&name))
		SetName(name);

	//
	//---------------
	// Copy the color
	//---------------
	//
	RGBColor color;
	light->GetColor(&color);
	SetColor(color);

	//
	//------------------------
	// Handle the ambient case
	//------------------------
	//
	if (light->IsAmbient())
		SetAmbient(true);

	//
	//-------------------
	// Copy the transform
	//-------------------
	//
	else
	{
		LinearMatrix4D matrix;
		if (light->GetLocalToParent(&matrix))
			SetLocalToParent(matrix);

		//
		//----------------------------------------------------------------------
		// Deal with falloff.  Only lights with falloff can have a spread angle,
		// and if the light has no falloff, it must be infinite
		//----------------------------------------------------------------------
		//
		Scalar n, f;
		if (light->GetFalloffDistance(&n, &f))
		{
			SetFalloffDistance(n, f);
			Radian spread;
			if (light->GetSpreadAngle(&spread))
				SetSpreadAngle(spread);
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	VertexProxy::Copy(
		CopyProcess *process,
		VertexProxy *vertex
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(vertex);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(vertex);
	if (!process->continueProcess)
		return;

	//
	//------------------
	// Copy the position
	//------------------
	//
	Point3D position;
	vertex->GetPosition(&position);
	SetPosition(position);

	//
	//-------------------------------
	// Copy the color if there is one
	//-------------------------------
	//
	RGBAColor color;
	if (vertex->GetColor(&color))
		SetColor(color);

	//
	//--------------------------------
	// Copy the normal if there is one
	//--------------------------------
	//
	Normal3D normal;
	if (vertex->GetNormal(&normal))
		SetNormal(normal);

	//
	//--------------------------------
	// Copy the uv if there is one
	//--------------------------------
	//
	Stuff::DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > uv;
	if (vertex->GetUVs(&uv))
		SetUVs(uv);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	PolygonMeshProxy::Copy(
		CopyProcess *process,
		PolygonMeshProxy *mesh
	)
{
	Check_Object(this);
	Check_Object(mesh);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(mesh);
	if (!process->continueProcess)
		return;

	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (mesh->GetName(&name))
	{
		SetName(name);
	}

	//
	//-------------------
	// Copy the transform
	//-------------------
	//
	LinearMatrix4D matrix;
	if (mesh->GetLocalToParent(&matrix))
	{
		SetLocalToParent(matrix);
	}

	//
	//---------------------------------------------------------------
	// Get the polygons of the source mesh, then analyze their states
	//---------------------------------------------------------------
	//
	DynamicArrayOf<PolygonProxy*> source_polygons;
	#if defined(_ARMOR)
		unsigned total_polys =
	#endif
	mesh->UsePolygonArray(&source_polygons);
	Verify(total_polys == source_polygons.GetLength());
	AddPolygons(process, source_polygons);
	mesh->DetachArrayReferences(&source_polygons);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	TextureLibrary::Copy(
		CopyProcess *process,
		TextureLibrary *library
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(library);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(this);
	if (!process->continueProcess)
		return;

	//
	//------------------------------------------------------------------
	// For each texture, copy the source mesh texture to the destination
	//------------------------------------------------------------------
	//
	TextureProxy *other_texture = library->UseFirstTextureProxy();
	while (other_texture)
	{
		Check_Object(other_texture);
		TextureProxy *texture = UseMatchingTextureProxy(other_texture);
		texture->DetachReference();
		TextureProxy *next = other_texture->UseNextTextureProxyInLibrary();
		other_texture->DetachReference();
		if (process->continueProcess)
			other_texture = next;
		else if (next)
		{
			Check_Object(next);
			next->DetachReference();
			break;
		}
		else
			break;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SceneProxy::Copy(
		CopyProcess *process,
		SceneProxy *scene
	)
{
	Check_Object(this);
	Check_Object(process);
	Check_Object(scene);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->CopyCallback(scene);
	if (!process->continueProcess)
		return;

	//
	//--------------
	// Copy the name
	//--------------
	//
	MString name;
	if (scene->GetName(&name))
		SetName(name);

	//
	//---------------------------------------------------------
	// For each child in the source, copy it to the destination
	//---------------------------------------------------------
	//
	ChildProxy *child = scene->UseFirstChildProxy();
	while (child)
	{
		Check_Object(child);
		ChildProxy *proxy = AppendMatchingChildProxy(process, child);
		if (proxy)
			proxy->DetachReference();
		ChildProxy *next = child->UseNextSiblingProxy();
		child->DetachReference();
		if (process->continueProcess)
			child = next;
		else if (next)
		{
			Check_Object(next);
			next->DetachReference();
			break;
		}
		else
			break;
	}
}
