#include "global.h"

enum mainMenuItems { START_GAME, JOIN_NETWORK_GAME, SETTINGS, REPLAY_INTRO, QUIT_GAME, NUM_MAIN_MENU_ITEMS };
enum netMenuItems  { NOSELECTION, PLAYER_NAME, SERVER_LIST, SERVER_NAME, JOIN_GAME, NUM_NET_MENU_ITEMS };
char* mainMenuText[NUM_MAIN_MENU_ITEMS] = {
	"Start Server",
	"Join Network Game",
	"Settings",
	"Replay Intro",
	"Quit"
};

double networkTimeOut = 5.0;
extern LARGE_INTEGER lasttime;

vec3f SettingsPanelColors[ NUM_SETTINGS_PANEL_COLORS ] = {
	vec3f( 0.2, 0.3, 0.5 ),		// SETTINGS_PANEL_BKG_SEL,
	vec3f( 0.1, 0.1, 0.1 ),		// SETTINGS_PANEL_BKG_UNSEL,
	vec3f( 0.0, 0.3, 0.3 ),		// SETTINGS_PANEL_ITEM_SEL,
	vec3f( 0.0, 1.0, 1.0 ),		// SETTINGS_PANEL_ITEM_TEXT,
};

char* SettingsChoiceText[ NUM_SETTINGS_PANELS ] = {
	"Video","Credits","Controls","Player", ""
};


// SETTINGS_PANEL_VIDEO_CHOICE,
// SETTINGS_PANEL_CREDITS_CHOICE,
// SETTINGS_PANEL_CONTROL_CHOICE,
// SETTINGS_PANEL_PLAYER_CHOICE,
// SETTINGS_PANEL_BACKGROUND,
vec4f SettingsPanelCoords[ NUM_SETTINGS_PANELS ] = {
	vec4f(  28, 79,  48, 72 ),		
	vec4f(  72, 79,  94, 72 ),		
	vec4f(  50, 79,  70, 72 ),		
	vec4f(   6, 79,  26, 72 ),		
	vec4f(   6, 72,  94, 27 ),		
};

typedef enum {
	SETTINGS_PLAYER_PANEL_TANK,
	SETTINGS_PLAYER_BUTTON_MODEL_NEXT,
	SETTINGS_PLAYER_BUTTON_MODEL_PREV,
	//SETTINGS_PLAYER_BUTTON_TEXTURE_NEXT,
	//SETTINGS_PLAYER_BUTTON_TEXTURE_PREV,
	NUM_SETTINGS_PLAYER_BUTTONS
} SettingsPlayerButtonID;

vec4f PlayerSettingsButtonCoords[NUM_SETTINGS_PLAYER_BUTTONS] = {
	vec4f( 7,70,37,42),		// SETTINGS_PLAYER_PANEL_TANK
	vec4f(23,41,37,37),		// SETTINGS_PLAYER_BUTTON_MODEL_NEXT
	vec4f( 7,41,21,37),		// SETTINGS_PLAYER_BUTTON_MODEL_PREV
};

vec3f PlayerSettingsButtonColors[NUM_SETTINGS_PLAYER_BUTTONS+1] = {
	vec3f( 0.1, 0.1, 0.1 ),		// SETTINGS_PLAYER_PANEL_TANK
	vec3f( 0.0, 0.8, 0.8 ),		// SETTINGS_PLAYER_BUTTON_MODEL_NEXT
	vec3f( 0.0, 0.8, 0.8 ),		// SETTINGS_PLAYER_BUTTON_MODEL_PREV
	vec3f( 1.0, 1.0, 1.0 ),		// button text color
};

const char* PlayerSettingsButtonText[NUM_SETTINGS_PLAYER_BUTTONS] = {
	NULL,
	"Next Model",		// SETTINGS_PLAYER_BUTTON_MODEL_NEXT
	"Prev Model",		// SETTINGS_PLAYER_BUTTON_MODEL_PREV
};

vec4f GlobalSettingsMainMenuButtonCoords[] = { vec4f( 63, 34, 93, 28 ) };
vec3f GlobalSettingsMainMenuButtonColors[2] = 
{ vec3f( 0.0, 0.0, 1.0 ), vec3f( 1.0, 1.0, 0.0 ) };
const float GlobalSettingsMainMenuButtonAlpha[]  = { 0.7 };
const char* GlobalSettingsMainMenuButtonText[] = { "Main Menu" };

vec4f INGAME_GlobalSettingsMainMenuButtonCoords[] = { vec4f( 63, 34, 93, 28 ) };
vec3f INGAME_GlobalSettingsMainMenuButtonColors[2] = 
{ vec3f( 1.0, 0.0, 0.0 ), vec3f( 1.0, 1.0, 0.0 ) };
const float INGAME_GlobalSettingsMainMenuButtonAlpha[]  = { 0.7 };
const char* INGAME_GlobalSettingsMainMenuButtonText[] = { "! DISCONNECT !" };

typedef enum { 
	SETTINGS_VIDEO_BUTTON_APPLY, 
	//SETTINGS_VIDEO_BUTTON_REJECT,
	SETTINGS_VIDEO_BUTTON_RES,
	SETTINGS_VIDEO_BUTTON_BPP,
	SETTINGS_VIDEO_BUTTON_FREQ,
	SETTINGS_VIDEO_BUTTON_FULLSCREEN,
	NUM_SETTINGS_VIDEO_BUTTONS
} SettingsVideoButtonID;

vec4f VideoSettingsButtonCoords[NUM_SETTINGS_VIDEO_BUTTONS] = {
	vec4f(  7, 34, 37, 28 ),	// SETTINGS_VIDEO_BUTTON_APPLY
	//vec4f( 63, 34, 93, 28 ),	// SETTINGS_VIDEO_BUTTON_REJECT

	vec4f(0,0,0,0),				// placeholder -- replaced in DrawVideoSettingsMenu
	vec4f(0,0,0,0),				// placeholder -- replaced in DrawVideoSettingsMenu
	vec4f(0,0,0,0),				// placeholder -- replaced in DrawVideoSettingsMenu
	vec4f(0,0,0,0),				// placeholder -- replaced in DrawVideoSettingsMenu
};

const vec3f VideoSettingsButtonColors[NUM_SETTINGS_VIDEO_BUTTONS+1] = {
	vec3f( 0.0, 1.0, 0.0 ),	// SETTINGS_VIDEO_BUTTON_APPLY
	//vec3f( 1.0, 0.0, 0.0 ),	// SETTINGS_VIDEO_BUTTON_REJECT

	vec3f( 0.5, 0.5, 0.5 ), // menu selection colors
	vec3f( 0.5, 0.5, 0.5 ), // menu selection colors
	vec3f( 0.5, 0.5, 0.5 ), // menu selection colors
	vec3f( 0.5, 0.5, 0.5 ), // menu selection colors

	vec3f( 1.0, 1.0, 0.0 ),	// button text color
};

const char* VideoSettingsButtonText[NUM_SETTINGS_VIDEO_BUTTONS] = {
	"Apply",	// SETTINGS_VIDEO_BUTTON_APPLY
	//"Reject",	// SETTINGS_VIDEO_BUTTON_REJECT
	NULL,
	NULL,
	NULL,
	NULL,
};

#define N_CREDIT_LINES 52
const char* CreditsHeadline = 
	"This game would have been impossible without the following:";
const char* CreditTextName[N_CREDIT_LINES] = {
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"\n- H O V E R T A N K -",
	"\nby",
	"\nA u g u s t o    R o m a n"
	"",
	"",
	"",
	"",
	"",
	"[ Friends & Family ]",
	"Edgar Roman (brother)",
	"Hrefna & Finnur",
	"Kerri Kusza, Hrefna & Finnur",
	"All of the above",
	"All my friends & family",
	"",
	"[ Resources ]",
	"Books:",
	"\t\"The Red Book\" - OpenGL Programming Guide, 3rd Ed.",
	"\tReal-time Rendering",
	"Incredibly useful game development sites:",
	"\tNehe's Game Tutorials (nehe.gamedev.net)",
	"\t   (also, the rest of www.gamedev.net!)",
	"\tFlipcode (www.flipcode.com)",
	"\tGamesutra (www.gamesutra.com)",
	"\t3D Gate (http://www.3dgate.com)",
	"\tROAM (http://www.llnl.gov/graphics/ROAM)",
	"\t  and the simple implementation by Bryan Turner off of Gamesutra)",
	"\tSounds",
	"",
	"[Libaries / Code]",
	"\tGLUT32 (Nate Robins)",
	"",
	"\tnVidia tech demos",
	"\tglh",
	"\t   (includes zLib)",
	"",
	"\tlibpng",
	"\tROAMsimple",
	"",
	"\tBASS (http://www.un4seen.com/music/)",
	"",
	"",
};
const char* CreditTextTask[N_CREDIT_LINES] = {
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"Inspiration, ideas, advice, and tank models",
	"Life support during the final week",
	"Intense play testing throughout",
	"Participation in final presentation!",
	"For infinite support and encouragement",
	"",
	"",
	"",
	"Woo, Neider, Davis, Shreiner",
	"Moller, Haines",
	"",
	"All the tutorials",
	"",
	"Articles, tutorials",
	"Especially the networking tutorials",
	"Textures",
	"Dynamic Terrain",
	"",
	"Acquired randomly from the internet from free sound sites",
	"",
	"",
	"Used to get started, eventually wrote \"GLUTAR\" - ",
	"my own (simple) implementation hacked to provide special needs.",
	"Ideas and some support code, glh & libpng below.",
	"\"A platform-independent OpenGL helper library\" --",
	"includes useful things like vectors and 2D arrays.",
	"Obtained from nVidia demo sources.  Modified to suit my program.",
	"Also from nVidia demo sources & modified for my program.",
	"Incorporated into my program, later discarded",
	"for being too slow. (probably my fault)",
	"Sound library",
	"(this was AWESOME.  Easy to use, incredibly powerful!)",
	"",
};
float creditTopLine;

