#include "MW4Headers.hpp"
#include "hudcomp.hpp"
#include "aiutils.hpp"
#include "vehicle.hpp"
#include "mwapplication.hpp"
#include "..\missionlang\resource.h"

#include <MLR\MLR.hpp>
#include <MLR\MLRTexturePool.hpp>
#include <MLR\MLRTexture.hpp>

#undef STRICT
#include "gameos\pch.hpp"
#include "gameos\Debugger.hpp"
#include "gameos\DXRasterizer.hpp"
#include "gameos\DirectX.hpp"
#include "gameos\3DRasterizer.hpp"
#include "gameos\Texture Manager.hpp"
#include "gameos\font3D_dbcs_storage.hpp"

//#define WIN32_LEAN_AND_MEAN
//#include <windows.h>

//#define NO_HUD_TEXT

void _stdcall DrawRect( int x1, int y1, int x2, int y2, DWORD Color );
gos_DBCS *_stdcall MW4HUD_TextDrawDBCS(  char *Message ,int size,bool dorender = true);
gos_DBCS *_stdcall MW4HUD_gos_TextStringLength (DWORD* w,DWORD* h,char *Message,int size);

namespace MechWarrior4
{
	stlport::vector <HUDRectData> *g_HUDRectRender;
	Stuff::Scalar g_AdjustMultX,g_AdjustMultY;
	Scalar g_HUDHeatLevel = 0;
	Scalar g_HUDPPCLevel = 0;
	int g_HUDHeatAlpha = 0;
}

int GenerateHUDPPCOffset (int base)
{
	Scalar value;
	value = Stuff::Random::GetFraction ();
	value -= 0.5f;
	return (int) (base + (value * g_HUDPPCLevel));
}

Scalar GenerateHUDPPCOffset (Scalar base)
{
	Scalar value;
	value = Stuff::Random::GetFraction ();
	value -= 0.5f;
	return (base + (value * g_HUDPPCLevel));
}

void my_DrawRectImplementation (void)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDRectTime);
#endif

	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_Perspective, 0 );
	gos_SetRenderState( gos_State_Clipping, 0 );
	gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate );
	gos_SetRenderState( gos_State_MonoEnable, 0 );
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );


//	stlport::sort (g_HUDRectRender->begin (),g_HUDRectRender->end ());
	stlport::vector <HUDRectData>::iterator iter;
	gos_VERTEX *pVertices;
	int numvertex = g_HUDRectRender->size()*4;
	pVertices = new gos_VERTEX[numvertex];
	int invertex = 0;
	DWORD lastalpha = 0x34000000;
	for (iter = g_HUDRectRender->begin ();iter != g_HUDRectRender->end();iter++)
	{
		if (lastalpha != (iter->color&0xff000000))
		{
			if (invertex)
			{
				gos_DrawQuads( pVertices, invertex );
				invertex = 0;
			}
			if( (iter->color&0xff000000)==0xff000000 )
				gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero );
			else
				gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
			lastalpha = (iter->color&0xff000000);
		}
		pVertices[invertex+0].rhw	= 1.0;
		pVertices[invertex+1].rhw	= 1.0;
		pVertices[invertex+2].rhw	= 1.0;
		pVertices[invertex+3].rhw	= 1.0;

		pVertices[invertex+0].x		= (float)iter->x1;
		pVertices[invertex+0].y		= (float)iter->y1;
		pVertices[invertex+0].argb	= iter->color;

		pVertices[invertex+1].x		= (float)iter->x1;
		pVertices[invertex+1].y		= (float)iter->y2;
		pVertices[invertex+1].argb	= iter->color;

		pVertices[invertex+2].x		= (float)iter->x2;
		pVertices[invertex+2].y		= (float)iter->y2;
		pVertices[invertex+2].argb	= iter->color;

		pVertices[invertex+3].x		= (float)iter->x2;
		pVertices[invertex+3].y		= (float)iter->y1;
		pVertices[invertex+3].argb	= iter->color;
		invertex+=4;
	}

	if (invertex)
	{
		gos_DrawQuads( pVertices, invertex );
	}
}

void my_DrawRect( int x1, int y1, int x2, int y2, DWORD Color )
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDRectTime);
#endif
	x2 += 1;
	y2 += 1;
	AdjustCoords (x1,y1,x2,y2);
	Clamp (x1,0,Environment.screenWidth-1);
	Clamp (x2,0,Environment.screenWidth-1);
	Clamp (y1,0,Environment.screenHeight-1);
	Clamp (y2,0,Environment.screenHeight-1);
	if (g_HUDPPCLevel != 0)
	{
		x1 = GenerateHUDPPCOffset (x1);
		y1 = GenerateHUDPPCOffset (y1);
		x2 = GenerateHUDPPCOffset (x2);
		y2 = GenerateHUDPPCOffset (y2);
		gos_SetRenderState( gos_State_Clipping, 1);
	}
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (Color >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		Color &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		Color |= alpha;
	}
	DrawRect (x1,y1,x2,y2,Color);
//	g_HUDRectRender->push_back (HUDRectData (x1,y1,x2,y2,Color));
}

void MechWarrior4::AdjustCoords (int& left, int& top,int& right, int& bottom)
{
	left = (int) (left * g_AdjustMultX);
	top = (int) (top * g_AdjustMultY);
	right = (int) (right * g_AdjustMultX);
	bottom = (int) (bottom * g_AdjustMultY);
}
void MechWarrior4::AdjustCoords (Scalar& left, Scalar& top,Scalar& right, Scalar& bottom)
{
	left =  (left * g_AdjustMultX);
	top =  (top * g_AdjustMultY);
	right =  (right * g_AdjustMultX);
	bottom = (bottom * g_AdjustMultY);
}
void MechWarrior4::AdjustCoords (Scalar& left, Scalar& top)
{
	left =  (left * g_AdjustMultX);
	top =  (top * g_AdjustMultY);
}

void MechWarrior4::AdjustCoords (int& left, int& top)
{
	left = (int) (left * g_AdjustMultX);
	top = (int) (top * g_AdjustMultY);
}


