VIEWER.CPP

/*========================================================================== 
*
* Copyright 1995 - 1998 Microsoft Corporation. All Rights Reserved.
*
* File: viewer.cpp
*
***************************************************************************/



#define INITGUID
#include "d3drmwin.h"
#include "resource.h"

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <direct.h>

#include "rlds3d.h"
#include "file.h"


static char ViewerClass[32] = "ViewerClass";

static BOOL FirstInstance(HINSTANCE);
static BOOL AnyInstance(HINSTANCE, HWND*);
long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM);
static void Idle();

BOOL CALLBACK WaitBoxDlgProc(HWND, UINT, WPARAM, LPARAM);

BOOL AboutBoxOn = FALSE;


/*
* Initialization, message loop
*/

int PASCAL WinMain
(HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline, int cmdshow)
{
MSG msg;
int idle;
int done = FALSE;
HACCEL accel;


DWORDprev_tick;
DWORDthis_tick;
D3DVALUEtime_delta;

prev_inst = prev_inst;
cmdline = cmdline;

// Register our class if necessary
if (!prev_inst) {
// Do the stuff for if this is the first instance of the program.
if (!FirstInstance(this_inst)) return FALSE;
}

// Create our window and get it's handle (needs to be done whether we're first or not)
HWND win;
if (!AnyInstance(this_inst, &win)) return FALSE;

// Initialize the RLDS3D interface
if (!RLDS3D_Initialize(win, this_inst)) {
// If it doesn't initialize then we don't have anything we need to clean up, so we just exit
exit(-1);
}

// Show our window!
ShowWindow(win, cmdshow);
UpdateWindow(win);

// Load accelerators
accel = LoadAccelerators(this_inst, "ViewerAccel");

prev_tick = timeGetTime();


while (!done)
{ idle = TRUE;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{ idle = FALSE;
if (msg.message == WM_QUIT)
{ done = TRUE;
break;
}

if (!TranslateAccelerator(msg.hwnd, accel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

}
if (idle) Idle();
this_tick = timeGetTime();
time_delta = D3DVAL((float)((this_tick - prev_tick)/1000.0));
prev_tick = this_tick;
RLDS3D_Render(time_delta);
}
RLDS3D_Deinitialize();
return msg.wParam;
}

/*
* Register window class for the application, and do any other
* application initialization
*/
static BOOL FirstInstance(HINSTANCE this_inst)
{
WNDCLASS wc;
BOOL rc;

/*
* set up and register window class
*/
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = this_inst;
wc.hIcon = LoadIcon(this_inst, "ViewerIcon");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "ViewerMenu";
wc.lpszClassName = ViewerClass;
rc = RegisterClass(&wc);

return rc;
}

/*
* Do work required for every instance of the application:
* create the window, initialize data
*/
static BOOL AnyInstance(HINSTANCE this_inst, HWND* window_handle)
{
HWND win;
char szCaption[] = "DirectSound3D Demo";

/*
* create main window
*/
win =
CreateWindow
( ViewerClass, /* class */
szCaption, /* caption */
WS_OVERLAPPEDWINDOW, /* style */
CW_USEDEFAULT, /* init. x pos */
CW_USEDEFAULT, /* init. y pos */
400, /* init. x size */
400, /* init. y size */
NULL, /* parent window */
NULL, /* menu handle */
this_inst, /* program handle */
NULL /* create parms */
);


if (!win) return FALSE;
*window_handle = win;
return TRUE;
}

/*
* Processes messages for the about dialog.
*/
BOOL WINAPI AboutDlgProc
(HWND win, unsigned msg, WPARAM wparam, LPARAM lparam)
{
lparam = lparam;

switch (msg)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
if (wparam == IDOK)
{
AboutBoxOn = FALSE;
EndDialog(win, TRUE);
return TRUE;
}
break;
case WM_CLOSE:
{
AboutBoxOn = FALSE;
EndDialog(win, TRUE);
return FALSE;
}
break;
}
return FALSE;
}

static int
left_drag = FALSE, right_drag = FALSE,
last_x, last_y;

static void Idle()
{
// Stop selected item being dragged from rotating/moving
if (left_drag) {
RLDS3D_SetSelectedRotRelToCam(D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0));
}
if (right_drag) {
RLDS3D_SetSelectedVelRelToCam(D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
}
}

static int FillModeToMenuItem(D3DRMFILLMODE fm)
{
switch (fm) {
case D3DRMFILL_POINTS:
return 2;

case D3DRMFILL_WIREFRAME:
return 3;

case D3DRMFILL_SOLID:
return 4;
}
return -1;
}

// Sets the polygon fill mode and checks/unchecks the appropriate menu items
static void SetFillMode(HWND win, D3DRMFILLMODE fm)
{
HMENU menu;
D3DRMFILLMODE oldfm = RLDS3D_GetPolygonFillMode();
menu = GetMenu(win);
menu = GetSubMenu(menu, 2);
CheckMenuItem(menu, FillModeToMenuItem(oldfm),
MF_BYPOSITION|MF_UNCHECKED);
CheckMenuItem(menu, FillModeToMenuItem(fm),
MF_BYPOSITION|MF_CHECKED);
RLDS3D_SetPolygonFillMode(fm);
}

static int ShadeModeToMenuItem(D3DRMSHADEMODE sm)
{
switch (sm) {
case D3DRMSHADE_FLAT:
return 6;

case D3DRMSHADE_GOURAUD:
return 7;

case D3DRMSHADE_PHONG:
return 8;
}
return -1;
}

// Sets the polygon shade mode and checks/unchecks the appropriate menu items
static void SetShadeMode(HWND win, D3DRMSHADEMODE sm)
{
HMENU menu;
D3DRMSHADEMODE oldsm = RLDS3D_GetPolygonShadeMode();

menu = GetMenu(win);
menu = GetSubMenu(menu, 2);
CheckMenuItem(menu, ShadeModeToMenuItem(oldsm),
MF_BYPOSITION|MF_UNCHECKED);
CheckMenuItem(menu, ShadeModeToMenuItem(sm),
MF_BYPOSITION|MF_CHECKED);
RLDS3D_SetPolygonShadeMode(sm);
}

// Sets the rendering model and checks/unchecks the appropriate menu items
static void SetModel(HWND win, D3DRMCOLORMODEL model)
{
HMENU menu;
D3DRMCOLORMODEL oldModel = RLDS3D_GetColourModel();

if (oldModel == model) return;

RLDS3D_SetColourModel(model);

menu = GetMenu(win);
menu = GetSubMenu(menu, 2);
CheckMenuItem(menu, 9 + (int) oldModel, MF_BYPOSITION|MF_UNCHECKED);
CheckMenuItem(menu, 9 + (int) model, MF_BYPOSITION|MF_CHECKED);
}

// Toggles dithering and checks/unchecks menu item
static void ToggleDither(HWND win)
{
HMENU menu;
int dither = RLDS3D_GetDither();
int checked;
dither = !dither;
RLDS3D_SetDither(dither);

menu = GetMenu(win);
menu = GetSubMenu(menu, 2);

if (dither) checked = MF_CHECKED;
else checked = MF_UNCHECKED;

CheckMenuItem(menu, 13, MF_BYPOSITION|checked);
}

// Toggles texture filtering and checks/unchecks menu item
static void ToggleTextureFiltering(HWND win)
{
HMENU menu;
D3DRMTEXTUREQUALITY tq = RLDS3D_GetTextureQuality();
int checked;
if (tq == D3DRMTEXTURE_NEAREST)
tq = D3DRMTEXTURE_LINEAR;
else
tq = D3DRMTEXTURE_NEAREST;

RLDS3D_SetTextureQuality(tq);
menu = GetMenu(win);
menu = GetSubMenu(menu, 2);

if (tq == D3DRMTEXTURE_LINEAR) checked = MF_CHECKED;
else checked = MF_UNCHECKED;

CheckMenuItem(menu, 14, MF_BYPOSITION|checked);
}

// Ditto for lighting
static void ToggleLighting(HWND win)
{
HMENU menu;
menu = GetMenu(win);
menu = GetSubMenu(menu, 2);
if (RLDS3D_GetLighting()) {
CheckMenuItem(menu, 0, (MF_BYPOSITION | MF_UNCHECKED));
RLDS3D_SetLighting(FALSE);
}
else {
CheckMenuItem(menu, 0, (MF_BYPOSITION | MF_CHECKED));
RLDS3D_SetLighting(TRUE);
}
}

/*
** Windows procs for the sound param dlg boxes
*/

BOOL CALLBACK WaitBoxDlgProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam) {
return FALSE;
};