vec3f creditCols[N_CREDIT_LINES+1];
vec3f creditTaskCols[N_CREDIT_LINES+1];

float creditColsTgt[N_CREDIT_LINES+1];
float creditTaskColsTgt[N_CREDIT_LINES+1];

#define N_CONTROL_HELP_LINES 31

const char* ControlHelpTitle = "HoverTank Controls";

const char* ControHelpText[N_CONTROL_HELP_LINES] = {
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"[ Tank Controls ]",
	"Keyboard:",
	"\tLEFT, RIGHT turn",
	"\tUP, DOWN thrust and brake respectively",
	"\tLEFT SHIFT fires",
	"\t'x' commits suicide (try it on a tree!)",
	"Mouse:",
	"\tLEFT MOUSE BUTTON fires",
	"\tRIGHT MOUSE BUTTON thrusts",
	"\tMouse X axis  (side to side) turns",
	"",
	"[ Game Controls ]",
	"\tESC during the game brings up the menu",
	"\tTAB displays the scoreboard",
	"\t't' chats with other players",
	"",
	"[ Music Controls ]",
	"\t[,] Cycles backwards/forwards through in-game songs",
	"\t\\ toggles in-game music",
	"\tm,k toggle DirectInput acquiring of mouse and keyboard, respectively.",
	"",
};


MenuInformation::MenuInformation()
{
	inGameMenu = false;

	state = MS_MAIN;
	selectedItem = 0;
	selectedNetServer = -1;
	selectionPosition = 0;
	selectionVel = 0;
	selectionAcc = 5.0;
	numItems = NUM_MAIN_MENU_ITEMS;

	input.mousex = 50*5;
	input.mousey = 50*5;

	texture_data_loaded = false;

	bEditingLabel = false;

	strcpy(workingPlayerName,"HoverTankDude");
	strcpy(workingServerAddress,"");
	game.netclient.SetPlayerName(workingPlayerName);
	game.netclient.SetServerName("");

	currentWorldFade = 0;
	targetWorldFade = 1;
	worldFadeSpeed = 0.2;
	statusMessageFadeSpeed = 0.6;

	settingsMenuChoiceFadeSpeed = 1.0;
	selectedSettingsMenuChoice = SETTINGS_PANEL_VIDEO_CHOICE;

	remainingStatusMessageDisplayTime=0;

	tankModelRotationSpeed = 90;		// in deg / sec
	tankModelRotation = 0;

	creditTopLine = 0;
	for (int i=0; i < N_CREDIT_LINES; i++)
	{
		creditCols[i] =  creditTaskCols[i] = vec3f(0,0,0);
		creditColsTgt[i] = creditTaskColsTgt[i] = 270.0/N_CREDIT_LINES * i;
	}
}

inline bool PointInRect(int px, int py, vec4f coords)
{	return (px >= coords[0] && px <= coords[2] && py >= coords[3] && py <= coords[1]); }

inline bool PointInRect(int px, int py, int rx1, int ry1, int rx2, int ry2)
{	return (px >= rx1 && px <= rx2 && py >= ry1 && py <= ry2); }

void MenuInformation::HandleMouse(bool click)
{
	int mx = input.mousex / 5;
	int my = input.mousey / 5;
	int selIdx;
	float hItem = 10.0;
	float hSep  = 10.0/6.0;
	float hLet  = 5.3;

	switch (state)
	{
		case MS_MAIN:
			if (PointInRect(mx,my,15,24,85,80))
			{
				selIdx = NUM_MAIN_MENU_ITEMS - (my - (20 + hLet/2.0 + hSep)*0.925)/(hItem+hSep);
				if (selIdx < 0) selIdx = 0;
				if (selIdx >= numItems) selIdx = numItems-1;

				if (selIdx == selectedItem && click)
					SelectItem();
				else
					SetItemSel(selIdx);
			}
			break;
		case MS_SETTINGS:
			{
				if (click)
				{
					if (PointInRect(mx,my,GlobalSettingsMainMenuButtonCoords[0]))
					{
						if (inGameMenu)
						{
							for (int i=0; i < NUM_SOUNDS; i++)
								StopSound(i);
							SetStatusMessage(false,0.5,"Disconnected from server.");
							game.netclient.Disconnect();
							game.SetState(GS_MENU);
						}
						else
							ChangeMenu(MS_MAIN);

						return;
					}
					if (PointInRect(mx,my,SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND]))
					{
						switch (selectedSettingsMenuChoice)
						{
							case SETTINGS_PANEL_VIDEO_CHOICE:
								HandleVideoSettingsMouse(click);
								break;
							case SETTINGS_PANEL_CREDITS_CHOICE:
								break;
							case SETTINGS_PANEL_CONTROL_CHOICE:
								break;
							case SETTINGS_PANEL_PLAYER_CHOICE:
								HandlePlayerSettingsMouse(click);
								break;
						}
					}
					else
					{
						for (int i=0; i < NUM_SETTINGS_PANELS-1; i++)
							if (PointInRect(mx,my,
								SettingsPanelCoords[i][0],
								SettingsPanelCoords[i][3],
								SettingsPanelCoords[i][2],
								SettingsPanelCoords[i][1] ))
							{
								SelectSettingsMenu(i);
								creditTopLine=0;
							}
					}
				}
				break;
			}
		case MS_JOIN_NETWORK_GAME:
			if (!bEditingLabel || click)
			{
				if (PointInRect(mx,my,50,71,92,77))
					selIdx = PLAYER_NAME;
				else if (PointInRect(mx,my,8,40,90,66))
				{
					selIdx = SERVER_LIST;
					if (click)
					{
						int potentialServerSelect = (63-my)/4;
						//printf("Attempted to select server #%d\n",potentialServerSelect);
						if (potentialServerSelect >= 0 && potentialServerSelect < game.netclient.GetNumFoundServers())
							selectedNetServer = potentialServerSelect;
						else
							selectedNetServer = -1;
					}
				}
				else if (PointInRect(mx,my,8,35,29,40))
					selIdx = JOIN_GAME;
				else if (PointInRect(mx,my,35,28,92,34))
					selIdx = SERVER_NAME;
				else
					selIdx = NOSELECTION;
				if (click)
				{
					if (selectedItem == selIdx && !bEditingLabel)
						SelectItem();
					else
						SetItemSel(selIdx);
				}
				else
					SetItemSel(selIdx);
			}
			break;
	}
}

const bool USE_SOUND = true;

void MenuInformation::SelectSettingsMenu(int menu)
{
	if (menu != selectedSettingsMenuChoice)
	{
		printf("\rsetting: %d->%d   \n",selectedSettingsMenuChoice,menu);
		selectedSettingsMenuChoice = menu;
		if (USE_SOUND)	PlaySound(HTMenuSelect);
	}
}


#define KEYCODE_BACKSPACE 8
#define KEYCODE_RETURN 13
#define KEYCODE_ESC    27

bool MenuInformation::HandleInput(InputEvent_type e)
{
	int len;
	if (e.type == IE_KB)
	{
		switch (state)
		{
			default:
				if (e.key == KEYCODE_ESC)
				{
					if (inGameMenu)
						return false;
					ChangeMenu(MS_MAIN);
					return true;
				}
				break;
			case MS_MAIN:
				switch (e.key)
				{
					case '8':	SetItemSel(selectedItem-1); return true;
					case '2':	SetItemSel(selectedItem+1); return true;
					case 13:    SelectItem(); return true;
					case 27:	if (state==MS_MAIN) PostQuitMessage(0);
								else ChangeMenu(MS_MAIN);
								return true;
				}
				break;

			case MS_JOINING_NETWORK_GAME:
				if (e.key == 27)
					networkStuffTimeoutTime = 0;		// Abort immediately
				break;

			case MS_JOIN_NETWORK_GAME:
				if (bEditingLabel)
				{
					char* strPtr;
					int maxlen;
					//printf("\rGot key code: %d   \n",(int)e.key);
					if (selectedItem == PLAYER_NAME)
					{
						strPtr = workingPlayerName;
						maxlen = MAX_PLAYER_NAME-1;
					}
					if (selectedItem == SERVER_NAME)
					{
						strPtr = workingServerAddress;
						maxlen = MAX_SERVER_NAME_LENGTH;
					}

					if (e.key == KEYCODE_BACKSPACE)
					{
						len = strlen(strPtr);
						if (len > 0)
							strPtr[len-1]=NULL;
					}
					else if (e.key == KEYCODE_RETURN)
					{
						SetItemSel(-1);
					}
					else if (e.key == KEYCODE_ESC)
					{
						bEditingLabel = false;
						if (selectedItem == PLAYER_NAME)
							strncpy(workingPlayerName,game.netclient.GetPlayerName(),MAX_PLAYER_NAME);
						else if (selectedItem == SERVER_NAME)
							strncpy(workingServerAddress,game.netclient.GetServerName(),MAX_SERVER_NAME_LENGTH);
					}
					else if (e.key >= 32 && e.key <= 126)
					{
						len = strlen(strPtr);
						if  (len < maxlen)
						{
							strPtr[len+1] = NULL;
							strPtr[len  ] = e.key;
						}
					}
					else
						printf("\rUnknown key code: %d \"%c\"    \n",(int)e.key,e.key);
					return true;
				}
				else
				{
					if (e.key == KEYCODE_ESC)
					{
						ChangeMenu(MS_MAIN);
						return true;
					}
					return false;
				}
		}
	}
	else if (e.type == IE_MOUSE)
	{
		if (e.button == GLUT_LEFT_BUTTON && e.state == GLUT_DOWN)
			HandleMouse(true);
		return true;
	}
	return false;
}

