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.

885 lines
24 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ==========++;
  2. //
  3. //=============================================================================
  4. // Valve includes
  5. #include "appframework/appframework.h"
  6. #include "appframework/tier3app.h"
  7. #include "filesystem.h"
  8. #include "icommandline.h"
  9. #include "mathlib/mathlib.h"
  10. #include "tier1/tier1.h"
  11. #include "tier2/tier2.h"
  12. #include "tier3/tier3.h"
  13. #include "tier1/utlbuffer.h"
  14. #include "tier1/fmtstr.h"
  15. #include "studio.h"
  16. #include "datacache/idatacache.h"
  17. #include "datacache/imdlcache.h"
  18. #include "vphysics_interface.h"
  19. #include "materialsystem/imaterialsystem.h"
  20. #include "istudiorender.h"
  21. #include "vstdlib/iprocessutils.h"
  22. #include "tier2/fileutils.h"
  23. // Last include
  24. #include "tier0/memdbgon.h"
  25. //-----------------------------------------------------------------------------
  26. //
  27. //-----------------------------------------------------------------------------
  28. static CFmtStr PrettyPrintFloat( const float &flVal, float flEps = 0.000005f )
  29. {
  30. if ( FloatMakePositive( flVal ) <= flEps )
  31. {
  32. return CFmtStr( "%.6f", 0.0f );
  33. }
  34. return CFmtStr( "%.6f", flVal );
  35. }
  36. //-----------------------------------------------------------------------------
  37. //
  38. //-----------------------------------------------------------------------------
  39. static CFmtStr PrettyPrintVector( const Vector &v )
  40. {
  41. return CFmtStr( "%s %s %s",
  42. PrettyPrintFloat( v.x ).Get(),
  43. PrettyPrintFloat( v.y ).Get(),
  44. PrettyPrintFloat( v.z ).Get() );
  45. }
  46. //-----------------------------------------------------------------------------
  47. // A src bone transform transforms pre-compiled data (.dmx or .smd files, for example)
  48. // into post-compiled data (.mdl or .ani files)
  49. //-----------------------------------------------------------------------------
  50. static const mstudiosrcbonetransform_t *GetSrcBoneTransform( const studiohdr_t *pStudioHdr, int nBoneIndex )
  51. {
  52. if ( !pStudioHdr || nBoneIndex < 0 || nBoneIndex >= pStudioHdr->numbones )
  53. return false;
  54. const char *pszBoneName = pStudioHdr->pBone( nBoneIndex )->pszName();
  55. const int nSrcBoneTransformCount = pStudioHdr->NumSrcBoneTransforms();
  56. for ( int i = 0; i < nSrcBoneTransformCount; ++i )
  57. {
  58. const mstudiosrcbonetransform_t *pSrcBoneTransform = pStudioHdr->SrcBoneTransform( i );
  59. if ( pSrcBoneTransform && !Q_stricmp( pSrcBoneTransform->pszName(), pszBoneName ) )
  60. return pSrcBoneTransform;
  61. }
  62. return NULL;
  63. }
  64. //-----------------------------------------------------------------------------
  65. //
  66. //-----------------------------------------------------------------------------
  67. struct CommandLineBinaryOpt_t
  68. {
  69. const char *m_pszShortName;
  70. const char *m_pszLongName;
  71. const char *m_pszDoc;
  72. };
  73. //-----------------------------------------------------------------------------
  74. //
  75. //-----------------------------------------------------------------------------
  76. class CMdlInfoApp : public CTier3SteamApp
  77. {
  78. typedef CTier3SteamApp BaseClass;
  79. public:
  80. CMdlInfoApp();
  81. // Methods of IApplication
  82. virtual bool Create() OVERRIDE;
  83. virtual bool PreInit() OVERRIDE;
  84. virtual int Startup() OVERRIDE;
  85. virtual int Main() OVERRIDE;
  86. virtual void Shutdown() OVERRIDE;
  87. virtual void PostShutdown() OVERRIDE;
  88. virtual void Destroy() OVERRIDE {};
  89. static const CommandLineBinaryOpt_t s_binaryOptions[];
  90. bool m_bOptAll;
  91. bool m_bOptVerbose;
  92. static const char kOptHelp[];
  93. static const char kOptVerbose[];
  94. static const char kOptInput[];
  95. static const char kOptGeneral[];
  96. static const char kOptBones[];
  97. static const char kOptAttachments[];
  98. static const char kOptAnimation[];
  99. static const char kOptSequence[];
  100. static const char kOptMesh[];
  101. static const char kOptTexture[];
  102. static const char kOptSkin[];
  103. static bool CommandLineHasOpt( const char *pszOpt );
  104. bool DoIt( const char *pszFileIn );
  105. void HandleOptions();
  106. static MDLHandle_t GetMDLHandle( const char *pszFilename );
  107. void PrintHelp();
  108. void DumpGeneral( MDLHandle_t hMdl, CStudioHdr &cStudioHdr ) const;
  109. void DumpBones( CStudioHdr &cStudioHdr ) const;
  110. void DumpAttachments( CStudioHdr &cStudioHdr ) const;
  111. void DumpAnimationList( CStudioHdr &cStudioHdr ) const;
  112. void DumpSequenceList( CStudioHdr &cStudioHdr ) const;
  113. void DumpMesh( CStudioHdr &cStudioHdr ) const;
  114. void DumpTexture( CStudioHdr &cStudioHdr ) const;
  115. void DumpSkin( CStudioHdr &cStudioHdr ) const;
  116. };
  117. //-----------------------------------------------------------------------------
  118. //
  119. //-----------------------------------------------------------------------------
  120. const char CMdlInfoApp::kOptHelp[] = "-help";
  121. const char CMdlInfoApp::kOptVerbose[] = "-verbose";
  122. const char CMdlInfoApp::kOptInput[] = "-input";
  123. const char CMdlInfoApp::kOptGeneral[] = "-general";
  124. const char CMdlInfoApp::kOptBones[] = "-bones";
  125. const char CMdlInfoApp::kOptAttachments[] = "-attachments";
  126. const char CMdlInfoApp::kOptAnimation[] = "-animation";
  127. const char CMdlInfoApp::kOptSequence[] = "-sequence";
  128. const char CMdlInfoApp::kOptMesh[] = "-mesh";
  129. const char CMdlInfoApp::kOptTexture[] = "-texture";
  130. const char CMdlInfoApp::kOptSkin[] = "-skin";
  131. const CommandLineBinaryOpt_t CMdlInfoApp::s_binaryOptions[] =
  132. {
  133. { "-h", kOptHelp, "Print usage information" },
  134. { "-v", kOptVerbose, "Print extra junk" },
  135. { "-i", kOptInput, "Specifies the input MDL file" },
  136. { "-g", kOptGeneral, "Print general information section" },
  137. { "-b", kOptBones, "Print bones/skeleton section" },
  138. { "-at", kOptAttachments, "Print attachments section" },
  139. { "-a", kOptAnimation, "Print animation section" },
  140. { "-s", kOptSequence, "Print sequence section" },
  141. { "-m", kOptMesh, "Print mesh section" },
  142. { "-t", kOptTexture, "Print texture section" },
  143. { "-k", kOptSkin, "Print sKin section" }
  144. };
  145. //-----------------------------------------------------------------------------
  146. //
  147. //-----------------------------------------------------------------------------
  148. DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( CMdlInfoApp );
  149. //-----------------------------------------------------------------------------
  150. //
  151. //-----------------------------------------------------------------------------
  152. CMdlInfoApp::CMdlInfoApp()
  153. : m_bOptAll( true )
  154. , m_bOptVerbose( false )
  155. {
  156. }
  157. //-----------------------------------------------------------------------------
  158. // The application object
  159. //-----------------------------------------------------------------------------
  160. bool CMdlInfoApp::Create()
  161. {
  162. AppSystemInfo_t appSystems[] =
  163. {
  164. { "vstdlib.dll", PROCESS_UTILS_INTERFACE_VERSION },
  165. { "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
  166. { "datacache.dll", DATACACHE_INTERFACE_VERSION },
  167. { "datacache.dll", MDLCACHE_INTERFACE_VERSION },
  168. { "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
  169. { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
  170. { "", "" } // Required to terminate the list
  171. };
  172. if ( !AddSystems( appSystems ) )
  173. return false;
  174. IMaterialSystem *pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
  175. if ( !pMaterialSystem )
  176. {
  177. Warning( "Create: Unable to connect to material system interface!\n" );
  178. return false;
  179. }
  180. pMaterialSystem->SetShaderAPI( "shaderapiempty.dll" );
  181. return true;
  182. }
  183. //-----------------------------------------------------------------------------
  184. //
  185. //-----------------------------------------------------------------------------
  186. bool CMdlInfoApp::PreInit()
  187. {
  188. MathLib_Init();
  189. if ( !BaseClass::PreInit() )
  190. return false;
  191. CreateInterfaceFn factory = GetFactory();
  192. ConnectTier1Libraries( &factory, 1 );
  193. ConnectTier2Libraries( &factory, 1 );
  194. ConnectTier3Libraries( &factory, 1 );
  195. if ( !g_pFullFileSystem || !g_pMDLCache )
  196. {
  197. Warning( "Error! mdlinfo is missing a required interface!\n" );
  198. return false;
  199. }
  200. SetupSearchPaths( NULL, false, true );
  201. return true;
  202. }
  203. //-----------------------------------------------------------------------------
  204. //
  205. //-----------------------------------------------------------------------------
  206. int CMdlInfoApp::Startup()
  207. {
  208. if ( BaseClass::Startup() < 0 )
  209. return -1;
  210. if ( g_pMaterialSystem )
  211. {
  212. g_pMaterialSystem->ModInit();
  213. }
  214. if ( g_pDataCache )
  215. {
  216. g_pDataCache->SetSize( 64 * 1024 * 1024 );
  217. }
  218. return 0;
  219. }
  220. //-----------------------------------------------------------------------------
  221. //
  222. //-----------------------------------------------------------------------------
  223. int CMdlInfoApp::Main()
  224. {
  225. // This bit of hackery allows us to access files on the harddrive
  226. g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
  227. if ( CommandLineHasOpt( kOptHelp ) )
  228. {
  229. PrintHelp();
  230. return 0;
  231. }
  232. const char *pszOptFileIn = CommandLine()->ParmValue( "-i" );
  233. if ( !pszOptFileIn )
  234. pszOptFileIn = CommandLine()->ParmValue( "-input" );
  235. if ( pszOptFileIn )
  236. return DoIt( pszOptFileIn );
  237. Warning( "Error! Missing -i <file>.mdl\n\n" );
  238. PrintHelp();
  239. return -1;
  240. }
  241. //-----------------------------------------------------------------------------
  242. //
  243. //-----------------------------------------------------------------------------
  244. void CMdlInfoApp::Shutdown()
  245. {
  246. if ( g_pMaterialSystem )
  247. {
  248. g_pMaterialSystem->ModShutdown();
  249. }
  250. BaseClass::Shutdown();
  251. }
  252. //-----------------------------------------------------------------------------
  253. //
  254. //-----------------------------------------------------------------------------
  255. void CMdlInfoApp::PostShutdown()
  256. {
  257. DisconnectTier3Libraries();
  258. DisconnectTier2Libraries();
  259. DisconnectTier1Libraries();
  260. }
  261. //-----------------------------------------------------------------------------
  262. //
  263. //-----------------------------------------------------------------------------
  264. bool CMdlInfoApp::CommandLineHasOpt( const char *pszOpt )
  265. {
  266. for ( int ii = 0; ii < ARRAYSIZE( s_binaryOptions ); ++ii )
  267. {
  268. if ( !V_stricmp( pszOpt, s_binaryOptions[ii].m_pszShortName ) || !V_stricmp( pszOpt, s_binaryOptions[ii].m_pszLongName ) )
  269. {
  270. if ( CommandLine()->FindParm( s_binaryOptions[ii].m_pszShortName ) > 0 || CommandLine()->FindParm( s_binaryOptions[ii].m_pszLongName ) > 0 )
  271. return true;
  272. return false;
  273. }
  274. }
  275. if ( CommandLine()->FindParm( pszOpt ) > 0 )
  276. return true;
  277. return false;
  278. }
  279. //-----------------------------------------------------------------------------
  280. //
  281. //-----------------------------------------------------------------------------
  282. bool CMdlInfoApp::DoIt( const char *pszFileIn )
  283. {
  284. HandleOptions();
  285. MDLHandle_t hMdl = GetMDLHandle( pszFileIn );
  286. if ( hMdl == MDLHANDLE_INVALID )
  287. return false;
  288. // Get the model
  289. studiohdr_t *pHdr = g_pMDLCache->GetStudioHdr( hMdl );
  290. if ( !pHdr )
  291. return false;
  292. CStudioHdr cStudioHdr( pHdr, g_pMDLCache );
  293. DumpGeneral( hMdl, cStudioHdr );
  294. DumpBones( cStudioHdr );
  295. DumpAttachments( cStudioHdr );
  296. DumpAnimationList( cStudioHdr );
  297. DumpSequenceList( cStudioHdr );
  298. DumpMesh( cStudioHdr );
  299. DumpTexture( cStudioHdr );
  300. DumpSkin( cStudioHdr );
  301. g_pMDLCache->Release( hMdl );
  302. return true;
  303. }
  304. //-----------------------------------------------------------------------------
  305. //
  306. //-----------------------------------------------------------------------------
  307. void CMdlInfoApp::HandleOptions()
  308. {
  309. if (
  310. CommandLineHasOpt( kOptGeneral ) ||
  311. CommandLineHasOpt( kOptBones ) ||
  312. CommandLineHasOpt( kOptAttachments ) ||
  313. CommandLineHasOpt( kOptAnimation ) ||
  314. CommandLineHasOpt( kOptSequence ) ||
  315. CommandLineHasOpt( kOptMesh ) ||
  316. CommandLineHasOpt( kOptTexture ) ||
  317. CommandLineHasOpt( kOptSkin ) )
  318. {
  319. m_bOptAll = false;
  320. }
  321. if ( CommandLineHasOpt( kOptVerbose ) )
  322. {
  323. m_bOptVerbose = true;
  324. }
  325. }
  326. //-----------------------------------------------------------------------------
  327. //
  328. //-----------------------------------------------------------------------------
  329. MDLHandle_t CMdlInfoApp::GetMDLHandle( const char *pszFilename )
  330. {
  331. if ( pszFilename == NULL )
  332. return MDLHANDLE_INVALID;
  333. char szFullPath[ MAX_PATH ];
  334. if ( !GenerateFullPath( pszFilename, NULL, szFullPath, ARRAYSIZE( szFullPath ) ) )
  335. {
  336. V_strncpy( szFullPath, pszFilename, ARRAYSIZE( szFullPath ) );
  337. }
  338. MDLHandle_t hMdl = g_pMDLCache->FindMDL( szFullPath );
  339. if ( hMdl == MDLHANDLE_INVALID )
  340. {
  341. Error( "Couldn't Load MDL %s via g_pMDLCache\n", pszFilename );
  342. }
  343. else
  344. {
  345. studiohdr_t *pHdr = g_pMDLCache->GetStudioHdr( hMdl );
  346. if ( !pHdr || !V_strcmp( "error.mdl", pHdr->pszName() ) )
  347. {
  348. Error( "Couldn't Load MDL %s via g_pMDLCache, got error model instead\n", pszFilename );
  349. g_pMDLCache->Release( hMdl );
  350. hMdl = MDLHANDLE_INVALID;
  351. }
  352. }
  353. return hMdl;
  354. }
  355. //-----------------------------------------------------------------------------
  356. //
  357. //-----------------------------------------------------------------------------
  358. void CMdlInfoApp::PrintHelp()
  359. {
  360. Msg( "\n" );
  361. Msg( "NAME\n" );
  362. Msg( " mdlinfo - Prints information about a VALVe MDL file\n" );
  363. Msg( "\n" );
  364. Msg( "SYNOPSIS\n" );
  365. Msg( " mdlinfo [ options ] < -i filename.mdl >\n" );
  366. Msg( "\n" );
  367. for ( int ii = 0; ii < ARRAYSIZE( s_binaryOptions ); ++ii )
  368. {
  369. const CommandLineBinaryOpt_t &opt = s_binaryOptions[ii];
  370. Msg( " %s | %s : %s\n", opt.m_pszShortName, opt.m_pszLongName, opt.m_pszDoc );
  371. }
  372. Msg( "\n" );
  373. Msg( "DESCRIPTION\n" );
  374. Msg( " Prints information about a VALVe MDL file\n" );
  375. Msg( " If no sections are specified, all are printed\n" );
  376. Msg( " Multiple section specifiers can be specified but print order is fixed\n" );
  377. Msg( "\n" );
  378. Msg( "\n" );
  379. }
  380. //-----------------------------------------------------------------------------
  381. //
  382. //-----------------------------------------------------------------------------
  383. void CMdlInfoApp::DumpGeneral( MDLHandle_t hMdl, CStudioHdr &cStudioHdr ) const
  384. {
  385. if ( !( m_bOptAll || CommandLineHasOpt( kOptGeneral ) ) )
  386. return;
  387. const studiohdr_t *pHdr = cStudioHdr.GetRenderHdr();
  388. Msg( "//\n" );
  389. Msg( "// MDL General Info\n" );
  390. Msg( "//\n" );
  391. Msg( "\n" );
  392. Msg( "// MDL: %s\n", cStudioHdr.pszName() );
  393. Msg( "// Filename: %s\n", g_pMDLCache->GetModelName( hMdl ) );
  394. Msg( "// Id: 0x%08x\n", pHdr->id );
  395. Msg( "// Version: 0x%08x\n", pHdr->version );
  396. Msg( "// Checksum: 0x%08x\n", pHdr->checksum );
  397. Msg( "// EyePosition: %s\n", PrettyPrintVector( pHdr->eyeposition ).Get() );
  398. Msg( "// IllumPosition: %s\n", PrettyPrintVector( pHdr->illumposition ).Get() );
  399. Msg( "// Hull Min: %s\n", PrettyPrintVector( pHdr->hull_min ).Get() );
  400. Msg( "// Hull Max: %s\n", PrettyPrintVector( pHdr->hull_max ).Get() );
  401. Msg( "// Bone Count: %d\n", cStudioHdr.numbones() );
  402. const char *pszSurfaceProp = cStudioHdr.pszSurfaceProp();
  403. if ( pszSurfaceProp )
  404. {
  405. Msg( "// SurfaceProp: %s\n", pszSurfaceProp );
  406. }
  407. Msg( "\n" );
  408. }
  409. //-----------------------------------------------------------------------------
  410. //
  411. //-----------------------------------------------------------------------------
  412. static void PrintBoneFlags( const mstudiobone_t *pBone )
  413. {
  414. CFmtStrMax sBoneFlags;
  415. struct BoneFlag_t
  416. {
  417. int m_nMask;
  418. const char *m_pzsName;
  419. };
  420. static const BoneFlag_t boneFlags[] =
  421. {
  422. { BONE_PHYSICALLY_SIMULATED, "BONE_PHYSICALLY_SIMULATED" },
  423. { BONE_PHYSICS_PROCEDURAL, "BONE_PHYSICS_PROCEDURAL" },
  424. { BONE_ALWAYS_PROCEDURAL, "BONE_ALWAYS_PROCEDURAL" },
  425. { BONE_SCREEN_ALIGN_SPHERE, "BONE_SCREEN_ALIGN_SPHERE" },
  426. { BONE_SCREEN_ALIGN_CYLINDER, "BONE_SCREEN_ALIGN_CYLINDER" },
  427. { BONE_USED_BY_HITBOX, "BONE_USED_BY_HITBOX" },
  428. { BONE_USED_BY_ATTACHMENT, "BONE_USED_BY_ATTACHMENT" },
  429. { BONE_USED_BY_VERTEX_LOD0, "BONE_USED_BY_VERTEX_LOD0" },
  430. { BONE_USED_BY_VERTEX_LOD1, "BONE_USED_BY_VERTEX_LOD1" },
  431. { BONE_USED_BY_VERTEX_LOD2, "BONE_USED_BY_VERTEX_LOD2" },
  432. { BONE_USED_BY_VERTEX_LOD3, "BONE_USED_BY_VERTEX_LOD3" },
  433. { BONE_USED_BY_VERTEX_LOD4, "BONE_USED_BY_VERTEX_LOD4" },
  434. { BONE_USED_BY_VERTEX_LOD5, "BONE_USED_BY_VERTEX_LOD5" },
  435. { BONE_USED_BY_VERTEX_LOD6, "BONE_USED_BY_VERTEX_LOD6" },
  436. { BONE_USED_BY_VERTEX_LOD7, "BONE_USED_BY_VERTEX_LOD7" },
  437. { BONE_USED_BY_BONE_MERGE, "BONE_USED_BY_BONE_MERGE" },
  438. { BONE_FIXED_ALIGNMENT, "BONE_FIXED_ALIGNMENT" },
  439. { BONE_HAS_SAVEFRAME_POS, "BONE_HAS_SAVEFRAME_POS" },
  440. { BONE_HAS_SAVEFRAME_ROT, "BONE_HAS_SAVEFRAME_ROT" },
  441. };
  442. Msg( "// + Bone Flags: 0x%08x\n", pBone->flags );
  443. for ( int ii = 0; ii < ARRAYSIZE( boneFlags ); ++ii )
  444. {
  445. if ( pBone->flags & boneFlags[ii].m_nMask )
  446. {
  447. Msg( "// - 0x%08x %s\n", boneFlags[ii].m_nMask, boneFlags[ii].m_pzsName );
  448. }
  449. }
  450. }
  451. //-----------------------------------------------------------------------------
  452. //
  453. //-----------------------------------------------------------------------------
  454. void CMdlInfoApp::DumpBones( CStudioHdr &cStudioHdr ) const
  455. {
  456. if ( !( m_bOptAll || CommandLineHasOpt( kOptBones ) ) )
  457. return;
  458. const float flEps = 1.0e-5;
  459. static const Quaternion qIdentity( 0.0f, 0.0f, 0.0f, 1.0f );
  460. const int nBoneCount = cStudioHdr.numbones();
  461. Msg( "//\n" );
  462. Msg( "// Define Bones, Bone Count: %d\n", nBoneCount );
  463. Msg( "//\n" );
  464. Msg( "\n" );
  465. for ( int ii = 0; ii < nBoneCount; ++ii )
  466. {
  467. const mstudiobone_t *pBone = cStudioHdr.pBone( ii );
  468. const mstudiobone_t *pParentBone = pBone->parent < ii && pBone->parent >= 0 ? cStudioHdr.pBone( pBone->parent ) : NULL;
  469. const mstudiosrcbonetransform_t *pSrcBoneTransform = GetSrcBoneTransform( cStudioHdr.GetRenderHdr(), ii );
  470. bool bRealigned = false;
  471. Vector vAlignment;
  472. QAngle aAlignment;
  473. if ( pSrcBoneTransform )
  474. {
  475. MatrixAngles( pSrcBoneTransform->posttransform, aAlignment, vAlignment );
  476. if ( !QAnglesAreEqual( QAngle( 0.0f, 0.0f, 0.0f ), aAlignment, flEps ) || !VectorsAreEqual( Vector( 0.0f, 0.0f, 0.0f ), vAlignment, flEps ) )
  477. {
  478. bRealigned = true;
  479. }
  480. }
  481. if ( m_bOptVerbose )
  482. {
  483. Msg( "// * %3d: %s\n", ii, pBone->pszName() );
  484. if ( pParentBone )
  485. {
  486. Msg( "// + Parent: %3d: %s\n", pBone->parent, pParentBone->pszName() );
  487. }
  488. if ( bRealigned )
  489. {
  490. Msg( "// + REALIGNED\n" );
  491. }
  492. if ( pBone->flags & BONE_ALWAYS_PROCEDURAL )
  493. {
  494. static const char *s_ProcType[] = { "<ERROR", "AXISINTERP", "QUATINTERP", "AIMATBONE", "AIMATTACH", "JIGGLE" };
  495. Msg( "// + Procedural Type: %s\n", s_ProcType[pBone->proctype] );
  496. }
  497. const char *pszSurfaceProp = pBone->pszSurfaceProp();
  498. if ( pszSurfaceProp )
  499. {
  500. Msg( "// + Surface Prop: %s\n", pszSurfaceProp );
  501. }
  502. PrintBoneFlags( pBone );
  503. }
  504. const QAngle aRot = pBone->rot.ToQAngle();
  505. if ( pBone->flags & BONE_ALWAYS_PROCEDURAL )
  506. {
  507. }
  508. CFmtStrMax sTmp( "%s$definebone \"%s\" \"%s\" %s %s %s %s %s %s",
  509. ( pBone->flags & BONE_ALWAYS_PROCEDURAL ) ? "// procedural " : "",
  510. pBone->pszName(),
  511. pParentBone ? pParentBone->pszName() : "",
  512. PrettyPrintFloat( pBone->pos.x ).Get(),
  513. PrettyPrintFloat( pBone->pos.y ).Get(),
  514. PrettyPrintFloat( pBone->pos.z ).Get(),
  515. PrettyPrintFloat( aRot.x ).Get(),
  516. PrettyPrintFloat( aRot.y ).Get(),
  517. PrettyPrintFloat( aRot.z ).Get() );
  518. if ( bRealigned )
  519. {
  520. sTmp.AppendFormat( " %s %s %s %s %s %s",
  521. PrettyPrintFloat( vAlignment.x ).Get(),
  522. PrettyPrintFloat( vAlignment.y ).Get(),
  523. PrettyPrintFloat( vAlignment.z ).Get(),
  524. PrettyPrintFloat( aAlignment.x ).Get(),
  525. PrettyPrintFloat( aAlignment.y ).Get(),
  526. PrettyPrintFloat( aAlignment.z ).Get() );
  527. }
  528. sTmp.Append( "\n" );
  529. Msg( sTmp.Get() );
  530. if ( m_bOptVerbose )
  531. {
  532. Msg( "\n" );
  533. }
  534. }
  535. if ( !m_bOptVerbose )
  536. {
  537. Msg( "\n" );
  538. }
  539. bool bSaveFrame = false;
  540. for ( int ii = 0; ii < nBoneCount; ++ii )
  541. {
  542. const mstudiobone_t *pBone = cStudioHdr.pBone( ii );
  543. const bool bPosition = ( pBone->flags & BONE_HAS_SAVEFRAME_POS ) != 0;
  544. const bool bRotation = ( pBone->flags & BONE_HAS_SAVEFRAME_POS ) != 0;
  545. if ( bPosition || bRotation )
  546. {
  547. bSaveFrame = true;
  548. CFmtStr sTmp( "$BoneSaveFrame \"%s\"", pBone->pszName() );
  549. if ( bPosition )
  550. {
  551. sTmp.Append( " position" );
  552. }
  553. if ( bRotation )
  554. {
  555. sTmp.Append( " rotation" );
  556. }
  557. sTmp.Append( "\n" );
  558. Msg( sTmp.Get() );
  559. }
  560. }
  561. if ( bSaveFrame )
  562. {
  563. Msg( "\n" );
  564. }
  565. }
  566. //-----------------------------------------------------------------------------
  567. //
  568. //-----------------------------------------------------------------------------
  569. void CMdlInfoApp::DumpAttachments( CStudioHdr &cStudioHdr ) const
  570. {
  571. if ( !( m_bOptAll || CommandLineHasOpt( kOptAttachments ) ) )
  572. return;
  573. const int nAtttachmentCount = cStudioHdr.GetNumAttachments();
  574. Msg( "//\n" );
  575. Msg( "// Attachment Count: %d\n", nAtttachmentCount );
  576. Msg( "//\n" );
  577. Msg( "\n" );
  578. for ( int ii = 0; ii < nAtttachmentCount; ++ii )
  579. {
  580. const mstudioattachment_t &attachment = cStudioHdr.pAttachment( ii );
  581. CFmtStrMax sTmp( "$attachment \"%s\"",
  582. attachment.pszName() );
  583. sTmp.Append( "\n" );
  584. Msg( sTmp.Get() );
  585. }
  586. if ( !m_bOptVerbose )
  587. {
  588. Msg( "\n" );
  589. }
  590. }
  591. //-----------------------------------------------------------------------------
  592. //
  593. //-----------------------------------------------------------------------------
  594. void CMdlInfoApp::DumpAnimationList( CStudioHdr &cStudioHdr ) const
  595. {
  596. if ( !( m_bOptAll || CommandLineHasOpt( kOptAnimation ) ) )
  597. return;
  598. int nAnimCount = 0;
  599. virtualmodel_t *pVirtualModel = cStudioHdr.GetVirtualModel();
  600. if ( pVirtualModel )
  601. {
  602. nAnimCount = pVirtualModel->m_anim.Count();
  603. }
  604. else
  605. {
  606. nAnimCount = cStudioHdr.GetRenderHdr()->numlocalanim;
  607. }
  608. Msg( "//\n" );
  609. Msg( "// Animation Count: %d\n", nAnimCount );
  610. Msg( "//\n" );
  611. Msg( "\n" );
  612. for ( int ii = 0; ii < nAnimCount; ++ii )
  613. {
  614. const mstudioanimdesc_t &animDesc = cStudioHdr.pAnimdesc( ii );
  615. const studiohdr_t *pHdr = cStudioHdr.pAnimStudioHdr( ii );
  616. if ( pHdr != cStudioHdr.GetRenderHdr() )
  617. {
  618. Msg( "// %3d: %-50s [Included From %s]\n", ii, animDesc.pszName(), pHdr->pszName() );
  619. }
  620. else
  621. {
  622. Msg( "// %3d: %-50s\n", ii, animDesc.pszName() );
  623. }
  624. }
  625. Msg( "\n" );
  626. }
  627. //-----------------------------------------------------------------------------
  628. //
  629. //-----------------------------------------------------------------------------
  630. void CMdlInfoApp::DumpSequenceList( CStudioHdr &cStudioHdr ) const
  631. {
  632. if ( !( m_bOptAll || CommandLineHasOpt( kOptSequence ) ) )
  633. return;
  634. const int nSeqCount = cStudioHdr.GetNumSeq();
  635. Msg( "//\n" );
  636. Msg( "// Sequence Count: %d\n", nSeqCount );
  637. Msg( "//\n" );
  638. Msg( "\n" );
  639. for ( int ii = 0; ii < nSeqCount; ++ii )
  640. {
  641. const mstudioseqdesc_t &seqDesc = cStudioHdr.pSeqdesc( ii );
  642. const studiohdr_t *pHdr = cStudioHdr.pSeqStudioHdr( ii );
  643. if ( pHdr != cStudioHdr.GetRenderHdr() )
  644. {
  645. Msg( "// %3d: %-50s %-50s [Included From %s]\n", ii, seqDesc.pszLabel(), seqDesc.pszActivityName(), pHdr->pszName() );
  646. }
  647. else
  648. {
  649. Msg( "// %3d: %-50s %-50s\n", ii, seqDesc.pszLabel(), seqDesc.pszActivityName() );
  650. }
  651. }
  652. Msg( "\n" );
  653. }
  654. //-----------------------------------------------------------------------------
  655. //
  656. //-----------------------------------------------------------------------------
  657. void CMdlInfoApp::DumpMesh( CStudioHdr &cStudioHdr ) const
  658. {
  659. if ( !( m_bOptAll || CommandLineHasOpt( kOptMesh ) ) )
  660. return;
  661. }
  662. //-----------------------------------------------------------------------------
  663. //
  664. //-----------------------------------------------------------------------------
  665. void CMdlInfoApp::DumpTexture( CStudioHdr &cStudioHdr ) const
  666. {
  667. if ( !( m_bOptAll || CommandLineHasOpt( kOptTexture ) ) )
  668. return;
  669. const studiohdr_t *pHdr = cStudioHdr.GetRenderHdr();
  670. const int nTextureCount = pHdr->numtextures;
  671. Msg( "//\n" );
  672. Msg( "// Texture Count: %d\n", nTextureCount );
  673. Msg( "//\n" );
  674. Msg( "\n" );
  675. for ( int ii = 0; ii < nTextureCount; ++ii )
  676. {
  677. const mstudiotexture_t *pTexture = pHdr->pTexture( ii );
  678. Msg( "// Texture: %2d: %s\n", ii, pTexture->pszName() );
  679. }
  680. Msg( "\n" );
  681. }
  682. //-----------------------------------------------------------------------------
  683. //
  684. //-----------------------------------------------------------------------------
  685. void CMdlInfoApp::DumpSkin( CStudioHdr &cStudioHdr ) const
  686. {
  687. if ( !( m_bOptAll || CommandLineHasOpt( kOptSkin ) ) )
  688. return;
  689. const studiohdr_t *pHdr = cStudioHdr.GetRenderHdr();
  690. const int nSkinCount = pHdr->numskinfamilies;
  691. Msg( "//\n" );
  692. Msg( "// Skin Count: %d\n", nSkinCount );
  693. Msg( "//\n" );
  694. Msg( "\n" );
  695. for ( int ii = 0; ii < nSkinCount; ++ii )
  696. {
  697. const short *pSkinRef = pHdr->pSkinref( ii * pHdr->numskinref );
  698. CFmtStrMax sTmp( "// Skin: %2d: [", ii );
  699. for ( int jj = 0; jj < pHdr->numskinref; ++jj )
  700. {
  701. const int nTextureIndex = pSkinRef[jj];
  702. sTmp.AppendFormat( " %3d", nTextureIndex );
  703. }
  704. sTmp.Append( " ]\n" );
  705. Msg( sTmp.Get() );
  706. }
  707. Msg( "\n" );
  708. }