/////////////////////////////////////////////////////////////////////
// $$root$$.cpp : Defines the entry point for the application.
/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////
// Generated by the CDX Application Wizard
// By: Michael Rich [istan@alltel.net]
//
// With valuable help from:
//   Ioannis Karagiorgos, for the debugging help
//   Bil Simser, for the good ideas and constructive criticism
/////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN

$$IF(DX3)
// this define is necessary to force
// CDX to use DirectX 3.0 interfaces
#define NTDX3

$$ENDIF
#include <windows.h>
#define CDXINCLUDEALL     // this define includes all headers, otherwise include one by one
#include <cdx.h>
#include <CDX3D.h>

#include "resource.h"

/////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////
char szAppName[] = "$$APP_TITLE$$";
char szClassName[] = "$$Safe_root$$WndClass";

HINSTANCE g_hInst;			// instance handle
HWND g_hWnd;				// window handle

$$IF(COOP_BOTH)
$$IF(COOP_ST_FS)
BOOL g_bFullScreen = TRUE;	// running fullscreen?
$$ELIF(COOP_ST_WIN)
BOOL g_bFullScreen = FALSE;	// running fullscreen?
$$ENDIF
$$ENDIF
$$IF(LOOSEFOCUS)
BOOL g_IsAppActive;			// is the app active
$$ENDIF

/////////////////////////////////////////////////////////////////////
// CDX Objects
/////////////////////////////////////////////////////////////////////
CDXScreen *Screen = 0;	// The CDX Screen object
CRMEngine* Engine = 0;	// The CRM 3D engine object
$$IF(ROTSQ)
CRMScene* Scene = 0;
CRMCamera* Camera = 0;
CRMLight* Light = 0;
CRMShape* Shape = 0;
$$ENDIF
$$IF(INPUT_CDXINPUT)
CDXInput *Input = 0;
$$ENDIF
$$IF(COOP_BOTH)

/////////////////////////////////////////////////////////////////////
// Forward declarations
/////////////////////////////////////////////////////////////////////
void AdjustWinStyle();
$$ENDIF

/////////////////////////////////////////////////////////////////////
// cdx_Init_3DS - handles initialization of the 3D scene objects
/////////////////////////////////////////////////////////////////////
BOOL cdx_Init_3DS()
{
	// Create our scene
	Scene = new CRMScene(Engine);
	Scene->Create();

	// Create a camera
	Camera = new CRMCamera(Engine);
	Camera->Create(Scene);

	// Create a light and add it to the scene
	Light = new CRMLight(Engine);
	Light->CreateDirectional(1.0, 1.0, 1.0);
	Scene->AddChild(Light);

	// Set the position and direction of the light in our scene
	Light->SetPosition(100.0, 100.0, -100.0, Scene);
	Light->SetDirection(-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, Scene);

	// Create our demo shape (a cube in this case) and add it to the scene
	Shape = new CRMShape(Engine);
	Shape->CreateCube(2.0, 2.0, 2.0);
	Shape->SetColor(1, 0, 1);
	Scene->AddChild(Shape);
	Shape->SetPosition(0.0, 0.0, 0.0, Scene);
	Shape->SetRotation(1, 0.1, 0.5, 0.1, Scene);

	return TRUE;
}