void MenuInformation::SelectItem()
{
	switch (state)
	{
		case MS_MAIN:
			PlaySound(HTMenuSelect);
			switch (selectedItem)
			{
				case START_GAME:
					//if (game.netclient.GetConnectionState()==HTCS_CONNECTED)
					selectionPosition = selectedItem;
					selectionVel = 0;
					if (!game.netserver.IsServerHosting())
					{
						//strncpy(StatusString,"Starting server, please wait...",MAX_PATH);
						SetStatusMessage(true,4.0,"Starting server, please wait...");
						printf("\n>> STARTING SERVER...\n");
						if (game.netserver.StartServer())
						{
							SetStatusMessage(false,1.0,"Server started");
							printf("\n>> SERVER STARTED\n");
						}
						else
						{
							SetStatusMessage(false,2.0,"ERROR: Could not start server");
							printf("\n>> COULD NOT START SERVER!\n");
						}
						QueryPerformanceCounter(&lasttime);
					}
					else
					{
						SetStatusMessage(true,4.0,"Stopping server, please wait...");
						//strncpy(StatusString,"Stopping server, please wait...",MAX_PATH);
						//DrawStatusMessage();
						printf("\n>> STOPPING SERVER...\n");
						game.netserver.StopServer();
						SetStatusMessage(false,2.0,"Server stopped");
						printf("\n>> SERVER STOPPED\n");
					}
					//game.SetState(GS_PLAYING);
					break;
				case JOIN_NETWORK_GAME:
					ChangeMenu(MS_JOIN_NETWORK_GAME);
					break;
				case SETTINGS:
					ChangeMenu(MS_SETTINGS);
					break;
				case REPLAY_INTRO:
					game.SetState(GS_INTRO);
					break;
				case QUIT_GAME:
					PostQuitMessage(0);
					break;
			}
			break;
		case MS_JOIN_NETWORK_GAME:
			switch (selectedItem)
			{
				default:
				case NOSELECTION:
					break;
				case PLAYER_NAME:
					bEditingLabel = true;
					break;
				case SERVER_NAME:
					bEditingLabel = true;
					break;
				case JOIN_GAME:
					if (selectedNetServer != -1)
					{
						if (game.netclient.StartConnectingToServer(selectedNetServer))
						{
							// Initiating the connection succeeded!  Now we're trying
							// to connect, so set state appropriately.
							ChangeMenu(MS_JOINING_NETWORK_GAME);
						}
					}

					break;
			}
			break;
	};
}

void MenuInformation::SetItemSel(int idx)
{
	if (selectedItem == idx)
		return;

	PlaySound(HTMenuChangeItem);

	if (bEditingLabel)
	{
		if (selectedItem == SERVER_NAME)
		{
			game.netclient.SetSearching(false);
			game.netclient.SetServerName(workingServerAddress);
			game.netclient.SetSearching(true);
		}
		else if (selectedItem == PLAYER_NAME)
			game.netclient.SetPlayerName(workingPlayerName);
	}
	bEditingLabel = false;

	if (idx < 0)					selectedItem = numItems-1;
	else if (idx >= numItems)	selectedItem = 0;
	else								selectedItem = idx;

	//selectionPosition = selectedItem;
}

void MenuInformation::ChangeMenu(MenuState newmenu)
{
	// If we _were_ in the join network game menu,
	// quit searching for a game now that we've found one.
	if (state == MS_JOIN_NETWORK_GAME && newmenu != MS_JOIN_NETWORK_GAME)
		game.netclient.SetSearching(false);

	switch(newmenu)
	{
		case MS_MAIN:
			numItems = NUM_MAIN_MENU_ITEMS;
			selectedItem = state;		// Set to previous menu item
			printf("\rSet main menu! \n");
			break;
		case MS_JOIN_NETWORK_GAME:
			numItems = NUM_NET_MENU_ITEMS;
			game.netclient.Init();
			game.netclient.SetSearching(true);
			selectedItem = NOSELECTION;
			printf("\rSet network menu! \n");
			break;
		case MS_SETTINGS:
			{
				for (int i=0; i < NUM_SETTINGS_PANELS; i++)
					settingsMenuChoiceAlpha[i] = 0;
				selectedSettingsMenuChoice=SETTINGS_PANEL_PLAYER_CHOICE;
				ResetVideoSettingsMenu();
				
				workingPlayerTankModel = 0;
			}
			printf("\rSet settings menu! \n");
			numItems = 0;					//--------------------------------     *** fix me!
			break;
		case MS_IN_GAME_MAIN:
			numItems = 0;					//--------------------------------     *** fix me!
			break;
		case MS_JOINING_NETWORK_GAME:
			//strncpy(StatusString,"Attempting to connect to server...",MAX_PATH);
			SetStatusMessage(false,10.0,"Attempting to connect to server...");
			lastNetworkStatus = HTCS_NOT_CONNECTED;
			abortingNetworkConnection = false;
			networkStuffTimeoutTime = game.world.currentTime + networkTimeOut;
			break;
	}
	state = newmenu;
}

void DrawMultiRect(float x1, float y1, float x2, float y2, float z, int divisions=1)
{
	float i,j;
	float xstep = (x2-x1)/divisions;
	float ystep = (y2-y1)/divisions;
	const float scale = 50.0;
	for (j=y1; j <= y2; j += ystep)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (i=x1; i <= x2; i += xstep)
		{
			glTexCoord2f( i/scale, j/scale +0.5 );
			glVertex3f( i,      j, z );
			glTexCoord2f( i/scale, (j+ystep)/scale +0.5 );
			glVertex3f( i, j+ystep, z );
		}
		glEnd();
	}
}

void MenuInformation::DrawMenuScreenBkg()
{
	const float scale = 50.0;

	if (input.shield)
		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	else
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);

	glColor4f(1.0,1.0,1.0,1.0);
	texob.enable();
	texob.bind();
	DrawMultiRect(0,0,100,100,-0.9);

	glDisable(GL_BLEND);

	/*
	//DrawMultiRect(0,0,100,100,-0.9,0.3);
	//DrawMultiRect(0,0,100,100,-0.9,50);
	glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f( 0, 0 );
		glVertex3f(  0,  0,-0.9);
		glTexCoord2f( 0, 100*scale );
		glVertex3f(  0,100,-0.9);
		glTexCoord2f( 100*scale, 0 );
		glVertex3f(100,  0,-0.9);
		glTexCoord2f( 100*scale, 100*scale );
		glVertex3f(100,100,-0.9);
	glEnd();
	*/
	texob.unbind();
	texob.disable();

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	/*
	glPushMatrix();
	glTranslatef(50,82.5,0.2);
	glScalef(20,20,1);
	glColor4f(1.0,0,0,0.5);
	game.font[FNT_TITLE]->printCenter("HoverTank");
	glPopMatrix();
	*/
	glColor4f(1.0,0,0,0.5);
	game.font[FNT_TITLE]->setScale(20,20,1);
	game.font[FNT_TITLE]->printxyzCenter(50,82.5,0.2,"HoverTank");

	glEnable(GL_LINE_SMOOTH);
	/*
	glPushMatrix();
	glTranslatef(50,82.5,0.2);
	glScalef(20,20,1);
	glColor4f(1.0,1.0,0,1.0);
	game.font[FNT_TITLE_OUTLINE]->printCenter("HoverTank");
	glPopMatrix();
	*/
	glColor4f(1.0,1.0,0,1.0);
	game.font[FNT_TITLE_OUTLINE]->setScale(20,20,1);
	game.font[FNT_TITLE_OUTLINE]->printxyzCenter(50,82.5,0.2,"HoverTank");
	glDisable(GL_LINE_SMOOTH);

	glDisable(GL_BLEND);
}