BOOL CALLBACK GlobalParamDlgProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam)
{
lparam = lparam;

char lpszTS[100];

switch (msg)
{
case WM_INITDIALOG:
{
// Set up our edit fields appropriately
D3DVALUE temp;
RLDS3D_GetDistanceFactor(&temp);
sprintf(lpszTS, "%f",temp);
SendDlgItemMessage(win, IDC_DISTANCEFACTOR, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_DISTANCEFACTOR, EM_SETLIMITTEXT, 10, 0);
RLDS3D_GetRolloffFactor(&temp);
sprintf(lpszTS, "%f",temp);
SendDlgItemMessage(win, IDC_ROLLOFFFACTOR, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_ROLLOFFFACTOR, EM_SETLIMITTEXT, 10, 0);
RLDS3D_GetDopplerFactor(&temp);
sprintf(lpszTS, "%f",temp);
SendDlgItemMessage(win, IDC_DOPPLERFACTOR, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_DOPPLERFACTOR, EM_SETLIMITTEXT, 10, 0);
return TRUE;
}
case WM_CLOSE:
EndDialog(win, TRUE);
return FALSE;

case WM_COMMAND:
{
if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_DOPPLERFACTOR) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_DOPPLERFACTOR, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_DOPPLERFACTOR, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
// No real need for error checking 'cause the edit field is numbers only
RLDS3D_SetDopplerFactor(D3DVAL(atof(lpszTS)));
return TRUE;
}
else if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_ROLLOFFFACTOR) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_ROLLOFFFACTOR, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_ROLLOFFFACTOR, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
RLDS3D_SetRolloffFactor(D3DVAL(atof(lpszTS)));
return TRUE;
}
else if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_DISTANCEFACTOR) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_DISTANCEFACTOR, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_DISTANCEFACTOR, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
RLDS3D_SetDistanceFactor(D3DVAL(atof(lpszTS)));
return TRUE;
}
else return FALSE;
}
break;
}
return FALSE;
}

