//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#include <mxtk/mx.h>
#include <mxtk/mxMessageBox.h>
#include <mxtk/mxTga.h>
#include <mxtk/mxPcx.h>
#include <mxtk/mxBmp.h>
#include <mxtk/mxMatSysWindow.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "MatSysWin.h"
#include "MDLViewer.h"
#include "StudioModel.h"
#include "ControlPanel.h"
#include "ViewerSettings.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterialproxyfactory.h"
#include "filesystem.h"
#include <keyvalues.h>
#include "materialsystem/imesh.h"
#include "expressions.h"
#include "hlfaceposer.h"
#include "ifaceposersound.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/itexture.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "istudiorender.h"
#include "choreowidgetdrawhelper.h"
#include "faceposer_models.h"
#include "tier0/icommandline.h"
#include "mathlib/vmatrix.h"
#include "vstdlib/cvar.h"

IFileSystem *filesystem = NULL;

extern char g_appTitle[];

// FIXME: move all this to mxMatSysWin

class DummyMaterialProxyFactory : public IMaterialProxyFactory
{
public:
	virtual IMaterialProxy *CreateProxy( const char *proxyName )	{return NULL;}
	virtual void DeleteProxy( IMaterialProxy *pProxy )				{}
};
DummyMaterialProxyFactory	g_DummyMaterialProxyFactory;


static void ReleaseMaterialSystemObjects()
{
	StudioModel::ReleaseStudioModel();
	models->ReleaseModels();
}

static void RestoreMaterialSystemObjects( int nChangeFlags )
{
	StudioModel::RestoreStudioModel();
	models->RestoreModels();
}

void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig)
{
	pConfig->SetFlag( MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS, true );
}

Vector g_vright( 50, 50, 0 );		// needs to be set to viewer's right in order for chrome to work

IMaterial *g_materialBackground = NULL;
IMaterial *g_materialWireframe = NULL;
IMaterial *g_materialWireframeVertexColor = NULL;
IMaterial *g_materialWireframeVertexColorNoCull = NULL;
IMaterial *g_materialDebugCopyBaseTexture = NULL;
IMaterial *g_materialFlatshaded = NULL;
IMaterial *g_materialSmoothshaded = NULL;
IMaterial *g_materialBones = NULL;
IMaterial *g_materialLines = NULL;
IMaterial *g_materialFloor = NULL;
IMaterial *g_materialVertexColor = NULL;
IMaterial *g_materialShadow = NULL;

MatSysWindow		*g_pMatSysWindow = 0;

#define MATSYSWIN_NAME "3D View"

