/*
===========================================================================

Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 

This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  

Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/




#include "qe3.h"
#include "Radiant.h"
#include "GLWidget.h"
#include "../common/ToolGL.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



/////////////////////////////////////////////////////////////////////////////
// idGLWidget
class idMiniDrawVert {
public:
	idVec3 xyz;
	idVec2 st;
	idMiniDrawVert(float x, float y, float z, float s, float t) : xyz(x,y,z), st(s, t) {
	};
};

static idMiniDrawVert cubeData[] = {
	idMiniDrawVert(-1.0, -1.0, +1.0, 0.0, 0.0),
	idMiniDrawVert(+1.0, -1.0, +1.0, 1.0, 0.0),
	idMiniDrawVert(+1.0, +1.0, +1.0, 1.0, 1.0),
	idMiniDrawVert(-1.0, +1.0, +1.0, 0.0, 1.0),

	idMiniDrawVert(-1.0, -1.0, -1.0, 1.0, 0.0),
	idMiniDrawVert(-1.0, +1.0, +1.0, 1.0, 1.0),
	idMiniDrawVert(+1.0, +1.0, -1.0, 0.0, 1.0),
	idMiniDrawVert(+1.0, -1.0, -1.0, 0.0, 0.0),

	idMiniDrawVert(-1.0, +1.0, -1.0, 0.0, 1.0),
	idMiniDrawVert(-1.0, +1.0, +1.0, 0.0, 0.0),
	idMiniDrawVert(+1.0, +1.0, +1.0, 1.0, 0.0),
	idMiniDrawVert(+1.0, +1.0, -1.0, 1.0, 1.0),

	idMiniDrawVert(-1.0, -1.0, -1.0, 1.0, 1.0),
	idMiniDrawVert(+1.0, -1.0, -1.0, 0.0, 1.0),
	idMiniDrawVert(+1.0, -1.0, +1.0, 0.0, 0.0),
	idMiniDrawVert(-1.0, -1.0, +1.0, 1.0, 0.0),

	idMiniDrawVert(+1.0, -1.0, -1.0, 1.0, 0.0),
	idMiniDrawVert(+1.0, +1.0, -1.0, 1.0, 1.0),
	idMiniDrawVert(+1.0, +1.0, +1.0, 0.0, 1.0),
	idMiniDrawVert(+1.0, -1.0, +1.0, 0.0, 0.0),

	idMiniDrawVert(-1.0, -1.0, -1.0, 0.0, 0.0),
	idMiniDrawVert(-1.0, -1.0, +1.0, 1.0, 0.0),
	idMiniDrawVert(-1.0, +1.0, +1.0, 1.0, 1.0),
	idMiniDrawVert(-1.0, +1.0, -1.0, 0.0, 1.0)
};

static int cubeSides = sizeof(cubeData) / sizeof(idMiniDrawVert);
static int numQuads = cubeSides / 4;

void glTexturedBox(idVec3 &point, float size, const idMaterial *mat) {
	qglTranslatef(point.x, point.y, point.z);
	for (int i = 0; i < numQuads; i++) {
		qglBegin(GL_QUADS);
		for (int j = 0; j < 4; j++) {
			idVec3 v = cubeData[i * 4 + j].xyz;
			v *= size;
			qglTexCoord2fv(cubeData[i * 4 + j].st.ToFloatPtr());
			qglVertex3fv(v.ToFloatPtr());
		}
		qglEnd();
	}
}

idGLWidget::idGLWidget()
{
	initialized = false;
	drawable = NULL;
}

idGLWidget::~idGLWidget()
{
}


BEGIN_MESSAGE_MAP(idGLWidget, CWnd)
	//{{AFX_MSG_MAP(idGLWidget)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_TIMER()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// idGLWidget message handlers

BOOL idGLWidget::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CWnd::PreCreateWindow(cs);
}

BOOL idGLWidget::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	if (CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext) == -1) {
		return FALSE;
	}

	CDC *dc = GetDC();
	QEW_SetupPixelFormat(dc->m_hDC, false);
	ReleaseDC(dc);

	return TRUE;

}

void idGLWidget::OnPaint() 
{

	if (!initialized) {
		CDC *dc = GetDC();
		QEW_SetupPixelFormat(dc->m_hDC, false);
		ReleaseDC(dc);
		initialized = true;
	}
	CPaintDC dc(this); // device context for painting
	
	CRect rect;
	GetClientRect(rect);

	if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
	}

	const GLboolean multisampleWasEnabled = ToolGL_DisableMultisampleForEditor();
	qglViewport(0, 0, rect.Width(), rect.Height());
	qglScissor(0, 0, rect.Width(), rect.Height());
	qglMatrixMode(GL_PROJECTION);
	qglLoadIdentity();
	qglClearColor (0.4f, 0.4f, 0.4f, 0.7f);
	qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


	qglDisable(GL_DEPTH_TEST);
	qglDisable(GL_BLEND);
	qglOrtho(0, rect.Width(), 0, rect.Height(), -256, 256);

	if (drawable) {
		drawable->draw(1, 1, rect.Width()-1, rect.Height()-1);
	} else {
		qglViewport(0, 0, rect.Width(), rect.Height());
		qglScissor(0, 0, rect.Width(), rect.Height());
		qglMatrixMode(GL_PROJECTION);
		qglLoadIdentity();
		qglClearColor (0.4f, 0.4f, 0.4f, 0.7f);
		qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	qwglSwapBuffers(dc);
	qglFlush();
	ToolGL_RestoreMultisampleForEditor( multisampleWasEnabled );
	qwglMakeCurrent(win32.hDC, win32.hGLRC);

}

extern bool Sys_KeyDown(int key);

void idGLDrawable::buttonDown(int _button, float x, float y) {
	pressX = x;
	pressY = y;
	button = _button;
	if (button == MK_RBUTTON) {
		handleMove = true;
	}
}

void idGLDrawable::buttonUp(int button, float x, float y) {
	handleMove = false;
}

extern float	fDiff(float f1, float f2);
void idGLDrawable::mouseMove(float x, float y) {
	if (handleMove) {
		Update();
		if (Sys_KeyDown(VK_MENU)) {
			// scale
			float *px = &x;
			float *px2 = &pressX;

			if (fDiff(y, pressY) > fDiff(x, pressX)) {
				px = &y;
				px2 = &pressY;
			}

			if (*px > *px2) {
				// zoom in
				scale += 0.1f;
				if ( scale > 10.0f ) {
					scale = 10.0f;
				}
			} else if (*px < *px2) {
				// zoom out
				scale -= 0.1f;
				if ( scale <= 0.001f ) {
					scale = 0.001f;
				}
			}

			*px2 = *px;
			::SetCursorPos(pressX, pressY);

		} else if (Sys_KeyDown(VK_SHIFT)) {
			// rotate
		} else {
			// origin
			if (x != pressX) {
				xOffset += (x - pressX);
				pressX = x;
			}
			if (y != pressY) {
				yOffset -= (y - pressY);
				pressY = y;
			}
			//::SetCursorPos(pressX, pressY);
		}
	}
}

void idGLDrawable::draw(int x, int y, int w, int h) {
	GL_State( GLS_DEFAULT );
	qglViewport(x, y, w, h);
	qglScissor(x, y, w, h);
	qglMatrixMode(GL_PROJECTION);
	qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
	qglClear(GL_COLOR_BUFFER_BIT);
	qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	qglLineWidth(0.5);
	qglColor3f(1, 1, 1);
	globalImages->BindNull();
	qglBegin(GL_LINE_LOOP);
	qglColor3f(1, 0, 0);
	qglVertex2f(x + 3, y + 3);
	qglColor3f(0, 1, 0);
	qglVertex2f(x + 3, h - 3);
	qglColor3f(0, 0, 1);
	qglVertex2f(w - 3, h - 3);
	qglColor3f(1, 1, 1);
	qglVertex2f(w - 3, y + 3);
	qglEnd();

}

static int viewAngle = -98;
void idGLDrawableMaterial::buttonDown(int button, float x, float y) {
	idGLDrawable::buttonDown(button, x, y);
	//viewAngle += (button == MK_LBUTTON) ? 15 : -15;
}


void idGLDrawableMaterial::mouseMove(float x, float y) {
	if (handleMove) {
		Update();
		bool doScale = Sys_KeyDown(VK_MENU);
		bool doLight = Sys_KeyDown(VK_SHIFT);
		if (doScale || doLight) {
			// scale
			float *px = &x;
			float *px2 = &pressX;

			if (fDiff(y, pressY) > fDiff(x, pressX)) {
				px = &y;
				px2 = &pressY;
			}

			if (*px > *px2) {
				// zoom in
				if (doScale) {
					scale += 0.1f;
					if ( scale > 10.0f ) {
						scale = 10.0f;
					}
				} else {
					light += 0.05f;
					if ( light > 2.0f ) {
						light = 2.0f;
					}
				}
			} else if (*px < *px2) {
				// zoom out
				if (doScale) {
					scale -= 0.1f;
					if ( scale <= 0.001f ) {
						scale = 0.001f;
					}
				} else {
					light -= 0.05f;
					if ( light < 0.0f ) {
						light = 0.0f;
					}
				}
			}
			*px2 = *px;
			::SetCursorPos(pressX, pressY);
		} else {
			// origin
			if (x != pressX) {
				xOffset += (x - pressX);
				pressX = x;
			}
			if (y != pressY) {
				yOffset -= (y - pressY);
				pressY = y;
			}
			//::SetCursorPos(pressX, pressY);
		}
	}
}


void idGLDrawableMaterial::draw(int x, int y, int w, int h) {
	const idMaterial *mat = material;
	if (mat) {
		qglViewport(x, y, w, h);
		qglScissor(x, y, w, h);
		qglMatrixMode(GL_PROJECTION);
		qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
		qglClear(GL_COLOR_BUFFER_BIT);

		if (worldDirty) {
			InitWorld();
			renderLight_t	parms;
			idDict spawnArgs;
			spawnArgs.Set("classname", "light");
			spawnArgs.Set("name", "light_1");
			spawnArgs.Set("origin", "0 0 0");
			idStr str;
			sprintf(str, "%f %f %f", light, light, light);
			spawnArgs.Set("_color", str);
			gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
			lightDef = world->AddLightDef( &parms );

			idImage *img = (mat->GetNumStages() > 0) ? mat->GetStage(0)->texture.image : mat->GetEditorImage();

			if (img == NULL) {
				common->Warning("Unable to load image for preview for %s", mat->GetName());
				return;
			}

			int width = img->uploadWidth;
			int height = img->uploadHeight;

			width *= scale;
			height *= scale;

			srfTriangles_t *tris = worldModel->AllocSurfaceTriangles( 4, 6 );
			tris->numVerts = 4;
			tris->numIndexes = 6;

			tris->indexes[0] = 0;
			tris->indexes[1] = 1;
			tris->indexes[2] = 2;
			tris->indexes[3] = 3;
			tris->indexes[4] = 1;
			tris->indexes[5] = 0;

			tris->verts[0].xyz.x = 64;
			tris->verts[0].xyz.y = -xOffset + 0 - width / 2;
			tris->verts[0].xyz.z = yOffset + 0 - height / 2;
			tris->verts[0].st.x = 1;
			tris->verts[0].st.y = 1;
			
			tris->verts[1].xyz.x = 64;
			tris->verts[1].xyz.y = -xOffset + width / 2;
			tris->verts[1].xyz.z = yOffset + height / 2;
			tris->verts[1].st.x = 0;
			tris->verts[1].st.y = 0;

			tris->verts[2].xyz.x = 64;
			tris->verts[2].xyz.y = -xOffset + 0 - width / 2;
			tris->verts[2].xyz.z = yOffset + height / 2;
			tris->verts[2].st.x = 1;
			tris->verts[2].st.y = 0;

			tris->verts[3].xyz.x = 64;
			tris->verts[3].xyz.y = -xOffset + width / 2;
			tris->verts[3].xyz.z = yOffset + 0 - height / 2;
			tris->verts[3].st.x = 0;
			tris->verts[3].st.y = 1;

			tris->verts[0].normal = tris->verts[1].xyz.Cross(tris->verts[3].xyz);
			tris->verts[1].normal = tris->verts[2].normal = tris->verts[3].normal = tris->verts[0].normal;
			AddTris(tris, mat);

			worldModel->FinishSurfaces();
			
			renderEntity_t worldEntity;

			memset( &worldEntity, 0, sizeof( worldEntity ) );
			if ( mat->HasGui() ) {
				worldEntity.gui[ 0 ] = mat->GlobalGui();
			}
			worldEntity.hModel = worldModel;
			worldEntity.axis = mat3_default;
			worldEntity.shaderParms[0] = 1;
			worldEntity.shaderParms[1] = 1;
			worldEntity.shaderParms[2] = 1;
			worldEntity.shaderParms[3] = 1;
			modelDef = world->AddEntityDef( &worldEntity );

			worldDirty = false;
		}
		
		renderView_t	refdef;
		// render it
		renderSystem->BeginFrame(w, h);
		memset( &refdef, 0, sizeof( refdef ) );
		refdef.vieworg.Set(viewAngle, 0, 0);

		refdef.viewaxis = idAngles(0,0,0).ToMat3();
		refdef.shaderParms[0] = 1;
		refdef.shaderParms[1] = 1;
		refdef.shaderParms[2] = 1;
		refdef.shaderParms[3] = 1;

		refdef.width = SCREEN_WIDTH;
		refdef.height = SCREEN_HEIGHT;
		refdef.fov_x = 90;
		refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG;

		refdef.time = eventLoop->Milliseconds();

		world->RenderScene( &refdef );
		int frontEnd, backEnd;
		renderSystem->EndFrame( &frontEnd, &backEnd );

		qglMatrixMode( GL_MODELVIEW );
		qglLoadIdentity();
	}

}

void idGLDrawableMaterial::setMedia(const char *name) {
	idImage *img = NULL;
	if (name && *name) {
		material = declManager->FindMaterial(name);
		if (material) {
			const shaderStage_t *stage = (material->GetNumStages() > 0) ? material->GetStage(0) : NULL;
			if (stage) {
				img = stage->texture.image;
			} else {
				img = material->GetEditorImage();
			}
		}
	} else {
		material = NULL;
	}
	// set scale to get a good fit

	if (material && img) {

		float size = (img->uploadWidth > img->uploadHeight) ? img->uploadWidth : img->uploadHeight;
		// use 128 as base scale of 1.0
		scale = 128.0 / size;
	} else {
		scale = 1.0;
	}
	xOffset = 0.0;
	yOffset = 0.0;
	worldDirty = true;
}

idGLDrawableModel::idGLDrawableModel(const char *name) {
	worldModel = renderModelManager->FindModel( name );
	light = 1.0;
	worldDirty = true;
}

idGLDrawableModel::idGLDrawableModel() {
	worldModel = renderModelManager->DefaultModel();
	light = 1.0;
}

void idGLDrawableModel::setMedia(const char *name) {
	worldModel = renderModelManager->FindModel(name);
	worldDirty = true;
	xOffset = 0.0;
	yOffset = 0.0;
	zOffset = -128;
	rotation.Set( 0.0f, 0.0f, 0.0f, 1.0f );
	radius = 2.6f;
	lastPress.Zero();
}

void idGLDrawableModel::SetSkin( const char *skin ) {
	skinStr = skin;
}


void idGLDrawableModel::buttonDown(int _button, float x, float y) {
	pressX = x;
	pressY = y;

	lastPress.y = -( float )( 2 * x - rect.z ) / rect.z;
	lastPress.x = -( float )( 2 * y - rect.w ) / rect.w;
	lastPress.z = 0.0f;
	button = _button;
	if (button == MK_RBUTTON || button == MK_LBUTTON) {
		handleMove = true;
	}
}

void idGLDrawableModel::mouseMove(float x, float y) {
	if (handleMove) {
		Update();
		if (button == MK_LBUTTON) {
			float cury = ( float )( 2 * x - rect.z ) / rect.z;
			float curx = ( float )( 2 * y - rect.w ) / rect.w;
			idVec3 to( -curx, -cury, 0.0f );
			to.ProjectSelfOntoSphere( radius );
			lastPress.ProjectSelfOntoSphere( radius );
			idVec3 axis;
			axis.Cross( to, lastPress );
			float len = ( lastPress - to ).Length() / ( 2.0f * radius );
			len = idMath::ClampFloat( -1.0f, 1.0f, len );
			float phi = 2.0f * asin ( len ) ;

			axis.Normalize();
			axis *= sin( phi / 2.0f );
			idQuat rot( axis.z, axis.y, axis.x, cos( phi / 2.0f ) );
			rot.Normalize();

			rotation *= rot;
			rotation.Normalize();

			lastPress = to;
			lastPress.z = 0.0f;
		} else {
			bool doScale = Sys_KeyDown(VK_MENU);
			bool doLight = Sys_KeyDown(VK_SHIFT);
			if (doLight) {
				// scale
				float *px = &x;
				float *px2 = &pressX;

				if (fDiff(y, pressY) > fDiff(x, pressX)) {
					px = &y;
					px2 = &pressY;
				}

				if (*px > *px2) {
					light += 0.05f;
					if ( light > 2.0f ) {
						light = 2.0f;
					}
				} else if (*px < *px2) {
					light -= 0.05f;
					if ( light < 0.0f ) {
						light = 0.0f;
					}
				}
				*px2 = *px;
				::SetCursorPos(pressX, pressY);
			} else {
				// origin
				if (x != pressX) {
					if (doScale) {
						zOffset += (x - pressX);
					} else {
						xOffset += (x - pressX);
					}
					pressX = x;
				}
				if (y != pressY) {
					if (doScale) {
						zOffset -= (y - pressY);
					} else {
						yOffset -= (y - pressY);
					}
					pressY = y;
				}
				//::SetCursorPos(pressX, pressY);
			}
		}
	}
}


void idGLDrawableModel::draw(int x, int y, int w, int h) {
	if ( !worldModel ) {
		return;
	}
	if ( worldModel->IsDynamicModel() != DM_STATIC ) {
		//return;
	}

	rect.Set( x, y, w, h );

	qglViewport(x, y, w, h);
	qglScissor(x, y, w, h);
	qglMatrixMode(GL_PROJECTION);
	qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
	qglClear(GL_COLOR_BUFFER_BIT);

	if (worldDirty) {
		//InitWorld();
		world->InitFromMap( NULL );
		renderLight_t	parms;
		idDict spawnArgs;
		spawnArgs.Set("classname", "light");
		spawnArgs.Set("name", "light_1");
		spawnArgs.Set("origin", "-128 0 0");
		idStr str;
		sprintf(str, "%f %f %f", light, light, light);
		spawnArgs.Set("_color", str);
		gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms );
		lightDef = world->AddLightDef( &parms );

		renderEntity_t worldEntity;
		memset( &worldEntity, 0, sizeof( worldEntity ) );
		spawnArgs.Clear();
		spawnArgs.Set("classname", "func_static");
		spawnArgs.Set("name", spawnArgs.GetString("model"));
		spawnArgs.Set("origin", "0 0 0");
		if ( skinStr.Length() ) {
			spawnArgs.Set( "skin", skinStr );
		}
		gameEdit->ParseSpawnArgsToRenderEntity(&spawnArgs, &worldEntity);
		worldEntity.hModel = worldModel;

		worldEntity.axis = rotation.ToMat3();

		worldEntity.shaderParms[0] = 1;
		worldEntity.shaderParms[1] = 1;
		worldEntity.shaderParms[2] = 1;
		worldEntity.shaderParms[3] = 1;
		modelDef = world->AddEntityDef( &worldEntity );

		worldDirty = false;
	}
		
	renderView_t	refdef;
	// render it
	renderSystem->BeginFrame(w, h);
	memset( &refdef, 0, sizeof( refdef ) );
	refdef.vieworg.Set(zOffset, xOffset, -yOffset);

	refdef.viewaxis = idAngles(0,0,0).ToMat3();
	refdef.shaderParms[0] = 1;
	refdef.shaderParms[1] = 1;
	refdef.shaderParms[2] = 1;
	refdef.shaderParms[3] = 1;

	refdef.width = SCREEN_WIDTH;
	refdef.height = SCREEN_HEIGHT;
	refdef.fov_x = 90;
	refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG;

	refdef.time = eventLoop->Milliseconds();

	world->RenderScene( &refdef );
	int frontEnd, backEnd;
	renderSystem->EndFrame( &frontEnd, &backEnd );

	qglMatrixMode( GL_MODELVIEW );
	qglLoadIdentity();
}



void idGLWidget::OnLButtonDown(UINT nFlags, CPoint point) 
{
	SetCapture();
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonDown(MK_LBUTTON, point.x, point.y);
	}
}

void idGLWidget::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonUp(MK_LBUTTON, point.x, point.y);
	}
	ReleaseCapture();
}

void idGLWidget::OnMButtonDown(UINT nFlags, CPoint point) 
{
	SetCapture();
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonDown(MK_MBUTTON, point.x, point.y);
	}
}

void idGLWidget::OnMButtonUp(UINT nFlags, CPoint point) 
{
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonUp(MK_MBUTTON, point.x, point.y);
	}
	ReleaseCapture();
}

void idGLWidget::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->mouseMove(point.x, point.y);
		RedrawWindow();
	}
}

BOOL idGLWidget::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	if (drawable) {
		float f = drawable->getScale();
		if ( zDelta > 0.0f ) {
			f += 0.1f;
		} else {
			f -= 0.1f;
		}
		if ( f <= 0.0f ) {
			f = 0.1f;
		}
		if ( f > 5.0f ) {
			f = 5.0f;
		}
		drawable->setScale(f);
	}
	return TRUE;
}

void idGLWidget::OnRButtonDown(UINT nFlags, CPoint point) 
{
	SetCapture();
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonDown(MK_RBUTTON, point.x, point.y);
	}
}

void idGLWidget::OnRButtonUp(UINT nFlags, CPoint point) 
{
	if (drawable) {
		if ( drawable->ScreenCoords() ) {
			ClientToScreen(&point);
		}
		drawable->buttonUp(MK_RBUTTON, point.x, point.y);
	}
	ReleaseCapture();
}

void idGLWidget::setDrawable(idGLDrawable *d) {
	drawable = d;
	if (d->getRealTime()) {
		SetTimer(1, d->getRealTime(), NULL);
	}
}


void idGLWidget::OnTimer(UINT nIDEvent) {
	if (drawable && drawable->getRealTime()) {
		Invalidate(FALSE);
	} else {
		KillTimer(1);
	}
}


idGLDrawable::idGLDrawable() {
	scale = 1.0;   
	xOffset = 0.0;
	yOffset = 0.0;
	handleMove = false;
	realTime = 0;

}

void idGLDrawableConsole::draw(int x, int y, int w, int h) {
	qglPushAttrib( GL_ALL_ATTRIB_BITS );
	qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
	qglScissor( 0, 0, w, h );
	qglClear( GL_COLOR_BUFFER_BIT );
	renderSystem->BeginFrame( w, h );

	console->Draw( true );

	renderSystem->EndFrame( NULL, NULL );
	qglPopAttrib();
}

void idGLConsoleWidget::init() {
	setDrawable(&console);
}

void idGLConsoleWidget::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	sysEvent_t	ev;

	memset( &ev, 0, sizeof( ev ) );
	ev.evType = SE_KEY;
	ev.evValue2 = 1;
	ev.evValue = nChar;

	::console->ProcessEvent( &ev, true );
}

BEGIN_MESSAGE_MAP(idGLConsoleWidget, idGLWidget)
	//{{AFX_MSG_MAP(idGLConsoleWidget)
	ON_WM_PAINT()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_WM_CHAR()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



void idGLConsoleWidget::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	sysEvent_t	ev;

	memset( &ev, 0, sizeof( ev ) );
	ev.evType = SE_KEY;
	ev.evValue2 = 0;
	ev.evValue = nChar;

	::console->ProcessEvent( &ev, true );
}

void idGLConsoleWidget::OnPaint() {
	idGLWidget::OnPaint();
}

void idGLConsoleWidget::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	sysEvent_t	ev;

	memset( &ev, 0, sizeof( ev ) );
	ev.evType = SE_CHAR;
	ev.evValue = nChar;

	::console->ProcessEvent( &ev, true );
}

void idGLConsoleWidget::OnLButtonDown(UINT nFlags, CPoint point) {
	SetFocus();
}

BOOL idGLWidget::OnEraseBkgnd(CDC* pDC) 
{
	return FALSE;
	
	//return CWnd::OnEraseBkgnd(pDC);
}


idGLDrawableWorld::idGLDrawableWorld() {
	world = NULL;
	worldModel = NULL;
	InitWorld();
}

idGLDrawableWorld::~idGLDrawableWorld() {
	delete world;
}

void idGLDrawableWorld::AddTris(srfTriangles_t *tris, const idMaterial *mat) {
	modelSurface_t	surf;
	surf.geometry = tris;
	surf.shader = mat;
	worldModel->AddSurface( surf );
}

void idGLDrawableWorld::draw(int x, int y, int w, int h) {
	
}

void idGLDrawableWorld::InitWorld() {
	if ( world == NULL ) {
		world = renderSystem->AllocRenderWorld();
	}
	if ( worldModel == NULL ) {
		worldModel = renderModelManager->AllocModel();
	}
	world->InitFromMap( NULL );
	worldModel->InitEmpty( va( "GLWorldModel_%i", Sys_Milliseconds() ) );
}