void MenuInformation::DrawMainMenu()
{
	int i;

	glPushMatrix();
	glTranslatef(0,5,0);
	glScalef(1,0.925,1);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	//glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mat_dif_menu);
	glColor4f(0.2,0.2,0.2,0.7);
	//DrawMultiRect(10,20,90,80,-0.1);
	
	glBegin(GL_QUADS);
		glVertex3f(10,20,-0.1);
		glVertex3f(90,20,-0.1);
		glVertex3f(90,80,-0.1);
		glVertex3f(10,80,-0.1);
	glEnd();
	//*/

	glDisable(GL_BLEND);

	glPushMatrix();
	glTranslatef(50,20 + 5.3/2.0 + 10.0/6.0 ,0);
	float hItem = 10.0;
	float hSep  = 10.0/6.0;
	float hLet  = 5.3;
	float yTop  = hLet/2.0 + hItem/2.0;
	float yBot  = hLet/2.0 - hItem/2.0;
	//glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mat_dif_lets);
	
	for (i=0; i < numItems; i++)
	{
		glPushMatrix();
		//glColor4f(0.0,1.0,1.0,0.5);
		glColor4f(1.0,0.0,0.0,1.0);
		glScalef(10,9,1);
		if (i==numItems-1)
		{
			if (!game.netserver.IsServerHosting())
				game.font[FNT_MENU1]->printCenter(mainMenuText[NUM_MAIN_MENU_ITEMS-i-1]);
			else
				game.font[FNT_MENU1]->printCenter("Stop Server");
		}
		else
			game.font[FNT_MENU1]->printCenter(mainMenuText[NUM_MAIN_MENU_ITEMS-i-1]);
		glPopMatrix();
		glTranslatef(0,hItem+hSep,0);
	}
	

	/*
	glTranslatef(0,numItems*(hItem+hSep),0);
	float zyBot =  -(numItems)*(hItem)-(numItems-1)*hSep - hItem/2;
	float zyTop =  -hLet/2;
	glBegin(GL_TRIANGLE_STRIP);
			glColor4f(1.0,0.0,0.0,1.0);
		glVertex3f( -30 ,  zyTop, 0.0 );
			glColor4f(0.0,0.0,0.0,1.0);
		glVertex3f( -30 ,  zyBot, 0.0 );
			glColor4f(1.0,0.0,0.0,0.0);
		glVertex3f(  30 ,  zyTop, 0.0 );
			glColor4f(0.0,0.0,0.0,0.0);
		glVertex3f(  30 ,  zyBot, 0.0 );
	glEnd();
	*/
	

	glEnable(GL_BLEND);

	//glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR,GL_ONE_MINUS_CONSTANT_COLOR);
	//glBlendFunc(GL_DST_COLOR,GL_ONE_MINUS_CONSTANT_COLOR);
	glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE_MINUS_SRC_COLOR);
	//glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR,GL_ONE_MINUS_CONSTANT_COLOR);

	glTranslatef(0, - selectionPosition * ( hItem + hSep ) - hItem - hSep, 0);
	//glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mat_dif_menu);
	//glColor4f(0.3,1.0,1.0,0.3);
	glColor4f(0.0,0.5,0.0,1.0);
	//DrawMultiRect(-35,yBot,35,yTop, 0.1, 1);
	glBegin(GL_QUADS);
			glColor4f(0.0,1.0,0.0,0.0);
		glVertex3f( -35 ,  yBot, 0.1 );
			glColor4f(0.0,1.0,0.0,0.0);
		glVertex3f(  35 ,  yBot, 0.1 );
			glColor4f(0.0,0.0,1.0,0.0);
		glVertex3f(  35 ,  yTop, 0.1 );
			glColor4f(0.0,0.0,1.0,0.0);
		glVertex3f( -35 ,  yTop, 0.1 );
	glEnd();
	glPopMatrix();

	glDisable(GL_BLEND);

	glPopMatrix();
}

void MenuInformation::DrawMenuMouse()
{
	//glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mat_dif_titl);

	if (input.mousex < 0)	input.mousex = 0;
	if (input.mousex > 100*5)	input.mousex = 100*5;
	if (input.mousey < 0)	input.mousey = 0;
	if (input.mousey > 100*5)	input.mousey = 100*5;
	float mx = input.mousex/5.0;
	float my = input.mousey/5.0;



	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	glPushMatrix();
	glTranslatef(mx,my,0.5);
	glRotatef(30,0,0,1);
	glColor4f(1.0,1.0,0.0,0.5);
	glBegin(GL_TRIANGLE_STRIP);
		glVertex3f(  -5,  -10, 0.1 );
		glVertex3f(   0, -7.5, 0.1 );
		glVertex3f(   0,    0, 0.1 );
		glVertex3f(   5,  -10, 0.1 );
	glEnd();
	glPopMatrix();

	glDisable(GL_BLEND);
}

void MenuInformation::Draw()
{
	if (inGameMenu)
	{
		state = MS_SETTINGS;
		glClear(GL_DEPTH_BUFFER_BIT);
		SetMenuDisplayMode();
		DrawSettingsMenu();
		DrawMenuMouse();
		return;
	}


	DrawMenuWorld();

	SetMenuDisplayMode();

	MaskoutMenuWorld();

	if (state != MS_IN_GAME_MAIN)
		DrawMenuScreenBkg();

	switch (state)
	{
		default:
		case MS_MAIN:				DrawMainMenu();		break;
		case MS_JOIN_NETWORK_GAME:	DrawNetMenu();		break;
		case MS_SETTINGS:			DrawSettingsMenu();	break;
		case MS_IN_GAME_MAIN:		DrawInGameMenu();	break;
		case MS_JOINING_NETWORK_GAME: DrawNetMenu(); break;
	}
	if (statusMessageAlpha > 0)
		DrawStatusMessage(false);

	DrawMenuMouse();

	glEnable(GL_DEPTH_TEST);
}