MatSysWindow::MatSysWindow (mxWindow *parent, int x, int y, int w, int h, const char *label, int style)
: IFacePoserToolWindow( "3D View", "3D View" ), mxMatSysWindow ( parent, x, y, w, h, label, style )
{
	g_pMaterialSystem->SetMaterialProxyFactory( &g_DummyMaterialProxyFactory );

	SetAutoProcess( true );

	setLabel( MATSYSWIN_NAME );

	m_bSuppressSwap = false;

	m_hWnd = (HWND)getHandle();

	Con_Printf( "Setting material system video mode\n" );

	MaterialSystem_Config_t config;
	config = g_pMaterialSystem->GetCurrentConfigForVideoCard();
	InitMaterialSystemConfig(&config);
	g_pMaterialSystem->OverrideConfig( config, false );
	
//	config.m_VideoMode.m_Width = config.m_VideoMode.m_Height = 0;
	config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
	config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, true );

	if (!g_pMaterialSystem->SetMode( ( void * )m_hWnd, config ) )
	{
		return;
	}
	g_pMaterialSystem->AddReleaseFunc( ReleaseMaterialSystemObjects );
	g_pMaterialSystem->AddRestoreFunc( RestoreMaterialSystemObjects );

	Con_Printf( "Loading debug materials\n" );

	ITexture *pCubemapTexture = g_pMaterialSystem->FindTexture( "hlmv/cubemap", NULL, true );
	pCubemapTexture->IncrementReferenceCount();
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	pRenderContext->BindLocalCubemap( pCubemapTexture );

	g_materialBackground	= g_pMaterialSystem->FindMaterial("particle/particleapp_background", TEXTURE_GROUP_OTHER, true);
	g_materialWireframe		= g_pMaterialSystem->FindMaterial("debug/debugmrmwireframe", TEXTURE_GROUP_OTHER, true);
	g_materialWireframeVertexColor = g_pMaterialSystem->FindMaterial("debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER, true);

	// test: create this from code - you need a vmt to make $nocull 1 happen, can't do it from the render context
	{
		KeyValues *pVMTKeyValues = new KeyValues( "Wireframe" );
		pVMTKeyValues->SetInt("$ignorez", 1);
		pVMTKeyValues->SetInt("$nocull", 1);
		pVMTKeyValues->SetInt("$vertexcolor", 1);
		pVMTKeyValues->SetInt("$decal", 1);
		g_materialWireframeVertexColorNoCull = g_pMaterialSystem->CreateMaterial( "debug/wireframenocull", pVMTKeyValues );
	}
	{
		KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
		pVMTKeyValues->SetString("$basetexture", "vgui/white" );
		g_materialDebugCopyBaseTexture = g_pMaterialSystem->CreateMaterial( "debug/copybasetexture", pVMTKeyValues );

	}

	g_materialFlatshaded	= g_pMaterialSystem->FindMaterial("debug/debugdrawflatpolygons", TEXTURE_GROUP_OTHER, true);
	g_materialSmoothshaded	= g_pMaterialSystem->FindMaterial("debug/debugmrmfullbright2", TEXTURE_GROUP_OTHER, true);
	g_materialBones			= g_pMaterialSystem->FindMaterial("debug/debugmrmwireframe", TEXTURE_GROUP_OTHER, true);
	g_materialLines			= g_pMaterialSystem->FindMaterial("debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER, true);
	g_materialFloor			= g_pMaterialSystem->FindMaterial("hlmv/floor", TEXTURE_GROUP_OTHER, true);
	g_materialVertexColor   = g_pMaterialSystem->FindMaterial("debug/debugvertexcolor", TEXTURE_GROUP_OTHER, true);
	g_materialShadow		= g_pMaterialSystem->FindMaterial("hlmv/shadow", TEXTURE_GROUP_OTHER, true);

	if (!parent)
		setVisible (true);
	else
		mx::setIdleWindow (this);

	m_bSuppressResize = false;

	m_stickyDepth = 0;
	m_bIsSticky = false;
	m_snapshotDepth = 0;
}



MatSysWindow::~MatSysWindow ()
{
	mx::setIdleWindow (0);
}

void MatSysWindow::redraw()
{
	BaseClass::redraw();
return;
	if ( IsLocked() )
	{
		RECT bounds;
		GetClientRect( (HWND)getHandle(), &bounds );
		bounds.bottom = bounds.top + GetCaptionHeight();
		CChoreoWidgetDrawHelper helper( this, bounds );
		HandleToolRedraw( helper );
	}
}

#define MAX_FPS 250.0f
#define MIN_TIMESTEP ( 1.0f / MAX_FPS )

double realtime = 0.0f;

void MatSysWindow::Frame( void )
{
	static bool recursion_guard = false;

	static double prev = 0.0;
	double curr = (double) mx::getTickCount () / 1000.0;
	double dt = ( curr - prev );
	
	if ( recursion_guard )
		return;

	recursion_guard = true;

	// clamp to MAX_FPS
	if ( dt >= 0.0 && dt < MIN_TIMESTEP )
	{
		Sleep( max( 0, (int)( ( MIN_TIMESTEP - dt ) * 1000.0f ) ) );

		recursion_guard = false;
		return;
	}

	if ( prev != 0.0 )
	{
		dt = min( 0.1, dt );
		
		g_MDLViewer->Think( dt );

		realtime += dt;
	}
	
	prev = curr;

	DrawFrame();

	recursion_guard = false;
}

void MatSysWindow::DrawFrame( void )
{
	if (!g_viewerSettings.pause)
	{
		redraw ();
	}
}

int MatSysWindow::handleEvent (mxEvent *event)
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	int iret = 0;
	
	if ( HandleToolEvent( event ) )
	{
		return iret;
	}

	static float oldrx = 0, oldry = 0, oldtz = 50, oldtx = 0, oldty = 0;
	static float oldlrx = 0, oldlry = 0;
	static int oldx, oldy;

	switch (event->event)
	{
	case mxEvent::Idle:
		{
			iret = 1;

			Frame();
		}
		break;

	case mxEvent::MouseDown:
		{
			StudioModel *pModel = models->GetActiveStudioModel();
			if (!pModel)
				break;
			oldrx = pModel->m_angles[0];
			oldry = pModel->m_angles[1];
			oldtx = pModel->m_origin[0];
			oldty = pModel->m_origin[1];
			oldtz = pModel->m_origin[2];
			oldx = (short)event->x;
			oldy = (short)event->y;
			oldlrx = g_viewerSettings.lightrot[0];
			oldlry = g_viewerSettings.lightrot[1];
			g_viewerSettings.pause = false;

			float r = 1.0/3.0 * min( w(), h() );

			float d = sqrt( ( float )( (event->x - w()/2) * (event->x - w()/2) + (event->y - h()/2) * (event->y - h()/2) ) );

			if (d < r)
				g_viewerSettings.rotating = false;
			else
				g_viewerSettings.rotating = true;

			iret = 1;
		}
		break;

	case mxEvent::MouseDrag:
		{
			StudioModel *pModel = models->GetActiveStudioModel();
			if (!pModel)
				break;

			if (event->buttons & mxEvent::MouseLeftButton)
			{
				if (event->modifiers & mxEvent::KeyShift)
				{
					pModel->m_origin[1] = oldty - (float) ((short)event->x - oldx) * 0.1;
					pModel->m_origin[2] = oldtz + (float) ((short)event->y - oldy) * 0.1;
				}
				else if (event->modifiers & mxEvent::KeyCtrl)
				{
					float ry = (float) (event->y - oldy);
					float rx = (float) (event->x - oldx);
					oldx = event->x;
					oldy = event->y;
					
					QAngle movement = QAngle( ry, rx, 0 );
					
					matrix3x4_t tmp1, tmp2, tmp3;
					AngleMatrix( g_viewerSettings.lightrot, tmp1 );
					AngleMatrix( movement, tmp2 );
					ConcatTransforms( tmp2, tmp1, tmp3 );
					MatrixAngles( tmp3, g_viewerSettings.lightrot );
				}
				else
				{
					if (!g_viewerSettings.rotating)
					{
						float ry = (float) (event->y - oldy);
						float rx = (float) (event->x - oldx);
						oldx = event->x;
						oldy = event->y;
						
						QAngle movement;
						matrix3x4_t tmp1, tmp2, tmp3;
						
						movement = QAngle( 0, rx, 0 );
						AngleMatrix( pModel->m_angles, tmp1 );
						AngleMatrix( movement, tmp2 );
						ConcatTransforms( tmp1, tmp2, tmp3 );
						MatrixAngles( tmp3, pModel->m_angles );
						
						movement = QAngle( ry, 0, 0 );
						AngleMatrix( pModel->m_angles, tmp1 );
						AngleMatrix( movement, tmp2 );
						ConcatTransforms( tmp2, tmp1, tmp3 );
						MatrixAngles( tmp3, pModel->m_angles );
					}
					else
					{
						float ang1 = (180 / 3.1415) * atan2( oldx - w()/2.0, oldy - h()/2.0 );
						float ang2 = (180 / 3.1415) * atan2( event->x - w()/2.0, event->y - h()/2.0 );
						oldx = event->x;
						oldy = event->y;
						
						QAngle movement = QAngle( 0, 0, ang2 - ang1 );
						
						matrix3x4_t tmp1, tmp2, tmp3;
						AngleMatrix( pModel->m_angles, tmp1 );
						AngleMatrix( movement, tmp2 );
						ConcatTransforms( tmp2, tmp1, tmp3 );
						MatrixAngles( tmp3, pModel->m_angles );
					}			
				}
			}
			else if (event->buttons & mxEvent::MouseRightButton)
			{
				pModel->m_origin[0] = oldtx + (float) ((short)event->y - oldy) * 0.1;
				pModel->m_origin[0] = clamp( pModel->m_origin[0], 8.0f, 1024.0f );
			}
			redraw ();

			iret = 1;
		}
		break;

	case mxEvent::KeyDown:
		{
			iret = 1;
			switch (event->key)
			{
			default:
				iret = 0;
				break;
			case 116: // F5
				{
					g_MDLViewer->Refresh();
				}
				break;
			case 32:
				{
					int iSeq = models->GetActiveStudioModel()->GetSequence();
					if (iSeq == models->GetActiveStudioModel()->SetSequence (iSeq + 1))
					{
						g_pControlPanel->setSequence( 0 );
					}
					else
					{
						g_pControlPanel->setSequence( iSeq + 1 );
					}
				}
				break;
				
			case 27:
				if (!getParent ()) // fullscreen mode ?
					mx::quit ();
				break;
				
			case 'g':
				g_viewerSettings.showGround = !g_viewerSettings.showGround;
				break;
				
			case 'h':
				g_viewerSettings.showHitBoxes = !g_viewerSettings.showHitBoxes;
				break;
				
			case 'o':
				g_viewerSettings.showBones = !g_viewerSettings.showBones;
				break;
				
			case 'b':
				g_viewerSettings.showBackground = !g_viewerSettings.showBackground;
				break;
				
			case 'm':
				g_viewerSettings.showMovement = !g_viewerSettings.showMovement;
				break;
				
			case '1':
			case '2':
			case '3':
			case '4':
				g_viewerSettings.renderMode = event->key - '1';
				break;
				
			case '-':
				g_viewerSettings.speedScale -= 0.1f;
				if (g_viewerSettings.speedScale < 0.0f)
					g_viewerSettings.speedScale = 0.0f;
				break;
				
			case '+':
				g_viewerSettings.speedScale += 0.1f;
				if (g_viewerSettings.speedScale > 5.0f)
					g_viewerSettings.speedScale = 5.0f;
				break;
			}
		}
		break;
	} // switch (event->event)

	return iret;
}