void MechWarrior4::DrawSpecFrame (int x1,int y1,int x2,int y2,DWORD color)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDFrameTime);
#endif
	int sx,sy;

	AdjustCoords (x1,y1,x2,y2);
	Clamp (x1,0,Environment.screenWidth-1);
	Clamp (x2,0,Environment.screenWidth-1);
	Clamp (y1,0,Environment.screenHeight-1);
	Clamp (y2,0,Environment.screenHeight-1);
	sx = x2-x1+1;
	sy = y2-y1+1;
	static int delta[4][2] = {
		{0,0},	
		{1,0},	
		{1,1},	
		{0,1}
	};
	static int offset[8][2] = {
		{1,0},	
		{0,0},	
		{0,1},	
		{0,0},
		{-1,0},	
		{0,0},	
		{0,-1},	
		{0,0}
	};
	if (g_HUDPPCLevel != 0)
	{
		x1 = GenerateHUDPPCOffset (x1);
		y1 = GenerateHUDPPCOffset (y1);
		x2 = GenerateHUDPPCOffset (x2);
		y2 = GenerateHUDPPCOffset (y2);
		gos_SetRenderState( gos_State_Clipping, 1);
	}
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (color >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		color &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		color |= alpha;
	}
	int i;
	gos_VERTEX quad_verticies[8];
	for (i=0;i<4;i++)
	{
		quad_verticies[i<<1].argb = color;
		quad_verticies[i<<1].frgb = 0;
		quad_verticies[i<<1].rhw = 1.0f;
		quad_verticies[i<<1].u = 0;
		quad_verticies[i<<1].v = 0;
		quad_verticies[i<<1].x = (Scalar) (x1 + (delta[i][0]*sx) + offset[i<<1][0]);
		quad_verticies[i<<1].y = (Scalar) (y1 + (delta[i][1]*sy) + offset[i<<1][1]);
		Clamp (quad_verticies[i<<1].x,0,Environment.screenWidth-1.0f);
		Clamp (quad_verticies[i<<1].y,0,Environment.screenHeight-1.0f);
		quad_verticies[i<<1].z = 0.9f;

		quad_verticies[(i<<1)+1].argb = color;
		quad_verticies[(i<<1)+1].frgb = 0;
		quad_verticies[(i<<1)+1].rhw = 1.0f;
		quad_verticies[(i<<1)+1].u = 0;
		quad_verticies[(i<<1)+1].v = 0;
		quad_verticies[(i<<1)+1].x = (Scalar) (x1 + ((delta[(i+1)&0x03][0])*sx) + offset[(i<<1)+1][0]);
		quad_verticies[(i<<1)+1].y = (Scalar) (y1 + ((delta[(i+1)&0x03][1])*sy) + offset[(i<<1)+1][1]);
		Clamp (quad_verticies[(i<<1)+1].x,0,Environment.screenWidth-1.0f);
		Clamp (quad_verticies[(i<<1)+1].y,0,Environment.screenHeight-1.0f);
		quad_verticies[(i<<1)+1].z = 0.9f;
	}
	gos_SetRenderState( gos_State_Texture, 0);
	gos_DrawLines (quad_verticies,8);
}

void MechWarrior4::DrawFrame (int x1,int y1,int x2,int y2,DWORD color)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDFrameTime);
#endif
	int sx,sy;

	AdjustCoords (x1,y1,x2,y2);
	Clamp (x1,0,Environment.screenWidth-1);
	Clamp (x2,0,Environment.screenWidth-1);
	Clamp (y1,0,Environment.screenHeight-1);
	Clamp (y2,0,Environment.screenHeight-1);
	sx = x2-x1+1;
	sy = y2-y1+1;
	static int delta[4][2] = {
		{0,0},	
		{1,0},	
		{1,1},	
		{0,1}
	};
	int i;
	if (g_HUDPPCLevel != 0)
	{
		x1 = GenerateHUDPPCOffset (x1);
		y1 = GenerateHUDPPCOffset (y1);
		x2 = GenerateHUDPPCOffset (x2);
		y2 = GenerateHUDPPCOffset (y2);
		gos_SetRenderState( gos_State_Clipping, 1);
	}
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (color >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		color &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		color |= alpha;
	}

	gos_VERTEX quad_verticies[8];
	for (i=0;i<4;i++)
	{
		quad_verticies[i<<1].argb = color;
		quad_verticies[i<<1].frgb = 0;
		quad_verticies[i<<1].rhw = 1.0f;
		quad_verticies[i<<1].u = 0;
		quad_verticies[i<<1].v = 0;
		quad_verticies[i<<1].x = (Scalar) (x1 + (delta[i][0]*sx));
		quad_verticies[i<<1].y = (Scalar) (y1 + (delta[i][1]*sy));
		Clamp (quad_verticies[i<<1].x,0,Environment.screenWidth-1.0f);
		Clamp (quad_verticies[i<<1].y,0,Environment.screenHeight-1.0f);
		quad_verticies[i<<1].z = 0.9f;

		quad_verticies[(i<<1)+1].argb = color;
		quad_verticies[(i<<1)+1].frgb = 0;
		quad_verticies[(i<<1)+1].rhw = 1.0f;
		quad_verticies[(i<<1)+1].u = 0;
		quad_verticies[(i<<1)+1].v = 0;
		quad_verticies[(i<<1)+1].x = (Scalar) (x1 + ((delta[(i+1)&0x03][0])*sx));
		quad_verticies[(i<<1)+1].y = (Scalar) (y1 + ((delta[(i+1)&0x03][1])*sy));
		Clamp (quad_verticies[(i<<1)+1].x,0,Environment.screenWidth-1.0f);
		Clamp (quad_verticies[(i<<1)+1].y,0,Environment.screenHeight-1.0f);
		quad_verticies[(i<<1)+1].z = 0.9f;
	}
	gos_SetRenderState( gos_State_Texture, 0);
	gos_DrawLines (quad_verticies,8);
}

void MechWarrior4::DrawLine (int x1,int y1,int x2,int y2,DWORD color)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDLineTime);
#endif
	if (g_HUDPPCLevel != 0)
	{
		x1 = GenerateHUDPPCOffset (x1);
		y1 = GenerateHUDPPCOffset (y1);
		x2 = GenerateHUDPPCOffset (x2);
		y2 = GenerateHUDPPCOffset (y2);
		gos_SetRenderState( gos_State_Clipping, 1);
	}
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (color >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		color &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		color |= alpha;
	}
	AdjustCoords (x1,y1,x2,y2);
	gos_VERTEX line[2];
	line[0].argb = color;
	line[0].frgb = 0;
	line[0].rhw = 1.0f;
	line[0].u = 0;
	line[0].v = 0;
	line[0].x = (Scalar) x1;
	line[0].y = (Scalar) y1;
	line[0].z = 0.9f;

	line[1].argb = color;
	line[1].frgb = 0;
	line[1].rhw = 1.0f;
	line[1].u = 0;
	line[1].v = 0;
	line[1].x = (Scalar) x2;
	line[1].y = (Scalar) y2;
	line[1].z = 0.9f;

	gos_SetRenderState( gos_State_Texture, 0);
	gos_DrawLines (line,2);
}

//#############################################################################
//###########################    HUDTexture   #################################
//#############################################################################

stlport::vector <HUDTexture::RenderData *> *HUDTexture::g_TextureRender = NULL;

int HUDTexture::m_LastTextureHandle = -1;
float HUDTexture::TOffset = 0;
void HUDTexture::StartTexturePass (void)
{
	TOffset=gos_GetMachineInformation(gos_Info_TextureOffset) ? 0.0f : 0.5f;

	static Time lasttime = 0;
	Verify (!g_TextureRender);
	Time currenttime = gos_GetElapsedTime ();

	if ((currenttime - lasttime) < 0)
		currenttime = lasttime;

	g_HUDPPCLevel -= (Scalar) (15.0*(currenttime-lasttime));
	Min_Clamp (g_HUDPPCLevel,0);

	if (g_HUDHeatLevel < 0.65f)
	{
		Scalar delta = 100 * (Scalar) (currenttime - lasttime);
		g_HUDHeatAlpha -= (int) delta;
	}
	else
	{
		Scalar value = Stuff::Random::GetFraction ();
		Scalar delta = g_HUDHeatLevel - 0.65f;
		delta *= 10;
		delta *= (Scalar) (currenttime - lasttime);
		if (value < (0.4f+(g_HUDHeatLevel-0.65f)))
			g_HUDHeatAlpha += (int) ((delta+0.25f)*100);
		else
			g_HUDHeatAlpha -= (int) ((delta+0.25f)*100);
	}
	Clamp (g_HUDHeatAlpha,0,180);
	lasttime = currenttime;
	g_AdjustMultX = Environment.screenWidth / 800.0f;
	g_AdjustMultY = Environment.screenHeight / 600.0f;

	g_TextureRender = new stlport::vector <HUDTexture::RenderData *>;
	g_TextureRender->reserve (100);
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_Filter, gos_FilterNone );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_WireframeMode, 0 );
	gos_SetRenderState( gos_State_Specular, 0 );
	gos_SetRenderState( gos_State_Dither, 0 );
	gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud );
	gos_SetRenderState( gos_State_AlphaTest, 0 );
	gos_SetRenderState( gos_State_Fog, 0 );