/////////////////////////////////////////////////////////////////////
// cdx_Init - handles initialization of the CDX objects
/////////////////////////////////////////////////////////////////////
BOOL cdx_Init()
{
	// Create the CDXSreen object
	Screen = new CDXScreen();
	if (Screen==NULL) return FALSE;

	// Create our 3D Engine object
	Engine = new CRMEngine();
	if (Engine==NULL) return FALSE;

$$IF(COOP_FS)
$$IF(TRIPLEBUFF)
	// enable triple buffering
	Screen->SetTripleBuffering(TRUE);

$$ENDIF
	// start app fullscreen
	if (Engine->CreateFullScreen(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$, $$BPP$$) != D3DRM_OK) return FALSE;
$$ELIF(COOP_WIN)
	// start app in a window
	if (Engine->CreateWindowed(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$) != D3DRM_OK) return FALSE;
$$ELSE
$$IF(COOP_ST_FS)
$$IF(TRIPLEBUFF)
	// enable triple buffering
	Screen->SetTripleBuffering(TRUE);

$$ENDIF
	// start app fullscreen
	if (Engine->CreateFullScreen(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$, $$BPP$$) != D3DRM_OK) return FALSE;
$$ELSE
	// start app in a window
	if (Engine->CreateWindowed(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$) != D3DRM_OK) return FALSE;
$$ENDIF

$$ENDIF
$$IF(ROTSQ)
	if (!cdx_Init_3DS()) return FALSE;

$$ENDIF
$$IF(INPUT_CDXINPUT)
	// create our input object
	Input = new CDXInput();
	if (Input==NULL) return FALSE;

	// Create input devices
	if(!Input->Create(g_hInst, g_hWnd)) return FALSE;
$$ENDIF

	// TODO: Initialize your own CDX objects here
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////
// cdx_DeInit - handles cleanup of CDX objects
/////////////////////////////////////////////////////////////////////
void cdx_DeInit()
{
	// TODO: Destroy your CDX objects here

$$IF(ROTSQ)
	SAFEDELETE(Camera);
	SAFEDELETE(Light);
	SAFEDELETE(Shape);
	SAFEDELETE(Scene);
$$ENDIF
$$IF(INPUT_CDXINPUT)
	SAFEDELETE(Input);	
$$ENDIF
	SAFEDELETE(Engine);
	SAFEDELETE(Screen);
}

/////////////////////////////////////////////////////////////////////
// cdx_DoFrame - performs drawing of the current frame
/////////////////////////////////////////////////////////////////////
void cdx_DoFrame()
{
$$IF(INPUT_CDXINPUT)
	// read input from devices
	Input->Update();

	// handle keyboard input	

	// if Escape is pressed, close the application
	if (Input->GetKeyState(CDXKEY_ESCAPE))
	{
		SendMessage(g_hWnd, WM_CLOSE, 0, 0);
		// return out as the code below is invalid now
		return;
	}

$$IF(COOP_BOTH)
	// Alt+Enter switches modes
	if ((Input->GetKeyState(CDXKEY_LEFTALT) || Input->GetKeyState(CDXKEY_RIGHTALT))
			&& Input->GetKeyState(CDXKEY_ENTER))
	{
		g_bFullScreen = !g_bFullScreen;
		if(g_bFullScreen)
		{
			AdjustWinStyle();
			// we need to destroy and recreate the supporting CDX objects
			// that can't survive intact when we switch back to fullscreen mode
			{
				// TODO: add your own CDX objects that would have to be destroyed
				// on a mode switch (they will be recreated below)
$$IF(ROTSQ)

				SAFEDELETE(Camera);
				SAFEDELETE(Light);
				SAFEDELETE(Shape);
				SAFEDELETE(Scene);
$$ENDIF
			}
$$IF(TRIPLEBUFF)
			// enable triple buffering
			Screen->SetTripleBuffering(TRUE);
$$ENDIF
			Engine->CreateFullScreen(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$, $$BPP$$);
			{
				// TODO: recreate your CDX objects that were destroyed above
$$IF(ROTSQ)
				// re-load our 3D scene
				cdx_Init_3DS();
$$ENDIF
			}
		}
		else
		{
			Screen->GetDD()->RestoreDisplayMode();
			AdjustWinStyle();
			// we need to destroy and recreate the supporting CDX objects
			// that can't survive intact when we switch back to windowed mode
			{
				// TODO: add your own CDX objects that would have to be destroyed
				// on a mode switch (they will be recreated below)
$$IF(ROTSQ)

				SAFEDELETE(Camera);
				SAFEDELETE(Light);
				SAFEDELETE(Shape);
				SAFEDELETE(Scene);
$$ENDIF
			}
			Engine->CreateWindowed(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$);
			{
				// TODO: recreate your CDX objects that were destroyed above
$$IF(ROTSQ)
				// re-load our 3D scene
				cdx_Init_3DS();
$$ENDIF
			}

		}
		// clear any data from the keyboard
		Input->FlushKeyboardData();
	}
$$ENDIF
		
	// TODO: Add your own code to handle the Mouse
	// and the joystick

$$ENDIF

	// clear the current frame
	Screen->GetBack()->Fill(0);
$$IF(ROTSQ)

	// draw the scene
	Camera->Clear();
	Engine->Tick(0.4);
	Camera->Render(Scene);

$$ENDIF
	// TODO: Add code to draw your objects during each frame

	Screen->Flip();	 // Flip the back buffer to the front
}

$$IF(!COOP_FS)
/////////////////////////////////////////////////////////////////////
// AdjustWinStyle - adjusts the window style according to the mode
/////////////////////////////////////////////////////////////////////
static void AdjustWinStyle()
{
$$IF(COOP_WIN)
	RECT        rect = {0, 0, $$WIDTH$$, $$HEIGHT$$};
	DWORD       dwStyle;

	// Change window attributes

	dwStyle = GetWindowStyle(g_hWnd);
	dwStyle &= ~WS_POPUP;
	dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

	SetWindowLong(g_hWnd, GWL_STYLE, dwStyle);

	// Resize the window so that the client area is $$WIDTH$$x$$HEIGHT$$

	AdjustWindowRectEx(&rect, GetWindowStyle(g_hWnd), GetMenu(g_hWnd) != NULL,
		GetWindowExStyle(g_hWnd));

	// Just in case the window was moved off the visible area of the
	// screen.

	SetWindowPos(g_hWnd, NULL, 0, 0, rect.right-rect.left,
		rect.bottom-rect.top, SWP_NOMOVE | SWP_NOZORDER |
		SWP_NOACTIVATE);

	SetWindowPos(g_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
		SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
$$ELSE
	if (g_bFullScreen)
	{
		DWORD       dwStyle;

		// Change window attributes

		dwStyle = WS_POPUP | WS_VISIBLE;

		SetWindowLong(g_hWnd, GWL_STYLE, dwStyle);

		SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN),
			GetSystemMetrics(SM_CYFULLSCREEN), SWP_NOACTIVATE |
			SWP_NOZORDER);
	}
	else
	{
		RECT        rect = {0, 0, $$WIDTH$$, $$HEIGHT$$};
		DWORD       dwStyle;

		// Change window attributes

		dwStyle = GetWindowStyle(g_hWnd);
		dwStyle &= ~WS_POPUP;
		dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

		SetWindowLong(g_hWnd, GWL_STYLE, dwStyle);

		// Resize the window so that the client area is $$WIDTH$$x$$HEIGHT$$

		AdjustWindowRectEx(&rect, GetWindowStyle(g_hWnd), GetMenu(g_hWnd) != NULL,
			GetWindowExStyle(g_hWnd));

		// Just in case the window was moved off the visible area of the
		// screen.

		SetWindowPos(g_hWnd, NULL, 0, 0, rect.right-rect.left,
			rect.bottom-rect.top, SWP_NOMOVE | SWP_NOZORDER |
			SWP_NOACTIVATE);

		SetWindowPos(g_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
			SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
	}
$$ENDIF
}
$$ENDIF

/////////////////////////////////////////////////////////////////////
// WinProc - handles application messages
/////////////////////////////////////////////////////////////////////
static long PASCAL WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
$$IF(LOOSEFOCUS)
		case WM_ACTIVATEAPP:
			g_IsAppActive = wParam;
			return 0;
$$ENDIF

$$IF(INPUT_KEYDOWN)
		case WM_KEYDOWN:
			switch(wParam)
			{
			case VK_ESCAPE:
				// if Escape is pressed, close the application
				SendMessage(hWnd, WM_CLOSE, 0, 0);
				break;
			}
			return  0;
$$IF(COOP_BOTH)
		case WM_SYSKEYUP:
			// Alt+Enter switches modes
			if (wParam == VK_RETURN)
			{
				g_bFullScreen = !g_bFullScreen;
				if(g_bFullScreen)
				{
					AdjustWinStyle();
					// we need to destroy and recreate the supporting CDX objects
					// that can't survive intact when we switch back to fullscreen mode
					{
						// TODO: add your own CDX objects that would have to be destroyed
						// on a mode switch (they will be recreated below)
$$IF(ROTSQ)

						SAFEDELETE(Camera);
						SAFEDELETE(Light);
						SAFEDELETE(Shape);
						SAFEDELETE(Scene);
$$ENDIF
					}
$$IF(TRIPLEBUFF)
					// enable triple buffering
					Screen->SetTripleBuffering(TRUE);
$$ENDIF
					Engine->CreateFullScreen(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$, $$BPP$$);
					{
						// TODO: recreate your CDX objects that were destroyed above
$$IF(ROTSQ)
						// re-load our 3D scene
						cdx_Init_3DS();
$$ENDIF
					}
				}
				else
				{
					Screen->GetDD()->RestoreDisplayMode();
					AdjustWinStyle();
					// we need to destroy and recreate the supporting CDX objects
					// that can't survive intact when we switch back to windowed mode
					{
						// TODO: add your own CDX objects that would have to be destroyed
						// on a mode switch (they will be recreated below)
$$IF(ROTSQ)

						SAFEDELETE(Camera);
						SAFEDELETE(Light);
						SAFEDELETE(Shape);
						SAFEDELETE(Scene);
$$ENDIF
					}
					Engine->CreateWindowed(Screen, g_hWnd, $$WIDTH$$, $$HEIGHT$$);
					{
						// TODO: recreate your CDX objects that were destroyed above
$$IF(ROTSQ)
						// re-load our 3D scene
						cdx_Init_3DS();
$$ENDIF
					}

				}
				return 0;
			}
			return 1;
$$ENDIF
$$ENDIF
$$IF(MOUSEON)
		// hide the mouse cursor
		case WM_SETCURSOR:
			SetCursor(NULL);
        
			return 1;
$$ENDIF
		case WM_CLOSE:
			cdx_DeInit();
		case WM_DESTROY:
			PostQuitMessage(0);
		return 0;

		default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
}