void MenuInformation::SetStatusMessage(bool forceUpdate, timet minDisplayTime, char* fmt, ...)
{
	float		length=0;											// Used To Find The Length Of The Text
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(StatusString, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	remainingStatusMessageDisplayTime = minDisplayTime;
	statusMessageAlpha = 1.0;

	DrawStatusMessage(forceUpdate);
}

void MenuInformation::DrawStatusMessage(bool forceUpdate)
{
	/*
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	Draw();
	*/
	GLfloat textz = 0.3;
	game.font[FNT_MENU2]->setScale(3,4,1);

	glEnable(GL_BLEND);
	glDisable(GL_CULL_FACE);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	// Draw background of status line
	glColor4f(0.0,0.0,0.0,0.7*statusMessageAlpha);
	glBegin(GL_QUADS);
		glVertex3f(5,43,0.2);
		glVertex3f(95,43,0.2);
		glVertex3f(95,50,0.2);
		glVertex3f(5,50,0.2);
	glEnd();

	// Draw border of status line
	glColor4f(1.0,1.0,0.0,0.7*statusMessageAlpha);
	glBegin(GL_LINE_LOOP);
		glVertex3f(5,43,0.2);
		glVertex3f(95,43,0.2);
		glVertex3f(95,50,0.2);
		glVertex3f(5,50,0.2);
	glEnd();

	glColor4f(0.8,0.8,0.8,1.0*statusMessageAlpha);
	//game.font[FNT_MENU2]->printxyz(7,45,textz,StatusString);
	game.font[FNT_MENU2]->printxyzCenter(50,45,textz,StatusString);

	glDisable(GL_BLEND);
	
	if (forceUpdate)
		glutarSwapBuffers();
}

void MenuInformation::DrawNetMenu()
{
	GLfloat textz = 0.1;

	game.font[FNT_MENU2]->setScale(3,4,1);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	// Draw menu window background
	glColor4f(0.2,0.2,0.2,0.7);
	glBegin(GL_QUADS);
		glVertex3f(5,26,-0.1);
		glVertex3f(95,26,-0.1);
		glVertex3f(95,80,-0.1);
		glVertex3f(5,80,-0.1);
	glEnd();

	// Draw edit label backgrounds
	// Name label
	if (bEditingLabel && selectedItem == PLAYER_NAME)
		glColor4f(1.0, 0.0, 0.0, 0.3);
	else
		glColor4f(0.0,0.0,1.0,0.3);
	glBegin(GL_QUADS);
		glVertex3f( 50, 71 , 0);
		glVertex3f( 92, 71 , 0);
		glVertex3f( 92, 77 , 0);
		glVertex3f( 50, 77 , 0);
	glEnd();
	// Server address label
	if (bEditingLabel && selectedItem == SERVER_NAME)
		glColor4f(1.0, 0.0, 0.0, 0.3);
	else
		glColor4f(0.0,0.0,1.0,0.3);
	glBegin(GL_QUADS);
		glVertex3f( 35.5, 28 , 0);
		glVertex3f( 92  , 28 , 0);
		glVertex3f( 92  , 34 , 0);
		glVertex3f( 35.5, 34 , 0);
	glEnd();
	// Server listing background
	glColor4f(0.0,1.0,1.0,0.2);
	glBegin(GL_QUADS);
		glVertex3f(  8, 66 , 0);
		glVertex3f( 90, 66 , 0);
		glVertex3f( 90, 40 , 0);
		glVertex3f(  8, 40 , 0);
	glEnd();

	// Highlight selected server
	if (selectedNetServer >= 0 && selectedNetServer < game.netclient.GetNumFoundServers())
	{
		glColor4f(0.0,1.0,1.0,0.5);
		glBegin(GL_QUADS);
			glVertex3f(  9, 64-4*selectedNetServer , 0.01);
			glVertex3f( 89, 64-4*selectedNetServer , 0.01);
			glVertex3f( 89, 60-4*selectedNetServer , 0.01);
			glVertex3f(  9, 60-4*selectedNetServer , 0.01);
		glEnd();
	}
	else
		selectedNetServer = -1;

	// Server join button
	if (selectedNetServer == -1)
		glColor4f(1.0,1.0,1.0,0.3);
	else if (selectedItem == JOIN_GAME)
		glColor4f(0.0,1.0,0.6,0.3);
	else
		glColor4f(0.0,1.0,1.0,0.2);
	glBegin(GL_QUADS);
		glVertex3f(  8, 39 , 0);
		glVertex3f( 29, 39 , 0);
		glVertex3f( 29, 34 , 0);
		glVertex3f(  8, 34 , 0);
	glEnd();

	// Server listing border
	// Draw edit label highlight borders if selected
	// Name label
	glLineWidth(2);
	glColor4f(0.0,1.0,1.0,0.5);
	if (selectedItem == PLAYER_NAME)
	{
		glBegin(GL_LINE_LOOP);
			glVertex3f( 50, 71 , 0);
			glVertex3f( 92, 71 , 0);
			glVertex3f( 92, 77 , 0);
			glVertex3f( 50, 77 , 0);
		glEnd();
	}
	else if (selectedItem == SERVER_LIST)
	{
		glBegin(GL_LINE_LOOP);
			glVertex3f(  8, 66 , 0);
			glVertex3f( 90, 66 , 0);
			glVertex3f( 90, 40 , 0);
			glVertex3f(  8, 40 , 0);
		glEnd();
	}
	else if (selectedItem == SERVER_NAME)
	{
		// Server address label
		glBegin(GL_LINE_LOOP);
			glVertex3f( 35.5, 28 , 0);
			glVertex3f( 92  , 28 , 0);
			glVertex3f( 92  , 34 , 0);
			glVertex3f( 35.5, 34 , 0);
		glEnd();
	}
	else if (selectedItem == JOIN_GAME)
	{
		glBegin(GL_LINE_LOOP);
			glVertex3f(  8, 39 , 0);
			glVertex3f( 29, 39 , 0);
			glVertex3f( 29, 34 , 0);
			glVertex3f(  8, 34 , 0);
		glEnd();
	}

	glDisable(GL_BLEND);

	if (selectedNetServer == -1)
		glColor4f(0.5,0.5,0.5,1.0);
	else
		glColor4f(0.7,0.9,0.7,1.0);
	game.font[FNT_MENU2]->printxyz(9.5,35,textz,"Join Selected");

	glColor4f(0.8,0.8,0.8,1.0);
	game.font[FNT_MENU2]->printxyz(8,73,textz,"Player Name:");
	game.font[FNT_MENU2]->printxyzRight(90,73,textz,workingPlayerName);

	game.font[FNT_MENU2]->printxyz(8,67,textz,"Server list:");
	//if (game.netclient.GetNumFoundServers() == 0)
	{
		if (game.netclient.IsSearching())
		{
			if (game.netclient.GetNumFoundServers() > 0)
				glColor4f(0.5,0.9,0.5,1.0);
			else
				glColor4f(0.9,0.9,0.5,1.0);

			if (game.netclient.GetServerName()[0])
				game.font[FNT_MENU2]->printxyzRight(90,67,textz,"Searching \"%s\"",game.netclient.GetServerName());
			else
				game.font[FNT_MENU2]->printxyzRight(90,67,textz,"Searching for local servers");
		}
		else
		{
			glColor4f(0.9,0.5,0.5,1.0);
			game.font[FNT_MENU2]->printxyzRight(90,67,textz,"Cannot locate \"%s\"",game.netclient.GetServerName());
		}
		/*
		if (game.netclient.IsSearching())
		{
			if (game.netclient.GetServerName()[0])
				game.font[FNT_MENU2]->printxyz(10,61,textz,"<< Searching \"%s\" >>",game.netclient.GetServerName());
			else
				game.font[FNT_MENU2]->printxyz(10,61,textz,"<< Searching for local servers >>");
		}
		else
			game.font[FNT_MENU2]->printxyz(10,61,textz,"<< READY TO SEARCH >>");
		*/
	}
	//else
	{
		glColor4f(0.8,0.8,0.8,1.0);
		for (int i=0; i < game.netclient.GetNumFoundServers(); i++)
			game.font[FNT_MENU2]->printxyz(10,61-4*i,textz,"%s (%d/%d players) (%d ms)",
					game.netclient.GetFoundServerName(i),
					game.netclient.GetFoundServerNumPlayers(i),
					game.netclient.GetFoundServerMaxPlayres(i),
					game.netclient.GetFoundServerPing(i));
			//game.font[FNT_MENU2]->printxyz(10,61-4*i,textz,"%s",game.netclient.GetFoundServerName(i));
	}

	game.font[FNT_MENU2]->printxyz(8,30,textz,"Search for server at:");
	if (workingServerAddress[0] == 0)
		game.font[FNT_MENU2]->printxyzRight(90,30,textz,"< No server address entered >");
	else
		game.font[FNT_MENU2]->printxyzRight(90,30,textz,workingServerAddress);
}

void DrawPanel(vec4f coords)
{
	//glBegin(GL_TRIANGLE_STRIP);
	glBegin(GL_QUADS);
		glVertex2f(coords[0],coords[1]);
		glVertex2f(coords[0],coords[3]);
		glVertex2f(coords[2],coords[3]);
		glVertex2f(coords[2],coords[1]);
	glEnd();
}

void DrawButtons(int nbuts, const vec4f coords[], const vec3f colors[], const char* text[], const float alphas[], GLFont& fnt, const vec3f* borderColor=NULL)
{
	int i;
	float xcenter;
	bool includeText = text!=NULL;
	for (i=0; i < nbuts; i++)
	{
		// Draw button
		glColor(colors[i],alphas[i]-0.2);
		DrawPanel(coords[i]);
		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
		glColor(colors[i],alphas[i]);
		DrawPanel(coords[i]);
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

		if (includeText)
		{
			if (text[i])
			{
				// Draw text
				xcenter = (coords[i][0] + coords[i][2])/2.0;
				glColor(colors[nbuts],alphas[i]);
				fnt.printxyzCenter(xcenter,coords[i][3]+1,0,text[i]);
			}
		}
	}
}

void MenuInformation::ResetVideoSettingsMenu()
{
	workingVideoResolutionIdx = game.config.chosenVideoMode;
	workingVideoBitdepthIdx = game.config.chosenBitdepth;
	workingVideoFreqIdx = game.config.chosenFreq;
	workingVideoFullscreen = game.config.fullScreen;

	selectedVideoSettingsMenuItem = 0;

	return;
}

void MenuInformation::DrawVideoSettingsMenu()
{
	GLFont& fnt = *(game.font[FNT_MENU2]);
	const float VideoSettingsButtonAlpha[NUM_SETTINGS_VIDEO_BUTTONS] = 
		{ 0.5, /*0.5,*/ 0.8, 0.8, 0.8, 0.8 };

	float lineheight = fnt.getHeight() * 1.2;
	float leftx  = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][0]+2;
	float rightx = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][2]-2;
	float topy   = SettingsPanelCoords[SETTINGS_PANEL_VIDEO_CHOICE][3]-2*lineheight;

	float centerx = (leftx+rightx)/2.0;

	for (int i=0; i < 4; i++)
		VideoSettingsButtonCoords[i + SETTINGS_VIDEO_BUTTON_RES] = 
			vec4f( centerx    , topy -   i  *lineheight - 1.0, 
					 rightx + 1 , topy - (i+1)*lineheight - 0.5 );


	DrawButtons(NUM_SETTINGS_VIDEO_BUTTONS,
		VideoSettingsButtonCoords,
		VideoSettingsButtonColors,
		VideoSettingsButtonText,
		VideoSettingsButtonAlpha,
		fnt);

	float alpha = settingsMenuChoiceAlpha[SETTINGS_PANEL_BACKGROUND] + 0.2;

	VideoModeList& vm = game.config.availableModes;

	glColor( SettingsPanelColors[SETTINGS_PANEL_ITEM_TEXT], alpha );
	fnt.printxyz     (  leftx, topy - 1*lineheight, 0, "Resolution:");
	fnt.printxyzRight( rightx, topy - 1*lineheight, 0, "%dx%d",
		vm[workingVideoResolutionIdx].width,
		vm[workingVideoResolutionIdx].height);

	fnt.printxyz     (  leftx, topy - 2*lineheight, 0, "Bitdepth:");
	fnt.printxyzRight( rightx, topy - 2*lineheight, 0, "%d bpp",
		vm[workingVideoResolutionIdx].
		bitdepth[workingVideoBitdepthIdx].bitdepth);

	fnt.printxyz     (  leftx, topy - 3*lineheight, 0, "Frequency:");
	fnt.printxyzRight( rightx, topy - 3*lineheight, 0, "%d Hz",
		vm[workingVideoResolutionIdx].
		bitdepth[workingVideoBitdepthIdx].
		freq[workingVideoFreqIdx].freq);

	fnt.printxyz     (  leftx, topy - 4*lineheight, 0, "Fullscreen:");
	fnt.printxyzRight( rightx, topy - 4*lineheight, 0, "%s",
		workingVideoFullscreen ? "YES" : "NO" );
}

