////////////////////////////////////////////////////////////////////////////////
// MechSimOverlay.cpp
// HUD Overlay for simulation window in MechVM
// Copyright Bjoern Ganster
// Developed since 2020
////////////////////////////////////////////////////////////////////////////////

#include "Font.h"
#include "MechSimOverlay.h"
#include "MechSim.h"

#include <algorithm>

#define FILE_NUMBER FILE_NO_MECHSIM_OVERLAY_CPP

// Constructor for HUD
MechSimOverlay::MechSimOverlay(int width, int height)
: mDeleteTexture(true),
  mFont(nullptr)
{
	SET_SCOPE;
	mOverlayTexture = new Texture (width, height, GL_RGBA);
	mOverlayTexture->fillRectI(0, 0, width, height, 0, 0, 0, 0);
	RETURN;
}

// Constructor for instruments
MechSimOverlay::MechSimOverlay(Texture* texture)
: mOverlayTexture(texture), 
  mDeleteTexture(false),
  mFont(nullptr)
{
}

// Destructor
MechSimOverlay::~MechSimOverlay()
{
	if (mDeleteTexture) {
		safeDelete(mOverlayTexture);
	}
}

// Show speed meter (vertically, only used by external hud or no instrument panel)
void MechSimOverlay::setSpeed(double metersPerSecond, double percent, double u1, double v1, double u2, double v2)
{
	SET_SCOPE;
	if (mFont == nullptr) {
		RETURN;
	}

	double kph = 3.6 * metersPerSecond;
	int barU1 = (int)(mOverlayTexture->getWidth()  * u1);
	int barU2 = (int)(mOverlayTexture->getWidth()  * u2);
	int barV1 = (int)(mOverlayTexture->getHeight() * v1);
	int barV2 = (int)(mOverlayTexture->getHeight() * v2);
	int iu1 = barU1-2;
	int iu2 = barU2+2;
	int iv1 = barV1+2;
	int iv2 = barV2-2;

	mOverlayTexture->renderLine(iu1, iv1, iu2, iv1, 255, 0, 0);
	mOverlayTexture->renderLine(iu1, iv2, iu2, iv2, 255, 0, 0);
	mOverlayTexture->renderLine(iu1, iv1, iu1, iv2, 255, 0, 0);
	mOverlayTexture->renderLine(iu2, iv1, iu2, iv2, 255, 0, 0);

	if (percent > 0) {
		barV2 = (int) (barV1 - (barV1-barV2) * percent / 100.0);
		mOverlayTexture->fillRectI(barU1, barV1, barU2, barV2, 0, 255, 0, 255);
	} else {
		barV2 = (int) (barV1 + (barV1-barV2) * percent / 100.0);
		mOverlayTexture->fillRectI(barU1, barV1, barU2, barV2, 255, 0, 0, 255);
	}

	BGCPString msg = BGCPString::fromDouble(metersPerSecond) + " m/s, " + BGCPString::fromDouble(kph) + BGCPString(" kph");
	mFont->renderText(mOverlayTexture, msg, iu1-200, iv1-20, iu1, iv1-40, 255, 0, 0);
	BGCPString msg2 = BGCPString::fromDouble(kph) + BGCPString(" kph");
	mFont->renderText(mOverlayTexture, msg2, iu1-200, iv1-40, iu1, iv1-60, 255, 0, 0);
	RETURN;
}

void MechSimOverlay::setHeading(double val)
{
	SET_SCOPE;
	BGCPString msg = BGCPString("Heading: ") + BGCPString::fromDouble(val);
	mFont->renderText(mOverlayTexture, msg, 0, 60, 200, 40, 0, 0, 0);
	RETURN;
}

// Show text (one line only)
void MechSimOverlay::showText(const BGCPString& text, double u1, double v1, uint8_t r, uint8_t g, uint8_t b)
{
	SET_SCOPE;
	if (mFont == nullptr) {
		RETURN;
	}

	auto msg2len = text.getByteCount();
	int tw = mFont->textWidth(text);
	int iu1 = (int)(mOverlayTexture->getWidth()  * u1);
	int iv1 = (int)(mOverlayTexture->getHeight() * v1);
	mFont->renderText(mOverlayTexture, text, iu1, iv1, iu1+tw, iv1+mFont->getCharHeight(), r, g, b);
	RETURN;
}

