Team Fortress 2 Source Code as on 22/4/2020
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.

839 lines
22 KiB

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