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.

1142 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "hlfaceposer.h"
  9. #include "StudioModel.h"
  10. #include "faceposer_models.h"
  11. #include "filesystem.h"
  12. #include "ifaceposerworkspace.h"
  13. #include <mxtk/mx.h>
  14. #include "mdlviewer.h"
  15. #include "mxexpressiontray.h"
  16. #include "ControlPanel.h"
  17. #include "checksum_crc.h"
  18. #include "ViewerSettings.h"
  19. #include "matsyswin.h"
  20. #include "KeyValues.h"
  21. #include "utlbuffer.h"
  22. #include "expression.h"
  23. #include "ProgressDialog.h"
  24. #include "tier1/UtlString.h"
  25. #include "tier1/FmtStr.h"
  26. #include "tier1/KeyValues.h"
  27. // memdbgon must be the last include file in a .cpp file!!!
  28. #include "tier0/memdbgon.h"
  29. void SetupModelFlexcontrollerLinks( StudioModel *model );
  30. IFaceposerModels::CFacePoserModel::CFacePoserModel( char const *modelfile, StudioModel *model )
  31. {
  32. m_pModel = model;
  33. m_szActorName[ 0 ] = 0;
  34. m_szShortName[ 0 ] = 0;
  35. strcpy( m_szModelFileName, modelfile );
  36. Q_FixSlashes( m_szModelFileName );
  37. CStudioHdr *hdr = model->GetStudioHdr();
  38. if ( hdr )
  39. {
  40. Q_StripExtension( hdr->pszName(), m_szShortName, sizeof( m_szShortName ) );
  41. }
  42. m_bVisibileIn3DView = false;
  43. m_bFirstBitmapLoad = true;
  44. LoadBitmaps();
  45. }
  46. IFaceposerModels::CFacePoserModel::~CFacePoserModel()
  47. {
  48. FreeBitmaps();
  49. }
  50. void IFaceposerModels::CFacePoserModel::LoadBitmaps()
  51. {
  52. CStudioHdr *hdr = m_pModel ? m_pModel->GetStudioHdr() : NULL;
  53. if ( hdr )
  54. {
  55. for ( int i = 0 ;i < hdr->GetNumSeq(); i++ )
  56. {
  57. mxbitmapdata_t *bm = new mxbitmapdata_t();
  58. AnimBitmap *entry = new AnimBitmap();
  59. entry->needsload = true;
  60. entry->bitmap = bm;
  61. // Need to load bitmap from disk image via crc, etc.
  62. //Assert( 0 );
  63. m_AnimationBitmaps.AddToTail( entry );
  64. }
  65. }
  66. }
  67. CRC32_t IFaceposerModels::CFacePoserModel::GetBitmapCRC( int sequence )
  68. {
  69. CStudioHdr *hdr = m_pModel ? m_pModel->GetStudioHdr() : NULL;
  70. if ( !hdr )
  71. return (CRC32_t)-1;
  72. if ( sequence < 0 || sequence >= hdr->GetNumSeq() )
  73. return (CRC32_t)-1;
  74. mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence );
  75. CRC32_t crc;
  76. CRC32_Init( &crc );
  77. // For sequences, we'll checsum a bit of data
  78. CRC32_ProcessBuffer( &crc, (void *)seqdesc.pszLabel(), Q_strlen( seqdesc.pszLabel() ) );
  79. CRC32_ProcessBuffer( &crc, (void *)seqdesc.pszActivityName(), Q_strlen( seqdesc.pszActivityName() ) );
  80. CRC32_ProcessBuffer( &crc, (void *)&seqdesc.flags, sizeof( seqdesc.flags ) );
  81. //CRC32_ProcessBuffer( &crc, (void *)&seqdesc.numevents, sizeof( seqdesc.numevents ) );
  82. CRC32_ProcessBuffer( &crc, (void *)&seqdesc.numblends, sizeof( seqdesc.numblends ) );
  83. CRC32_ProcessBuffer( &crc, (void *)seqdesc.groupsize, sizeof( seqdesc.groupsize ) );
  84. KeyValues *seqKeyValues = new KeyValues("");
  85. if ( seqKeyValues->LoadFromBuffer( m_pModel->GetFileName( ), m_pModel->GetKeyValueText( sequence ) ) )
  86. {
  87. // Yuck, but I need it in a contiguous block of memory... oh well...
  88. CUtlBuffer buf;
  89. seqKeyValues->RecursiveSaveToFile( buf, 0 );
  90. CRC32_ProcessBuffer( &crc, ( void * )buf.Base(), buf.TellPut() );
  91. }
  92. seqKeyValues->deleteThis();
  93. CRC32_Final( &crc );
  94. return crc;
  95. }
  96. const char *IFaceposerModels::CFacePoserModel::GetBitmapChecksum( int sequence )
  97. {
  98. CRC32_t crc = GetBitmapCRC( sequence );
  99. // Create string name out of binary data
  100. static char filename[ 512 ];
  101. char hex[ 16 ];
  102. Q_binarytohex( (byte *)&crc, sizeof( crc ), hex, sizeof( hex ) );
  103. Q_snprintf( filename, sizeof( filename ), "%s", hex );
  104. return filename;
  105. }
  106. const char *IFaceposerModels::CFacePoserModel::GetBitmapFilename( int sequence )
  107. {
  108. char *in, *out;
  109. static char filename[ 256 ];
  110. filename[ 0 ] = 0;
  111. char modelName[512], modelNameTemp[512];
  112. Q_strncpy( modelNameTemp, GetShortModelName(), sizeof( modelNameTemp ) );
  113. in = modelNameTemp;
  114. out = modelName;
  115. while ( *in )
  116. {
  117. if ( V_isalnum( *in ) ||
  118. *in == '_' ||
  119. *in == '\\' ||
  120. *in == '/' ||
  121. *in == '.' ||
  122. *in == ':' )
  123. {
  124. *out++ = *in;
  125. }
  126. in++;
  127. }
  128. *out = 0;
  129. Q_snprintf( filename, sizeof( filename ), "expressions/%s/animation/%s.bmp", modelName, GetBitmapChecksum( sequence ) );
  130. Q_FixSlashes( filename );
  131. strlwr( filename );
  132. CreatePath( filename );
  133. return filename;
  134. }
  135. void IFaceposerModels::CFacePoserModel::FreeBitmaps()
  136. {
  137. while ( m_AnimationBitmaps.Count() > 0 )
  138. {
  139. AnimBitmap *bm = m_AnimationBitmaps[ 0 ];
  140. delete bm->bitmap;
  141. delete bm;
  142. m_AnimationBitmaps.Remove( 0 );
  143. }
  144. }
  145. void IFaceposerModels::CFacePoserModel::LoadBitmapForSequence( mxbitmapdata_t *bitmap, int sequence )
  146. {
  147. // See if it exists
  148. char filename[ 512 ];
  149. Q_strncpy( filename, GetBitmapFilename( sequence ), sizeof( filename ) );
  150. if ( !LoadBitmapFromFile( filename, *bitmap ) )
  151. {
  152. CreateNewBitmap( filename, sequence, 256, false, NULL, bitmap );
  153. }
  154. }
  155. static float FindPoseCycle( StudioModel *model, int sequence )
  156. {
  157. float cycle = 0.0f;
  158. if ( !model->GetStudioHdr() )
  159. return cycle;
  160. KeyValues *seqKeyValues = new KeyValues("");
  161. if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
  162. {
  163. // Do we have a build point section?
  164. KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
  165. if ( pkvAllFaceposer )
  166. {
  167. int thumbnail_frame = pkvAllFaceposer->GetInt( "thumbnail_frame", 0 );
  168. if ( thumbnail_frame )
  169. {
  170. // Convert frame to cycle if we have valid data
  171. int maxFrame = model->GetNumFrames( sequence ) - 1;
  172. if ( maxFrame > 0 )
  173. {
  174. cycle = thumbnail_frame / (float)maxFrame;
  175. }
  176. }
  177. }
  178. }
  179. seqKeyValues->deleteThis();
  180. return cycle;
  181. }
  182. void EnableStickySnapshotMode( void )
  183. {
  184. g_pMatSysWindow->EnableStickySnapshotMode( );
  185. }
  186. void DisableStickySnapshotMode( void )
  187. {
  188. g_pMatSysWindow->DisableStickySnapshotMode( );
  189. }
  190. void IFaceposerModels::CreateNewBitmap( int modelindex, char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap )
  191. {
  192. CFacePoserModel *m = m_Models[ modelindex ];
  193. if ( m )
  194. {
  195. m->CreateNewBitmap( pchBitmapFilename, sequence, nSnapShotSize, bZoomInOnFace, pExpression, bitmap );
  196. }
  197. }
  198. void IFaceposerModels::CFacePoserModel::CreateNewBitmap( char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap )
  199. {
  200. MatSysWindow *pWnd = g_pMatSysWindow;
  201. if ( !pWnd )
  202. return;
  203. StudioModel *model = m_pModel;
  204. if ( !model )
  205. return;
  206. CStudioHdr *hdr = model->GetStudioHdr();
  207. if ( !hdr )
  208. return;
  209. if ( sequence < 0 || sequence >= hdr->GetNumSeq() )
  210. return;
  211. mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence );
  212. Con_ColorPrintf( FILE_COLOR, "Creating bitmap %s for sequence '%s'\n", pchBitmapFilename, seqdesc.pszLabel() );
  213. model->ClearOverlaysSequences();
  214. int iLayer = model->GetNewAnimationLayer();
  215. model->SetOverlaySequence( iLayer, sequence, 1.0 );
  216. model->SetOverlayRate( iLayer, FindPoseCycle( model, sequence ), 0.0 );
  217. for (int i = 0; i < hdr->GetNumPoseParameters(); i++)
  218. {
  219. model->SetPoseParameter( i, 0.0 );
  220. }
  221. float flexValues[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ] = { 0 };
  222. if ( pExpression )
  223. {
  224. float *settings = pExpression->GetSettings();
  225. float *weights = pExpression->GetWeights();
  226. // Save existing settings from model
  227. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
  228. {
  229. int j = hdr->pFlexcontroller( i )->localToGlobal;
  230. if ( j == -1 )
  231. continue;
  232. flexValues[ i ] = model->GetFlexController( i );
  233. // Set Value from passed in settings
  234. model->SetFlexController( i, settings[ j ] * weights[ j ] );
  235. }
  236. }
  237. model->ClearLookTargets( );
  238. QAngle oldrot, oldLight;
  239. Vector oldtrans;
  240. VectorCopy( model->m_angles, oldrot );
  241. VectorCopy( model->m_origin, oldtrans );
  242. VectorCopy( g_viewerSettings.lightrot, oldLight );
  243. model->m_angles.Init();
  244. model->m_origin.Init();
  245. g_viewerSettings.lightrot.Init();
  246. g_viewerSettings.lightrot.y = -180;
  247. bool bSaveGround = g_viewerSettings.showGround;
  248. g_viewerSettings.showGround = false;
  249. if ( bZoomInOnFace )
  250. {
  251. Vector size;
  252. VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );
  253. float eyeheight = hdr->hull_min().z + 0.9 * size.z;
  254. // float width = ( size.x + size.y ) / 2.0f;
  255. model->m_origin.x = size.z * .6f;
  256. if ( hdr->GetNumAttachments() > 0 )
  257. {
  258. for (int i = 0; i < hdr->GetNumAttachments(); i++)
  259. {
  260. const mstudioattachment_t &attachment = hdr->pAttachment( i );
  261. int iBone = hdr->GetAttachmentBone( i );
  262. if ( Q_stricmp( attachment.pszName(), "eyes" ) )
  263. continue;
  264. mstudiobone_t *bone = hdr->pBone( iBone );
  265. if ( !bone )
  266. continue;
  267. matrix3x4_t boneToPose;
  268. MatrixInvert( bone->poseToBone, boneToPose );
  269. matrix3x4_t attachmentPoseToLocal;
  270. ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );
  271. Vector localSpaceEyePosition;
  272. VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );
  273. // Not sure why this must be negative?
  274. eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
  275. break;
  276. }
  277. }
  278. KeyValues *seqKeyValues = new KeyValues("");
  279. if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
  280. {
  281. // Do we have a build point section?
  282. KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
  283. if ( pkvAllFaceposer )
  284. {
  285. float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
  286. if ( flEyeheight != -9999.0f )
  287. {
  288. eyeheight = flEyeheight;
  289. }
  290. }
  291. }
  292. model->m_origin.z += eyeheight;
  293. }
  294. else
  295. {
  296. Vector mins, maxs;
  297. model->ExtractBbox(mins, maxs);
  298. Vector size;
  299. VectorSubtract( maxs, mins, size );
  300. float maxdim = size.x;
  301. if ( size.y > maxdim )
  302. maxdim = size.y;
  303. if ( size.z > maxdim )
  304. maxdim = size.z;
  305. float midpoint = mins.z + 0.5 * size.z;
  306. model->m_origin.x = 3 * maxdim;
  307. model->m_origin.z += midpoint;
  308. }
  309. g_pMatSysWindow->PushSnapshotMode( nSnapShotSize );
  310. // Snapshots are taken of the back buffer;
  311. // we need to render to the back buffer but not move it to the front
  312. pWnd->SuppressBufferSwap( true );
  313. pWnd->redraw();
  314. pWnd->SuppressBufferSwap( false );
  315. // make it square, assumes w > h
  316. char fullpath[ 512 ];
  317. Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename );
  318. pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize );
  319. g_pMatSysWindow->PopSnapshotMode( );
  320. VectorCopy( oldrot, model->m_angles );
  321. VectorCopy( oldtrans, model->m_origin );
  322. VectorCopy( oldLight, g_viewerSettings.lightrot );
  323. g_viewerSettings.showGround = bSaveGround;
  324. if ( pExpression )
  325. {
  326. // Save existing settings from model
  327. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
  328. {
  329. int j = hdr->pFlexcontroller( i )->localToGlobal;
  330. if ( j == -1 )
  331. continue;
  332. model->SetFlexController( i, flexValues[ i ] );
  333. }
  334. }
  335. model->ClearOverlaysSequences();
  336. if ( bitmap->valid )
  337. {
  338. DeleteObject( bitmap->image );
  339. bitmap->image = 0;
  340. bitmap->valid = false;
  341. }
  342. LoadBitmapFromFile( pchBitmapFilename, *bitmap );
  343. }
  344. mxbitmapdata_t *IFaceposerModels::CFacePoserModel::GetBitmapForSequence( int sequence )
  345. {
  346. static mxbitmapdata_t nullbitmap;
  347. if ( sequence < 0 || sequence >= m_AnimationBitmaps.Count() )
  348. return &nullbitmap;
  349. /*
  350. if ( m_bFirstBitmapLoad )
  351. {
  352. m_bFirstBitmapLoad = false;
  353. ReconcileAnimationBitmaps();
  354. }
  355. */
  356. AnimBitmap *slot = m_AnimationBitmaps[ sequence ];
  357. if ( slot->needsload )
  358. {
  359. slot->needsload = false;
  360. LoadBitmapForSequence( slot->bitmap, sequence );
  361. }
  362. return m_AnimationBitmaps[ sequence ]->bitmap;
  363. }
  364. void IFaceposerModels::CFacePoserModel::BuildValidChecksums( CUtlRBTree< CRC32_t > &tree )
  365. {
  366. StudioModel *model = m_pModel;
  367. if ( !model )
  368. return;
  369. CStudioHdr *hdr = model->GetStudioHdr();
  370. if ( !hdr )
  371. return;
  372. for ( int i = 0; i < hdr->GetNumSeq(); i++ )
  373. {
  374. CRC32_t crc = GetBitmapCRC( i );
  375. tree.Insert( crc );
  376. }
  377. }
  378. void IFaceposerModels::CFacePoserModel::ReconcileAnimationBitmaps()
  379. {
  380. // iterate files in directory and see if each checksum is valid and if not delete the .bmp
  381. char path[ 512 ];
  382. Q_snprintf( path, sizeof( path ), "expressions/%s/animation/*.bmp", GetShortModelName() );
  383. FileFindHandle_t hFindFile;
  384. char const *fn = filesystem->FindFirstEx( path, "MOD", &hFindFile );
  385. g_pProgressDialog->Start( CFmtStr( "%s - Reconcile Animation Thumbnails", GetShortModelName() ), "", true );
  386. CUtlVector< CUtlString > workList;
  387. if ( fn )
  388. {
  389. while ( fn )
  390. {
  391. // Don't do anything with directories
  392. if ( !filesystem->FindIsDirectory( hFindFile ) )
  393. {
  394. CUtlString s = fn;
  395. workList.AddToTail( s );
  396. }
  397. fn = filesystem->FindNext( hFindFile );
  398. }
  399. filesystem->FindClose( hFindFile );
  400. }
  401. CUtlRBTree< CRC32_t > tree( 0, 0, DefLessFunc( CRC32_t ) );
  402. BuildValidChecksums( tree );
  403. for ( int i = 0 ; i < workList.Count(); ++i )
  404. {
  405. char testname[ 256 ];
  406. Q_StripExtension( workList[ i ].String(), testname, sizeof( testname ) );
  407. g_pProgressDialog->UpdateText( "%s", testname );
  408. g_pProgressDialog->Update( (float)i / (float)workList.Count() );
  409. CRC32_t check;
  410. Q_hextobinary( testname, Q_strlen( testname ), (byte *)&check, sizeof( check ) );
  411. if ( tree.Find( check ) == tree.InvalidIndex() )
  412. {
  413. Q_snprintf( testname, sizeof( testname ), "expressions/%s/animation/%s", GetShortModelName(), fn );
  414. char fullpath[ 512 ];
  415. filesystem->RelativePathToFullPath( testname, "MOD", fullpath, sizeof( fullpath ) );
  416. // Delete it
  417. Con_ErrorPrintf( "Removing unused bitmap file %s\n",
  418. fullpath );
  419. _unlink( fullpath );
  420. }
  421. if ( g_pProgressDialog->IsCancelled() )
  422. {
  423. Msg( "Cancelled\n" );
  424. break;
  425. }
  426. }
  427. g_pProgressDialog->Finish();
  428. }
  429. void IFaceposerModels::CFacePoserModel::RecreateAllAnimationBitmaps()
  430. {
  431. StudioModel *model = m_pModel;
  432. if ( !model )
  433. return;
  434. CStudioHdr *hdr = model->GetStudioHdr();
  435. if ( !hdr )
  436. return;
  437. g_pProgressDialog->Start( CFmtStr( "%s - Animation Thumbnails", GetShortModelName() ), "", true );
  438. for ( int i = 0; i < hdr->GetNumSeq(); ++i )
  439. {
  440. const mstudioseqdesc_t &seq = hdr->pSeqdesc( i );
  441. g_pProgressDialog->UpdateText( "%s", seq.pszLabel() );
  442. g_pProgressDialog->Update( (float)i / (float)hdr->GetNumSeq() );
  443. RecreateAnimationBitmap( i, false );
  444. if ( g_pProgressDialog->IsCancelled() )
  445. {
  446. Msg( "Cancelling\n" );
  447. break;
  448. }
  449. }
  450. g_pProgressDialog->Finish();
  451. ReconcileAnimationBitmaps();
  452. }
  453. void IFaceposerModels::CFacePoserModel::RecreateAnimationBitmap( int sequence, bool reconcile )
  454. {
  455. if ( sequence < 0 || sequence >= m_AnimationBitmaps.Count() )
  456. {
  457. Assert( 0 );
  458. return;
  459. }
  460. AnimBitmap *slot = m_AnimationBitmaps[ sequence ];
  461. slot->needsload = true;
  462. if ( slot->bitmap->valid )
  463. {
  464. DeleteObject( slot->bitmap->image );
  465. slot->bitmap->image = 0;
  466. slot->bitmap->valid = false;
  467. }
  468. char filename[ 512 ];
  469. Q_snprintf( filename, sizeof( filename ), "%s", GetBitmapFilename( sequence ) );
  470. if ( filesystem->FileExists( filename ) )
  471. {
  472. char fullpath[ 512 ];
  473. filesystem->RelativePathToFullPath( filename, "MOD", fullpath, sizeof( fullpath ) );
  474. _unlink( fullpath );
  475. }
  476. // Force recreation
  477. GetBitmapForSequence( sequence );
  478. if ( reconcile )
  479. {
  480. ReconcileAnimationBitmaps( );
  481. }
  482. }
  483. void IFaceposerModels::CFacePoserModel::Release( void )
  484. {
  485. m_pModel->FreeModel( true );
  486. }
  487. void IFaceposerModels::CFacePoserModel::Restore( void )
  488. {
  489. StudioModel *save = g_pStudioModel;
  490. g_pStudioModel = m_pModel;
  491. if (m_pModel->LoadModel( m_pModel->GetFileName() ) )
  492. {
  493. m_pModel->PostLoadModel( m_pModel->GetFileName() );
  494. m_pModel->SetSequence( m_pModel->LookupSequence( "idle_subtle" ) );
  495. }
  496. g_pStudioModel = save;
  497. SetupModelFlexcontrollerLinks( m_pModel );
  498. }
  499. IFaceposerModels::IFaceposerModels()
  500. {
  501. m_nLastRenderFrame = -1;
  502. m_nForceModelIndex = -1;
  503. }
  504. IFaceposerModels::~IFaceposerModels()
  505. {
  506. while ( m_Models.Count() > 0 )
  507. {
  508. delete m_Models[ 0 ];
  509. m_Models.Remove( 0 );
  510. }
  511. }
  512. IFaceposerModels::CFacePoserModel *IFaceposerModels::GetEntry( int index )
  513. {
  514. if ( index < 0 || index >= Count() )
  515. return NULL;
  516. CFacePoserModel *m = m_Models[ index ];
  517. if ( !m )
  518. return NULL;
  519. return m;
  520. }
  521. int IFaceposerModels::Count( void ) const
  522. {
  523. return m_Models.Count();
  524. }
  525. char const *IFaceposerModels::GetModelName( int index )
  526. {
  527. CFacePoserModel *entry = GetEntry( index );
  528. if ( !entry )
  529. return "";
  530. return entry->GetShortModelName();
  531. }
  532. char const *IFaceposerModels::GetModelFileName( int index )
  533. {
  534. CFacePoserModel *entry = GetEntry( index );
  535. if ( !entry )
  536. return "";
  537. return entry->GetModelFileName();
  538. }
  539. void IFaceposerModels::ForceActiveModelIndex( int index )
  540. {
  541. m_nForceModelIndex = index;
  542. }
  543. void IFaceposerModels::UnForceActiveModelIndex()
  544. {
  545. m_nForceModelIndex = -1;
  546. }
  547. int IFaceposerModels::GetActiveModelIndex( void ) const
  548. {
  549. if ( !g_MDLViewer )
  550. return 0;
  551. if ( m_nForceModelIndex != -1 )
  552. return m_nForceModelIndex;
  553. return g_MDLViewer->GetActiveModelTab();
  554. }
  555. char const *IFaceposerModels::GetActiveModelName( void )
  556. {
  557. if ( !g_MDLViewer )
  558. return NULL;
  559. return GetModelName( GetActiveModelIndex() );
  560. }
  561. //-----------------------------------------------------------------------------
  562. // Purpose:
  563. // Output : StudioModel
  564. //-----------------------------------------------------------------------------
  565. StudioModel *IFaceposerModels::GetActiveStudioModel( void )
  566. {
  567. StudioModel *mdl = GetStudioModel( GetActiveModelIndex() );
  568. if ( !mdl )
  569. return g_pStudioModel;
  570. return mdl;
  571. }
  572. int IFaceposerModels::FindModelByFilename( char const *filename )
  573. {
  574. int c = Count();
  575. for ( int i = 0; i < c; i++ )
  576. {
  577. CFacePoserModel *m = GetEntry( i );
  578. if ( !m )
  579. continue;
  580. if ( !stricmp( m->GetModelFileName(), filename ) )
  581. return i;
  582. }
  583. return -1;
  584. }
  585. void SetupModelFlexcontrollerLinks( StudioModel *model );
  586. int IFaceposerModels::LoadModel( char const *filename )
  587. {
  588. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  589. int idx = FindModelByFilename( filename );
  590. if ( idx == -1 && Count() < MAX_FP_MODELS )
  591. {
  592. StudioModel *model = new StudioModel();
  593. StudioModel *save = g_pStudioModel;
  594. g_pStudioModel = model;
  595. if ( !model->LoadModel( filename ) )
  596. {
  597. delete model;
  598. g_pStudioModel = save;
  599. return 0; // ?? ERROR
  600. }
  601. g_pStudioModel = save;
  602. model->SetSequence( model->LookupSequence( "idle_subtle" ) );
  603. int idx = model->GetSequence();
  604. model->SetSequence( idx );
  605. SetupModelFlexcontrollerLinks( model );
  606. if (!LoadViewerSettings( filename, model ))
  607. {
  608. InitViewerSettings( "faceposer" );
  609. }
  610. model->ClearOverlaysSequences();
  611. CFacePoserModel *newEntry = new CFacePoserModel( filename, model );
  612. idx = m_Models.AddToTail( newEntry );
  613. g_MDLViewer->InitModelTab();
  614. g_MDLViewer->SetActiveModelTab( idx );
  615. //g_pControlPanel->CenterOnFace();
  616. }
  617. return idx;
  618. }
  619. void IFaceposerModels::FreeModel( int index )
  620. {
  621. CFacePoserModel *entry = GetEntry( index );
  622. if ( !entry )
  623. return;
  624. StudioModel *m = entry->GetModel();
  625. SaveViewerSettings( m->GetFileName(), m );
  626. m->FreeModel( false );
  627. delete m;
  628. delete entry;
  629. m_Models.Remove( index );
  630. g_MDLViewer->InitModelTab();
  631. }
  632. void IFaceposerModels::CloseAllModels( void )
  633. {
  634. int c = Count();
  635. for ( int i = c - 1; i >= 0; i-- )
  636. {
  637. FreeModel( i );
  638. }
  639. }
  640. StudioModel *IFaceposerModels::GetStudioModel( int index )
  641. {
  642. CFacePoserModel *m = GetEntry( index );
  643. if ( !m )
  644. return NULL;
  645. if ( !m->GetModel() )
  646. return NULL;
  647. return m->GetModel();
  648. }
  649. CStudioHdr *IFaceposerModels::GetStudioHeader( int index )
  650. {
  651. StudioModel *m = GetStudioModel( index );
  652. if ( !m )
  653. return NULL;
  654. CStudioHdr *hdr = m->GetStudioHdr();
  655. if ( !hdr )
  656. return NULL;
  657. return hdr;
  658. }
  659. int IFaceposerModels::GetModelIndexForActor( char const *actorname )
  660. {
  661. int c = Count();
  662. for ( int i = 0; i < c; i++ )
  663. {
  664. CFacePoserModel *m = GetEntry( i );
  665. if ( !m )
  666. continue;
  667. if ( !stricmp( m->GetActorName(), actorname ) )
  668. return i;
  669. }
  670. return 0;
  671. }
  672. StudioModel *IFaceposerModels::GetModelForActor( char const *actorname )
  673. {
  674. int c = Count();
  675. for ( int i = 0; i < c; i++ )
  676. {
  677. CFacePoserModel *m = GetEntry( i );
  678. if ( !m )
  679. continue;
  680. if ( !stricmp( m->GetActorName(), actorname ) )
  681. return m->GetModel();
  682. }
  683. return NULL;
  684. }
  685. char const *IFaceposerModels::GetActorNameForModel( int modelindex )
  686. {
  687. CFacePoserModel *m = GetEntry( modelindex );
  688. if ( !m )
  689. return "";
  690. return m->GetActorName();
  691. }
  692. void IFaceposerModels::SetActorNameForModel( int modelindex, char const *actorname )
  693. {
  694. CFacePoserModel *m = GetEntry( modelindex );
  695. if ( !m )
  696. return;
  697. m->SetActorName( actorname );
  698. }
  699. void IFaceposerModels::SaveModelList( void )
  700. {
  701. workspacefiles->StartStoringFiles( IWorkspaceFiles::MODELDATA );
  702. int c = Count();
  703. for ( int i = 0; i < c; i++ )
  704. {
  705. CFacePoserModel *m = GetEntry( i );
  706. if ( !m )
  707. continue;
  708. workspacefiles->StoreFile( IWorkspaceFiles::MODELDATA, m->GetModelFileName() );
  709. }
  710. workspacefiles->FinishStoringFiles( IWorkspaceFiles::MODELDATA );
  711. }
  712. void IFaceposerModels::LoadModelList( void )
  713. {
  714. int files = workspacefiles->GetNumStoredFiles( IWorkspaceFiles::MODELDATA );
  715. for ( int i = 0; i < files; i++ )
  716. {
  717. char const *filename = workspacefiles->GetStoredFile( IWorkspaceFiles::MODELDATA, i );
  718. LoadModel( filename );
  719. }
  720. }
  721. void IFaceposerModels::ReleaseModels( void )
  722. {
  723. int c = Count();
  724. for ( int i = 0; i < c; i++ )
  725. {
  726. CFacePoserModel *m = GetEntry( i );
  727. if ( !m )
  728. continue;
  729. m->Release();
  730. }
  731. }
  732. void IFaceposerModels::RestoreModels( void )
  733. {
  734. int c = Count();
  735. for ( int i = 0; i < c; i++ )
  736. {
  737. CFacePoserModel *m = GetEntry( i );
  738. if ( !m )
  739. continue;
  740. m->Restore();
  741. }
  742. }
  743. /*
  744. void IFaceposerModels::RefreshModels( void )
  745. {
  746. int c = Count();
  747. for ( int i = 0; i < c; i++ )
  748. {
  749. CFacePoserModel *m = GetEntry( i );
  750. if ( !m )
  751. continue;
  752. m->Refresh();
  753. }
  754. }
  755. */
  756. int IFaceposerModels::CountVisibleModels( void )
  757. {
  758. int num = 0;
  759. int c = Count();
  760. for ( int i = 0; i < c; i++ )
  761. {
  762. CFacePoserModel *m = GetEntry( i );
  763. if ( !m )
  764. continue;
  765. if ( m->GetVisibleIn3DView() )
  766. {
  767. num++;
  768. }
  769. }
  770. return num;
  771. }
  772. void IFaceposerModels::ShowModelIn3DView( int modelindex, bool show )
  773. {
  774. CFacePoserModel *m = GetEntry( modelindex );
  775. if ( !m )
  776. return;
  777. m->SetVisibleIn3DView( show );
  778. }
  779. bool IFaceposerModels::IsModelShownIn3DView( int modelindex )
  780. {
  781. CFacePoserModel *m = GetEntry( modelindex );
  782. if ( !m )
  783. return false;
  784. return m->GetVisibleIn3DView();
  785. }
  786. int IFaceposerModels::GetIndexForStudioModel( StudioModel *model )
  787. {
  788. int c = Count();
  789. for ( int i = 0; i < c; i++ )
  790. {
  791. CFacePoserModel *m = GetEntry( i );
  792. if ( !m )
  793. continue;
  794. if ( m->GetModel() == model )
  795. return i;
  796. }
  797. return -1;
  798. }
  799. void IFaceposerModels::CheckResetFlexes( void )
  800. {
  801. int current_render_frame = g_MDLViewer->GetCurrentFrame();
  802. if ( current_render_frame == m_nLastRenderFrame )
  803. return;
  804. m_nLastRenderFrame = current_render_frame;
  805. // the phoneme editor just adds to the face, so reset the controllers
  806. int c = Count();
  807. for ( int i = 0; i < c; i++ )
  808. {
  809. CFacePoserModel *m = GetEntry( i );
  810. if ( !m )
  811. continue;
  812. StudioModel *model = m->GetModel();
  813. if ( !model )
  814. continue;
  815. CStudioHdr *hdr = model->GetStudioHdr();
  816. if ( !hdr )
  817. continue;
  818. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ )
  819. {
  820. model->SetFlexController( i, 0.0f );
  821. }
  822. }
  823. }
  824. void IFaceposerModels::ClearOverlaysSequences( void )
  825. {
  826. int c = Count();
  827. for ( int i = 0; i < c; i++ )
  828. {
  829. CFacePoserModel *m = GetEntry( i );
  830. if ( !m )
  831. continue;
  832. StudioModel *model = m->GetModel();
  833. if ( !model )
  834. continue;
  835. model->ClearOverlaysSequences();
  836. }
  837. }
  838. mxbitmapdata_t *IFaceposerModels::GetBitmapForSequence( int modelindex, int sequence )
  839. {
  840. static mxbitmapdata_t nullbitmap;
  841. CFacePoserModel *m = GetEntry( modelindex );
  842. if ( !m )
  843. return &nullbitmap;
  844. return m->GetBitmapForSequence( sequence );
  845. }
  846. void IFaceposerModels::RecreateAllAnimationBitmaps( int modelindex )
  847. {
  848. CFacePoserModel *m = GetEntry( modelindex );
  849. if ( !m )
  850. return;
  851. m->RecreateAllAnimationBitmaps();
  852. }
  853. void IFaceposerModels::RecreateAnimationBitmap( int modelindex, int sequence )
  854. {
  855. CFacePoserModel *m = GetEntry( modelindex );
  856. if ( !m )
  857. return;
  858. m->RecreateAnimationBitmap( sequence, true );
  859. }
  860. int IFaceposerModels::CountActiveSources()
  861. {
  862. int count = 0;
  863. int c = Count();
  864. for ( int i = 0; i < c; i++ )
  865. {
  866. CFacePoserModel *m = GetEntry( i );
  867. if ( !m )
  868. continue;
  869. StudioModel *model = m->GetModel();
  870. if ( !model )
  871. continue;
  872. count += model->m_mouth.GetNumVoiceSources();
  873. }
  874. return count;
  875. }
  876. void IFaceposerModels::ClearModelTargets( bool force /*=false*/ )
  877. {
  878. int c = Count();
  879. for ( int i = 0; i < c; i++ )
  880. {
  881. CFacePoserModel *m = GetEntry( i );
  882. if ( !m )
  883. continue;
  884. StudioModel *mdl = m->GetModel();
  885. if ( !mdl )
  886. continue;
  887. mdl->ClearLookTargets();
  888. }
  889. }
  890. void IFaceposerModels::SetSolveHeadTurn( int solve )
  891. {
  892. int c = Count();
  893. for ( int i = 0; i < c; i++ )
  894. {
  895. CFacePoserModel *m = GetEntry( i );
  896. if ( !m )
  897. continue;
  898. StudioModel *mdl = m->GetModel();
  899. if ( !mdl )
  900. continue;
  901. mdl->SetSolveHeadTurn( solve );
  902. }
  903. }
  904. static IFaceposerModels g_ModelManager;
  905. IFaceposerModels *models = &g_ModelManager;