/*
	FILE:	Motoko_Sort.c
	
	AUTHOR:	Brent H. Pease
	
	CREATED: July 30, 1999
	
	PURPOSE: Interface to the Motoko 3D engine
	
	Copyright 1997

*/

#include <stdlib.h>

#include "BFW.h"
#include "BFW_Motoko.h"

#include "Motoko_Manager.h"
#include "Motoko_Private.h"
#include "Motoko_Sort.h"
#include "BFW_AppUtilities.h"

M3tTextureCoord sprite_uv[4] = { { 0.f, 0.f }, { 1.f, 0.f }, { 0.f, 1.f }, { 1.f, 1.f } };

M3tDrawContext_Counters	M3gDrawContext_Counters;

/*
 * 
 */
const M3tDrawContext_Counters*
M3rDraw_Counters_Get(
	void)
{
	return &M3gDrawContext_Counters;
}

/*
* Frame functions
*/	
UUtError 
M3rDraw_Frame_Start(
	UUtUns32			inGameTime)
{
	UUtError	error;
	
	M3rDraw_State_SetInt(M3cDrawStateIntType_Time, inGameTime);
	
	error = M3rSort_Frame_Start();
	UUmError_ReturnOnError(error);
	
	UUrMemory_Clear(&M3gDrawContext_Counters, sizeof(M3tDrawContext_Counters));
	
	return M3gManagerDrawContext.drawFuncs->frameStart(inGameTime);
}
	
UUtError 
M3rDraw_Frame_End(
	void)
{
	UUtError	error;

	error = M3rSort_Frame_End();
	UUmError_ReturnOnError(error);
	
	return M3gManagerDrawContext.drawFuncs->frameEnd(&M3gDrawContext_Counters.textureDownload);
}

UUtError 
M3rDraw_Frame_Sync(
	void)
{
	return M3gManagerDrawContext.drawFuncs->frameSync();
}

// reset fog S.S.
void M3rDraw_Reset_Fog(
	void)
{
	M3gManagerDrawContext.drawFuncs->resetFog();

	return;
}

// load texture S.S.
static void M3iDraw_Texture_EnsureLoaded_Internal(M3tTextureMap *texture_map)
{
	if (NULL != texture_map) {
		UUtUns32 opengl_texture_name = texture_map->opengl_texture_name;
		UUtBool opengl_dirty = texture_map->opengl_dirty;

		if ((opengl_dirty) || (0 == opengl_texture_name)) {
			M3rDraw_Texture_Load(texture_map);
		}
	}

	return;
}

void M3rDraw_Texture_EnsureLoaded(M3tTextureMap *texture_map)
{
	if (NULL != texture_map) {
		M3iDraw_Texture_EnsureLoaded_Internal(texture_map);

		if (NULL != texture_map->animation) {
			M3tTextureMapAnimation *animation = texture_map->animation;
			UUtUns32 itr;
			UUtUns32 count = animation->numFrames;

			for(itr = 0; itr < count; itr++)
			{
				M3tTextureMap *current_texture = animation->maps[itr];

				M3iDraw_Texture_EnsureLoaded_Internal(current_texture);
			}
		}
	}

	return;
}

UUtBool M3rDraw_Texture_Load(
	M3tTextureMap *texture_map)
{
	return M3gManagerDrawContext.drawFuncs->loadTexture(texture_map);
}

UUtBool M3rDraw_Texture_Unload(
	M3tTextureMap *texture_map)
{
	return M3gManagerDrawContext.drawFuncs->unloadTexture(texture_map);
}


/*
* 2 1/2 D triangles
*/

M3rDraw_Triangle_Func M3rDraw_GetTriangleFunction()
{
	if(!M3gDraw_Sorting)
	{
		return M3gManagerDrawContext.drawFuncs->triangle;
	}
	else
	{
		if(M3gDraw_Vertex_Unified)
		{
			return M3rSort_Draw_Triangle;
		}
		else
		{
			return M3rSort_Draw_TriSplit;
		}
	}
}

void
M3rDraw_Triangle(
	void*			inTriangle)
{
	M3gDrawContext_Counters.numTris++;
	
	if(!M3gDraw_Sorting)
	{
		M3gManagerDrawContext.drawFuncs->triangle(inTriangle);
	}
	else
	{
		if(M3gDraw_Vertex_Unified)
		{
			M3rSort_Draw_Triangle(inTriangle);
		}
		else
		{
			M3rSort_Draw_TriSplit(inTriangle);
		}
	}
}

