Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1860 lines
49 KiB

  1. //========= Copyright 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. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Purpose:
  16. //-----------------------------------------------------------------------------
  17. mstudioanimdesc_t &studiohdr_t::pAnimdesc( int i ) const
  18. {
  19. if (numincludemodels == 0)
  20. {
  21. return *pLocalAnimdesc( i );
  22. }
  23. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  24. Assert( pVModel );
  25. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_anim[i].group ];
  26. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  27. Assert( pStudioHdr );
  28. return *pStudioHdr->pLocalAnimdesc( pVModel->m_anim[i].index );
  29. }
  30. //-----------------------------------------------------------------------------
  31. // Purpose:
  32. //-----------------------------------------------------------------------------
  33. mstudioanim_t *mstudioanimdesc_t::pAnimBlock( int block, int index ) const
  34. {
  35. if (block == -1)
  36. {
  37. return (mstudioanim_t *)NULL;
  38. }
  39. if (block == 0)
  40. {
  41. return (mstudioanim_t *)(((byte *)this) + index);
  42. }
  43. byte *pAnimBlock = pStudiohdr()->GetAnimBlock( block );
  44. if ( pAnimBlock )
  45. {
  46. return (mstudioanim_t *)(pAnimBlock + index);
  47. }
  48. return (mstudioanim_t *)NULL;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Purpose:
  52. //-----------------------------------------------------------------------------
  53. static ConVar mod_load_showstall( "mod_load_showstall", "0", 0, "1 - show hitches , 2 - show stalls" );
  54. mstudioanim_t *mstudioanimdesc_t::pAnim( int *piFrame ) const
  55. {
  56. float flStall;
  57. return pAnim( piFrame, flStall );
  58. }
  59. mstudioanim_t *mstudioanimdesc_t::pAnim( int *piFrame, float &flStall ) const
  60. {
  61. mstudioanim_t *panim = NULL;
  62. int block = animblock;
  63. int index = animindex;
  64. int section = 0;
  65. if (sectionframes != 0)
  66. {
  67. if (numframes > sectionframes && *piFrame == numframes - 1)
  68. {
  69. // last frame on long anims is stored separately
  70. *piFrame = 0;
  71. section = (numframes / sectionframes) + 1;
  72. }
  73. else
  74. {
  75. section = *piFrame / sectionframes;
  76. *piFrame -= section * sectionframes;
  77. }
  78. block = pSection( section )->animblock;
  79. index = pSection( section )->animindex;
  80. }
  81. if (block == -1)
  82. {
  83. // model needs to be recompiled
  84. return NULL;
  85. }
  86. panim = pAnimBlock( block, index );
  87. // force a preload on the next block
  88. if ( sectionframes != 0 )
  89. {
  90. int count = ( numframes / sectionframes) + 2;
  91. for ( int i = section + 1; i < count; i++ )
  92. {
  93. if ( pSection( i )->animblock != block )
  94. {
  95. pAnimBlock( pSection( i )->animblock, pSection( i )->animindex );
  96. break;
  97. }
  98. }
  99. }
  100. if (panim == NULL)
  101. {
  102. if (section > 0 && mod_load_showstall.GetInt() > 0)
  103. {
  104. Msg("[%8.3f] hitch on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block );
  105. }
  106. // back up until a previously loaded block is found
  107. while (--section >= 0)
  108. {
  109. block = pSection( section )->animblock;
  110. index = pSection( section )->animindex;
  111. panim = pAnimBlock( block, index );
  112. if (panim)
  113. {
  114. // set it to the last frame in the last valid section
  115. *piFrame = sectionframes - 1;
  116. break;
  117. }
  118. }
  119. }
  120. // try to guess a valid stall time interval (tuned for the X360)
  121. flStall = 0.0f;
  122. if (panim == NULL && section <= 0)
  123. {
  124. zeroframestalltime = Plat_FloatTime();
  125. flStall = 1.0f;
  126. }
  127. else if (panim != NULL && zeroframestalltime != 0.0f)
  128. {
  129. float dt = Plat_FloatTime() - zeroframestalltime;
  130. if (dt >= 0.0)
  131. {
  132. flStall = SimpleSpline( clamp( (0.200f - dt) * 5.0f, 0.0f, 1.0f ) );
  133. }
  134. if (flStall == 0.0f)
  135. {
  136. // disable stalltime
  137. zeroframestalltime = 0.0f;
  138. }
  139. else if (mod_load_showstall.GetInt() > 1)
  140. {
  141. Msg("[%8.3f] stall blend %.2f on %s:%s:%d:%d\n", Plat_FloatTime(), flStall, pStudiohdr()->pszName(), pszName(), section, block );
  142. }
  143. }
  144. if (panim == NULL && mod_load_showstall.GetInt() > 1)
  145. {
  146. Msg("[%8.3f] stall on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block );
  147. }
  148. return panim;
  149. }
  150. mstudioikrule_t *mstudioanimdesc_t::pIKRule( int i ) const
  151. {
  152. if (ikruleindex)
  153. {
  154. return (mstudioikrule_t *)(((byte *)this) + ikruleindex) + i;
  155. }
  156. else if (animblockikruleindex)
  157. {
  158. if (animblock == 0)
  159. {
  160. return (mstudioikrule_t *)(((byte *)this) + animblockikruleindex) + i;
  161. }
  162. else
  163. {
  164. byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock );
  165. if ( pAnimBlocks )
  166. {
  167. return (mstudioikrule_t *)(pAnimBlocks + animblockikruleindex) + i;
  168. }
  169. }
  170. }
  171. return NULL;
  172. }
  173. mstudiolocalhierarchy_t *mstudioanimdesc_t::pHierarchy( int i ) const
  174. {
  175. if (localhierarchyindex)
  176. {
  177. if (animblock == 0)
  178. {
  179. return (mstudiolocalhierarchy_t *)(((byte *)this) + localhierarchyindex) + i;
  180. }
  181. else
  182. {
  183. byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock );
  184. if ( pAnimBlocks )
  185. {
  186. return (mstudiolocalhierarchy_t *)(pAnimBlocks + localhierarchyindex) + i;
  187. }
  188. }
  189. }
  190. return NULL;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose:
  194. //-----------------------------------------------------------------------------
  195. bool studiohdr_t::SequencesAvailable() const
  196. {
  197. if (numincludemodels == 0)
  198. {
  199. return true;
  200. }
  201. return ( GetVirtualModel() != NULL );
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose:
  205. //-----------------------------------------------------------------------------
  206. int studiohdr_t::GetNumSeq( void ) const
  207. {
  208. if (numincludemodels == 0)
  209. {
  210. return numlocalseq;
  211. }
  212. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  213. Assert( pVModel );
  214. return pVModel->m_seq.Count();
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose:
  218. //-----------------------------------------------------------------------------
  219. mstudioseqdesc_t &studiohdr_t::pSeqdesc( int i ) const
  220. {
  221. if (numincludemodels == 0)
  222. {
  223. return *pLocalSeqdesc( i );
  224. }
  225. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  226. Assert( pVModel );
  227. if ( !pVModel )
  228. {
  229. return *pLocalSeqdesc( i );
  230. }
  231. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[i].group ];
  232. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  233. Assert( pStudioHdr );
  234. return *pStudioHdr->pLocalSeqdesc( pVModel->m_seq[i].index );
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Purpose:
  238. //-----------------------------------------------------------------------------
  239. int studiohdr_t::iRelativeAnim( int baseseq, int relanim ) const
  240. {
  241. if (numincludemodels == 0)
  242. {
  243. return relanim;
  244. }
  245. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  246. Assert( pVModel );
  247. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
  248. return pGroup->masterAnim[ relanim ];
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose:
  252. //-----------------------------------------------------------------------------
  253. int studiohdr_t::iRelativeSeq( int baseseq, int relseq ) const
  254. {
  255. if (numincludemodels == 0)
  256. {
  257. return relseq;
  258. }
  259. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  260. Assert( pVModel );
  261. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
  262. return pGroup->masterSeq[ relseq ];
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Purpose:
  266. //-----------------------------------------------------------------------------
  267. int studiohdr_t::GetNumPoseParameters( void ) const
  268. {
  269. if (numincludemodels == 0)
  270. {
  271. return numlocalposeparameters;
  272. }
  273. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  274. Assert( pVModel );
  275. return pVModel->m_pose.Count();
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Purpose:
  279. //-----------------------------------------------------------------------------
  280. const mstudioposeparamdesc_t &studiohdr_t::pPoseParameter( int i )
  281. {
  282. if (numincludemodels == 0)
  283. {
  284. return *pLocalPoseParameter( i );
  285. }
  286. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  287. Assert( pVModel );
  288. if ( pVModel->m_pose[i].group == 0)
  289. return *pLocalPoseParameter( pVModel->m_pose[i].index );
  290. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_pose[i].group ];
  291. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  292. Assert( pStudioHdr );
  293. return *pStudioHdr->pLocalPoseParameter( pVModel->m_pose[i].index );
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose:
  297. //-----------------------------------------------------------------------------
  298. int studiohdr_t::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
  299. {
  300. if (numincludemodels == 0)
  301. {
  302. return iLocalPose;
  303. }
  304. if (iLocalPose == -1)
  305. return iLocalPose;
  306. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  307. Assert( pVModel );
  308. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
  309. return pGroup->masterPose[iLocalPose];
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Purpose:
  313. //-----------------------------------------------------------------------------
  314. int studiohdr_t::EntryNode( int iSequence )
  315. {
  316. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  317. if (numincludemodels == 0 || seqdesc.localentrynode == 0)
  318. {
  319. return seqdesc.localentrynode;
  320. }
  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->masterNode[seqdesc.localentrynode-1]+1;
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose:
  328. //-----------------------------------------------------------------------------
  329. int studiohdr_t::ExitNode( int iSequence )
  330. {
  331. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  332. if (numincludemodels == 0 || seqdesc.localexitnode == 0)
  333. {
  334. return seqdesc.localexitnode;
  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.localexitnode-1]+1;
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Purpose:
  343. //-----------------------------------------------------------------------------
  344. int studiohdr_t::GetNumAttachments( void ) const
  345. {
  346. if (numincludemodels == 0)
  347. {
  348. return numlocalattachments;
  349. }
  350. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  351. Assert( pVModel );
  352. return pVModel->m_attachment.Count();
  353. }
  354. //-----------------------------------------------------------------------------
  355. // Purpose:
  356. //-----------------------------------------------------------------------------
  357. const mstudioattachment_t &studiohdr_t::pAttachment( int i ) const
  358. {
  359. if (numincludemodels == 0)
  360. {
  361. return *pLocalAttachment( i );
  362. }
  363. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  364. Assert( pVModel );
  365. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
  366. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  367. Assert( pStudioHdr );
  368. return *pStudioHdr->pLocalAttachment( pVModel->m_attachment[i].index );
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Purpose:
  372. //-----------------------------------------------------------------------------
  373. int studiohdr_t::GetAttachmentBone( int i )
  374. {
  375. const mstudioattachment_t &attachment = pAttachment( i );
  376. // remap bone
  377. virtualmodel_t *pVModel = GetVirtualModel();
  378. if (pVModel)
  379. {
  380. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
  381. int iBone = pGroup->masterBone[attachment.localbone];
  382. if (iBone == -1)
  383. return 0;
  384. return iBone;
  385. }
  386. return attachment.localbone;
  387. }
  388. //-----------------------------------------------------------------------------
  389. // Purpose:
  390. //-----------------------------------------------------------------------------
  391. void studiohdr_t::SetAttachmentBone( int iAttachment, int iBone )
  392. {
  393. mstudioattachment_t &attachment = (mstudioattachment_t &)pAttachment( iAttachment );
  394. // remap bone
  395. virtualmodel_t *pVModel = GetVirtualModel();
  396. if (pVModel)
  397. {
  398. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[iAttachment].group ];
  399. iBone = pGroup->boneMap[iBone];
  400. }
  401. attachment.localbone = iBone;
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Purpose:
  405. //-----------------------------------------------------------------------------
  406. char *studiohdr_t::pszNodeName( int iNode )
  407. {
  408. if (numincludemodels == 0)
  409. {
  410. return pszLocalNodeName( iNode );
  411. }
  412. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  413. Assert( pVModel );
  414. if ( pVModel->m_node.Count() <= iNode-1 )
  415. return "Invalid node";
  416. return pVModel->m_group[ pVModel->m_node[iNode-1].group ].GetStudioHdr()->pszLocalNodeName( pVModel->m_node[iNode-1].index );
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Purpose:
  420. //-----------------------------------------------------------------------------
  421. int studiohdr_t::GetTransition( int iFrom, int iTo ) const
  422. {
  423. if (numincludemodels == 0)
  424. {
  425. return *pLocalTransition( (iFrom-1)*numlocalnodes + (iTo - 1) );
  426. }
  427. return iTo;
  428. /*
  429. FIXME: not connected
  430. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  431. Assert( pVModel );
  432. return pVModel->m_transition.Element( iFrom ).Element( iTo );
  433. */
  434. }
  435. int studiohdr_t::GetActivityListVersion( void )
  436. {
  437. if (numincludemodels == 0)
  438. {
  439. return activitylistversion;
  440. }
  441. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  442. Assert( pVModel );
  443. int ActVersion = activitylistversion;
  444. int i;
  445. for (i = 1; i < pVModel->m_group.Count(); i++)
  446. {
  447. virtualgroup_t *pGroup = &pVModel->m_group[ i ];
  448. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  449. Assert( pStudioHdr );
  450. ActVersion = min( ActVersion, pStudioHdr->activitylistversion );
  451. }
  452. return ActVersion;
  453. }
  454. void studiohdr_t::SetActivityListVersion( int ActVersion ) const
  455. {
  456. activitylistversion = ActVersion;
  457. if (numincludemodels == 0)
  458. {
  459. return;
  460. }
  461. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  462. Assert( pVModel );
  463. int i;
  464. for (i = 1; i < pVModel->m_group.Count(); i++)
  465. {
  466. virtualgroup_t *pGroup = &pVModel->m_group[ i ];
  467. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  468. Assert( pStudioHdr );
  469. pStudioHdr->SetActivityListVersion( ActVersion );
  470. }
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose:
  474. //-----------------------------------------------------------------------------
  475. int studiohdr_t::GetNumIKAutoplayLocks( void ) const
  476. {
  477. if (numincludemodels == 0)
  478. {
  479. return numlocalikautoplaylocks;
  480. }
  481. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  482. Assert( pVModel );
  483. return pVModel->m_iklock.Count();
  484. }
  485. const mstudioiklock_t &studiohdr_t::pIKAutoplayLock( int i )
  486. {
  487. if (numincludemodels == 0)
  488. {
  489. return *pLocalIKAutoplayLock( i );
  490. }
  491. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  492. Assert( pVModel );
  493. virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_iklock[i].group ];
  494. const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
  495. Assert( pStudioHdr );
  496. return *pStudioHdr->pLocalIKAutoplayLock( pVModel->m_iklock[i].index );
  497. }
  498. int studiohdr_t::CountAutoplaySequences() const
  499. {
  500. int count = 0;
  501. for (int i = 0; i < GetNumSeq(); i++)
  502. {
  503. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  504. if (seqdesc.flags & STUDIO_AUTOPLAY)
  505. {
  506. count++;
  507. }
  508. }
  509. return count;
  510. }
  511. int studiohdr_t::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
  512. {
  513. int outIndex = 0;
  514. for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
  515. {
  516. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  517. if (seqdesc.flags & STUDIO_AUTOPLAY)
  518. {
  519. pOut[outIndex] = i;
  520. outIndex++;
  521. }
  522. }
  523. return outIndex;
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Purpose: maps local sequence bone to global bone
  527. //-----------------------------------------------------------------------------
  528. int studiohdr_t::RemapSeqBone( int iSequence, int iLocalBone ) const
  529. {
  530. // remap bone
  531. virtualmodel_t *pVModel = GetVirtualModel();
  532. if (pVModel)
  533. {
  534. const virtualgroup_t *pSeqGroup = pVModel->pSeqGroup( iSequence );
  535. return pSeqGroup->masterBone[iLocalBone];
  536. }
  537. return iLocalBone;
  538. }
  539. int studiohdr_t::RemapAnimBone( int iAnim, int iLocalBone ) const
  540. {
  541. // remap bone
  542. virtualmodel_t *pVModel = GetVirtualModel();
  543. if (pVModel)
  544. {
  545. const virtualgroup_t *pAnimGroup = pVModel->pAnimGroup( iAnim );
  546. return pAnimGroup->masterBone[iLocalBone];
  547. }
  548. return iLocalBone;
  549. }
  550. //-----------------------------------------------------------------------------
  551. // Purpose:
  552. //-----------------------------------------------------------------------------
  553. CStudioHdr::CStudioHdr( void )
  554. {
  555. // set pointer to bogus value
  556. m_nFrameUnlockCounter = 0;
  557. m_pFrameUnlockCounter = &m_nFrameUnlockCounter;
  558. Init( NULL );
  559. }
  560. CStudioHdr::CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache )
  561. {
  562. // preset pointer to bogus value (it may be overwritten with legitimate data later)
  563. m_nFrameUnlockCounter = 0;
  564. m_pFrameUnlockCounter = &m_nFrameUnlockCounter;
  565. Init( pStudioHdr, mdlcache );
  566. }
  567. // extern IDataCache *g_pDataCache;
  568. void CStudioHdr::Init( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache )
  569. {
  570. m_pStudioHdr = pStudioHdr;
  571. m_pVModel = NULL;
  572. m_pStudioHdrCache.RemoveAll();
  573. if (m_pStudioHdr == NULL)
  574. {
  575. return;
  576. }
  577. if ( mdlcache )
  578. {
  579. m_pFrameUnlockCounter = mdlcache->GetFrameUnlockCounterPtr( MDLCACHE_STUDIOHDR );
  580. m_nFrameUnlockCounter = *m_pFrameUnlockCounter - 1;
  581. }
  582. if (m_pStudioHdr->numincludemodels == 0)
  583. {
  584. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  585. #else
  586. m_ActivityToSequence.Initialize(this);
  587. #endif
  588. }
  589. else
  590. {
  591. ResetVModel( m_pStudioHdr->GetVirtualModel() );
  592. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  593. #else
  594. m_ActivityToSequence.Initialize(this);
  595. #endif
  596. }
  597. m_boneFlags.EnsureCount( numbones() );
  598. m_boneParent.EnsureCount( numbones() );
  599. for (int i = 0; i < numbones(); i++)
  600. {
  601. m_boneFlags[i] = pBone( i )->flags;
  602. m_boneParent[i] = pBone( i )->parent;
  603. }
  604. }
  605. void CStudioHdr::Term()
  606. {
  607. }
  608. //-----------------------------------------------------------------------------
  609. // Purpose:
  610. //-----------------------------------------------------------------------------
  611. bool CStudioHdr::SequencesAvailable() const
  612. {
  613. if (m_pStudioHdr->numincludemodels == 0)
  614. {
  615. return true;
  616. }
  617. if (m_pVModel == NULL)
  618. {
  619. // repoll m_pVModel
  620. return (ResetVModel( m_pStudioHdr->GetVirtualModel() ) != NULL);
  621. }
  622. else
  623. return true;
  624. }
  625. const virtualmodel_t * CStudioHdr::ResetVModel( const virtualmodel_t *pVModel ) const
  626. {
  627. if (pVModel != NULL)
  628. {
  629. m_pVModel = (virtualmodel_t *)pVModel;
  630. Assert( !pVModel->m_Lock.GetOwnerId() );
  631. m_pStudioHdrCache.SetCount( m_pVModel->m_group.Count() );
  632. int i;
  633. for (i = 0; i < m_pStudioHdrCache.Count(); i++)
  634. {
  635. m_pStudioHdrCache[ i ] = NULL;
  636. }
  637. return const_cast<virtualmodel_t *>(pVModel);
  638. }
  639. else
  640. {
  641. m_pVModel = NULL;
  642. return NULL;
  643. }
  644. }
  645. const studiohdr_t *CStudioHdr::GroupStudioHdr( int i )
  646. {
  647. if ( !this )
  648. {
  649. ExecuteNTimes( 5, Warning( "Call to NULL CStudioHdr::GroupStudioHdr()\n" ) );
  650. }
  651. if ( m_nFrameUnlockCounter != *m_pFrameUnlockCounter )
  652. {
  653. m_FrameUnlockCounterMutex.Lock();
  654. if ( *m_pFrameUnlockCounter != m_nFrameUnlockCounter ) // i.e., this thread got the mutex
  655. {
  656. memset( m_pStudioHdrCache.Base(), 0, m_pStudioHdrCache.Count() * sizeof(studiohdr_t *) );
  657. m_nFrameUnlockCounter = *m_pFrameUnlockCounter;
  658. }
  659. m_FrameUnlockCounterMutex.Unlock();
  660. }
  661. if ( !m_pStudioHdrCache.IsValidIndex( i ) )
  662. {
  663. const char *pszName = ( m_pStudioHdr ) ? m_pStudioHdr->pszName() : "<<null>>";
  664. ExecuteNTimes( 5, Warning( "Invalid index passed to CStudioHdr(%s)::GroupStudioHdr(): %d, but max is %d\n", pszName, i, m_pStudioHdrCache.Count() ) );
  665. DebuggerBreakIfDebugging();
  666. return m_pStudioHdr; // return something known to probably exist, certainly things will be messed up, but hopefully not crash before the warning is noticed
  667. }
  668. const studiohdr_t *pStudioHdr = m_pStudioHdrCache[ i ];
  669. if (pStudioHdr == NULL)
  670. {
  671. Assert( !m_pVModel->m_Lock.GetOwnerId() );
  672. virtualgroup_t *pGroup = &m_pVModel->m_group[ i ];
  673. pStudioHdr = pGroup->GetStudioHdr();
  674. m_pStudioHdrCache[ i ] = pStudioHdr;
  675. }
  676. Assert( pStudioHdr );
  677. return pStudioHdr;
  678. }
  679. const studiohdr_t *CStudioHdr::pSeqStudioHdr( int sequence )
  680. {
  681. if (m_pVModel == NULL)
  682. {
  683. return m_pStudioHdr;
  684. }
  685. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[sequence].group );
  686. return pStudioHdr;
  687. }
  688. const studiohdr_t *CStudioHdr::pAnimStudioHdr( int animation )
  689. {
  690. if (m_pVModel == NULL)
  691. {
  692. return m_pStudioHdr;
  693. }
  694. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[animation].group );
  695. return pStudioHdr;
  696. }
  697. mstudioanimdesc_t &CStudioHdr::pAnimdesc( int i )
  698. {
  699. if (m_pVModel == NULL)
  700. {
  701. return *m_pStudioHdr->pLocalAnimdesc( i );
  702. }
  703. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[i].group );
  704. return *pStudioHdr->pLocalAnimdesc( m_pVModel->m_anim[i].index );
  705. }
  706. //-----------------------------------------------------------------------------
  707. // Purpose:
  708. //-----------------------------------------------------------------------------
  709. int CStudioHdr::GetNumSeq( void ) const
  710. {
  711. if (m_pVModel == NULL)
  712. {
  713. return m_pStudioHdr->numlocalseq;
  714. }
  715. return m_pVModel->m_seq.Count();
  716. }
  717. //-----------------------------------------------------------------------------
  718. // Purpose:
  719. //-----------------------------------------------------------------------------
  720. mstudioseqdesc_t &CStudioHdr::pSeqdesc( int i )
  721. {
  722. Assert( ( i >= 0 && i < GetNumSeq() ) || ( i == 1 && GetNumSeq() <= 1 ) );
  723. if ( i < 0 || i >= GetNumSeq() )
  724. {
  725. if ( GetNumSeq() <= 0 )
  726. {
  727. // Return a zero'd out struct reference if we've got nothing.
  728. // C_BaseObject::StopAnimGeneratedSounds was crashing due to this function
  729. // returning a reference to garbage. It should now see numevents is 0,
  730. // and bail.
  731. static mstudioseqdesc_t s_nil_seq;
  732. return s_nil_seq;
  733. }
  734. // Avoid reading random memory.
  735. i = 0;
  736. }
  737. if (m_pVModel == NULL)
  738. {
  739. return *m_pStudioHdr->pLocalSeqdesc( i );
  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( int baseseq, int relanim ) const
  748. {
  749. if (m_pVModel == NULL)
  750. {
  751. return relanim;
  752. }
  753. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
  754. return pGroup->masterAnim[ relanim ];
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Purpose:
  758. //-----------------------------------------------------------------------------
  759. int CStudioHdr::iRelativeSeq( int baseseq, int relseq ) const
  760. {
  761. if (m_pVModel == NULL)
  762. {
  763. return relseq;
  764. }
  765. Assert( m_pVModel );
  766. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
  767. return pGroup->masterSeq[ relseq ];
  768. }
  769. //-----------------------------------------------------------------------------
  770. // Purpose:
  771. //-----------------------------------------------------------------------------
  772. int CStudioHdr::GetNumPoseParameters( void ) const
  773. {
  774. if (m_pVModel == NULL)
  775. {
  776. if ( m_pStudioHdr )
  777. return m_pStudioHdr->numlocalposeparameters;
  778. else
  779. return 0;
  780. }
  781. Assert( m_pVModel );
  782. return m_pVModel->m_pose.Count();
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Purpose:
  786. //-----------------------------------------------------------------------------
  787. const mstudioposeparamdesc_t &CStudioHdr::pPoseParameter( int i )
  788. {
  789. if (m_pVModel == NULL)
  790. {
  791. return *m_pStudioHdr->pLocalPoseParameter( i );
  792. }
  793. if ( m_pVModel->m_pose[i].group == 0)
  794. return *m_pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
  795. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_pose[i].group );
  796. return *pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
  797. }
  798. //-----------------------------------------------------------------------------
  799. // Purpose:
  800. //-----------------------------------------------------------------------------
  801. int CStudioHdr::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
  802. {
  803. if (m_pVModel == NULL)
  804. {
  805. return iLocalPose;
  806. }
  807. if (iLocalPose == -1)
  808. return iLocalPose;
  809. Assert( m_pVModel );
  810. int group = m_pVModel->m_seq[iSequence].group;
  811. virtualgroup_t *pGroup = m_pVModel->m_group.IsValidIndex( group ) ? &m_pVModel->m_group[ group ] : NULL;
  812. return pGroup ? pGroup->masterPose[iLocalPose] : iLocalPose;
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Purpose:
  816. //-----------------------------------------------------------------------------
  817. int CStudioHdr::EntryNode( int iSequence )
  818. {
  819. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  820. if (m_pVModel == NULL || seqdesc.localentrynode == 0)
  821. {
  822. return seqdesc.localentrynode;
  823. }
  824. Assert( m_pVModel );
  825. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
  826. return pGroup->masterNode[seqdesc.localentrynode-1]+1;
  827. }
  828. //-----------------------------------------------------------------------------
  829. // Purpose:
  830. //-----------------------------------------------------------------------------
  831. int CStudioHdr::ExitNode( int iSequence )
  832. {
  833. mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
  834. if (m_pVModel == NULL || seqdesc.localexitnode == 0)
  835. {
  836. return seqdesc.localexitnode;
  837. }
  838. Assert( m_pVModel );
  839. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
  840. return pGroup->masterNode[seqdesc.localexitnode-1]+1;
  841. }
  842. //-----------------------------------------------------------------------------
  843. // Purpose:
  844. //-----------------------------------------------------------------------------
  845. int CStudioHdr::GetNumAttachments( void ) const
  846. {
  847. if (m_pVModel == NULL)
  848. {
  849. return m_pStudioHdr->numlocalattachments;
  850. }
  851. Assert( m_pVModel );
  852. return m_pVModel->m_attachment.Count();
  853. }
  854. //-----------------------------------------------------------------------------
  855. // Purpose:
  856. //-----------------------------------------------------------------------------
  857. const mstudioattachment_t &CStudioHdr::pAttachment( int i )
  858. {
  859. if (m_pVModel == NULL)
  860. {
  861. return *m_pStudioHdr->pLocalAttachment( i );
  862. }
  863. Assert( m_pVModel );
  864. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_attachment[i].group );
  865. return *pStudioHdr->pLocalAttachment( m_pVModel->m_attachment[i].index );
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Purpose:
  869. //-----------------------------------------------------------------------------
  870. int CStudioHdr::GetAttachmentBone( int i )
  871. {
  872. if (m_pVModel == 0)
  873. {
  874. return m_pStudioHdr->pLocalAttachment( i )->localbone;
  875. }
  876. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[i].group ];
  877. const mstudioattachment_t &attachment = pAttachment( i );
  878. int iBone = pGroup->masterBone[attachment.localbone];
  879. if (iBone == -1)
  880. return 0;
  881. return iBone;
  882. }
  883. //-----------------------------------------------------------------------------
  884. // Purpose:
  885. //-----------------------------------------------------------------------------
  886. void CStudioHdr::SetAttachmentBone( int iAttachment, int iBone )
  887. {
  888. mstudioattachment_t &attachment = (mstudioattachment_t &)m_pStudioHdr->pAttachment( iAttachment );
  889. // remap bone
  890. if (m_pVModel)
  891. {
  892. virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[iAttachment].group ];
  893. iBone = pGroup->boneMap[iBone];
  894. }
  895. attachment.localbone = iBone;
  896. }
  897. //-----------------------------------------------------------------------------
  898. // Purpose:
  899. //-----------------------------------------------------------------------------
  900. char *CStudioHdr::pszNodeName( int iNode )
  901. {
  902. if (m_pVModel == NULL)
  903. {
  904. return m_pStudioHdr->pszLocalNodeName( iNode );
  905. }
  906. if ( m_pVModel->m_node.Count() <= iNode-1 )
  907. return "Invalid node";
  908. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_node[iNode-1].group );
  909. return pStudioHdr->pszLocalNodeName( m_pVModel->m_node[iNode-1].index );
  910. }
  911. //-----------------------------------------------------------------------------
  912. // Purpose:
  913. //-----------------------------------------------------------------------------
  914. int CStudioHdr::GetTransition( int iFrom, int iTo ) const
  915. {
  916. if (m_pVModel == NULL)
  917. {
  918. return *m_pStudioHdr->pLocalTransition( (iFrom-1)*m_pStudioHdr->numlocalnodes + (iTo - 1) );
  919. }
  920. return iTo;
  921. /*
  922. FIXME: not connected
  923. virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
  924. Assert( pVModel );
  925. return pVModel->m_transition.Element( iFrom ).Element( iTo );
  926. */
  927. }
  928. //-----------------------------------------------------------------------------
  929. // Purpose:
  930. //-----------------------------------------------------------------------------
  931. int CStudioHdr::GetActivityListVersion( void )
  932. {
  933. if (m_pVModel == NULL)
  934. {
  935. return m_pStudioHdr->activitylistversion;
  936. }
  937. int version = m_pStudioHdr->activitylistversion;
  938. int i;
  939. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  940. {
  941. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  942. Assert( pStudioHdr );
  943. version = min( version, pStudioHdr->activitylistversion );
  944. }
  945. return version;
  946. }
  947. void CStudioHdr::SetActivityListVersion( int version )
  948. {
  949. m_pStudioHdr->activitylistversion = version;
  950. if (m_pVModel == NULL)
  951. {
  952. return;
  953. }
  954. int i;
  955. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  956. {
  957. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  958. Assert( pStudioHdr );
  959. pStudioHdr->SetActivityListVersion( version );
  960. }
  961. }
  962. //-----------------------------------------------------------------------------
  963. // Purpose:
  964. //-----------------------------------------------------------------------------
  965. int CStudioHdr::GetEventListVersion( void )
  966. {
  967. if (m_pVModel == NULL)
  968. {
  969. return m_pStudioHdr->eventsindexed;
  970. }
  971. int version = m_pStudioHdr->eventsindexed;
  972. int i;
  973. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  974. {
  975. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  976. Assert( pStudioHdr );
  977. version = min( version, pStudioHdr->eventsindexed );
  978. }
  979. return version;
  980. }
  981. void CStudioHdr::SetEventListVersion( int version )
  982. {
  983. m_pStudioHdr->eventsindexed = version;
  984. if (m_pVModel == NULL)
  985. {
  986. return;
  987. }
  988. int i;
  989. for (i = 1; i < m_pVModel->m_group.Count(); i++)
  990. {
  991. const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
  992. Assert( pStudioHdr );
  993. pStudioHdr->eventsindexed = version;
  994. }
  995. }
  996. //-----------------------------------------------------------------------------
  997. // Purpose:
  998. //-----------------------------------------------------------------------------
  999. int CStudioHdr::GetNumIKAutoplayLocks( void ) const
  1000. {
  1001. if (m_pVModel == NULL)
  1002. {
  1003. return m_pStudioHdr->numlocalikautoplaylocks;
  1004. }
  1005. return m_pVModel->m_iklock.Count();
  1006. }
  1007. const mstudioiklock_t &CStudioHdr::pIKAutoplayLock( int i )
  1008. {
  1009. if (m_pVModel == NULL)
  1010. {
  1011. return *m_pStudioHdr->pLocalIKAutoplayLock( i );
  1012. }
  1013. const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_iklock[i].group );
  1014. Assert( pStudioHdr );
  1015. return *pStudioHdr->pLocalIKAutoplayLock( m_pVModel->m_iklock[i].index );
  1016. }
  1017. #if 0
  1018. int CStudioHdr::CountAutoplaySequences() const
  1019. {
  1020. int count = 0;
  1021. for (int i = 0; i < GetNumSeq(); i++)
  1022. {
  1023. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  1024. if (seqdesc.flags & STUDIO_AUTOPLAY)
  1025. {
  1026. count++;
  1027. }
  1028. }
  1029. return count;
  1030. }
  1031. int CStudioHdr::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
  1032. {
  1033. int outIndex = 0;
  1034. for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
  1035. {
  1036. mstudioseqdesc_t &seqdesc = pSeqdesc( i );
  1037. if (seqdesc.flags & STUDIO_AUTOPLAY)
  1038. {
  1039. pOut[outIndex] = i;
  1040. outIndex++;
  1041. }
  1042. }
  1043. return outIndex;
  1044. }
  1045. #endif
  1046. //-----------------------------------------------------------------------------
  1047. // Purpose: maps local sequence bone to global bone
  1048. //-----------------------------------------------------------------------------
  1049. int CStudioHdr::RemapSeqBone( int iSequence, int iLocalBone ) const
  1050. {
  1051. // remap bone
  1052. if (m_pVModel)
  1053. {
  1054. const virtualgroup_t *pSeqGroup = m_pVModel->pSeqGroup( iSequence );
  1055. return pSeqGroup->masterBone[iLocalBone];
  1056. }
  1057. return iLocalBone;
  1058. }
  1059. int CStudioHdr::RemapAnimBone( int iAnim, int iLocalBone ) const
  1060. {
  1061. // remap bone
  1062. if (m_pVModel)
  1063. {
  1064. const virtualgroup_t *pAnimGroup = m_pVModel->pAnimGroup( iAnim );
  1065. return pAnimGroup->masterBone[iLocalBone];
  1066. }
  1067. return iLocalBone;
  1068. }
  1069. // JasonM hack
  1070. //ConVar flex_maxrule( "flex_maxrule", "0" );
  1071. //-----------------------------------------------------------------------------
  1072. // Purpose: run the interpreted FAC's expressions, converting flex_controller
  1073. // values into FAC weights
  1074. //-----------------------------------------------------------------------------
  1075. void CStudioHdr::RunFlexRules( const float *src, float *dest )
  1076. {
  1077. // FIXME: this shouldn't be needed, flex without rules should be stripped in studiomdl
  1078. for (int i = 0; i < numflexdesc(); i++)
  1079. {
  1080. dest[i] = 0;
  1081. }
  1082. for (int i = 0; i < numflexrules(); i++)
  1083. {
  1084. float stack[32] = {};
  1085. int k = 0;
  1086. mstudioflexrule_t *prule = pFlexRule( i );
  1087. mstudioflexop_t *pops = prule->iFlexOp( 0 );
  1088. /*
  1089. // JasonM hack for flex perf testing...
  1090. int nFlexRulesToRun = 0; // 0 means run them all
  1091. const char *pszExpression = flex_maxrule.GetString();
  1092. if ( pszExpression )
  1093. {
  1094. nFlexRulesToRun = atoi(pszExpression); // 0 will be returned if not a numeric string
  1095. }
  1096. // end JasonM hack
  1097. //*/
  1098. // debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), i + 1, 0, "%2d:%d\n", i, prule->flex );
  1099. for (int j = 0; j < prule->numops; j++)
  1100. {
  1101. switch (pops->op)
  1102. {
  1103. case STUDIO_ADD: stack[k-2] = stack[k-2] + stack[k-1]; k--; break;
  1104. case STUDIO_SUB: stack[k-2] = stack[k-2] - stack[k-1]; k--; break;
  1105. case STUDIO_MUL: stack[k-2] = stack[k-2] * stack[k-1]; k--; break;
  1106. case STUDIO_DIV:
  1107. if (stack[k-1] > 0.0001)
  1108. {
  1109. stack[k-2] = stack[k-2] / stack[k-1];
  1110. }
  1111. else
  1112. {
  1113. stack[k-2] = 0;
  1114. }
  1115. k--;
  1116. break;
  1117. case STUDIO_NEG: stack[k-1] = -stack[k-1]; break;
  1118. case STUDIO_MAX: stack[k-2] = max( stack[k-2], stack[k-1] ); k--; break;
  1119. case STUDIO_MIN: stack[k-2] = min( stack[k-2], stack[k-1] ); k--; break;
  1120. case STUDIO_CONST: stack[k] = pops->d.value; k++; break;
  1121. case STUDIO_FETCH1:
  1122. {
  1123. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index)->localToGlobal;
  1124. stack[k] = src[m];
  1125. k++;
  1126. break;
  1127. }
  1128. case STUDIO_FETCH2:
  1129. {
  1130. stack[k] = dest[pops->d.index]; k++; break;
  1131. }
  1132. case STUDIO_COMBO:
  1133. {
  1134. int m = pops->d.index;
  1135. int km = k - m;
  1136. for ( int iStack = km + 1; iStack < k; ++iStack )
  1137. {
  1138. stack[ km ] *= stack[iStack];
  1139. }
  1140. k = k - m + 1;
  1141. }
  1142. break;
  1143. case STUDIO_DOMINATE:
  1144. {
  1145. int m = pops->d.index;
  1146. int km = k - m;
  1147. float dv = stack[ km ];
  1148. for ( int iStack = km + 1; iStack < k; ++iStack )
  1149. {
  1150. dv *= stack[iStack];
  1151. }
  1152. stack[ km - 1 ] *= 1.0f - dv;
  1153. k -= m;
  1154. }
  1155. break;
  1156. case STUDIO_2WAY_0:
  1157. {
  1158. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1159. stack[ k ] = RemapValClamped( src[m], -1.0f, 0.0f, 1.0f, 0.0f );
  1160. k++;
  1161. }
  1162. break;
  1163. case STUDIO_2WAY_1:
  1164. {
  1165. int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1166. stack[ k ] = RemapValClamped( src[m], 0.0f, 1.0f, 0.0f, 1.0f );
  1167. k++;
  1168. }
  1169. break;
  1170. case STUDIO_NWAY:
  1171. {
  1172. LocalFlexController_t valueControllerIndex = static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] );
  1173. int m = pFlexcontroller( valueControllerIndex )->localToGlobal;
  1174. float flValue = src[ m ];
  1175. int v = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal;
  1176. const Vector4D filterRamp( stack[ k - 5 ], stack[ k - 4 ], stack[ k - 3 ], stack[ k - 2 ] );
  1177. // Apply multicontrol remapping
  1178. if ( flValue <= filterRamp.x || flValue >= filterRamp.w )
  1179. {
  1180. flValue = 0.0f;
  1181. }
  1182. else if ( flValue < filterRamp.y )
  1183. {
  1184. flValue = RemapValClamped( flValue, filterRamp.x, filterRamp.y, 0.0f, 1.0f );
  1185. }
  1186. else if ( flValue > filterRamp.z )
  1187. {
  1188. flValue = RemapValClamped( flValue, filterRamp.z, filterRamp.w, 1.0f, 0.0f );
  1189. }
  1190. else
  1191. {
  1192. flValue = 1.0f;
  1193. }
  1194. stack[ k - 5 ] = flValue * src[ v ];
  1195. k -= 4;
  1196. }
  1197. break;
  1198. case STUDIO_DME_LOWER_EYELID:
  1199. {
  1200. const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1201. const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1202. const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) );
  1203. const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1204. int nBlinkIndex = static_cast< int >( stack[ k - 2 ] );
  1205. float flBlink = 0.0f;
  1206. if ( nBlinkIndex >= 0 )
  1207. {
  1208. const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) );
  1209. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1210. }
  1211. int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] );
  1212. float flEyeUpDown = 0.0f;
  1213. if ( nEyeUpDownIndex >= 0 )
  1214. {
  1215. const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) );
  1216. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1217. }
  1218. if ( flEyeUpDown > 0.0 )
  1219. {
  1220. stack [ k - 3 ] = ( 1.0f - flEyeUpDown ) * ( 1.0f - flCloseLidV ) * flCloseLid;
  1221. }
  1222. else
  1223. {
  1224. stack [ k - 3 ] = ( 1.0f - flCloseLidV ) * flCloseLid;
  1225. }
  1226. k -= 2;
  1227. }
  1228. break;
  1229. case STUDIO_DME_UPPER_EYELID:
  1230. {
  1231. const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index );
  1232. const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f );
  1233. const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) );
  1234. const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f );
  1235. int nBlinkIndex = static_cast< int >( stack[ k - 2 ] );
  1236. float flBlink = 0.0f;
  1237. if ( nBlinkIndex >= 0 )
  1238. {
  1239. const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) );
  1240. flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f );
  1241. }
  1242. int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] );
  1243. float flEyeUpDown = 0.0f;
  1244. if ( nEyeUpDownIndex >= 0 )
  1245. {
  1246. const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) );
  1247. flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f );
  1248. }
  1249. if ( flEyeUpDown < 0.0f )
  1250. {
  1251. stack [ k - 3 ] = ( 1.0f + flEyeUpDown ) * flCloseLidV * flCloseLid;
  1252. }
  1253. else
  1254. {
  1255. stack [ k - 3 ] = flCloseLidV * flCloseLid;
  1256. }
  1257. k -= 2;
  1258. }
  1259. break;
  1260. }
  1261. pops++;
  1262. }
  1263. dest[prule->flex] = stack[0];
  1264. /*
  1265. // JasonM hack
  1266. if ( nFlexRulesToRun == 0) // 0 means run all rules correctly
  1267. {
  1268. dest[prule->flex] = stack[0];
  1269. }
  1270. else // run only up to nFlexRulesToRun correctly...zero out the rest
  1271. {
  1272. if ( j < nFlexRulesToRun )
  1273. dest[prule->flex] = stack[0];
  1274. else
  1275. dest[prule->flex] = 0.0f;
  1276. }
  1277. dest[prule->flex] = 1.0f;
  1278. //*/
  1279. // end JasonM hack
  1280. }
  1281. }
  1282. //-----------------------------------------------------------------------------
  1283. // CODE PERTAINING TO ACTIVITY->SEQUENCE MAPPING SUBCLASS
  1284. //-----------------------------------------------------------------------------
  1285. #define iabs(i) (( (i) >= 0 ) ? (i) : -(i) )
  1286. CUtlSymbolTable g_ActivityModifiersTable;
  1287. extern void SetActivityForSequence( CStudioHdr *pstudiohdr, int i );
  1288. void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict pstudiohdr )
  1289. {
  1290. // Algorithm: walk through every sequence in the model, determine to which activity
  1291. // it corresponds, and keep a count of sequences per activity. Once the total count
  1292. // is available, allocate an array large enough to contain them all, update the
  1293. // starting indices for every activity's section in the array, and go back through,
  1294. // populating the array with its data.
  1295. AssertMsg1( m_pSequenceTuples == NULL, "Tried to double-initialize sequence mapping for %s", pstudiohdr->pszName() );
  1296. if ( m_pSequenceTuples != NULL )
  1297. return; // don't double initialize.
  1298. SetValidationPair(pstudiohdr);
  1299. if ( ! pstudiohdr->SequencesAvailable() )
  1300. return; // nothing to do.
  1301. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  1302. m_bIsInitialized = true;
  1303. #endif
  1304. // Some studio headers have no activities at all. In those
  1305. // cases we can avoid a lot of this effort.
  1306. bool bFoundOne = false;
  1307. // for each sequence in the header...
  1308. const int NumSeq = pstudiohdr->GetNumSeq();
  1309. for ( int i = 0 ; i < NumSeq ; ++i )
  1310. {
  1311. const mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  1312. #if defined(SERVER_DLL) || defined(CLIENT_DLL) || defined(GAME_DLL)
  1313. if (!(seqdesc.flags & STUDIO_ACTIVITY))
  1314. {
  1315. // AssertMsg2( false, "Sequence %d on studiohdr %s didn't have its activity initialized!", i, pstudiohdr->pszName() );
  1316. SetActivityForSequence( pstudiohdr, i );
  1317. }
  1318. #endif
  1319. // is there an activity associated with this sequence?
  1320. if (seqdesc.activity >= 0)
  1321. {
  1322. bFoundOne = true;
  1323. // look up if we already have an entry. First we need to make a speculative one --
  1324. HashValueType entry(seqdesc.activity, 0, 1, iabs(seqdesc.actweight));
  1325. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1326. if ( m_ActToSeqHash.IsValidHandle(handle) )
  1327. {
  1328. // we already have an entry and must update it by incrementing count
  1329. HashValueType * __restrict toUpdate = &m_ActToSeqHash.Element(handle);
  1330. toUpdate->count += 1;
  1331. toUpdate->totalWeight += iabs(seqdesc.actweight);
  1332. if ( !HushAsserts() )
  1333. {
  1334. AssertMsg( toUpdate->totalWeight > 0, "toUpdate->totalWeight: %d", toUpdate->totalWeight );
  1335. }
  1336. }
  1337. else
  1338. {
  1339. // we do not have an entry yet; create one.
  1340. m_ActToSeqHash.Insert(entry);
  1341. }
  1342. }
  1343. }
  1344. // if we found nothing, don't bother with any other initialization!
  1345. if (!bFoundOne)
  1346. return;
  1347. // Now, create starting indices for each activity. For an activity n,
  1348. // the starting index is of course the sum of counts [0..n-1].
  1349. int sequenceCount = 0;
  1350. int topActivity = 0; // this will store the highest seen activity number (used later to make an ad hoc map on the stack)
  1351. for ( UtlHashHandle_t handle = m_ActToSeqHash.GetFirstHandle() ;
  1352. m_ActToSeqHash.IsValidHandle(handle) ;
  1353. handle = m_ActToSeqHash.GetNextHandle(handle) )
  1354. {
  1355. HashValueType &element = m_ActToSeqHash[handle];
  1356. element.startingIdx = sequenceCount;
  1357. sequenceCount += element.count;
  1358. topActivity = max(topActivity, element.activityIdx);
  1359. }
  1360. // Allocate the actual array of sequence information. Note the use of restrict;
  1361. // this is an important optimization, but means that you must never refer to this
  1362. // array through m_pSequenceTuples in the scope of this function.
  1363. SequenceTuple * __restrict tupleList = new SequenceTuple[sequenceCount];
  1364. m_pSequenceTuples = tupleList; // save it off -- NEVER USE m_pSequenceTuples in this function!
  1365. m_iSequenceTuplesCount = sequenceCount;
  1366. // Now we're going to actually populate that list with the relevant data.
  1367. // First, create an array on the stack to store how many sequences we've written
  1368. // so far for each activity. (This is basically a very simple way of doing a map.)
  1369. // This stack may potentially grow very large; so if you have problems with it,
  1370. // go to a utlmap or similar structure.
  1371. unsigned int allocsize = (topActivity + 1) * sizeof(int);
  1372. #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression
  1373. allocsize = ALIGN_VALUE(allocsize,16);
  1374. int * __restrict seqsPerAct = static_cast<int *>(stackalloc(allocsize));
  1375. memset(seqsPerAct, 0, allocsize);
  1376. // okay, walk through all the sequences again, and write the relevant data into
  1377. // our little table.
  1378. for ( int i = 0 ; i < NumSeq ; ++i )
  1379. {
  1380. const mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  1381. if (seqdesc.activity >= 0)
  1382. {
  1383. const HashValueType &element = m_ActToSeqHash[m_ActToSeqHash.Find(HashValueType(seqdesc.activity, 0, 0, 0))];
  1384. // If this assert trips, we've written more sequences per activity than we allocated
  1385. // (therefore there must have been a miscount in the first for loop above).
  1386. int tupleOffset = seqsPerAct[seqdesc.activity];
  1387. Assert( tupleOffset < element.count );
  1388. if ( seqdesc.numactivitymodifiers > 0 )
  1389. {
  1390. // add entries for this model's activity modifiers
  1391. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = new CUtlSymbol[ seqdesc.numactivitymodifiers ];
  1392. (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = seqdesc.numactivitymodifiers;
  1393. for ( int k = 0; k < seqdesc.numactivitymodifiers; k++ )
  1394. {
  1395. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers[ k ] = g_ActivityModifiersTable.AddString( seqdesc.pActivityModifier( k )->pszName() );
  1396. }
  1397. }
  1398. else
  1399. {
  1400. (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = NULL;
  1401. (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = 0;
  1402. }
  1403. // You might be tempted to collapse this pointer math into a single pointer --
  1404. // don't! the tuple list is marked __restrict above.
  1405. (tupleList + element.startingIdx + tupleOffset)->seqnum = i; // store sequence number
  1406. (tupleList + element.startingIdx + tupleOffset)->weight = iabs(seqdesc.actweight);
  1407. // We can't have weights of 0
  1408. // Assert( (tupleList + element.startingIdx + tupleOffset)->weight > 0 );
  1409. if ( (tupleList + element.startingIdx + tupleOffset)->weight == 0 )
  1410. {
  1411. (tupleList + element.startingIdx + tupleOffset)->weight = 1;
  1412. }
  1413. seqsPerAct[seqdesc.activity] += 1;
  1414. }
  1415. }
  1416. #ifdef DBGFLAG_ASSERT
  1417. // double check that we wrote exactly the right number of sequences.
  1418. unsigned int chkSequenceCount = 0;
  1419. for (int j = 0 ; j <= topActivity ; ++j)
  1420. {
  1421. chkSequenceCount += seqsPerAct[j];
  1422. }
  1423. Assert(chkSequenceCount == m_iSequenceTuplesCount);
  1424. #endif
  1425. }
  1426. /// Force Initialize() to occur again, even if it has already occured.
  1427. void CStudioHdr::CActivityToSequenceMapping::Reinitialize( CStudioHdr *pstudiohdr )
  1428. {
  1429. m_bIsInitialized = false;
  1430. if (m_pSequenceTuples)
  1431. {
  1432. delete m_pSequenceTuples;
  1433. m_pSequenceTuples = NULL;
  1434. }
  1435. m_ActToSeqHash.RemoveAll();
  1436. Initialize(pstudiohdr);
  1437. }
  1438. // Look up relevant data for an activity's sequences. This isn't terribly efficient, due to the
  1439. // load-hit-store on the output parameters, so the most common case -- SelectWeightedSequence --
  1440. // is specially implemented.
  1441. const CStudioHdr::CActivityToSequenceMapping::SequenceTuple *CStudioHdr::CActivityToSequenceMapping::GetSequences( int forActivity, int * __restrict outSequenceCount, int * __restrict outTotalWeight )
  1442. {
  1443. // Construct a dummy entry so we can do a hash lookup (the UtlHash does not divorce keys from values)
  1444. HashValueType entry(forActivity, 0, 0, 0);
  1445. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1446. if (m_ActToSeqHash.IsValidHandle(handle))
  1447. {
  1448. const HashValueType &element = m_ActToSeqHash[handle];
  1449. const SequenceTuple *retval = m_pSequenceTuples + element.startingIdx;
  1450. *outSequenceCount = element.count;
  1451. *outTotalWeight = element.totalWeight;
  1452. return retval;
  1453. }
  1454. else
  1455. {
  1456. // invalid handle; return NULL.
  1457. // this is actually a legit use case, so no need to assert.
  1458. return NULL;
  1459. }
  1460. }
  1461. int CStudioHdr::CActivityToSequenceMapping::NumSequencesForActivity( int forActivity )
  1462. {
  1463. // If this trips, you've called this function on something that doesn't
  1464. // have activities.
  1465. //Assert(m_pSequenceTuples != NULL);
  1466. if ( m_pSequenceTuples == NULL )
  1467. return 0;
  1468. HashValueType entry(forActivity, 0, 0, 0);
  1469. UtlHashHandle_t handle = m_ActToSeqHash.Find(entry);
  1470. if (m_ActToSeqHash.IsValidHandle(handle))
  1471. {
  1472. return m_ActToSeqHash[handle].count;
  1473. }
  1474. else
  1475. {
  1476. return 0;
  1477. }
  1478. }
  1479. // double-check that the data I point to hasn't changed
  1480. bool CStudioHdr::CActivityToSequenceMapping::ValidateAgainst( const CStudioHdr * RESTRICT pstudiohdr ) RESTRICT
  1481. {
  1482. if (m_bIsInitialized)
  1483. {
  1484. return m_expectedPStudioHdr == pstudiohdr->GetRenderHdr() &&
  1485. m_expectedVModel == pstudiohdr->GetVirtualModel();
  1486. }
  1487. else
  1488. {
  1489. return true; // Allow an ordinary initialization to take place without printing a panicky assert.
  1490. }
  1491. }
  1492. void CStudioHdr::CActivityToSequenceMapping::SetValidationPair( const CStudioHdr *RESTRICT pstudiohdr ) RESTRICT
  1493. {
  1494. m_expectedPStudioHdr = pstudiohdr->GetRenderHdr();
  1495. m_expectedVModel = pstudiohdr->GetVirtualModel();
  1496. }