// Show text (multiple lines allowed)
void MechSimOverlay::showText(const BGCPString& text, double u1, double v1, double u2, double v2, uint8_t r, uint8_t g, uint8_t b)
{
	if (mFont == nullptr) {
		return;
	}

	auto msg2len = text.getByteCount();
	int tw = mFont->textWidth(text);
	int iu1 = (int)(mOverlayTexture->getWidth()  * u1);
	int iv1 = (int)(mOverlayTexture->getHeight() * v1);
	int iu2 = (int)(mOverlayTexture->getWidth()  * u2);
	int iv2 = (int)(mOverlayTexture->getHeight() * v2);
	mFont->renderText(mOverlayTexture, text, iu1, iv1, iu2, iv2, r, g, b);
}

// Display horizontal bar
void MechSimOverlay::showHBar(double val, const DisplayComponentCoords& displayCoords, uint8_t r, uint8_t g, uint8_t b, const BGCPString& text)
{
	SET_SCOPE;
	if (mFont == nullptr) {
		RETURN;
	}

	int x1 = (int)(displayCoords.u1 * mOverlayTexture->getWidth());
	int y1 = (int)(displayCoords.v1 * mOverlayTexture->getHeight());
	int x3 = (int)(displayCoords.u2 * mOverlayTexture->getWidth());
	int x2 = std::min<int>((int)((displayCoords.u1 + val * (displayCoords.u2-displayCoords.u1)) * mOverlayTexture->getWidth()), x3);
	int y2 = (int)(displayCoords.v2 * mOverlayTexture->getHeight());
	mOverlayTexture->fillRectI(x1, y1, x3, y2, 0, 0, 0);
	if (x2 > x1) {
		mOverlayTexture->fillRectI(x1, y1, x2, y2, r, g, b);
	}

	x2 = (int)(displayCoords.u2 * mOverlayTexture->getWidth());
	int x = (int)(0.5 * (x1 + x2) -0.5 * mFont->textWidth(text));
	int y = (int)(0.5 * (y1 + y2) -0.5 * mFont->getCharHeight());
	mFont->renderText(mOverlayTexture, text, x, y, x+200, y-200, 255-r, 255-g, 255-b);
	RETURN;
}

// Display vertical bar
void MechSimOverlay::showVBar(double percent, double u1, double v1, double u2, double v2, uint8_t r, uint8_t g, uint8_t b)
{
	SET_SCOPE;
	if (mFont == nullptr) {
		RETURN;
	}

	int barU1 = (int)(mOverlayTexture->getWidth()  * u1);
	int barU2 = (int)(mOverlayTexture->getWidth()  * u2);
	int barV1 = (int)(mOverlayTexture->getHeight() * v1);
	int barV2 = (int)(mOverlayTexture->getHeight() * v2);

	int iu1 = barU1-2;
	int iu2 = barU2+2;
	int iv1 = barV1-2;
	int iv2 = barV2+2;
	mOverlayTexture->renderLine(iu1, iv1, iu2, iv1, r, g, b);
	mOverlayTexture->renderLine(iu1, iv2, iu2, iv2, r, g, b);
	mOverlayTexture->renderLine(iu1, iv1, iu1, iv2, r, g, b);
	mOverlayTexture->renderLine(iu2, iv1, iu2, iv2, r, g, b);

	barV2 = (int) (barV1 - (barV1-barV2) * percent / 100.0);
	mOverlayTexture->fillRectI(barU1, barV1, barU2, barV2, r, g, b, 255);

	RETURN;
}

