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.

726 lines
22 KiB

  1. //====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #if defined(WIN32) && !defined( _GAMECONSOLE )
  7. #include <windows.h>
  8. #endif
  9. #include "filesystem.h"
  10. #include "filesystem_init.h"
  11. #include "appframework/IAppSystemGroup.h"
  12. #include "appframework/iappsystem.h"
  13. #include "appframework/AppFramework.h"
  14. #include "filesystem_helpers.h"
  15. #include "matsys_controls/QCGenerator.h"
  16. #include "tier1/keyvalues.h"
  17. #include "tier2/vconfig.h"
  18. #include "vgui_controls/ListPanel.h"
  19. #include "vgui_controls/TextEntry.h"
  20. #include "vgui_controls/Button.h"
  21. #include "vgui_controls/FileOpenDialog.h"
  22. #include "vgui_controls/DirectorySelectDialog.h"
  23. #include "vgui_controls/ComboBox.h"
  24. #include "vgui_controls/CheckButton.h"
  25. #include "vgui_controls/MessageBox.h"
  26. #include "vgui/ISurface.h"
  27. #include "vgui/IInput.h"
  28. #include "vgui/Cursor.h"
  29. #include "vgui_controls/KeyBoardEditorDialog.h"
  30. #if defined( _X360 )
  31. #include "xbox/xbox_win32stubs.h"
  32. #endif
  33. // NOTE: This has to be the last file included!
  34. #include "tier0/memdbgon.h"
  35. using namespace vgui;
  36. #define MAX_KEYVALUE 1024
  37. //-----------------------------------------------------------------------------
  38. // Purpose: returns a pointer to the 'count' occurence of a character from the end of a string
  39. // returns 0 of there aren't 'count' number of the character in the string
  40. //-----------------------------------------------------------------------------
  41. char *strrchrcount(char *string, int character, int count )
  42. {
  43. int j = count;
  44. int numChars = strlen( string );
  45. for( int i = numChars; i > 0; i-- )
  46. {
  47. if( string[i-1] == character )
  48. {
  49. j--;
  50. }
  51. if( j == 0 )
  52. {
  53. return string + i-1;
  54. }
  55. }
  56. return 0;
  57. }
  58. class CModalPreserveMessageBox : public vgui::MessageBox
  59. {
  60. public:
  61. CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
  62. : vgui::MessageBox( title, text, parent )
  63. {
  64. m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
  65. }
  66. ~CModalPreserveMessageBox()
  67. {
  68. vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
  69. }
  70. public:
  71. vgui::VPANEL m_PrevAppFocusPanel;
  72. };
  73. void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
  74. {
  75. char msg[4096];
  76. va_list marker;
  77. va_start( marker, pMsg );
  78. Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
  79. va_end( marker );
  80. vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
  81. dlg->DoModal();
  82. dlg->Activate();
  83. dlg->RequestFocus();
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose: Places all the info from the vgui controls into the QCInfo struct
  87. //-----------------------------------------------------------------------------
  88. void QCInfo::SyncFromControls()
  89. {
  90. char tempText[MAX_PATH];
  91. vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
  92. bStaticProp = ((CheckButton *)pTargetField)->IsSelected();
  93. pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
  94. bMostlyOpaque = ((CheckButton *)pTargetField)->IsSelected();
  95. pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
  96. bDisableCollision = ((CheckButton *)pTargetField)->IsSelected();
  97. pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
  98. bReferenceAsPhys = ((CheckButton *)pTargetField)->IsSelected();
  99. pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
  100. bConcave = ((CheckButton *)pTargetField)->IsSelected();
  101. pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
  102. bAutomass = ((CheckButton *)pTargetField)->IsSelected();
  103. pTargetField = pQCGenerator->FindChildByName( "massField" );
  104. ((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
  105. fMass = atof(tempText);
  106. pTargetField = pQCGenerator->FindChildByName( "scaleField" );
  107. ((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
  108. fScale = atof(tempText);
  109. pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
  110. ((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
  111. Q_strcpy( pszCollisionPath, tempText );
  112. pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
  113. ((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
  114. Q_strcpy( pszSurfaceProperty, tempText );
  115. pTargetField = pQCGenerator->FindChildByName( "materialsField" );
  116. ((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
  117. Q_strcpy( pszMaterialPath, tempText );
  118. LODs.RemoveAll();
  119. pTargetField = pQCGenerator->FindChildByName( "LODList" );
  120. int numLOD = ((ListPanel *)pTargetField)->GetItemCount();
  121. for ( int i = 0; i < numLOD; i++ )
  122. {
  123. KeyValues *key = ((ListPanel *)pTargetField)->GetItem( i );
  124. LODInfo newLOD;
  125. Q_strcpy( newLOD.pszFilename, key->GetString( "SMD" ) );
  126. newLOD.iLOD = key->GetInt( "LOD" );
  127. LODs.AddToTail( newLOD );
  128. }
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: Called during intialization to setup the initial state of the VGUI controls
  132. //-----------------------------------------------------------------------------
  133. void QCInfo::SyncToControls()
  134. {
  135. char tempText[MAX_PATH];
  136. vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
  137. ((CheckButton *)pTargetField)->SetSelected( bStaticProp );
  138. pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
  139. ((CheckButton *)pTargetField)->SetSelected( bMostlyOpaque );
  140. pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
  141. ((CheckButton *)pTargetField)->SetSelected( bDisableCollision );
  142. pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
  143. ((CheckButton *)pTargetField)->SetSelected( bReferenceAsPhys );
  144. pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
  145. ((CheckButton *)pTargetField)->SetSelected( bConcave );
  146. pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
  147. ((CheckButton *)pTargetField)->SetSelected( bAutomass );
  148. Q_snprintf( tempText, 10, "%d", (int)fMass );
  149. pTargetField = pQCGenerator->FindChildByName( "massField" );
  150. ((TextEntry *)pTargetField)->SetText( tempText );
  151. Q_snprintf( tempText, 10, "%d", (int)fScale );
  152. pTargetField = pQCGenerator->FindChildByName( "scaleField" );
  153. ((TextEntry *)pTargetField)->SetText( tempText );
  154. pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
  155. ((TextEntry *)pTargetField)->SetText( pszCollisionPath );
  156. pTargetField = pQCGenerator->FindChildByName( "materialsField" );
  157. ((TextEntry *)pTargetField)->SetText( pszMaterialPath );
  158. pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
  159. int numItems = ((ComboBox *)pTargetField)->GetItemCount();
  160. for( int i = 0; i < numItems; i++ )
  161. {
  162. ((ComboBox *)pTargetField)->GetItemText( i, tempText, MAX_PATH );
  163. if ( !Q_strcmp( tempText, pszSurfaceProperty ) )
  164. {
  165. ((ComboBox *)pTargetField)->SetItemEnabled( i, true );
  166. ((ComboBox *)pTargetField)->SetText( tempText );
  167. break;
  168. }
  169. }
  170. }
  171. CBrowseButton::CBrowseButton( vgui::Panel *pParent ) : BaseClass( pParent, "Browse Button", "...", pParent, "browse" )
  172. {
  173. SetParent( pParent );
  174. pszStartingDirectory = NULL;
  175. pszFileFilter = NULL;
  176. pszTargetField = NULL;
  177. }
  178. CBrowseButton::~CBrowseButton()
  179. {
  180. }
  181. void CBrowseButton::SetCharVar( char **pVar, const char *pszNewText )
  182. {
  183. if ( *pVar && pszNewText && !Q_strcmp( *pVar, pszNewText ) )
  184. {
  185. return;
  186. }
  187. if ( *pVar )
  188. {
  189. delete [] *pVar;
  190. *pVar = NULL;
  191. }
  192. if ( pszNewText )
  193. {
  194. int len = Q_strlen( pszNewText ) + 1;
  195. *pVar = new char[ len ];
  196. Q_strncpy( *pVar, pszNewText, len );
  197. }
  198. }
  199. void CBrowseButton::InitBrowseInfo( int x, int y, char *pszName, const char *pszDir, char *pszFilter, char *pszField )
  200. {
  201. SetSize( 24, 24 );
  202. SetPos( x, y );
  203. SetName( pszName );
  204. SetCharVar( GetStartingDirectory(), pszDir );
  205. SetCharVar( GetFileFilter(), pszFilter );
  206. SetCharVar( GetTargetField(), pszField );
  207. SetActionMessage();
  208. }
  209. void CBrowseButton::SetActionMessage()
  210. {
  211. KeyValues *newActionMessage = new KeyValues( "browse", "directory", pszStartingDirectory, "filter", pszFileFilter);
  212. newActionMessage->SetString( "targetField", pszTargetField );
  213. SetCommand( newActionMessage );
  214. }
  215. const char *ParseKeyvalue( const char *pBuffer, char *key, char *value )
  216. {
  217. char com_token[1024];
  218. pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
  219. if ( Q_strlen( com_token ) < MAX_KEYVALUE )
  220. {
  221. Q_strncpy( key, com_token, MAX_KEYVALUE );
  222. Q_strlower( key );
  223. }
  224. // no value on a close brace
  225. if ( !Q_strcmp( key, "}" ) )
  226. {
  227. value[0] = 0;
  228. return pBuffer;
  229. }
  230. pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
  231. if ( Q_strlen( com_token ) < MAX_KEYVALUE )
  232. {
  233. Q_strncpy( value, com_token, MAX_KEYVALUE );
  234. Q_strlower( value );
  235. }
  236. return pBuffer;
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose: Constructor
  240. //-----------------------------------------------------------------------------
  241. CQCGenerator::CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ) : BaseClass( pParent, "QCGenerator" )
  242. {
  243. m_QCInfo_t.Init( this );
  244. SetMinimumSize(846, 770);
  245. m_pLODPanel = new ListPanel(this, "LODList");
  246. m_pLODPanel->SetSelectIndividualCells( true );
  247. m_pLODPanel->AddColumnHeader(0, "SMD", "LOD SMD", 450, 0);
  248. m_pLODPanel->AddColumnHeader(1, "LOD", "LOD Distance", 50, 0);
  249. m_pLODPanel->AddActionSignalTarget( this );
  250. m_pLODPanel->SetMouseInputEnabled( true );
  251. LoadControlSettings( "QCGenerator.res" );
  252. m_pCollisionBrowseButton = new CBrowseButton( this );
  253. m_pCollisionBrowseButton->InitBrowseInfo( 808, 158, "collisionBrowseButton", pszPath, "*.smd", "collisionSMDField" );
  254. char szTerminatedPath[1024] = "\0";
  255. sprintf( szTerminatedPath, "%s\\", pszPath );
  256. InitializeSMDPaths( szTerminatedPath, pszScene );
  257. char *pszMaterialsStart = strrchrcount( szTerminatedPath, '\\', 3 ) + 1;
  258. char *pszMaterialsEnd = strrchr( szTerminatedPath, '\\');
  259. Q_strncpy( m_QCInfo_t.pszMaterialPath, pszMaterialsStart, pszMaterialsEnd - pszMaterialsStart + 1 );
  260. SetParent( pParent );
  261. char szGamePath[1024] = "\0";
  262. char szSearchPath[1024] = "\0";
  263. // Get the currently set game configuration
  264. GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
  265. static const char *pSurfacePropFilename = "\\scripts\\surfaceproperties.txt";
  266. sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
  267. FileHandle_t fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
  268. if ( !fp )
  269. {
  270. //the set game configuration didn't have a surfaceproperties file; we are grabbing it from hl2
  271. //TODO: This only works if they are in a subdirectory that is a peer to an hl2 directory
  272. // that contains the file. It potentially needs to search the entire drive or prompt for the location
  273. char *pszEndGamePath = Q_strrchr( szGamePath, '\\' );
  274. Q_strcpy( pszEndGamePath, "\\hl2" );
  275. sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
  276. fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
  277. }
  278. int len = g_pFullFileSystem->Size( fp );
  279. const char *szSurfacePropContents = new char[len+1];
  280. g_pFullFileSystem->Read( (void *)szSurfacePropContents, len, fp );
  281. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  282. vgui::Panel *pSurfacePropDropDown = FindChildByName( "surfacePropertyDropDown" );
  283. //filling up the surface property dropdown
  284. while ( szSurfacePropContents )
  285. {
  286. szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
  287. ((ComboBox *)pSurfacePropDropDown)->AddItem( key, NULL );
  288. while ( szSurfacePropContents )
  289. {
  290. szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
  291. if (!stricmp( key, "}" ) )
  292. {
  293. break;
  294. }
  295. }
  296. }
  297. m_QCInfo_t.SyncToControls();
  298. m_pLODEdit = 0;
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: Destructor
  302. //-----------------------------------------------------------------------------
  303. CQCGenerator::~CQCGenerator()
  304. {
  305. }
  306. void CQCGenerator::OnCommand( const char *command )
  307. {
  308. if ( Q_stricmp( command, "createQC" ) == 0 )
  309. {
  310. m_QCInfo_t.SyncFromControls();
  311. GenerateQCFile();
  312. }
  313. if ( Q_stricmp( command, "deleteSeq" ) == 0 )
  314. {
  315. //delete it
  316. DeleteLOD();
  317. }
  318. if ( Q_stricmp( command, "editSeq" ) == 0 )
  319. {
  320. //edit
  321. EditLOD();
  322. }
  323. BaseClass::OnCommand( command );
  324. }
  325. void CQCGenerator::OnKeyCodeTyped( KeyCode code )
  326. {
  327. switch ( code )
  328. {
  329. case KEY_ENTER:
  330. EditLOD();
  331. }
  332. }
  333. void CQCGenerator::OnBrowse( KeyValues *data )
  334. {
  335. Q_strcpy( m_szTargetField, data->GetString( "targetField" ) );
  336. const char *filter = data->GetString( "filter" );
  337. if ( Q_strlen( filter ) == 0 )
  338. {
  339. // BrowseDirectory( data );
  340. }
  341. else
  342. {
  343. BrowseFile( data );
  344. }
  345. }
  346. /*
  347. //This function is no longer used in the current version of the program.
  348. void CQCGenerator::BrowseDirectory( KeyValues *data )
  349. {
  350. DirectorySelectDialog *pDialog = new DirectorySelectDialog( this, "Select Directory" );
  351. pDialog->AddActionSignalTarget( this );
  352. pDialog->DoModal();
  353. pDialog->SetStartDirectory( data->GetString( "directory" ) );
  354. }
  355. */
  356. void CQCGenerator::BrowseFile( KeyValues *data )
  357. {
  358. const char *filter = data->GetString( "filter" );
  359. FileOpenDialog *pDialog = new FileOpenDialog( this, "Select File", true );
  360. pDialog->AddFilter( filter, filter, true );
  361. pDialog->AddActionSignalTarget(this);
  362. pDialog->SetStartDirectory( data->GetString( "directory" ) );
  363. pDialog->DoModal( true );
  364. }
  365. void CQCGenerator::OnFileSelected( KeyValues *data )
  366. {
  367. if ( m_szTargetField )
  368. {
  369. vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
  370. ((TextEntry *)pTargetField)->SetText( data->GetString( "fullpath" ) );
  371. Repaint();
  372. }
  373. }
  374. void CQCGenerator::OnDirectorySelected( KeyValues *data )
  375. {
  376. if ( m_szTargetField )
  377. {
  378. vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
  379. ((TextEntry *)pTargetField)->SetText( data->GetString( "dir" ) );
  380. Repaint();
  381. }
  382. }
  383. bool CQCGenerator::GenerateQCFile()
  384. {
  385. //TODO: clean this up. Consider creating a datatype that includes the string to write out when the QC file is created
  386. char *nameBegin = strrchr( m_QCInfo_t.pszSMDPath, '\\' );
  387. char szPath[MAX_PATH];
  388. char szName[MAX_PATH];
  389. Q_strncpy( szPath, m_QCInfo_t.pszSMDPath, nameBegin - m_QCInfo_t.pszSMDPath + 2 );
  390. strcpy( szName, szPath);
  391. strcat( szName, m_QCInfo_t.pszSceneName);
  392. strcat( szName, ".qc" );
  393. FileHandle_t pSaveFile = g_pFullFileSystem->Open( szName, "wt" );
  394. if (!pSaveFile)
  395. {
  396. char szSaveError[1024] = "";
  397. Q_snprintf( szSaveError, 1024, "Save failed: invalid file name '%s'\n\nDirectory '%s' must exist.", szName, szPath );
  398. VGUIMessageBox( this, "QC Generator error", szSaveError );
  399. return 0;
  400. }
  401. //write qc header
  402. g_pFullFileSystem->FPrintf( pSaveFile, "//\n// .qc file version 1.0\n\n");
  403. //write out modelname info
  404. char szModelName[MAX_PATH];
  405. char *modelStart = strrchrcount( szName, '\\', 2) + 1;
  406. char *modelEnd = strrchr( szName, '.' );
  407. Q_strncpy( szModelName, modelStart, modelEnd - modelStart + 1 );
  408. strcat( szModelName, ".mdl" );
  409. g_pFullFileSystem->FPrintf( pSaveFile, "$modelname %s\n\n", szModelName );
  410. //write out scale info
  411. g_pFullFileSystem->FPrintf( pSaveFile, "$scale %f\n", m_QCInfo_t.fScale );
  412. //write out body info
  413. g_pFullFileSystem->FPrintf( pSaveFile, "$body \"Body\" \"%s\"\n", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
  414. if ( m_QCInfo_t.bStaticProp == true )
  415. {
  416. g_pFullFileSystem->FPrintf( pSaveFile, "$staticprop\n" );
  417. }
  418. if ( m_QCInfo_t.bMostlyOpaque == true )
  419. {
  420. g_pFullFileSystem->FPrintf( pSaveFile, "$mostlyopaque\n" );
  421. }
  422. //write out surfaceprop info
  423. g_pFullFileSystem->FPrintf( pSaveFile, "$surfaceprop \"%s\"\n\n", m_QCInfo_t.pszSurfaceProperty );
  424. //write materials
  425. g_pFullFileSystem->FPrintf( pSaveFile, "$cdmaterials %s\n\n", m_QCInfo_t.pszMaterialPath);
  426. if ( m_QCInfo_t.bStaticProp || m_QCInfo_t.bNoAnimation )
  427. {
  428. g_pFullFileSystem->FPrintf( pSaveFile, "// --------- Animation sequences -------\n");
  429. g_pFullFileSystem->FPrintf( pSaveFile, "$sequence \"idle\" \"%s\" fps 30\n\n", strrchr(m_QCInfo_t.pszSMDPath, '\\')+1);
  430. }
  431. //write out lod info
  432. for( int i = 0; i < m_QCInfo_t.LODs.Count(); i++ )
  433. {
  434. LODInfo thisLOD = m_QCInfo_t.LODs.Element( i );
  435. g_pFullFileSystem->FPrintf( pSaveFile, "$lod %d\n{\n\treplacemodel \"%s\" \"%s\"\n}\n\n", thisLOD.iLOD, strrchr(m_QCInfo_t.pszSMDPath, '\\')+1, thisLOD.pszFilename );
  436. }
  437. if ( m_QCInfo_t.bDisableCollision != true )
  438. {
  439. //write out collision header
  440. g_pFullFileSystem->FPrintf( pSaveFile, "\n" );
  441. //write out collision info
  442. if ( m_QCInfo_t.bReferenceAsPhys == true )
  443. {
  444. g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
  445. }
  446. else
  447. {
  448. if( Q_strcmp( m_QCInfo_t.pszCollisionPath, "" ) )
  449. {
  450. g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszCollisionPath, '\\' ) + 1 );
  451. }
  452. }
  453. g_pFullFileSystem->FPrintf( pSaveFile, " {\n\t// Mass in kilograms\n ");
  454. if ( m_QCInfo_t.bAutomass == true )
  455. {
  456. g_pFullFileSystem->FPrintf( pSaveFile, "\t$automass\n" );
  457. }
  458. else
  459. {
  460. g_pFullFileSystem->FPrintf( pSaveFile, "\t$mass %f\n", m_QCInfo_t.fMass );
  461. }
  462. if ( m_QCInfo_t.bConcave == true )
  463. {
  464. g_pFullFileSystem->FPrintf( pSaveFile, "\t$concave\n" );
  465. }
  466. g_pFullFileSystem->FPrintf( pSaveFile, "}\n\n");
  467. }
  468. g_pFullFileSystem->Close( pSaveFile );
  469. char szCommand[MAX_PATH];
  470. char szGamePath[MAX_PATH];
  471. char studiomdlPath[512];
  472. g_pFullFileSystem->RelativePathToFullPath( "studiomdl.bat", NULL, studiomdlPath, sizeof( studiomdlPath ));
  473. GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
  474. #ifdef WIN32
  475. STARTUPINFO startup;
  476. PROCESS_INFORMATION process;
  477. memset(&startup, 0, sizeof(startup));
  478. startup.cb = sizeof(startup);
  479. sprintf( szCommand, "%s -game %s %s", studiomdlPath, szGamePath, szName);
  480. bool bReturn = CreateProcess( NULL, szCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startup, &process) ? true : false;
  481. #else
  482. Assert( !"Implement me, why aren't we using a thread tool abstraction?" );
  483. bool bReturn = false;
  484. #endif
  485. return bReturn;
  486. }
  487. void CQCGenerator::InitializeSMDPaths( const char *pszPath, const char *pszScene )
  488. {
  489. strcpy( m_QCInfo_t.pszSceneName, pszScene );
  490. FileFindHandle_t *pFileHandle = new FileFindHandle_t();
  491. g_pFullFileSystem->AddSearchPath( pszPath, "SMD_DIR" );
  492. const char *filename = g_pFullFileSystem->FindFirst( "*.smd", pFileHandle );
  493. bool bFoundReference = false;
  494. bool bFoundCollision = false;
  495. bool bFoundLOD = false;
  496. //iterate through .smd files
  497. const char *startName = pszScene;
  498. int nSearchLength = Q_strlen( pszScene );
  499. int currentLOD = 1;
  500. while( filename )
  501. {
  502. if ( !strncmp( startName, filename, nSearchLength ) )
  503. {
  504. const char *filenameEnd = filename + nSearchLength;
  505. if ( !strncmp( filenameEnd, "_ref", 4 ) || !strncmp( filenameEnd, ".smd", 4 ) )
  506. {
  507. bFoundReference = true;
  508. //we have found the reference smd.
  509. strcpy( m_QCInfo_t.pszSMDPath, pszPath );
  510. strcat( m_QCInfo_t.pszSMDPath, filename );
  511. }
  512. if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
  513. {
  514. bFoundCollision = true;
  515. //we have found the collision smd.
  516. strcpy( m_QCInfo_t.pszCollisionPath, pszPath );
  517. strcat( m_QCInfo_t.pszCollisionPath, filename );
  518. }
  519. if ( !strncmp( filenameEnd, "_lod", 4) )
  520. {
  521. bFoundLOD = true;
  522. //we found an LOD smd.
  523. char lodName[255];
  524. Q_snprintf( lodName, Q_strlen( lodName ), "lod%d", currentLOD );
  525. //we found an LOD
  526. KeyValues *newKv = new KeyValues( lodName, "SMD", filename, "LOD", "10" );
  527. m_pLODPanel->AddItem( newKv, currentLOD, false, false );
  528. currentLOD++;
  529. }
  530. }
  531. filename = g_pFullFileSystem->FindNext( *pFileHandle );
  532. }
  533. char pszMessage[2048] = "";
  534. char pszRefMessage[1024] = "";
  535. char pszColMessage[1024] = "";
  536. if (!bFoundReference )
  537. {
  538. strcat( m_QCInfo_t.pszSMDPath, pszPath );
  539. strcat( m_QCInfo_t.pszSMDPath, pszScene );
  540. strcat( m_QCInfo_t.pszSMDPath, ".smd" );
  541. Q_snprintf( pszRefMessage, 1024, "Reference SMD not found.\n\nValid default reference SMDs are %s%s_ref*.smd and %s%s.smd\nUsing default of %s. Model will not compile.\n\n", pszPath, pszScene, pszPath, pszScene, m_QCInfo_t.pszSMDPath );
  542. }
  543. if ( !bFoundCollision )
  544. {
  545. Q_snprintf( pszColMessage, 1024, "Collision SMD not found.\n\nThe valid default collision SMD is %s%s_phy*.smd.\nUsing reference SMD as default.\n", pszPath, pszScene );
  546. strcpy( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
  547. m_QCInfo_t.bReferenceAsPhys = true;
  548. }
  549. if ( !bFoundReference || !bFoundCollision)
  550. {
  551. Q_strcpy( pszMessage, pszRefMessage );
  552. Q_strcat( pszMessage, pszColMessage, 1024 );
  553. VGUIMessageBox( this, "Error Initializing Paths", pszMessage );
  554. }
  555. }
  556. void CQCGenerator::DeleteLOD()
  557. {
  558. int numSelected = m_pLODPanel->GetSelectedItemsCount();
  559. int selected;
  560. for ( int i = numSelected-1; i >= 0; i-- )
  561. {
  562. selected = m_pLODPanel->GetSelectedItem( i );
  563. m_pLODPanel->RemoveItem( selected );
  564. }
  565. }
  566. void CQCGenerator::EditLOD()
  567. {
  568. int numSelected = m_pLODPanel->GetSelectedItemsCount();
  569. if ( numSelected == 1 && !m_pLODPanel->IsInEditMode() )
  570. {
  571. if ( m_pLODEdit )
  572. {
  573. m_pLODEdit->DeletePanel();
  574. m_pLODEdit = 0;
  575. }
  576. m_pLODEdit = new vgui::TextEntry( this, "Edit" );
  577. m_pLODEdit->SendNewLine( true );
  578. m_nSelectedSequence = m_pLODPanel->GetSelectedItem( 0 );
  579. m_nSelectedColumn = m_pLODPanel->GetSelectedColumn();
  580. m_pLODPanel->EnterEditMode( m_nSelectedSequence, m_nSelectedColumn, m_pLODEdit );
  581. }
  582. }
  583. void CQCGenerator::OnNewLODText()
  584. {
  585. KeyValues *pEditItem = m_pLODPanel->GetItem( m_nSelectedSequence );
  586. KeyValues *pListItem = pEditItem;
  587. wchar_t szEditText[MAX_PATH];
  588. pEditItem = pEditItem->GetFirstValue();
  589. const char *name = pEditItem->GetName();
  590. for( int i = 0; i < m_nSelectedColumn; i++ )
  591. {
  592. pEditItem = pEditItem->GetNextValue();
  593. name = pEditItem->GetName();
  594. }
  595. m_pLODEdit->GetText( szEditText, MAX_PATH );
  596. pListItem->SetWString( name, szEditText );
  597. m_pLODPanel->LeaveEditMode();
  598. m_pLODPanel->InvalidateLayout();
  599. return;
  600. }