void
drawFloor ()
{
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	pRenderContext->Bind(g_materialFloor);
	pRenderContext->MatrixMode(MATERIAL_MODEL);
	pRenderContext->PushMatrix();
	pRenderContext->LoadIdentity();
	pRenderContext->MatrixMode(MATERIAL_VIEW);
	pRenderContext->PushMatrix();
	pRenderContext->LoadIdentity();
	{
		IMesh* pMesh = pRenderContext->GetDynamicMesh();
		CMeshBuilder meshBuilder;
		meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );

		float dist=-15000.0f;
		float tMin=0, tMax=1;
		
		meshBuilder.Position3f(-dist, dist, dist);
		meshBuilder.TexCoord2f( 0, tMin,tMax );
		meshBuilder.Color4ub( 255, 255, 255, 255 );
		meshBuilder.AdvanceVertex();

		meshBuilder.Position3f( dist, dist, dist);
		meshBuilder.TexCoord2f( 0, tMax,tMax );
		meshBuilder.Color4ub( 255, 255, 255, 255 );
		meshBuilder.AdvanceVertex();

		meshBuilder.Position3f( dist,-dist, dist);
		meshBuilder.TexCoord2f( 0, tMax,tMin );
		meshBuilder.Color4ub( 255, 255, 255, 255 );
		meshBuilder.AdvanceVertex();

		meshBuilder.Position3f(-dist,-dist, dist);
		meshBuilder.TexCoord2f( 0, tMin,tMin );
		meshBuilder.Color4ub( 255, 255, 255, 255 );
		meshBuilder.AdvanceVertex();

		meshBuilder.End();
		pMesh->Draw();
	}
	pRenderContext->MatrixMode(MATERIAL_MODEL);
	pRenderContext->PopMatrix();
	pRenderContext->MatrixMode(MATERIAL_VIEW);
	pRenderContext->PopMatrix();
}