void MenuInformation::DrawGraphicsSettingsMenu()
{
	GLFont& fnt = *(game.font[FNT_MENU2]);

	fnt.setScale(2,3,1);
	float lineheight = fnt.getHeight() * 1.2;
	float leftx  = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][0]+1;
	float rightx = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][2]-1;
	float topy   = SettingsPanelCoords[SETTINGS_PANEL_VIDEO_CHOICE][3]-2*lineheight;

	float offset = creditTopLine - ((int)creditTopLine);

	if (creditTopLine >= 12.0)
	{
		fnt.setScale(3,4,1);
		if (((int)creditTopLine)==12)	glColor( creditCols[0] , 1.0-offset );
		else if (((int)creditTopLine)==N_CREDIT_LINES-1)	glColor( creditCols[0] , offset );
		else							{ glColor( creditCols[0] , 1.0 ); }
		fnt.printxyzCenter( (leftx+rightx)/2.0, topy, 0, CreditsHeadline );
	}

	fnt.setScale(2,3,1);
	topy -= lineheight*1.5;
	float taboffset = 3;
	//printf(" offset = %.2f  topline = %.2f \r",offset,creditTopLine);
	for (int i=0; i < 10; i++)
	{
		int lineIdx = ((int)(i+creditTopLine))%N_CREDIT_LINES;

		if (i==0)		glColor( creditCols[lineIdx+1] , 1.0-offset );
		else if (i==9)	glColor( creditCols[lineIdx+1] , offset );
		else				glColor( creditCols[lineIdx+1] , 1.0 );
		if (CreditTextName[lineIdx][0]=='[')
			fnt.printxyzCenter( (leftx+rightx)/2.0, topy - (i-offset)*lineheight , 0, CreditTextName[lineIdx] );
		else if (CreditTextName[lineIdx][0]=='\n')
			fnt.printxyzCenter( (leftx+rightx)/2.0, topy - (i-offset)*lineheight , 0, &CreditTextName[lineIdx][1] );
		else if (CreditTextName[lineIdx][0]=='\t')
			fnt.printxyz( leftx+taboffset, topy - (i-offset)*lineheight , 0, &CreditTextName[lineIdx][1] );
		else
			fnt.printxyz( leftx, topy - (i-offset)*lineheight , 0, CreditTextName[lineIdx] );

		if (i==0)		glColor( creditTaskCols[lineIdx+1] , 1.0-offset );
		else if (i==9)	glColor( creditTaskCols[lineIdx+1] , offset );
		else				glColor( creditTaskCols[lineIdx+1] , 1.0 );
		fnt.printxyzRight( rightx, topy - (i-offset)*lineheight, 0, CreditTextTask[lineIdx] );
	}
}

void MenuInformation::DrawControlSettingsMenu()
{
	GLFont& fnt = *(game.font[FNT_MENU2]);

	fnt.setScale(4,3,1);
	float lineheight = fnt.getHeight() * 1.2;
	float leftx  = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][0]+2;
	float rightx = SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND][2]-2;
	float topy   = SettingsPanelCoords[SETTINGS_PANEL_VIDEO_CHOICE][3]-2*lineheight;

	vec3f helpcol( 1.0, 1.0, 1.0 );

	fnt.setScale(3,4,1);
	glColor( helpcol , 1.0 );
	fnt.printxyzCenter( (leftx+rightx)/2.0, topy, 0, ControlHelpTitle );

	fnt.setScale(2,3,1);
	topy -= lineheight*1.5;
	float offset = creditTopLine - ((int)creditTopLine);
	float taboffset = 3;
	printf("\r offset = %.2f  topline = %.2f ",offset,creditTopLine);
	for (int i=0; i < 10; i++)
	{
		int lineIdx = ((int)(i+creditTopLine))%N_CONTROL_HELP_LINES;

		if (i==0)		glColor( helpcol , 1.0-offset );
		else if (i==9)	glColor( helpcol , offset );
		else				glColor( helpcol , 1.0 );
		if (ControHelpText[lineIdx][0]=='[')
			fnt.printxyzCenter( (leftx+rightx)/2.0, topy - (i-offset)*lineheight , 0, ControHelpText[lineIdx] );
		else if (ControHelpText[lineIdx][0]=='\t')
			fnt.printxyz( leftx+taboffset, topy - (i-offset)*lineheight , 0, &ControHelpText[lineIdx][1] );
		else
			fnt.printxyz( leftx, topy - (i-offset)*lineheight , 0, ControHelpText[lineIdx] );
	}
}


void MenuInformation::DrawPlayerSettingsMenu()
{
	GLFont& fnt = *(game.font[FNT_MENU2]);
	const float PlayerSettingsButtonAlpha[NUM_SETTINGS_PLAYER_BUTTONS] = 
		{ 0.8, 0.5, 0.5 };
	
	vec3f tankPreviewEyePos = menu_world.eyedyn.followerOffset;

	//---- Draw the preview tank
	vec4f& panelCoords = PlayerSettingsButtonCoords[SETTINGS_PLAYER_PANEL_TANK];
	float winXscale = glutarConfig.win_width / 100.0;
	float winYscale = glutarConfig.win_height / 100.0;
	float winX  = panelCoords[0] * winXscale;
	float winY  = panelCoords[3] * winYscale;
	float winDX = (panelCoords[2] - panelCoords[0]) * winXscale;
	float winDY = (panelCoords[1] - panelCoords[3]) * winYscale;

	/*
	printf("\r Win: %d,%d - %dx%d  (%dx%d) ",
		(int)winX, (int)winY, (int)winDX, (int)winDY,
		glutarConfig.win_width, glutarConfig.win_width );
		*/

	//menu_world.lightPos = vec4f(1,1,-1,0);
	glViewport( winX, winY, winDX, winDY );
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60, winDX/winDY, 1.0, 5000.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	menu_world.SetDisplayLighting();

	gluLookAt(
		0,  50, 30,
		0,   0,  0,
		UP[X], UP[Y], UP[Z] );

	glRotate(tankModelRotation,UP);
	glColor4f( 1.0, 1.0, 1.0, 1.0 );
	TankObject::tankModel[workingPlayerTankModel].call_list();

	glViewport(0,0,glutarConfig.win_width,glutarConfig.win_height);
	SetMenuDisplayMode();

	//---- Draw the control buttons
	fnt.setScale(2.5,3,1);
	DrawButtons(NUM_SETTINGS_PLAYER_BUTTONS,
		PlayerSettingsButtonCoords,
		PlayerSettingsButtonColors,
		PlayerSettingsButtonText,
		PlayerSettingsButtonAlpha,
		fnt);
}


void MenuInformation::DrawSettingsMenu()
{
	GLFont& fnt = *(game.font[FNT_MENU2]);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	int i;

	float fontheight = fnt.getBaseHeight();
	float lineheight = 4;
	fnt.setScale(4,lineheight/fontheight,1);
	for (i=0; i < NUM_SETTINGS_PANELS-1; i++)
	{
		if (i==selectedSettingsMenuChoice)
			glColor(SettingsPanelColors[SETTINGS_PANEL_BKG_SEL],settingsMenuChoiceAlpha[i]);
		else
			glColor(SettingsPanelColors[SETTINGS_PANEL_BKG_UNSEL],settingsMenuChoiceAlpha[i]);
		DrawPanel(SettingsPanelCoords[i]);

		float xcenter = (SettingsPanelCoords[i][0] + SettingsPanelCoords[i][2])/2.0;
		glColor(SettingsPanelColors[SETTINGS_PANEL_ITEM_TEXT],settingsMenuChoiceAlpha[i]);
		fnt.printxyzCenter( xcenter, SettingsPanelCoords[i][3] +1, 0, SettingsChoiceText[i] );
	}
	/*
	if (inGameMenu)
		glColor(SettingsPanelColors[SETTINGS_PANEL_BKG_SEL],settingsMenuChoiceAlpha[SETTINGS_PANEL_BACKGROUND]);
	else
	*/
		glColor(SettingsPanelColors[SETTINGS_PANEL_BKG_SEL],settingsMenuChoiceAlpha[SETTINGS_PANEL_BACKGROUND]);
	DrawPanel(SettingsPanelCoords[SETTINGS_PANEL_BACKGROUND]);

	switch(selectedSettingsMenuChoice)
	{
		default:
			// Unknown menu item, just choose video
			selectedSettingsMenuChoice=SETTINGS_PANEL_VIDEO_CHOICE;
		case SETTINGS_PANEL_VIDEO_CHOICE:
			DrawVideoSettingsMenu();
			break;
		case SETTINGS_PANEL_CREDITS_CHOICE:
			DrawGraphicsSettingsMenu();
			break;
		case SETTINGS_PANEL_CONTROL_CHOICE:
			DrawControlSettingsMenu();
			break;
		case SETTINGS_PANEL_PLAYER_CHOICE:
			DrawPlayerSettingsMenu();
			break;
	}

	fnt.setScale(4,lineheight/fontheight,1);

	if (inGameMenu)
	{
		const vec3f bordercol(1.0,0.0,0.0);
		DrawButtons(1, 
			INGAME_GlobalSettingsMainMenuButtonCoords,
			INGAME_GlobalSettingsMainMenuButtonColors,
			INGAME_GlobalSettingsMainMenuButtonText,
			INGAME_GlobalSettingsMainMenuButtonAlpha,
			fnt,&bordercol);
	}
	else
	{
		const vec3f bordercol(1.0,0.0,0.0);
		DrawButtons(1, 
			GlobalSettingsMainMenuButtonCoords,
			GlobalSettingsMainMenuButtonColors,
			GlobalSettingsMainMenuButtonText,
			GlobalSettingsMainMenuButtonAlpha,
			fnt,&bordercol);
	}

	glDisable(GL_BLEND);
}

void MenuInformation::DrawInGameMenu()
{
}