//	g_HUDRectRender = new stlport::vector <HUDRectData>;
//	g_HUDRectRender->reserve (100);
}

void HUDTexture::EndTexturePass (void)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer fred ((void *) &tHUDTextureTime);
#endif
	stlport::vector<RenderData *>::iterator iter;

	m_LastTextureHandle = -1;
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_Filter, gos_FilterNone );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_WireframeMode, 0 );
	gos_SetRenderState( gos_State_Specular, 0 );
	gos_SetRenderState( gos_State_Dither, 0 );
	gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud );
	gos_SetRenderState( gos_State_AlphaTest, 0 );
	gos_SetRenderState( gos_State_Fog, 0 );

//	my_DrawRectImplementation ();

	gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );

	stlport::sort (g_TextureRender->begin (),g_TextureRender->end ());
	for (iter=g_TextureRender->begin ();iter != g_TextureRender->end ();iter++)
	{
		(*iter)->texture->DrawImplementation ((*iter)->loc,(*iter)->size,(*iter)->color,(*iter)->flip);
		delete (*iter);
		(*iter) = NULL;
	}
	delete g_TextureRender;
	g_TextureRender = NULL;
	delete g_HUDRectRender;
	g_HUDRectRender = NULL;
}
int HUDTexture::TextureID (void) const
{
	return m_Texture->GetImage()->GetHandle();
}

HUDTexture::HUDTexture (const char *name,Stuff::Scalar left,Stuff::Scalar top,Stuff::Scalar right,Stuff::Scalar bottom,Stuff::Scalar width,Stuff::Scalar height)
{
	m_Texture=MidLevelRenderer::MLRTexturePool::Instance->Add(name);

	m_Width = width;
	m_Height = height;
	if (left>1.0f)
		left = left / m_Width;
	if (top>1.0f)
		top = top / m_Height;
	if (right>1.0f)
		right = right / m_Width;
	if (bottom>1.0f)
		bottom = bottom / m_Height;
	m_TopLeft[0] = left;
	m_TopLeft[1] = top;
	m_BottomRight[0] = right;
	m_BottomRight[1] = bottom;
	m_Rotation = 0;
	m_CosRot = 1;
	m_SinRot = 0;
	m_OriginX = m_OriginY = 0;
	m_ScaleX = m_ScaleY = 1.0f;
	m_Clip = false;
	m_BlendMode = gos_BlendModulateAlpha;
	m_AlphaMode = gos_Alpha_AlphaInvAlpha;
}

HUDTexture::~HUDTexture ()
{
	m_Texture = NULL;
}

void HUDTexture::Rotate (Stuff::Scalar value)
{
	m_Rotation = value;
	m_CosRot = Cos (m_Rotation);
	m_SinRot = Sin (m_Rotation);
}

void HUDTexture::TopLeft (Stuff::Scalar x,Stuff::Scalar y)
{
	if (x >1.0f)
		x = x / m_Width;
	if (y>1.0f)
		y = y / m_Height;
	m_TopLeft[0] = x;
	m_TopLeft[1] = y;
}