void
setupRenderMode ()
{
}

void MatSysWindow::SuppressBufferSwap( bool bSuppress )
{
	m_bSuppressSwap = bSuppress;
}

void MatSysWindow::draw ()
{
	int i;

	g_pMaterialSystem->BeginFrame( 0 );
	CUtlVector< StudioModel * > modellist;

	modellist.AddToTail( models->GetActiveStudioModel() );

	if ( models->CountVisibleModels() > 0 )
	{
		modellist.RemoveAll();
		for ( i = 0; i < models->Count(); i++ )
		{
			if ( models->IsModelShownIn3DView( i ) )
			{
				modellist.AddToTail( models->GetStudioModel( i ) );
			}
		}
	}

	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	pRenderContext->ClearBuffers(true, true);

	int captiony = GetCaptionHeight();
	int viewh = h2() - captiony;

	g_pMaterialSystem->SetView( (HWND)getHandle() );

	pRenderContext->Viewport( 0, captiony, w2(), viewh );

	pRenderContext->MatrixMode( MATERIAL_PROJECTION );
	pRenderContext->LoadIdentity( );
	pRenderContext->PerspectiveX(20.0f, (float)w2() / (float)viewh, 1.0f, 20000.0f);
	
	pRenderContext->MatrixMode( MATERIAL_VIEW );
	pRenderContext->LoadIdentity( );
	// FIXME: why is this needed?  Doesn't SetView() override this?
	pRenderContext->Rotate( -90,  1, 0, 0 );	    // put Z going up
	pRenderContext->Rotate( -90,  0, 0, 1 );

	int modelcount = modellist.Count();
	int countover2 = modelcount / 2;
	int ydelta = g_pControlPanel->GetModelGap();
	int yoffset = -countover2 * ydelta;
	for ( i = 0 ; i < modelcount; i++ )
	{
		modellist[ i ]->IncrementFramecounter( );

		Vector oldtrans = modellist[ i ]->m_origin;

		modellist[ i ]->m_origin[ 1 ] = oldtrans[ 1 ] + yoffset;
		yoffset += ydelta;

		modellist[ i ]->GetStudioRender()->BeginFrame();
		modellist[ i ]->DrawModel();
		modellist[ i ]->GetStudioRender()->EndFrame();

		modellist[ i ]->m_origin = oldtrans;
	}

	//
	// draw ground
	//
	if (g_viewerSettings.showGround)
	{
		drawFloor ();
	}

	if (!m_bSuppressSwap)
	{
		g_pMaterialSystem->SwapBuffers();
	}

	g_pMaterialSystem->EndFrame();
}