$$IF(CHGEXEDIR)
/////////////////////////////////////////////////////////////////////
// ChangeToEXEDir - sets CWD to the DIR the EXE is in
/////////////////////////////////////////////////////////////////////
static void ChangeToEXEDir()
{
	char buf[MAX_PATH];
	char *cptr;

	//now change the directory
	//to make sure were accessing the proper file
	GetModuleFileName(NULL, buf, MAX_PATH);

	//move pointer to end of string
	cptr = buf + lstrlen(buf);

	//find the end of the path
	do
	{
		cptr--;
	} while (*cptr != '\\');
	cptr++;
	*cptr='\0';

	//change directory
	SetCurrentDirectory(buf);
}

$$ENDIF
/////////////////////////////////////////////////////////////////////
// InitApp - Create the window and the CDX objects
/////////////////////////////////////////////////////////////////////
static BOOL InitApp(int nCmdShow)
{
	WNDCLASS WndClass;

	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	WndClass.lpfnWndProc = WinProc;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = g_hInst;
	WndClass.hIcon = LoadIcon(g_hInst, "APPICON");
	WndClass.hCursor = LoadCursor(0, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	WndClass.lpszMenuName = 0;
	WndClass.lpszClassName = szClassName;
	RegisterClass(&WndClass);

	g_hWnd = CreateWindowEx(
$$IF(COOP_FS)
		WS_EX_TOPMOST,
$$ELIF(COOP_WIN)
		0,
$$ELSE
$$IF(COOP_ST_FS)
		WS_EX_TOPMOST,
$$ELSE
		0,
$$ENDIF
$$ENDIF
		szClassName,
		szAppName,
$$IF(COOP_FS)
 		WS_POPUP,
$$ELIF(COOP_WIN)
 		WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
$$ELSE
$$IF(COOP_ST_FS)
 		WS_POPUP,
$$ELSE
 		WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
$$ENDIF
$$ENDIF
		0,
		0,
$$IF(COOP_FS)
		GetSystemMetrics(SM_CXFULLSCREEN),
		GetSystemMetrics(SM_CYFULLSCREEN),
$$ELIF(COOP_WIN)
		320,
		240,
$$ELSE
$$IF(COOP_ST_FS)
		GetSystemMetrics(SM_CXFULLSCREEN),
		GetSystemMetrics(SM_CYFULLSCREEN),
$$ELSE
		320,
		240,
$$ENDIF
$$ENDIF
		NULL,
		NULL,
		g_hInst,
		NULL);

	if(!g_hWnd) return FALSE;

$$IF(COOP_WIN)
	AdjustWinStyle();
$$ELIF(COOP_BOTH)
$$IF(COOP_ST_WIN)
	AdjustWinStyle();
$$ENDIF
$$ENDIF

	ShowWindow(g_hWnd, nCmdShow);
	UpdateWindow(g_hWnd);

$$IF(CHGEXEDIR)
	ChangeToEXEDir();
	
$$ENDIF
	return TRUE;
}

/////////////////////////////////////////////////////////////////////
// WinMain - inital function called by windows
/////////////////////////////////////////////////////////////////////
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
	MSG msg;

	// save the app instance
	g_hInst = hInstance;


	if(!InitApp(nCmdShow)) return FALSE;
	if(!cdx_Init())
	{
		PostQuitMessage(0);
		return FALSE;
	}

	while(1)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if(!GetMessage(&msg, NULL, 0, 0 )) return msg.wParam;
			TranslateMessage(&msg); 
			DispatchMessage(&msg);
		}
$$IF(LOOSEFOCUS)
		else if(g_IsAppActive)
		{
			cdx_DoFrame();
		}
		else
		{
			WaitMessage();
		}
$$ELSE
		else
		{
			cdx_DoFrame();
		}
$$ENDIF
	}
}
