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.

1146 lines
25 KiB

  1. //========= Copyright � 1996-2005, 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. const 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. KeyValues::AutoDelete autodelete_key(seqKeyValues);
  280. if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
  281. {
  282. // Do we have a build point section?
  283. KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
  284. if ( pkvAllFaceposer )
  285. {
  286. float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
  287. if ( flEyeheight != -9999.0f )
  288. {
  289. eyeheight = flEyeheight;
  290. }
  291. }
  292. }
  293. model->m_origin.z += eyeheight;
  294. }
  295. else
  296. {
  297. Vector mins, maxs;
  298. model->ExtractBbox(mins, maxs);
  299. Vector size;
  300. VectorSubtract( maxs, mins, size );
  301. float maxdim = size.x;
  302. if ( size.y > maxdim )
  303. maxdim = size.y;
  304. if ( size.z > maxdim )
  305. maxdim = size.z;
  306. float midpoint = mins.z + 0.5 * size.z;
  307. model->m_origin.x = 3 * maxdim;
  308. model->m_origin.z += midpoint;
  309. }
  310. g_pMatSysWindow->PushSnapshotMode( nSnapShotSize );
  311. // Snapshots are taken of the back buffer;
  312. // we need to render to the back buffer but not move it to the front
  313. pWnd->SuppressBufferSwap( true );
  314. pWnd->redraw();
  315. pWnd->SuppressBufferSwap( false );
  316. // make it square, assumes w > h
  317. char fullpath[ 512 ];
  318. Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename );
  319. pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize );
  320. g_pMatSysWindow->PopSnapshotMode( );
  321. VectorCopy( oldrot, model->m_angles );
  322. VectorCopy( oldtrans, model->m_origin );
  323. VectorCopy( oldLight, g_viewerSettings.lightrot );
  324. g_viewerSettings.showGround = bSaveGround;
  325. if ( pExpression )
  326. {
  327. // Save existing settings from model
  328. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
  329. {
  330. int j = hdr->pFlexcontroller( i )->localToGlobal;
  331. if ( j == -1 )
  332. continue;
  333. model->SetFlexController( i, flexValues[ i ] );
  334. }
  335. }
  336. model->ClearOverlaysSequences();
  337. if ( bitmap->valid )
  338. {
  339. DeleteObject( bitmap->image );
  340. bitmap->image = 0;
  341. bitmap->valid = false;
  342. }
  343. LoadBitmapFromFile( pchBitmapFilename, *bitmap );
  344. }
  345. mxbitmapdata_t *IFaceposerModels::CFacePoserModel::GetBitmapForSequence( int sequence )
  346. {
  347. static mxbitmapdata_t nullbitmap;
  348. if ( sequence < 0 || sequence >= m_AnimationBitmaps.Count() )
  349. return &nullbitmap;
  350. /*
  351. if ( m_bFirstBitmapLoad )
  352. {
  353. m_bFirstBitmapLoad = false;
  354. ReconcileAnimationBitmaps();
  355. }
  356. */
  357. AnimBitmap *slot = m_AnimationBitmaps[ sequence ];
  358. if ( slot->needsload )
  359. {
  360. slot->needsload = false;
  361. LoadBitmapForSequence( slot->bitmap, sequence );
  362. }
  363. return m_AnimationBitmaps[ sequence ]->bitmap;
  364. }
  365. void IFaceposerModels::CFacePoserModel::BuildValidChecksums( CUtlRBTree< CRC32_t > &tree )
  366. {
  367. StudioModel *model = m_pModel;
  368. if ( !model )
  369. return;
  370. CStudioHdr *hdr = model->GetStudioHdr();
  371. if ( !hdr )
  372. return;
  373. for ( int i = 0; i < hdr->GetNumSeq(); i++ )
  374. {
  375. CRC32_t crc = GetBitmapCRC( i );
  376. tree.Insert( crc );
  377. }
  378. }
  379. void IFaceposerModels::CFacePoserModel::ReconcileAnimationBitmaps()
  380. {
  381. // iterate files in directory and see if each checksum is valid and if not delete the .bmp
  382. char path[ 512 ];
  383. Q_snprintf( path, sizeof( path ), "expressions/%s/animation/*.bmp", GetShortModelName() );
  384. FileFindHandle_t hFindFile;
  385. char const *fn = filesystem->FindFirstEx( path, "MOD", &hFindFile );
  386. g_pProgressDialog->Start( CFmtStr( "%s - Reconcile Animation Thumbnails", GetShortModelName() ), "", true );
  387. CUtlVector< CUtlString > workList;
  388. if ( fn )
  389. {
  390. while ( fn )
  391. {
  392. // Don't do anything with directories
  393. if ( !filesystem->FindIsDirectory( hFindFile ) )
  394. {
  395. CUtlString s = fn;
  396. workList.AddToTail( s );
  397. }
  398. fn = filesystem->FindNext( hFindFile );
  399. }
  400. filesystem->FindClose( hFindFile );
  401. }
  402. CUtlRBTree< CRC32_t > tree( 0, 0, DefLessFunc( CRC32_t ) );
  403. BuildValidChecksums( tree );
  404. for ( int i = 0 ; i < workList.Count(); ++i )
  405. {
  406. char testname[ 256 ];
  407. Q_StripExtension( workList[ i ].String(), testname, sizeof( testname ) );
  408. g_pProgressDialog->UpdateText( "%s", testname );
  409. g_pProgressDialog->Update( (float)i / (float)workList.Count() );
  410. CRC32_t check;
  411. Q_hextobinary( testname, Q_strlen( testname ), (byte *)&check, sizeof( check ) );
  412. if ( tree.Find( check ) == tree.InvalidIndex() )
  413. {
  414. Q_snprintf( testname, sizeof( testname ), "expressions/%s/animation/%s", GetShortModelName(), fn );
  415. char fullpath[ 512 ];
  416. filesystem->RelativePathToFullPath( testname, "MOD", fullpath, sizeof( fullpath ) );
  417. // Delete it
  418. Con_ErrorPrintf( "Removing unused bitmap file %s\n",
  419. fullpath );
  420. _unlink( fullpath );
  421. }
  422. if ( g_pProgressDialog->IsCancelled() )
  423. {
  424. Msg( "Cancelled\n" );
  425. break;
  426. }
  427. }
  428. g_pProgressDialog->Finish();
  429. }
  430. void IFaceposerModels::CFacePoserModel::RecreateAllAnimationBitmaps()
  431. {
  432. StudioModel *model = m_pModel;
  433. if ( !model )
  434. return;
  435. CStudioHdr *hdr = model->GetStudioHdr();
  436. if ( !hdr )
  437. return;
  438. g_pProgressDialog->Start( CFmtStr( "%s - Animation Thumbnails", GetShortModelName() ), "", true );
  439. for ( int i = 0; i < hdr->GetNumSeq(); ++i )
  440. {
  441. const mstudioseqdesc_t &seq = hdr->pSeqdesc( i );
  442. g_pProgressDialog->UpdateText( "%s", seq.pszLabel() );
  443. g_pProgressDialog->Update( (float)i / (float)hdr->GetNumSeq() );
  444. RecreateAnimationBitmap( i, false );
  445. if ( g_pProgressDialog->IsCancelled() )
  446. {
  447. Msg( "Cancelling\n" );
  448. break;
  449. }
  450. }
  451. g_pProgressDialog->Finish();
  452. ReconcileAnimationBitmaps();
  453. }
  454. void IFaceposerModels::CFacePoserModel::RecreateAnimationBitmap( int sequence, bool reconcile )
  455. {
  456. if ( sequence < 0 || sequence >= m_AnimationBitmaps.Count() )
  457. {
  458. Assert( 0 );
  459. return;
  460. }
  461. AnimBitmap *slot = m_AnimationBitmaps[ sequence ];
  462. slot->needsload = true;
  463. if ( slot->bitmap->valid )
  464. {
  465. DeleteObject( slot->bitmap->image );
  466. slot->bitmap->image = 0;
  467. slot->bitmap->valid = false;
  468. }
  469. char filename[ 512 ];
  470. Q_snprintf( filename, sizeof( filename ), "%s", GetBitmapFilename( sequence ) );
  471. if ( filesystem->FileExists( filename ) )
  472. {
  473. char fullpath[ 512 ];
  474. filesystem->RelativePathToFullPath( filename, "MOD", fullpath, sizeof( fullpath ) );
  475. _unlink( fullpath );
  476. }
  477. // Force recreation
  478. GetBitmapForSequence( sequence );
  479. if ( reconcile )
  480. {
  481. ReconcileAnimationBitmaps( );
  482. }
  483. }
  484. void IFaceposerModels::CFacePoserModel::Release( void )
  485. {
  486. m_pModel->FreeModel( true );
  487. }
  488. void IFaceposerModels::CFacePoserModel::Restore( void )
  489. {
  490. StudioModel *save = g_pStudioModel;
  491. g_pStudioModel = m_pModel;
  492. if (m_pModel->LoadModel( m_pModel->GetFileName() ) )
  493. {
  494. SetupModelFlexcontrollerLinks( m_pModel );
  495. if (!LoadViewerSettings( m_pModel->GetFileName(), m_pModel ))
  496. {
  497. InitViewerSettings( "faceposer" );
  498. }
  499. m_pModel->ClearOverlaysSequences();
  500. }
  501. g_pStudioModel = save;
  502. }
  503. IFaceposerModels::IFaceposerModels()
  504. {
  505. m_nLastRenderFrame = -1;
  506. m_nForceModelIndex = -1;
  507. }
  508. IFaceposerModels::~IFaceposerModels()
  509. {
  510. while ( m_Models.Count() > 0 )
  511. {
  512. delete m_Models[ 0 ];
  513. m_Models.Remove( 0 );
  514. }
  515. }
  516. IFaceposerModels::CFacePoserModel *IFaceposerModels::GetEntry( int index )
  517. {
  518. if ( index < 0 || index >= Count() )
  519. return NULL;
  520. CFacePoserModel *m = m_Models[ index ];
  521. if ( !m )
  522. return NULL;
  523. return m;
  524. }
  525. int IFaceposerModels::Count( void ) const
  526. {
  527. return m_Models.Count();
  528. }
  529. char const *IFaceposerModels::GetModelName( int index )
  530. {
  531. CFacePoserModel *entry = GetEntry( index );
  532. if ( !entry )
  533. return "";
  534. return entry->GetShortModelName();
  535. }
  536. char const *IFaceposerModels::GetModelFileName( int index )
  537. {
  538. CFacePoserModel *entry = GetEntry( index );
  539. if ( !entry )
  540. return "";
  541. return entry->GetModelFileName();
  542. }
  543. void IFaceposerModels::ForceActiveModelIndex( int index )
  544. {
  545. m_nForceModelIndex = index;
  546. }
  547. void IFaceposerModels::UnForceActiveModelIndex()
  548. {
  549. m_nForceModelIndex = -1;
  550. }
  551. int IFaceposerModels::GetActiveModelIndex( void ) const
  552. {
  553. if ( !g_MDLViewer )
  554. return 0;
  555. if ( m_nForceModelIndex != -1 )
  556. return m_nForceModelIndex;
  557. return g_MDLViewer->GetActiveModelTab();
  558. }
  559. char const *IFaceposerModels::GetActiveModelName( void )
  560. {
  561. if ( !g_MDLViewer )
  562. return NULL;
  563. return GetModelName( GetActiveModelIndex() );
  564. }
  565. //-----------------------------------------------------------------------------
  566. // Purpose:
  567. // Output : StudioModel
  568. //-----------------------------------------------------------------------------
  569. StudioModel *IFaceposerModels::GetActiveStudioModel( void )
  570. {
  571. StudioModel *mdl = GetStudioModel( GetActiveModelIndex() );
  572. if ( !mdl )
  573. return g_pStudioModel;
  574. return mdl;
  575. }
  576. int IFaceposerModels::FindModelByFilename( char const *filename )
  577. {
  578. int c = Count();
  579. for ( int i = 0; i < c; i++ )
  580. {
  581. CFacePoserModel *m = GetEntry( i );
  582. if ( !m )
  583. continue;
  584. if ( !stricmp( m->GetModelFileName(), filename ) )
  585. return i;
  586. }
  587. return -1;
  588. }
  589. void SetupModelFlexcontrollerLinks( StudioModel *model );
  590. int IFaceposerModels::LoadModel( char const *filename )
  591. {
  592. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  593. int idx = FindModelByFilename( filename );
  594. if ( idx == -1 && Count() < MAX_FP_MODELS )
  595. {
  596. StudioModel *model = new StudioModel();
  597. StudioModel *save = g_pStudioModel;
  598. g_pStudioModel = model;
  599. if ( !model->LoadModel( filename ) )
  600. {
  601. delete model;
  602. g_pStudioModel = save;
  603. return 0; // ?? ERROR
  604. }
  605. g_pStudioModel = save;
  606. model->SetSequence( model->LookupSequence( "idle_subtle" ) );
  607. int idx = model->GetSequence();
  608. model->SetSequence( idx );
  609. SetupModelFlexcontrollerLinks( model );
  610. if (!LoadViewerSettings( filename, model ))
  611. {
  612. InitViewerSettings( "faceposer" );
  613. }
  614. model->ClearOverlaysSequences();
  615. CFacePoserModel *newEntry = new CFacePoserModel( filename, model );
  616. idx = m_Models.AddToTail( newEntry );
  617. g_MDLViewer->InitModelTab();
  618. g_MDLViewer->SetActiveModelTab( idx );
  619. //g_pControlPanel->CenterOnFace();
  620. }
  621. return idx;
  622. }
  623. void IFaceposerModels::FreeModel( int index )
  624. {
  625. CFacePoserModel *entry = GetEntry( index );
  626. if ( !entry )
  627. return;
  628. StudioModel *m = entry->GetModel();
  629. SaveViewerSettings( m->GetFileName(), m );
  630. m->FreeModel( false );
  631. delete m;
  632. delete entry;
  633. m_Models.Remove( index );
  634. g_MDLViewer->InitModelTab();
  635. }
  636. void IFaceposerModels::CloseAllModels( void )
  637. {
  638. int c = Count();
  639. for ( int i = c - 1; i >= 0; i-- )
  640. {
  641. FreeModel( i );
  642. }
  643. }
  644. StudioModel *IFaceposerModels::GetStudioModel( int index )
  645. {
  646. CFacePoserModel *m = GetEntry( index );
  647. if ( !m )
  648. return NULL;
  649. if ( !m->GetModel() )
  650. return NULL;
  651. return m->GetModel();
  652. }
  653. CStudioHdr *IFaceposerModels::GetStudioHeader( int index )
  654. {
  655. StudioModel *m = GetStudioModel( index );
  656. if ( !m )
  657. return NULL;
  658. CStudioHdr *hdr = m->GetStudioHdr();
  659. if ( !hdr )
  660. return NULL;
  661. return hdr;
  662. }
  663. int IFaceposerModels::GetModelIndexForActor( char const *actorname )
  664. {
  665. int c = Count();
  666. for ( int i = 0; i < c; i++ )
  667. {
  668. CFacePoserModel *m = GetEntry( i );
  669. if ( !m )
  670. continue;
  671. if ( !stricmp( m->GetActorName(), actorname ) )
  672. return i;
  673. }
  674. return 0;
  675. }
  676. StudioModel *IFaceposerModels::GetModelForActor( char const *actorname )
  677. {
  678. int c = Count();
  679. for ( int i = 0; i < c; i++ )
  680. {
  681. CFacePoserModel *m = GetEntry( i );
  682. if ( !m )
  683. continue;
  684. if ( !stricmp( m->GetActorName(), actorname ) )
  685. return m->GetModel();
  686. }
  687. return NULL;
  688. }
  689. char const *IFaceposerModels::GetActorNameForModel( int modelindex )
  690. {
  691. CFacePoserModel *m = GetEntry( modelindex );
  692. if ( !m )
  693. return "";
  694. return m->GetActorName();
  695. }
  696. void IFaceposerModels::SetActorNameForModel( int modelindex, char const *actorname )
  697. {
  698. CFacePoserModel *m = GetEntry( modelindex );
  699. if ( !m )
  700. return;
  701. m->SetActorName( actorname );
  702. }
  703. void IFaceposerModels::SaveModelList( void )
  704. {
  705. workspacefiles->StartStoringFiles( IWorkspaceFiles::MODELDATA );
  706. int c = Count();
  707. for ( int i = 0; i < c; i++ )
  708. {
  709. CFacePoserModel *m = GetEntry( i );
  710. if ( !m )
  711. continue;
  712. workspacefiles->StoreFile( IWorkspaceFiles::MODELDATA, m->GetModelFileName() );
  713. }
  714. workspacefiles->FinishStoringFiles( IWorkspaceFiles::MODELDATA );
  715. }
  716. void IFaceposerModels::LoadModelList( void )
  717. {
  718. int files = workspacefiles->GetNumStoredFiles( IWorkspaceFiles::MODELDATA );
  719. for ( int i = 0; i < files; i++ )
  720. {
  721. char const *filename = workspacefiles->GetStoredFile( IWorkspaceFiles::MODELDATA, i );
  722. LoadModel( filename );
  723. }
  724. }
  725. void IFaceposerModels::ReleaseModels( void )
  726. {
  727. int c = Count();
  728. for ( int i = 0; i < c; i++ )
  729. {
  730. CFacePoserModel *m = GetEntry( i );
  731. if ( !m )
  732. continue;
  733. m->Release();
  734. }
  735. }
  736. void IFaceposerModels::RestoreModels( void )
  737. {
  738. int c = Count();
  739. for ( int i = 0; i < c; i++ )
  740. {
  741. CFacePoserModel *m = GetEntry( i );
  742. if ( !m )
  743. continue;
  744. m->Restore();
  745. }
  746. }
  747. /*
  748. void IFaceposerModels::RefreshModels( void )
  749. {
  750. int c = Count();
  751. for ( int i = 0; i < c; i++ )
  752. {
  753. CFacePoserModel *m = GetEntry( i );
  754. if ( !m )
  755. continue;
  756. m->Refresh();
  757. }
  758. }
  759. */
  760. int IFaceposerModels::CountVisibleModels( void )
  761. {
  762. int num = 0;
  763. int c = Count();
  764. for ( int i = 0; i < c; i++ )
  765. {
  766. CFacePoserModel *m = GetEntry( i );
  767. if ( !m )
  768. continue;
  769. if ( m->GetVisibleIn3DView() )
  770. {
  771. num++;
  772. }
  773. }
  774. return num;
  775. }
  776. void IFaceposerModels::ShowModelIn3DView( int modelindex, bool show )
  777. {
  778. CFacePoserModel *m = GetEntry( modelindex );
  779. if ( !m )
  780. return;
  781. m->SetVisibleIn3DView( show );
  782. }
  783. bool IFaceposerModels::IsModelShownIn3DView( int modelindex )
  784. {
  785. CFacePoserModel *m = GetEntry( modelindex );
  786. if ( !m )
  787. return false;
  788. return m->GetVisibleIn3DView();
  789. }
  790. int IFaceposerModels::GetIndexForStudioModel( StudioModel *model )
  791. {
  792. int c = Count();
  793. for ( int i = 0; i < c; i++ )
  794. {
  795. CFacePoserModel *m = GetEntry( i );
  796. if ( !m )
  797. continue;
  798. if ( m->GetModel() == model )
  799. return i;
  800. }
  801. return -1;
  802. }
  803. void IFaceposerModels::CheckResetFlexes( void )
  804. {
  805. int current_render_frame = g_MDLViewer->GetCurrentFrame();
  806. if ( current_render_frame == m_nLastRenderFrame )
  807. return;
  808. m_nLastRenderFrame = current_render_frame;
  809. // the phoneme editor just adds to the face, so reset the controllers
  810. int c = Count();
  811. for ( int i = 0; i < c; i++ )
  812. {
  813. CFacePoserModel *m = GetEntry( i );
  814. if ( !m )
  815. continue;
  816. StudioModel *model = m->GetModel();
  817. if ( !model )
  818. continue;
  819. CStudioHdr *hdr = model->GetStudioHdr();
  820. if ( !hdr )
  821. continue;
  822. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ )
  823. {
  824. model->SetFlexController( i, 0.0f );
  825. }
  826. }
  827. }
  828. void IFaceposerModels::ClearOverlaysSequences( void )
  829. {
  830. int c = Count();
  831. for ( int i = 0; i < c; i++ )
  832. {
  833. CFacePoserModel *m = GetEntry( i );
  834. if ( !m )
  835. continue;
  836. StudioModel *model = m->GetModel();
  837. if ( !model )
  838. continue;
  839. model->ClearOverlaysSequences();
  840. }
  841. }
  842. mxbitmapdata_t *IFaceposerModels::GetBitmapForSequence( int modelindex, int sequence )
  843. {
  844. static mxbitmapdata_t nullbitmap;
  845. CFacePoserModel *m = GetEntry( modelindex );
  846. if ( !m )
  847. return &nullbitmap;
  848. return m->GetBitmapForSequence( sequence );
  849. }
  850. void IFaceposerModels::RecreateAllAnimationBitmaps( int modelindex )
  851. {
  852. CFacePoserModel *m = GetEntry( modelindex );
  853. if ( !m )
  854. return;
  855. m->RecreateAllAnimationBitmaps();
  856. }
  857. void IFaceposerModels::RecreateAnimationBitmap( int modelindex, int sequence )
  858. {
  859. CFacePoserModel *m = GetEntry( modelindex );
  860. if ( !m )
  861. return;
  862. m->RecreateAnimationBitmap( sequence, true );
  863. }
  864. int IFaceposerModels::CountActiveSources()
  865. {
  866. int count = 0;
  867. int c = Count();
  868. for ( int i = 0; i < c; i++ )
  869. {
  870. CFacePoserModel *m = GetEntry( i );
  871. if ( !m )
  872. continue;
  873. StudioModel *model = m->GetModel();
  874. if ( !model )
  875. continue;
  876. count += model->m_mouth.GetNumVoiceSources();
  877. }
  878. return count;
  879. }
  880. void IFaceposerModels::ClearModelTargets( bool force /*=false*/ )
  881. {
  882. int c = Count();
  883. for ( int i = 0; i < c; i++ )
  884. {
  885. CFacePoserModel *m = GetEntry( i );
  886. if ( !m )
  887. continue;
  888. StudioModel *mdl = m->GetModel();
  889. if ( !mdl )
  890. continue;
  891. mdl->ClearLookTargets();
  892. }
  893. }
  894. void IFaceposerModels::SetSolveHeadTurn( int solve )
  895. {
  896. int c = Count();
  897. for ( int i = 0; i < c; i++ )
  898. {
  899. CFacePoserModel *m = GetEntry( i );
  900. if ( !m )
  901. continue;
  902. StudioModel *mdl = m->GetModel();
  903. if ( !mdl )
  904. continue;
  905. mdl->SetSolveHeadTurn( solve );
  906. }
  907. }
  908. static IFaceposerModels g_ModelManager;
  909. IFaceposerModels *models = &g_ModelManager;