void MatSysWindow::EnableStickySnapshotMode( )
{
	m_stickyDepth++;
}

void MatSysWindow::DisableStickySnapshotMode( )
{
	if (--m_stickyDepth == 0)
	{
		if (m_bIsSticky)
		{
			m_bIsSticky = false;

			HWND wnd = (HWND)getHandle();

			// Move back to original position
			SetWindowPlacement( wnd, &m_wp );

			SuppressResize( false );

			SetCursor( m_hPrevCursor );
		}
	}
}


void MatSysWindow::PushSnapshotMode( int nSnapShotSize )
{
	if (m_snapshotDepth++ == 0)
	{
		if (m_stickyDepth)
		{
			if (m_bIsSticky)
				return;

			m_bIsSticky = true;
			m_hPrevCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
		}

		SuppressResize( true );

		RECT rcClient;
		HWND wnd = (HWND)getHandle();

		GetWindowPlacement( wnd, &m_wp );

		GetClientRect( wnd, &rcClient );

		MoveWindow( wnd, 0, 0, nSnapShotSize + 16, nSnapShotSize + 16, TRUE );
	}
}


void MatSysWindow::PopSnapshotMode( )
{
	if (--m_snapshotDepth == 0)
	{
		if (m_stickyDepth == 0)
		{
			HWND wnd = (HWND)getHandle();

			// Move back to original position
			SetWindowPlacement( wnd, &m_wp );

			SuppressResize( false );
		}
	}
}


