//============================================================
// Program:		GameFrame
// Description:	Class for simplifying the DirectX setup process
// Author:		Benjamin Gottemoller
// Website:		http://www.particlefield.com
// Date:		4/20/01
// Legal:		Licensed under the gnu GPL (see gpl.txt for details)
//============================================================
//Link Files:	dxguid.lib dxerr8.lib dinput8.lib d3dx8dt.lib 
//				d3dx8.lib d3d8.lib d3dxof.lib winmm.lib 

#ifndef _GAME_FRAME_
#define _GAME_FRAME_

#define DIRECTINPUT_VERSION 0x0800
#pragma warning(disable:4995)

#include <d3dx8.h>
#include <dinput.h>
#include "d3dfile.h"
#include "d3dutil.h"
#include "didcfgview.h"
#include "diutil.h"
#include "dmutil.h"
#include "dsutil.h"
#include "dxutil.h"
#include "d3dfont.h"

#include "WindowFrame.h"
#include "GameFrameVertexLibrary.h"
#include "GameFrameTextureLibrary.h"
#include "GameFrameMaterialLibrary.h"
#include "GameFrameObjectLibrary.h"
#include "GameFrameCamera.h"
#include "GameFrameEntity.h"
#include "GameFrameHUD.h"
#include "GameFrameSmartLoader.h"
#include "GameFrameParticleSystem.h"
#include "GameFrameSoundSystem.h"
#include "GameFrameFontLibrary.h"
#include "GameFrameSolarSystem.h"
#include "GameFrameWeaponSystem.h"
#include "GameFrameCollisionHandler.h"

#include "GFDebugHandler.h"

#ifndef DXUTIL_H
#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
#endif

const float PI			= 3.14159265358979323846264338327950288419716939937510f;
const float PI2			= PI * 2.0f;
const float RADIAN		= PI / 180.0f; 
const float DEGREE360	= 180.0f / PI;

#define SIN360(theta)	(float)sin((float)theta * RADIAN) 
#define COS360(theta)	(float)cos((float)theta * RADIAN) 
#define TAN360(theta)	(float)tan((float)theta * RADIAN)

#define SQRT(a)			((float)sqrt((float)a))
#define SWAP(a,b)		((a)^=(b)^=(a)^=(b))
#define ABS(a)			((a < 0) ? (-(a)) : (a))
#define MIN(a,b)		((a >= b) ? (b) : (a))  
#define MAX(a,b)		((a >= b) ? (a) : (b)) 
#define RAND(a)			(rand() % a)

#define MOUSE_X				1
#define MOUSE_Y				2
#define MOUSE_Z				4
#define MOUSE_LBUTTON		8
#define MOUSE_RBUTTON		16
#define MOUSE_BUTTON3		32
#define MOUSE_BUTTON4		64

#define MOUSE_BUFFER_SIZE	20

class GameFrame:public WindowFrame
{
public:

	struct SETUP_DATA
	{
		UINT adapter;
		int width, height;
		D3DFORMAT depth;
		D3DDEVTYPE device_type;
		int filter_type;				 //0=none, 1=linear, 2=anisotropic
		int is_vertex_lighting_enabled;
		int mesh_geometry_detail;		 //0=high, 1=medium, 2=low	
		int texture_maps_detail;		 //0=high, 1=medium, 2=low
	};

public:

	GameFrame(char *program_name = "GameFrame", bool debug_detail = 0);
	~GameFrame();

	void	BeginDirectX(HINSTANCE hInst, char *config_file, char *name = "GameFrame Window");
	void	DestroyDirectX(void);
	void	Present(void);
	
	void	TakeScreenShot(char* file);

	inline	float GetFPS(void)				{ return FPS; }
	inline	float GetTimeDiff(void)			{ return time_diff; }
	float	GetTime(void);
	
	inline	void EnableLighting(int state)	{ IsLightingEnabled = state; }
	
	void	UpdateKeyInfo(void);
	int		KEYDOWN(UCHAR key);

	void	SetMouseSmoothing(int state = 1);
	void	UpdateMouseInfo(void);
	float	MOUSEMESSAGE(UINT type);

	int						IsLightingEnabled;

	CGFVertexLibrary		VertexLib;
	CGFTextureLibrary		TextureLib;
	CGFMaterialLibrary		MaterialLib;
	CGFObjectLibrary		ObjectLib;
	CGFFontLibrary			FontLib;
	CGFSoundSystem			Sound;

	CGFParticleSystem		ParticleSystem;

	CGFSmartLoader			SmartLoader;

	D3DXMATRIX				ProjectionMatrix;
	D3DXMATRIX				OrthoProjectionMatrix;
	float					W2HRatio;
	float					H2WRatio;

	LPDIRECT3D8				D3DObject;
	LPDIRECT3DDEVICE8		D3DDevice;
	D3DPRESENT_PARAMETERS	D3DDisplayInfo;
	SETUP_DATA				Settings;

	LPDIRECTINPUT8			DIObject; 
	LPDIRECTINPUTDEVICE8	DIDeviceKeyboard; 
	LPDIRECTINPUTDEVICE8	DIDeviceMouse; 

private:

	void					TestRestore(void);

	BYTE					KEYBOARD[256];
	DIMOUSESTATE			MOUSE;
	bool					state_toggle;

	int						MeshDetailLevel;		//0=high, 1=medium, 2=low	
	int						TextureDetailLevel;		//0=high, 1=medium, 2=low	

	int						SmoothState;
	float					MouseXBuffer[MOUSE_BUFFER_SIZE];
	float					MouseYBuffer[MOUSE_BUFFER_SIZE];
};

#endif