#include "ElementProxyHeaders.hpp"

//
//############################################################################
//########################    MLRVertexProxy    ########################
//############################################################################
//

MemoryBlock*
	MLRVertexProxy::AllocatedMemory = NULL;
MLRVertexProxy::ClassData*
	MLRVertexProxy::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::InitializeClass()
{
	Verify(!AllocatedMemory);
	AllocatedMemory =
		new MemoryBlock(
			sizeof(MLRVertexProxy),
			10,
			10,
			"MLRVertexProxy"
		);
	Register_Object(AllocatedMemory);

	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MLRVertexProxyClassID,
			"MLRVertexProxy",
			VertexProxy::DefaultData
		);
	Register_Object(DefaultData);
}

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

	Unregister_Object(AllocatedMemory);
	delete AllocatedMemory;
	AllocatedMemory = NULL;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRVertexProxy::MLRVertexProxy(
	ElementPolygonMeshProxy *mesh,
	unsigned primitive_index,
	unsigned vertex_index
	):
	VertexProxy (DefaultData, mesh),
	primitiveIndex(primitive_index),
	vertexIndex(vertex_index)
{
	Check_Pointer(this);
	Check_Object(mesh);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRVertexProxy::~MLRVertexProxy()
{
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::Destroy()
{
	Check_Object(this);
	STOP(("Not implemented"));
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VertexProxy*
	MLRVertexProxy::UseNextVertexProxy()
{
	Check_Object(this);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	return mesh->GetVertexProxy(primitiveIndex, vertexIndex+1);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VertexProxy*
	MLRVertexProxy::UsePreviousVertexProxy()
{
	Check_Object(this);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	return mesh->GetVertexProxy(primitiveIndex, vertexIndex-1);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::GetPosition(Point3D *position)
{
	Check_Object(this);
	Check_Pointer(position);

	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	
	const Point3D *array = mesh->positionArray[primitiveIndex];
	Check_Pointer(array);

	*position = array[vertexIndex];
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::SetPosition(const Point3D &position)
{
	Check_Object(this);
	Check_Object(&position);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	
	Point3D *array = mesh->positionArray[primitiveIndex];
	Check_Pointer(array);

	array[vertexIndex] = position;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MLRVertexProxy::GetColor(RGBAColor *color)
{
	Check_Object(this);
	Check_Pointer(color);

	//
	//-----------------------------
	// See if the polygon has color
	//-----------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	
	const ColorType *array = mesh->colorArray[primitiveIndex];
	if (!array)
	{
		return false;
	}

	//
	//------------------
	// Look up the color
	//------------------
	//
	Check_Pointer(array);
#if COLOR_AS_DWORD>0
	DWORD2Color(*color, array[vertexIndex]);
#else
	*color = array[vertexIndex];
#endif
	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::SetColor(const RGBAColor& color)
{
	Check_Object(this);
	Check_Object(&color);

	//
	//-----------------------------
	// See if the polygon has color
	//-----------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	ColorType *array = mesh->colorArray[primitiveIndex];
	Check_Pointer(array);
#if COLOR_AS_DWORD>0
	array[vertexIndex] = GOSCopyColor(&color);
#else
	array[vertexIndex] = color;
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MLRVertexProxy::GetNormal(Normal3D *normal)
{
	Check_Object(this);
	Check_Pointer(normal);

	//
	//-------------------------------
	// See if the polygon has normals
	//-------------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	const Vector3D *array = mesh->normalArray[primitiveIndex];
	if (!array)
	{
		return false;
	}

	//
	//-------------------
	// Look up the normal
	//-------------------
	//
	Check_Pointer(array);
	normal->Normalize(array[vertexIndex]);
	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::SetNormal(const Normal3D &normal)
{
	Check_Object(this);
	Check_Object(&normal);

	//
	//-------------------------------
	// See if the polygon has normals
	//-------------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	Vector3D *array = mesh->normalArray[primitiveIndex];
	Check_Pointer(array);
	array[vertexIndex] = normal;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MLRVertexProxy::GetUVs(DynamicArrayOf<Vector2DOf<Scalar> > *uv)
{
	Check_Object(this);
	Check_Pointer(uv);

	//
	//---------------------------
	// See if the polygon has uvs
	//---------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	Verify (
		mesh->uvArray.GetLength() == mesh->positionArray.GetLength() ||
		mesh->uvArray.GetLength() == 2*mesh->positionArray.GetLength()
	);

	const Vector2DOf<Scalar> *array = mesh->uvArray[primitiveIndex];
	if (!array)
	{
		return false;
	}

	//
	//------------------
	// Look up the uv's
	//------------------
	//
	Check_Pointer(array);

	if(mesh->primitiveArray[primitiveIndex]->GetNumPasses() == 1)
	{
		uv->SetLength(1);
		(*uv)[0] = array[vertexIndex];
	}
	else
	{
		uv->SetLength(2);
		(*uv)[0] = array[vertexIndex];
		(*uv)[1] = array[vertexIndex + mesh->vertexCountArray[primitiveIndex]];
	}

	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRVertexProxy::SetUVs(DynamicArrayOf<Vector2DOf<Scalar> > &uv)
{
	Check_Object(this);
	Check_Object(&uv);

	//
	//---------------------------
	// See if the polygon has uvs
	//---------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	Vector2DOf<Scalar> *array = mesh->uvArray[primitiveIndex];
	Check_Pointer(array);

	if(mesh->primitiveArray[primitiveIndex]->GetNumPasses() == 1)
	{
		Verify(uv.GetLength() > 0);
		array[vertexIndex] = uv[0];
	}
	else
	{
		Verify(uv.GetLength() > 1);
		array[vertexIndex] = uv[0];
		array[vertexIndex+mesh->vertexCountArray[primitiveIndex]] = uv[1];
	}
}

