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.

706 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <windows.h>
  9. #include "tier0/dbg.h"
  10. #include "strtools.h"
  11. #include "utlvector.h"
  12. bool verbose = false;
  13. SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
  14. {
  15. printf( "%s", pMsg );
  16. OutputDebugString( pMsg );
  17. if ( type == SPEW_ERROR )
  18. {
  19. printf( "\n" );
  20. OutputDebugString( "\n" );
  21. }
  22. return SPEW_CONTINUE;
  23. }
  24. //-----------------------------------------------------------------------------
  25. // Purpose:
  26. //-----------------------------------------------------------------------------
  27. void printusage( )
  28. {
  29. printf( "usage: obj2mdl <modelname.obj file> \n\n" );
  30. printf( "The directory containing the <modelname>.obj file must also contain a\n" );
  31. printf( "<modelname>.mtl file.\n" );
  32. }
  33. void CreateTemplateQC( const char *pcDirectory, const char *pcBaseName, const char *pcSteamName )
  34. {
  35. char sz_Buffer[MAX_PATH];
  36. V_snprintf( sz_Buffer, MAX_PATH, "%s%s.qc", pcDirectory, pcBaseName );
  37. FILE *fp = fopen( sz_Buffer, "w" );
  38. V_snprintf( sz_Buffer, MAX_PATH, "$modelname \"contrib\\%s\\%s.mdl\"\n", pcSteamName, pcBaseName );
  39. fputs( sz_Buffer, fp );
  40. fputs( "$upaxis Y\n", fp );
  41. fputs( "$scale 1.00\n", fp );
  42. V_snprintf( sz_Buffer, MAX_PATH, "$body \"Body\" \"%s.obj\"\n", pcBaseName );
  43. fputs( sz_Buffer, fp );
  44. fputs( "$surfaceprop \"cloth\"\n", fp );
  45. V_snprintf( sz_Buffer, MAX_PATH, "$cdmaterials \"models\\contrib\\%s\\%s\"\n", pcSteamName, pcBaseName );
  46. fputs( sz_Buffer, fp );
  47. V_snprintf( sz_Buffer, MAX_PATH, "$sequence \"idle\" \"%s.obj\" fps 30 numframes 30 loop\n", pcBaseName );
  48. fputs( sz_Buffer, fp );
  49. V_snprintf( sz_Buffer, MAX_PATH, "$collisionmodel \"%s.obj\" {\n", pcBaseName );
  50. fputs( sz_Buffer, fp );
  51. fputs( "$mass 5.0\n", fp );
  52. fputs( "}\n", fp );
  53. fclose( fp );
  54. }
  55. void CreateTemplateVMT( const char *pcDirectory, const char *pcBaseName, const char *pcTGAColorFile, const char *pcTGANormalFile, const char *pcSteamName )
  56. {
  57. char sz_Buffer[MAX_PATH];
  58. char szTGAColorFileBase[MAX_PATH];
  59. char szTGANormalFileBase[MAX_PATH];
  60. V_snprintf( sz_Buffer, MAX_PATH, "%s%s.vmt", pcDirectory, pcBaseName );
  61. FILE *fp = fopen( sz_Buffer, "w" );
  62. /* fputs( "\"UnlitGeneric\"\n", fp );
  63. fputs( "{\n", fp );
  64. V_StripExtension( pcTGAColorFile, szTGAColorFileBase, sizeof( szTGAColorFileBase ) );
  65. V_snprintf( sz_Buffer, MAX_PATH, "\t\"$baseTexture\" \"models/contrib/%s/%s/%s\"\n", pcSteamName, pcBaseName, szTGAColorFileBase );
  66. fputs( sz_Buffer, fp );
  67. fputs( "\t\$translucent\t1\n", fp );
  68. fputs( "\t\"$vertexcolor\"\t1\n}\n", fp ); */
  69. fputs( "\"VertexlitGeneric\"\n", fp );
  70. fputs( "{\n", fp );
  71. V_StripExtension( pcTGAColorFile, szTGAColorFileBase, sizeof( szTGAColorFileBase ) );
  72. V_snprintf( sz_Buffer, MAX_PATH, "\t\"$baseTexture\" \"models/contrib/%s/%s/%s\"\n", pcSteamName, pcBaseName, szTGAColorFileBase );
  73. fputs( sz_Buffer, fp );
  74. if ( pcTGANormalFile && ( V_strlen( pcTGANormalFile ) > 0 ) )
  75. {
  76. V_StripExtension( pcTGANormalFile, szTGANormalFileBase, sizeof( szTGANormalFileBase ) );
  77. V_snprintf( sz_Buffer, MAX_PATH, "\t\"$bumpmap\" \"models/contrib/%s/%s/%s\"\n", pcSteamName, pcBaseName, szTGANormalFileBase );
  78. fputs( sz_Buffer, fp );
  79. }
  80. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$detail", "effects/tiledfire/fireLayeredSlowTiled512.vtf" );
  81. fputs( sz_Buffer, fp );
  82. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$detailscale", "5" );
  83. fputs( sz_Buffer, fp );
  84. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" %s\n", "$detailblendfactor", ".01" );
  85. fputs( sz_Buffer, fp );
  86. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" %s\n", "$detailblendmode", "6" );
  87. fputs( sz_Buffer, fp );
  88. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$yellow", "0" );
  89. fputs( sz_Buffer, fp );
  90. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$phong", "1" );
  91. fputs( sz_Buffer, fp );
  92. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$phongexponent", "25" );
  93. fputs( sz_Buffer, fp );
  94. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$phongboost", "5" );
  95. fputs( sz_Buffer, fp );
  96. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$lightwarptexture", "models\\lightwarps\\weapon_lightwarp" );
  97. fputs( sz_Buffer, fp );
  98. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$phongfresnelranges", "[.25 .5 1]" );
  99. fputs( sz_Buffer, fp );
  100. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$basemapalphaphongmask", "1" );
  101. fputs( sz_Buffer, fp );
  102. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$rimlight", "1" );
  103. fputs( sz_Buffer, fp );
  104. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$rimlightexponent", "4" );
  105. fputs( sz_Buffer, fp );
  106. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$rimlightboost", "2" );
  107. fputs( sz_Buffer, fp );
  108. V_snprintf( sz_Buffer, MAX_PATH, "\t\"%s\" \"%s\"\n", "$cloakPassEnabled", "1" );
  109. fputs( sz_Buffer, fp );
  110. fputs( "\t\"Proxies\"\n", fp );
  111. fputs( "\t{\n", fp );
  112. fputs( "\t\t\"weapon_invis\"\n", fp );
  113. fputs( "\t\t{\n", fp );
  114. fputs( "\t\t}\n", fp );
  115. fputs( "\t\t\"AnimatedTexture\"\n", fp );
  116. fputs( "\t\t{\n", fp );
  117. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "animatedtexturevar", "$detail" );
  118. fputs( sz_Buffer, fp );
  119. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "animatedtextureframenumvar", "$detailframe" );
  120. fputs( sz_Buffer, fp );
  121. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" %s\n", "animatedtextureframerate", "30" );
  122. fputs( sz_Buffer, fp );
  123. fputs( "\t\t}\n", fp );
  124. fputs( "\t\t\"BurnLevel\"\n", fp );
  125. fputs( "\t\t{\n", fp );
  126. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "resultVar", "$detailblendfactor" );
  127. fputs( sz_Buffer, fp );
  128. fputs( "\t\t}\n", fp );
  129. fputs( "\t\t\"YellowLevel\"\n", fp );
  130. fputs( "\t\t{\n", fp );
  131. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "resultVar", "$yellow" );
  132. fputs( sz_Buffer, fp );
  133. fputs( "\t\t}\n", fp );
  134. fputs( "\t\t\"Equals\"\n", fp );
  135. fputs( "\t\t{\n", fp );
  136. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "srcVar1", "$yellow" );
  137. fputs( sz_Buffer, fp );
  138. V_snprintf( sz_Buffer, MAX_PATH, "\t\t\t\"%s\" \"%s\"\n", "resultVar", "$color2" );
  139. fputs( sz_Buffer, fp );
  140. fputs( "\t\t}\n", fp );
  141. fputs( "\t}\n", fp );
  142. fputs( "}\n", fp );
  143. fclose( fp );
  144. }
  145. bool CheckFilesExist( const char *pcDirectory, const char *pcOBJFile, const char *pcMTLFile )
  146. {
  147. WIN32_FIND_DATA wfd;
  148. HANDLE ff;
  149. char szSearchFile[MAX_PATH];
  150. V_snprintf( szSearchFile, MAX_PATH, "%s%s", pcDirectory, pcOBJFile );
  151. if ( ( ff = FindFirstFile( szSearchFile, &wfd ) ) != INVALID_HANDLE_VALUE )
  152. {
  153. V_snprintf( szSearchFile, MAX_PATH, "%s%s", pcDirectory, pcMTLFile );
  154. if ( ( ff = FindFirstFile( szSearchFile, &wfd ) ) != INVALID_HANDLE_VALUE )
  155. {
  156. return true;
  157. }
  158. }
  159. return false;
  160. }
  161. bool ParseMTL( const char *pcDirectory, const char *pcOBJFile, const char *pcMTLFile, char *pcTGAColorFile, size_t nTGAColorBufSize, char *pcTGASpecularFile, size_t nTGASpecularBufSize )
  162. {
  163. char szMTLFile[MAX_PATH];
  164. V_snprintf( szMTLFile, MAX_PATH, "%s%s", pcDirectory, pcMTLFile );
  165. FILE *fp = fopen( szMTLFile, "r" );
  166. char szLine[MAX_PATH];
  167. while( fgets( szLine, sizeof( szLine ), fp ) )
  168. {
  169. char szToken[MAX_PATH];
  170. char szValue[MAX_PATH];
  171. char cTab;
  172. sscanf( szLine, "%s%c%s", szToken, &cTab, szValue );
  173. if ( V_stristr( szToken, "map_Kd" ) )
  174. {
  175. V_strncpy( pcTGAColorFile, V_UnqualifiedFileName( szValue ), nTGAColorBufSize );
  176. }
  177. else if ( V_stristr( szLine, "map_Ks" ) )
  178. {
  179. V_strncpy( pcTGASpecularFile, V_UnqualifiedFileName( szValue ), nTGASpecularBufSize );
  180. }
  181. }
  182. fclose( fp );
  183. return true;
  184. }
  185. bool ParseArguments( int argc, char* argv[], char *pcDirectory, size_t nDirectoryBufSize, char *pcBaseName, size_t nBaseNameBufSize, char *pcOBJFile, size_t nOBJFileBufSize, char *pcMTLFile, size_t nMTLFileBufSize )
  186. {
  187. if ( argc < 2)
  188. {
  189. printusage();
  190. return false;
  191. }
  192. else
  193. {
  194. //
  195. // Setup OBJ and MTL globals. Exit if neither type is passed in
  196. //
  197. char szFile[MAX_PATH];
  198. V_ExtractFilePath( argv[1], pcDirectory, nDirectoryBufSize );
  199. V_strncpy( szFile, V_UnqualifiedFileName( argv[1] ), MAX_PATH );
  200. // Make sure that the file passed in was an OBJ
  201. if ( V_stristr( szFile, ".obj" ) )
  202. {
  203. V_FileBase( szFile, pcBaseName, nBaseNameBufSize );
  204. V_strncpy( pcOBJFile, szFile, nOBJFileBufSize );
  205. V_snprintf( pcMTLFile, nMTLFileBufSize, "%s.mtl", pcBaseName );
  206. }
  207. else
  208. {
  209. // Invalid file type passed in
  210. printusage();
  211. return false;
  212. }
  213. }
  214. return true;
  215. }
  216. bool GetSteamUserName( char *pcSteamName, size_t nSteamNameBufSize )
  217. {
  218. HKEY hKey;
  219. char szModInstallPath[MAX_PATH];
  220. pcSteamName[0] = NULL;
  221. if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey ) )
  222. {
  223. DWORD dwSize = sizeof( szModInstallPath );
  224. RegQueryValueEx( hKey, "ModInstallPath", NULL, NULL, (LPBYTE)szModInstallPath, &dwSize );
  225. RegCloseKey( hKey );
  226. V_StripFilename( szModInstallPath );
  227. V_FileBase( szModInstallPath, pcSteamName, nSteamNameBufSize );
  228. }
  229. return ( V_strlen( pcSteamName ) > 0 );
  230. }
  231. bool GetSDKBinDirectory( char *pcSDKBinDir, size_t nBuffSize )
  232. {
  233. HKEY hKey;
  234. char szEngineVersion[MAX_PATH];
  235. char szSDKPath[MAX_PATH];
  236. *pcSDKBinDir = szEngineVersion[0] = szSDKPath[0] = NULL;
  237. if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, "Software\\Valve\\Source SDK", &hKey ) )
  238. {
  239. DWORD dwSize = sizeof( szEngineVersion );
  240. RegQueryValueEx( hKey, "EngineVer", NULL, NULL, (LPBYTE)szEngineVersion, &dwSize );
  241. RegCloseKey( hKey );
  242. }
  243. if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, "Environment", &hKey ) )
  244. {
  245. DWORD dwSize = sizeof( szSDKPath );
  246. RegQueryValueEx( hKey, "sourcesdk", NULL, NULL, (LPBYTE)szSDKPath, &dwSize );
  247. RegCloseKey( hKey );
  248. }
  249. if ( szEngineVersion[0] && szSDKPath[0] )
  250. {
  251. V_snprintf( pcSDKBinDir, nBuffSize, "%s\\bin\\%s\\bin", szSDKPath, szEngineVersion );
  252. return true;
  253. }
  254. return false;
  255. }
  256. bool GetSDKSourcesDirectory( char *pcSDKSourcesDir, size_t nBufSize )
  257. {
  258. HKEY hKey;
  259. char szSDKPath[MAX_PATH];
  260. char szVProjectPath[MAX_PATH];
  261. *pcSDKSourcesDir = NULL;
  262. if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, "Environment", &hKey ) )
  263. {
  264. DWORD dwSize = sizeof( szSDKPath );
  265. RegQueryValueEx( hKey, "sourcesdk", NULL, NULL, (LPBYTE)szSDKPath, &dwSize );
  266. dwSize = sizeof( szVProjectPath );
  267. RegQueryValueEx( hKey, "vproject", NULL, NULL, (LPBYTE)szVProjectPath, &dwSize );
  268. RegCloseKey( hKey );
  269. V_snprintf( pcSDKSourcesDir, nBufSize, "%s_content\\%s", szSDKPath, V_UnqualifiedFileName( szVProjectPath ) );
  270. return true;
  271. }
  272. return false;
  273. }
  274. void RunCommandLine( const char *pCmdLine, const char *pWorkingDir )
  275. {
  276. STARTUPINFO startupInfo;
  277. memset( &startupInfo, 0, sizeof( startupInfo ) );
  278. startupInfo.cb = sizeof( startupInfo );
  279. PROCESS_INFORMATION pi;
  280. memset( &pi, 0, sizeof( pi ) );
  281. CreateProcess(
  282. NULL,
  283. (char*)pCmdLine,
  284. NULL,
  285. NULL,
  286. FALSE,
  287. CREATE_NO_WINDOW,
  288. NULL,
  289. pWorkingDir,
  290. &startupInfo,
  291. &pi );
  292. WaitForSingleObject(pi.hProcess, INFINITE);
  293. }
  294. void CompileVTEX( const char *pcDirectory, const char *pcTGAColorFile, const char *pcSteamName, const char *pcBaseName )
  295. {
  296. char szCmdLine[MAX_PATH];
  297. char szSDKBinDir[MAX_PATH];
  298. char szSDKSourcesDir[MAX_PATH];
  299. GetSDKBinDirectory( szSDKBinDir, sizeof( szSDKBinDir ) );
  300. GetSDKSourcesDirectory( szSDKSourcesDir, sizeof( szSDKSourcesDir ) );
  301. V_snprintf( szCmdLine, sizeof( szCmdLine ), "\"%s\\vtex.exe\" -nopause \"%s\\materialsrc\\models\\contrib\\%s\\%s\\%s\"", szSDKBinDir, szSDKSourcesDir, pcSteamName, pcBaseName, pcTGAColorFile );
  302. RunCommandLine( szCmdLine, szSDKBinDir );
  303. }
  304. void CompileMDL( const char *pcObjFile, const char *pcSteamName, const char *pcBaseName )
  305. {
  306. char szCmdLine[MAX_PATH];
  307. char szSDKBinDir[MAX_PATH];
  308. char szSDKSourcesDir[MAX_PATH];
  309. GetSDKBinDirectory( szSDKBinDir, sizeof( szSDKBinDir ) );
  310. GetSDKSourcesDirectory( szSDKSourcesDir, sizeof( szSDKSourcesDir ) );
  311. V_snprintf( szCmdLine, sizeof( szCmdLine ), "\"%s\\studiomdl.exe\" -nop4 \"%s\\modelsrc\\contrib\\%s\\%s\\%s.qc\"", szSDKBinDir, szSDKSourcesDir, pcSteamName, pcBaseName, pcBaseName );
  312. RunCommandLine( szCmdLine, szSDKBinDir );
  313. }
  314. bool GetVProjectDirectory( char *pcVProjectPath, size_t nBufSize )
  315. {
  316. bool bRetVal = false;
  317. HKEY hKey;
  318. pcVProjectPath[0] = NULL;
  319. if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, "Environment", &hKey ) )
  320. {
  321. DWORD dwSize = nBufSize;
  322. RegQueryValueEx( hKey, "vproject", NULL, NULL, (LPBYTE)pcVProjectPath, &dwSize );
  323. RegCloseKey( hKey );
  324. bRetVal = true;
  325. }
  326. return bRetVal;
  327. }
  328. void LaunchHLMV( const char *pcSteamName, const char *pcBaseName )
  329. {
  330. char szCmdLine[MAX_PATH];
  331. char szSDKBinDir[MAX_PATH];
  332. char szVProjectPath[MAX_PATH];
  333. GetSDKBinDirectory( szSDKBinDir, sizeof( szSDKBinDir ) );
  334. GetVProjectDirectory( szVProjectPath, sizeof( szVProjectPath ) );
  335. V_snprintf( szCmdLine, sizeof( szCmdLine ), "\"%s\\hlmv.exe\" -game \"%s\" \"%s\\models\\contrib\\%s\\%s\\%s.mdl\"", szSDKBinDir, szVProjectPath, szVProjectPath, pcSteamName, pcBaseName, pcBaseName );
  336. RunCommandLine( szCmdLine, szSDKBinDir );
  337. }
  338. void CopyVMT( const char *pcDirectory, const char *pcBaseName, const char *pcSteamName )
  339. {
  340. char szVProjectPath[MAX_PATH];
  341. char szSourceVMT[MAX_PATH];
  342. char szDestVMT[MAX_PATH];
  343. GetVProjectDirectory( szVProjectPath, sizeof( szVProjectPath ) );
  344. V_snprintf( szSourceVMT, sizeof( szSourceVMT), "%s%s.vmt", pcDirectory, pcBaseName );
  345. V_snprintf( szDestVMT, sizeof( szDestVMT), "%s\\materials\\models\\contrib\\%s\\%s\\%s.vmt", szVProjectPath, pcSteamName, pcBaseName, pcBaseName );
  346. DeleteFile( szDestVMT );
  347. CopyFile( szSourceVMT, szDestVMT, false );
  348. }
  349. bool FileExists( const char* filePathName )
  350. {
  351. DWORD attribs = ::GetFileAttributesA( filePathName );
  352. if (attribs == INVALID_FILE_ATTRIBUTES)
  353. {
  354. return false;
  355. }
  356. return ( ( attribs & FILE_ATTRIBUTE_DIRECTORY ) == 0 );
  357. }
  358. bool DirectoryExists(const char* dirName)
  359. {
  360. DWORD attribs = ::GetFileAttributesA(dirName);
  361. if (attribs == INVALID_FILE_ATTRIBUTES)
  362. {
  363. return false;
  364. }
  365. return ( ( attribs & FILE_ATTRIBUTE_DIRECTORY ) != 0 );
  366. }
  367. bool CopyFiles( const char *pcSourceDir, const char *pcPattern, const char *pcDestDir )
  368. {
  369. char szFindPattern[MAX_PATH];
  370. bool bAllSucceeded = true;
  371. V_snprintf( szFindPattern, sizeof( szFindPattern ), "%s%s", pcSourceDir, pcPattern );
  372. WIN32_FIND_DATA findData;
  373. HANDLE hFind = FindFirstFile( szFindPattern, &findData );
  374. if ( hFind == INVALID_HANDLE_VALUE )
  375. {
  376. return false;
  377. }
  378. else
  379. {
  380. do
  381. {
  382. char szSrcPath[MAX_PATH];
  383. char szDestPath[MAX_PATH];
  384. V_snprintf( szSrcPath, sizeof( szSrcPath ), "%s%s", pcSourceDir, findData.cFileName );
  385. V_snprintf( szDestPath, sizeof( szDestPath ), "%s\\%s", pcDestDir, findData.cFileName );
  386. DeleteFile( szDestPath );
  387. CopyFile( szSrcPath, szDestPath, false );
  388. bAllSucceeded &= FileExists( szDestPath );
  389. } while ( FindNextFile( hFind, &findData ) );
  390. FindClose( hFind );
  391. return bAllSucceeded;
  392. }
  393. }
  394. bool CopyMaterialSourcesToSrcTree( const char *pcDirectory, const char *pcSteamName, const char *pcBaseName )
  395. {
  396. char szSDKSourcesDir[MAX_PATH];
  397. char szBuffer[MAX_PATH];
  398. bool bAllSucceeded = true;
  399. GetSDKSourcesDirectory( szSDKSourcesDir, sizeof( szSDKSourcesDir ) );
  400. // Root
  401. CreateDirectory( szSDKSourcesDir, NULL );
  402. bAllSucceeded &= DirectoryExists( szSDKSourcesDir );
  403. //
  404. // Materials
  405. //
  406. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s", szSDKSourcesDir, "\\materialsrc" );
  407. CreateDirectory( szBuffer, NULL );
  408. bAllSucceeded &= DirectoryExists( szBuffer );
  409. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s", szSDKSourcesDir, "\\materialsrc\\models" );
  410. CreateDirectory( szBuffer, NULL );
  411. bAllSucceeded &= DirectoryExists( szBuffer );
  412. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s", szSDKSourcesDir, "\\materialsrc\\models\\contrib" );
  413. CreateDirectory( szBuffer, NULL );
  414. bAllSucceeded &= DirectoryExists( szBuffer );
  415. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s%s", szSDKSourcesDir, "\\materialsrc\\models\\contrib\\", pcSteamName );
  416. CreateDirectory( szBuffer, NULL );
  417. bAllSucceeded &= DirectoryExists( szBuffer );
  418. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s%s\\%s", szSDKSourcesDir, "\\materialsrc\\models\\contrib\\", pcSteamName, pcBaseName );
  419. CreateDirectory( szBuffer, NULL );
  420. bAllSucceeded &= DirectoryExists( szBuffer );
  421. if ( bAllSucceeded )
  422. {
  423. CopyFiles( pcDirectory, "*.tga", szBuffer );
  424. }
  425. return bAllSucceeded;
  426. }
  427. bool ReplaceLineInTXTFile( const char *pcFilePath, const char* pcFirstChars, const char* pcReplacement )
  428. {
  429. char sz_Buffer[MAX_PATH];
  430. CUtlStringList fileContents;
  431. // Read the old
  432. FILE *fp = fopen( pcFilePath, "r" );
  433. if ( !fp )
  434. {
  435. return false;
  436. }
  437. while( fgets( sz_Buffer, sizeof( sz_Buffer ), fp ) )
  438. {
  439. if ( !V_strncmp( sz_Buffer, pcFirstChars, V_strlen( pcFirstChars ) ) )
  440. {
  441. V_strncpy( sz_Buffer, pcReplacement, V_strlen( pcReplacement ) + 1 );
  442. }
  443. fileContents.CopyAndAddToTail( sz_Buffer );
  444. }
  445. fclose( fp );
  446. //
  447. // Write the new
  448. //
  449. fp = fopen( pcFilePath, "w" );
  450. if ( !fp )
  451. {
  452. fileContents.PurgeAndDeleteElements();
  453. return false;
  454. }
  455. FOR_EACH_VEC( fileContents, i )
  456. {
  457. fputs( fileContents[i], fp );
  458. }
  459. fclose( fp );
  460. fileContents.PurgeAndDeleteElements();
  461. return true;
  462. }
  463. bool CopyModelSourcesToSrcTree( const char *pcDirectory, const char *pcSteamName, const char *pcBaseName )
  464. {
  465. char szSDKSourcesDir[MAX_PATH];
  466. char szBuffer[MAX_PATH];
  467. bool bAllSucceeded = true;
  468. GetSDKSourcesDirectory( szSDKSourcesDir, sizeof( szSDKSourcesDir ) );
  469. // Root
  470. CreateDirectory( szSDKSourcesDir, NULL );
  471. bAllSucceeded &= DirectoryExists( szSDKSourcesDir );
  472. //
  473. // Models
  474. //
  475. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s", szSDKSourcesDir, "\\modelsrc" );
  476. CreateDirectory( szBuffer, NULL );
  477. bAllSucceeded &= DirectoryExists( szBuffer );
  478. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s", szSDKSourcesDir, "\\modelsrc\\contrib" );
  479. CreateDirectory( szBuffer, NULL );
  480. bAllSucceeded &= DirectoryExists( szBuffer );
  481. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s%s", szSDKSourcesDir, "\\modelsrc\\contrib\\", pcSteamName );
  482. CreateDirectory( szBuffer, NULL );
  483. bAllSucceeded &= DirectoryExists( szBuffer );
  484. V_snprintf( szBuffer, sizeof( szBuffer ), "%s%s%s\\%s", szSDKSourcesDir, "\\modelsrc\\contrib\\", pcSteamName, pcBaseName );
  485. CreateDirectory( szBuffer, NULL );
  486. bAllSucceeded &= DirectoryExists( szBuffer );
  487. if ( bAllSucceeded )
  488. {
  489. CopyFiles( pcDirectory, "*.obj", szBuffer );
  490. CopyFiles( pcDirectory, "*.mtl", szBuffer );
  491. CopyFiles( pcDirectory, "*.qc", szBuffer );
  492. }
  493. // Replace some tags in the OBJ and MTL to satisfy some assumptions made by studiomdl
  494. char szFileToChange[MAX_PATH];
  495. char szReplacementLine[MAX_PATH];
  496. V_snprintf( szFileToChange, sizeof( szFileToChange ), "%s\\%s.mtl", szBuffer, pcBaseName );
  497. V_snprintf( szReplacementLine, sizeof( szReplacementLine ), "newmtl %s\n", pcBaseName );
  498. ReplaceLineInTXTFile( szFileToChange, "newmtl", szReplacementLine );
  499. V_snprintf( szReplacementLine, sizeof( szReplacementLine ), "map_Kd %s.tga\n", pcBaseName );
  500. ReplaceLineInTXTFile( szFileToChange, "map_Kd", szReplacementLine );
  501. V_snprintf( szFileToChange, sizeof( szFileToChange ), "%s\\%s.obj", szBuffer, pcBaseName );
  502. V_snprintf( szReplacementLine, sizeof( szReplacementLine ), "g %s\n", pcBaseName );
  503. ReplaceLineInTXTFile( szFileToChange, "g ", szReplacementLine );
  504. V_snprintf( szReplacementLine, sizeof( szReplacementLine ), "usemtl %s\n", pcBaseName );
  505. ReplaceLineInTXTFile( szFileToChange, "usemtl ", szReplacementLine );
  506. return bAllSucceeded;
  507. }
  508. //-----------------------------------------------------------------------------
  509. // Purpose:
  510. // Input : argc -
  511. // argv[] -
  512. // Output : int
  513. //-----------------------------------------------------------------------------
  514. int main( int argc, char* argv[] )
  515. {
  516. char szDirectory[MAX_PATH];
  517. char szOBJFile[MAX_PATH];
  518. char szMTLFile[MAX_PATH];
  519. char szTGAColorFile[MAX_PATH];
  520. char szTGANormalFile[MAX_PATH];
  521. char szTGATransparencyFile[MAX_PATH];
  522. char szTGASpecularFile[MAX_PATH];
  523. char szBaseName[MAX_PATH];
  524. char szSteamName[64];
  525. SpewOutputFunc( SpewFunc );
  526. szDirectory[0] = szMTLFile[0] = szOBJFile[0] = szSteamName[0] = szTGAColorFile[0] = szTGANormalFile[0] = szTGATransparencyFile[0] = szTGASpecularFile[0] = NULL;
  527. if ( ParseArguments( argc, argv, szDirectory, sizeof( szDirectory ), szBaseName, sizeof( szBaseName ), szOBJFile, sizeof( szOBJFile ), szMTLFile, sizeof( szMTLFile ) ) )
  528. {
  529. if ( CheckFilesExist(szDirectory, szOBJFile, szMTLFile ) )
  530. {
  531. printf( "Valve Software - obj2mdl.exe (%s)\n", __DATE__ );
  532. printf( "--- OBJ to MDL file conversion helper ---\n" );
  533. if ( !GetSteamUserName( szSteamName, sizeof( szSteamName ) ) )
  534. {
  535. printf( "--- Unable to get Steam user name. Exiting. ---\n" );
  536. }
  537. printf( "--- Reading MTL file ---\n" );
  538. ParseMTL( szDirectory, szOBJFile, szMTLFile, szTGAColorFile, sizeof( szTGAColorFile ), szTGASpecularFile, sizeof( szTGASpecularFile ) );
  539. printf( "--- Creating VMT and QC files ---\n" );
  540. CreateTemplateVMT( szDirectory, szBaseName, szTGAColorFile, szTGANormalFile, szSteamName );
  541. CreateTemplateQC( szDirectory, szBaseName, szSteamName );
  542. CopyMaterialSourcesToSrcTree( szDirectory, szSteamName, szBaseName );
  543. printf( "--- Compiling TGAs into a VTEX with vtex.exe---\n" );
  544. CompileVTEX( szDirectory, szTGAColorFile, szSteamName, szBaseName );
  545. CopyVMT( szDirectory, szBaseName, szSteamName );
  546. printf( "--- Compiling OBJs into an MDL with studiomdl.exe---\n" );
  547. CopyModelSourcesToSrcTree( szDirectory, szSteamName, szBaseName );
  548. CompileMDL( szOBJFile, szSteamName, szBaseName );
  549. // printf( "--- Launching model viewer ---\n" );
  550. // LaunchHLMV( szSteamName, szBaseName );
  551. return 0;
  552. }
  553. }
  554. return 1;
  555. }