void HUDTexture::BottomRight (Stuff::Scalar x,Stuff::Scalar y)
{
	if (x >1.0f)
		x = x / m_Width;
	if (y>1.0f)
		y = y / m_Height;
	m_BottomRight[0] = x;
	m_BottomRight[1] = y;
}
void HUDTexture::Draw (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip,bool drawnow)
{
//	DrawImplemenation (loc,size,flip);
	if (!m_Clip)
	{
		Verify (loc.x >= 0);
		Verify (loc.x < 800);			// scaled to actual screen size in drawimplementation
		Verify (loc.y >= 0);
		Verify (loc.y < 600);
	}
	if (Small_Enough(size.x) || Small_Enough(size.y))
	{
		return;
	}

	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (argb >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		argb &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		argb |= alpha;
	}
	if (drawnow)
	{
		DrawImplementation (loc,size,argb,flip,drawnow);
	}
	else
		g_TextureRender->push_back (new RenderData (this,loc,size,argb,flip));
}
void HUDTexture::DrawImplementation (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip,bool drawnow)
{
	if ((g_HUDHeatAlpha != 0) && (m_AlphaMode != gos_Alpha_AlphaInvAlpha))
		gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
	else
		gos_SetRenderState( gos_State_AlphaMode, m_AlphaMode );
	if (m_Clip)
		gos_SetRenderState( gos_State_Clipping, 1 );
	else
		gos_SetRenderState( gos_State_Clipping, 0 );

	if ((g_HUDHeatAlpha != 0) && (m_BlendMode != gos_BlendModulateAlpha))
		gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulateAlpha );
	else
		gos_SetRenderState( gos_State_TextureMapBlend, m_BlendMode );

	gos_VERTEX quad_verticies[4];
	memset(quad_verticies, 0, sizeof(quad_verticies));

	int i;
	for(i=0;i<4;i++)
	{
		quad_verticies[i].rhw	= 1.0;
		quad_verticies[i].argb	= argb;
		quad_verticies[i].z		= 0.9f;
	}
	
	if ((Texture()->GetImage()->GetHandle() != m_LastTextureHandle) || (drawnow))
	{
		gos_SetRenderState( gos_State_Texture, Texture()->GetImage()->GetHandle() );
		m_LastTextureHandle = Texture()->GetImage()->GetHandle() ;
	}

	Stuff::Point3D textureSize;
	textureSize = Size();
	Point3D realloc = loc;
	Point3D realsize = size;

	Scalar x1 = -m_OriginX * (size.x/textureSize.x);
	Scalar y1 = -m_OriginY * (size.y/textureSize.y);
	Scalar x2 = x1 + realsize.x;
	Scalar y2 = y1 + size.y;
	x1 *= m_ScaleX;
	y1 *= m_ScaleY;
	x2 *= m_ScaleX;
	y2 *= m_ScaleY;

	quad_verticies[0].x		= loc.x + (m_CosRot*x1 - m_SinRot *y1) - TOffset;
	quad_verticies[0].y		= loc.y + (m_SinRot*x1 + m_CosRot *y1) - TOffset;

	quad_verticies[1].x		= loc.x + (m_CosRot*x2 - m_SinRot *y1) - TOffset;
	quad_verticies[1].y		= loc.y + (m_SinRot*x2 + m_CosRot *y1) - TOffset;

	quad_verticies[2].x		= loc.x + (m_CosRot*x2 - m_SinRot *y2) - TOffset;
	quad_verticies[2].y		= loc.y + (m_SinRot*x2 + m_CosRot *y2) - TOffset;

	quad_verticies[3].x		= loc.x + (m_CosRot*x1 - m_SinRot *y2) - TOffset;
	quad_verticies[3].y		= loc.y + (m_SinRot*x1 + m_CosRot *y2) - TOffset;

	if (g_HUDPPCLevel != 0)
	{
		gos_SetRenderState( gos_State_Clipping, 1);
		quad_verticies[0].x		= GenerateHUDPPCOffset(quad_verticies[0].x);
		quad_verticies[0].y		= GenerateHUDPPCOffset(quad_verticies[0].y);
																																		
		quad_verticies[1].x		= GenerateHUDPPCOffset(quad_verticies[1].x);
		quad_verticies[1].y		= GenerateHUDPPCOffset(quad_verticies[1].y);
																																		
		quad_verticies[2].x		= GenerateHUDPPCOffset(quad_verticies[2].x);
		quad_verticies[2].y		= GenerateHUDPPCOffset(quad_verticies[2].y);
																																		
		quad_verticies[3].x		= GenerateHUDPPCOffset(quad_verticies[3].x);
		quad_verticies[3].y		= GenerateHUDPPCOffset(quad_verticies[3].y);
	}

	AdjustCoords (quad_verticies[0].x,quad_verticies[0].y,quad_verticies[1].x,quad_verticies[1].y);
	AdjustCoords (quad_verticies[2].x,quad_verticies[2].y,quad_verticies[3].x,quad_verticies[3].y);



	switch (flip)
	{
	case NO_FLIP:
		quad_verticies[0].u		= Left ();
		quad_verticies[0].v		= Top ();
		quad_verticies[1].u		= Right ();
		quad_verticies[1].v		= Top ();
		quad_verticies[2].u		= Right ();
		quad_verticies[2].v		= Bottom ();
		quad_verticies[3].u		= Left ();
		quad_verticies[3].v		= Bottom ();
		break;
	case XFLIP:
		quad_verticies[1].u		= Left ();
		quad_verticies[0].v		= Top ();
		quad_verticies[0].u		= Right ();
		quad_verticies[1].v		= Top ();
		quad_verticies[3].u		= Right ();
		quad_verticies[2].v		= Bottom ();
		quad_verticies[2].u		= Left ();
		quad_verticies[3].v		= Bottom ();
		break;
	case YFLIP:
		quad_verticies[0].u		= Left ();
		quad_verticies[1].v		= Top ();
		quad_verticies[1].u		= Right ();
		quad_verticies[2].v		= Top ();
		quad_verticies[2].u		= Right ();
		quad_verticies[1].v		= Bottom ();
		quad_verticies[3].u		= Left ();
		quad_verticies[0].v		= Bottom ();
		break;
	case XYFLIP:
		quad_verticies[2].u		= Left ();
		quad_verticies[2].v		= Top ();
		quad_verticies[3].u		= Right ();
		quad_verticies[3].v		= Top ();
		quad_verticies[0].u		= Right ();
		quad_verticies[0].v		= Bottom ();
		quad_verticies[1].u		= Left ();
		quad_verticies[1].v		= Bottom ();
		break;
	}
	
	if( 0.0f==TOffset )
	{
		float TexOffset=0.0625f/m_Width;			//   0.0625/texture size.

		quad_verticies[0].u +=TexOffset;
		quad_verticies[0].v +=TexOffset;
		quad_verticies[1].u +=TexOffset;
		quad_verticies[1].v +=TexOffset;
		quad_verticies[2].u +=TexOffset;
		quad_verticies[2].v +=TexOffset;
		quad_verticies[3].u +=TexOffset;
		quad_verticies[3].v +=TexOffset;
	}


	gos_DrawQuads(quad_verticies, 4);
}



int ReviewTexture::TextureID (void) const
{
	return m_TextureHandle;
}
ReviewTexture::ReviewTexture (const char *name,Stuff::Scalar left,Stuff::Scalar top,Stuff::Scalar right,Stuff::Scalar bottom,Stuff::Scalar width,Stuff::Scalar height,bool alpha)
{
	if (alpha)
		m_TextureHandle=gos_NewTextureFromFile (gos_Texture_Alpha,name);
	else
		m_TextureHandle=gos_NewTextureFromFile (gos_Texture_Solid,name);

	m_Width = width;
	m_Height = height;
	if (left>1.0f)
		left = left / m_Width;
	if (top>1.0f)
		top = top / m_Height;
	if (right>1.0f)
		right = right / m_Width;
	if (bottom>1.0f)
		bottom = bottom / m_Height;
	m_TopLeft[0] = left;
	m_TopLeft[1] = top;
	m_BottomRight[0] = right;
	m_BottomRight[1] = bottom;
	m_Rotation = 0;
	m_CosRot = 1;
	m_SinRot = 0;
	m_OriginX = m_OriginY = 0;
	m_ScaleX = m_ScaleY = 1.0f;
	m_Clip = false;
	m_BlendMode = gos_BlendModulateAlpha;
	m_AlphaMode = gos_Alpha_AlphaInvAlpha;
}

ReviewTexture::~ReviewTexture ()
{
	gos_DestroyTexture (m_TextureHandle);
}

void ReviewTexture::Rotate (Stuff::Scalar value)
{
	m_Rotation = value;
	m_CosRot = Cos (m_Rotation);
	m_SinRot = Sin (m_Rotation);
}

void ReviewTexture::TopLeft (Stuff::Scalar x,Stuff::Scalar y)
{
	if (x >1.0f)
		x = x / m_Width;
	if (y>1.0f)
		y = y / m_Height;
	m_TopLeft[0] = x;
	m_TopLeft[1] = y;
}

