//=====================================================================
// NemesisWINGSv2.
//      ""(§)FrÅgÊd(§)""
//               **Monarch**
//
//              555 ---===CrAzYBoNeS===--- 555
//			Boppolis_The_Dog
//
//
// Thank you Al McElrath for SLV2.
//=====================================================================
/** A gauge on the SLHUD.
*/
class HUDLevel extends SLInfo;


/** Linked list.
*/
var HUDLevel next;

var int x, y;
var int w, h;

var float alarm;
var float realLvl;
var float dispLvl;

var string label;
var string readout;
var string qualifier;
var Font lFont, sFont;

var float bubx, buby;

var() float bubbleRate;
var() float lvlRate;

/** Label info. These are adjusted based on screen size and font
	choice. Store all this garbage so we don't have to init every time.
*/
var int labely;
var Font labelFont;
var int roy;
var Font roFont;
var int qx, qy;

/** This is the "qualifier" font, used to write "m" for meters, "kg"
	for kilograms, etc.
*/
var Font qualFont;

var bool bBorder;					// Draw the border around the gauge?
var bool bNoFitLabels;


function init(float alarm, string label, string qualifier, Font lFont, Font sFont, optional HUDLevel nextlvl) {
	self.alarm = alarm;
	self.label = label;
	self.qualifier = qualifier;
	self.lFont = lFont;
	self.sFont = sFont;

	bubx = rand(w - 1);
	buby = rand(h);

	next = nextlvl;
}


function position(int x, int y, int w, int h) {
	self.w = w;
	self.h = h;
	self.x = x;
	self.y = y;

	// Reset label info.
	labely = -1;
}


function render(Stylus s) {
	local Canvas c;
	local float lvl;
	local int x, y, mx;
	local int i, slide, top;
	local float partial;
	local float xl, yl;
	local Color color, origColor;
	local float fade;

	c = s.c;

	// This buffers the display level.
	lvl = dispLvl;

	fade = SLHUD(owner).screenFade;

	// I fucked this all up and for some reason reversed the y axis.
	x = self.x;
	y = self.y + h - 1;

	/*
	if (lvl > 1.0) {
		// Used to have a secondary level.
		drawLevel(c, pos, lvl - 1.0, 0, col, scale, alarm);
		lvl = 1.0;
	}
	*/

	// Grab the current color from the parent (HUD) and store it.
	origColor = c.drawColor;
	color = c.drawColor;

	// Flash the level from red to bright green.
	if (alarmOn()) {
		color = alarmColor(color, SLHUD(owner).bAlarm);
	} else if (lvl > 1.0) {
		color = s.blendc(color, alarmColor(color, true), lvl - 0.5);
		lvl = 1.0;
	}

	if (lvl > 0.0) {
		// This top function rounds down all the time, so if we take the modulo of it
		// we can draw the fraction that's lopped off as a partially faded extra line at
		// the top. It gives it a smooth look.

		top = Min(h, lvl * h);

		c.drawColor = color * fade;

		// The top and bottom lines are offset by one pixel, so we have to
		// handle them separatelsy. This is the bottom line.
		if (top >= 1) {
			s.setPos(x + 1, y);
			s.pix(w, 1);
		}

		// Top line.
		if (top == h) {
			s.setPos(x + 1, y - (h - 1));
			s.pix(w, 1);
		}

		// The rest.
		if (top > 1) {
			// Line h is already done, if necessary, hence the min() func.
			s.setPos(x, y - (min(h - 1, top) - 1));
			s.pix(w, (min(h - 1, top) - 1));
		}

		if (level.bHighDetailMode) {
			// The "partial" line.
			partial = (lvl * h) % 1.0;
			if (partial > 0.0) {
				c.drawColor = color * partial * fade;
				mx = x;
				if (top == 0 || top == (h - 1)) {
					mx++;
				}
				s.setPos(mx, y - top);
				s.pix(w, 1);
			}
		}
	}

	// Draw bubbles.
	if (level.bHighDetailMode && buby < top) {
		//if (buby == top - 1) {
		if (buby == top) {
			// We're at the top - draw it faded to the partial line.
			c.drawColor = color * partial * fade;
		} else {
			c.drawColor = color * fade;
		}
		s.setPos(bubx + x, y - buby);
		s.pix(1, 2);
	}
	
	if (bBorder && level.bHighDetailMode) {
		// Draw a frame. Gets fainter as the level approaches 100%.
		c.drawColor = color * 0.25 * (1.0 - lvl) * fade;
		s.drawFrame(x, y - h + 1, w + 1, h);
	}

	c.drawColor = color * fade;
	drawLabels(s, x, y);

	// Restore the original color. The next gauge will pick the canvas
	// color up and use it, and if we've tainted it...
	c.drawColor = origColor;
}