void MatSysWindow::TakeSnapshotRect( const char *pFilename, int x, int y, int w, int h )
{
	int i;
	HANDLE hf;
	BITMAPFILEHEADER hdr;
	BITMAPINFOHEADER bi;
	DWORD dwTmp, imageSize;
	byte *hp, b, *pBlue, *pRed;

	w = ( w + 3 ) & ~3;

	imageSize = w * h * 3;
	// Create the file
	hf = CreateFile( pFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	if( hf == INVALID_HANDLE_VALUE )
	{
		return;
	}

	// file header
	hdr.bfType = 0x4d42;	// 'BM'
	hdr.bfSize = (DWORD) ( sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + imageSize );
	hdr.bfReserved1 = 0;
	hdr.bfReserved2 = 0;
	hdr.bfOffBits = (DWORD) ( sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) );

	if( !WriteFile( hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL ) )
		Error( "Couldn't write file header to snapshot.\n" );

	// bitmap header
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = w;
	bi.biHeight = h;
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;	//vid.rowbytes * vid.height;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	if( !WriteFile( hf, (LPVOID) &bi, sizeof(BITMAPINFOHEADER), (LPDWORD) &dwTmp, NULL ) )
		Error( "Couldn't write bitmap header to snapshot.\n" );

	// bitmap bits
	hp = (byte *) malloc(imageSize);
	
	if (hp == NULL)
		Error( "Couldn't allocate bitmap header to snapshot.\n" );

	// Get Bits from the renderer
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	pRenderContext->ReadPixels( x, y, w, h, hp, IMAGE_FORMAT_RGB888 );

	// Invert vertically for BMP format
	for (i = 0; i < h / 2; i++)
	{
		byte *top = hp + i * w * 3;
		byte *bottom = hp + (h - i - 1) * w * 3;
		for (int j = 0; j < w * 3; j++)
		{
			b = *top;
			*top = *bottom;
			*bottom = b;
			top++;
			bottom++;
		}
	}

	// Reverse Red and Blue
	pRed = hp;
	pBlue = pRed + 2;
	for(i = 0; i < w * h;i++)
	{
		b = *pRed;
		*pRed = *pBlue;
		*pBlue = b;
		pBlue += 3;
		pRed += 3;
	}

	if( !WriteFile( hf, (LPVOID)hp, imageSize, (LPDWORD) &dwTmp, NULL ) )
		Error( "Couldn't write bitmap data snapshot.\n" );

	free(hp);

	// clean up
	if( !CloseHandle( hf ) )
		Error( "Couldn't close file for snapshot.\n" );
}

//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool MatSysWindow::IsSuppressingResize( void )
{
	return m_bSuppressResize;
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : suppress - 
//-----------------------------------------------------------------------------
void MatSysWindow::SuppressResize( bool suppress )
{
	m_bSuppressResize = suppress;
}

void
MatSysWindow::TakeScreenShot (const char *filename)
{
	redraw ();
	int w = w2 ();
	int h = h2 ();

	mxImage *image = new mxImage ();
	if (image->create (w, h, 24))
	{
#if 0
		glReadBuffer (GL_FRONT);
		glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image->data);
#else
		HDC hdc = GetDC ((HWND) getHandle ());
		byte *data = (byte *) image->data;
		int i = 0;
		for (int y = 0; y < h; y++)
		{
			for (int x = 0; x < w; x++)
			{
				COLORREF cref = GetPixel (hdc, x, y);
				data[i++] = (byte) ((cref >> 0)& 0xff);
				data[i++] = (byte) ((cref >> 8) & 0xff);
				data[i++] = (byte) ((cref >> 16) & 0xff);
			}
		}
		ReleaseDC ((HWND) getHandle (), hdc);
#endif
		if (!mxTgaWrite (filename, image))
			mxMessageBox (this, "Error writing screenshot.", g_appTitle, MX_MB_OK | MX_MB_ERROR);

		delete image;
	}
}