void ReviewTexture::BottomRight (Stuff::Scalar x,Stuff::Scalar y)
{
	if (x >1.0f)
		x = x / m_Width;
	if (y>1.0f)
		y = y / m_Height;
	m_BottomRight[0] = x;
	m_BottomRight[1] = y;
}
void ReviewTexture::Draw (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip)
{
//	DrawImplemenation (loc,size,flip);
	if (!m_Clip)
	{
		Verify (loc.x >= 0);
		Verify (loc.x < 800);			// scaled to actual screen size in drawimplementation
		Verify (loc.y >= 0);
		Verify (loc.y < 600);
	}
	if (Small_Enough(size.x) || Small_Enough(size.y))
	{
		return;
	}

	DrawImplementation (loc,size,argb,flip);
}
void ReviewTexture::DrawImplementation (const Stuff::Point3D& loc,const Stuff::Point3D& size,DWORD argb,FLIP flip)
{
	if ((g_HUDHeatAlpha != 0) && (m_AlphaMode != gos_Alpha_AlphaInvAlpha))
		gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
	else
		gos_SetRenderState( gos_State_AlphaMode, m_AlphaMode );
	if (m_Clip)
		gos_SetRenderState( gos_State_Clipping, 1 );
	else
		gos_SetRenderState( gos_State_Clipping, 0 );

	if ((g_HUDHeatAlpha != 0) && (m_BlendMode != gos_BlendModulateAlpha))
		gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulateAlpha );
	else
		gos_SetRenderState( gos_State_TextureMapBlend, m_BlendMode );

	gos_VERTEX quad_verticies[4];
	memset(quad_verticies, 0, sizeof(quad_verticies));

	int i;
	for(i=0;i<4;i++)
	{
		quad_verticies[i].rhw	= 1.0;
		quad_verticies[i].argb	= argb;
		quad_verticies[i].z		= 0.9f;
	}
	
	gos_SetRenderState( gos_State_Texture, m_TextureHandle);

	Stuff::Point3D textureSize;
	textureSize = Size();
	Point3D realloc = loc;
	Point3D realsize = size;

	Scalar x1 = -m_OriginX * (size.x/textureSize.x);
	Scalar y1 = -m_OriginY * (size.y/textureSize.y);
	Scalar x2 = x1 + realsize.x;
	Scalar y2 = y1 + size.y;
	x1 *= m_ScaleX;
	y1 *= m_ScaleY;
	x2 *= m_ScaleX;
	y2 *= m_ScaleY;

	quad_verticies[0].x		= loc.x + (m_CosRot*x1 - m_SinRot *y1);
	quad_verticies[0].y		= loc.y + (m_SinRot*x1 + m_CosRot *y1);

	quad_verticies[1].x		= loc.x + (m_CosRot*x2 - m_SinRot *y1);
	quad_verticies[1].y		= loc.y + (m_SinRot*x2 + m_CosRot *y1);

	quad_verticies[2].x		= loc.x + (m_CosRot*x2 - m_SinRot *y2);
	quad_verticies[2].y		= loc.y + (m_SinRot*x2 + m_CosRot *y2);

	quad_verticies[3].x		= loc.x + (m_CosRot*x1 - m_SinRot *y2);
	quad_verticies[3].y		= loc.y + (m_SinRot*x1 + m_CosRot *y2);

	if (g_HUDPPCLevel != 0)
	{
		gos_SetRenderState( gos_State_Clipping, 1);
		quad_verticies[0].x		= GenerateHUDPPCOffset(quad_verticies[0].x);
		quad_verticies[0].y		= GenerateHUDPPCOffset(quad_verticies[0].y);
																																		
		quad_verticies[1].x		= GenerateHUDPPCOffset(quad_verticies[1].x);
		quad_verticies[1].y		= GenerateHUDPPCOffset(quad_verticies[1].y);
																																		
		quad_verticies[2].x		= GenerateHUDPPCOffset(quad_verticies[2].x);
		quad_verticies[2].y		= GenerateHUDPPCOffset(quad_verticies[2].y);
																																		
		quad_verticies[3].x		= GenerateHUDPPCOffset(quad_verticies[3].x);
		quad_verticies[3].y		= GenerateHUDPPCOffset(quad_verticies[3].y);
	}


	switch (flip)
	{
	case NO_FLIP:
		quad_verticies[0].u		= Left ();
		quad_verticies[0].v		= Top ();
		quad_verticies[1].u		= Right ();
		quad_verticies[1].v		= Top ();
		quad_verticies[2].u		= Right ();
		quad_verticies[2].v		= Bottom ();
		quad_verticies[3].u		= Left ();
		quad_verticies[3].v		= Bottom ();
		break;
	case XFLIP:
		quad_verticies[1].u		= Left ();
		quad_verticies[0].v		= Top ();
		quad_verticies[0].u		= Right ();
		quad_verticies[1].v		= Top ();
		quad_verticies[3].u		= Right ();
		quad_verticies[2].v		= Bottom ();
		quad_verticies[2].u		= Left ();
		quad_verticies[3].v		= Bottom ();
		break;
	case YFLIP:
		quad_verticies[0].u		= Left ();
		quad_verticies[1].v		= Top ();
		quad_verticies[1].u		= Right ();
		quad_verticies[2].v		= Top ();
		quad_verticies[2].u		= Right ();
		quad_verticies[1].v		= Bottom ();
		quad_verticies[3].u		= Left ();
		quad_verticies[0].v		= Bottom ();
		break;
	case XYFLIP:
		quad_verticies[2].u		= Left ();
		quad_verticies[2].v		= Top ();
		quad_verticies[3].u		= Right ();
		quad_verticies[3].v		= Top ();
		quad_verticies[0].u		= Right ();
		quad_verticies[0].v		= Bottom ();
		quad_verticies[1].u		= Left ();
		quad_verticies[1].v		= Bottom ();
		break;
	}

	gos_DrawQuads(quad_verticies, 4);
}

HGOSFONT3D HUDText::defaultFontHandle=0;
HGOSFONT3D HUDText::altFontHandle=0;
int HUDText::defaultFontRefCount = 0;
int HUDText::altFontRefCount = 0;
int HUDText::defaultSmallFontSize,HUDText::defaultMediumFontSize,HUDText::defaultLargeFontSize,HUDText::defaultLarge2FontSize,HUDText::defaultLarge3FontSize;
//Scalar HUDText::defaultFontSize = -10.0f;

HUDText::HUDText (bool oldmode)
{
	m_UseOldText = oldmode;
	m_GosObject = NULL;
	m_Justification = LEFT_ALIGN;
	if (defaultFontRefCount == 0)
	{
		char *str;
		MWApplication *app;
		app = MWApplication::GetInstance ();
		defaultFontHandle = gos_LoadFont(app->GetLocString (IDS_HUDFONT), 0);
		str = app->GetLocString (IDS_SMALLFONT);
		defaultSmallFontSize = atoi (str);
		str = app->GetLocString (IDS_MEDIUMFONT);
		defaultMediumFontSize = atoi (str);
		str = app->GetLocString (IDS_LARGEFONT);
		defaultLargeFontSize = atoi (str);
		str = app->GetLocString (IDS_LARGE2FONT);
		defaultLarge2FontSize = atoi (str);
		str = app->GetLocString (IDS_LARGE3FONT);
		defaultLarge3FontSize = atoi (str);
	}
	if(altFontRefCount==0){
		altFontHandle = gos_LoadFont("arial black.ttf",0);
	}
//	defaultFontHandle = gos_LoadFont("Assets\\Graphics\\ocraext10reg.d3f", 0);
	defaultFontRefCount++;
	altFontRefCount++;
	m_Font = defaultFontHandle;
	m_TopLeft[0] = 0;
	m_TopLeft[1] = 0;
	m_BottomRight[0] = 800;
	m_BottomRight[1] = 600;
	m_Wrap = false;
	m_Size = defaultMediumFontSize;
	m_Text[0] = 0;
	m_BoundsValid = false;
}

HUDText::~HUDText (void)
{
	if (m_GosObject)
		m_GosObject->Release ();
	defaultFontRefCount--;
	if (defaultFontRefCount == 0)
		gos_DeleteFont (defaultFontHandle);

	altFontRefCount--;
	if (altFontRefCount == 0)
		gos_DeleteFont (altFontHandle);

}

void HUDText::TopLeft (Stuff::Scalar x,Stuff::Scalar y)
{
	m_TopLeft[0] = x;
	m_TopLeft[1] = y;
}

void HUDText::BottomRight (Stuff::Scalar x,Stuff::Scalar y)
{
	m_BottomRight[0] = x;
	m_BottomRight[1] = y;
}