HWND hSelCfgDlg = 0;

BOOL CALLBACK SelectedParamDlgProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam)
{
lparam = lparam;

char lpszTS[100];

switch (msg)
{
case WM_INITDIALOG:
{
// Set up our edit fields appropriately
D3DVALUE temp;
LONG temp2;
DWORD temp3, temp4;
// Ignores the out side cone angle for now, which is fine, because elsewhere we
// set it to equal the inside angle
RLDS3D_GetSelConeAngles(&temp3, &temp4);
sprintf(lpszTS, "%i",temp3);
SendDlgItemMessage(win, IDC_CONEANGLE, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_CONEANGLE, EM_SETLIMITTEXT, 10, 0);
RLDS3D_GetSelConeOutsideVolume(&temp2);
sprintf(lpszTS, "%i",temp2);
SendDlgItemMessage(win, IDC_CONEOUTSIDEVOLUME, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_CONEOUTSIDEVOLUME, EM_SETLIMITTEXT, 10, 0);
RLDS3D_GetSelMaximumDistance(&temp);
sprintf(lpszTS, "%f",temp);
SendDlgItemMessage(win, IDC_MAXIMUMDISTANCE, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_MAXIMUMDISTANCE, EM_SETLIMITTEXT, 10, 0);
RLDS3D_GetSelMinimumDistance(&temp);
sprintf(lpszTS, "%f",temp);
SendDlgItemMessage(win, IDC_MINIMUMDISTANCE, WM_SETTEXT, 0, (LPARAM) lpszTS);
SendDlgItemMessage(win, IDC_MINIMUMDISTANCE, EM_SETLIMITTEXT, 10, 0);
hSelCfgDlg = win;
return TRUE;
}

case WM_CLOSE:
EndDialog(win, TRUE);
hSelCfgDlg = 0;
return FALSE;

case WM_COMMAND:
{
if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_CONEANGLE) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_CONEANGLE, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_CONEANGLE, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
// No real need for error checking 'cause the edit field is numbers only
RLDS3D_SetSelConeAngles((DWORD)atol(lpszTS), (DWORD)atol(lpszTS));
return TRUE;
}
else if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_CONEOUTSIDEVOLUME) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_CONEOUTSIDEVOLUME, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_CONEOUTSIDEVOLUME, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
RLDS3D_SetSelConeOutsideVolume(atol(lpszTS));
return TRUE;
}
else if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_MAXIMUMDISTANCE) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_MAXIMUMDISTANCE, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_MAXIMUMDISTANCE, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
RLDS3D_SetSelMaximumDistance(D3DVAL(atof(lpszTS)));
return TRUE;
}
else if (HIWORD(wparam) == EN_UPDATE && LOWORD(wparam) == IDC_MINIMUMDISTANCE) {
// Get value from edit box (get length, check lenth, set first char to length, request string, end it with 0)
int stringlength = SendDlgItemMessage(win, IDC_MINIMUMDISTANCE, EM_LINELENGTH, 0, 0);
if (stringlength > 10) return TRUE;
lpszTS[0] = (char)stringlength;
SendDlgItemMessage(win, IDC_MINIMUMDISTANCE, EM_GETLINE, 0, (LPARAM) lpszTS);
lpszTS[stringlength] = 0;
// Set value in RLDS3D (convert string to long and go crazy with the bad boy)
RLDS3D_SetSelMinimumDistance(D3DVAL(atof(lpszTS)));
return TRUE;
}
else return FALSE;
}
break;
}
return FALSE;
}

