/**
 *
 * \file	world.cc
 *
 * \brief Implementation of the World class.
 *
 * \author	MAxx Headroom
 * \version	0.0
 * \date	13.01.2004 01:07:09
 *
 **/


#include "stdafx.h"
#include "world.h"


/**
 *
 * \brief Default constructor.
 *
 **/
//{{{ World::World()
World::World()
:	cam(0),
	lstFont(0),
	timer(WORLD_FPS_COUNT)
{
	DEBUGPRINT1("World::World()\n");
} /* World::World() */
//}}}


/**
 *
 * \brief Create a world and also create a font.
 *
 * \param hDC	Device Context.
 *
 **/
//{{{ World::World(HDC hDC)
World::World(HDC hDC)
:	cam(0),
	lstFont(0),
	timer(WORLD_FPS_COUNT)
{
	DEBUGPRINT1("World::World(HDC hDC)\n");

	HFONT	font;
	HFONT	oldfont;

	lstFont = glGenLists(96);

	font = CreateFont(	-24,				// Height Of Font
				0,							// Width Of Font
				0,							// Angle Of Escapement
				0,							// Orientation Angle
				FW_BOLD,					// Font Weight
				FALSE,						// Italic
				FALSE,						// Underline
				FALSE,						// Strikeout
				ANSI_CHARSET,				// Character Set Identifier
				OUT_TT_PRECIS,				// Output Precision
				CLIP_DEFAULT_PRECIS,		// Clipping Precision
				ANTIALIASED_QUALITY,		// Output Quality
				FF_DONTCARE|DEFAULT_PITCH,	// Family And Pitch
				"Courier New");				// Font Name

	oldfont = (HFONT)SelectObject(hDC, font);	// Selects The Font We Want
	wglUseFontBitmaps(hDC, 32, 96, lstFont);	// Builds 96 Characters Starting At Character 32
	SelectObject(hDC, oldfont);			// Selects The Font We Want
	DeleteObject(font);
} /* World::World(HDC hDC) */
//}}}


/**
 *
 * \brief Destructor.
 *
 **/
//{{{ World::~World()
World::~World()
{
	glDeleteLists(lstFont, 96);	// Delete All 96 Characters
	if (cam) delete cam;
} /* World::~World(); */
//}}}


/**
 *
 * \brief Prints text to the screen (i.e. the fps).
 *
 * \param fmt	The format of the output string.
 * \param ...	Variables referenced in the format string.
 *
 **/
//{{{ void World::Print(const char *fmt, ...)
void World::Print(const char *fmt, ...)
{
	char		text[256];			// Holds Our String
	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(text, fmt, ap);	// And Converts Symbols To Actual Numbers
	va_end(ap);						// Results Are Stored In Text

	glPushAttrib(GL_LIST_BIT);		// Pushes The Display List Bits
	glListBase(lstFont - 32);		// Sets The Base Character to 32
	glCallLists((GLsizei)strlen(text), GL_UNSIGNED_BYTE, text);
									// Draws The Display List Text
	glPopAttrib();					// Pops The Display List Bits
} /* void World::Print(const char *fmt, ...) */
//}}}


/**
 *
 * \brief Does the drawing of all objects in the world.
 *
 **/
//{{{ void World::draw()
void World::draw(bool updateFPS) throw(Exception)
{
	int diff = 0;
	//if (!cam) throw Exception("No camera defined!!!");

	// Update Objects:
	//cam->update(diff);
	for(oIterator i = objects.begin(); i != objects.end(); ++i)
		(*i)->update(diff);

	// Draw objects:
	for(oIterator i = objects.begin(); i != objects.end(); ++i)
		(*i)->draw();

	// Last of all, print the fps:
	// init
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_TEXTURE_2D);
	//glShadeModel(GL_FLAT);
	//glDisable(GL_LIGHTING);
	glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
	/*
	if (timer.getFPS() >= 100.0) {
		glRasterPos3f(1.15f, 0.7f, -2.0f);
	} else {
		glRasterPos3f(1.186f, 0.7f, -2.0f);
	}
	*/

	if (updateFPS) {
		if (timer.getFPS() >= 100.0) {
			glRasterPos3f(0.8225f, 0.95f, -1.0f);
		} else {
			glRasterPos3f(0.85f, 0.95f, -1.0f);
		}
		Print("%3.2f", timer.getFPS());
	}

	// reset
	//glDisable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	//glEnable(GL_LIGHTING);
	//glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_DEPTH_TEST);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	if (updateFPS) timer.update();
} /* void World::draw() */
//}}}


/**
 *
 * \brief Add the camera to the world.
 *
 * \param c	The camera.
 *
 **/
//{{{ void World::addCamera(Camera *c)
void World::addCamera(Camera *c)
{
	cam = c;
} /* void World::addCamera(Camera *c) */
//}}}


//{{{ void World::addObject(Object *o)
void World::addObject(Object *o)
{
	objects.push_back(o);
} /* void World::addObject(Object *o) */
//}}}


//// vim:fdm=marker
