Counter Strike : Global Offensive Source Code
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.

1078 lines
35 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Manages the set of application configuration options.
  4. //
  5. //=============================================================================//
  6. #include "stdafx.h"
  7. #include "Options.h"
  8. #include "hammer.h"
  9. #include "MainFrm.h"
  10. #include "mapdoc.h"
  11. #include "KeyValues.h"
  12. #include "ConfigManager.h"
  13. #include "GlobalFunctions.h"
  14. #include "CustomMessages.h"
  15. #include "OptionProperties.h"
  16. #include <process.h>
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include <tier0/memdbgon.h>
  19. const char GAMECFG_SIG[] = "Game Configurations File\r\n\x1a";
  20. const float GAMECFG_VERSION = 1.4f;
  21. static const char *pszGeneral = "General";
  22. static const char *pszView2D = "2D Views";
  23. static const char *pszView3D = "3D Views";
  24. static const char *g_szColors = "Custom2DColors";
  25. const int iThisVersion = 2;
  26. // So File | Open will be in the right directory.
  27. char *g_pMapDir = NULL;
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. COptionsConfigs::COptionsConfigs(void)
  32. {
  33. nConfigs = 0;
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Purpose:
  37. // Output :
  38. //-----------------------------------------------------------------------------
  39. COptionsConfigs::~COptionsConfigs(void)
  40. {
  41. for (int i = 0; i < nConfigs; i++)
  42. {
  43. CGameConfig *pConfig = Configs[i];
  44. if (!pConfig)
  45. continue;
  46. delete pConfig;
  47. }
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose:
  51. // Output :
  52. //-----------------------------------------------------------------------------
  53. CGameConfig *COptionsConfigs::AddConfig(void)
  54. {
  55. CGameConfig *pConfig = new CGameConfig;
  56. Configs.SetAtGrow(nConfigs++, pConfig);
  57. return pConfig;
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose:
  61. // Input : dwID -
  62. // piIndex -
  63. // Output :
  64. //-----------------------------------------------------------------------------
  65. CGameConfig *COptionsConfigs::FindConfig(DWORD dwID, int *piIndex)
  66. {
  67. for(int i = 0; i < nConfigs; i++)
  68. {
  69. if(Configs[i]->dwID == dwID)
  70. {
  71. if(piIndex)
  72. piIndex[0] = i;
  73. return Configs[i];
  74. }
  75. }
  76. return NULL;
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Looks for a game configuration with a given mod directory.
  80. //-----------------------------------------------------------------------------
  81. CGameConfig *COptionsConfigs::FindConfigForGame(const char *szGame)
  82. {
  83. for (int i = 0; i < nConfigs; i++)
  84. {
  85. char *pszGameDir = Configs[i]->m_szModDir;
  86. if ( Q_stricmp( pszGameDir, szGame ) == 0 )
  87. return Configs[i];
  88. }
  89. return NULL;
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Purpose:
  93. // Output : Returns the number of game configurations successfully imported.
  94. //-----------------------------------------------------------------------------
  95. int COptionsConfigs::ImportOldGameConfigs(const char *pszFileName)
  96. {
  97. int nConfigsRead = 0;
  98. char szRootDir[MAX_PATH];
  99. char szFullPath[MAX_PATH];
  100. APP()->GetDirectory(DIR_PROGRAM, szRootDir);
  101. Q_MakeAbsolutePath( szFullPath, MAX_PATH, pszFileName, szRootDir );
  102. std::fstream file( szFullPath, std::ios::in | std::ios::binary );
  103. if (file.is_open())
  104. {
  105. // Read sig.
  106. char szSig[sizeof(GAMECFG_SIG)];
  107. file.read(szSig, sizeof szSig);
  108. if (!memcmp(szSig, GAMECFG_SIG, sizeof szSig))
  109. {
  110. // Read version.
  111. float fThisVersion;
  112. file.read((char *)&fThisVersion, sizeof(fThisVersion));
  113. if ((fThisVersion >= 1.0) && (fThisVersion <= GAMECFG_VERSION))
  114. {
  115. // Read number of configs.
  116. int nTotalConfigs;
  117. file.read((char *)&nTotalConfigs, sizeof(nTotalConfigs));
  118. // Load each config.
  119. for (int i = 0; i < nTotalConfigs; i++)
  120. {
  121. CGameConfig *pConfig = AddConfig();
  122. pConfig->Import(file, fThisVersion);
  123. nConfigsRead++;
  124. if (!g_pMapDir)
  125. {
  126. g_pMapDir = (char *)pConfig->szMapDir;
  127. }
  128. }
  129. }
  130. }
  131. file.close();
  132. }
  133. return(nConfigsRead);
  134. }
  135. // Our call to "new" will be hosed without this header
  136. #include "tier0/memdbgoff.h"
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. // Output : Returns true on success, false on failure.
  140. //-----------------------------------------------------------------------------
  141. bool COptionsConfigs::ResetGameConfigs( bool bOverwrite )
  142. {
  143. CGameConfigManager mgr;
  144. int nNumLoaded = 0;
  145. mgr.SetBaseDirectory( m_strConfigDir );
  146. if ( bOverwrite )
  147. {
  148. // Reset the configurations on the disk
  149. mgr.ResetConfigs();
  150. // Load the newly changed game configs
  151. nNumLoaded = LoadGameConfigs();
  152. }
  153. else
  154. {
  155. // Simply get the keyvalue block from the manager and parse that
  156. KeyValues *pDefaultConfigs = new KeyValues( "Defaults" );
  157. if ( mgr.GetDefaultGameBlock( pDefaultConfigs ) == false )
  158. return false;
  159. // Load from the blocks
  160. nNumLoaded = LoadGameConfigsBlock( pDefaultConfigs );
  161. // Clean up
  162. pDefaultConfigs->deleteThis();
  163. }
  164. return ( nNumLoaded > 0 );
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose:
  168. // Input : *pBlock -
  169. // Output : int
  170. //-----------------------------------------------------------------------------
  171. int COptionsConfigs::LoadGameConfigsBlock( KeyValues *pBlock )
  172. {
  173. if ( pBlock == NULL )
  174. return 0;
  175. int nConfigsRead = 0;
  176. for ( KeyValues *pKey = pBlock->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
  177. {
  178. CGameConfig *pConfig = AddConfig();
  179. if ( pConfig != NULL )
  180. {
  181. if ( pConfig->Load( pKey ) )
  182. {
  183. nConfigsRead++;
  184. }
  185. }
  186. }
  187. return nConfigsRead;
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: Loads all the game configs from disk.
  191. // Output : Returns the number of game configurations successfully loaded.
  192. //-----------------------------------------------------------------------------
  193. int COptionsConfigs::LoadGameConfigs()
  194. {
  195. //
  196. // Read game configs - this is from an external file so we can distribute it
  197. // with the editor as a set of defaults.
  198. //
  199. // Older versions of the editor used a binary file. Try that first.
  200. //
  201. int nConfigsRead = ImportOldGameConfigs("GameCfg.wc");
  202. if (nConfigsRead > 0)
  203. {
  204. // This will cause a double conversion, from .wc to .ini to .txt, but oh well...
  205. char szRootDir[MAX_PATH];
  206. char szFullPath[MAX_PATH];
  207. APP()->GetDirectory(DIR_PROGRAM, szRootDir);
  208. Q_MakeAbsolutePath( szFullPath, MAX_PATH, "GameCfg.wc", szRootDir );
  209. remove( szFullPath );
  210. char szSaveName[MAX_PATH];
  211. strcpy(szSaveName, m_strConfigDir);
  212. Q_AppendSlash(szSaveName, sizeof(szSaveName));
  213. Q_strcat(szSaveName, "GameCfg.ini", sizeof(szSaveName));
  214. SaveGameConfigs();
  215. return(nConfigsRead);
  216. }
  217. CGameConfigManager mgr;
  218. if ( !mgr.LoadConfigs( m_strConfigDir ) )
  219. return 0;
  220. KeyValues *pGame = mgr.GetGameBlock();
  221. if (!pGame)
  222. return 0;
  223. // Install the message handler for error messages.
  224. GDSetMessageFunc(Msg);
  225. // Load from the blocks
  226. nConfigsRead = LoadGameConfigsBlock( pGame );
  227. return nConfigsRead;
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Purpose: Saves all the cgame configurations to disk.
  231. // Input : *pszFileName -
  232. //-----------------------------------------------------------------------------
  233. void COptionsConfigs::SaveGameConfigs()
  234. {
  235. // Only do this if we've got configs to save!
  236. if ( GetGameConfigCount() == 0 )
  237. return;
  238. CGameConfigManager mgr;
  239. if ( mgr.LoadConfigs( m_strConfigDir ) == false )
  240. return;
  241. // Get the global configuration data
  242. KeyValues *pGame = mgr.GetGameBlock();
  243. // For each Hammer known configuation, update the values in the global configs
  244. for ( int i = 0; i < nConfigs; i++ )
  245. {
  246. KeyValues *pConfig = pGame->FindKey(Configs.GetAt(i)->szName);
  247. // Add the configuration if it wasn't found
  248. if ( pConfig == NULL )
  249. {
  250. pConfig = pGame->CreateNewKey();
  251. if ( pConfig == NULL )
  252. {
  253. // FIXME: fatal error
  254. return;
  255. }
  256. }
  257. // Update the changes
  258. Configs.GetAt(i)->Save(pConfig);
  259. }
  260. // For each global configuration, remove any configs Hammer has deleted
  261. bool bFoundConfig;
  262. KeyValues *pConfig = pGame->GetFirstTrueSubKey();
  263. while ( pConfig != NULL )
  264. {
  265. // Search through all the configs Hammer knows of for a matching name
  266. bFoundConfig = false;
  267. for ( int i = 0; i < nConfigs; i++ )
  268. {
  269. if ( !Q_stricmp( pConfig->GetName(), Configs.GetAt(i)->szName ) )
  270. {
  271. bFoundConfig = true;
  272. break;
  273. }
  274. }
  275. // Move along to the next config
  276. if ( bFoundConfig )
  277. {
  278. pConfig = pConfig->GetNextTrueSubKey();
  279. continue;
  280. }
  281. // Delete the configuration block if we didn't find it
  282. KeyValues *pNextConfig = pConfig->GetNextTrueSubKey();
  283. pGame->RemoveSubKey( pConfig );
  284. pConfig->deleteThis();
  285. pConfig = pNextConfig;
  286. }
  287. // Save the resulting changes
  288. mgr.SaveConfigs( m_strConfigDir );
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Purpose:
  292. //-----------------------------------------------------------------------------
  293. COptions::COptions(void)
  294. {
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Purpose: Looks for the Valve Hammer Editor registry settings and returns whether
  298. // they were found.
  299. //-----------------------------------------------------------------------------
  300. static bool HammerSettingsFound(void)
  301. {
  302. bool bFound = false;
  303. HKEY hkeySoftware;
  304. if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ | KEY_WRITE, &hkeySoftware) == ERROR_SUCCESS)
  305. {
  306. HKEY hkeyValve;
  307. if (RegOpenKeyEx(hkeySoftware, "Valve", 0, KEY_READ | KEY_WRITE, &hkeyValve) == ERROR_SUCCESS)
  308. {
  309. HKEY hkeyHammer;
  310. if (RegOpenKeyEx(hkeyValve, "Hammer", 0, KEY_READ | KEY_WRITE, &hkeyHammer) == ERROR_SUCCESS)
  311. {
  312. HKEY hkeyConfigured;
  313. if (RegOpenKeyEx(hkeyHammer, "Configured", 0, KEY_READ | KEY_WRITE, &hkeyConfigured) == ERROR_SUCCESS)
  314. {
  315. bFound = true;
  316. RegCloseKey(hkeyConfigured);
  317. }
  318. RegCloseKey(hkeyHammer);
  319. }
  320. RegCloseKey(hkeyValve);
  321. }
  322. RegCloseKey(hkeySoftware);
  323. }
  324. return bFound;
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose: Looks for the Valve Hammer Editor registry settings and returns whether
  328. // they were found.
  329. //-----------------------------------------------------------------------------
  330. static bool ValveHammerEditorSettingsFound(void)
  331. {
  332. bool bFound = false;
  333. HKEY hkeySoftware;
  334. if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ | KEY_WRITE, &hkeySoftware) == ERROR_SUCCESS)
  335. {
  336. HKEY hkeyValve;
  337. if (RegOpenKeyEx(hkeySoftware, "Valve", 0, KEY_READ | KEY_WRITE, &hkeyValve) == ERROR_SUCCESS)
  338. {
  339. HKEY hkeyHammer;
  340. if (RegOpenKeyEx(hkeyValve, "Valve Hammer Editor", 0, KEY_READ | KEY_WRITE, &hkeyHammer) == ERROR_SUCCESS)
  341. {
  342. HKEY hkeyConfigured;
  343. if (RegOpenKeyEx(hkeyHammer, "Configured", 0, KEY_READ | KEY_WRITE, &hkeyConfigured) == ERROR_SUCCESS)
  344. {
  345. bFound = true;
  346. RegCloseKey(hkeyConfigured);
  347. }
  348. RegCloseKey(hkeyHammer);
  349. }
  350. RegCloseKey(hkeyValve);
  351. }
  352. RegCloseKey(hkeySoftware);
  353. }
  354. return bFound;
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose: Looks for the Worldcraft registry settings and returns whether they
  358. // were found.
  359. //-----------------------------------------------------------------------------
  360. static bool WorldcraftSettingsFound(void)
  361. {
  362. bool bFound = false;
  363. HKEY hkeySoftware;
  364. if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ | KEY_WRITE, &hkeySoftware) == ERROR_SUCCESS)
  365. {
  366. HKEY hkeyValve;
  367. if (RegOpenKeyEx(hkeySoftware, "Valve", 0, KEY_READ | KEY_WRITE, &hkeyValve) == ERROR_SUCCESS)
  368. {
  369. HKEY hkeyWorldcraft;
  370. if (RegOpenKeyEx(hkeyValve, "Worldcraft", 0, KEY_READ | KEY_WRITE, &hkeyWorldcraft) == ERROR_SUCCESS)
  371. {
  372. bFound = true;
  373. RegCloseKey(hkeyWorldcraft);
  374. }
  375. RegCloseKey(hkeyValve);
  376. }
  377. RegCloseKey(hkeySoftware);
  378. }
  379. return bFound;
  380. }
  381. //-----------------------------------------------------------------------------
  382. // Purpose:
  383. //-----------------------------------------------------------------------------
  384. bool COptions::Init(void)
  385. {
  386. //
  387. // If the we have no registry settings and the "Valve Hammer Editor" registry tree exists,
  388. // import settings from there. If that isn't found, try "Worldcraft".
  389. //
  390. bool bWCSettingsFound = false;
  391. bool bVHESettingsFound = false;
  392. if (!HammerSettingsFound())
  393. {
  394. bVHESettingsFound = ValveHammerEditorSettingsFound();
  395. if (!bVHESettingsFound)
  396. {
  397. bWCSettingsFound = WorldcraftSettingsFound();
  398. }
  399. }
  400. if (bVHESettingsFound)
  401. {
  402. APP()->BeginImportVHESettings();
  403. }
  404. else if (bWCSettingsFound)
  405. {
  406. APP()->BeginImportWCSettings();
  407. }
  408. SetDefaults();
  409. if (!Read())
  410. {
  411. return false;
  412. }
  413. if (bVHESettingsFound || bWCSettingsFound)
  414. {
  415. APP()->EndImportSettings();
  416. }
  417. //
  418. // Notify appropriate windows of new settings.
  419. // dvs: is all this necessary?
  420. //
  421. CMainFrame *pMainWnd = GetMainWnd();
  422. if (pMainWnd != NULL)
  423. {
  424. pMainWnd->SetBrightness(textures.fBrightness);
  425. pMainWnd->UpdateAllDocViews( MAPVIEW_OPTIONS_CHANGED );
  426. // FIXME: can't do this before the filesystem is initialized
  427. //pMainWnd->GlobalNotify(WM_GAME_CHANGED);
  428. }
  429. return true;
  430. }
  431. //-----------------------------------------------------------------------------
  432. // Purpose: Enables or disables texture locking.
  433. // Input : b - TRUE to enable texture locking, FALSE to disable.
  434. // Output : Returns the previous value of the texture locking flag.
  435. //-----------------------------------------------------------------------------
  436. BOOL COptions::SetLockingTextures(BOOL b)
  437. {
  438. BOOL bOld = general.bLockingTextures;
  439. general.bLockingTextures = b;
  440. return(bOld);
  441. }
  442. //-----------------------------------------------------------------------------
  443. // Purpose: Returns TRUE if texture locking is enabled, FALSE if not.
  444. //-----------------------------------------------------------------------------
  445. BOOL COptions::IsLockingTextures(void)
  446. {
  447. return(general.bLockingTextures);
  448. }
  449. BOOL COptions::SetScaleLockingTextures(BOOL b)
  450. {
  451. BOOL bOld = general.bScaleLockingTextures;
  452. general.bScaleLockingTextures = b;
  453. return(bOld);
  454. }
  455. BOOL COptions::IsScaleLockingTextures(void)
  456. {
  457. return general.bScaleLockingTextures;
  458. }
  459. //-----------------------------------------------------------------------------
  460. // Purpose: Returns whether new faces should be world aligned or face aligned.
  461. //-----------------------------------------------------------------------------
  462. TextureAlignment_t COptions::GetTextureAlignment(void)
  463. {
  464. return(general.eTextureAlignment);
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Purpose: Sets whether new faces should be world aligned or face aligned.
  468. // Input : eTextureAlignment - TEXTURE_ALIGN_WORLD or TEXTURE_ALIGN_FACE.
  469. // Output : Returns the old setting for texture alignment.
  470. //-----------------------------------------------------------------------------
  471. TextureAlignment_t COptions::SetTextureAlignment(TextureAlignment_t eTextureAlignment)
  472. {
  473. TextureAlignment_t eOld = general.eTextureAlignment;
  474. general.eTextureAlignment = eTextureAlignment;
  475. return(eOld);
  476. }
  477. //-----------------------------------------------------------------------------
  478. // Purpose: Returns whether helpers should be hidden or shown.
  479. //-----------------------------------------------------------------------------
  480. bool COptions::GetShowHelpers(void)
  481. {
  482. return (general.bShowHelpers == TRUE);
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Purpose: Sets whether helpers should be hidden or shown.
  486. //-----------------------------------------------------------------------------
  487. void COptions::SetShowHelpers(bool bShow)
  488. {
  489. general.bShowHelpers = bShow ? TRUE : FALSE;
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Purpose: Loads the application configuration settings.
  493. // Output : Returns TRUE on success, FALSE on failure.
  494. //-----------------------------------------------------------------------------
  495. bool COptions::Read(void)
  496. {
  497. if (!APP()->GetProfileInt("Configured", "Configured", 0))
  498. {
  499. return false;
  500. }
  501. DWORD dwTime = APP()->GetProfileInt("Configured", "Installed", time(NULL));
  502. CTimeSpan ts(time(NULL) - dwTime);
  503. uDaysSinceInstalled = ts.GetDays();
  504. int i, iSize;
  505. CString str;
  506. // read texture info - it's stored in the general section from
  507. // an old version, but this doesn't matter much.
  508. iSize = APP()->GetProfileInt(pszGeneral, "TextureFileCount", 0);
  509. if(iSize)
  510. {
  511. // make sure default is removed
  512. textures.nTextureFiles = 0;
  513. textures.TextureFiles.RemoveAll();
  514. // read texture file names
  515. for(i = 0; i < iSize; i++)
  516. {
  517. str.Format("TextureFile%d", i);
  518. str = APP()->GetProfileString(pszGeneral, str);
  519. if(GetFileAttributes(str) == 0xffffffff)
  520. {
  521. // can't find
  522. continue;
  523. }
  524. textures.TextureFiles.Add(str);
  525. textures.nTextureFiles++;
  526. }
  527. }
  528. else
  529. {
  530. // SetDefaults() added 'textures.wad' to the list
  531. }
  532. textures.fBrightness = float(APP()->GetProfileInt(pszGeneral, "Brightness", 10)) / 10.0;
  533. // load general info
  534. general.nMaxCameras = APP()->GetProfileInt(pszGeneral, "Max Cameras", 100);
  535. general.iUndoLevels = APP()->GetProfileInt(pszGeneral, "Undo Levels", 50);
  536. general.bLockingTextures = APP()->GetProfileInt(pszGeneral, "Locking Textures", TRUE);
  537. general.bScaleLockingTextures = APP()->GetProfileInt(pszGeneral, "Scale Locking Textures", FALSE);
  538. general.eTextureAlignment = (TextureAlignment_t)APP()->GetProfileInt(pszGeneral, "Texture Alignment", TEXTURE_ALIGN_WORLD);
  539. general.bLoadwinpos = APP()->GetProfileInt(pszGeneral, "Load Default Positions", TRUE);
  540. general.bIndependentwin = APP()->GetProfileInt(pszGeneral, "Independent Windows", FALSE);
  541. general.bEnablePerforceIntegration = APP()->GetProfileInt( pszGeneral, "Perforce Integration", TRUE );
  542. general.bGroupWhileIgnore = APP()->GetProfileInt(pszGeneral, "GroupWhileIgnore", FALSE);
  543. general.bStretchArches = APP()->GetProfileInt(pszGeneral, "StretchArches", TRUE);
  544. general.bShowHelpers = APP()->GetProfileInt(pszGeneral, "Show Helpers", TRUE);
  545. general.bCheckVisibleMapErrors = APP()->GetProfileInt(pszGeneral, "Visible Map Errors", FALSE);
  546. general.iTimeBetweenSaves = APP()->GetProfileInt(pszGeneral, "Time Between Saves", 15);
  547. general.iMaxAutosaveSpace = APP()->GetProfileInt(pszGeneral, "Max Autosave Space", 100);
  548. general.iMaxAutosavesPerMap = APP()->GetProfileInt(pszGeneral, "Max Saves Per Map", 5);
  549. general.bEnableAutosave = APP()->GetProfileInt(pszGeneral, "Autosaves Enabled", 1);
  550. general.bClosedCorrectly = APP()->GetProfileInt(pszGeneral, "Closed Correctly", TRUE);
  551. general.bShowHiddenTargetsAsBroken = APP()->GetProfileInt(pszGeneral, "Show Hidden Targets As Broken", TRUE);
  552. general.bRadiusCulling = APP()->GetProfileInt(pszGeneral, "Use Radius Culling", FALSE);
  553. char szDefaultAutosavePath[MAX_PATH];
  554. strcpy( szDefaultAutosavePath, APP()->GetProfileString(pszGeneral, "Directory", "C:"));
  555. strcat( szDefaultAutosavePath, "\\HammerAutosave\\" );
  556. strcpy( general.szAutosaveDir, APP()->GetProfileString("General", "Autosave Dir", szDefaultAutosavePath));
  557. if ( Q_strlen( general.szAutosaveDir ) == 0 )
  558. {
  559. strcpy( general.szAutosaveDir, szDefaultAutosavePath );
  560. }
  561. APP()->SetDirectory( DIR_AUTOSAVE, general.szAutosaveDir );
  562. // read view2d
  563. view2d.bCrosshairs = APP()->GetProfileInt(pszView2D, "Crosshairs", FALSE);
  564. view2d.bGroupCarve = APP()->GetProfileInt(pszView2D, "GroupCarve", TRUE);
  565. view2d.bScrollbars = APP()->GetProfileInt(pszView2D, "Scrollbars", TRUE);
  566. view2d.bRotateConstrain = APP()->GetProfileInt(pszView2D, "RotateConstrain", FALSE);
  567. view2d.bDrawVertices = APP()->GetProfileInt(pszView2D, "Draw Vertices", TRUE);
  568. view2d.bDrawModels = APP()->GetProfileInt(pszView2D, "Draw Models", TRUE);
  569. view2d.bWhiteOnBlack = APP()->GetProfileInt(pszView2D, "WhiteOnBlack", TRUE);
  570. view2d.bGridHigh1024 = APP()->GetProfileInt(pszView2D, "GridHigh1024", TRUE);
  571. view2d.bGridHigh10 = APP()->GetProfileInt(pszView2D, "GridHigh10", TRUE);
  572. view2d.bHideSmallGrid = APP()->GetProfileInt(pszView2D, "HideSmallGrid", TRUE);
  573. view2d.bNudge = APP()->GetProfileInt(pszView2D, "Nudge", FALSE);
  574. view2d.bOrientPrimitives = APP()->GetProfileInt(pszView2D, "OrientPrimitives", FALSE);
  575. view2d.bAutoSelect = APP()->GetProfileInt(pszView2D, "AutoSelect", FALSE);
  576. view2d.bSelectbyhandles = APP()->GetProfileInt(pszView2D, "SelectByHandles", FALSE);
  577. view2d.iGridIntensity = APP()->GetProfileInt(pszView2D, "GridIntensity", 30);
  578. view2d.iDefaultGrid = APP()->GetProfileInt(pszView2D, "Default Grid", 64);
  579. view2d.iGridHighSpec = APP()->GetProfileInt(pszView2D, "GridHighSpec", 8);
  580. view2d.bKeepclonegroup = APP()->GetProfileInt(pszView2D, "Keepclonegroup", TRUE);
  581. view2d.bGridHigh64 = APP()->GetProfileInt(pszView2D, "Gridhigh64", TRUE);
  582. view2d.bGridDots = APP()->GetProfileInt(pszView2D, "GridDots", FALSE);
  583. view2d.bCenteroncamera = APP()->GetProfileInt(pszView2D, "Centeroncamera", FALSE);
  584. view2d.bUsegroupcolors = APP()->GetProfileInt(pszView2D, "Usegroupcolors", TRUE);
  585. // read view3d
  586. view3d.bHardware = APP()->GetProfileInt(pszView3D, "Hardware", FALSE);
  587. view3d.bReverseY = APP()->GetProfileInt(pszView3D, "Reverse Y", TRUE);
  588. view3d.iBackPlane = APP()->GetProfileInt(pszView3D, "BackPlane", 5000);
  589. view3d.bUseMouseLook = APP()->GetProfileInt(pszView3D, "UseMouseLook", TRUE);
  590. view3d.nModelDistance = APP()->GetProfileInt(pszView3D, "ModelDistance", 400);
  591. view3d.nDetailDistance = APP()->GetProfileInt(pszView3D, "DetailDistance", 1200);
  592. view3d.bAnimateModels = APP()->GetProfileInt(pszView3D, "AnimateModels", FALSE);
  593. view3d.nForwardSpeedMax = APP()->GetProfileInt(pszView3D, "ForwardSpeedMax", 1000);
  594. view3d.nTimeToMaxSpeed = APP()->GetProfileInt(pszView3D, "TimeToMaxSpeed", 500);
  595. view3d.bFilterTextures = APP()->GetProfileInt(pszView3D, "FilterTextures", TRUE);
  596. view3d.bReverseSelection = APP()->GetProfileInt(pszView3D, "ReverseSelection", FALSE);
  597. view3d.fFOV = 90;
  598. view3d.iViewInstancesMode = APP()->GetProfileInt(pszView3D, "ViewInstancesMode", 1);
  599. ReadColorSettings();
  600. //
  601. // If we can't load any game configurations, pop up the options screen.
  602. //
  603. if (configs.LoadGameConfigs() == 0)
  604. {
  605. if (!RunConfigurationDialog())
  606. return false;
  607. }
  608. //
  609. // By default use the first config.
  610. //
  611. if (configs.nConfigs > 0)
  612. {
  613. g_pGameConfig = configs.Configs.GetAt(0);
  614. }
  615. return true;
  616. }
  617. //-----------------------------------------------------------------------------
  618. // Purpose:
  619. // Output : Returns true on success, false on failure.
  620. //-----------------------------------------------------------------------------
  621. bool COptions::RunConfigurationDialog()
  622. {
  623. CString strText;
  624. strText.LoadString(IDS_NO_CONFIGS_AVAILABLE);
  625. if (MessageBox(NULL, strText, "First Time Setup", MB_ICONQUESTION | MB_YESNO) == IDYES)
  626. {
  627. APP()->OpenURL(ID_HELP_FIRST_TIME_SETUP, GetMainWnd()->GetSafeHwnd());
  628. }
  629. COptionProperties dlg("Configure Hammer");
  630. do
  631. {
  632. if (dlg.DoModal() != IDOK)
  633. {
  634. return false;
  635. }
  636. if (configs.nConfigs == 0)
  637. {
  638. MessageBox(NULL, "You must create at least one game configuration before using Hammer.", "First Time Setup", MB_ICONEXCLAMATION | MB_OK);
  639. }
  640. } while (configs.nConfigs == 0);
  641. Options.Write( TRUE, TRUE );
  642. return true;
  643. }
  644. //-----------------------------------------------------------------------------
  645. // Purpose:
  646. //-----------------------------------------------------------------------------
  647. void COptions::ReadColorSettings(void)
  648. {
  649. colors.bUseCustom = (APP()->GetProfileInt(g_szColors, "UseCustom", 0) != 0);
  650. if (colors.bUseCustom)
  651. {
  652. colors.clrAxis = APP()->GetProfileColor(g_szColors, "Grid0", 0 , 100, 100);
  653. colors.bScaleAxisColor = (APP()->GetProfileInt(g_szColors, "ScaleGrid0", 0) != 0);
  654. colors.clrGrid = APP()->GetProfileColor(g_szColors, "Grid", 50 , 50, 50);
  655. colors.bScaleGridColor = (APP()->GetProfileInt(g_szColors, "ScaleGrid", 1) != 0);
  656. colors.clrGrid10 = APP()->GetProfileColor(g_szColors, "Grid10", 40 , 40, 40);
  657. colors.bScaleGrid10Color = (APP()->GetProfileInt(g_szColors, "ScaleGrid10", 1) != 0);
  658. colors.clrGrid1024 = APP()->GetProfileColor(g_szColors, "Grid1024", 40 , 40, 40);
  659. colors.bScaleGrid1024Color = (APP()->GetProfileInt(g_szColors, "ScaleGrid1024", 1) != 0);
  660. colors.clrGridDot = APP()->GetProfileColor(g_szColors, "GridDot", 128, 128, 128);
  661. colors.bScaleGridDotColor = (APP()->GetProfileInt(g_szColors, "ScaleGridDot", 1) != 0);
  662. colors.clrBrush = APP()->GetProfileColor(g_szColors, "LineColor", 0, 0, 0);
  663. colors.clrEntity = APP()->GetProfileColor(g_szColors, "Entity", 220, 30, 220);
  664. colors.clrVertex = APP()->GetProfileColor(g_szColors, "Vertex", 0, 0, 0);
  665. colors.clrBackground = APP()->GetProfileColor(g_szColors, "Background", 0, 0, 0);
  666. colors.clrToolHandle = APP()->GetProfileColor(g_szColors, "HandleColor", 0, 0, 0);
  667. colors.clrToolBlock = APP()->GetProfileColor(g_szColors, "BoxColor", 0, 0, 0);
  668. colors.clrToolSelection = APP()->GetProfileColor(g_szColors, "ToolSelect", 0, 0, 0);
  669. colors.clrToolMorph = APP()->GetProfileColor(g_szColors, "Morph", 255, 0, 0);
  670. colors.clrToolPath = APP()->GetProfileColor(g_szColors, "Path", 255, 0, 0);
  671. colors.clrSelection = APP()->GetProfileColor(g_szColors, "Selection", 220, 0, 0);
  672. colors.clrToolDrag = APP()->GetProfileColor(g_szColors, "ToolDrag", 255, 255, 0);
  673. }
  674. else
  675. {
  676. if (Options.view2d.bWhiteOnBlack)
  677. {
  678. // BLACK BACKGROUND
  679. colors.clrBackground = RGB(0, 0, 0);
  680. colors.clrGrid = RGB(255, 255, 255);
  681. colors.clrGridDot = RGB(255, 255, 255);
  682. colors.clrGrid1024 = RGB(100, 50, 5);
  683. colors.clrGrid10 = RGB(255, 255, 255);
  684. colors.clrAxis = RGB(0, 100, 100);
  685. colors.clrBrush = RGB(255, 255, 255);
  686. colors.clrVertex = RGB(255, 255, 255);
  687. colors.clrToolHandle = RGB(255, 255, 255);
  688. colors.clrToolBlock = RGB(255, 255, 255);
  689. colors.clrToolDrag = RGB(255, 255, 0);
  690. }
  691. else
  692. {
  693. // WHITE BACKGROUND
  694. colors.clrBackground = RGB(255, 255, 255);
  695. colors.clrGrid = RGB(50, 50, 50);
  696. colors.clrGridDot = RGB(40, 40, 40);
  697. colors.clrGrid1024 = RGB(200, 100, 10);
  698. colors.clrGrid10 = RGB(40, 40, 40);
  699. colors.clrAxis = RGB(0, 100, 100);
  700. colors.clrBrush = RGB(0, 0, 0);
  701. colors.clrVertex = RGB(0, 0, 0);
  702. colors.clrToolHandle = RGB(0, 0, 0);
  703. colors.clrToolBlock = RGB(0, 0, 0);
  704. colors.clrToolDrag = RGB(0, 0, 255);
  705. }
  706. colors.bScaleAxisColor = false;
  707. colors.bScaleGridColor = true;
  708. colors.bScaleGrid10Color = true;
  709. colors.bScaleGrid1024Color = false;
  710. colors.bScaleGridDotColor = true;
  711. colors.clrToolSelection = RGB(255, 255, 0);
  712. colors.clrSelection = RGB(255, 0, 0);
  713. colors.clrToolMorph = RGB(255, 0, 0);
  714. colors.clrToolPath = RGB(255, 0, 0);
  715. colors.clrEntity = RGB(220, 30, 220);
  716. colors.clrModelCollisionWireframe = RGB( 255, 255, 0 );
  717. colors.clrModelCollisionWireframeDisabled = RGB( 220, 30, 220 );
  718. }
  719. }
  720. //-----------------------------------------------------------------------------
  721. // Purpose:
  722. // Input : fOverwrite -
  723. //-----------------------------------------------------------------------------
  724. void COptions::Write( BOOL fOverwrite, BOOL fSaveConfigs )
  725. {
  726. APP()->WriteProfileInt("Configured", "Configured", iThisVersion);
  727. int i, iSize;
  728. CString str;
  729. // write texture info - remember, it's stored in general
  730. iSize = textures.nTextureFiles;
  731. APP()->WriteProfileInt(pszGeneral, "TextureFileCount", iSize);
  732. for(i = 0; i < iSize; i++)
  733. {
  734. str.Format("TextureFile%d", i);
  735. APP()->WriteProfileString(pszGeneral, str, textures.TextureFiles[i]);
  736. }
  737. APP()->WriteProfileInt(pszGeneral, "Brightness", int(textures.fBrightness * 10));
  738. // write general
  739. APP()->WriteProfileInt(pszGeneral, "Max Cameras", general.nMaxCameras);
  740. APP()->WriteProfileInt(pszGeneral, "Undo Levels", general.iUndoLevels);
  741. APP()->WriteProfileInt(pszGeneral, "Locking Textures", general.bLockingTextures);
  742. APP()->WriteProfileInt(pszGeneral, "Scale Locking Textures", general.bScaleLockingTextures);
  743. APP()->WriteProfileInt(pszGeneral, "Texture Alignment", general.eTextureAlignment);
  744. APP()->WriteProfileInt(pszGeneral, "Independent Windows", general.bIndependentwin);
  745. APP()->WriteProfileInt( pszGeneral, "Perforce Integration", general.bEnablePerforceIntegration );
  746. APP()->WriteProfileInt(pszGeneral, "Load Default Positions", general.bLoadwinpos);
  747. APP()->WriteProfileInt(pszGeneral, "GroupWhileIgnore", general.bGroupWhileIgnore);
  748. APP()->WriteProfileInt(pszGeneral, "StretchArches", general.bStretchArches);
  749. APP()->WriteProfileInt(pszGeneral, "Show Helpers", general.bShowHelpers);
  750. APP()->WriteProfileInt(pszGeneral, "Visible Map Errors", general.bCheckVisibleMapErrors);
  751. APP()->WriteProfileInt(pszGeneral, "Time Between Saves", general.iTimeBetweenSaves);
  752. APP()->WriteProfileInt(pszGeneral, "Max Autosave Space", general.iMaxAutosaveSpace);
  753. APP()->WriteProfileInt(pszGeneral, "Max Saves Per Map", general.iMaxAutosavesPerMap);
  754. APP()->WriteProfileInt(pszGeneral, "Autosaves Enabled", general.bEnableAutosave);
  755. APP()->WriteProfileInt(pszGeneral, "Closed Correctly", general.bClosedCorrectly);
  756. APP()->WriteProfileString(pszGeneral, "Autosave Dir", general.szAutosaveDir);
  757. APP()->SetDirectory( DIR_AUTOSAVE, general.szAutosaveDir );
  758. APP()->WriteProfileInt(pszGeneral, "Show Hidden Targets As Broken", general.bShowHiddenTargetsAsBroken);
  759. APP()->WriteProfileInt(pszGeneral, "Use Radius Culling", general.bRadiusCulling);
  760. // write view2d
  761. APP()->WriteProfileInt(pszView2D, "Crosshairs", view2d.bCrosshairs);
  762. APP()->WriteProfileInt(pszView2D, "GroupCarve", view2d.bGroupCarve);
  763. APP()->WriteProfileInt(pszView2D, "Scrollbars", view2d.bScrollbars);
  764. APP()->WriteProfileInt(pszView2D, "RotateConstrain", view2d.bRotateConstrain);
  765. APP()->WriteProfileInt(pszView2D, "Draw Vertices", view2d.bDrawVertices);
  766. APP()->WriteProfileInt(pszView2D, "Draw Models", view2d.bDrawModels);
  767. APP()->WriteProfileInt(pszView2D, "Default Grid", view2d.iDefaultGrid);
  768. APP()->WriteProfileInt(pszView2D, "WhiteOnBlack", view2d.bWhiteOnBlack);
  769. APP()->WriteProfileInt(pszView2D, "GridHigh1024", view2d.bGridHigh1024);
  770. APP()->WriteProfileInt(pszView2D, "GridHigh10", view2d.bGridHigh10);
  771. APP()->WriteProfileInt(pszView2D, "GridIntensity", view2d.iGridIntensity);
  772. APP()->WriteProfileInt(pszView2D, "HideSmallGrid", view2d.bHideSmallGrid);
  773. APP()->WriteProfileInt(pszView2D, "Nudge", view2d.bNudge);
  774. APP()->WriteProfileInt(pszView2D, "OrientPrimitives", view2d.bOrientPrimitives);
  775. APP()->WriteProfileInt(pszView2D, "AutoSelect", view2d.bAutoSelect);
  776. APP()->WriteProfileInt(pszView2D, "SelectByHandles", view2d.bSelectbyhandles);
  777. APP()->WriteProfileInt(pszView2D, "GridHighSpec", view2d.iGridHighSpec);
  778. APP()->WriteProfileInt(pszView2D, "KeepCloneGroup", view2d.bKeepclonegroup);
  779. APP()->WriteProfileInt(pszView2D, "Gridhigh64", view2d.bGridHigh64);
  780. APP()->WriteProfileInt(pszView2D, "GridDots", view2d.bGridDots);
  781. APP()->WriteProfileInt(pszView2D, "Centeroncamera", view2d.bCenteroncamera);
  782. APP()->WriteProfileInt(pszView2D, "Usegroupcolors", view2d.bUsegroupcolors);
  783. // write view3d
  784. APP()->WriteProfileInt(pszView3D, "Hardware", view3d.bHardware);
  785. APP()->WriteProfileInt(pszView3D, "Reverse Y", view3d.bReverseY);
  786. APP()->WriteProfileInt(pszView3D, "BackPlane", view3d.iBackPlane);
  787. APP()->WriteProfileInt(pszView3D, "UseMouseLook", view3d.bUseMouseLook);
  788. APP()->WriteProfileInt(pszView3D, "ModelDistance", view3d.nModelDistance);
  789. APP()->WriteProfileInt(pszView3D, "DetailDistance", view3d.nDetailDistance);
  790. APP()->WriteProfileInt(pszView3D, "AnimateModels", view3d.bAnimateModels);
  791. APP()->WriteProfileInt(pszView3D, "ForwardSpeedMax", view3d.nForwardSpeedMax);
  792. APP()->WriteProfileInt(pszView3D, "TimeToMaxSpeed", view3d.nTimeToMaxSpeed);
  793. APP()->WriteProfileInt(pszView3D, "FilterTextures", view3d.bFilterTextures);
  794. APP()->WriteProfileInt(pszView3D, "ReverseSelection", view3d.bReverseSelection);
  795. APP()->WriteProfileInt(pszView3D, "ViewInstancesMode", view3d.iViewInstancesMode);
  796. //
  797. // We don't write custom color settings because there is no GUI for them yet.
  798. //
  799. // Write out the game configurations
  800. if ( fSaveConfigs )
  801. {
  802. configs.SaveGameConfigs();
  803. }
  804. }
  805. void COptions::SetClosedCorrectly(BOOL bClosed)
  806. {
  807. APP()->WriteProfileInt( pszGeneral, "Closed Correctly", bClosed );
  808. }
  809. //-----------------------------------------------------------------------------
  810. // Purpose:
  811. //-----------------------------------------------------------------------------
  812. void COptions::SetDefaults(void)
  813. {
  814. BOOL bWrite = FALSE;
  815. if (APP()->GetProfileInt("Configured", "Configured", 0) != iThisVersion)
  816. {
  817. bWrite = TRUE;
  818. }
  819. if (APP()->GetProfileInt("Configured", "Installed", 42151) == 42151)
  820. {
  821. APP()->WriteProfileInt("Configured", "Installed", time(NULL));
  822. }
  823. uDaysSinceInstalled = 0;
  824. // textures
  825. textures.nTextureFiles = 1;
  826. textures.TextureFiles.Add("textures.wad");
  827. textures.fBrightness = 1.0;
  828. // general
  829. general.bIndependentwin = FALSE;
  830. general.bEnablePerforceIntegration = TRUE;
  831. general.bLoadwinpos = TRUE;
  832. general.iUndoLevels = 50;
  833. general.nMaxCameras = 100;
  834. general.bGroupWhileIgnore = FALSE;
  835. general.bStretchArches = TRUE;
  836. general.bLockingTextures = TRUE;
  837. general.bScaleLockingTextures = FALSE;
  838. general.bShowHelpers = TRUE;
  839. general.iTimeBetweenSaves = 15;
  840. general.iMaxAutosaveSpace = 100;
  841. general.iMaxAutosavesPerMap = 5;
  842. general.bEnableAutosave = TRUE;
  843. general.bClosedCorrectly = TRUE;
  844. general.bShowCollisionModels = FALSE;
  845. general.bShowDetailObjects = TRUE;
  846. general.bShowNoDrawBrushes = TRUE;
  847. // view2d
  848. view2d.bCrosshairs = FALSE;
  849. view2d.bGroupCarve = TRUE;
  850. view2d.bScrollbars = TRUE;
  851. view2d.bRotateConstrain = FALSE;
  852. view2d.bDrawVertices = TRUE;
  853. view2d.bDrawModels = TRUE;
  854. view2d.iDefaultGrid = 64;
  855. view2d.bWhiteOnBlack = TRUE;
  856. view2d.bGridHigh1024 = TRUE;
  857. view2d.bGridHigh10 = TRUE;
  858. view2d.iGridIntensity = 30;
  859. view2d.bHideSmallGrid = TRUE;
  860. view2d.bNudge = FALSE;
  861. view2d.bOrientPrimitives = FALSE;
  862. view2d.bAutoSelect = FALSE;
  863. view2d.bSelectbyhandles = FALSE;
  864. view2d.iGridHighSpec = 8;
  865. view2d.bKeepclonegroup = TRUE;
  866. view2d.bGridHigh64 = FALSE;
  867. view2d.bGridDots = FALSE;
  868. view2d.bCenteroncamera = FALSE;
  869. view2d.bUsegroupcolors = TRUE;
  870. // view3d
  871. view3d.bUseMouseLook = TRUE;
  872. view3d.bHardware = FALSE;
  873. view3d.bReverseY = FALSE;
  874. view3d.iBackPlane = 5000;
  875. view3d.nModelDistance = 400;
  876. view3d.nDetailDistance = 1200;
  877. view3d.bAnimateModels = FALSE;
  878. view3d.nForwardSpeedMax = 1000;
  879. view3d.nTimeToMaxSpeed = 500;
  880. view3d.bFilterTextures = TRUE;
  881. view3d.bReverseSelection = FALSE;
  882. view3d.bPreviewModelFade = false;
  883. view3d.iViewInstancesMode = 1;
  884. if ( bWrite )
  885. {
  886. Write( FALSE, FALSE );
  887. }
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose: This is called by the user interface itself when changes are made.
  891. // tells the COptions object to notify the parts of the interface.
  892. // Input : dwOptionsChanged - Flags indicating which options changed.
  893. //-----------------------------------------------------------------------------
  894. void COptions::PerformChanges(DWORD dwOptionsChanged)
  895. {
  896. CMainFrame *pMainWnd = GetMainWnd();
  897. if (dwOptionsChanged & secTextures)
  898. {
  899. if (pMainWnd != NULL)
  900. {
  901. pMainWnd->SetBrightness(textures.fBrightness);
  902. }
  903. }
  904. if (dwOptionsChanged & secView2D)
  905. {
  906. ReadColorSettings();
  907. if (pMainWnd != NULL)
  908. {
  909. pMainWnd->UpdateAllDocViews( MAPVIEW_UPDATE_ONLY_2D | MAPVIEW_OPTIONS_CHANGED | MAPVIEW_RENDER_NOW );
  910. }
  911. }
  912. if (dwOptionsChanged & secView3D)
  913. {
  914. if (pMainWnd != NULL)
  915. {
  916. pMainWnd->UpdateAllDocViews(MAPVIEW_UPDATE_ONLY_3D | MAPVIEW_OPTIONS_CHANGED | MAPVIEW_RENDER_NOW );
  917. }
  918. }
  919. if (dwOptionsChanged & secConfigs)
  920. {
  921. if (pMainWnd != NULL)
  922. {
  923. pMainWnd->GlobalNotify(WM_GAME_CHANGED);
  924. }
  925. }
  926. }