/** Check the HUD and see if the alarm loop is "on". Alter the color if so.
*/
function Color alarmColor(Color c1, bool on) {
	local Color newc;

	newc = c1;

	if (!on) {
		newc.r /= 3;
		newc.g /= 3;
		newc.b /= 3;
	} else {
		newc.r *= 3;
		newc.r = min(255, newc.r);
		newc.g /= 3;
		newc.b /= 3;
	}

	return newc;
}


// Draw labels.
function drawLabels(Stylus s, int x, int y) {
	local Canvas c;
	local float xl, yl;

	c = s.c;

	if (label != "" && readout != "") {
		// Initialize for this canvas.
		if (labely == -1) {
			if (label != "") {
				c.font = lFont;
				c.textSize(label, xl, yl);
				if (xl >= w) {
					c.font = sFont;
					c.textSize(label, xl, yl);

					if (xl >= w && !bNoFitLabels) {
						// Chop it off and re-init.
						label = left(label, w / xl - 2);
						labely = -1;
						return;
					}
				}

				labely = y - yl + 1;
				labelFont = c.font;

				if (readout != "") {
					// Gah. Hardcoded.
					if (w < 32 && !bNoFitLabels) {
						c.font = sFont;
					} else {
						c.font = lFont;
					}
	
					c.textSize(readout, xl, yl);
					roy = labely - yl + 1;
					qx = x + 1 + xl;
					roFont = c.font;
	
					if (qualifier != "") {
						c.font = lFont;
						c.textSize(readout, xl, yl);
						if (xl + qx >= w) {
							c.font = sFont;
							c.textSize(readout, xl, yl);
						}
						qy = labely - yl;
						qualFont = c.font;
					}
				}
			}
		}

		s.setPos(x + 2, labely);
		c.font = labelFont;
		s.drawText(label);

		if (readout != "") {
			s.setPos(x + 1, roy);
			c.font = roFont;
			c.textSize(readout, xl, yl);
			s.drawText(readout);

			if (qualifier != "") {
				s.setPos(x + 1 + xl, qy);
				c.font = qualFont;
				s.drawText(qualifier);			
			}
		}
	}
}


function bool alarmOn() {
	return (realLvl < alarm);
}


/** Called from the HUD in tick().
*/
function update(float delta, float l, coerce string s) {
	realLvl = l;
	readout = s;

	if (level.bHighDetailMode) {
		// Bubbles!
		buby += bubbleRate * delta;
		if (buby >= h) {
			buby = 1; // 2 pixels tall.
			bubx = rand(w - 1);
		}
	}

	if (dispLvl == realLvl) {
		// Nothing.
	} else if (dispLvl < realLvl) {
		dispLvl = fmin(realLvl, dispLvl + lvlRate * delta);
	} else {
		dispLvl = fmax(realLvl, dispLvl - lvlRate * delta);
	}

	/*
	if (next != none)
		next.update(delta);
	*/
}


function destroyed() {
	if (next != none)
		next.destroy();
}



// end

defaultproperties
{
     bubbleRate=50.000000
     lvlRate=3.000000
}