void HSV2RGB(float *r, float *g, float *b, float h, float s, float v)
{
	/* Taken directly from FvD */
	// For undefined H and S=0, we happily just set R=G=B=V :)
	if (s==0)
		*r = *g = *b = v*255;
	else
	{
		double f, p, q, t;
		int i;
		if (h>=360)
			h = 0.0;
		h /= 60.0;
		i = (int)h;
		f = h-i;
		p = v*(1.0-s)           *255;
		q = v*(1.0-(s*f))       *255;
		t = v*(1.0-(s*(1.0-f))) *255;
		v *= 255;
		switch(i)
		{
			case 0: *r=v; *g=t; *b=p; break;
			case 1: *r=q; *g=v; *b=p; break;
			case 2: *r=p; *g=v; *b=t; break;
			case 3: *r=p; *g=q; *b=v; break;
			case 4: *r=t; *g=p; *b=v; break;
			case 5: *r=v; *g=p; *b=q; break;
		}
	}
}


void MenuInformation::update(timet dtime)
{
	static bool inputPressed = false;

	if (state == MS_JOIN_NETWORK_GAME)
		game.netclient.UpdateServerList();

	menu_world.lightCol = vec4f(1.0,1.0,1.0,1.0);

	if (state == MS_SETTINGS)
	{
		int i;
		float tgtAlpha;
		for (i=0; i < NUM_SETTINGS_PANELS-1; i++)
		{
			if (i==selectedSettingsMenuChoice)
				tgtAlpha = settingsMenuPanelSelectedTargetAlpha;
			else
				tgtAlpha = settingsMenuPanelUnselectedTargetAlpha;
			settingsMenuChoiceAlpha[i] += (tgtAlpha-settingsMenuChoiceAlpha[i])*settingsMenuChoiceFadeSpeed*dtime;
		}
		// For main background, always selected during normal menu, and special during in-game
		if (inGameMenu)
			tgtAlpha = 0.95;
		else
			tgtAlpha = settingsMenuPanelSelectedTargetAlpha;
		settingsMenuChoiceAlpha[SETTINGS_PANEL_BACKGROUND] += 
			(tgtAlpha-settingsMenuChoiceAlpha[SETTINGS_PANEL_BACKGROUND])*
				settingsMenuChoiceFadeSpeed*dtime;

		vec3f col;
		for (i=0; i < N_CREDIT_LINES; i++)
		{
			HSV2RGB( &col[0], &col[1], &col[2], creditColsTgt[i], 1.0, 1.0 );
			col /= 256.0;
			creditCols[i] = col;
			creditColsTgt[i] -= 60*dtime;
			if (creditColsTgt[i] < 0) creditColsTgt[i] += 360;

			HSV2RGB( &col[0], &col[1], &col[2], creditTaskColsTgt[i], 1.0, 1.0 );
			col /= 256.0;
			creditTaskCols[i] = col;
			creditTaskColsTgt[i] -= 65*dtime;
			if (creditTaskColsTgt[i] < 0) creditTaskColsTgt[i] += 360;
		}
		creditTopLine += dtime * 1.0;  // dtime * lines_per_sec
		if (creditTopLine >= N_CREDIT_LINES)
			creditTopLine -= N_CREDIT_LINES;
	}
	else if (state == MS_JOINING_NETWORK_GAME)
	{
		if (game.world.currentTime > networkStuffTimeoutTime)
		{
			if (abortingNetworkConnection)
			{
				ChangeMenu(MS_JOIN_NETWORK_GAME);
				//abortingNetworkConnection = false;
			}
			else
			{
				SetStatusMessage(false,4.0,"Cannot connecting, aborting...");
				//strcpy(StatusString,"Cannot connect, aborting...");
				networkStuffTimeoutTime = game.world.currentTime + networkTimeOut;
				game.netclient.AbortNetworkConnect();
				ChangeMenu(MS_JOIN_NETWORK_GAME);
				//abortingNetworkConnection = true;
			}
		}
		else if ((game.netclient.GetConnectionState() != lastNetworkStatus || lastNetworkStatus == HTCS_CONNECTED) && !abortingNetworkConnection)
		{
			switch (game.netclient.GetConnectionState())
			{
				case HTCS_CONNECTING:
					SetStatusMessage(false,10.0,"Attempting to connect to server...");
					//strcpy(StatusString,"Attempting to connect to server...");
					break;
				case HTCS_CONNECTED:
					if (!game.netclient.m_SetupMsgReady)
					{
						SetStatusMessage(false,10.0,"Connected to server!  Retrieving game information...");
						//strcpy(StatusString,"Connected to server!  Retrieving game information...");
					}
					else
					{
						SetStatusMessage(false,10.0,"Received game information, loading level data...");
						//strcpy(StatusString,"Received game information, loading level data...");
						game.world.map.LoadMapByID(game.netclient.m_recvSetupMsg.mapID);
						game.world.map.GenTrees(game.netclient.m_recvSetupMsg.treeSeed,game.netclient.m_recvSetupMsg.numTrees);
						printf("\nServer-specified map data: ID%d, seed:%ud, ntrees:%d\n",game.netclient.m_recvSetupMsg.mapID,game.netclient.m_recvSetupMsg.treeSeed,game.netclient.m_recvSetupMsg.numTrees);
						game.world.map.RegisterModelData();
						game.world.Reset();
						//mouseAcquire(false);
						//keyboardAcquire(false);
						game.SetState(GS_PLAYING);
					}
					break;
				case HTCS_CONNECTION_FAILED:
					SetStatusMessage(false,10.0,"Uh oh!  Connection failed!");
					//strcpy(StatusString,"Uh oh!  Connection failed!");
					break;
				case HTCS_CONNECTION_TERMINATED:
					SetStatusMessage(false,10.0,"Uh oh!  Connection failed!");
					//strcpy(StatusString,"Uh oh!  Connection terminated!");
					break;
				case HTCS_NOT_CONNECTED:
					SetStatusMessage(false,10.0,"Uh oh!  Not connected!");
					//strcpy(StatusString,"Uh oh!  Not connected!");
					break;
				default:
					SetStatusMessage(false,10.0,"Uh oh!  Unknown network connection state! Very bad.");
					//strcpy(StatusString,"Uh oh!  Unknown network connection state! Very bad.");
					break;
			}
			if (lastNetworkStatus != game.netclient.GetConnectionState())
				networkStuffTimeoutTime = game.world.currentTime + networkTimeOut;
			lastNetworkStatus = game.netclient.GetConnectionState();
		}
	}

	HandleMouse(false);

	tankModelRotation += tankModelRotationSpeed * dtime;

	if (!inputPressed)
	{
		if (input.mousebuttons[0])
		{
			HandleMouse(true);
			inputPressed = true;
		}
		if (input.downkey)
		{
			SetItemSel(selectedItem+1);
			inputPressed = true;
		}
		if (input.upkey)
		{
			SetItemSel(selectedItem-1);
			inputPressed = true;
		}
	}
	else
	{
		if (!input.downkey && !input.upkey && !input.selectkey && !input.mousebuttons[0])
			inputPressed = false;
	}

	selectionVel = ((float)selectedItem - selectionPosition) * selectionAcc;
	selectionPosition += selectionVel * dtime;

	if (remainingStatusMessageDisplayTime > 0)
		remainingStatusMessageDisplayTime -= dtime;
	else if (statusMessageAlpha > 0)
		statusMessageAlpha -= statusMessageFadeSpeed * dtime;

	/*
	printf("\r %6.3lf sec status remaining, %3.0f%% alpha (%.5lf sec dtime)  ",
		(double)remainingStatusMessageDisplayTime,(float)statusMessageAlpha*1000,(double)dtime);
		*/

	UpdateMenuWorld(dtime);
}

void MenuInformation::UpdateMenuWorld(timet dtime)
{
	static GLfloat angle = 0.0;
	GLfloat dangle = 60.0 * dtime;
	static GLfloat eye_dist = 35;
	static GLfloat eye_height = 15;

	angle += dangle;
	while (angle >= 360.0)
		angle -= 360.0;

	GLfloat xcomp = cos( angle * M_PI / 180.0 );
	GLfloat ycomp = sin( angle * M_PI / 180.0 );

	menu_world.eyepoint.pos = menu_world.tank[0].model.pos + vec3f( xcomp*eye_dist, ycomp*eye_dist, eye_height );

	if (currentWorldFade != targetWorldFade)
	{
		if (currentWorldFade > targetWorldFade)
		{
			currentWorldFade -= worldFadeSpeed * dtime;
			if (currentWorldFade < targetWorldFade)
				currentWorldFade = targetWorldFade;
		}
		else
		{
			currentWorldFade += worldFadeSpeed * dtime;
			if (currentWorldFade > targetWorldFade)
				currentWorldFade = targetWorldFade;
		}
	}

	//menu_world.update(dtime);
}

void MenuInformation::MaskoutMenuWorld()
{
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA);
	GLfloat maskZ = 0.3;
	worldmasktexob.enable();
	worldmasktexob.bind();
	glColor4f(0.0,0.0,0.0,currentWorldFade);
	glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f( 0.0, 0.0 );
		glVertex3f( 2.5,   2.5, maskZ );
		glTexCoord2f( 0.0, 1.0 );
		glVertex3f( 2.5,  22.5, maskZ );
		glTexCoord2f( 1.0, 0.0 );
		glVertex3f( 97.5,    2.5, maskZ );
		glTexCoord2f( 1.0, 1.0 );
		glVertex3f( 97.5,   22.5, maskZ );
	glEnd();
	worldmasktexob.unbind();
	worldmasktexob.disable();
	glDisable(GL_BLEND);
}

