windows-nt/Source/XPSP1/NT/multimedia/opengl/scrsave/maze/dialog.cxx
2020-09-26 16:20:57 +08:00

813 lines
23 KiB
C++

/******************************Module*Header*******************************\
* Module Name: dialog.cxx
*
* Dialog box functions
*
* Created: 11-16-95 -by- Marc Fortier [marcfo]
*
* Copyright (c) 1995 Microsoft Corporation
\**************************************************************************/
#include "pch.c"
#pragma hdrstop
#include <commdlg.h>
#include <commctrl.h>
#include <scrnsave.h>
#include "mazedlg.h"
#include "sscommon.hxx"
// Global string buffers for message box.
// local funtions
static void updateDialogControls(HWND hDlg);
HWND ghDlg; // main dialog window handle
int giSize;
int giImageQual;
BOOL gbTurboMode;
int gnBitsPerPixel;
static void DrawTexture( int surface );
static void CleanUp( HWND hwnd );
// Texture information for each surface: used in both configure and run mode
TEX_INFO gTexInfo[NUM_SURFACES] = {0};
// default surface texture cache
static TEXTURE gDefTex[NUM_DEF_SURFACE_TEXTURES] = {0};
// Per-surface texture information relevant only to configure mode
typedef struct {
TEXTURE userTex;
int iDefTex;
int defTexIDS;
int fileIDS;
int offsetIDS;
int dlgSpinTexID;
int iPalRot; // texture palette rotation index
SS_TEX_BUTTON *pTexBtn; // GL texture drawing button thing
} TEX_DLG;
static TEX_DLG gTex[NUM_SURFACES] = {
{
{0},
BRICK_TEXTURE,
IDS_DEF_WALL_TEXTURE,
IDS_WALL_TEXTURE_FILE,
IDS_WALL_TEXTURE_OFFSET,
DLG_SPIN_WALLS,
NULL
},
{
{0},
WOOD_TEXTURE,
IDS_DEF_FLOOR_TEXTURE,
IDS_FLOOR_TEXTURE_FILE,
IDS_FLOOR_TEXTURE_OFFSET,
DLG_SPIN_FLOOR,
NULL
},
{
{0},
CASTLE_TEXTURE,
IDS_DEF_CEILING_TEXTURE,
IDS_CEILING_TEXTURE_FILE,
IDS_CEILING_TEXTURE_OFFSET,
DLG_SPIN_CEILING,
NULL
}
};
static UINT idTimer = 0;
static BOOL CALLBACK TextureConfigureDialog(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam);
/******************************Public*Routine******************************\
* getIniSettings
*
* - Get the screen saver configuration options from .INI file/registry.
* - Called by both dialog box and screen saver
*
* History:
* Nov. 95 [marcfo]
* - Creation
*
\**************************************************************************/
void
getIniSettings()
{
int option;
int i;
// Load resources
LoadString(hMainInstance, IDS_GENNAME, szScreenSaver,
sizeof(szScreenSaver) / sizeof(TCHAR));
// Get registry settings
if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) )
{
// get wall/floor/ceiling texture enables
// For now, texturing always on
for( i = 0; i < NUM_SURFACES; i++ )
gTexInfo[i].bTex = TRUE;
option = ss_GetRegistryInt( IDS_DEFAULT_TEXTURE_ENABLE, (1 << NUM_SURFACES)-1 );
for( i = 0; i < NUM_SURFACES; i++, option >>= 1 )
gTexInfo[i].bDefTex = option & 1;
// get default texture indices
for( i = 0; i < NUM_SURFACES; i++ ) {
gTexInfo[i].iDefTex =
ss_GetRegistryInt( gTex[i].defTexIDS, gTex[i].iDefTex );
SS_CLAMP_TO_RANGE2( gTexInfo[i].iDefTex, 0,
NUM_DEF_SURFACE_TEXTURES-1 );
}
// get user texture files
for( i = 0; i < NUM_SURFACES; i++ ) {
ss_GetRegistryString( gTex[i].fileIDS, 0,
gTexInfo[i].texFile.szPathName, MAX_PATH);
gTexInfo[i].texFile.nOffset = ss_GetRegistryInt( gTex[i].offsetIDS, 0 );
}
// get overlay
maze_options.top_view = ss_GetRegistryInt( IDS_OVERLAY, 0 );
// Get rat population
maze_options.nrats = ss_GetRegistryInt(IDS_NRATS, 1);
// get image quality
giImageQual = ss_GetRegistryInt( IDS_IMAGEQUAL, IMAGEQUAL_DEFAULT );
SS_CLAMP_TO_RANGE2( giImageQual, IMAGEQUAL_DEFAULT, IMAGEQUAL_HIGH );
// get size
giSize = ss_GetRegistryInt( IDS_SIZE, 0 );
SS_CLAMP_TO_RANGE2( giSize, MIN_SLIDER, MAX_SLIDER );
// get turbo mode
gbTurboMode = ss_GetRegistryInt( IDS_TURBOMODE, 1 );
}
}
/******************************Public*Routine******************************\
* saveIniSettings
*
* Save the screen saver configuration option to the .INI file/registry.
*
* History:
* Nov. 95 [marcfo]
* - Creation
\**************************************************************************/
static void
saveIniSettings(HWND hDlg)
{
if( ss_RegistrySetup( hMainInstance, IDS_SAVERNAME, IDS_INIFILE ) )
{
int i, option = 0;
// write enables
for( i = NUM_SURFACES-1, option = 0; i >= 0; i--, option <<= 1 )
option |= gTexInfo[i].bDefTex & 1;
ss_WriteRegistryInt( IDS_DEFAULT_TEXTURE_ENABLE, option >>= 1 );
// Write default texture indices
for( i = 0; i < NUM_SURFACES; i++ ) {
ss_WriteRegistryInt( gTex[i].defTexIDS, gTexInfo[i].iDefTex );
}
// write user texture files
for( i = 0; i < NUM_SURFACES; i++ ) {
ss_WriteRegistryString( gTex[i].fileIDS,
gTexInfo[i].texFile.szPathName );
ss_WriteRegistryInt( gTex[i].offsetIDS, gTexInfo[i].texFile.nOffset);
}
// write size
ss_WriteRegistryInt( IDS_SIZE,
ss_GetTrackbarPos(hDlg, DLG_SLIDER_SIZE) );
// write overlay enable
ss_WriteRegistryInt( IDS_OVERLAY, maze_options.top_view );
// Write rat population
ss_WriteRegistryInt( IDS_NRATS, maze_options.nrats );
// write image quality
ss_WriteRegistryInt( IDS_IMAGEQUAL, giImageQual );
// turbot mod
ss_WriteRegistryInt( IDS_TURBOMODE, gbTurboMode );
}
}
/******************************Public*Routine******************************\
* setupDialogControls
*
* Do initial setup of dialog controls.
*
* History:
* Nov. 95 [marcfo]
* - Creation
\**************************************************************************/
static void
setupDialogControls(HWND hDlg)
{
int i;
int idsImageQual;
TCHAR szStr[GEN_STRING_SIZE];
InitCommonControls();
// setup size slider
ss_SetupTrackbar( hDlg, DLG_SLIDER_SIZE, MIN_SLIDER, MAX_SLIDER, 1, 9,
giSize );
// setup default texture spins
for( i = 0; i < NUM_SURFACES; i ++ ) {
SendDlgItemMessage( hDlg, gTex[i].dlgSpinTexID, UDM_SETRANGE, 0,
MAKELONG(NUM_DEF_SURFACE_TEXTURES-1, 0) );
SendDlgItemMessage( hDlg, gTex[i].dlgSpinTexID, UDM_SETPOS, 0,
MAKELONG(gTexInfo[i].iDefTex, 0) );
}
// setup image quality combo box
idsImageQual = IDS_IMAGEQUAL_DEFAULT;
for( i = 0; i < IMAGEQUAL_COUNT; i++, idsImageQual++ ) {
LoadString(hMainInstance, idsImageQual, szStr,
GEN_STRING_SIZE);
SendDlgItemMessage(hDlg, DLG_COMBO_IMAGEQUAL, CB_ADDSTRING, 0,
(LPARAM) szStr);
}
SendDlgItemMessage(hDlg, DLG_COMBO_IMAGEQUAL, CB_SETCURSEL,
giImageQual, 0);
// Disable Quality box when running on > 16 bits per pixel (since it only
// affects dithering)
gnBitsPerPixel = GetDeviceCaps( GetDC(hDlg), BITSPIXEL );
EnableWindow( GetDlgItem(hDlg, DLG_COMBO_IMAGEQUAL), gnBitsPerPixel <= 16 );
EnableWindow( GetDlgItem(hDlg, IDC_STATIC_IMAGEQUAL), gnBitsPerPixel <= 16 );
// set palette rotation index for each surface for a8 textures
for( i = 0; i < NUM_SURFACES; i ++ )
gTex[i].iPalRot = ss_iRand(0xff);
// set state of other controls
CheckDlgButton(hDlg, DLG_CHECK_OVERLAY, maze_options.top_view );
CheckDlgButton(hDlg, DLG_CHECK_TURBOMODE, gbTurboMode );
updateDialogControls(hDlg);
}
/******************************Public*Routine******************************\
* updateDialogControls
*
* Updates dialog controls according to current state
*
* History:
* Nov. 95 [marcfo]
* - Creation
\**************************************************************************/
static void
updateDialogControls(HWND hDlg)
{
int i;
BOOL bDither;
static int dlgSpinTexDef[NUM_SURFACES] = {
DLG_SPIN_WALLS,
DLG_SPIN_FLOOR,
DLG_SPIN_CEILING};
for( i = 0; i < NUM_SURFACES; i ++ ) {
EnableWindow( GetDlgItem(hDlg, gTex[i].dlgSpinTexID), gTexInfo[i].bDefTex );
}
EnableWindow( GetDlgItem(hDlg, DLG_SLIDER_SIZE), !gbTurboMode );
EnableWindow( GetDlgItem(hDlg, IDC_STATIC_SIZE), !gbTurboMode );
EnableWindow( GetDlgItem(hDlg, IDC_STATIC_MIN), !gbTurboMode );
EnableWindow( GetDlgItem(hDlg, IDC_STATIC_MAX), !gbTurboMode );
// Dithering looks bad with turbo mode on and 8 bits/pixel
bDither = (gnBitsPerPixel <= 16) && !gbTurboMode;
EnableWindow( GetDlgItem(hDlg, DLG_COMBO_IMAGEQUAL), bDither );
EnableWindow( GetDlgItem(hDlg, IDC_STATIC_IMAGEQUAL), bDither );
}
/******************************Public*Routine******************************\
* updateGLState
*
\**************************************************************************/
static void
updateGLState()
{
if( (giImageQual == IMAGEQUAL_DEFAULT) || gbTurboMode )
glDisable( GL_DITHER );
else
glEnable( GL_DITHER );
}
/******************************Public*Routine******************************\
* ValidateTexture
*
*
\**************************************************************************/
static TEXTURE *
ValidateTexture( int surface )
{
TEXTURE *pTex = NULL;
TEX_INFO *pTexInfo = &gTexInfo[surface];
extern TEX_RES gTexResSurf[]; // from glmaze.c
if( !pTexInfo->bDefTex ) {
// Try to draw user texture
pTex = &gTex[surface].userTex;
if( !pTex->data ) {
// Load user texture - this can fail!
// If nOffset = 0, we assume user has never specified a texture,
// so we silently switch to the default texture.
// If the load of user texture fails, we use default texture
if( (pTexInfo->texFile.nOffset == 0) ||
(! ss_LoadTextureFile( &pTexInfo->texFile, pTex )) ) {
pTexInfo->bDefTex = TRUE; // draw default texture resource
// Enable the spin control
EnableWindow( GetDlgItem(ghDlg, gTex[surface].dlgSpinTexID),
TRUE );
}
}
}
if( pTexInfo->bDefTex ) {
// Draw default texture resource
pTex = &gDefTex[pTexInfo->iDefTex];
if( !pTex->data ) {
if( !ss_LoadTextureResource( &gTexResSurf[pTexInfo->iDefTex], pTex ))
pTex = NULL;
}
}
return pTex;
}
/******************************Public*Routine******************************\
* DrawTextures
*
* Draw all the textures
*
\**************************************************************************/
static void
DrawTextures()
{
for( int i = 0; i < NUM_SURFACES; i++ ) {
DrawTexture( i );
}
}
/******************************Public*Routine******************************\
* DrawTexture
*
* Draw appropriate texture in supplied window (e.g. a button)
* - Use TEX_INFO state to determine texture
* - Load texture if not in cache
*
\**************************************************************************/
static void
DrawTexture( int surface )
{
TEXTURE *pTex;
// Make sure valid texture loaded for this surface
if( ! (pTex = ValidateTexture( surface )) )
return;
SS_TEX_BUTTON *pTexBtn = gTex[surface].pTexBtn;
// pTexBtn never NULL, else ss_ConfigInit fails
// If palette rotation for this texture, slam in the current rotation,
// to be used by pTexBtn->Draw
if( pTex->pal )
pTex->iPalRot = gTex[surface].iPalRot;
pTexBtn->Draw( pTex );
}
/******************************Public*Routine******************************\
* RegisterDialogClasses
*
\**************************************************************************/
BOOL WINAPI RegisterDialogClasses(HANDLE hinst)
{
return TRUE;
}
/******************************Public*Routine******************************\
* HandlePreviewDraw
*
* History:
* Dec. 95 [marcfo]
* - Creation
\**************************************************************************/
static BOOL
HandlePreviewDraw( UINT idCtl, LPDRAWITEMSTRUCT lpdis )
{
int surface = DLG_PREVIEW_TO_SURFACE( idCtl );
if( lpdis->itemAction == ODA_DRAWENTIRE ) {
DrawTexture( surface );
return TRUE;
}
return FALSE;
}
/******************************Public*Routine******************************\
* HandleTexButtonNewTexture
*
* - Handle when a user selects a new texture
*
* If the new texture fails to load (unlikely, since we validate a good chunk
* of it with the selection dialog), then the current default texture is
* used.
\**************************************************************************/
static void
HandleTexButtonNewTexture( int surface )
{
TEXTURE *pTex = &gTex[surface].userTex;
// Delete the old texture
ss_DeleteTexture( pTex );
// Load up the new texture
if( ! ss_LoadTextureFile( &gTexInfo[surface].texFile, pTex ) )
gTexInfo[surface].bDefTex = TRUE;
}
/******************************Public*Routine******************************\
* MazeDlgTimerProc
*
* Runs off of WM_TIMER message. Used for any gl animation in the dialog
*
* History:
* Jan. 96 [marcfo]
* - Creation
\**************************************************************************/
static void
MazeDlgTimerProc()
{
extern TEX_RES gTexResSurf[]; // from glmaze.c
if( ss_PalettedTextureEnabled() ) {
TEX_INFO *pti = gTexInfo;
int i;
// rotate texture palettes for surfaces with a8 palettes
for( i = 0; i < NUM_SURFACES; i++, pti++ ) {
if( pti->bTex &&
pti->bDefTex &&
( gTexResSurf[pti->iDefTex].type == TEX_A8 ) )
{
// Increment palette rotation for this surface
gTex[i].iPalRot++;
// Draw texture associated with the surface
DrawTexture( i );
}
}
}
}
/******************************Public*Routine******************************\
* ConfigInit
*
* Do Initialization for Config mode
*
* This is the config equivalent of ss_Init
*
* Setup SS_TEX_BUTTON wrappers for each of the 3 texture preview buttons.
\**************************************************************************/
BOOL
ss_ConfigInit( HWND hDlg )
{
SS_DBGLEVEL1( SS_LEVEL_INFO, "ConfigInit for %d\n", hDlg );
// Create GL texture buttons to draw the surface previews
SS_TEX_BUTTON *pTexBtn;
for( int i = 0; i < NUM_SURFACES; i++ ) {
pTexBtn = new SS_TEX_BUTTON( hDlg,
GetDlgItem(hDlg, DLG_SURFACE_TO_PREVIEW(i)) );
if( !pTexBtn ) {
return FALSE;
}
gTex[i].pTexBtn = pTexBtn;
}
updateGLState();
// Start a timer for animating texture palettes
idTimer = 1;
SetTimer(hDlg, idTimer, 16, 0);
// Note: no textures are loaded here, they are 'demand-loaded'
return TRUE;
}
/******************************Public*Routine******************************\
* ScreenSaverConfigureDialog
*
* Processes messages for the configuration dialog box.
*
* History:
* Nov. 95 [marcfo]
* - Creation
\**************************************************************************/
BOOL ScreenSaverConfigureDialog(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
int wTmp, surface;
static BOOL bInited = 0;
switch (message) {
case WM_INITDIALOG:
getIniSettings();
setupDialogControls(hDlg);
// cache the window handle
ghDlg = hDlg;
return TRUE;
case WM_TIMER:
MazeDlgTimerProc();
return 0;
break;
case WM_DRAWITEM:
switch( (UINT) wParam ) {
case DLG_PREVIEW_WALLS:
case DLG_PREVIEW_FLOOR:
case DLG_PREVIEW_CEILING:
if( HandlePreviewDraw( (UINT) wParam,
(LPDRAWITEMSTRUCT) lParam ) )
return TRUE;
default:
break;
}
break;
case WM_VSCROLL:
switch(LOWORD(wParam))
{
case SB_THUMBPOSITION:
// get new value
wTmp = HIWORD(wParam);
{
int id;
HWND hwndScroll = (HWND) lParam;
id = GetDlgCtrlID( hwndScroll );
surface = DLG_SPIN_TEX_TO_SURFACE( id );
gTexInfo[surface].iDefTex = wTmp;
DrawTexture( surface );
}
break;
default:
break;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case DLG_BUTTON_WALLS_TEX:
case DLG_BUTTON_FLOOR_TEX:
case DLG_BUTTON_CEILING_TEX:
surface = DLG_BUTTON_TEX_TO_SURFACE( LOWORD(wParam) );
if( DialogBoxParam(
hMainInstance,
(LPTSTR) MAKEINTRESOURCE( DLG_TEXTURE_CONFIGURE ),
hDlg, (DLGPROC)TextureConfigureDialog, surface ) ) {
//mf: If anything changed here, we have to draw it, as it
// seems when choose texture dialog box terminates, we
// don't get any DRAW_ITEM messages.
// Draw preview area
DrawTexture( surface );
}
break;
case DLG_CHECK_OVERLAY:
maze_options.top_view = !maze_options.top_view;
CheckDlgButton(hDlg, DLG_CHECK_OVERLAY,
maze_options.top_view );
break;
case DLG_CHECK_TURBOMODE:
gbTurboMode = !gbTurboMode;
CheckDlgButton(hDlg, DLG_CHECK_TURBOMODE, gbTurboMode );
updateGLState();
DrawTextures();
break;
case DLG_COMBO_IMAGEQUAL:
switch (HIWORD(wParam))
{
case CBN_EDITCHANGE:
case CBN_SELCHANGE:
{
int oldImageQual = giImageQual;
giImageQual =
(int)SendDlgItemMessage(hDlg, DLG_COMBO_IMAGEQUAL,
CB_GETCURSEL, 0, 0);
if( giImageQual != oldImageQual ) {
// change has occurred - redraw any gl objects
updateGLState();
DrawTextures();
}
}
break;
default:
return FALSE;
}
break;
case IDOK:
saveIniSettings(hDlg);
// fall thru...
case IDCANCEL:
CleanUp( hDlg );
EndDialog(hDlg, FALSE);
break;
default:
return 0;
break;
}
updateDialogControls(hDlg);
return TRUE;
break;
default:
return 0;
}
return 0;
}
/******************************Public*Routine******************************\
* updateTextureConfigControls
*
* Updates dialog controls according to current state
*
* History:
* - Creation
\**************************************************************************/
static void
updateTextureConfigControls(HWND hDlg, BOOL bDefTex )
{
CheckDlgButton(hDlg, IDC_RADIO_TEX_DEFAULT, bDefTex );
CheckDlgButton(hDlg, IDC_RADIO_TEX_CHOOSE, !bDefTex );
EnableWindow(GetDlgItem(hDlg, DLG_BUTTON_TEX_CHOOSE ), !bDefTex );
}
/******************************Public*Routine******************************\
* TextureConfigureDialog
*
* Processes messages for the texture configure dialog box.
*
* - Call EndDialog with TRUE if texture changed, otherwise FALSE
*
* History:
* Dec. 95 [marcfo]
* - Creation
\**************************************************************************/
static BOOL CALLBACK
TextureConfigureDialog(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
// static state ok here, cuz only one of these dialogs can be active
static int surface;
static BOOL bDefTex; // temporary state
switch (message) {
case WM_INITDIALOG:
// Cache some initial values
surface = (int) lParam;
bDefTex = gTexInfo[surface].bDefTex;
updateTextureConfigControls(hDlg, bDefTex );
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case DLG_BUTTON_TEX_CHOOSE:
if( ss_SelectTextureFile( hDlg,
&gTexInfo[surface].texFile ) ) {
// New user texture was selected
HandleTexButtonNewTexture( surface );
// For now, let's end the dialog right here if a
// new one chosen - otherwise we'd have to make the
// new texture discardable if user entered Cancel
gTexInfo[surface].bDefTex = bDefTex;
EndDialog(hDlg, TRUE );
}
break;
case IDC_RADIO_TEX_DEFAULT:
bDefTex = TRUE;
break;
case IDC_RADIO_TEX_CHOOSE:
bDefTex = FALSE;
break;
case IDOK:
// save state
gTexInfo[surface].bDefTex = bDefTex;
EndDialog(hDlg, TRUE);
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
default:
return 0;
break;
}
updateTextureConfigControls(hDlg, bDefTex );
return TRUE;
break;
default:
return 0;
}
return 0;
}
/******************************Public*Routine******************************\
* CleanUp
*
\**************************************************************************/
static void
CleanUp( HWND hwnd )
{
int i;
if (idTimer) {
KillTimer(hwnd, idTimer);
idTimer = 0;
}
// delete any textures and tex buttons created
for( i = 0; i < NUM_SURFACES; i ++ ) {
if( gTex[i].userTex.data )
ss_DeleteTexture( &gTex[i].userTex );
if( gDefTex[i].data )
ss_DeleteTexture( &gDefTex[i] );
if( gTex[i].pTexBtn )
delete gTex[i].pTexBtn;
}
}