#define SIGN_EXTEND(w) ((((int)(w)) << 16) >> 16)

/*
* Handle messages for the main application window
*/

LONG FAR PASCAL WindowProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam)
{
HINSTANCE inst_handle;
static HCURSOR oldCursor = NULL;

switch (msg)
{
case WM_KEYDOWN:
{
switch (wparam)
{

case 'A':
RLDS3D_SetCamVelRelToCam(D3DVAL(5.0), D3DVAL(0.0), D3DVAL(0.0));
break;

case 'Z':
RLDS3D_SetCamVelRelToCam(D3DVAL(-5.0), D3DVAL(0.0), D3DVAL(0.0));
break;

case VK_RIGHT:
RLDS3D_SetCamRotUp(D3DVAL(1.0));
break;
case VK_LEFT:
RLDS3D_SetCamRotUp(D3DVAL(-1.0));
break;
case VK_UP:
RLDS3D_SetCamRotRight(D3DVAL(1.0));
break;
case VK_DOWN:
RLDS3D_SetCamRotRight(D3DVAL(-1.0));
break;
}
}
break;

case WM_KEYUP:
switch (wparam)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
// Stop the camera from rotating completely
RLDS3D_SetCamRotForward(D3DVAL(0.0));
break;

case 'A':
case 'Z':
RLDS3D_SetCamVelRelToCam(D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
break;
}
break;

case WM_LBUTTONDOWN:
{ HCURSOR hCur;
int x = LOWORD(lparam);
int y = HIWORD(lparam);
last_x = x;
last_y = y;
BOOL bChanged = FALSE;
RLDS3D_FindAndSelectVisual(x, y, &bChanged);
// Get rid of the Selected Object Cfg dialog if we've selected a new object
if (bChanged && hSelCfgDlg) EndDialog(hSelCfgDlg, TRUE);
left_drag = TRUE;
SetCapture(win);
/* change to a groovy cursor */
hCur = LoadCursor(NULL, IDC_ARROW);
if (hCur) oldCursor = SetCursor(hCur);
else oldCursor = NULL;
}
break;

case WM_LBUTTONUP:
ReleaseCapture();
left_drag = FALSE;
if (oldCursor) SetCursor(oldCursor);
break;

case WM_RBUTTONDOWN:
{
HCURSOR hCur;
int x = LOWORD(lparam);
int y = HIWORD(lparam);
last_x = x;
last_y = y;
BOOL bChanged = FALSE;
RLDS3D_FindAndSelectVisual(x, y, &bChanged);
// Get rid of the Selected Object Cfg dialog if we've selected a new object
if (bChanged && hSelCfgDlg) EndDialog(hSelCfgDlg, TRUE);
right_drag = TRUE;
SetCapture(win);
/* change to a groovy cursor */
hCur = LoadCursor(NULL, IDC_ARROW);
if (hCur) oldCursor = SetCursor(hCur);
else oldCursor = NULL;
}
break;

case WM_RBUTTONUP:
right_drag = FALSE;
ReleaseCapture();
if (oldCursor) SetCursor(oldCursor);
break;

case WM_MOUSEMOVE:
if ((wparam & MK_LBUTTON) && left_drag)
{ double delta_x, delta_y;
delta_x = SIGN_EXTEND(LOWORD(lparam)) - last_x;
delta_y = -SIGN_EXTEND((HIWORD(lparam)) - last_y);
last_x = SIGN_EXTEND(LOWORD(lparam));
last_y = SIGN_EXTEND(HIWORD(lparam));
{
double delta_r = sqrt(delta_x * delta_x + delta_y * delta_y);
double radius = 50;
double denom;

denom = 0.05 * sqrt(radius * radius + delta_r * delta_r);

if (delta_r == 0 || denom == 0) break;
RLDS3D_SetSelectedRotRelToCam(D3DDivide(D3DVAL((float) delta_y), D3DVAL((float) delta_r)),
D3DDivide(D3DVAL((float) -delta_x), D3DVAL((float) delta_r)),
D3DVAL(0.0),
D3DDivide(D3DVAL((float) delta_r), D3DVAL((float) denom)));
}
}
else if ((wparam & MK_RBUTTON) && right_drag)
{ double delta_x, delta_y;

delta_x = SIGN_EXTEND(LOWORD(lparam)) - last_x;
delta_y = SIGN_EXTEND(HIWORD(lparam)) - last_y;
last_x = SIGN_EXTEND(LOWORD(lparam));
last_y = SIGN_EXTEND(HIWORD(lparam));
RLDS3D_MoveSelectedPosByScreenCoords(delta_x, delta_y);
}
break;
case WM_COMMAND:
switch( wparam & 0xffff )
{
case MENU_MOTION_ORBITSELECTEDOBJECT:
{
RLDS3D_OrbitSelected();
}
break;
case MENU_MOTION_BULLETSELECTEDOBJECT:
{
RLDS3D_BulletSelected();
}
break;
case MENU_SOUND_ATTACHSOUND:
{
if (RLDS3D_SoundInitialized())
{
if (RLDS3D_FrameSelected()) {
char* file = OpenNewSoundFile(win);
if (file) RLDS3D_AttachSound(file);
}
else MessageBox(win, "No object selected to attach a sound to!", "Doh!", MB_ICONEXCLAMATION);
}
else MessageBox(win, "Sound not initialized!", "Doh!", MB_ICONEXCLAMATION);
}
break;
case MENU_SOUND_REMOVESOUND:
RLDS3D_RemoveSound();
break;
case MENU_SOUND_REMOVEALLSOUNDS:
RLDS3D_RemoveAllSounds();
break;

case MENU_SOUND_PLAYSOUND:
RLDS3D_PlaySound(FALSE);
break;
case MENU_SOUND_PLAYSOUNDLOOPING:
RLDS3D_PlaySound(TRUE);
break;
case MENU_SOUND_STOPSOUND:
RLDS3D_StopSelectedSound();
break;

case MENU_SOUND_STOPALLSOUNDS:
RLDS3D_StopAllSounds();
break;

case MENU_SOUND_SELECTEDSOUNDPROPERTIES:
{
if (RLDS3D_SoundInitialized()) {
if (RLDS3D_SoundSelected()) {
inst_handle = (HINSTANCE) GetWindowLong(win, GWL_HINSTANCE);
HWND mydial = CreateDialog(inst_handle, "SelectedParamBox", win, SelectedParamDlgProc);
if (mydial) {
ShowWindow(mydial, SW_SHOW);
UpdateWindow(mydial);
}
}
else MessageBox(win, "No sound currently selected", "Doh!", MB_ICONEXCLAMATION);
}
else MessageBox(win, "Sound not initialized!", "Doh!", MB_ICONEXCLAMATION);
}
break;
case MENU_SOUND_GLOBALPROPERTIES:
{
if (RLDS3D_SoundInitialized()) {
inst_handle = (HINSTANCE) GetWindowLong(win, GWL_HINSTANCE);
HWND mydial = CreateDialog(inst_handle, "GlobalParamBox", win, GlobalParamDlgProc);
if (mydial) {
ShowWindow(mydial, SW_SHOW);
UpdateWindow(mydial);
}
}
else MessageBox(win, "Sound not initialized!", "Doh!", MB_ICONEXCLAMATION);
}
break;

case MENU_FILE_ABOUT:
{
inst_handle = (HINSTANCE) GetWindowLong(win, GWL_HINSTANCE);
DialogBox(inst_handle,"AboutBox", win, AboutDlgProc);
}
break;

case MENU_FILE_OPEN:
{
char *file = OpenNewFile(win);
if (file) {
RLDS3D_LoadXOF(file);
}
}
break;

case MENU_FILE_EXIT:
PostQuitMessage(0);
break;

case MENU_EDIT_CUT:
RLDS3D_CutVisual();
break;

case MENU_EDIT_COPY:
RLDS3D_CopyVisual();
break;

case MENU_EDIT_PASTE:
RLDS3D_PasteVisual();
break;

case MENU_EDIT_DELETE:
RLDS3D_DeleteVisual();
break;

case MENU_EDIT_COLOUR:
// Currently everything is handled there but the selection wheel maybe should be out here?
RLDS3D_SetSelColour();
break;

case MENU_EDIT_BOXES:
{
HMENU menu;
if (RLDS3D_GetBoxes() == TRUE) RLDS3D_SetBoxes(FALSE); else RLDS3D_SetBoxes(TRUE);
int checked = (RLDS3D_GetBoxes()==TRUE) ? MF_CHECKED : MF_UNCHECKED;
menu = GetMenu(win);
menu = GetSubMenu(menu, 1);
CheckMenuItem(menu, MENU_EDIT_BOXES, MF_BYCOMMAND|checked);
}
break;

case MENU_QUALITY_LIGHTING:
ToggleLighting(win);
break;

// Fill Modes
case MENU_QUALITY_POINTS:
SetFillMode(win, D3DRMFILL_POINTS);
break;

case MENU_QUALITY_WIREFRAME:
SetFillMode(win, D3DRMFILL_WIREFRAME);
break;

case MENU_QUALITY_SOLID:
SetFillMode(win, D3DRMFILL_SOLID);
break;

// Shading modes
case MENU_QUALITY_FLAT:
SetShadeMode(win, D3DRMSHADE_FLAT);
break;

case MENU_QUALITY_GOURAUD:
SetShadeMode(win, D3DRMSHADE_GOURAUD);
break;

case MENU_QUALITY_PHONG:
SetShadeMode(win, D3DRMSHADE_PHONG);
break;

// Color models
case MENU_MODEL_MONO:
SetModel(win, D3DCOLOR_MONO);
break;

case MENU_MODEL_RGB:
SetModel(win, D3DCOLOR_RGB);
break;

case MENU_DITHER:
ToggleDither(win);
break;

case MENU_TEXTURE_FILTERING:
ToggleTextureFiltering(win);
break;

case MENU_LIGHT_DIRECTIONAL:
RLDS3D_AddDirectionalLight();
break;
case MENU_LIGHT_PARALLEL_POINT:
RLDS3D_AddParallelPointLight();
break;
case MENU_LIGHT_POINT:
RLDS3D_AddPointLight();
break;
case MENU_LIGHT_SPOT:
RLDS3D_AddSpotlight();
break;
}
break;

case WM_DESTROY:
PostQuitMessage( 0 );
break;

case WM_SIZE:
{
int width = LOWORD(lparam);
int height = HIWORD(lparam);
RLDS3D_ResizeViewport(width, height);
}
break;

case WM_ACTIVATE:
{
RLDS3D_HandleActivate(wparam);
}
break;

case WM_PAINT:
if (RLDS3D_WinDevice())
{
RECT r;
PAINTSTRUCT ps;

if (GetUpdateRect(win, &r, FALSE))
{ BeginPaint(win, &ps);
RLDS3D_HandlePaint(&ps);
EndPaint(win, &ps);
}
}
else return DefWindowProc(win, msg, wparam, lparam);

default:
return DefWindowProc(win, msg, wparam, lparam);
}
return 0L;
}