void HUDText::UpdateText (const char *text,bool force,bool extrareturn)
{
	if ((!force) && (!strcmp (m_Text,text)))
		return;

	if (m_GosObject)
	{
		m_GosObject->Release ();
	}
	m_BoundsValid = false;
	m_GosObject = NULL;
	Str_Copy (m_Text,text,MAX_HUD_TEXT);
	if (extrareturn)
		Str_Cat (m_Text,"\n",MAX_HUD_TEXT);
}

void HUDText::Draw (void)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer wilma ((void *) &tHUDTextTime);
#endif
	Scalar size;
	m_Color = m_Color & 0x00ffffff;
	m_Color = m_Color | 0xff000000;
	
	int argb = m_Color;
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (argb >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		argb &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		argb |= alpha;
	}
	
	size = (float) m_Size;
	Scalar fred=0;
	AdjustCoords (fred,size);
	gos_TextSetAttributes(m_Font,argb,size,m_Wrap,true,false,false,m_Justification);
#ifndef NO_HUD_TEXT
	if (m_UseOldText)
	{
    gos_TextDraw (m_Text);
	}
	else
	{
		if (m_GosObject)
			m_GosObject->Release ();
		m_GosObject = MW4HUD_TextDrawDBCS(m_Text,(int) size);
		if (m_GosObject)
			m_GosObject->AddRef ();
	}
#endif
}

void HUDText::Draw (Stuff::Point3D loc, bool bTextSetPos)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer wilma ((void *) &tHUDTextTime);
#endif

	Scalar left,right,top,bottom;
#if 0
	if (loc.x <= 1.0f)
		loc.x *= 800;
	if (loc.y <= 1.0f)
		loc.y *= 600;
#endif
//	if (m_TopLeft[0] <= 1.0f)
//		left = m_TopLeft[0] * 800;
//	else
		left = m_TopLeft[0];
//	if (m_TopLeft[1] <= 1.0f)
//		top = m_TopLeft[1] * 600;
//	else
		top = m_TopLeft[1];

//	if (m_BottomRight[0] <= 1.0f)
//		right = m_BottomRight[0] * 800;
//	else
		right = m_BottomRight[0];
//	if (m_BottomRight[1] <= 1.0f)
//		bottom = m_BottomRight[1] * 600;
//	else
		bottom = m_BottomRight[1];

	if (g_HUDPPCLevel != 0)
	{
		gos_SetRenderState( gos_State_Clipping, 1);
		loc.x	= GenerateHUDPPCOffset(loc.x);
		loc.y	= GenerateHUDPPCOffset(loc.y);
	}
	m_Color = m_Color & 0x00ffffff;
	m_Color = m_Color | 0xff000000;
	int argb = m_Color;
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (argb >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		argb &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		argb |= alpha;
	}

	AdjustCoords (left,top,right,bottom);
	gos_TextSetRegion((int) left,(int) top,(int) right,(int) bottom);
	
	Scalar size= (float) m_Size;
	Scalar fred=0;
	AdjustCoords (fred,size);
	gos_TextSetAttributes(m_Font,argb,size,m_Wrap,true,false,false,m_Justification);
				
	AdjustCoords (loc.x,loc.y);
//	Min_Clamp (loc.x,2);
//	Min_Clamp (loc.y,2);
	if (bTextSetPos)
		gos_TextSetPosition((int) loc.x,(int) loc.y);
#ifndef NO_HUD_TEXT
	if (m_UseOldText)
	{
    gos_TextDraw (m_Text);
	}
	else
	{
		if (m_GosObject)
			m_GosObject->Release ();
		m_GosObject = MW4HUD_TextDrawDBCS(m_Text,(int) size);
		if (m_GosObject)
		{
			m_GosObject->AddRef ();
		}
	}
#endif
}

void HUDText::EndPos (DWORD& x,DWORD& y, bool bAdjust)
{
	if (!m_GosObject)
	{
		x = y = 0;
		return;
	}
	x = (int) m_GosObject->m_doneFontX;
	y = (int) m_GosObject->m_doneFontY;
	if (bAdjust)
	{
		x = (int) (x/g_AdjustMultX);
		y = (int) (y/g_AdjustMultY);
	}
}

int HUDText::deltaSmallSize,HUDText::deltaMediumSize,HUDText::deltaLargeSize,HUDText::deltaLarge2Size,HUDText::deltaLarge3Size;

void HUDText::LoadFontSizeDelta (NotationFile *startup_ini)
{
	deltaSmallSize = 0;
	deltaMediumSize = 0;
	deltaLargeSize = 0;
	deltaLarge2Size = 0;
	deltaLarge3Size = 0;
	Page *page=startup_ini->FindPage("graphics options");
	if (page)
	{
		Check_Object(page);
		page->GetEntry("fontsmall",&deltaSmallSize,false);
		page->GetEntry("fontmedium",&deltaMediumSize,false);
		page->GetEntry("fontlarge",&deltaLargeSize,false);
		page->GetEntry("fontlarge2",&deltaLarge2Size,false);
		page->GetEntry("fontlarge3",&deltaLarge3Size,false);
	}
}

void HUDText::DrawSize (DWORD& x,DWORD& y)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer wilma ((void *) &tHUDTextTime);
#endif

#if 0
	if (m_BoundsValid)
	{
		x = m_Width;
		y = m_Height;
		return;
	}
#endif

	Scalar size;
	size = (float) m_Size;
	Scalar fred=0;
	Scalar left,right,top,bottom;

	left = m_TopLeft[0];
	top = m_TopLeft[1];
	right = m_BottomRight[0];
	bottom = m_BottomRight[1];

	AdjustCoords (left,top,right,bottom);
	gos_TextSetRegion((int) left,(int) top,(int) right,(int) bottom);

	AdjustCoords (fred,size);
	gos_TextSetAttributes(m_Font,m_Color,size,m_Wrap,true,false,false,m_Justification);
	gos_TextSetPosition((int) (left+1),(int) (top+1));

	if (m_GosObject)
		m_GosObject->Release ();
	m_GosObject = MW4HUD_gos_TextStringLength(&x,&y,m_Text,(int) size);
	if (m_GosObject)
		m_GosObject->AddRef ();

	x = (int) (x/g_AdjustMultX);
	y = (int) (y/g_AdjustMultY);
	m_BoundsValid = true;
	m_Width = x;
	m_Height = y;
}


//#############################################################################
//###########################    HUDNumberText   ##############################
//#############################################################################

//const char *str[NUM_LETTERS] ={"0","1","2","3","4","5","6","7","8","9","m"};