void DrawTankModel();
void MenuInformation::DrawMenuWorld()
{
	vec<2,int> startPixel, endPixel;
	startPixel[X] = glutarConfig.win_width	* 0.025;
	endPixel[X]   = glutarConfig.win_width * 0.975 - startPixel[X];
	startPixel[Y] = glutarConfig.win_height * 0.025;
	endPixel[Y]   = glutarConfig.win_height * 0.225 - startPixel[Y];

	glViewport(startPixel[X],startPixel[Y],endPixel[X],endPixel[Y]);

	float oldasp = game.config.aspect;
	game.config.aspect = (endPixel[X]-startPixel[X]) / (endPixel[Y]-startPixel[Y]);

	//glClear(GL_DEPTH_BUFFER_BIT);
	glColor4f(0.0,0.0,0.0,1.0);

	//glEnable(GL_LIGHTING);
	//glEnable(GL_BLEND);
	//glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
	menu_world.lightPos = vec4f(-1,1,1,0);
	menu_world.Draw();
	//glDisable(GL_BLEND);
	//glDisable(GL_LIGHTING);

	//glDisable(GL_CULL_FACE);

	/*
	//-------------------------------------------------------------
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	float speedfactor = game.world.tank[0].model.vel.length() / game.world.tank[0].MaxVelocity;
	speedfactor -= 0.3;
	if (speedfactor < 0)	speedfactor = 0;

	gluPerspective(80 + 40*speedfactor, game.config.aspect, 1.0, 4000.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	static float lastEyeTargetZ = menu_world.tank[0].model.pos[Z];

	lastEyeTargetZ *= 0.9;
	lastEyeTargetZ += menu_world.tank[0].model.pos[Z] * 0.1;

	gluLookAt(menu_world.eyepoint.pos[X], menu_world.eyepoint.pos[Y], menu_world.eyepoint.pos[Z],
			  menu_world.tank[0].model.pos[X], menu_world.tank[0].model.pos[Y], lastEyeTargetZ,
			  0.0, 0.0, 1.0 );

	GLfloat lightpos[] = { 1.0, -0.5, 1.0, 0.0 };
	GLfloat lightcol[] = { 1.0, 1.0, 1.0, 1.0 };
	GLfloat lightamb[] = { 0.1, 0.1, 0.1, 1.0 };
	GLfloat lightspc[] = { 0.0, 0.0, 0.0, 1.0 };
	glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightcol);
	glLightfv(GL_LIGHT0, GL_AMBIENT, lightamb);
	glLightfv(GL_LIGHT0, GL_SPECULAR, lightspc);
	glEnable(GL_LIGHT0);

	//glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,light0_dir);
	glLightf (GL_LIGHT0,GL_SPOT_CUTOFF,180);
	//-------------------------------------------------------------//*/

	//menu_world.tank[0].DrawModel();
	/*
	glTranslate(menu_world.tank[0].model.pos);
	glScalef(3,3,3);
	menu_world.tank[0].model.dlist->call_list();
	/*
	glPushMatrix();
	glRotatef(90,0.0,0.0,1.0);
	glRotatef(90,1.0,0.0,0.0);
	glScalef(20.0,20.0,20.0);
	glColor4f(1.0,1.0,1.0,1.0);
	glDisable(GL_TEXTURE_2D);
	DrawTankModel();
	glPopMatrix();
	*/

	/*
	glTranslatef(20,0,0);

	glColor4f( 1.0, 1.0, 1.0, 1.0);
	glutSolidSphere(10,8,8);
	*/

	game.config.aspect = oldasp;
	glViewport(0,0,glutarConfig.win_width,glutarConfig.win_height);
}


void MenuInformation::ReleaseModels()
{
	texob.del();
	worldmasktexob.del();

	menu_world.ReleaseModels();

	setMenuMatrices.del();
}

bool MenuInformation::RegisterModels()
{
	if (!texture_data_loaded)
	{
		printf("ERROR: Cannot register texture -- no texture data loaded!\n");
		return false;
	}
	// Register the texture data:
	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
	texob.bind();
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,		// 2D texture mode
			0,										// mipmap level
			GL_RGBA,								// internal format
			textureimage.get_width(),		// image width
			textureimage.get_height(),		// image height
			0,										// image border (0/1)
			GL_RGB,								// image pixel format
			GL_UNSIGNED_BYTE,					// image pixel size/type
			textureimage.get_pointer());	// ptr to image data
	texob.unbind();

	worldmasktexob.bind();
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,		// 2D texture mode
			0,										// mipmap level
			GL_ALPHA,								// internal format
			worldmaskimage.get_width(),		// image width
			worldmaskimage.get_height(),		// image height
			0,										// image border (0/1)
			GL_ALPHA,								// image pixel format
			GL_UNSIGNED_BYTE,					// image pixel size/type
			worldmaskimage.get_pointer());	// ptr to image data
	worldmasktexob.unbind();

	menu_world.RegisterModels();

	setMenuMatrices.new_list(GL_COMPILE);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0,100,0,100);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glLineWidth(1.5);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_LIGHTING);
		glDisable(GL_CULL_FACE);
	setMenuMatrices.end_list();

	return true;
}

bool MenuInformation::LoadData()
{
	char* fname = "../data/rusty2.png";
	printf("Reading texture map (%s): ",fname);
	if (!read_png_rgb(fname,textureimage))
	{
		printf("> Error loading texture\n");
		return false;
	}
	printf("[%d,%d]\n",textureimage.get_width(),textureimage.get_height());

	char* fname2 = "../data/menu_world_mask2.png";
	printf("Reading texture map (%s): ",fname2);
	if (!read_png_grey(fname2,worldmaskimage))
	{
		printf("> Error loading texture\n");
		return false;
	}
	printf("[%d,%d]\n",worldmaskimage.get_width(),worldmaskimage.get_height());

	menu_world.map.LoadMapByID(1);

	texture_data_loaded = true;

	return true;
}

void MenuInformation::HandleVideoSettingsMouse(bool click)
{
	int mx = input.mousex / 5;
	int my = input.mousey / 5;

	int clickedIdx = -1;
	for (int i=0; i < NUM_SETTINGS_VIDEO_BUTTONS; i++)
		if (PointInRect(mx,my,VideoSettingsButtonCoords[i]))
			clickedIdx = i;

	VideoModeList& vm = game.config.availableModes;
	switch (clickedIdx)
	{
		case SETTINGS_VIDEO_BUTTON_APPLY:
			game.SetVideoMode(workingVideoResolutionIdx,
									workingVideoBitdepthIdx,
									workingVideoFreqIdx,
									workingVideoFullscreen);
			break;

		/*case SETTINGS_VIDEO_BUTTON_REJECT:
			ResetVideoSettingsMenu();
			break;
			*/
		case SETTINGS_VIDEO_BUTTON_RES:
			if (++workingVideoResolutionIdx >= vm.size())
				workingVideoResolutionIdx = 0;
			workingVideoBitdepthIdx=0;
			workingVideoFreqIdx=0;
			break;
		case SETTINGS_VIDEO_BUTTON_BPP:
			if (++workingVideoBitdepthIdx >= vm[workingVideoResolutionIdx].bitdepth.size())
				workingVideoBitdepthIdx = 0;
			workingVideoFreqIdx=0;
			break;
		case SETTINGS_VIDEO_BUTTON_FREQ:
			if (++workingVideoFreqIdx >= 
				vm[workingVideoResolutionIdx].
				bitdepth[workingVideoBitdepthIdx].
				freq.size())
				workingVideoFreqIdx = 0;
			break;
		case SETTINGS_VIDEO_BUTTON_FULLSCREEN:
			workingVideoFullscreen = !workingVideoFullscreen;
			break;
		default:
			break;
	}
}

void MenuInformation::HandlePlayerSettingsMouse(bool click)
{
	int mx = input.mousex / 5;
	int my = input.mousey / 5;

	int clickedIdx = -1;
	for (int i=0; i < NUM_SETTINGS_PLAYER_BUTTONS; i++)
		if (PointInRect(mx,my,PlayerSettingsButtonCoords[i]))
			clickedIdx = i;

	switch (clickedIdx)
	{
		case SETTINGS_PLAYER_BUTTON_MODEL_NEXT:
			if (++workingPlayerTankModel >= NUM_TANK_MODELS)
				workingPlayerTankModel = 0;
			//game.world.tank[0].SetTankModel(workingPlayerTankModel);
			menu_world.tank[0].SetTankModel(workingPlayerTankModel);
			break;
		case SETTINGS_PLAYER_BUTTON_MODEL_PREV:
			if (--workingPlayerTankModel < 0)
				workingPlayerTankModel = NUM_TANK_MODELS-1;
			//game.world.tank[0].SetTankModel(workingPlayerTankModel);
			menu_world.tank[0].SetTankModel(workingPlayerTankModel);
			break;

	}
}

void MenuInformation::ResetMenuWorld()
{
	menu_world.Reset();
	menu_world.tank[0].Spawn();
	menu_world.tank[0].model.pos = menu_world.map.GetStartingLocation(5);
	menu_world.tank[0].model.pos[Z] += 15;
	menu_world.tank[0].state = TS_NORMAL;
	menu_world.tank[0].model.vel = vec3f(0,0,0);
	menu_world.eyedyn.followerOffset = vec3f(500,500,100);
	menu_world.tank[0].stateStartTime = -10;
}