void MechSimOverlay::showWeapons(const AbstractVehicleAI* ai, int x, int y, DWORD missionTime)
{
	SET_SCOPE;
	if (mFont == nullptr) {
		RETURN;
	}
	double now = missionTime / 1000.0;
	const Vehicle* vehicle = ai->getVehicle();
	int lineH = mFont->getCharHeight()+2;

	if (vehicle != nullptr) {
		size_t weaponsCount = vehicle->getWeaponListEntryCount();
		for (size_t i = 0; i < weaponsCount; ++i) {
			if (i == 0 || (i % 6) != 0) {
				y -= lineH;
			} else {
				y += 5*lineH;
				x += 130;
			}
			const MountedWeapon* mountedWeapon = vehicle->getMountedWeapon(i);
			if (mountedWeapon != nullptr) {
				BGCPString weaponName = vehicle->getWeaponListEntryName(i);
				const MWEquipment* baseWeapon = vehicle->getBaseWeapon(i);

				if (baseWeapon != nullptr) {
					if (baseWeapon->ammoUsedPerShot > 0) {
						WeaponType weaponType = vehicle->getBaseWeaponType(i);
						auto remainingAmmo = vehicle->ammoAvailable(weaponType);
						weaponName += BGCPString(" ") + BGCPString::fromInt(remainingAmmo);
					}

					double lastFired = vehicle->getLastFireTime(i) / 1000.0;
					if (lastFired > 0.0) {
						if (lastFired + baseWeapon->fireDuration > now) {
							// Still firing: show bar filling
							double value = (now - lastFired) / baseWeapon->fireDuration;
							int x2 = (int) (x + 100*value)+10;
							mOverlayTexture->fillRectI(x+10, y+2, x2, y+lineH, 0, 128, 128);
						} else if (lastFired + baseWeapon->fireDuration + baseWeapon->coolDown > now) {
							// Show cooldown bar
							double value = 1.0 - (now - lastFired - baseWeapon->fireDuration) / baseWeapon->coolDown;
							int x2 = (int) (x + 100*value)+10;
							mOverlayTexture->fillRectI(x+10, y+2, x2, y+lineH, 128, 0, 0);
						}
					}
				}

				unsigned int r = 0;
				unsigned int g = 0;
				unsigned int b = 0;
				if (!mountedWeapon->destroyed) {
					switch(vehicle->getGroup(i)) {
						case 0: // Group 1: green
							g = 255;
							break;
						case 1: // Group 2: white
							r = 255;
							g = 255;
							b = 255;
							break;
						case 2: // Group 3: yellow
							r = 255;
							g = 255;
							break;
						case 3: // Group 4: red
							r = 255;
							break;
						default: // Group 5: blue
							b = 255;
							break;
					}
				}

				mFont->renderText(mOverlayTexture, weaponName, x+10, y, x+200, y-200, r, g, b);

				if (ai->weaponActive(i, ai->groupFire)) {
					mOverlayTexture->fillTriangle(x, y+2, x+9, y + lineH / 2, x, y + lineH-2, 0xff, 0, 0);
				}
			}
		}
	}
	RETURN;
}

