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.

490 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // ModelCheckInDlg.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "ModelCheckIn.h"
  12. #include "ModelCheckInDlg.h"
  13. #include <direct.h>
  14. #include <sys/stat.h>
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CModelCheckInDlg dialog
  22. CModelCheckInDlg::CModelCheckInDlg(CWnd* pParent /*=NULL*/)
  23. : CDialog(CModelCheckInDlg::IDD, pParent)
  24. {
  25. //{{AFX_DATA_INIT(CModelCheckInDlg)
  26. m_HL2GameDirectory = _T("");
  27. m_TF2GameDirectory = _T("");
  28. m_UserName = _T("");
  29. m_HL2Radio = -1;
  30. m_TF2Radio = -1;
  31. //}}AFX_DATA_INIT
  32. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  33. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  34. }
  35. void CModelCheckInDlg::DoDataExchange(CDataExchange* pDX)
  36. {
  37. CDialog::DoDataExchange(pDX);
  38. //{{AFX_DATA_MAP(CModelCheckInDlg)
  39. DDX_Text(pDX, IDC_EDIT_HL2_GAME_DIRECTORY, m_HL2GameDirectory);
  40. DDX_Text(pDX, IDC_EDIT_TF2_GAME_DIRECTORY, m_TF2GameDirectory);
  41. DDX_Text(pDX, IDC_EDIT_USERNAME, m_UserName);
  42. //}}AFX_DATA_MAP
  43. }
  44. BEGIN_MESSAGE_MAP(CModelCheckInDlg, CDialog)
  45. //{{AFX_MSG_MAP(CModelCheckInDlg)
  46. ON_WM_PAINT()
  47. ON_WM_QUERYDRAGICON()
  48. //}}AFX_MSG_MAP
  49. ON_COMMAND(ID_FILE_CHECK_OUT, OnFileCheckOut)
  50. ON_COMMAND(ID_FILE_CHECK_IN, OnFileCheckIn)
  51. ON_COMMAND(ID_FILE_EXIT, OnFileExit)
  52. END_MESSAGE_MAP()
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CModelCheckInDlg message handlers
  55. BOOL CModelCheckInDlg::OnInitDialog()
  56. {
  57. CDialog::OnInitDialog();
  58. // Restore state
  59. RestoreStateFromRegistry();
  60. UpdateData( FALSE );
  61. // Set the icon for this dialog. The framework does this automatically
  62. // when the application's main window is not a dialog
  63. SetIcon(m_hIcon, TRUE); // Set big icon
  64. SetIcon(m_hIcon, FALSE); // Set small icon
  65. // TODO: Add extra initialization here
  66. return TRUE; // return TRUE unless you set the focus to a control
  67. }
  68. // If you add a minimize button to your dialog, you will need the code below
  69. // to draw the icon. For MFC applications using the document/view model,
  70. // this is automatically done for you by the framework.
  71. void CModelCheckInDlg::OnPaint()
  72. {
  73. if (IsIconic())
  74. {
  75. CPaintDC dc(this); // device context for painting
  76. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  77. // Center icon in client rectangle
  78. int cxIcon = GetSystemMetrics(SM_CXICON);
  79. int cyIcon = GetSystemMetrics(SM_CYICON);
  80. CRect rect;
  81. GetClientRect(&rect);
  82. int x = (rect.Width() - cxIcon + 1) / 2;
  83. int y = (rect.Height() - cyIcon + 1) / 2;
  84. // Draw the icon
  85. dc.DrawIcon(x, y, m_hIcon);
  86. }
  87. else
  88. {
  89. CDialog::OnPaint();
  90. }
  91. }
  92. // The system calls this to obtain the cursor to display while the user drags
  93. // the minimized window.
  94. HCURSOR CModelCheckInDlg::OnQueryDragIcon()
  95. {
  96. return (HCURSOR) m_hIcon;
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Resets our last used directory
  100. //-----------------------------------------------------------------------------
  101. void CModelCheckInDlg::ResetDirectoryEntry( CString &fullPath, char *pRegEntry )
  102. {
  103. // reset the last directory...
  104. CString temp = fullPath;
  105. int i = temp.ReverseFind( '\\' );
  106. int j = temp.ReverseFind( '/' );
  107. if (i < j) i = j;
  108. temp.SetAt(i, 0);
  109. AfxGetApp()->WriteProfileString( MDL_CHECKOUT_REG_CLASS, pRegEntry, temp );
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Stores state
  113. //-----------------------------------------------------------------------------
  114. void CModelCheckInDlg::StoreStateIntoRegistry( )
  115. {
  116. AfxGetApp()->WriteProfileString( MDL_CHECKOUT_REG_CLASS,
  117. MDL_CHECKOUT_REG_USER, m_UserName );
  118. AfxGetApp()->WriteProfileString( MDL_CHECKOUT_REG_CLASS,
  119. MDL_CHECKOUT_REG_HL2_PATH, m_HL2GameDirectory );
  120. AfxGetApp()->WriteProfileString( MDL_CHECKOUT_REG_CLASS,
  121. MDL_CHECKOUT_REG_TF2_PATH, m_TF2GameDirectory );
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Restores state
  125. //-----------------------------------------------------------------------------
  126. void CModelCheckInDlg::RestoreStateFromRegistry( )
  127. {
  128. m_UserName = AfxGetApp()->GetProfileString( MDL_CHECKOUT_REG_CLASS,
  129. MDL_CHECKOUT_REG_USER, "" );
  130. m_HL2GameDirectory = AfxGetApp()->GetProfileString( MDL_CHECKOUT_REG_CLASS,
  131. MDL_CHECKOUT_REG_HL2_PATH, "u:/hl2/hl2" );
  132. m_TF2GameDirectory = AfxGetApp()->GetProfileString( MDL_CHECKOUT_REG_CLASS,
  133. MDL_CHECKOUT_REG_TF2_PATH, "u:/hl2/tf2" );
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Extensions of all files related to the model file
  137. //-----------------------------------------------------------------------------
  138. static char* s_ppExtensions[] =
  139. {
  140. ".dx7_2bone.vtx",
  141. ".dx80.vtx",
  142. ".phy",
  143. ".mdl",
  144. ""
  145. };
  146. static char* s_ppProjectDir[] =
  147. {
  148. "$/HL2/release/dev/hl2/",
  149. "$/TF2/release/dev/tf2/"
  150. };
  151. //-----------------------------------------------------------------------------
  152. // Checks it out/ checks it in baby
  153. //-----------------------------------------------------------------------------
  154. void CModelCheckInDlg::PerformCheckoutCommand( ProjectType_t project,
  155. char const* pRelativeDir, char const* pDestPath, char const* pFileName )
  156. {
  157. char error[1024];
  158. char buf[1024];
  159. int len = 0;
  160. int currExtension;
  161. for ( currExtension = 0; s_ppExtensions[currExtension][0]; ++currExtension )
  162. {
  163. // Check for the existence of the file in source safe...
  164. sprintf( buf, "ss filetype %s%s/%s%s -O- -y%s\n",
  165. s_ppProjectDir[project], pRelativeDir, pFileName, s_ppExtensions[currExtension],
  166. (char const*)m_UserName );
  167. int retVal = system( buf );
  168. if (retVal > 0)
  169. continue;
  170. // It's there, try to check it out
  171. sprintf( buf, "ss checkout %s%s/%s%s -GL%s -GWA -O- -y%s\n",
  172. s_ppProjectDir[project], pRelativeDir, pFileName, s_ppExtensions[currExtension],
  173. pDestPath, (char const*)m_UserName );
  174. retVal = system( buf );
  175. if (retVal > 0)
  176. {
  177. len += sprintf( &error[len], "*** SourceSafe error attempting to check out \"%s%s\"\n",
  178. pFileName, s_ppExtensions[currExtension] );
  179. }
  180. }
  181. if (len > 0)
  182. {
  183. MessageBox( error, "Error!" );
  184. }
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Checks it out/ checks it in baby
  188. //-----------------------------------------------------------------------------
  189. void CModelCheckInDlg::PerformCheckinCommand( ProjectType_t project,
  190. char const* pRelativeDir, char const* pDestPath, char const* pFileName )
  191. {
  192. char buf[1024];
  193. char error[1024];
  194. int len = 0;
  195. int currExtension;
  196. for ( currExtension = 0; s_ppExtensions[currExtension][0]; ++currExtension )
  197. {
  198. // Check for the existence of the file on disk. If it's not there, don't bother
  199. sprintf( buf, "%s/%s%s", pDestPath, pFileName, s_ppExtensions[currExtension] );
  200. struct _stat statbuf;
  201. int result = _stat( buf, &statbuf );
  202. if (result != 0)
  203. continue;
  204. // Check for the existence of the file in source safe...
  205. sprintf( buf, "ss filetype %s%s/%s%s -O- -y%s\n",
  206. s_ppProjectDir[project], pRelativeDir, pFileName, s_ppExtensions[currExtension],
  207. (char const*)m_UserName );
  208. int retVal = system( buf );
  209. if (retVal > 0)
  210. {
  211. // Try to add the file to source safe...
  212. sprintf( buf, "ss add %s%s/%s%s -GL%s -O- -y%s\n",
  213. s_ppProjectDir[project], pRelativeDir, pFileName, s_ppExtensions[currExtension],
  214. pDestPath, (char const*)m_UserName );
  215. int retVal = system( buf );
  216. if (retVal > 0)
  217. {
  218. len += sprintf( &error[len], "SourceSafe error attempting to add \"%s%s\"\n",
  219. pFileName, s_ppExtensions[currExtension] );
  220. }
  221. }
  222. else
  223. {
  224. // It's there, just check it in
  225. sprintf( buf, "ss checkin %s%s/%s%s -GL%s -O- -y%s\n",
  226. s_ppProjectDir[project], pRelativeDir, pFileName, s_ppExtensions[currExtension],
  227. pDestPath, (char const*)m_UserName );
  228. retVal = system( buf );
  229. if (retVal > 0)
  230. {
  231. len += sprintf( &error[len], "SourceSafe error attempting to check in \"%s%s\"\n",
  232. pFileName, s_ppExtensions[currExtension] );
  233. }
  234. }
  235. }
  236. if (len > 0)
  237. {
  238. MessageBox( error, "Error!" );
  239. }
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Fixes up a filename
  243. //-----------------------------------------------------------------------------
  244. static int FixupFileName( char const* pInFile, char* pOutBuf )
  245. {
  246. if (!pInFile)
  247. {
  248. *pOutBuf = '\0';
  249. return 0;
  250. }
  251. int len = strlen(pInFile);
  252. for (int i = 0; i <= len; ++i)
  253. {
  254. pOutBuf[i] = tolower( pInFile[i] );
  255. if (pOutBuf[i] == '\\')
  256. pOutBuf[i] = '/';
  257. }
  258. // Make sure no trailing '/'
  259. if (pOutBuf[len - 1] == '/')
  260. pOutBuf[--len] = '\0';
  261. return len;
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Gets the relative file name
  265. //-----------------------------------------------------------------------------
  266. CModelCheckInDlg::ProjectType_t CModelCheckInDlg::ComputeRelativeFileName( char const* pInFile, char* pRelativeFile )
  267. {
  268. // Depending on which project is selected, strip out the game directory
  269. char tempIn[MAX_PATH];
  270. char tempPath[MAX_PATH];
  271. FixupFileName( pInFile, tempIn );
  272. int len;
  273. if (!m_HL2GameDirectory.IsEmpty())
  274. {
  275. len = FixupFileName( m_HL2GameDirectory, tempPath );
  276. if (!strncmp( tempIn, m_HL2GameDirectory, len ))
  277. {
  278. strcpy( pRelativeFile, &tempIn[len+1] );
  279. return PROJECT_HL2;
  280. }
  281. }
  282. if (!m_TF2GameDirectory.IsEmpty())
  283. {
  284. len = FixupFileName( m_TF2GameDirectory, tempPath );
  285. if (!strncmp( tempIn, m_TF2GameDirectory, len ))
  286. {
  287. strcpy( pRelativeFile, &tempIn[len+1] );
  288. return PROJECT_TF2;
  289. }
  290. }
  291. return PROJECT_ERROR;
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Have we typed in anything for our user name?
  295. //-----------------------------------------------------------------------------
  296. bool CModelCheckInDlg::CheckInfo()
  297. {
  298. if (m_UserName.IsEmpty())
  299. {
  300. MessageBox( "Please enter your user name.\n", "Error!" );
  301. return false;
  302. }
  303. if (m_HL2GameDirectory.IsEmpty() && m_TF2GameDirectory.IsEmpty())
  304. {
  305. MessageBox( "Please enter the game directories for HL2 and/or TF2.\n", "Error!" );
  306. return false;
  307. }
  308. return true;
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Resets our last used directory
  312. //-----------------------------------------------------------------------------
  313. CModelCheckInDlg::ProjectType_t CModelCheckInDlg::GetFileNames( char const* pTitle,
  314. char*& pRelativePath, char*& pFileName, char*& pDestPath )
  315. {
  316. UpdateData( TRUE );
  317. StoreStateIntoRegistry();
  318. if (!CheckInfo())
  319. return PROJECT_ERROR;
  320. CFileDialog dlg( TRUE, ".mdl", "*.mdl", OFN_HIDEREADONLY,
  321. "Model Files (*.mdl)|*.mdl||" );
  322. // Set up initial paths
  323. char pCwd[MAX_PATH];
  324. _getcwd( pCwd, MAX_PATH );
  325. // Setup the title and initial directory
  326. CString temp = AfxGetApp()->GetProfileString( MDL_CHECKOUT_REG_CLASS,
  327. MDL_CHECKOUT_REG_LAST_PATH, pCwd );
  328. dlg.m_ofn.lpstrInitialDir = temp;
  329. dlg.m_ofn.lpstrTitle = pTitle;
  330. // Grab the data from the dialog...
  331. if (dlg.DoModal() != IDOK)
  332. return PROJECT_ERROR;
  333. // Get the relative file name
  334. static char relativeFile[MAX_PATH];
  335. ProjectType_t projectType = ComputeRelativeFileName( dlg.GetPathName(), relativeFile );
  336. if (projectType == PROJECT_ERROR)
  337. {
  338. char buf[MAX_PATH];
  339. sprintf( buf, "%s\nwas not found under either game directory!\n", dlg.GetPathName() );
  340. MessageBox( buf, "Error!" );
  341. return PROJECT_ERROR;
  342. }
  343. // reset the last directory...
  344. ResetDirectoryEntry( dlg.GetPathName(), MDL_CHECKOUT_REG_LAST_PATH );
  345. // Split into relative file + path...
  346. char* pSlash = strrchr( relativeFile, '/' );
  347. if (pSlash)
  348. {
  349. *pSlash = 0;
  350. pRelativePath = relativeFile;
  351. pFileName = pSlash + 1;
  352. }
  353. else
  354. {
  355. pFileName = relativeFile;
  356. pRelativePath = "";
  357. }
  358. // Remove extension
  359. char* pExt = strchr( pFileName, '.' );
  360. if (pExt)
  361. *pExt = 0;
  362. static char destPath[MAX_PATH];
  363. FixupFileName( dlg.GetPathName(), destPath );
  364. pSlash = strrchr( destPath, '/' );
  365. if (pSlash)
  366. *pSlash = 0;
  367. else
  368. destPath[0] = 0;
  369. pDestPath = destPath;
  370. return projectType;
  371. }
  372. //-----------------------------------------------------------------------------
  373. // Does checkout and check-in
  374. //-----------------------------------------------------------------------------
  375. void CModelCheckInDlg::OnFileCheckOut()
  376. {
  377. char* pRelativePath;
  378. char* pFileName;
  379. char* pDestPath;
  380. ProjectType_t projectType;
  381. projectType = GetFileNames( "Select MDL file to check out...", pRelativePath,
  382. pFileName, pDestPath );
  383. if (projectType != PROJECT_ERROR)
  384. {
  385. PerformCheckoutCommand( projectType, pRelativePath, pDestPath, pFileName );
  386. }
  387. }
  388. void CModelCheckInDlg::OnFileCheckIn()
  389. {
  390. char* pRelativePath;
  391. char* pFileName;
  392. char* pDestPath;
  393. ProjectType_t projectType;
  394. projectType = GetFileNames( "Select MDL file to check in...", pRelativePath,
  395. pFileName, pDestPath );
  396. if (projectType != PROJECT_ERROR)
  397. {
  398. PerformCheckinCommand( projectType, pRelativePath, pDestPath, pFileName );
  399. }
  400. }
  401. void CModelCheckInDlg::OnFileExit()
  402. {
  403. PostQuitMessage(0);
  404. }