/*
* Quad routines
*/
void
M3rDraw_Quad(
	void*		inQuad)
{
	M3gDrawContext_Counters.numQuads++;

	if(!M3gDraw_Sorting)
	{
		M3gManagerDrawContext.drawFuncs->quad(inQuad);
	}
	else
	{
		if(M3gDraw_Vertex_Unified)
		{
			M3rSort_Draw_Quad(inQuad);
		}
		else
		{
			M3rSort_Draw_QuadSplit(inQuad);
		}
	}
}

/*
* Pent functions, these are generated by the clipper
*/
void
M3rDraw_Pent(
	void*		inPent)
{
	M3gDrawContext_Counters.numPents++;

	if(!M3gDraw_Sorting)
	{
		M3gManagerDrawContext.drawFuncs->pent(inPent);
	}
	else
	{
		if(M3gDraw_Vertex_Unified)
		{
			M3rSort_Draw_Pent(inPent);
		}
		else
		{
			M3rSort_Draw_PentSplit(inPent);
		}
	}
}

/*
* 2 1/2 D Points and Lines
*/
void
M3rDraw_Line(
	UUtUns32		inVIndex0,
	UUtUns32		inVIndex1)
{
	M3gManagerDrawContext.drawFuncs->line(inVIndex0, inVIndex1);
}

void
M3rDraw_Point(
	M3tPointScreen*	inCoord)
{
	M3gManagerDrawContext.drawFuncs->point(inCoord);
}

/*
* Bitmap drawing
*/
void
M3rDraw_TriSprite(
	const M3tPointScreen	*inPoints,			// points[3]
	const M3tTextureCoord	*inTextureCoords)	// UVs[3]
{
	M3gDrawContext_Counters.numSprites++;

		M3gManagerDrawContext.drawFuncs->triSprite(inPoints, inTextureCoords);
}

void
M3rDraw_Sprite(
	const M3tPointScreen	*inPoints,			// topleft, botright
	const M3tTextureCoord	*inTextureCoords)	// topleft, topright, botleft, botright
{
	M3gDrawContext_Counters.numSprites++;

	if(!M3gDraw_Sorting)
	{
		M3gManagerDrawContext.drawFuncs->sprite(inPoints, inTextureCoords);
	}
	else
	{
		M3rSort_Draw_Sprite(inPoints, inTextureCoords);
	}
}

void
M3rDraw_SpriteArray(
	const M3tPointScreen	*inPoints,			// topleft, botright
	const M3tTextureCoord	*inTextureCoords,	// topleft, topright, botleft, botright
	const UUtUns32			*inColors,
	const UUtUns32			inCount )
{
	M3gDrawContext_Counters.numSprites += inCount;

	//if(!M3gDraw_Sorting)
	{
		M3gManagerDrawContext.drawFuncs->spriteArray( inPoints, inTextureCoords, inColors, inCount );
	}
	//else
	//{
		//M3rSort_Draw_Sprite(inPoints, inTextureCoords);
	//}
}

UUtError 
M3rDraw_ScreenCapture(
	const UUtRect*	inRect, 
	void*			outBuffer)
{
	return M3gManagerDrawContext.drawFuncs->screenCapture(inRect, outBuffer);
}

UUtBool 
M3rDraw_PointVisible(
	const M3tPointScreen	*inPoint,
	float					inTolerance)
{
	return M3gManagerDrawContext.drawFuncs->pointVisible(inPoint, inTolerance);
}

UUtBool 
M3rDraw_SupportPointVisible(
	void)
{
	return M3gManagerDrawContext.drawFuncs->supportPointVisible();
}

/*
* Query functions
*/

UUtBool
M3rDraw_TextureFormatAvailable(
	IMtPixelType	inTexelType)
{
	return M3gManagerDrawContext.drawFuncs->textureFormatAvailable(inTexelType);
}

// Sprite arrays
/*
UUtError M3rSpriteArray_Draw( M3tSpriteArray* inSpriteArray )
{
	return M3gManagerDrawContext.drawFuncs->drawSpriteArray(inPoint, inTolerance);
}

UUtError
OGrGeomContext_Method_SpriteArray_Draw(
	M3tSpriteArray*		inSpriteArray);	


*/

/*
 * Resolution functions
 */
UUtError
M3rDraw_SetResolution(M3tDisplayMode mode)
{
	return M3gManagerDrawContext.drawFuncs->changeMode(mode);
}