void MechSimOverlay::showArmor(const Vehicle* vehicle, double u1, double v1, double u2, double v2)
{
	if (mFont == nullptr
	||  mOverlayTexture == nullptr) 
	{
		return;
	}

	SET_SCOPE;
	auto tw = mOverlayTexture->getWidth();
	auto th = mOverlayTexture->getHeight();
	int x1 = (int)(tw * u1);
	int x2 = (int)(tw * u2);
	int y1 = (int)(th * v1);
	int y2 = (int)(y1 + mFont->getCharHeight());
	int y3 = (int)(th * v2);
	mOverlayTexture->fillRectI(x1, y1, x2, y3, 0, 0, 0);
	auto sectionCount = vehicle->getSectionCount();

	for (int i = 0; i < sectionCount; ++i) {
		SET_OP;
		BGCPString columnName;
		const char* columnNames = vehicle->mArmorDiagramSubtitle;
		columnName.add(&columnNames[i]);
		x1 = (int)(tw * (u1 + i * (u2-u1) / sectionCount));
		x2 = (int)(tw * (u1 + (i + 1) * (u2-u1) / sectionCount)-2);
		int x = (x1+x2)/2 - 4;
		mFont->renderText(mOverlayTexture,columnName, x, y1-1, x+20, y1-mFont->getCharHeight(), 255, 255, 255);

		// Armor
		if (vehicle->separateFrontAndRearArmor(i)) {
			// Front armor
			SET_OP;
			double sectionDamage = vehicle->getArmorDamage(i, Vehicle::Armor_Front);
			int sectionArmorFront = vehicle->getArmor(i, Vehicle::Armor_Front);
			int sectionArmorRear  = vehicle->getArmor(i, Vehicle::Armor_Rear);
			int xm = (x1+x2) / 2;
			if (sectionDamage < sectionArmorFront) {
				int y1a = (int)(y2 + 0.68 * (y3 - y2));
				int y2a = (int)(y1a + (y3 - y2) * 0.32 * (sectionArmorFront-sectionDamage) / std::max(sectionArmorFront, sectionArmorRear));
				mOverlayTexture->fillRectI(x1, y1a, xm-1, y2a, 0, 255, 0);
			}

			// Rear armor
			sectionDamage = vehicle->getArmorDamage(i, Vehicle::Armor_Rear);
			if (sectionDamage < sectionArmorRear) {
				int y1a = (int)(y2 + 0.68 * (y3 - y2));
				int y2a = (int)(y1a + (y3 - y2) * 0.32 * (sectionArmorRear-sectionDamage) / std::max(sectionArmorFront, sectionArmorRear));
				mOverlayTexture->fillRectI(xm+1, y1a, x2, y2a, 0, 255, 0);
			}
		} else {
			SET_OP;
			double sectionDamage = vehicle->getArmorDamage(i, Vehicle::Armor_Front);
			int sectionArmor = vehicle->getArmor(i, Vehicle::Armor_Front) + vehicle->getArmor(i, Vehicle::Armor_Rear);
			if (sectionDamage < sectionArmor) {
				int y1a = (int)(y2 + 0.68 * (y3 - y2));
				int y2a = (int)(y1a + (y3 - y2) * 0.32 * (sectionArmor-sectionDamage) / sectionArmor);
				mOverlayTexture->fillRectI(x1, y1a, x2, y2a, 0, 255, 0);
			}
		}

		// Internal structure
		{
			SET_OP;
			double sectionDamage = vehicle->getInternalDamage(i);
			auto internalStructure = vehicle->getInternalStructure(i);
			if (sectionDamage < internalStructure) {
				int y1i = (int)(y2 + 0.34 * (y3 - y2));
				int y2i = (int)(y1i + (y3 - y2) * 0.32 * (internalStructure - sectionDamage) / internalStructure);
				mOverlayTexture->fillRectI(x1, y1i, x2, y2i, 255, 255, 0);
			}
		}

		// Criticals
		{
			SET_OP;
			int y1c = y2;
			int y2c = y1c + (int)(0.32 * (y3 - y2));
			int criticals = vehicle->getCriticalCount(i);
			//mOverlayTexture->fillRect(x1, y1c, x2, y2c, 255, 0, 0);

			// Draw a stripe for each critical present
			for (int j = 0; j < criticals; ++j) {
				int y1cs = y1c + (int)((y2c - y1c) * j / criticals); // at most 12 sections with 11 spaces between them
				int y2cs = y1c + (int)((y2c - y1c) * (j + 1.0) / criticals); // at most 12 sections with 11 spaces between them
				if (!vehicle->criticalDamaged(i, j)) {
					mOverlayTexture->fillRectI(x1, y1cs, x2, y2cs, 255, 0, 0);
				} /*else {
					mOverlayTexture->fillRect(x1, y1cs, x2, y2cs, 0, 0, 255);
				}*/
			}
		}
	}

	RETURN;
}

