You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
560 lines
10 KiB
560 lines
10 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
// TerrainBlend.cpp : Defines the entry point for the application. |
|
// |
|
|
|
#include "stdafx.h" |
|
#include "resource.h" |
|
#include "mathlib/mathlib.h" |
|
#include "tier0/dbg.h" |
|
#include "tier0/icommandline.h" |
|
#include "tier1/strtools.h" |
|
|
|
|
|
#define MAX_LOADSTRING 100 |
|
|
|
// Global Variables: |
|
HINSTANCE hInst; // current instance |
|
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text |
|
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text |
|
HWND g_hWnd; |
|
|
|
// Foward declarations of functions included in this code module: |
|
ATOM MyRegisterClass(HINSTANCE hInstance); |
|
BOOL InitInstance(HINSTANCE, int); |
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); |
|
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); |
|
|
|
int g_nCapture = 0; |
|
bool g_bFocus = false; |
|
|
|
int g_ScreenWidth, g_ScreenHeight; |
|
|
|
D3DPRESENT_PARAMETERS d3dpp; |
|
|
|
|
|
IDirect3D8 *g_pDirect3D; |
|
IDirect3DDevice8 *g_pDevice; |
|
|
|
|
|
POINT GetWindowCenter() |
|
{ |
|
RECT rc; |
|
GetWindowRect(g_hWnd, &rc); |
|
POINT ret; |
|
ret.x = (rc.left + rc.right) / 2; |
|
ret.y = (rc.top + rc.bottom) / 2; |
|
return ret; |
|
} |
|
|
|
|
|
void CallAppRender( bool bInvalidRect ) |
|
{ |
|
static DWORD lastTime = 0; |
|
static POINT lastMousePos = {0xFFFF, 0xFFFF}; |
|
|
|
// Sample time and mouse position and tell the app to render. |
|
DWORD curTime = GetTickCount(); |
|
float frametime = (curTime - lastTime) / 1000.0f; |
|
if( frametime > 0.1f ) |
|
frametime = 0.1f; |
|
|
|
lastTime = curTime; |
|
|
|
// Get the cursor delta. |
|
POINT curMousePos; |
|
GetCursorPos(&curMousePos); |
|
|
|
int deltaX, deltaY; |
|
|
|
if( lastMousePos.x == 0xFFFF ) |
|
{ |
|
deltaX = deltaY = 0; |
|
} |
|
else |
|
{ |
|
deltaX = curMousePos.x - lastMousePos.x; |
|
deltaY = curMousePos.y - lastMousePos.y; |
|
} |
|
|
|
// Recenter the cursor. |
|
if( g_nCapture ) |
|
{ |
|
lastMousePos = GetWindowCenter(); |
|
SetCursorPos( lastMousePos.x, lastMousePos.y ); |
|
} |
|
else |
|
{ |
|
lastMousePos = curMousePos; |
|
} |
|
|
|
AppRender( frametime, (float)deltaX, (float)deltaY, bInvalidRect ); |
|
} |
|
|
|
|
|
SpewRetval_t D3DAppSpewFunc( SpewType_t spewType, char const *pMsg ) |
|
{ |
|
switch (spewType) |
|
{ |
|
case SPEW_ERROR: |
|
MessageBox(NULL, pMsg, "FATAL ERROR", MB_OK); |
|
return SPEW_ABORT; |
|
|
|
default: |
|
OutputDebugString(pMsg); |
|
#ifdef _DEBUG |
|
return spewType == SPEW_ASSERT ? SPEW_DEBUGGER : SPEW_CONTINUE; |
|
#else |
|
return SPEW_CONTINUE; |
|
#endif |
|
} |
|
} |
|
|
|
int APIENTRY WinMain(HINSTANCE hInstance, |
|
HINSTANCE hPrevInstance, |
|
LPSTR lpCmdLine, |
|
int nCmdShow) |
|
{ |
|
CommandLine()->CreateCmdLine( Plat_GetCommandLine() ); |
|
|
|
// TODO: Place code here. |
|
SpewOutputFunc( D3DAppSpewFunc ); |
|
MathLib_Init( true, true, true, 2.2f, 2.2f, 0.0f, 2.0f ); |
|
MSG msg; |
|
HACCEL hAccelTable; |
|
|
|
// Initialize global strings |
|
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); |
|
strcpy( szWindowClass, "d3dapp" ); |
|
MyRegisterClass(hInstance); |
|
|
|
// Perform application initialization: |
|
if (!InitInstance (hInstance, nCmdShow)) |
|
{ |
|
return FALSE; |
|
} |
|
|
|
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TERRAINBLEND); |
|
|
|
|
|
InvalidateRect( g_hWnd, NULL, FALSE ); |
|
|
|
// Main message loop: |
|
while(1) |
|
{ |
|
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) |
|
{ |
|
if(msg.message == WM_QUIT) |
|
break; |
|
|
|
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) |
|
{ |
|
TranslateMessage(&msg); |
|
DispatchMessage(&msg); |
|
} |
|
} |
|
|
|
if(msg.message == WM_QUIT) |
|
break; |
|
|
|
CallAppRender( false ); |
|
} |
|
|
|
AppExit(); |
|
|
|
return msg.wParam; |
|
} |
|
|
|
|
|
|
|
// |
|
// FUNCTION: MyRegisterClass() |
|
// |
|
// PURPOSE: Registers the window class. |
|
// |
|
// COMMENTS: |
|
// |
|
// This function and its usage is only necessary if you want this code |
|
// to be compatible with Win32 systems prior to the 'RegisterClassEx' |
|
// function that was added to Windows 95. It is important to call this function |
|
// so that the application will get 'well formed' small icons associated |
|
// with it. |
|
// |
|
ATOM MyRegisterClass(HINSTANCE hInstance) |
|
{ |
|
WNDCLASSEX wcex; |
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX); |
|
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW; |
|
wcex.lpfnWndProc = (WNDPROC)WndProc; |
|
wcex.cbClsExtra = 0; |
|
wcex.cbWndExtra = 0; |
|
wcex.hInstance = hInstance; |
|
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TERRAINBLEND); |
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); |
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); |
|
wcex.lpszMenuName = NULL; |
|
wcex.lpszClassName = szWindowClass; |
|
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); |
|
|
|
return RegisterClassEx(&wcex); |
|
} |
|
|
|
|
|
void ShutdownD3D() |
|
{ |
|
if( g_pDevice ) |
|
{ |
|
g_pDevice->Release(); |
|
g_pDevice = NULL; |
|
} |
|
|
|
if( g_pDirect3D ) |
|
{ |
|
g_pDirect3D->Release(); |
|
g_pDirect3D = NULL; |
|
} |
|
} |
|
|
|
|
|
void InitD3D() |
|
{ |
|
ShutdownD3D(); |
|
|
|
|
|
RECT rcClient; |
|
GetClientRect( g_hWnd, &rcClient ); |
|
|
|
g_ScreenWidth = rcClient.right - rcClient.left; |
|
g_ScreenHeight = rcClient.bottom - rcClient.top; |
|
|
|
// Initialize D3D. |
|
g_pDirect3D = Direct3DCreate8( D3D_SDK_VERSION ); |
|
|
|
// Get the current desktop display mode, so we can set up a back |
|
// buffer of the same format |
|
D3DDISPLAYMODE d3ddm; |
|
g_pDirect3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ); |
|
|
|
|
|
// Set up the structure used to create the D3DDevice |
|
ZeroMemory( &d3dpp, sizeof(d3dpp) ); |
|
d3dpp.Windowed = TRUE; |
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; |
|
d3dpp.BackBufferFormat = d3ddm.Format; |
|
d3dpp.EnableAutoDepthStencil = TRUE; |
|
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; |
|
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; |
|
|
|
HRESULT hr = g_pDirect3D->CreateDevice( |
|
D3DADAPTER_DEFAULT, |
|
D3DDEVTYPE_HAL, |
|
g_hWnd, |
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING, |
|
&d3dpp, |
|
&g_pDevice); |
|
if( FAILED(hr) ) |
|
{ |
|
Sys_Error( "CreateDevice failed (%s)", DXGetErrorString8(hr) ); |
|
} |
|
|
|
g_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); |
|
g_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); |
|
} |
|
|
|
void DoResize() |
|
{ |
|
AppPreResize(); |
|
InitD3D(); |
|
AppPostResize(); |
|
CallAppRender( true ); |
|
} |
|
|
|
// |
|
// FUNCTION: InitInstance(HANDLE, int) |
|
// |
|
// PURPOSE: Saves instance handle and creates main window |
|
// |
|
// COMMENTS: |
|
// |
|
// In this function, we save the instance handle in a global variable and |
|
// create and display the main program window. |
|
// |
|
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) |
|
{ |
|
hInst = hInstance; // Store instance handle in our global variable |
|
|
|
int x = Sys_FindArgInt( "-x", 0 ); |
|
int y = Sys_FindArgInt( "-y", 0 ); |
|
int w = Sys_FindArgInt( "-width", CW_USEDEFAULT ); |
|
int h = Sys_FindArgInt( "-height", CW_USEDEFAULT ); |
|
|
|
DWORD dwFlags = WS_OVERLAPPEDWINDOW; |
|
|
|
// Get the 'work area' so we don't overlap the taskbar on the top or left. |
|
RECT rcWorkArea; |
|
SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWorkArea, 0 ); |
|
|
|
// If they don't specify anything, maximize the window. |
|
if( x == 0 && y == 0 && w == CW_USEDEFAULT && h == CW_USEDEFAULT ) |
|
{ |
|
x = rcWorkArea.left; |
|
y = rcWorkArea.top; |
|
w = rcWorkArea.right - rcWorkArea.left; |
|
h = rcWorkArea.bottom - rcWorkArea.top; |
|
dwFlags |= WS_MAXIMIZE; |
|
} |
|
else |
|
{ |
|
x += rcWorkArea.left; |
|
y += rcWorkArea.top; |
|
} |
|
|
|
|
|
g_hWnd = CreateWindow( |
|
szWindowClass, |
|
szTitle, |
|
dwFlags, // window style |
|
x, // x |
|
y, // y |
|
w, // width |
|
h, // height |
|
NULL, |
|
NULL, |
|
hInstance, |
|
NULL); |
|
|
|
if (!g_hWnd) |
|
{ |
|
return FALSE; |
|
} |
|
|
|
ShowWindow(g_hWnd, nCmdShow); |
|
UpdateWindow(g_hWnd); |
|
|
|
|
|
InitD3D(); |
|
AppInit(); |
|
|
|
// Reinitialize D3D. For some reason, D3D point primitives are way too large |
|
// unless we do this. |
|
DoResize(); |
|
|
|
return TRUE; |
|
} |
|
|
|
|
|
// |
|
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) |
|
// |
|
// PURPOSE: Processes messages for the main window. |
|
// |
|
// WM_COMMAND - process the application menu |
|
// WM_PAINT - Paint the main window |
|
// WM_DESTROY - post a quit message and return |
|
// |
|
// |
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (message) |
|
{ |
|
case WM_PAINT: |
|
{ |
|
PAINTSTRUCT ps; |
|
BeginPaint( hWnd, &ps ); |
|
EndPaint( hWnd, &ps ); |
|
|
|
if( g_pDevice ) |
|
CallAppRender( true ); |
|
} |
|
break; |
|
|
|
case WM_KEYDOWN: |
|
{ |
|
AppKey( (int)wParam, lParam&0xFFFF ); |
|
} |
|
break; |
|
|
|
case WM_KEYUP: |
|
{ |
|
AppKey( (int)wParam, 0 ); |
|
} |
|
break; |
|
|
|
case WM_CHAR: |
|
{ |
|
AppChar( (int)wParam ); |
|
} |
|
break; |
|
|
|
case WM_DESTROY: |
|
PostQuitMessage(0); |
|
break; |
|
|
|
case WM_LBUTTONDOWN: |
|
{ |
|
ShowCursor( FALSE ); |
|
SetCapture( g_hWnd ); |
|
g_nCapture++; |
|
} |
|
break; |
|
|
|
case WM_LBUTTONUP: |
|
{ |
|
ShowCursor( TRUE ); |
|
ReleaseCapture( ); |
|
g_nCapture--; |
|
} |
|
break; |
|
|
|
case WM_RBUTTONDOWN: |
|
{ |
|
ShowCursor( FALSE ); |
|
SetCapture( g_hWnd ); |
|
g_nCapture++; |
|
} |
|
break; |
|
|
|
case WM_RBUTTONUP: |
|
{ |
|
ShowCursor( TRUE ); |
|
ReleaseCapture( ); |
|
g_nCapture--; |
|
} |
|
break; |
|
|
|
case WM_SIZE: |
|
{ |
|
if( g_pDevice ) |
|
DoResize(); |
|
} |
|
break; |
|
|
|
case WM_SETFOCUS: |
|
{ |
|
g_bFocus = true; |
|
} |
|
break; |
|
|
|
case WM_KILLFOCUS: |
|
{ |
|
g_bFocus = false; |
|
} |
|
break; |
|
|
|
default: |
|
return DefWindowProc(hWnd, message, wParam, lParam); |
|
} |
|
return 0; |
|
} |
|
|
|
|
|
bool Sys_Error(const char *pMsg, ...) |
|
{ |
|
char msg[4096]; |
|
va_list marker; |
|
|
|
va_start( marker, pMsg ); |
|
V_vsprintf_safe( msg, pMsg, marker ); |
|
va_end( marker ); |
|
|
|
MessageBox( NULL, msg, "Error!", MB_OK ); |
|
exit(1); |
|
return true; |
|
} |
|
|
|
|
|
void Sys_Quit() |
|
{ |
|
PostQuitMessage( 0 ); |
|
} |
|
|
|
|
|
void Sys_SetWindowText( char const *pMsg, ... ) |
|
{ |
|
va_list marker; |
|
char msg[4096]; |
|
|
|
va_start(marker, pMsg); |
|
V_vsprintf_safe(msg, pMsg, marker); |
|
va_end(marker); |
|
|
|
SetWindowText( g_hWnd, msg ); |
|
} |
|
|
|
|
|
bool Sys_GetKeyState( int key ) |
|
{ |
|
int keyTranslations[][2] = |
|
{ |
|
{APPKEY_LBUTTON, VK_LBUTTON}, |
|
{APPKEY_RBUTTON, VK_RBUTTON}, |
|
{APPKEY_SPACE, VK_SPACE} |
|
}; |
|
int nKeyTranslations = sizeof(keyTranslations) / sizeof(keyTranslations[0]); |
|
|
|
for( int i=0; i < nKeyTranslations; i++ ) |
|
{ |
|
if( key == keyTranslations[i][0] ) |
|
{ |
|
key = keyTranslations[i][1]; |
|
break; |
|
} |
|
} |
|
|
|
return !!( GetAsyncKeyState( key ) & 0x8000 ); |
|
} |
|
|
|
|
|
void Sys_Sleep( int ms ) |
|
{ |
|
Sleep( (DWORD)ms ); |
|
} |
|
|
|
|
|
bool Sys_HasFocus() |
|
{ |
|
return g_bFocus; |
|
} |
|
|
|
|
|
char const* Sys_FindArg( char const *pArg, char const *pDefault ) |
|
{ |
|
for( int i=0; i < __argc; i++ ) |
|
{ |
|
if( stricmp( __argv[i], pArg ) == 0 ) |
|
return (i+1) < __argc ? __argv[i+1] : ""; |
|
} |
|
|
|
return pDefault; |
|
} |
|
|
|
|
|
int Sys_FindArgInt( char const *pArg, int defaultVal ) |
|
{ |
|
char const *pVal = Sys_FindArg( pArg, NULL ); |
|
if( pVal ) |
|
return atoi( pVal ); |
|
else |
|
return defaultVal; |
|
} |
|
|
|
|
|
int Sys_ScreenWidth() |
|
{ |
|
return g_ScreenWidth; |
|
} |
|
|
|
|
|
int Sys_ScreenHeight() |
|
{ |
|
return g_ScreenHeight; |
|
} |
|
|
|
|
|
|