//----------------------------------------------------------------------------- // File: Pipes.cpp // // Desc: Fun screen saver. // // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #include "stdafx.h" //----------------------------------------------------------------------------- // Name: struct MYVERTEX // Desc: D3D vertex type for this app //----------------------------------------------------------------------------- struct MYVERTEX { D3DXVECTOR3 p; // Position FLOAT tu; // Vertex texture coordinates FLOAT tv; MYVERTEX(D3DXVECTOR3 pInit, FLOAT tuInit, FLOAT tvInit) { p = pInit; tu = tuInit; tv = tvInit; } }; #define D3DFVF_MYVERTEX (D3DFVF_XYZ | D3DFVF_TEX1) #define BUF_SIZE 255 TCHAR g_szSectName[BUF_SIZE]; TCHAR g_szFname[BUF_SIZE]; CPipesScreensaver* g_pMyPipesScreensaver = NULL; //----------------------------------------------------------------------------- // Name: WinMain() // Desc: Entry point to the program. Initializes everything, and goes into a // message-processing loop. Idle time is used to render the scene. //----------------------------------------------------------------------------- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { HRESULT hr; CPipesScreensaver pipesScreensaverSS; if( FAILED( hr = pipesScreensaverSS.Create( hInst ) ) ) { pipesScreensaverSS.DisplayErrorMsg( hr ); return 0; } return pipesScreensaverSS.Run(); } //----------------------------------------------------------------------------- // Name: CPipesScreensaver() // Desc: Constructor //----------------------------------------------------------------------------- CPipesScreensaver::CPipesScreensaver( ) { g_pMyPipesScreensaver = this; InitCommonControls(); for( int i=0; iRegisterSoftwareDevice( D3D8RGBRasterizer ); return S_OK; } //----------------------------------------------------------------------------- // Name: FrameMove() // Desc: Called once per frame, the call is the entry point for animating // the scene. //----------------------------------------------------------------------------- HRESULT CPipesScreensaver::FrameMove() { m_pDeviceObjects->m_pState->FrameMove( m_fElapsedTime ); return S_OK; } //----------------------------------------------------------------------------- // Name: DoPaint() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::DoPaint(HWND hwnd, HDC hdc) { CD3DScreensaver::DoPaint( hwnd, hdc ); for( int iDevice=0; iDeviceRepaint(); } } //----------------------------------------------------------------------------- // Name: Render() // Desc: Called once per frame, the call is the entry point for 3d // rendering. This function sets up render states, clears the // viewport, and renders the scene. //----------------------------------------------------------------------------- HRESULT CPipesScreensaver::Render() { BOOL bRenderNewPiece = FALSE; if( m_Config.dwSpeed == 20 ) { bRenderNewPiece = TRUE; } else { FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME ); if( fCurTime - m_pDeviceObjects->m_pState->m_fLastTime > (20-m_Config.dwSpeed) * 0.005 ) { bRenderNewPiece = TRUE; m_pDeviceObjects->m_pState->m_fLastTime = fCurTime; } } if( bRenderNewPiece ) { // Begin the scene if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { m_pDeviceObjects->m_pState->Render(); // End the scene. m_pd3dDevice->EndScene(); } } else { if( m_iRenderUnit == 0 ) { // Wait for a little while so we don't draw the pipes too fast Sleep(10); } } return S_OK; } //----------------------------------------------------------------------------- // Name: RestoreDeviceObjects() // Desc: //----------------------------------------------------------------------------- HRESULT CPipesScreensaver::RestoreDeviceObjects() { if( m_pd3dDevice == NULL ) return S_OK; m_pDeviceObjects->m_pState = new STATE( &m_Config ); m_pDeviceObjects->m_pState->InitDeviceObjects( m_pd3dDevice ); m_pDeviceObjects->m_pState->RestoreDeviceObjects(); m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ); return S_OK; } //----------------------------------------------------------------------------- // Name: InvalidateDeviceObjects() // Desc: //----------------------------------------------------------------------------- HRESULT CPipesScreensaver::InvalidateDeviceObjects() { m_pDeviceObjects->m_pState->InvalidateDeviceObjects(); m_pDeviceObjects->m_pState->DeleteDeviceObjects(); SAFE_DELETE( m_pDeviceObjects->m_pState ); return S_OK; } //----------------------------------------------------------------------------- // Name: ConfigureDialogProcHelper() // Desc: //----------------------------------------------------------------------------- INT_PTR CALLBACK ConfigureDialogProcHelper( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { return g_pMyPipesScreensaver->ConfigureDialogProc( hwndDlg, uMsg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: DoConfig() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::DoConfig() { DialogBox( NULL, MAKEINTRESOURCE(IDD_CONFIGURE), m_hWndParent, ConfigureDialogProcHelper ); } //----------------------------------------------------------------------------- // Name: ConfigureDialogProc() // Desc: //----------------------------------------------------------------------------- INT_PTR CALLBACK CPipesScreensaver::ConfigureDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static CONFIG s_TempConfig; switch (uMsg) { case WM_INITDIALOG: { ReadSettings(); s_TempConfig = m_Config; lstrcpy( s_TempConfig.strTextureName[0], m_Config.strTextureName[0] ); if( s_TempConfig.bMultiPipes ) CheckRadioButton(hwndDlg, IDC_RADIO_SINGLE_PIPE, IDC_RADIO_MULTIPLE_PIPES, IDC_RADIO_MULTIPLE_PIPES); else CheckRadioButton(hwndDlg, IDC_RADIO_SINGLE_PIPE, IDC_RADIO_MULTIPLE_PIPES, IDC_RADIO_SINGLE_PIPE); HWND hCtrl = GetDlgItem(hwndDlg, DLG_COMBO_JOINTTYPE); SendMessage(hCtrl, CB_RESETCONTENT, 0, 0); TCHAR strJointNames[IDS_JOINT_COUNT][MAX_PATH]; for (int i = 0; i < IDS_JOINT_COUNT; i++) { LoadString( NULL, i+IDS_JOINT_FIRST, strJointNames[i], sizeof(strJointNames)/IDS_JOINT_COUNT ); SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)strJointNames[i]); } SendMessage(hCtrl, CB_SETCURSEL, s_TempConfig.nJointType, 0); if( !s_TempConfig.bTextured ) { CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX, IDC_RADIO_SOLID); EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), FALSE ); } else { CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX, IDC_RADIO_TEX); EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), TRUE ); } SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 20 ) ); SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) m_Config.dwSpeed ); SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) 5 ); SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) 1 ); return TRUE; } case WM_COMMAND: { switch( LOWORD( wParam ) ) { case IDC_RADIO_TEX: EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), TRUE ); break; case IDC_RADIO_SOLID: EnableWindow( GetDlgItem( hwndDlg, DLG_SETUP_TEXTURE ), FALSE ); break; case DLG_SETUP_TEXTURE: { if( SelectTextureFile( hwndDlg, s_TempConfig.strTextureName[0] ) ) { CheckRadioButton(hwndDlg, IDC_RADIO_SOLID, IDC_RADIO_TEX, IDC_RADIO_TEX); s_TempConfig.bDefaultTexture = FALSE; } else { s_TempConfig.bDefaultTexture = TRUE; } break; } case IDC_SCREENSETTINGS: { DoScreenSettingsDialog( hwndDlg ); break; } case IDOK: { s_TempConfig.bMultiPipes = IsDlgButtonChecked(hwndDlg, IDC_RADIO_MULTIPLE_PIPES); HWND hCtrl = GetDlgItem(hwndDlg, DLG_COMBO_JOINTTYPE); s_TempConfig.nJointType = (DWORD) SendMessage(hCtrl, CB_GETCURSEL, 0, 0); s_TempConfig.bTextured = IsDlgButtonChecked(hwndDlg, IDC_RADIO_TEX); s_TempConfig.dwSpeed = (DWORD) SendDlgItemMessage( hwndDlg, IDC_SPEED_SLIDER, TBM_GETPOS, 0, 0 ); m_Config = s_TempConfig; lstrcpy( m_Config.strTextureName[0], s_TempConfig.strTextureName[0] ); WriteSettings(); EndDialog(hwndDlg, IDOK); break; } case IDCANCEL: { EndDialog(hwndDlg, IDCANCEL); break; } } return TRUE; } } return FALSE; } //----------------------------------------------------------------------------- // Name: SelectTextureFile() // Desc: //----------------------------------------------------------------------------- BOOL CPipesScreensaver::SelectTextureFile( HWND hDlg, TCHAR* origPathName ) { TCHAR fn[MAX_PATH] = TEXT("\0"); TCHAR szDialogTitle[MAX_PATH]; TCHAR szTextureFilter[MAX_PATH]; TCHAR szTitle[MAX_PATH]; LoadString(NULL, IDS_TEXTUREFILTER, szTextureFilter, MAX_PATH); // Filter strings are weird because they contain nulls. // The string loaded from a resource has # where nulls // should be inserted. for( TCHAR* pch = szTextureFilter; *pch != TEXT('\0'); pch++ ) { if (*pch == TEXT('#')) *pch = TEXT('\0'); } LoadString(NULL, IDS_TEXTUREDIALOGTITLE, szDialogTitle, MAX_PATH); LoadString(NULL, IDS_TITLE, szTitle, MAX_PATH); TCHAR szWindowsDir[MAX_PATH + 1]; if( 0 == GetWindowsDirectory( szWindowsDir, MAX_PATH + 1 ) ) szWindowsDir[0] = TEXT('\0'); OPENFILENAME ofn; memset( &ofn, 0, sizeof(ofn) ); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hDlg; ofn.hInstance = m_hInstance; ofn.lpstrFilter = szTextureFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = origPathName; ofn.nMaxFile = sizeof(fn); ofn.lpstrTitle = szDialogTitle; ofn.Flags = OFN_ENABLESIZING|OFN_FILEMUSTEXIST; ofn.lpstrDefExt = TEXT("BMP"); if( lstrlen( origPathName ) == 0 ) ofn.lpstrInitialDir = szWindowsDir; if( GetOpenFileName( &ofn ) ) { lstrcpy( origPathName, ofn.lpstrFile ); return TRUE; } else { return FALSE; } } //----------------------------------------------------------------------------- // Name: ReadSettings() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::ReadSettings() { HKEY hkey; // Read OpenGL settings first, so OS upgrade cases work ss_ReadSettings(); if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) ) { ReadScreenSettings( hkey ); // DXUtil_ReadBoolRegKey( hkey, TEXT("Flex Mode"), &m_Config.bFlexMode, m_Config.bFlexMode ); DXUtil_ReadBoolRegKey( hkey, TEXT("MultiPipes"), &m_Config.bMultiPipes, m_Config.bMultiPipes ); DXUtil_ReadBoolRegKey( hkey, TEXT("Textured"), &m_Config.bTextured, m_Config.bTextured ); DXUtil_ReadBoolRegKey( hkey, TEXT("Default Texture"), &m_Config.bDefaultTexture, m_Config.bDefaultTexture ); DXUtil_ReadIntRegKey( hkey, TEXT("Tessel Factor"), &m_Config.dwTesselFact, m_Config.dwTesselFact ); if( m_Config.dwTesselFact >= 4 ) m_Config.dwTesselFact = 4; DXUtil_ReadIntRegKey( hkey, TEXT("Joint Type"), &m_Config.nJointType, m_Config.nJointType ); if( m_Config.nJointType >= NUM_JOINTTYPES ) m_Config.nJointType = JOINT_ELBOW; DXUtil_ReadIntRegKey( hkey, TEXT("Speed"), &m_Config.dwSpeed, m_Config.dwSpeed ); DXUtil_ReadStringRegKey( hkey, TEXT("Texture Name"), m_Config.strTextureName[0], MAX_PATH, m_Config.strTextureName[0] ); RegCloseKey( hkey ); } } //----------------------------------------------------------------------------- // Name: ss_ReadSettings() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::ss_ReadSettings() { // Get registry settings if( ss_RegistrySetup( IDS_SAVERNAME, IDS_INIFILE ) ) { m_Config.nJointType = ss_GetRegistryInt( IDS_JOINTTYPE, 0 ); m_Config.bTextured = (ss_GetRegistryInt( IDS_SURFSTYLE, 0 ) == 1); if( m_Config.bTextured ) m_Config.bDefaultTexture = TRUE; m_Config.bMultiPipes = ss_GetRegistryInt( IDS_MULTIPIPES, 0 ); ss_GetRegistryString( IDS_TEXTURE, 0, m_Config.strTextureName[0], MAX_PATH); if( lstrlen(m_Config.strTextureName[0]) > 0 ) m_Config.bDefaultTexture = FALSE; } } //----------------------------------------------------------------------------- // Name: ss_GetRegistryString() // Desc: //----------------------------------------------------------------------------- BOOL CPipesScreensaver::ss_RegistrySetup( int section, int file ) { if( LoadString(m_hInstance, section, g_szSectName, BUF_SIZE) && LoadString(m_hInstance, file, g_szFname, BUF_SIZE) ) { TCHAR pBuffer[100]; DWORD dwRealSize = GetPrivateProfileSection( g_szSectName, pBuffer, 100, g_szFname ); if( dwRealSize > 0 ) return TRUE; } return FALSE; } //----------------------------------------------------------------------------- // Name: ss_GetRegistryString() // Desc: //----------------------------------------------------------------------------- int CPipesScreensaver::ss_GetRegistryInt( int name, int iDefault ) { TCHAR szItemName[BUF_SIZE]; if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) ) return GetPrivateProfileInt(g_szSectName, szItemName, iDefault, g_szFname); return 0; } //----------------------------------------------------------------------------- // Name: ss_GetRegistryString() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::ss_GetRegistryString( int name, LPTSTR lpDefault, LPTSTR lpDest, int bufSize ) { TCHAR szItemName[BUF_SIZE]; if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) ) GetPrivateProfileString(g_szSectName, szItemName, lpDefault, lpDest, bufSize, g_szFname); return; } //----------------------------------------------------------------------------- // Name: WriteSettings() // Desc: //----------------------------------------------------------------------------- VOID CPipesScreensaver::WriteSettings() { HKEY hkey; DWORD dwType = REG_DWORD; DWORD dwLength = sizeof(DWORD); if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) ) { WriteScreenSettings( hkey ); // DXUtil_WriteBoolRegKey( hkey, TEXT("Flex Mode"), m_Config.bFlexMode ); DXUtil_WriteBoolRegKey( hkey, TEXT("MultiPipes"), m_Config.bMultiPipes ); DXUtil_WriteBoolRegKey( hkey, TEXT("Textured"), m_Config.bTextured ); DXUtil_WriteBoolRegKey( hkey, TEXT("Default Texture"), m_Config.bDefaultTexture ); DXUtil_WriteIntRegKey( hkey, TEXT("Tessel Factor"), m_Config.dwTesselFact ); DXUtil_WriteIntRegKey( hkey, TEXT("Joint Type"), m_Config.nJointType ); DXUtil_WriteStringRegKey( hkey, TEXT("Texture Name"), m_Config.strTextureName[0] ); DXUtil_WriteIntRegKey( hkey, TEXT("Speed"), m_Config.dwSpeed ); RegCloseKey( hkey ); } } //----------------------------------------------------------------------------- // Name: iRand() // Desc: Generates integer random number 0..(max-1) //----------------------------------------------------------------------------- int CPipesScreensaver::iRand( int max ) { return (int) ( max * ( ((float)rand()) / ((float)(RAND_MAX+1)) ) ); } //----------------------------------------------------------------------------- // Name: iRand2() // Desc: Generates integer random number min..max //----------------------------------------------------------------------------- int CPipesScreensaver::iRand2( int min, int max ) { if( min == max ) { return min; } else if( max < min ) { int temp = min; min = max; max = temp; } return min + (int) ( (max-min+1) * ( ((float)rand()) / ((float)(RAND_MAX+1)) ) ); } //----------------------------------------------------------------------------- // Name: fRand() // Desc: Generates float random number min...max //----------------------------------------------------------------------------- FLOAT CPipesScreensaver::fRand( FLOAT min, FLOAT max ) { FLOAT diff; diff = max - min; return min + ( diff * ( ((float)rand()) / ((float)(RAND_MAX)) ) ); } //----------------------------------------------------------------------------- // Name: RandInit() // Desc: Initializes the randomizer //----------------------------------------------------------------------------- VOID CPipesScreensaver::RandInit() { struct _timeb time; _ftime( &time ); srand( time.millitm ); for( int i = 0; i < 10; i ++ ) rand(); }