void MechSimOverlay::showArtificialHorizon(const DisplayComponentCoords& displayCoords, Vehicle* vehicle, 
	RenderToTexture& textureBuffer, Texture* targetTexture)
{
	if (displayCoords.u1 >= displayCoords.u2 
	||  displayCoords.v1 >= displayCoords.v2
	||  vehicle == nullptr
	||  targetTexture == nullptr
	||  mFont == nullptr)
	{
		return;
	}

	// Render map to texture
	SET_SCOPE;
	auto tw = targetTexture->getWidth();
	auto th = targetTexture->getHeight();

	TextureDim x1 = (TextureDim)(tw * displayCoords.u1);
	TextureDim y1 = (TextureDim)(th * displayCoords.v1);
	TextureDim x2 = (TextureDim)(tw * displayCoords.u2);
	TextureDim y2 = (TextureDim)(th * displayCoords.v2);
	TextureDim stopx = x2-x1;
	TextureDim stopy = y2-y1;
	textureBuffer.prepare(stopx, stopy, true);

	SET_OP;
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, stopx, stopy);

	// Set viewing projection
	SET_OP;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Render ground as a polygon
	glColor3d(0.25, 0.1, 0.1);
	glDepthMask(GL_FALSE);
	glBegin(GL_POLYGON);
		glVertex2d(-1.0, 0.0);
		glVertex2d(1.0, 0.0);
		glVertex2d(1.0, -1.0);
		glVertex2d(-1.0, -1.0);
	glEnd();
	glDepthMask(GL_TRUE);

	gluPerspective(60.0, ((double)stopx) / ((double)stopy), 0.1, 5000.0);

	Point3D minPos, maxPos;
	vehicle->getMinCoords(minPos);
	vehicle->getMaxCoords(maxPos);
	double targetSize = (minPos - maxPos).length();
	Point3D targetMid = 0.5 * (minPos + maxPos);
	Point3D eye = targetMid - Point3D(0.0, 0.0, 1.0 * targetSize);
	gluLookAt(eye.x, eye.y, eye.z,
		targetMid.x, targetMid.y, targetMid.z,
		0, 1, 0);
	//glTranslated(-targetMid.x, -targetMid.y, -targetMid.z);
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();
	glColor3d(1, 1, 1);
	vehicle->render();

	SET_OP;
	textureBuffer.stopRenderingToTexture(false);

	//targetTexture->fillRectI(x1, y1, x2, y2, 255, 128, 128);
	targetTexture->copy(&textureBuffer, 0, 0, stopx, stopy, x1, y1);
	RETURN;
}

void MechSimOverlay::showInterceptCourse(const DisplayComponentCoords& displayCoords, 
	RenderToTexture& textureBuffer, Texture* targetTexture, Mesh* arrow)
{
	if (displayCoords.u1 >= displayCoords.u2 
	||  displayCoords.v1 >= displayCoords.v2
	||  targetTexture == nullptr
	||  arrow == nullptr
	||  mFont == nullptr)
	{
		return;
	}

	// Render map to texture
	SET_SCOPE;
	auto tw = targetTexture->getWidth();
	auto th = targetTexture->getHeight();

	TextureDim x1 = (TextureDim)(tw * displayCoords.u1);
	TextureDim y1 = (TextureDim)(th * displayCoords.v1);
	TextureDim x2 = (TextureDim)(tw * displayCoords.u2);
	TextureDim y2 = (TextureDim)(th * displayCoords.v2);
	TextureDim stopx = x2-x1;
	TextureDim stopy = y2-y1;
	textureBuffer.prepare(stopx, stopy, true);

	SET_OP;
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, stopx, stopy);

	// Set viewing projection
	SET_OP;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, ((double)stopx) / ((double)stopy), 0.1, 5000.0);

	Point3D minPos, maxPos;
	arrow->cacheTransformedVertices(Matrix());
	arrow->getMinCoords(minPos);
	arrow->getMaxCoords(maxPos);
	double targetSize = (minPos - maxPos).length();
	Point3D targetMid = 0.5 * (minPos + maxPos);
	Point3D eye = targetMid - Point3D(0.0, 0.0, 1.0 * targetSize);
	gluLookAt(eye.x, eye.y, eye.z,
		targetMid.x, targetMid.y, targetMid.z,
		0, 1, 0);
	//glTranslated(-targetMid.x, -targetMid.y, -targetMid.z);
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();
	glColor3d(1, 1, 1);
	arrow->render();

	SET_OP;
	textureBuffer.stopRenderingToTexture(false);

	//targetTexture->fillRectI(x1, y1, x2, y2, 255, 128, 128);
	targetTexture->copy(&textureBuffer, 0, 0, stopx, stopy, x1, y1);
	RETURN;
}

