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.

2297 lines
63 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "studio.h"
  9. #include "datacache/idatacache.h"
  10. #include "datacache/imdlcache.h"
  11. #include "convar.h"
  12. #include "tier1/utlmap.h"
  13. #include "tier1/utlbufferstrider.h"
  14. #include "tier0/vprof.h"
  15. #include "mathlib/femodel.h"
  16. #include "mathlib/femodeldesc.h"
  17. #include "mathlib/softbody.h"
  18. #include "mathlib/softbody.inl"
  19. #include "bone_setup.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. // preload up to 1 second worth of blocks ahead.
  23. ConVar mod_load_preload( "mod_load_preload", IsGameConsole() ? "1.0" : "1.0", 0, "Indicates how far ahead in seconds to preload animations." );
  24. #ifdef _DEBUG
  25. ConVar softbody_debug( "softbody_debug", "0", FCVAR_CHEAT );
  26. ConVar softbody_debug_substr( "softbody_debug_substr", "", FCVAR_CHEAT );
  27. #endif
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. mstudioanimdesc_t &studiohdr_t::pAnimdesc_Internal( int i ) const
  32. {
  33. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  34. Assert( pVModel );
  35. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_anim[i].group ];
  36. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  37. Assert( pStudioHdr );
  38. return *pStudioHdr->pLocalAnimdesc( pVModel->m_anim[i].index );
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. byte *mstudioanimdesc_t::pAnimBlock( int block, int index, bool preloadIfMissing ) const
  44. {
  45. if (block == -1)
  46. {
  47. return (byte *)NULL;
  48. }
  49. if (block == 0)
  50. {
  51. return (((byte *)this) + index);
  52. }
  53. byte *pAnimBlock = pStudiohdr()->GetAnimBlock( block, preloadIfMissing );
  54. if ( pAnimBlock )
  55. {
  56. return pAnimBlock + index;
  57. }
  58. return (byte *)NULL;
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose: Indicates if the block has been preloaded already.
  62. // Returns true if the block is in memory, or is asynchronously loading.
  63. //-----------------------------------------------------------------------------
  64. bool mstudioanimdesc_t::hasAnimBlockBeenPreloaded( int block ) const
  65. {
  66. return pStudiohdr()->hasAnimBlockBeenPreloaded( block );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. static ConVar mod_load_showstall( "mod_load_showstall", "0", 0, "1 - show hitches , 2 - show stalls" );
  72. byte *mstudioanimdesc_t::pAnim( int *piFrame ) const
  73. {
  74. float flStall = 0;
  75. return pAnim( piFrame, flStall );
  76. }
  77. byte *mstudioanimdesc_t::pAnim( int *piFrame, float &flStall ) const
  78. {
  79. byte *panim = NULL;
  80. int block = animblock;
  81. int index = animindex;
  82. int section = 0;
  83. if (sectionframes != 0)
  84. {
  85. if (numframes > sectionframes && *piFrame == numframes - 1)
  86. {
  87. // last frame on long anims is stored separately
  88. *piFrame = 0;
  89. section = (numframes / sectionframes) + 1;
  90. }
  91. else
  92. {
  93. section = *piFrame / sectionframes;
  94. *piFrame -= section * sectionframes;
  95. }
  96. block = pSection( section )->animblock;
  97. index = pSection( section )->animindex;
  98. }
  99. if (block == -1)
  100. {
  101. // model needs to be recompiled
  102. return NULL;
  103. }
  104. panim = pAnimBlock( block, index );
  105. // force a preload of future animations
  106. if ( sectionframes != 0 )
  107. {
  108. // calc how many sections ahead to try looking
  109. int maxSection = MIN( section + (mod_load_preload.GetFloat() * fps / sectionframes), (numframes / sectionframes) ) + 1;
  110. int prevBlock = block;
  111. for ( int i = section + 1; i <= maxSection; i++ )
  112. {
  113. // if this is a new block, preload it
  114. if ( pSection( i )->animblock != prevBlock )
  115. {
  116. bool preloaded = hasAnimBlockBeenPreloaded( pSection( i )->animblock );
  117. if ( preloaded == false )
  118. {
  119. // This will preload the block
  120. pAnimBlock( pSection( i )->animblock, pSection( i )->animindex, true );
  121. // Msg( "[%8.3f] precaching %s:%s:%d:%d.\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), i, pSection( i )->animblock );
  122. }
  123. prevBlock = pSection( i )->animblock;
  124. }
  125. }
  126. }
  127. if (panim == NULL)
  128. {
  129. if (section > 0 && mod_load_showstall.GetInt() > 0)
  130. {
  131. Msg("[%8.3f] hitch on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block );
  132. }
  133. // back up until a previously loaded block is found
  134. while (--section >= 0)
  135. {
  136. block = pSection( section )->animblock;
  137. index = pSection( section )->animindex;
  138. panim = pAnimBlock( block, index, false );
  139. if (panim)
  140. {
  141. // set it to the last frame in the last valid section
  142. *piFrame = sectionframes - 1;
  143. break;
  144. }
  145. }
  146. }
  147. // try to guess a valid stall time interval (tuned for the X360)
  148. flStall = 0.0f;
  149. if (panim == NULL && section <= 0)
  150. {
  151. zeroframestalltime = Plat_FloatTime();
  152. flStall = 1.0f;
  153. }
  154. else if (panim != NULL && zeroframestalltime != 0.0f)
  155. {
  156. float dt = Plat_FloatTime() - zeroframestalltime;
  157. if (dt >= 0.0)
  158. {
  159. flStall = SimpleSpline( clamp( (0.200f - dt) * 5.0, 0.0f, 1.0f ) );
  160. }
  161. if (flStall == 0.0f)
  162. {
  163. // disable stalltime
  164. zeroframestalltime = 0.0f;
  165. }
  166. else if (mod_load_showstall.GetInt() > 1)
  167. {
  168. Msg("[%8.3f] stall blend %.2f on %s:%s:%d:%d\n", Plat_FloatTime(), flStall, pStudiohdr()->pszName(), pszName(), section, block );
  169. }
  170. }
  171. if (panim == NULL && mod_load_showstall.GetInt() > 1)
  172. {
  173. Msg("[%8.3f] stall on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block );
  174. }
  175. return panim;
  176. }
  177. mstudioikrule_t *mstudioanimdesc_t::pIKRule( int i ) const
  178. {
  179. if (numikrules)
  180. {
  181. if (ikruleindex)
  182. {
  183. return (mstudioikrule_t *)(((byte *)this) + ikruleindex) + i;
  184. }
  185. else
  186. {
  187. if (animblock == 0)
  188. {
  189. AssertOnce(0); // Should never happen
  190. return (mstudioikrule_t *)(((byte *)this) + animblockikruleindex) + i;
  191. }
  192. else
  193. {
  194. byte *pAnimBlock = pStudiohdr()->GetAnimBlock( animblock );
  195. if ( pAnimBlock )
  196. {
  197. return (mstudioikrule_t *)(pAnimBlock + animblockikruleindex) + i;
  198. }
  199. }
  200. }
  201. }
  202. return NULL;
  203. }
  204. mstudiolocalhierarchy_t *mstudioanimdesc_t::pHierarchy( int i ) const
  205. {
  206. if (localhierarchyindex)
  207. {
  208. if (animblock == 0)
  209. {
  210. return (mstudiolocalhierarchy_t *)(((byte *)this) + localhierarchyindex) + i;
  211. }
  212. else
  213. {
  214. byte *pAnimBlock = pStudiohdr()->GetAnimBlock( animblock );
  215. if ( pAnimBlock )
  216. {
  217. return (mstudiolocalhierarchy_t *)(pAnimBlock + localhierarchyindex) + i;
  218. }
  219. }
  220. }
  221. return NULL;
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose:
  225. //-----------------------------------------------------------------------------
  226. bool studiohdr_t::SequencesAvailable() const
  227. {
  228. if (numincludemodels == 0)
  229. {
  230. return true;
  231. }
  232. return ( GetVirtualModel() != NULL );
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose:
  236. //-----------------------------------------------------------------------------
  237. int studiohdr_t::GetNumSeq_Internal( void ) const
  238. {
  239. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  240. Assert( pVModel );
  241. return pVModel->m_seq.Count();
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose:
  245. //-----------------------------------------------------------------------------
  246. mstudioseqdesc_t &studiohdr_t::pSeqdesc_Internal( int i ) const
  247. {
  248. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  249. Assert( pVModel );
  250. if ( !pVModel )
  251. {
  252. return *pLocalSeqdesc( i );
  253. }
  254. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[i].group ];
  255. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  256. Assert( pStudioHdr );
  257. return *pStudioHdr->pLocalSeqdesc( pVModel->m_seq[i].index );
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose:
  261. //-----------------------------------------------------------------------------
  262. int studiohdr_t::iRelativeAnim_Internal( int baseseq, int relanim ) const
  263. {
  264. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  265. Assert( pVModel );
  266. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
  267. return pGroup->masterAnim[ relanim ];
  268. }
  269. //-----------------------------------------------------------------------------
  270. // Purpose:
  271. //-----------------------------------------------------------------------------
  272. int studiohdr_t::iRelativeSeq_Internal( int baseseq, int relseq ) const
  273. {
  274. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  275. Assert( pVModel );
  276. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
  277. return pGroup->masterSeq[ relseq ];
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose:
  281. //-----------------------------------------------------------------------------
  282. int studiohdr_t::GetNumPoseParameters( void ) const
  283. {
  284. if (numincludemodels == 0)
  285. {
  286. return numlocalposeparameters;
  287. }
  288. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  289. Assert( pVModel );
  290. return pVModel->m_pose.Count();
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Purpose:
  294. //-----------------------------------------------------------------------------
  295. const mstudioposeparamdesc_t &studiohdr_t::pPoseParameter( int i )
  296. {
  297. if (numincludemodels == 0)
  298. {
  299. return *pLocalPoseParameter( i );
  300. }
  301. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  302. Assert( pVModel );
  303. if ( pVModel->m_pose[i].group == 0)
  304. return *pLocalPoseParameter( pVModel->m_pose[i].index );
  305. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_pose[i].group ];
  306. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  307. Assert( pStudioHdr );
  308. return *pStudioHdr->pLocalPoseParameter( pVModel->m_pose[i].index );
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose:
  312. //-----------------------------------------------------------------------------
  313. int studiohdr_t::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
  314. {
  315. if (numincludemodels == 0)
  316. {
  317. return iLocalPose;
  318. }
  319. if (iLocalPose == -1)
  320. return iLocalPose;
  321. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  322. Assert( pVModel );
  323. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
  324. return pGroup->masterPose[iLocalPose];
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose:
  328. //-----------------------------------------------------------------------------
  329. int studiohdr_t::EntryNode( int iSequence )
  330. {
  331. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  332. if (numincludemodels == 0 || seqdesc.localentrynode == 0)
  333. {
  334. return seqdesc.localentrynode;
  335. }
  336. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  337. Assert( pVModel );
  338. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
  339. return pGroup->masterNode[seqdesc.localentrynode-1]+1;
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Purpose:
  343. //-----------------------------------------------------------------------------
  344. int studiohdr_t::ExitNode( int iSequence )
  345. {
  346. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  347. if (numincludemodels == 0 || seqdesc.localexitnode == 0)
  348. {
  349. return seqdesc.localexitnode;
  350. }
  351. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  352. Assert( pVModel );
  353. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
  354. return pGroup->masterNode[seqdesc.localexitnode-1]+1;
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose:
  358. //-----------------------------------------------------------------------------
  359. int studiohdr_t::GetNumAttachments( void ) const
  360. {
  361. if (numincludemodels == 0)
  362. {
  363. return numlocalattachments;
  364. }
  365. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  366. Assert( pVModel );
  367. return pVModel->m_attachment.Count();
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose:
  371. //-----------------------------------------------------------------------------
  372. const mstudioattachment_t &studiohdr_t::pAttachment( int i ) const
  373. {
  374. if (numincludemodels == 0)
  375. {
  376. return *pLocalAttachment( i );
  377. }
  378. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  379. Assert( pVModel );
  380. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
  381. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  382. Assert( pStudioHdr );
  383. return *pStudioHdr->pLocalAttachment( pVModel->m_attachment[i].index );
  384. }
  385. //-----------------------------------------------------------------------------
  386. // Purpose:
  387. //-----------------------------------------------------------------------------
  388. int studiohdr_t::GetAttachmentBone( int i )
  389. {
  390. const mstudioattachment_t &attachment = pAttachment( i );
  391. // remap bone
  392. virtualmodel_t *pVModel = GetVirtualModel();
  393. if (pVModel)
  394. {
  395. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
  396. int iBone = pGroup->masterBone[attachment.localbone];
  397. if (iBone == -1)
  398. return 0;
  399. return iBone;
  400. }
  401. return attachment.localbone;
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Purpose:
  405. //-----------------------------------------------------------------------------
  406. void studiohdr_t::SetAttachmentBone( int iAttachment, int iBone )
  407. {
  408. mstudioattachment_t &attachment = (mstudioattachment_t &)pAttachment( iAttachment );
  409. // remap bone
  410. virtualmodel_t *pVModel = GetVirtualModel();
  411. if (pVModel)
  412. {
  413. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[iAttachment].group ];
  414. iBone = pGroup->boneMap[iBone];
  415. }
  416. attachment.localbone = iBone;
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Purpose:
  420. //-----------------------------------------------------------------------------
  421. char *studiohdr_t::pszNodeName( int iNode )
  422. {
  423. if (numincludemodels == 0)
  424. {
  425. return pszLocalNodeName( iNode );
  426. }
  427. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  428. Assert( pVModel );
  429. if ( pVModel->m_node.Count() <= iNode-1 )
  430. return "Invalid node";
  431. return pVModel->m_group[ pVModel->m_node[iNode-1].group ].GetStudioHdr()->pszLocalNodeName( pVModel->m_node[iNode-1].index );
  432. }
  433. //-----------------------------------------------------------------------------
  434. // Purpose:
  435. //-----------------------------------------------------------------------------
  436. int studiohdr_t::GetTransition( int iFrom, int iTo ) const
  437. {
  438. if (numincludemodels == 0)
  439. {
  440. return *pLocalTransition( (iFrom-1)*numlocalnodes + (iTo - 1) );
  441. }
  442. return iTo;
  443. /*
  444. FIXME: not connected
  445. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  446. Assert( pVModel );
  447. return pVModel->m_transition.Element( iFrom ).Element( iTo );
  448. */
  449. }
  450. int studiohdr_t::GetActivityListVersion( void )
  451. {
  452. if (numincludemodels == 0)
  453. {
  454. return activitylistversion;
  455. }
  456. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  457. Assert( pVModel );
  458. int version = activitylistversion;
  459. int i;
  460. for (i = 1; i < pVModel->m_group.Count(); i++)
  461. {
  462. virtualgroup_t *pGroup = &pVModel->m_group[ i ];
  463. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  464. Assert( pStudioHdr );
  465. version = MIN( version, pStudioHdr->activitylistversion );
  466. }
  467. return version;
  468. }
  469. void studiohdr_t::SetActivityListVersion( int version ) const
  470. {
  471. activitylistversion = version;
  472. if (numincludemodels == 0)
  473. {
  474. return;
  475. }
  476. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  477. Assert( pVModel );
  478. int i;
  479. for (i = 1; i < pVModel->m_group.Count(); i++)
  480. {
  481. virtualgroup_t *pGroup = &pVModel->m_group[ i ];
  482. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  483. Assert( pStudioHdr );
  484. pStudioHdr->SetActivityListVersion( version );
  485. }
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Purpose:
  489. //-----------------------------------------------------------------------------
  490. int studiohdr_t::GetNumIKAutoplayLocks( void ) const
  491. {
  492. if (numincludemodels == 0)
  493. {
  494. return numlocalikautoplaylocks;
  495. }
  496. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  497. Assert( pVModel );
  498. return pVModel->m_iklock.Count();
  499. }
  500. const mstudioiklock_t &studiohdr_t::pIKAutoplayLock( int i )
  501. {
  502. if (numincludemodels == 0)
  503. {
  504. return *pLocalIKAutoplayLock( i );
  505. }
  506. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  507. Assert( pVModel );
  508. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_iklock[i].group ];
  509. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  510. Assert( pStudioHdr );
  511. return *pStudioHdr->pLocalIKAutoplayLock( pVModel->m_iklock[i].index );
  512. }
  513. int studiohdr_t::CountAutoplaySequences() const
  514. {
  515. int count = 0;
  516. for (int i = 0; i < GetNumSeq(); i++)
  517. {
  518. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  519. if (seqdesc.flags & STUDIO_AUTOPLAY)
  520. {
  521. count++;
  522. }
  523. }
  524. return count;
  525. }
  526. int studiohdr_t::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
  527. {
  528. int outIndex = 0;
  529. for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
  530. {
  531. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  532. if (seqdesc.flags & STUDIO_AUTOPLAY)
  533. {
  534. pOut[outIndex] = i;
  535. outIndex++;
  536. }
  537. }
  538. return outIndex;
  539. }
  540. //-----------------------------------------------------------------------------
  541. // Purpose: maps local sequence bone to global bone
  542. //-----------------------------------------------------------------------------
  543. int studiohdr_t::RemapSeqBone( int iSequence, int iLocalBone ) const
  544. {
  545. // remap bone
  546. virtualmodel_t *pVModel = GetVirtualModel();
  547. if (pVModel)
  548. {
  549. const virtualgroup_t *pSeqGroup = pVModel->pSeqGroup( iSequence );
  550. return pSeqGroup->masterBone[iLocalBone];
  551. }
  552. return iLocalBone;
  553. }
  554. int studiohdr_t::RemapAnimBone( int iAnim, int iLocalBone ) const
  555. {
  556. // remap bone
  557. virtualmodel_t *pVModel = GetVirtualModel();
  558. if (pVModel)
  559. {
  560. const virtualgroup_t *pAnimGroup = pVModel->pAnimGroup( iAnim );
  561. return pAnimGroup->masterBone[iLocalBone];
  562. }
  563. return iLocalBone;
  564. }
  565. //-----------------------------------------------------------------------------
  566. // Purpose:
  567. //-----------------------------------------------------------------------------
  568. CStudioHdr::CStudioHdr( void )
  569. {
  570. // set pointer to bogus value
  571. m_nFrameUnlockCounter = 0;
  572. m_pFrameUnlockCounter = &m_nFrameUnlockCounter;
  573. Init( NULL );
  574. }
  575. CStudioHdr::CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache )
  576. {
  577. // preset pointer to bogus value (it may be overwritten with legitimate data later)
  578. m_nFrameUnlockCounter = 0;
  579. m_pFrameUnlockCounter = &m_nFrameUnlockCounter;
  580. Init( pStudioHdr, mdlcache );
  581. }
  582. // extern IDataCache *g_pDataCache;
  583. void CStudioHdr::Init( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache )
  584. {
  585. m_pStudioHdr = pStudioHdr;
  586. m_pVModel = NULL;
  587. m_pSoftbody = NULL;
  588. m_pStudioHdrCache.RemoveAll();
  589. if (m_pStudioHdr == NULL)
  590. {
  591. return;
  592. }
  593. if ( mdlcache )
  594. {
  595. m_pFrameUnlockCounter = mdlcache->GetFrameUnlockCounterPtr( MDLCACHE_STUDIOHDR );
  596. m_nFrameUnlockCounter = *m_pFrameUnlockCounter - 1;
  597. }
  598. if (m_pStudioHdr->numincludemodels != 0)
  599. {
  600. ResetVModel( m_pStudioHdr->GetVirtualModel() );
  601. }
  602. m_boneFlags.EnsureCount( numbones() );
  603. m_boneParent.EnsureCount( numbones() );
  604. for (int i = 0; i < numbones(); i++)
  605. {
  606. m_boneFlags[i] = pBone( i )->flags;
  607. m_boneParent[i] = pBone( i )->parent;
  608. }
  609. m_pActivityToSequence = NULL;
  610. }
  611. void CStudioHdr::Term()
  612. {
  613. if ( m_pSoftbody )
  614. {
  615. CFeModel *pFeModel = m_pSoftbody->GetFeModel();
  616. m_pSoftbody->Shutdown();
  617. Assert( pFeModel );
  618. MemAlloc_FreeAligned( pFeModel );
  619. m_pSoftbody = NULL;
  620. }
  621. CActivityToSequenceMapping::ReleaseMapping( m_pActivityToSequence );
  622. m_pActivityToSequence = NULL;
  623. }
  624. //-----------------------------------------------------------------------------
  625. // Purpose:
  626. //-----------------------------------------------------------------------------
  627. bool CStudioHdr::SequencesAvailable() const
  628. {
  629. if (m_pStudioHdr->numincludemodels == 0)
  630. {
  631. return true;
  632. }
  633. if (m_pVModel == NULL)
  634. {
  635. // repoll m_pVModel
  636. return (ResetVModel( m_pStudioHdr->GetVirtualModel() ) != NULL);
  637. }
  638. else
  639. return true;
  640. }
  641. const virtualmodel_t * CStudioHdr::ResetVModel( const virtualmodel_t *pVModel ) const
  642. {
  643. if (pVModel != NULL)
  644. {
  645. m_pVModel = (virtualmodel_t *)pVModel;
  646. #if !defined( POSIX )
  647. Assert( !pVModel->m_Lock.GetOwnerId() );
  648. #endif
  649. m_pStudioHdrCache.SetCount( m_pVModel->m_group.Count() );
  650. int i;
  651. for (i = 0; i < m_pStudioHdrCache.Count(); i++)
  652. {
  653. m_pStudioHdrCache[ i ] = NULL;
  654. }
  655. return const_cast<virtualmodel_t *>(pVModel);
  656. }
  657. else
  658. {
  659. m_pVModel = NULL;
  660. return NULL;
  661. }
  662. }
  663. const studiohdr_t *CStudioHdr::GroupStudioHdr( int i )
  664. {
  665. if ( !this )
  666. {
  667. ExecuteNTimes( 5, Warning( "Call to NULL CStudioHdr::GroupStudioHdr()\n" ) );
  668. }
  669. if ( m_nFrameUnlockCounter != *m_pFrameUnlockCounter )
  670. {
  671. m_FrameUnlockCounterMutex.Lock();
  672. if ( *m_pFrameUnlockCounter != m_nFrameUnlockCounter ) // i.e., this thread got the mutex
  673. {
  674. memset( m_pStudioHdrCache.Base(), 0, m_pStudioHdrCache.Count() * sizeof(studiohdr_t *) );
  675. m_nFrameUnlockCounter = *m_pFrameUnlockCounter;
  676. }
  677. m_FrameUnlockCounterMutex.Unlock();
  678. }
  679. if ( !m_pStudioHdrCache.IsValidIndex( i ) )
  680. {
  681. const char *pszName;
  682. pszName = ( m_pStudioHdr ) ? m_pStudioHdr->pszName() : "<<null>>";
  683. ExecuteNTimes( 5, Warning( "Invalid index passed to CStudioHdr(%s)::GroupStudioHdr(): %d [%d]\n", pszName, i, m_pStudioHdrCache.Count() ) );
  684. DebuggerBreakIfDebugging();
  685. return m_pStudioHdr; // return something known to probably exist, certainly things will be messed up, but hopefully not crash before the warning is noticed
  686. }
  687. const studiohdr_t *pStudioHdr = m_pStudioHdrCache[ i ];
  688. if (pStudioHdr == NULL)
  689. {
  690. #if !defined( POSIX )
  691. Assert( !m_pVModel->m_Lock.GetOwnerId() );
  692. #endif
  693. virtualgroup_t *pGroup = &m_pVModel->m_group[ i ];
  694. pStudioHdr = pGroup->GetStudioHdr();
  695. m_pStudioHdrCache[ i ] = pStudioHdr;
  696. }
  697. Assert( pStudioHdr );
  698. return pStudioHdr;
  699. }
  700. const studiohdr_t *CStudioHdr::pSeqStudioHdr( int sequence )
  701. {
  702. if (m_pVModel == NULL)
  703. {
  704. return m_pStudioHdr;
  705. }
  706. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[sequence].group );
  707. return pStudioHdr;
  708. }
  709. const studiohdr_t *CStudioHdr::pAnimStudioHdr( int animation )
  710. {
  711. if (m_pVModel == NULL)
  712. {
  713. return m_pStudioHdr;
  714. }
  715. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[animation].group );
  716. return pStudioHdr;
  717. }
  718. mstudioanimdesc_t &CStudioHdr::pAnimdesc_Internal( int i )
  719. {
  720. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[i].group );
  721. return *pStudioHdr->pLocalAnimdesc( m_pVModel->m_anim[i].index );
  722. }
  723. //-----------------------------------------------------------------------------
  724. // Purpose:
  725. //-----------------------------------------------------------------------------
  726. int CStudioHdr::GetNumSeq_Internal( void ) const
  727. {
  728. return m_pVModel->m_seq.Count();
  729. }
  730. //-----------------------------------------------------------------------------
  731. // Purpose:
  732. //-----------------------------------------------------------------------------
  733. mstudioseqdesc_t &CStudioHdr::pSeqdesc_Internal( int i )
  734. {
  735. Assert( i >= 0 && i < GetNumSeq() );
  736. if ( i < 0 || i >= GetNumSeq() )
  737. {
  738. // Avoid reading random memory.
  739. i = 0;
  740. }
  741. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[i].group );
  742. return *pStudioHdr->pLocalSeqdesc( m_pVModel->m_seq[i].index );
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose:
  746. //-----------------------------------------------------------------------------
  747. int CStudioHdr::iRelativeAnim_Internal( int baseseq, int relanim ) const
  748. {
  749. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
  750. return pGroup->masterAnim[ relanim ];
  751. }
  752. //-----------------------------------------------------------------------------
  753. // Purpose:
  754. //-----------------------------------------------------------------------------
  755. int CStudioHdr::iRelativeSeq( int baseseq, int relseq ) const
  756. {
  757. if (m_pVModel == NULL)
  758. {
  759. return relseq;
  760. }
  761. Assert( m_pVModel );
  762. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
  763. return pGroup->masterSeq[ relseq ];
  764. }
  765. //-----------------------------------------------------------------------------
  766. // Purpose:
  767. //-----------------------------------------------------------------------------
  768. int CStudioHdr::GetNumPoseParameters( void ) const
  769. {
  770. if (m_pVModel == NULL)
  771. {
  772. if ( m_pStudioHdr )
  773. return m_pStudioHdr->numlocalposeparameters;
  774. else
  775. return 0;
  776. }
  777. Assert( m_pVModel );
  778. return m_pVModel->m_pose.Count();
  779. }
  780. //-----------------------------------------------------------------------------
  781. // Purpose:
  782. //-----------------------------------------------------------------------------
  783. const mstudioposeparamdesc_t &CStudioHdr::pPoseParameter( int i )
  784. {
  785. if (m_pVModel == NULL)
  786. {
  787. return *m_pStudioHdr->pLocalPoseParameter( i );
  788. }
  789. if ( m_pVModel->m_pose[i].group == 0)
  790. return *m_pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
  791. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_pose[i].group );
  792. return *pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
  793. }
  794. //-----------------------------------------------------------------------------
  795. // Purpose:
  796. //-----------------------------------------------------------------------------
  797. int CStudioHdr::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
  798. {
  799. if (m_pVModel == NULL)
  800. {
  801. return iLocalPose;
  802. }
  803. if (iLocalPose == -1)
  804. return iLocalPose;
  805. Assert( m_pVModel );
  806. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
  807. return pGroup->masterPose[iLocalPose];
  808. }
  809. //-----------------------------------------------------------------------------
  810. // Purpose:
  811. //-----------------------------------------------------------------------------
  812. int CStudioHdr::EntryNode( int iSequence )
  813. {
  814. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  815. if (m_pVModel == NULL || seqdesc.localentrynode == 0)
  816. {
  817. return seqdesc.localentrynode;
  818. }
  819. Assert( m_pVModel );
  820. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
  821. return pGroup->masterNode[seqdesc.localentrynode-1]+1;
  822. }
  823. //-----------------------------------------------------------------------------
  824. // Purpose:
  825. //-----------------------------------------------------------------------------
  826. int CStudioHdr::ExitNode( int iSequence )
  827. {
  828. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  829. if (m_pVModel == NULL || seqdesc.localexitnode == 0)
  830. {
  831. return seqdesc.localexitnode;
  832. }
  833. Assert( m_pVModel );
  834. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
  835. return pGroup->masterNode[seqdesc.localexitnode-1]+1;
  836. }
  837. //-----------------------------------------------------------------------------
  838. // Purpose:
  839. //-----------------------------------------------------------------------------
  840. int CStudioHdr::GetNumAttachments( void ) const
  841. {
  842. if (m_pVModel == NULL)
  843. {
  844. return m_pStudioHdr->numlocalattachments;
  845. }
  846. Assert( m_pVModel );
  847. return m_pVModel->m_attachment.Count();
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Purpose:
  851. //-----------------------------------------------------------------------------
  852. const mstudioattachment_t &CStudioHdr::pAttachment( int i )
  853. {
  854. if (m_pVModel == NULL)
  855. {
  856. return *m_pStudioHdr->pLocalAttachment( i );
  857. }
  858. Assert( m_pVModel );
  859. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_attachment[i].group );
  860. return *pStudioHdr->pLocalAttachment( m_pVModel->m_attachment[i].index );
  861. }
  862. //-----------------------------------------------------------------------------
  863. // Purpose:
  864. //-----------------------------------------------------------------------------
  865. int CStudioHdr::GetAttachmentBone( int i )
  866. {
  867. if (m_pVModel == 0)
  868. {
  869. return m_pStudioHdr->pLocalAttachment( i )->localbone;
  870. }
  871. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[i].group ];
  872. const mstudioattachment_t &attachment = pAttachment( i );
  873. int iBone = pGroup->masterBone[attachment.localbone];
  874. if (iBone == -1)
  875. return 0;
  876. return iBone;
  877. }
  878. //-----------------------------------------------------------------------------
  879. // Purpose:
  880. //-----------------------------------------------------------------------------
  881. void CStudioHdr::SetAttachmentBone( int iAttachment, int iBone )
  882. {
  883. mstudioattachment_t &attachment = (mstudioattachment_t &)m_pStudioHdr->pAttachment( iAttachment );
  884. // remap bone
  885. if (m_pVModel)
  886. {
  887. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[iAttachment].group ];
  888. iBone = pGroup->boneMap[iBone];
  889. }
  890. attachment.localbone = iBone;
  891. }
  892. //-----------------------------------------------------------------------------
  893. // Purpose:
  894. //-----------------------------------------------------------------------------
  895. char *CStudioHdr::pszNodeName( int iNode )
  896. {
  897. if (m_pVModel == NULL)
  898. {
  899. return m_pStudioHdr->pszLocalNodeName( iNode );
  900. }
  901. if ( m_pVModel->m_node.Count() <= iNode-1 )
  902. return "Invalid node";
  903. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_node[iNode-1].group );
  904. return pStudioHdr->pszLocalNodeName( m_pVModel->m_node[iNode-1].index );
  905. }
  906. //-----------------------------------------------------------------------------
  907. // Purpose:
  908. //-----------------------------------------------------------------------------
  909. int CStudioHdr::GetTransition( int iFrom, int iTo ) const
  910. {
  911. if (m_pVModel == NULL)
  912. {
  913. return *m_pStudioHdr->pLocalTransition( (iFrom-1)*m_pStudioHdr->numlocalnodes + (iTo - 1) );
  914. }
  915. return iTo;
  916. /*
  917. FIXME: not connected
  918. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  919. Assert( pVModel );
  920. return pVModel->m_transition.Element( iFrom ).Element( iTo );
  921. */
  922. }
  923. //-----------------------------------------------------------------------------
  924. // Purpose:
  925. //-----------------------------------------------------------------------------
  926. int CStudioHdr::GetActivityListVersion( void )
  927. {
  928. if (m_pVModel == NULL)
  929. {
  930. return m_pStudioHdr->activitylistversion;
  931. }
  932. int version = m_pStudioHdr->activitylistversion;
  933. int i;
  934. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  935. {
  936. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  937. Assert( pStudioHdr );
  938. version = MIN( version, pStudioHdr->activitylistversion );
  939. }
  940. return version;
  941. }
  942. void CStudioHdr::SetActivityListVersion( int version )
  943. {
  944. m_pStudioHdr->activitylistversion = version;
  945. if (m_pVModel == NULL)
  946. {
  947. return;
  948. }
  949. int i;
  950. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  951. {
  952. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  953. Assert( pStudioHdr );
  954. pStudioHdr->SetActivityListVersion( version );
  955. }
  956. }
  957. //-----------------------------------------------------------------------------
  958. // Purpose:
  959. //-----------------------------------------------------------------------------
  960. int CStudioHdr::GetEventListVersion( void )
  961. {
  962. if (m_pVModel == NULL)
  963. {
  964. return m_pStudioHdr->eventsindexed;
  965. }
  966. int version = m_pStudioHdr->eventsindexed;
  967. int i;
  968. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  969. {
  970. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  971. Assert( pStudioHdr );
  972. version = MIN( version, pStudioHdr->eventsindexed );
  973. }
  974. return version;
  975. }
  976. void CStudioHdr::SetEventListVersion( int version )
  977. {
  978. m_pStudioHdr->eventsindexed = version;
  979. if (m_pVModel == NULL)
  980. {
  981. return;
  982. }
  983. int i;
  984. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  985. {
  986. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  987. Assert( pStudioHdr );
  988. pStudioHdr->eventsindexed = version;
  989. }
  990. }
  991. //-----------------------------------------------------------------------------
  992. // Purpose:
  993. //-----------------------------------------------------------------------------
  994. int CStudioHdr::GetNumIKAutoplayLocks( void ) const
  995. {
  996. if (m_pVModel == NULL)
  997. {
  998. return m_pStudioHdr->numlocalikautoplaylocks;
  999. }
  1000. return m_pVModel->m_iklock.Count();
  1001. }
  1002. const mstudioiklock_t &CStudioHdr::pIKAutoplayLock( int i )
  1003. {
  1004. if (m_pVModel == NULL)
  1005. {
  1006. return *m_pStudioHdr->pLocalIKAutoplayLock( i );
  1007. }
  1008. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_iklock[i].group );
  1009. Assert( pStudioHdr );
  1010. return *pStudioHdr->pLocalIKAutoplayLock( m_pVModel->m_iklock[i].index );
  1011. }
  1012. #if 0
  1013. int CStudioHdr::CountAutoplaySequences() const
  1014. {
  1015. int count = 0;
  1016. for (int i = 0; i < GetNumSeq(); i++)
  1017. {
  1018. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  1019. if (seqdesc.flags & STUDIO_AUTOPLAY)
  1020. {
  1021. count++;
  1022. }
  1023. }
  1024. return count;
  1025. }
  1026. int CStudioHdr::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
  1027. {
  1028. int outIndex = 0;
  1029. for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
  1030. {
  1031. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  1032. if (seqdesc.flags & STUDIO_AUTOPLAY)
  1033. {
  1034. pOut[outIndex] = i;
  1035. outIndex++;
  1036. }
  1037. }
  1038. return outIndex;
  1039. }
  1040. #endif
  1041. //-----------------------------------------------------------------------------
  1042. // Purpose: maps local sequence bone to global bone
  1043. //-----------------------------------------------------------------------------
  1044. int CStudioHdr::RemapSeqBone( int iSequence, int iLocalBone ) const
  1045. {
  1046. // remap bone
  1047. if (m_pVModel)
  1048. {
  1049. const virtualgroup_t *pSeqGroup = m_pVModel->pSeqGroup( iSequence );
  1050. return pSeqGroup->masterBone[iLocalBone];
  1051. }
  1052. return iLocalBone;
  1053. }
  1054. int CStudioHdr::RemapAnimBone( int iAnim, int iLocalBone ) const
  1055. {
  1056. // remap bone
  1057. if (m_pVModel)
  1058. {
  1059. const virtualgroup_t *pAnimGroup = m_pVModel->pAnimGroup( iAnim );
  1060. return pAnimGroup->masterBone[iLocalBone];
  1061. }
  1062. return iLocalBone;
  1063. }
  1064. //-----------------------------------------------------------------------------
  1065. // Purpose: run the interpreted FAC's expressions, converting flex_controller
  1066. // values into FAC weights
  1067. //-----------------------------------------------------------------------------
  1068. void CStudioHdr::RunFlexRulesOld( const float *src, float *dest )
  1069. {
  1070. int i, j;
  1071. // FIXME: this shouldn't be needed, flex without rules should be stripped in studiomdl
  1072. for (i = 0; i < numflexdesc(); i++)
  1073. {
  1074. dest[i] = 0;
  1075. }
  1076. for (i = 0; i < numflexrules(); i++)
  1077. {
  1078. float stack[32] = { 0.0 };
  1079. int k = 0;
  1080. mstudioflexrule_t *prule = pFlexRule( i );
  1081. mstudioflexop_t *pops = prule->iFlexOp( 0 );
  1082. // debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), i + 1, 0, "%2d:%d\n", i, prule->flex );
  1083. for (j = 0; j < prule->numops; j++)
  1084. {
  1085. switch (pops->op)
  1086. {
  1087. case STUDIO_ADD: stack[k-2] = stack[k-2] + stack[k-1]; k--; break;
  1088. case STUDIO_SUB: stack[k-2] = stack[k-2] - stack[k-1]; k--; break;
  1089. case STUDIO_MUL: stack[k-2] = stack[k-2] * stack[k-1]; k--; break;
  1090. case STUDIO_DIV:
  1091. if (stack[k-1] > 0.0001)
  1092. {
  1093. stack[k-2] = stack[k-2] / stack[k-1];
  1094. }
  1095. else
  1096. {
  1097. stack[k-2] = 0;
  1098. }
  1099. k--;
  1100. break;
  1101. case STUDIO_NEG: stack[k-1] = -stack[k-1]; break;
  1102. case STUDIO_MAX: stack[k-2] = MAX( stack[k-2], stack[k-1] ); k--; break;
  1103. case STUDIO_MIN: stack[k-2] = MIN( stack[k-2], stack[k-1] ); k--; break;
  1104. case STUDIO_CONST: stack[k] = pops->d.value; k++; break;
  1105. case STUDIO_FETCH1:
  1106. {
  1107. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index)->localToGlobal;
  1108. stack[k] = src[m];
  1109. k++;
  1110. break;
  1111. }
  1112. case STUDIO_FETCH2:
  1113. {
  1114. stack[k] = dest[pops->d.index]; k++; break;
  1115. }
  1116. case STUDIO_COMBO:
  1117. {
  1118. int m = pops->d.index;
  1119. int km = k - m;
  1120. for ( int i = km + 1; i < k; ++i )
  1121. {
  1122. stack[ km ] *= stack[ i ];
  1123. }
  1124. k = k - m + 1;
  1125. }
  1126. break;
  1127. case STUDIO_DOMINATE:
  1128. {
  1129. int m = pops->d.index;
  1130. int km = k - m;
  1131. float dv = stack[ km ];
  1132. for ( int i = km + 1; i < k; ++i )
  1133. {
  1134. dv *= stack[ i ];
  1135. }
  1136. stack[ km - 1 ] *= 1.0f - dv;
  1137. k -= m;
  1138. }
  1139. break;
  1140. case STUDIO_2WAY_0:
  1141. {
  1142. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1143. stack[ k ] = RemapValClamped( src[m], -1.0f, 0.0f, 1.0f, 0.0f );
  1144. k++;
  1145. }
  1146. break;
  1147. case STUDIO_2WAY_1:
  1148. {
  1149. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1150. stack[ k ] = RemapValClamped( src[m], 0.0f, 1.0f, 0.0f, 1.0f );
  1151. k++;
  1152. }
  1153. break;
  1154. case STUDIO_NWAY:
  1155. {
  1156. LocalFlexController_t valueControllerIndex = static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] );
  1157. int m = pFlexcontroller( valueControllerIndex )->localToGlobal;
  1158. float flValue = src[ m ];
  1159. int v = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1160. const Vector4D filterRamp( stack[ k - 5 ], stack[ k - 4 ], stack[ k - 3 ], stack[ k - 2 ] );
  1161. // Apply multicontrol remapping
  1162. if ( flValue <= filterRamp.x || flValue >= filterRamp.w )
  1163. {
  1164. flValue = 0.0f;
  1165. }
  1166. else if ( flValue < filterRamp.y )
  1167. {
  1168. flValue = RemapValClamped( flValue, filterRamp.x, filterRamp.y, 0.0f, 1.0f );
  1169. }
  1170. else if ( flValue > filterRamp.z )
  1171. {
  1172. flValue = RemapValClamped( flValue, filterRamp.z, filterRamp.w, 1.0f, 0.0f );
  1173. }
  1174. else
  1175. {
  1176. flValue = 1.0f;
  1177. }
  1178. stack[ k - 5 ] = flValue * src[ v ];
  1179. k -= 4;
  1180. }
  1181. break;
  1182. case STUDIO_DME_LOWER_EYELID:
  1183. {
  1184. const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1185. const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1186. const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) );
  1187. const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1188. int nBlinkIndex = static_cast< int >( stack[ k - 2 ] );
  1189. float flBlink = 0.0f;
  1190. if ( nBlinkIndex >= 0 )
  1191. {
  1192. const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) );
  1193. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1194. }
  1195. int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] );
  1196. float flEyeUpDown = 0.0f;
  1197. if ( nEyeUpDownIndex >= 0 )
  1198. {
  1199. const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) );
  1200. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1201. }
  1202. if ( flEyeUpDown > 0.0 )
  1203. {
  1204. stack [ k - 3 ] = ( 1.0f - flEyeUpDown ) * ( 1.0f - flCloseLidV ) * flCloseLid;
  1205. }
  1206. else
  1207. {
  1208. stack [ k - 3 ] = ( 1.0f - flCloseLidV ) * flCloseLid;
  1209. }
  1210. k -= 2;
  1211. }
  1212. break;
  1213. case STUDIO_DME_UPPER_EYELID:
  1214. {
  1215. const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1216. const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1217. const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) );
  1218. const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1219. int nBlinkIndex = static_cast< int >( stack[ k - 2 ] );
  1220. float flBlink = 0.0f;
  1221. if ( nBlinkIndex >= 0 )
  1222. {
  1223. const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) );
  1224. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1225. }
  1226. int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] );
  1227. float flEyeUpDown = 0.0f;
  1228. if ( nEyeUpDownIndex >= 0 )
  1229. {
  1230. const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) );
  1231. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1232. }
  1233. if ( flEyeUpDown < 0.0f )
  1234. {
  1235. stack [ k - 3 ] = ( 1.0f + flEyeUpDown ) * flCloseLidV * flCloseLid;
  1236. }
  1237. else
  1238. {
  1239. stack [ k - 3 ] = flCloseLidV * flCloseLid;
  1240. }
  1241. k -= 2;
  1242. }
  1243. break;
  1244. }
  1245. pops++;
  1246. }
  1247. dest[prule->flex] = stack[0];
  1248. }
  1249. }
  1250. void CStudioHdr::RunFlexRulesNew( const float *src, float *dest )
  1251. {
  1252. // FIXME: this shouldn't be needed, flex without rules should be stripped in studiomdl
  1253. memset( dest, 0, sizeof( dest[0] ) * numflexdesc() );
  1254. for (int i = 0; i < numflexrules(); i++)
  1255. {
  1256. float stack[32];
  1257. float *pSP = stack + ARRAYSIZE( stack );
  1258. mstudioflexrule_t *prule = pFlexRule( i );
  1259. mstudioflexop_t *pops = prule->iFlexOp( 0 );
  1260. int nOps = prule->numops;
  1261. float flTOS = 0.;
  1262. if ( nOps )
  1263. do
  1264. {
  1265. switch (pops->op)
  1266. {
  1267. case STUDIO_ADD:
  1268. flTOS += *(pSP++);
  1269. break;
  1270. case STUDIO_SUB:
  1271. flTOS = *(pSP++) - flTOS;
  1272. break;
  1273. case STUDIO_MUL:
  1274. flTOS *= *(pSP++);
  1275. break;
  1276. case STUDIO_DIV:
  1277. if (flTOS > 0.0001)
  1278. {
  1279. flTOS = *(pSP) / flTOS;
  1280. }
  1281. else
  1282. {
  1283. flTOS = 0.;
  1284. }
  1285. pSP++;
  1286. break;
  1287. case STUDIO_NEG:
  1288. flTOS = -flTOS;
  1289. break;
  1290. case STUDIO_MAX:
  1291. {
  1292. float flNos = *(pSP++);
  1293. flTOS = MAX( flTOS, flNos );
  1294. break;
  1295. }
  1296. case STUDIO_MIN:
  1297. {
  1298. float flNos = *(pSP++);
  1299. flTOS = MIN( flTOS, flNos);
  1300. break;
  1301. }
  1302. case STUDIO_CONST:
  1303. *(--pSP) = flTOS;
  1304. flTOS = pops->d.value;
  1305. break;
  1306. case STUDIO_FETCH1:
  1307. {
  1308. *(--pSP ) = flTOS;
  1309. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index)->localToGlobal;
  1310. flTOS = src[m];
  1311. break;
  1312. }
  1313. case STUDIO_FETCH2:
  1314. {
  1315. *(--pSP) = flTOS;
  1316. flTOS = dest[pops->d.index];
  1317. break;
  1318. }
  1319. case STUDIO_COMBO:
  1320. {
  1321. // tos = prod( top m elements on stack)
  1322. int m = pops->d.index;
  1323. while( --m )
  1324. {
  1325. flTOS *= *(pSP++);
  1326. }
  1327. break;
  1328. }
  1329. break;
  1330. case STUDIO_DOMINATE:
  1331. {
  1332. // tos *= 1-prod( next top m elements on stack)
  1333. int m = pops->d.index;
  1334. float dv = *(pSP++);
  1335. while( --m )
  1336. {
  1337. dv *= *(pSP++);
  1338. }
  1339. flTOS *= 1.0 - dv;
  1340. break;
  1341. }
  1342. break;
  1343. case STUDIO_2WAY_0:
  1344. {
  1345. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1346. *(--pSP) = flTOS;
  1347. flTOS = RemapValClamped( src[m], -1.0f, 0.0f, 1.0f, 0.0f );
  1348. }
  1349. break;
  1350. case STUDIO_2WAY_1:
  1351. {
  1352. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1353. *(--pSP) = flTOS;
  1354. flTOS = RemapValClamped( src[m], 0.0f, 1.0f, 0.0f, 1.0f );
  1355. }
  1356. break;
  1357. case STUDIO_NWAY:
  1358. {
  1359. LocalFlexController_t valueControllerIndex = static_cast< LocalFlexController_t >( (int) flTOS );
  1360. int m = pFlexcontroller( valueControllerIndex )->localToGlobal;
  1361. float flValue = src[ m ];
  1362. int v = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1363. const Vector4D filterRamp( pSP[3], pSP[2], pSP[1], pSP[0] );
  1364. // Apply multicontrol remapping
  1365. if ( flValue <= filterRamp.x || flValue >= filterRamp.w )
  1366. {
  1367. flValue = 0.0f;
  1368. }
  1369. else if ( flValue < filterRamp.y )
  1370. {
  1371. flValue = RemapValClamped( flValue, filterRamp.x, filterRamp.y, 0.0f, 1.0f );
  1372. }
  1373. else if ( flValue > filterRamp.z )
  1374. {
  1375. flValue = RemapValClamped( flValue, filterRamp.z, filterRamp.w, 1.0f, 0.0f );
  1376. }
  1377. else
  1378. {
  1379. flValue = 1.0f;
  1380. }
  1381. pSP+= 4;
  1382. flTOS = flValue * src[ v ];
  1383. }
  1384. break;
  1385. case STUDIO_DME_LOWER_EYELID:
  1386. {
  1387. const mstudioflexcontroller_t *const pCloseLidV =
  1388. pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1389. const float flCloseLidV =
  1390. RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1391. const mstudioflexcontroller_t *const pCloseLid =
  1392. pFlexcontroller( static_cast< LocalFlexController_t >( (int)flTOS ) );
  1393. const float flCloseLid =
  1394. RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1395. int nBlinkIndex = static_cast< int >( pSP[0] );
  1396. float flBlink = 0.0f;
  1397. if ( nBlinkIndex >= 0 )
  1398. {
  1399. const mstudioflexcontroller_t *const pBlink =
  1400. pFlexcontroller( static_cast< LocalFlexController_t >( nBlinkIndex ) );
  1401. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1402. }
  1403. int nEyeUpDownIndex = static_cast< int >( pSP[1] );
  1404. float flEyeUpDown = 0.0f;
  1405. if ( nEyeUpDownIndex >= 0 )
  1406. {
  1407. const mstudioflexcontroller_t *const pEyeUpDown =
  1408. pFlexcontroller( static_cast< LocalFlexController_t >( nEyeUpDownIndex ) );
  1409. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1410. }
  1411. if ( flEyeUpDown > 0.0 )
  1412. {
  1413. flTOS = ( 1.0f - flEyeUpDown ) * ( 1.0f - flCloseLidV ) * flCloseLid;
  1414. }
  1415. else
  1416. {
  1417. flTOS = ( 1.0f - flCloseLidV ) * flCloseLid;
  1418. }
  1419. pSP += 2;
  1420. }
  1421. break;
  1422. case STUDIO_DME_UPPER_EYELID:
  1423. {
  1424. const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1425. const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1426. const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)flTOS ) );
  1427. const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1428. int nBlinkIndex = static_cast< int >( pSP[0] );
  1429. float flBlink = 0.0f;
  1430. if ( nBlinkIndex >= 0 )
  1431. {
  1432. const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( nBlinkIndex ) );
  1433. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1434. }
  1435. int nEyeUpDownIndex = static_cast< int >( pSP[1] );
  1436. float flEyeUpDown = 0.0f;
  1437. if ( nEyeUpDownIndex >= 0 )
  1438. {
  1439. const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( nEyeUpDownIndex ) );
  1440. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1441. }
  1442. if ( flEyeUpDown < 0.0f )
  1443. {
  1444. flTOS = ( 1.0f + flEyeUpDown ) * flCloseLidV * flCloseLid;
  1445. }
  1446. else
  1447. {
  1448. flTOS = flCloseLidV * flCloseLid;
  1449. }
  1450. pSP += 2;
  1451. }
  1452. break;
  1453. }
  1454. pops++;
  1455. } while( --nOps );
  1456. dest[prule->flex] = flTOS;
  1457. }
  1458. }
  1459. #define USE_OLD_FLEX_RULES_INTERPRETER
  1460. void CStudioHdr::RunFlexRules( const float *src, float *dest )
  1461. {
  1462. #ifndef USE_OLD_FLEX_RULES_INTERPRETER
  1463. RunFlexRulesNew( src, dest );
  1464. #else
  1465. RunFlexRulesOld( src, dest );
  1466. #endif
  1467. #if defined(_DEBUG) && !defined(USE_OLD_FLEX_RULES_INTERPRETER)
  1468. float d1[ MAXSTUDIOFLEXDESC ];
  1469. RunFlexRulesOld( src, d1 );
  1470. for ( int i =0; i < numflexdesc(); i++)
  1471. {
  1472. if ( fabs( d1[i] - dest[i] ) > 0.001 )
  1473. {
  1474. Warning("bad %d old =%f new=%f\n", i, dest[i], d1[i] );
  1475. }
  1476. }
  1477. #endif // _DEBUG
  1478. }
  1479. //-----------------------------------------------------------------------------
  1480. // propagate flags all the way down
  1481. //-----------------------------------------------------------------------------
  1482. void CStudioHdr::setBoneFlags( int iBone, int flags )
  1483. {
  1484. ((mstudiobone_t *)pBone( iBone ))->flags |= flags;
  1485. mstudiolinearbone_t *pLinear = pLinearBones();
  1486. if ( pLinear )
  1487. {
  1488. *(pLinear->pflags( iBone )) |= flags;
  1489. }
  1490. m_boneFlags[ iBone ] |= flags;
  1491. }
  1492. void CStudioHdr::clearBoneFlags( int iBone, int flags )
  1493. {
  1494. ((mstudiobone_t *)pBone( iBone ))->flags &= ~flags;
  1495. mstudiolinearbone_t *pLinear = pLinearBones();
  1496. if ( pLinear )
  1497. {
  1498. *(pLinear->pflags( iBone )) &= ~flags;
  1499. }
  1500. m_boneFlags[ iBone ] &= ~flags;
  1501. }
  1502. //-----------------------------------------------------------------------------
  1503. // CODE PERTAINING TO ACTIVITY->SEQUENCE MAPPING SUBCLASS
  1504. //-----------------------------------------------------------------------------
  1505. #define iabs(i) (( (i) >= 0 ) ? (i) : -(i) )
  1506. CUtlSymbolTable g_ActivityModifiersTable;
  1507. extern void SetActivityForSequence( CStudioHdr *pstudiohdr, int i );
  1508. void CStudioHdr::CActivityToSequenceMapping::Initialize( const CStudioHdr * __restrict pstudiohdr )
  1509. {
  1510. VPROF( "CStudioHdr::CActivityToSequenceMapping::Initialize" );
  1511. // Algorithm: walk through every sequence in the model, determine to which activity
  1512. // it corresponds, and keep a count of sequences per activity. Once the total count
  1513. // is available, allocate an array large enough to contain them all, update the
  1514. // starting indices for every activity's section in the array, and go back through,
  1515. // populating the array with its data.
  1516. m_pStudioHdr = pstudiohdr->m_pStudioHdr;
  1517. AssertMsg1( m_pSequenceTuples == NULL, "Tried to double-initialize sequence mapping for %s", pstudiohdr->pszName() );
  1518. if ( m_pSequenceTuples != NULL )
  1519. return; // don't double initialize.
  1520. SetValidation(pstudiohdr);
  1521. if ( ! pstudiohdr->SequencesAvailable() )
  1522. return; // nothing to do.
  1523. // Some studio headers have no activities at all. In those
  1524. // cases we can avoid a lot of this effort.
  1525. bool bFoundOne = false;
  1526. // for each sequence in the header...
  1527. const int NumSeq = pstudiohdr->GetNumSeq();
  1528. for ( int i = 0 ; i < NumSeq ; ++i )
  1529. {
  1530. const mstudioseqdesc_t &seqdesc = ((CStudioHdr *)pstudiohdr)->pSeqdesc( i );
  1531. #if defined(SERVER_DLL) || defined(CLIENT_DLL) || defined(GAME_DLL)
  1532. if (!(seqdesc.flags & STUDIO_ACTIVITY))
  1533. {
  1534. // AssertMsg2( false, "Sequence %d on studiohdr %s didn't have its activity initialized!", i, pstudiohdr->pszName() );
  1535. SetActivityForSequence( (CStudioHdr *)pstudiohdr, i );
  1536. }
  1537. #endif
  1538. // is there an activity associated with this sequence?
  1539. if (seqdesc.activity >= 0)
  1540. {
  1541. bFoundOne = true;
  1542. // look up if we already have an entry. First we need to make a speculative one --
  1543. HashValueType entry(seqdesc.activity, 0, 1, iabs(seqdesc.actweight));
  1544. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1545. if ( m_ActToSeqHash.IsValidHandle(handle) )
  1546. {
  1547. // we already have an entry and must update it by incrementing count
  1548. HashValueType * __restrict toUpdate = &m_ActToSeqHash.Element(handle);
  1549. toUpdate->count += 1;
  1550. toUpdate->totalWeight += iabs(seqdesc.actweight);
  1551. Assert( toUpdate->totalWeight > 0 );
  1552. }
  1553. else
  1554. {
  1555. // we do not have an entry yet; create one.
  1556. m_ActToSeqHash.Insert(entry);
  1557. }
  1558. }
  1559. }
  1560. // if we found nothing, don't bother with any other initialization!
  1561. if (!bFoundOne)
  1562. return;
  1563. // Now, create starting indices for each activity. For an activity n,
  1564. // the starting index is of course the sum of counts [0..n-1].
  1565. register int sequenceCount = 0;
  1566. int topActivity = 0; // this will store the highest seen activity number (used later to make an ad hoc map on the stack)
  1567. for ( UtlHashHandle_t handle = m_ActToSeqHash.GetFirstHandle() ;
  1568. m_ActToSeqHash.IsValidHandle(handle) ;
  1569. handle = m_ActToSeqHash.GetNextHandle(handle) )
  1570. {
  1571. HashValueType &element = m_ActToSeqHash[handle];
  1572. element.startingIdx = sequenceCount;
  1573. sequenceCount += element.count;
  1574. topActivity = MAX(topActivity, element.activityIdx);
  1575. }
  1576. // Allocate the actual array of sequence information. Note the use of restrict;
  1577. // this is an important optimization, but means that you must never refer to this
  1578. // array through m_pSequenceTuples in the scope of this function.
  1579. SequenceTuple * __restrict tupleList = new SequenceTuple[sequenceCount];
  1580. m_pSequenceTuples = tupleList; // save it off -- NEVER USE m_pSequenceTuples in this function!
  1581. m_iSequenceTuplesCount = sequenceCount;
  1582. // Now we're going to actually populate that list with the relevant data.
  1583. // First, create an array on the stack to store how many sequences we've written
  1584. // so far for each activity. (This is basically a very simple way of doing a map.)
  1585. // This stack may potentially grow very large; so if you have problems with it,
  1586. // go to a utlmap or similar structure.
  1587. unsigned int allocsize = (topActivity + 1) * sizeof(int);
  1588. #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression
  1589. allocsize = ALIGN_VALUE(allocsize,16);
  1590. int * __restrict seqsPerAct = static_cast<int *>(stackalloc(allocsize));
  1591. memset(seqsPerAct, 0, allocsize);
  1592. // okay, walk through all the sequences again, and write the relevant data into
  1593. // our little table.
  1594. for ( int i = 0 ; i < NumSeq ; ++i )
  1595. {
  1596. const mstudioseqdesc_t &seqdesc = ((CStudioHdr *)pstudiohdr)->pSeqdesc( i );
  1597. if (seqdesc.activity >= 0)
  1598. {
  1599. const HashValueType &element = m_ActToSeqHash[m_ActToSeqHash.Find(HashValueType(seqdesc.activity, 0, 0, 0))];
  1600. // If this assert trips, we've written more sequences per activity than we allocated
  1601. // (therefore there must have been a miscount in the first for loop above).
  1602. int tupleOffset = seqsPerAct[seqdesc.activity];
  1603. Assert( tupleOffset < element.count );
  1604. if ( seqdesc.numactivitymodifiers > 0 )
  1605. {
  1606. // add entries for this model's activity modifiers
  1607. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = new CUtlSymbol[ seqdesc.numactivitymodifiers ];
  1608. (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = seqdesc.numactivitymodifiers;
  1609. for ( int k = 0; k < seqdesc.numactivitymodifiers; k++ )
  1610. {
  1611. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers[ k ] = g_ActivityModifiersTable.AddString( seqdesc.pActivityModifier( k )->pszName() );
  1612. }
  1613. }
  1614. else
  1615. {
  1616. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = NULL;
  1617. (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = 0;
  1618. }
  1619. // You might be tempted to collapse this pointer math into a single pointer --
  1620. // don't! the tuple list is marked __restrict above.
  1621. (tupleList + element.startingIdx + tupleOffset)->seqnum = i; // store sequence number
  1622. (tupleList + element.startingIdx + tupleOffset)->weight = iabs(seqdesc.actweight);
  1623. // We can't have weights of 0
  1624. // Assert( (tupleList + element.startingIdx + tupleOffset)->weight > 0 );
  1625. if ( (tupleList + element.startingIdx + tupleOffset)->weight == 0 )
  1626. {
  1627. (tupleList + element.startingIdx + tupleOffset)->weight = 1;
  1628. }
  1629. seqsPerAct[seqdesc.activity] += 1;
  1630. }
  1631. }
  1632. #ifdef DBGFLAG_ASSERT
  1633. // double check that we wrote exactly the right number of sequences.
  1634. unsigned int chkSequenceCount = 0;
  1635. for (int j = 0 ; j <= topActivity ; ++j)
  1636. {
  1637. chkSequenceCount += seqsPerAct[j];
  1638. }
  1639. Assert(chkSequenceCount == m_iSequenceTuplesCount);
  1640. #endif
  1641. }
  1642. /// Force Initialize() to occur again, even if it has already occured.
  1643. void CStudioHdr::CActivityToSequenceMapping::Reinitialize( CStudioHdr *pstudiohdr )
  1644. {
  1645. if (m_pSequenceTuples)
  1646. {
  1647. delete m_pSequenceTuples;
  1648. m_pSequenceTuples = NULL;
  1649. }
  1650. m_ActToSeqHash.RemoveAll();
  1651. Initialize(pstudiohdr);
  1652. }
  1653. // Look up relevant data for an activity's sequences. This isn't terribly efficient, due to the
  1654. // load-hit-store on the output parameters, so the most common case -- SelectWeightedSequence --
  1655. // is specially implemented.
  1656. const CStudioHdr::CActivityToSequenceMapping::SequenceTuple *CStudioHdr::CActivityToSequenceMapping::GetSequences( int forActivity, int * __restrict outSequenceCount, int * __restrict outTotalWeight )
  1657. {
  1658. // Construct a dummy entry so we can do a hash lookup (the UtlHash does not divorce keys from values)
  1659. HashValueType entry(forActivity, 0, 0, 0);
  1660. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1661. if (m_ActToSeqHash.IsValidHandle(handle))
  1662. {
  1663. const HashValueType &element = m_ActToSeqHash[handle];
  1664. const SequenceTuple *retval = m_pSequenceTuples + element.startingIdx;
  1665. *outSequenceCount = element.count;
  1666. *outTotalWeight = element.totalWeight;
  1667. return retval;
  1668. }
  1669. else
  1670. {
  1671. // invalid handle; return NULL.
  1672. // this is actually a legit use case, so no need to assert.
  1673. return NULL;
  1674. }
  1675. }
  1676. int CStudioHdr::CActivityToSequenceMapping::NumSequencesForActivity( int forActivity )
  1677. {
  1678. // If this trips, you've called this function on something that doesn't
  1679. // have activities.
  1680. //Assert(m_pSequenceTuples != NULL);
  1681. if ( m_pSequenceTuples == NULL )
  1682. return 0;
  1683. HashValueType entry(forActivity, 0, 0, 0);
  1684. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1685. if (m_ActToSeqHash.IsValidHandle(handle))
  1686. {
  1687. return m_ActToSeqHash[handle].count;
  1688. }
  1689. else
  1690. {
  1691. return 0;
  1692. }
  1693. }
  1694. static CStudioHdr::CActivityToSequenceMapping emptyMapping;
  1695. // double-check that the data I point to hasn't changed
  1696. bool CStudioHdr::CActivityToSequenceMapping::ValidateAgainst( const CStudioHdr * RESTRICT pstudiohdr ) RESTRICT
  1697. {
  1698. return ( this == &emptyMapping ||
  1699. ( m_pStudioHdr == pstudiohdr->m_pStudioHdr && m_expectedVModel == pstudiohdr->GetVirtualModel() ) );
  1700. }
  1701. void CStudioHdr::CActivityToSequenceMapping::SetValidation( const CStudioHdr *RESTRICT pstudiohdr ) RESTRICT
  1702. {
  1703. m_expectedVModel = pstudiohdr->GetVirtualModel();
  1704. }
  1705. struct StudioHdrToActivityMapEntry_t
  1706. {
  1707. long checksum;
  1708. char name[64];
  1709. int nRefs;
  1710. CStudioHdr::CActivityToSequenceMapping *pMap;
  1711. };
  1712. CUtlMap<const studiohdr_t *, StudioHdrToActivityMapEntry_t> g_StudioHdrToActivityMaps( DefLessFunc( const studiohdr_t * ) );
  1713. CThreadFastMutex g_StudioHdrToActivityMapsLock;
  1714. CStudioHdr::CActivityToSequenceMapping *CStudioHdr::CActivityToSequenceMapping::FindMapping( const CStudioHdr *pHdr )
  1715. {
  1716. VPROF( "CStudioHdr::CActivityToSequenceMapping::FindMapping" );
  1717. if ( !pHdr->SequencesAvailable() || pHdr->GetNumSeq() <= 1 )
  1718. {
  1719. return &emptyMapping;
  1720. }
  1721. Assert( !pHdr->m_pActivityToSequence );
  1722. AUTO_LOCK( g_StudioHdrToActivityMapsLock );
  1723. const studiohdr_t *pRealHdr = pHdr->m_pStudioHdr;
  1724. int i = g_StudioHdrToActivityMaps.Find( pRealHdr );
  1725. if ( i != g_StudioHdrToActivityMaps.InvalidIndex() )
  1726. {
  1727. if ( !IsX360() && ( g_StudioHdrToActivityMaps[i].checksum != pRealHdr->checksum || Q_strcmp( g_StudioHdrToActivityMaps[i].name, pRealHdr->name ) != 0 ) )
  1728. {
  1729. AssertFatal( g_StudioHdrToActivityMaps[i].nRefs == 0 );
  1730. delete g_StudioHdrToActivityMaps[i].pMap;
  1731. g_StudioHdrToActivityMaps.RemoveAt( i );
  1732. }
  1733. else
  1734. {
  1735. Assert( g_StudioHdrToActivityMaps[i].checksum == pRealHdr->checksum && Q_strcmp( g_StudioHdrToActivityMaps[i].name, pRealHdr->name ) == 0 );
  1736. g_StudioHdrToActivityMaps[i].nRefs++;
  1737. return g_StudioHdrToActivityMaps[i].pMap;
  1738. }
  1739. }
  1740. i = g_StudioHdrToActivityMaps.Insert( pRealHdr );
  1741. g_StudioHdrToActivityMaps[i].checksum = pRealHdr->checksum;
  1742. Q_strncpy( g_StudioHdrToActivityMaps[i].name, pRealHdr->name, 64 );
  1743. g_StudioHdrToActivityMaps[i].nRefs = 1;
  1744. g_StudioHdrToActivityMaps[i].pMap = new CStudioHdr::CActivityToSequenceMapping;
  1745. g_StudioHdrToActivityMaps[i].pMap->Initialize( pHdr );
  1746. return g_StudioHdrToActivityMaps[i].pMap;
  1747. }
  1748. void CStudioHdr::CActivityToSequenceMapping::ReleaseMapping( CActivityToSequenceMapping *pMap )
  1749. {
  1750. if ( pMap && pMap != &emptyMapping)
  1751. {
  1752. VPROF( "CStudioHdr::CActivityToSequenceMapping::ReleaseMapping" );
  1753. AUTO_LOCK( g_StudioHdrToActivityMapsLock );
  1754. int i = g_StudioHdrToActivityMaps.Find( pMap->m_pStudioHdr );
  1755. if ( i != g_StudioHdrToActivityMaps.InvalidIndex() )
  1756. {
  1757. Assert( g_StudioHdrToActivityMaps[i].nRefs > 0 );
  1758. g_StudioHdrToActivityMaps[i].nRefs--;
  1759. }
  1760. else
  1761. {
  1762. Assert( 0 );
  1763. }
  1764. }
  1765. }
  1766. void CStudioHdr::CActivityToSequenceMapping::ResetMappings()
  1767. {
  1768. for ( int i = g_StudioHdrToActivityMaps.FirstInorder(); i != g_StudioHdrToActivityMaps.InvalidIndex(); i = g_StudioHdrToActivityMaps.NextInorder( i ) )
  1769. {
  1770. if ( g_StudioHdrToActivityMaps[i].nRefs == 0 )
  1771. {
  1772. delete g_StudioHdrToActivityMaps[i].pMap;
  1773. }
  1774. else
  1775. {
  1776. Msg( "****************************************************************\n" );
  1777. Msg( "****************************************************************\n" );
  1778. Msg( "************* DO NOT IGNORE ME *******************************\n" );
  1779. Msg( "****************************************************************\n" );
  1780. Msg( "****************************************************************\n" );
  1781. Warning( "Studio activity sequence mapping leak! (%s, %d)\n", g_StudioHdrToActivityMaps[i].name, g_StudioHdrToActivityMaps[i].nRefs );
  1782. Msg( "****************************************************************\n" );
  1783. Msg( "****************************************************************\n" );
  1784. Msg( "****************************************************************\n" );
  1785. Msg( "****************************************************************\n" );
  1786. Msg( "****************************************************************\n" );
  1787. }
  1788. }
  1789. g_StudioHdrToActivityMaps.RemoveAll();
  1790. }
  1791. //-----------------------------------------------------------------------------
  1792. //
  1793. //-----------------------------------------------------------------------------
  1794. int CStudioHdr::LookupSequence( const char *pszName )
  1795. {
  1796. int iSequence = m_namedSequence.Find( pszName );
  1797. if ( iSequence == m_namedSequence.InvalidIndex() )
  1798. {
  1799. for (iSequence = 0; iSequence < GetNumSeq(); iSequence++)
  1800. {
  1801. if ( V_stricmp( pSeqdesc( iSequence ).pszLabel(), pszName ) == 0)
  1802. break;
  1803. }
  1804. if ( iSequence == GetNumSeq() )
  1805. {
  1806. m_namedSequence.Insert( pszName, -1 );
  1807. return -1;
  1808. }
  1809. else
  1810. {
  1811. m_namedSequence.Insert( pszName, iSequence );
  1812. return iSequence;
  1813. }
  1814. }
  1815. else
  1816. {
  1817. return m_namedSequence[iSequence];
  1818. }
  1819. }
  1820. CSoftbody * CStudioHdr::InitSoftbody( CSoftbodyEnvironment *pSoftbodyEnvironment )
  1821. {
  1822. #if defined( CLIENT_DLL ) || defined( ENABLE_STUDIO_SOFTBODY )
  1823. if ( m_pSoftbody )
  1824. {
  1825. ExecuteOnce( Warning( "InitSoftbody is called with Softbody already existing. This pattern is suspicious and will not work if skeleton has changed, please show Sergiy a repro.\n" ) );
  1826. return m_pSoftbody;
  1827. }
  1828. if ( m_pStudioHdr->studiohdr2index )
  1829. {
  1830. const studiohdr2_t *pHdr2 = m_pStudioHdr->pStudioHdr2();
  1831. if ( const PhysFeModelDesc_t *pFeModelDesc = pHdr2->m_pFeModel.GetPtr() )
  1832. {
  1833. uint numCtrlNames = pFeModelDesc->m_CtrlName.Count();
  1834. CBufferStrider feModelData( MemAlloc_AllocAligned( sizeof( CFeModel ) + sizeof( CSoftbody ) + sizeof( char* ) * numCtrlNames, 16 ) );
  1835. CFeModel *pFeModel = feModelData.Stride<CFeModel>();
  1836. m_pSoftbody = feModelData.Stride< CSoftbody >();
  1837. Construct( m_pSoftbody );
  1838. #ifdef _DEBUG
  1839. if ( softbody_debug.GetInt() )
  1840. {
  1841. const char *pSubstr = softbody_debug_substr.GetString();
  1842. Msg( "InitSoftbody%s %s %p\n", ( *pSubstr && V_stristr( name(), pSubstr ) ) ? "!":"", name(), m_pSoftbody );
  1843. }
  1844. #endif
  1845. char **pCtrlNames = feModelData.Stride< char* >( numCtrlNames );
  1846. Clone( pFeModelDesc, 0, pCtrlNames, pFeModel );
  1847. int numModelBones = numbones();
  1848. m_pSoftbody->Init( pSoftbodyEnvironment, pFeModel, numModelBones );
  1849. for ( uint nCtrl = 0; nCtrl < pFeModel->m_nCtrlCount; ++nCtrl )
  1850. {
  1851. int nModelBone = Studio_BoneIndexByName( this, pFeModel->m_pCtrlName[ nCtrl ] );
  1852. m_pSoftbody->BindModelBoneToCtrl( nModelBone, nCtrl );
  1853. //m_pStudioHdr->setBoneFlags( nModelBone, BONE_ALWAYS_PROCEDURAL );
  1854. //const_cast< mstudiobone_t* >( m_pStudioHdr->pBone( nModelBone ) )->proctype = STUDIO_PROC_SOFTBODY;
  1855. }
  1856. }
  1857. }
  1858. #endif
  1859. return m_pSoftbody;
  1860. }
  1861. void CStudioHdr::FreeSoftbody()
  1862. {
  1863. #if defined( CLIENT_DLL ) || defined( ENABLE_STUDIO_SOFTBODY )
  1864. if ( m_pSoftbody )
  1865. {
  1866. #ifdef _DEBUG
  1867. if ( softbody_debug.GetInt() )
  1868. Msg("FreeSoftbody %s %p\n", name(), m_pSoftbody);
  1869. #endif
  1870. CFeModel *pFeModel = m_pSoftbody->GetFeModel();
  1871. m_pSoftbody->Shutdown();
  1872. Assert( pFeModel );
  1873. MemAlloc_FreeAligned( pFeModel );
  1874. m_pSoftbody = NULL;
  1875. }
  1876. #endif
  1877. }