int HUDNumberText::fontdata[14][11][4] = {
{{2,2,6,9},{7,2,11,9},{12,2,16,9},{17,2,21,9},{22,2,26,9},{27,2,31,9},{32,2,36,9},{37,2,41,9},{42,2,46,9},{47,2,51,9},{52,2,57,9}},
{{2,11,6,19},{7,11,11,19},{12,11,16,19},{17,11,21,19},{22,11,26,19},{27,11,31,19},{32,11,36,19},{37,11,41,19},{42,11,46,19},{47,11,51,19},{52,11,58,19}},
{{2,21,7,31},{8,21,13,31},{14,21,19,31},{20,21,25,31},{26,21,31,31},{32,21,37,31},{38,21,43,31},{44,21,49,31},{50,21,55,31},{56,21,61,31},{62,21,69,31}},
{{2,33,7,44},{8,33,13,44},{14,33,19,44},{20,33,25,44},{26,33,31,44},{32,33,37,44},{38,33,43,44},{44,33,49,44},{50,33,55,44},{56,33,61,44},{62,33,70,44}},
{{2,46,8,57},{9,46,15,57},{16,46,22,57},{23,46,29,57},{30,46,36,57},{37,46,43,57},{44,46,50,57},{51,46,57,57},{58,46,64,57},{65,46,71,57},{72,46,81,57}},
{{2,59,9,73},{10,59,17,73},{18,59,25,73},{26,59,33,73},{34,59,41,73},{42,59,49,73},{50,59,57,73},{58,59,65,73},{66,59,73,73},{74,59,81,73},{82,59,93,73}},
{{2,75,10,91},{11,75,19,91},{20,75,28,91},{29,75,37,91},{38,75,46,91},{47,75,55,91},{56,75,64,91},{65,75,73,91},{74,75,82,91},{83,75,91,91},{92,75,104,91}},
{{2,93,11,110},{12,93,21,110},{22,93,31,110},{32,93,41,110},{42,93,51,110},{52,93,61,110},{62,93,71,110},{72,93,81,110},{82,93,91,110},{92,93,101,110},{102,93,115,110}},
{{2,112,12,130},{13,112,23,130},{24,112,34,130},{35,112,45,130},{46,112,56,130},{57,112,67,130},{68,112,78,130},{79,112,89,130},{90,112,100,130},{101,112,111,130},{112,112,126,130}},
{{2,132,12,152},{13,132,23,152},{24,132,34,152},{35,132,45,152},{46,132,56,152},{57,132,67,152},{68,132,78,152},{79,132,89,152},{90,132,100,152},{101,132,111,152},{112,132,127,152}},
{{2,154,13,175},{14,154,25,175},{26,154,37,175},{38,154,49,175},{50,154,61,175},{62,154,73,175},{74,154,85,175},{86,154,97,175},{98,154,109,175},{110,154,121,175},{122,154,138,175}},
{{2,177,14,200},{15,177,27,200},{28,177,40,200},{41,177,53,200},{54,177,66,200},{67,177,79,200},{80,177,92,200},{93,177,105,200},{106,177,118,200},{119,177,131,200},{132,177,150,200}},
{{2,202,15,228},{16,202,29,228},{30,202,43,228},{44,202,57,228},{58,202,71,228},{72,202,85,228},{86,202,99,228},{100,202,113,228},{114,202,127,228},{128,202,141,228},{142,202,161,228}},
{{2,230,16,258},{17,230,31,258},{32,230,46,258},{47,230,61,258},{62,230,76,258},{77,230,91,258},{92,230,106,258},{107,230,121,258},{122,230,136,258},{137,230,151,258},{152,230,173,258}}
};

//const float size[NUM_SIZES] = {6,7,8,9,10,12,14,15,16,17,18,20,22,24};

HUDTexture *HUDNumberText::numTexture = NULL;
int HUDNumberText::numTextureRefCount = 0;

HUDNumberText::HUDNumberText (void)
{
	if (numTextureRefCount == 0)
		numTexture = new HUDTexture ("hud\\num",0,0,256,256,256,256);
	numTextureRefCount++;
	SetSize (SMALL_SIZE);
}

HUDNumberText::~HUDNumberText (void)
{
	numTextureRefCount--;
	if (numTextureRefCount == 0)
		delete numTexture;
}

int HUDNumberText::GetIndex (int size)
{
	if (size <= -8)
	{
		switch (Environment.screenHeight)
		{
			case 480:
				return 0;
			break;
			case 600:
				return 2;
			break;
			case 768:
				return 4;
			break;
			case 1024:
				return 6;
			break;
			case 1200:
				return 8;
			break;
		}
	}
	else if (size <= -10)
	{
		switch (Environment.screenHeight)
		{
			case 480:
				return 2;
			break;
			case 600:
				return 4;
			break;
			case 768:
				return 5;
			break;
			case 1024:
				return 7;
			break;
			case 1200:
				return 11;
			break;
		}
	}
	else
	{
		switch (Environment.screenHeight)
		{
			case 480:
				return 4;
			break;
			case 600:
				return 5;
			break;
			case 768:
				return 7;
			break;
			case 1024:
				return 11;
			break;
			case 1200:
				return 13;
			break;
		}
	}
	STOP (("unknown screen size in HUDNumberText::GetIndex"));
	return 0;
}

void HUDNumberText::DrawSize (DWORD& x,DWORD& y)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer wilma ((void *) &tHUDTextTime);
#endif
	int index,i,len;
	index = GetIndex (Size ())+1;
	Clamp (index,0,13);
	x = y = 0;
	int charloc=0;
	
	len = strlen (m_Text);
	for (i=0;i<len;i++)
	{
		if (m_Text[i] == ' ')
		{
			charloc = 0;
			x+= (fontdata[index][charloc][2] - fontdata[index][charloc][0]);
		}
		else if (m_Text[i] == 'm')
		{
			charloc = 10;
			x+= (fontdata[index][charloc][2] - fontdata[index][charloc][0]);
		}
		else
		{
			charloc = m_Text[i] - '0';
			x += (fontdata[index][charloc][2] - fontdata[index][charloc][0]);
		}

		if ((fontdata[index][charloc][3] - fontdata[index][charloc][1]) > y)
		{
			y = (fontdata[index][charloc][3] - fontdata[index][charloc][1]);
		}
	}
	x = (int) (x/g_AdjustMultX);
	y = (int) (y/g_AdjustMultY);
}

