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.

869 lines
22 KiB

  1. //========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "stdafx.h"
  7. #include <shlobj.h>
  8. #include "GameConfig.h"
  9. #include "EditGameConfigs.h"
  10. #include "hammer.h"
  11. #include "OPTConfigs.h"
  12. #include "ConfigManager.h"
  13. #include "process.h"
  14. #include "Options.h"
  15. #include "TextureBrowser.h"
  16. #include "tier2/vconfig.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include <tier0/memdbgon.h>
  19. IMPLEMENT_DYNCREATE(COPTConfigs, CPropertyPage)
  20. //-----------------------------------------------------------------------------
  21. // Purpose: Returns the string value of a registry key
  22. // Input : *pName - name of the subKey to read
  23. // *pReturn - string buffer to receive read string
  24. // size - size of specified buffer
  25. //-----------------------------------------------------------------------------
  26. bool GetPersistentEnvironmentVariable( const char *pName, char *pReturn, int size )
  27. {
  28. // Open the key
  29. HKEY hregkey;
  30. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, VPROJECT_REG_KEY, 0, KEY_QUERY_VALUE, &hregkey ) != ERROR_SUCCESS )
  31. return false;
  32. // Get the value
  33. DWORD dwSize = size;
  34. if ( RegQueryValueEx( hregkey, pName, NULL, NULL,(LPBYTE) pReturn, &dwSize ) != ERROR_SUCCESS )
  35. return false;
  36. // Close the key
  37. RegCloseKey( hregkey );
  38. return true;
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose: Set the registry entry to a string value, under the given subKey
  42. // Input : *pName - name of the subKey to set
  43. // *pValue - string value
  44. //-----------------------------------------------------------------------------
  45. void SetPersistentEnvironmentVariable( const char *pName, const char *pValue )
  46. {
  47. HKEY hregkey;
  48. DWORD dwReturnValue = 0;
  49. // Open the key
  50. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, VPROJECT_REG_KEY, 0, KEY_ALL_ACCESS, &hregkey ) != ERROR_SUCCESS )
  51. return;
  52. // Set the value to the string passed in
  53. RegSetValueEx( hregkey, pName, 0, REG_SZ, (const unsigned char *)pValue, (int) strlen(pValue) );
  54. // Propagate changes so that environment variables takes immediate effect!
  55. SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue );
  56. // Close the key
  57. RegCloseKey( hregkey );
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose: Converts a Steam path prefix to %STEAM% and back.
  61. //-----------------------------------------------------------------------------
  62. void EditorUtil_ConvertPath(CString &str, bool bExpand)
  63. {
  64. CString strSteamDir;
  65. g_pGameConfig->GetSteamDir(strSteamDir);
  66. CString strSteamUserDir;
  67. g_pGameConfig->GetSteamUserDir(strSteamUserDir);
  68. if (!strSteamDir.GetLength() && !strSteamUserDir.GetLength())
  69. {
  70. // Can't do the token replacement.
  71. return;
  72. }
  73. const char *szSteamDirToken = "$SteamDir";
  74. const char *szSteamUserDirToken = "$SteamUserDir";
  75. char szPathOut[MAX_PATH];
  76. if (bExpand)
  77. {
  78. // Replace the tokens with the full strings
  79. if (Q_StrSubst(str, szSteamUserDirToken, strSteamUserDir, szPathOut, sizeof(szPathOut)))
  80. {
  81. str = szPathOut;
  82. }
  83. if (Q_StrSubst(str, szSteamDirToken, strSteamDir, szPathOut, sizeof(szPathOut)))
  84. {
  85. str = szPathOut;
  86. }
  87. }
  88. else
  89. {
  90. // Replace the full strings with the tokens
  91. // Go from longest paths to shortest paths to insure the most brief expression.
  92. if (Q_StrSubst(str, strSteamUserDir, szSteamUserDirToken, szPathOut, sizeof(szPathOut)))
  93. {
  94. str = szPathOut;
  95. }
  96. if (Q_StrSubst(str, strSteamDir, szSteamDirToken, szPathOut, sizeof(szPathOut)))
  97. {
  98. str = szPathOut;
  99. }
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: Exchanges path data between a CString and an edit control, converting
  104. // the Steam path to %STEAM% and back.
  105. //-----------------------------------------------------------------------------
  106. void EditorUtil_TransferPath(CDialog *pDlg, int nIDC, char *szDest, bool bExpand)
  107. {
  108. CWnd *pwnd = pDlg->GetDlgItem(nIDC);
  109. if (!pwnd)
  110. return;
  111. CString str;
  112. if (bExpand)
  113. {
  114. pwnd->GetWindowText(str);
  115. EditorUtil_ConvertPath(str, true);
  116. strcpy(szDest, str);
  117. }
  118. else
  119. {
  120. str = szDest;
  121. EditorUtil_ConvertPath(str, false);
  122. pwnd->SetWindowText(str);
  123. }
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Constructor.
  127. //-----------------------------------------------------------------------------
  128. COPTConfigs::COPTConfigs(void) : CPropertyPage(COPTConfigs::IDD)
  129. {
  130. //{{AFX_DATA_INIT(COPTConfigs)
  131. //}}AFX_DATA_INIT
  132. m_pLastSelConfig = NULL;
  133. m_pInitialSelectedConfig = NULL;
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Purpose: Destructor.
  137. //-----------------------------------------------------------------------------
  138. COPTConfigs::~COPTConfigs(void)
  139. {
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Purpose:
  143. // Input : pDX -
  144. //-----------------------------------------------------------------------------
  145. void COPTConfigs::DoDataExchange(CDataExchange* pDX)
  146. {
  147. CPropertyPage::DoDataExchange(pDX);
  148. //{{AFX_DATA_MAP(COPTConfigs)
  149. DDX_Control(pDX, IDC_MAPDIR, m_cMapDir);
  150. DDX_Control(pDX, IDC_PREFABDIR, m_cPrefabDir);
  151. DDX_Control(pDX, IDC_GAMEEXEDIR, m_cGameExeDir);
  152. DDX_Control(pDX, IDC_MODDIR, m_cModDir);
  153. DDX_Control(pDX, IDC_MAPFORMAT, m_cMapFormat);
  154. DDX_Control(pDX, IDC_CORDON_TEXTURE, m_cCordonTexture);
  155. DDX_Control(pDX, IDC_TEXTUREFORMAT, m_cTextureFormat);
  156. DDX_Control(pDX, IDC_DEFAULTPOINT, m_cDefaultPoint);
  157. DDX_Control(pDX, IDC_DEFAULTENTITY, m_cDefaultSolid);
  158. DDX_Control(pDX, IDC_DATAFILES, m_cGDFiles);
  159. DDX_Control(pDX, IDC_CONFIGURATIONS, m_cConfigs);
  160. DDX_Control(pDX, IDC_DEFAULT_TEXTURE_SCALE, m_cDefaultTextureScale);
  161. //}}AFX_DATA_MAP
  162. }
  163. BEGIN_MESSAGE_MAP(COPTConfigs, CPropertyPage)
  164. //{{AFX_MSG_MAP(COPTConfigs)
  165. ON_BN_CLICKED(IDC_EDITCONFIGS, OnEditconfigs)
  166. ON_BN_CLICKED(IDC_GDFILE_ADD, OnGdfileAdd)
  167. ON_BN_CLICKED(IDC_GDFILE_EDIT, OnGdfileEdit)
  168. ON_BN_CLICKED(IDC_GDFILE_REMOVE, OnGdfileRemove)
  169. ON_CBN_SELCHANGE(IDC_CONFIGURATIONS, OnSelchangeConfigurations)
  170. ON_BN_CLICKED(IDC_BROWSEMAPDIR, OnBrowsemapdir)
  171. ON_BN_CLICKED(IDC_BROWSEPREFABDIR, OnBrowsePrefabDir)
  172. ON_BN_CLICKED(IDC_BROWSEGAMEEXEDIR, OnBrowseGameExeDir)
  173. ON_BN_CLICKED(IDC_BROWSEMODDIR, OnBrowseModDir)
  174. ON_BN_CLICKED(IDC_BROWSE_CORDON_TEXTURE, OnBrowseCordonTexture)
  175. ON_MESSAGE( WM_SETTINGCHANGE, OnSettingChange )
  176. //}}AFX_MSG_MAP
  177. END_MESSAGE_MAP()
  178. void COPTConfigs::OnEditconfigs(void)
  179. {
  180. SaveInfo(m_pLastSelConfig);
  181. CEditGameConfigs dlg;
  182. dlg.DoModal();
  183. UpdateConfigList();
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Purpose:
  187. //-----------------------------------------------------------------------------
  188. void COPTConfigs::OnGdfileAdd(void)
  189. {
  190. if (m_pLastSelConfig == NULL)
  191. return;
  192. char szAppDir[MAX_PATH];
  193. APP()->GetDirectory(DIR_PROGRAM, szAppDir);
  194. // browse for .FGD files
  195. CFileDialog dlg(TRUE, ".fgd", NULL, OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST, "Game Data Files (*.fgd)|*.fgd||");
  196. dlg.m_ofn.lpstrInitialDir = szAppDir;
  197. if (dlg.DoModal() != IDOK)
  198. return;
  199. CString str = dlg.GetPathName();
  200. EditorUtil_ConvertPath(str, false);
  201. m_cGDFiles.AddString(str);
  202. SaveInfo(m_pLastSelConfig);
  203. m_pLastSelConfig->LoadGDFiles();
  204. UpdateEntityLists();
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Purpose:
  208. //-----------------------------------------------------------------------------
  209. void COPTConfigs::OnGdfileEdit(void)
  210. {
  211. if(m_pLastSelConfig == NULL)
  212. return;
  213. // edit the selected FGD file
  214. int iCurSel = m_cGDFiles.GetCurSel();
  215. if(iCurSel == LB_ERR)
  216. return;
  217. CString str;
  218. m_cGDFiles.GetText(iCurSel, str);
  219. EditorUtil_ConvertPath(str, true);
  220. // call editor (notepad!)
  221. char szBuf[MAX_PATH];
  222. GetWindowsDirectory(szBuf, MAX_PATH);
  223. strcat(szBuf, "\\notepad.exe");
  224. _spawnl(_P_WAIT, szBuf, szBuf, str, NULL);
  225. m_pLastSelConfig->LoadGDFiles();
  226. UpdateEntityLists();
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose:
  230. //-----------------------------------------------------------------------------
  231. void COPTConfigs::OnGdfileRemove(void)
  232. {
  233. if(m_pLastSelConfig == NULL)
  234. return;
  235. int iCurSel = m_cGDFiles.GetCurSel();
  236. if(iCurSel == LB_ERR)
  237. return;
  238. m_cGDFiles.DeleteString(iCurSel);
  239. SaveInfo(m_pLastSelConfig);
  240. m_pLastSelConfig->LoadGDFiles();
  241. UpdateEntityLists();
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose:
  245. // Input : *pConfig -
  246. //-----------------------------------------------------------------------------
  247. void COPTConfigs::SaveInfo(CGameConfig *pConfig)
  248. {
  249. if (pConfig == NULL)
  250. {
  251. return;
  252. }
  253. // game data files
  254. pConfig->nGDFiles = 0;
  255. pConfig->GDFiles.RemoveAll();
  256. int iSize = m_cGDFiles.GetCount();
  257. for(int i = 0; i < iSize; i++)
  258. {
  259. CString str;
  260. m_cGDFiles.GetText(i, str);
  261. EditorUtil_ConvertPath(str, true);
  262. pConfig->GDFiles.Add(str);
  263. ++pConfig->nGDFiles;
  264. }
  265. //
  266. // Map file type.
  267. //
  268. int nIndex = m_cMapFormat.GetCurSel();
  269. if (nIndex != CB_ERR)
  270. {
  271. pConfig->mapformat = (MAPFORMAT)m_cMapFormat.GetItemData(nIndex);
  272. }
  273. else
  274. {
  275. pConfig->mapformat = mfHalfLife2;
  276. }
  277. //
  278. // WAD file type.
  279. //
  280. nIndex = m_cTextureFormat.GetCurSel();
  281. if (nIndex != CB_ERR)
  282. {
  283. pConfig->SetTextureFormat((TEXTUREFORMAT)m_cTextureFormat.GetItemData(nIndex));
  284. }
  285. else
  286. {
  287. pConfig->SetTextureFormat(tfVMT);
  288. }
  289. m_cDefaultSolid.GetWindowText(pConfig->szDefaultSolid, sizeof pConfig->szDefaultSolid);
  290. m_cDefaultPoint.GetWindowText(pConfig->szDefaultPoint, sizeof pConfig->szDefaultPoint);
  291. EditorUtil_TransferPath(this, IDC_GAMEEXEDIR, pConfig->m_szGameExeDir, true);
  292. EditorUtil_TransferPath(this, IDC_MODDIR, pConfig->m_szModDir, true);
  293. EditorUtil_TransferPath(this, IDC_MAPDIR, pConfig->szMapDir, true);
  294. // Check to see if the prefab folder changed, and warn user that they need to restart hammer if it did
  295. char szOldPrefabDir[128];
  296. strcpy(szOldPrefabDir, pConfig->m_szPrefabDir);
  297. EditorUtil_TransferPath(this, IDC_PREFABDIR, pConfig->m_szPrefabDir, true);
  298. if ( strcmp( szOldPrefabDir, pConfig->m_szPrefabDir ) )
  299. {
  300. AfxMessageBox("Your changes to the prefab path will not take effect until the next time you run Hammer.");
  301. }
  302. char szCordonTexture[MAX_PATH];
  303. m_cCordonTexture.GetWindowText(szCordonTexture, sizeof(szCordonTexture));
  304. pConfig->SetCordonTexture(szCordonTexture);
  305. //
  306. // Default texture scale.
  307. //
  308. char szText[100];
  309. m_cDefaultTextureScale.GetWindowText(szText, sizeof(szText));
  310. float fScale = (float)atof(szText);
  311. if (fScale == 0)
  312. {
  313. fScale = 1;
  314. }
  315. pConfig->SetDefaultTextureScale(fScale);
  316. //
  317. // Default lightmap scale.
  318. //
  319. int nLightmapScale = GetDlgItemInt(IDC_DEFAULT_LIGHTMAP_SCALE, NULL, FALSE);
  320. pConfig->SetDefaultLightmapScale(nLightmapScale);
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose:
  324. //-----------------------------------------------------------------------------
  325. void COPTConfigs::OnSelchangeConfigurations(void)
  326. {
  327. // save info from controls into last selected config
  328. SaveInfo(m_pLastSelConfig);
  329. m_pLastSelConfig = NULL;
  330. // load info from newly selected config into controls
  331. int iCurSel = m_cConfigs.GetCurSel();
  332. CGameConfig *pConfig = Options.configs.FindConfig(m_cConfigs.GetItemData(iCurSel));
  333. BOOL bKillFields = FALSE;
  334. if (pConfig == NULL)
  335. {
  336. bKillFields = TRUE;
  337. }
  338. m_cGDFiles.EnableWindow(!bKillFields);
  339. m_cDefaultPoint.EnableWindow(!bKillFields);
  340. m_cDefaultSolid.EnableWindow(!bKillFields);
  341. m_cTextureFormat.EnableWindow(!bKillFields);
  342. m_cMapFormat.EnableWindow(!bKillFields);
  343. m_cGameExeDir.EnableWindow(!bKillFields);
  344. m_cModDir.EnableWindow(!bKillFields);
  345. m_cMapDir.EnableWindow(!bKillFields);
  346. m_cPrefabDir.EnableWindow(!bKillFields);
  347. m_cCordonTexture.EnableWindow(!bKillFields);
  348. if (pConfig == NULL)
  349. {
  350. return;
  351. }
  352. m_pLastSelConfig = pConfig;
  353. // load game data files
  354. m_cGDFiles.ResetContent();
  355. for (int i = 0; i < pConfig->nGDFiles; i++)
  356. {
  357. CString str(pConfig->GDFiles[i]);
  358. EditorUtil_ConvertPath(str, false);
  359. m_cGDFiles.AddString(str);
  360. }
  361. //
  362. // Select the correct map format.
  363. //
  364. m_cMapFormat.SetCurSel(0);
  365. int nItems = m_cMapFormat.GetCount();
  366. for (int i = 0; i < nItems; i++)
  367. {
  368. if (pConfig->mapformat == (MAPFORMAT)m_cMapFormat.GetItemData(i))
  369. {
  370. m_cMapFormat.SetCurSel(i);
  371. break;
  372. }
  373. }
  374. //
  375. // Select the correct texture format.
  376. //
  377. m_cTextureFormat.SetCurSel(0);
  378. nItems = m_cTextureFormat.GetCount();
  379. for (int i = 0; i < nItems; i++)
  380. {
  381. if (pConfig->GetTextureFormat() == (TEXTUREFORMAT)m_cTextureFormat.GetItemData(i))
  382. {
  383. m_cTextureFormat.SetCurSel(i);
  384. break;
  385. }
  386. }
  387. EditorUtil_TransferPath(this, IDC_GAMEEXEDIR, pConfig->m_szGameExeDir, false);
  388. EditorUtil_TransferPath(this, IDC_MODDIR, pConfig->m_szModDir, false);
  389. EditorUtil_TransferPath(this, IDC_MAPDIR, pConfig->szMapDir, false);
  390. EditorUtil_TransferPath(this, IDC_PREFABDIR, pConfig->m_szPrefabDir, false);
  391. m_cCordonTexture.SetWindowText(pConfig->GetCordonTexture());
  392. char szText[100];
  393. sprintf(szText, "%g", pConfig->GetDefaultTextureScale());
  394. m_cDefaultTextureScale.SetWindowText(szText);
  395. SetDlgItemInt(IDC_DEFAULT_LIGHTMAP_SCALE, pConfig->GetDefaultLightmapScale(), FALSE);
  396. // load entity type comboboxes and set strings
  397. UpdateEntityLists();
  398. }
  399. //-----------------------------------------------------------------------------
  400. // Purpose:
  401. //-----------------------------------------------------------------------------
  402. void COPTConfigs::UpdateEntityLists(void)
  403. {
  404. if(m_pLastSelConfig == NULL)
  405. return;
  406. m_cDefaultPoint.ResetContent();
  407. m_cDefaultSolid.ResetContent();
  408. CGameConfig *pConfig = m_pLastSelConfig;
  409. int nCount = pConfig->GD.GetClassCount();
  410. for (int i = 0; i < nCount; i++)
  411. {
  412. GDclass *pClass = pConfig->GD.GetClass(i);
  413. if (pClass->IsBaseClass())
  414. {
  415. continue;
  416. }
  417. else if (pClass->IsSolidClass())
  418. {
  419. m_cDefaultSolid.AddString(pClass->GetName());
  420. }
  421. else
  422. {
  423. m_cDefaultPoint.AddString(pClass->GetName());
  424. }
  425. }
  426. if (pConfig->szDefaultSolid[0] != '\0')
  427. {
  428. m_cDefaultSolid.SetWindowText(pConfig->szDefaultSolid);
  429. }
  430. else
  431. {
  432. m_cDefaultSolid.SetCurSel(0);
  433. }
  434. if (pConfig->szDefaultPoint[0] != '\0')
  435. {
  436. m_cDefaultPoint.SetWindowText(pConfig->szDefaultPoint);
  437. }
  438. else
  439. {
  440. m_cDefaultPoint.SetCurSel(0);
  441. }
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Purpose: Fills the combo box with the list of configs. Tries to select the
  445. // config that was selected before coming in or, failing that, the
  446. // currently active config.
  447. //-----------------------------------------------------------------------------
  448. void UpdateConfigList(CComboBox &combo)
  449. {
  450. int iCurSel = combo.GetCurSel();
  451. DWORD dwSelID = 0xffffffff;
  452. if (iCurSel != CB_ERR)
  453. {
  454. dwSelID = combo.GetItemData(iCurSel);
  455. }
  456. combo.ResetContent();
  457. // add configs to the combo box
  458. for (int i = 0; i < Options.configs.nConfigs; i++)
  459. {
  460. CGameConfig *pConfig = Options.configs.Configs[i];
  461. int iIndex = combo.AddString(pConfig->szName);
  462. combo.SetItemData(iIndex, pConfig->dwID);
  463. }
  464. if (dwSelID == 0xffffffff)
  465. {
  466. dwSelID = g_pGameConfig->dwID;
  467. }
  468. // Find the item with the given ID.
  469. int nSelIndex = -1;
  470. for (int i = 0; i < Options.configs.nConfigs; i++)
  471. {
  472. DWORD dwData = combo.GetItemData(i);
  473. if (dwData == dwSelID)
  474. {
  475. nSelIndex = i;
  476. }
  477. }
  478. combo.SetCurSel(nSelIndex == -1 ? 0 : nSelIndex);
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose:
  482. //-----------------------------------------------------------------------------
  483. void SelectActiveConfig(CComboBox &combo)
  484. {
  485. char szGameDir[MAX_PATH];
  486. if (GetPersistentEnvironmentVariable(GAMEDIR_TOKEN, szGameDir, sizeof(szGameDir)))
  487. {
  488. CGameConfig *pConfig = Options.configs.FindConfigForGame(szGameDir);
  489. if (pConfig)
  490. {
  491. // Find the item with the given ID.
  492. int nSelIndex = -1;
  493. int nCount = combo.GetCount();
  494. for (int i = 0; i < nCount; i++)
  495. {
  496. DWORD dwData = combo.GetItemData(i);
  497. if (pConfig->dwID == dwData)
  498. {
  499. nSelIndex = i;
  500. break;
  501. }
  502. }
  503. if (nSelIndex != -1)
  504. {
  505. combo.SetCurSel(nSelIndex);
  506. }
  507. }
  508. }
  509. }
  510. //-----------------------------------------------------------------------------
  511. // Purpose:
  512. //-----------------------------------------------------------------------------
  513. void COPTConfigs::UpdateConfigList()
  514. {
  515. m_pLastSelConfig = NULL;
  516. ::UpdateConfigList(m_cConfigs);
  517. ::SelectActiveConfig(m_cConfigs);
  518. OnSelchangeConfigurations();
  519. SetModified();
  520. }
  521. //-----------------------------------------------------------------------------
  522. // Purpose: Populates the combo boxes with the map formats and WAD formats, and
  523. // the list of game configurations.
  524. //-----------------------------------------------------------------------------
  525. BOOL COPTConfigs::OnInitDialog(void)
  526. {
  527. CPropertyPage::OnInitDialog();
  528. int nIndex;
  529. //
  530. // Add map formats.
  531. //
  532. nIndex = m_cMapFormat.AddString("Half-Life 2");
  533. m_cMapFormat.SetItemData(nIndex, mfHalfLife2);
  534. nIndex = m_cMapFormat.AddString("Half-Life / TFC");
  535. m_cMapFormat.SetItemData(nIndex, mfHalfLife);
  536. //
  537. // Add texture formats.
  538. //
  539. nIndex = m_cTextureFormat.AddString("Materials (Half-Life 2)");
  540. m_cTextureFormat.SetItemData(nIndex, tfVMT);
  541. nIndex = m_cTextureFormat.AddString("WAD3 (Half-Life / TFC)");
  542. m_cTextureFormat.SetItemData(nIndex, tfWAD3);
  543. UpdateConfigList();
  544. int nCurSel = m_cConfigs.GetCurSel();
  545. m_pInitialSelectedConfig = Options.configs.FindConfig(m_cConfigs.GetItemData(nCurSel));
  546. m_strInitialGameDir.Empty();
  547. if (m_pInitialSelectedConfig)
  548. {
  549. m_strInitialGameDir = m_pInitialSelectedConfig->m_szModDir;
  550. }
  551. return TRUE;
  552. }
  553. //-----------------------------------------------------------------------------
  554. // Purpose: Returns true if the given config is different from the one set when
  555. // OnInitDialog was called.
  556. //-----------------------------------------------------------------------------
  557. bool COPTConfigs::ConfigChanged(CGameConfig *pConfig)
  558. {
  559. if (m_pInitialSelectedConfig != pConfig)
  560. return true;
  561. if (pConfig && m_pInitialSelectedConfig)
  562. {
  563. if (m_pInitialSelectedConfig->dwID != pConfig->dwID)
  564. return true;
  565. if (m_strInitialGameDir.CompareNoCase(pConfig->m_szModDir))
  566. return true;
  567. }
  568. return false;
  569. }
  570. //-----------------------------------------------------------------------------
  571. // Purpose:
  572. // Output : Returns TRUE on success, FALSE on failure.
  573. //-----------------------------------------------------------------------------
  574. BOOL COPTConfigs::OnApply(void)
  575. {
  576. SaveInfo(m_pLastSelConfig);
  577. int nCurSel = m_cConfigs.GetCurSel();
  578. CGameConfig *pConfig = Options.configs.FindConfig(m_cConfigs.GetItemData(nCurSel));
  579. if ( pConfig != NULL && ConfigChanged( pConfig ) )
  580. {
  581. SetPersistentEnvironmentVariable("vproject", pConfig->m_szModDir);
  582. AfxMessageBox("Your changes to the active configuration will not take effect until the next time you run Hammer.");
  583. }
  584. Options.PerformChanges(COptions::secConfigs);
  585. return CPropertyPage::OnApply();
  586. }
  587. //-----------------------------------------------------------------------------
  588. // Purpose:
  589. // Input : *pszTitle -
  590. // *pszDirectory -
  591. // Output : Returns TRUE on success, FALSE on failure.
  592. //-----------------------------------------------------------------------------
  593. BOOL COPTConfigs::BrowseForFolder(char *pszTitle, char *pszDirectory)
  594. {
  595. char szTmp[MAX_PATH];
  596. BROWSEINFO bi;
  597. memset(&bi, 0, sizeof bi);
  598. bi.hwndOwner = m_hWnd;
  599. bi.pszDisplayName = szTmp;
  600. bi.lpszTitle = pszTitle;
  601. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  602. LPITEMIDLIST idl = SHBrowseForFolder(&bi);
  603. if(idl == NULL)
  604. return FALSE;
  605. SHGetPathFromIDList(idl, pszDirectory);
  606. CoTaskMemFree(idl);
  607. return TRUE;
  608. }
  609. //-----------------------------------------------------------------------------
  610. // Purpose:
  611. //-----------------------------------------------------------------------------
  612. void COPTConfigs::OnBrowseCordonTexture(void)
  613. {
  614. CTextureBrowser *pBrowser = new CTextureBrowser(this);
  615. if (pBrowser != NULL)
  616. {
  617. //
  618. // Use the currently selected texture format for browsing.
  619. //
  620. TEXTUREFORMAT eTextureFormat = tfVMT;
  621. int nIndex = m_cTextureFormat.GetCurSel();
  622. if (nIndex != LB_ERR)
  623. {
  624. eTextureFormat = (TEXTUREFORMAT)m_cTextureFormat.GetItemData(nIndex);
  625. }
  626. pBrowser->SetTextureFormat(eTextureFormat);
  627. //
  628. // Select the current cordon texture in the texture browser.
  629. //
  630. CString strTex;
  631. m_cCordonTexture.GetWindowText(strTex);
  632. pBrowser->SetInitialTexture(strTex);
  633. if (pBrowser->DoModal() == IDOK)
  634. {
  635. m_cCordonTexture.SetWindowText(pBrowser->m_cTextureWindow.szCurTexture);
  636. }
  637. delete pBrowser;
  638. }
  639. }
  640. //-----------------------------------------------------------------------------
  641. // Purpose:
  642. //-----------------------------------------------------------------------------
  643. void COPTConfigs::OnBrowseGameExeDir(void)
  644. {
  645. char szTmp[MAX_PATH];
  646. if (!BrowseForFolder("Select Game Executable Directory", szTmp))
  647. {
  648. return;
  649. }
  650. CString str(szTmp);
  651. EditorUtil_ConvertPath(str, false);
  652. m_cGameExeDir.SetWindowText(str);
  653. }
  654. //-----------------------------------------------------------------------------
  655. // Purpose:
  656. //-----------------------------------------------------------------------------
  657. void COPTConfigs::OnBrowseModDir(void)
  658. {
  659. char szTmp[MAX_PATH];
  660. if (!BrowseForFolder("Select Mod Directory", szTmp))
  661. {
  662. return;
  663. }
  664. CString str(szTmp);
  665. EditorUtil_ConvertPath(str, false);
  666. m_cModDir.SetWindowText(str);
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Purpose:
  670. //-----------------------------------------------------------------------------
  671. void COPTConfigs::OnBrowsemapdir(void)
  672. {
  673. char szTmp[MAX_PATH];
  674. if (!BrowseForFolder("Select Map Directory", szTmp))
  675. {
  676. return;
  677. }
  678. CString str(szTmp);
  679. EditorUtil_ConvertPath(str, false);
  680. m_cMapDir.SetWindowText(str);
  681. }
  682. //-----------------------------------------------------------------------------
  683. // Purpose:
  684. //-----------------------------------------------------------------------------
  685. void COPTConfigs::OnBrowsePrefabDir(void)
  686. {
  687. char szTmp[MAX_PATH];
  688. if (!BrowseForFolder("Select Map Directory", szTmp))
  689. {
  690. return;
  691. }
  692. CString str(szTmp);
  693. EditorUtil_ConvertPath(str, false);
  694. m_cPrefabDir.SetWindowText(str);
  695. }
  696. //-----------------------------------------------------------------------------
  697. // Purpose: Handles the notification from the VCONFIG that the active config has changed.
  698. //-----------------------------------------------------------------------------
  699. LRESULT COPTConfigs::OnSettingChange(WPARAM wParam, LPARAM lParam)
  700. {
  701. const char *changedSection = (const char *)lParam;
  702. if ( Q_stricmp( changedSection, "Environment" ) == 0 )
  703. {
  704. UpdateConfigList();
  705. //SelectActiveConfig();
  706. }
  707. return 0;
  708. }