// Render overlay
void MechSimOverlay::render()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	mOverlayTexture->use();
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glColor3d(1.0, 1.0, 1.0);

	glBegin(GL_QUADS);
		mOverlayTexture->glTexCoord(0.0, 0.0);
		glVertex2f(-1.0, -1.0);
		mOverlayTexture->glTexCoord(1.0, 0.0);
		glVertex2f(1.0, -1.0);
		mOverlayTexture->glTexCoord(1.0, 1.0);
		glVertex2f(1.0, 1.0);
		mOverlayTexture->glTexCoord(0.0, 1.0);
		glVertex2f(-1.0, 1.0);
	glEnd();

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
}

// Show communications summary
void MechSimOverlay::showComms(double u1, double v1, double u2, double v2)
{
	if (mFont == nullptr) {
		return;
	}

	SET_SCOPE;
	MechSim* mechSim = getMechSim();
	Vehicle* playerVehicle = mechSim->findVehicleByID("Player1");
	Vehicle* starmate1 = mechSim->findVehicleByID("Starmate1");
	Vehicle* starmate2 = mechSim->findVehicleByID("Starmate2");

	BGCPString starmateOrLancemateStr = "starmate";
	if (playerVehicle != nullptr) {
		auto techType = playerVehicle->getInteger(Vehicle::Info_TechType);
		if (techType != Tech_Type_Clan) {
		starmateOrLancemateStr = "lancemate";
		}
	}

	BGCPString msg = BGCPString("No ") + starmateOrLancemateStr + BGCPString("s");
	if (starmate1 != nullptr) {
		if (starmate2 != nullptr) {
			msg = BGCPString("1 - Contact ") + starmateOrLancemateStr + BGCPString(" 1\n") + 
			      BGCPString("2 - Contact ") + starmateOrLancemateStr + BGCPString(" 2\n") +
			      BGCPString("3 - Contact all ") + starmateOrLancemateStr + BGCPString("s\n");
		} else {
			msg = BGCPString("1 - Contact ") + starmateOrLancemateStr + BGCPString(" 1\n");
		}
	} else if (starmate2 != nullptr) {
		msg = BGCPString("2 - Contact ") + starmateOrLancemateStr + BGCPString(" 2\n");
	}

	mOverlayTexture->fillRectI(u1, v2, u2, v1, 0, 0, 0);
	mFont->renderText(mOverlayTexture, msg, u1+1, v2-mFont->getCharHeight()-1, u2, v1-1, 0, 255, 0);
	RETURN;
}

// Show communications with specific Mech
void MechSimOverlay::showComms2(double u1, double v1, double u2, double v2, MfdMode mfdMode)
{
	if (mFont == nullptr) {
		return;
	}

	SET_SCOPE;
	MechSim* mechSim = getMechSim();
	Vehicle* playerVehicle = mechSim->findVehicleByID("Player1");

	BGCPString starmateOrLancemateStr = "starmate";
	if (playerVehicle != nullptr) {
		auto techType = playerVehicle->getInteger(Vehicle::Info_TechType);
		if (techType != Tech_Type_Clan) {
			starmateOrLancemateStr = "lancemate";
		}
	}

	BGCPString msg;
	switch(mfdMode) {
		case MFD_CommAll:
			msg = BGCPString("Contact all ") + starmateOrLancemateStr + BGCPString("s\n");
			break;
		case MFD_Comm1:
			msg = BGCPString("Contact ") + starmateOrLancemateStr + BGCPString(" 1\n");
			break;
		case MFD_Comm2:
			msg = BGCPString("Contact ") + starmateOrLancemateStr + BGCPString(" 2\n");
			break;
	}

	msg += "1 - Attack my target\n2 - Join Formation\n3 - Shut down";

	mOverlayTexture->fillRectI(u1, v1, u2, v2, 0, 0, 0);
	mFont->renderText(mOverlayTexture, msg, u1+1, v2-mFont->getCharHeight()-1, u2, v1, 0, 255, 0);
	RETURN;
}

Texture* MechSimOverlay::getOverlayTexture()
{
	return mOverlayTexture;
}