void HUDNumberText::Draw (Stuff::Point3D loc)
{
#if !defined(NO_TIMERS)
	MW4AI::my_AutoTimer wilma ((void *) &tHUDTextTime);
#endif
	int index,i,len;
	Scalar curx,cury;
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
	gos_SetRenderState( gos_State_Clipping, 0 );
	gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulateAlpha );

	loc.x *= g_AdjustMultX;
	loc.y *= g_AdjustMultY;
	gos_VERTEX quad_verticies[4];
	memset(quad_verticies, 0, sizeof(quad_verticies));

	int argb = m_Color;
	if (g_HUDHeatLevel != 0)
	{
		int alpha;
		alpha = (argb >> 24) & 0xff;
		alpha -= g_HUDHeatAlpha;
		argb &= 0x00ffffff;
		Clamp (alpha,0,255);
		alpha <<= 24;
		argb |= alpha;
	}
	for(i=0;i<4;i++)
	{
		quad_verticies[i].rhw	= 1.0;
		quad_verticies[i].argb	= argb;
		quad_verticies[i].z		= 0.9f;
	}
	
	gos_SetRenderState( gos_State_Texture, numTexture->TextureID () );
	curx = loc.x;
	cury = loc.y;

	DWORD w,h;
	switch (m_Justification)
	{
		case LEFT_ALIGN:
			break;
		case RIGHT_ALIGN:
			DrawSize (w,h);
			curx -= w;
			break;
		case CENTER_ALIGN:
			DrawSize (w,h);
			curx -= (w>>1);
			break;
		case CENTERREGION_ALIGN:
			DrawSize (w,h);
			curx = (((m_BottomRight[0] - m_TopLeft[0]) - h)/2) + m_TopLeft[0];
			cury = (((m_BottomRight[1] - m_TopLeft[1]) - w)/2) + m_TopLeft[1];
			curx *= g_AdjustMultX;
			cury *= g_AdjustMultY;
			break;
	}
	index = GetIndex (Size ())+1;
	Clamp (index,0,13);
	len = strlen (m_Text);
	int charloc = 0;
	for (i=0;i<len;i++)
	{
		if (m_Text[i] == ' ')
		{
			curx += (fontdata[index][0][2] - fontdata[index][0][0]);
			continue;
		}
		else if (m_Text[i] == 'm')
			charloc = 10;
		else if ((m_Text[i] < '0') || (m_Text[i] > '9'))
			continue;
		else
			charloc = m_Text[i] - '0';

		int left,right,top,bottom;

		left = fontdata[index][charloc][0];
		top = fontdata[index][charloc][1];
		right = fontdata[index][charloc][2];
		bottom = fontdata[index][charloc][3];

		quad_verticies[0].x		= curx;
		quad_verticies[0].y		= cury;

		quad_verticies[1].x		= curx+(right-left)+1;
		quad_verticies[1].y		= cury;

		quad_verticies[2].x		= curx+(right-left)+1;
		quad_verticies[2].y		= cury+(bottom-top)+1;

		quad_verticies[3].x		= curx;
		quad_verticies[3].y		= cury+(bottom-top)+1;
		curx += (right-left);
		if (g_HUDPPCLevel != 0)
		{
			gos_SetRenderState( gos_State_Clipping, 1);
			quad_verticies[0].x		= GenerateHUDPPCOffset(quad_verticies[0].x);
			quad_verticies[0].y		= GenerateHUDPPCOffset(quad_verticies[0].y);

			quad_verticies[1].x		= GenerateHUDPPCOffset(quad_verticies[1].x);
			quad_verticies[1].y		= GenerateHUDPPCOffset(quad_verticies[1].y);

			quad_verticies[2].x		= GenerateHUDPPCOffset(quad_verticies[2].x);
			quad_verticies[2].y		= GenerateHUDPPCOffset(quad_verticies[2].y);

			quad_verticies[3].x		= GenerateHUDPPCOffset(quad_verticies[3].x);
			quad_verticies[3].y		= GenerateHUDPPCOffset(quad_verticies[3].y);
		}


		quad_verticies[0].u		= left/256.0f;
		quad_verticies[0].v		= top/256.0f;
		quad_verticies[1].u		= right/256.0f;
		quad_verticies[1].v		= top/256.0f;
		quad_verticies[2].u		= right/256.0f;
		quad_verticies[2].v		= bottom/256.0f;
		quad_verticies[3].u		= left/256.0f;
		quad_verticies[3].v		= bottom/256.0f;

//		AdjustCoords (quad_verticies[0].x,quad_verticies[0].y,quad_verticies[1].x,quad_verticies[1].y);
//		AdjustCoords (quad_verticies[2].x,quad_verticies[2].y,quad_verticies[3].x,quad_verticies[3].y);
		gos_DrawQuads(quad_verticies, 4);
	}
}

//#############################################################################
//###########################    HUDComponent   ###############################
//#############################################################################

HUDComponent::ClassData* HUDComponent::DefaultData = NULL;
bool g_AddHUDFont = false;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void HUDComponent::InitializeClass()
{
#if 0
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			HUDComponentClassID,
			"MechWarrior4::HudComponent",
			GUIObject::DefaultData,
			0,
			NULL
		);
	Register_Object(DefaultData);
#endif
//	g_AddHUDFont = false;
//	if (AddFontResource ("Assets\\Graphics\\ARLRDBD.TTF") != 0)
//		g_AddHUDFont = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void HUDComponent::TerminateClass()
{
//	if (g_AddHUDFont)
//		RemoveFontResource ("Assets\\Graphics\\ARLRDBD.TTF");
//	g_AddHUDFont = false;
#if 0
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
#endif
}

HUDComponent::HUDComponent(ClassData *class_data,Stuff::Page *instance_page) :
		m_Vehicle (NULL)
{
	m_Visible = false;
}

HUDComponent::HUDComponent(ClassData *class_data,Stuff::MemoryStream *stream) :
		m_Vehicle (NULL)
{
	m_Visible = false;
}

HUDComponent::HUDComponent(ClassData *class_data) :
		m_Vehicle (NULL)
{
	m_Visible = false;
}

HUDTexture *HUDComponent::AddTexture (const char *name,int id,Scalar left,Scalar top,Scalar right,Scalar bottom,Scalar width,Scalar height)
{
	stlport::map<int,HUDTexture *>::iterator iter;

	if (m_Textures.find (id) != m_Textures.end ())
	{
		delete m_Textures[id];
	}
	HUDTexture *toret;
	toret = new HUDTexture (name,left,top,right,bottom,width,height);
	m_Textures[id] = toret;
	return toret;
}

ReviewTexture *HUDComponent::AddReviewTexture (const char *name,int id,Scalar left,Scalar top,Scalar right,Scalar bottom,Scalar width,Scalar height,bool alpha)
{
	stlport::map<int,ReviewTexture *>::iterator iter;

	if (m_ReviewTextures.find (id) != m_ReviewTextures.end ())
	{
		delete m_ReviewTextures[id];
	}
	ReviewTexture *toret;
	toret = new ReviewTexture (name,left,top,right,bottom,width,height,alpha);
	m_ReviewTextures[id] = toret;
	return toret;
}

HUDComponent::~HUDComponent()
{
	stlport::map <int,HUDTexture *>::iterator iter;
	
	for (iter = m_Textures.begin ();iter != m_Textures.end ();iter++)
	{
		delete iter->second;
		iter->second = NULL;
	}
	stlport::map <int,ReviewTexture *>::iterator iter1;
	
	for (iter1 = m_ReviewTextures.begin ();iter1 != m_ReviewTextures.end ();iter1++)
	{
		delete iter1->second;
		iter1->second = NULL;
	}
	
}

Stuff::Point3D HUDComponent::TopLeft (void) const
{
	Stuff::Point3D loc,size;

	loc = Location ();
	size = Size ();
	switch (Alignment ())
	{
		case LEFT_ALIGN:
			break;
		case CENTER_ALIGNX:
			loc.x -= (size.x/2.0f);
			break;
		case CENTER_ALIGNY:
			loc.y -= (size.y/2.0f);
			break;
		case CENTER_ALIGNBOTH:
			loc.x -= (size.x/2.0f);
			loc.y -= (size.y/2.0f);
			break;
		case RIGHT_ALIGN:
			loc.x -= size.x;
			break;
	}
	return loc;
}

void HUDComponent::DrawImplementation (void)
{
}
void HUDComponent::TestInstance()
{
}
void HUDComponent::SetVehicle (Vehicle *veh)
{
	m_Vehicle.Remove ();
	if (veh)
	{
		Check_Object (veh);
		m_Vehicle.Add (veh);
	}
	else
	{
		m_Vehicle.Remove ();
	}
}

