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.

986 lines
27 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Dme version of a game model (MDL)
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmegamemodel.h"
  7. #include "movieobjects_interfaces.h"
  8. #include "datamodel/dmelementfactoryhelper.h"
  9. #include "studio.h"
  10. #include "tier3/tier3.h"
  11. #include "tier1/fmtstr.h"
  12. #include "bone_setup.h"
  13. #include "movieobjects/dmeoverlay.h" // FIXME: Why do I have to explicitly include dmeoverlay.h here?
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. //-----------------------------------------------------------------------------
  17. // Expose this class to the scene database
  18. //-----------------------------------------------------------------------------
  19. IMPLEMENT_ELEMENT_FACTORY( DmeGlobalFlexControllerOperator, CDmeGlobalFlexControllerOperator );
  20. //-----------------------------------------------------------------------------
  21. // Purpose:
  22. //-----------------------------------------------------------------------------
  23. void CDmeGlobalFlexControllerOperator::OnConstruction()
  24. {
  25. m_flexWeight.Init( this, "flexWeight" );
  26. m_gameModel.Init( this, "gameModel", FATTRIB_HAS_CALLBACK | FATTRIB_NEVERCOPY );
  27. m_ToAttributeHandle = DMATTRIBUTE_HANDLE_INVALID;
  28. m_nFlexControllerIndex = -1;
  29. }
  30. void CDmeGlobalFlexControllerOperator::OnDestruction()
  31. {
  32. }
  33. void CDmeGlobalFlexControllerOperator::Resolve()
  34. {
  35. if ( m_nFlexControllerIndex < 0 )
  36. {
  37. m_nFlexControllerIndex = FindGlobalFlexControllerIndex();
  38. }
  39. if ( m_ToAttributeHandle == DMATTRIBUTE_HANDLE_INVALID )
  40. {
  41. SetupToAttribute();
  42. }
  43. }
  44. void CDmeGlobalFlexControllerOperator::OnAttributeChanged( CDmAttribute *pAttribute )
  45. {
  46. // Don't have the required interface...
  47. if ( !g_pGlobalFlexController )
  48. return;
  49. if ( pAttribute == m_gameModel.GetAttribute() && m_gameModel.GetElement() )
  50. {
  51. m_nFlexControllerIndex = FindGlobalFlexControllerIndex();
  52. SetupToAttribute();
  53. }
  54. }
  55. void CDmeGlobalFlexControllerOperator::Operate()
  56. {
  57. CDmAttribute *pToAttr = g_pDataModel->GetAttribute( m_ToAttributeHandle );
  58. if ( !pToAttr )
  59. return;
  60. DmAttributeType_t type = m_flexWeight.GetAttribute()->GetType();
  61. const void *pValue = m_flexWeight.GetAttribute()->GetValueUntyped();
  62. if ( IsArrayType( pToAttr->GetType() ) )
  63. {
  64. if ( m_nFlexControllerIndex == -1 )
  65. return;
  66. CDmrGenericArray array( pToAttr );
  67. array.Set( m_nFlexControllerIndex, type, pValue );
  68. }
  69. else
  70. {
  71. pToAttr->SetValue( type, pValue );
  72. }
  73. }
  74. void CDmeGlobalFlexControllerOperator::SetGameModel( CDmeGameModel *gameModel )
  75. {
  76. m_gameModel = gameModel;
  77. }
  78. void CDmeGlobalFlexControllerOperator::SetWeight( float flWeight )
  79. {
  80. m_flexWeight = flWeight;
  81. }
  82. void CDmeGlobalFlexControllerOperator::SetMapping( int globalIndex )
  83. {
  84. m_nFlexControllerIndex = globalIndex;
  85. if ( m_gameModel.GetElement() )
  86. {
  87. if ( (uint)globalIndex >= m_gameModel->NumFlexWeights() )
  88. {
  89. m_gameModel->SetNumFlexWeights( (uint)( globalIndex + 1 ) );
  90. }
  91. }
  92. }
  93. int CDmeGlobalFlexControllerOperator::GetGlobalIndex() const
  94. {
  95. return m_nFlexControllerIndex;
  96. }
  97. void CDmeGlobalFlexControllerOperator::GetInputAttributes ( CUtlVector< CDmAttribute * > &attrs )
  98. {
  99. attrs.AddToTail( m_flexWeight.GetAttribute() );
  100. }
  101. void CDmeGlobalFlexControllerOperator::GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs )
  102. {
  103. CDmAttribute *toAttribute = g_pDataModel->GetAttribute( m_ToAttributeHandle );
  104. if ( toAttribute )
  105. {
  106. attrs.AddToTail( toAttribute );
  107. }
  108. }
  109. void CDmeGlobalFlexControllerOperator::SetupToAttribute()
  110. {
  111. CDmElement *pObject = m_gameModel.GetElement();
  112. if ( pObject == NULL)
  113. return;
  114. CDmAttribute *pAttr = pObject->GetAttribute( "flexWeights" );
  115. Assert( pAttr );
  116. if ( !pAttr )
  117. return;
  118. m_ToAttributeHandle = pAttr->GetHandle();
  119. return;
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Connect up stuff by index
  123. //-----------------------------------------------------------------------------
  124. int CDmeGlobalFlexControllerOperator::FindGlobalFlexControllerIndex() const
  125. {
  126. int nGlobalFlexControllerIndex = -1;
  127. MDLHandle_t h = m_gameModel->GetModelHandle();
  128. if ( h != MDLHANDLE_INVALID )
  129. {
  130. studiohdr_t *hdr = g_pMDLCache->GetStudioHdr( h );
  131. Assert( hdr );
  132. if ( hdr )
  133. {
  134. int fc = hdr->numflexcontrollers;
  135. for ( LocalFlexController_t i = LocalFlexController_t(0) ; i < fc; ++i )
  136. {
  137. mstudioflexcontroller_t *flex = hdr->pFlexcontroller( i );
  138. if ( flex->localToGlobal == -1 && g_pGlobalFlexController )
  139. {
  140. flex->localToGlobal = g_pGlobalFlexController->FindGlobalFlexController( flex->pszName() );
  141. }
  142. if ( !Q_stricmp( flex->pszName(), GetName() ) )
  143. {
  144. nGlobalFlexControllerIndex = flex->localToGlobal;
  145. // Grow the array
  146. if ( (uint)flex->localToGlobal >= m_gameModel->NumFlexWeights() )
  147. {
  148. m_gameModel->SetNumFlexWeights( (uint)( flex->localToGlobal + 1 ) );
  149. }
  150. break;
  151. }
  152. }
  153. }
  154. }
  155. return nGlobalFlexControllerIndex;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Expose this class to the scene database
  159. //-----------------------------------------------------------------------------
  160. IMPLEMENT_ELEMENT_FACTORY( DmeGameModel, CDmeGameModel );
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. void CDmeGameModel::OnConstruction()
  165. {
  166. m_flexWeights.Init( this, "flexWeights" );
  167. m_modelName.Init( this, "modelName", FATTRIB_HAS_CALLBACK );
  168. m_skin.Init( this, "skin" );
  169. m_body.Init( this, "body" );
  170. m_sequence.Init( this, "sequence" );
  171. m_flags.Init( this, "flags" );
  172. m_bones.Init( this, "bones" );
  173. m_globalFlexControllers.Init( this, "globalFlexControllers" );
  174. m_bComputeBounds.Init( this, "computeBounds" );
  175. m_bEvaluateProceduralBones.InitAndSet( this, "evaluateProceduralBones", true );
  176. m_hMDL = MDLHANDLE_INVALID;
  177. m_bHMDLDirty = true;
  178. }
  179. void CDmeGameModel::OnDestruction()
  180. {
  181. if ( m_hMDL != MDLHANDLE_INVALID )
  182. {
  183. g_pMDLCache->Release( m_hMDL );
  184. m_hMDL = MDLHANDLE_INVALID;
  185. }
  186. }
  187. void CDmeGameModel::OnAttributeChanged( CDmAttribute *pAttribute )
  188. {
  189. if ( pAttribute == m_modelName.GetAttribute() )
  190. {
  191. m_bHMDLDirty = true;
  192. }
  193. }
  194. CDmeGlobalFlexControllerOperator *CDmeGameModel::AddGlobalFlexController( const char *controllerName, int globalIndex )
  195. {
  196. int i, c;
  197. c = m_globalFlexControllers.Count();
  198. for ( i = 0; i < c; ++i )
  199. {
  200. CDmeGlobalFlexControllerOperator *op = m_globalFlexControllers.Get( i );
  201. Assert( op );
  202. if ( op && !Q_stricmp( op->GetName(), controllerName ) )
  203. break;
  204. }
  205. if ( i >= c )
  206. {
  207. CDmeGlobalFlexControllerOperator *newOperator = CreateElement< CDmeGlobalFlexControllerOperator >( controllerName, GetFileId() );
  208. Assert( newOperator );
  209. if ( !newOperator )
  210. return NULL;
  211. i = m_globalFlexControllers.AddToTail( newOperator );
  212. }
  213. Assert( m_globalFlexControllers.IsValidIndex( i ) );
  214. CDmeGlobalFlexControllerOperator *op = m_globalFlexControllers.Get( i );
  215. Assert( op );
  216. if ( op )
  217. {
  218. op->SetMapping( globalIndex );
  219. op->SetGameModel( this );
  220. }
  221. if ( (uint)globalIndex >= NumFlexWeights() )
  222. {
  223. SetNumFlexWeights( globalIndex + 1 );
  224. }
  225. return op;
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Find a flex controller by its global index
  229. //-----------------------------------------------------------------------------
  230. CDmeGlobalFlexControllerOperator *CDmeGameModel::FindGlobalFlexController( int nGlobalIndex )
  231. {
  232. int i, c;
  233. c = m_globalFlexControllers.Count();
  234. for ( i = 0; i < c; ++i )
  235. {
  236. CDmeGlobalFlexControllerOperator *op = m_globalFlexControllers.Get( i );
  237. Assert( op );
  238. if ( op && op->GetGlobalIndex() == nGlobalIndex )
  239. return op;
  240. }
  241. return NULL;
  242. }
  243. studiohdr_t* CDmeGameModel::GetStudioHdr() const
  244. {
  245. const char *pModelName = GetModelName();
  246. MDLHandle_t h = pModelName && pModelName[0] ? g_pMDLCache->FindMDL( pModelName ) : MDLHANDLE_INVALID;
  247. return ( h != MDLHANDLE_INVALID ) ? g_pMDLCache->GetStudioHdr( h ) : NULL;
  248. }
  249. // A src bone transform transforms pre-compiled data (.dmx or .smd files, for example)
  250. // into post-compiled data (.mdl or .ani files)
  251. bool CDmeGameModel::GetSrcBoneTransforms( matrix3x4_t *pPreTransform, matrix3x4_t *pPostTransform, int nBoneIndex ) const
  252. {
  253. studiohdr_t *pStudioHdr = GetStudioHdr();
  254. if ( !pStudioHdr )
  255. return false;
  256. if ( pStudioHdr->numbones <= nBoneIndex )
  257. return false;
  258. const char *pBoneName = pStudioHdr->pBone( nBoneIndex )->pszName();
  259. int nCount = pStudioHdr->NumSrcBoneTransforms();
  260. for ( int i = 0; i < nCount; ++i )
  261. {
  262. const mstudiosrcbonetransform_t *pSrcTransform = pStudioHdr->SrcBoneTransform( i );
  263. if ( Q_stricmp( pSrcTransform->pszName(), pBoneName ) )
  264. continue;
  265. MatrixCopy( pSrcTransform->pretransform, *pPreTransform );
  266. MatrixCopy( pSrcTransform->posttransform, *pPostTransform );
  267. return true;
  268. }
  269. return false;
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Purpose: Get the default position of the specified bone.
  273. //-----------------------------------------------------------------------------
  274. bool CDmeGameModel::GetBoneDefaultPosition( int nBoneIndex, Vector &position ) const
  275. {
  276. studiohdr_t *pStudioHdr = GetStudioHdr();
  277. if ( !pStudioHdr )
  278. return false;
  279. if ( ( nBoneIndex < 0 ) || ( nBoneIndex >= pStudioHdr->numbones ) )
  280. return false;
  281. const mstudiobone_t *pBone = pStudioHdr->pBone( nBoneIndex );
  282. if ( pBone == NULL )
  283. return false;
  284. position = pBone->pos;
  285. return true;
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: Get the default orientation of the specified bone.
  289. //-----------------------------------------------------------------------------
  290. bool CDmeGameModel::GetBoneDefaultOrientation( int nBoneIndex, Quaternion &orientation ) const
  291. {
  292. studiohdr_t *pStudioHdr = GetStudioHdr();
  293. if ( !pStudioHdr )
  294. return false;
  295. if ( ( nBoneIndex < 0 ) || ( nBoneIndex >= pStudioHdr->numbones ) )
  296. return false;
  297. const mstudiobone_t *pBone = pStudioHdr->pBone( nBoneIndex );
  298. if ( pBone == NULL )
  299. return false;
  300. orientation = pBone->quat;
  301. return true;
  302. }
  303. bool CDmeGameModel::IsRootTransform( int nBoneIndex ) const
  304. {
  305. studiohdr_t *pStudioHdr = GetStudioHdr();
  306. if ( !pStudioHdr )
  307. return true;
  308. if ( pStudioHdr->numbones <= nBoneIndex )
  309. return true;
  310. const mstudiobone_t *pBone = pStudioHdr->pBone( nBoneIndex );
  311. return pBone->parent == -1;
  312. }
  313. int CDmeGameModel::NumGlobalFlexControllers() const
  314. {
  315. return m_globalFlexControllers.Count();
  316. }
  317. CDmeGlobalFlexControllerOperator *CDmeGameModel::GetGlobalFlexController( int localIndex )
  318. {
  319. return m_globalFlexControllers.Get( localIndex );
  320. }
  321. void CDmeGameModel::RemoveGlobalFlexController( CDmeGlobalFlexControllerOperator *controller )
  322. {
  323. int c = m_globalFlexControllers.Count();
  324. for ( int i = 0; i < c; ++i )
  325. {
  326. CDmeGlobalFlexControllerOperator *check = m_globalFlexControllers.Get( i );
  327. if ( check == controller )
  328. {
  329. m_globalFlexControllers.Remove( i );
  330. break;
  331. }
  332. }
  333. }
  334. void CDmeGameModel::AppendGlobalFlexControllerOperators( CUtlVector< IDmeOperator * >& list )
  335. {
  336. int c = m_globalFlexControllers.Count();
  337. for ( int i = 0 ; i < c; ++i )
  338. {
  339. CDmeOperator *op = m_globalFlexControllers.Get( i );
  340. if ( !op )
  341. continue;
  342. list.AddToTail( op );
  343. }
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Purpose: Find the dependencies of each flex controller on the other flex
  347. // controllers
  348. //-----------------------------------------------------------------------------
  349. void CDmeGameModel::FindFlexControllerDependencies( CUtlVector< CUtlVector< int > > &dependencyList ) const
  350. {
  351. studiohdr_t *hdr = GetStudioHdr();
  352. if ( hdr == NULL )
  353. return;
  354. // Build a table to reference the controller operators by the
  355. // global index of the flex control they are associated with.
  356. int controllerTable[ MAXSTUDIOFLEXDESC ];
  357. memset( controllerTable, -1, sizeof( controllerTable ) );
  358. int nControllers = m_globalFlexControllers.Count();
  359. if ( nControllers > MAXSTUDIOFLEXDESC )
  360. {
  361. Assert( nControllers < MAXSTUDIOFLEXDESC );
  362. return;
  363. }
  364. for ( int iCtrl = 0; iCtrl < nControllers; ++iCtrl )
  365. {
  366. CDmeGlobalFlexControllerOperator *pCtrlOp = m_globalFlexControllers[ iCtrl ];
  367. if ( pCtrlOp )
  368. {
  369. int globalIndex = pCtrlOp->GetGlobalIndex();
  370. if ( ( globalIndex < MAXSTUDIOFLEXDESC ) && ( globalIndex >= 0 ) )
  371. {
  372. controllerTable[ globalIndex ] = iCtrl;
  373. }
  374. }
  375. }
  376. // Determine which rules each of the controllers contribute to
  377. CStudioHdr studioHdr( hdr );
  378. CUtlVector< int > controllerRuleTable[ MAXSTUDIOFLEXDESC ]; // Table of rules each controller contributes to
  379. CUtlVector< int > ruleDepTable[ MAXSTUDIOFLEXDESC ]; // Table of controllers contributing to each rule
  380. int nFlexRules = studioHdr.numflexrules();
  381. for ( int iRule = 0; iRule < nFlexRules; ++iRule )
  382. {
  383. mstudioflexrule_t *pRule = studioHdr.pFlexRule( iRule );
  384. if ( pRule == NULL )
  385. return;
  386. for ( int iOp = 0; iOp < pRule->numops; ++iOp )
  387. {
  388. mstudioflexop_t *pOp = pRule->iFlexOp( iOp );
  389. switch ( pOp->op )
  390. {
  391. case STUDIO_FETCH1:
  392. case STUDIO_2WAY_0:
  393. case STUDIO_2WAY_1:
  394. case STUDIO_NWAY:
  395. case STUDIO_DME_LOWER_EYELID:
  396. case STUDIO_DME_UPPER_EYELID:
  397. {
  398. int globalIndex = studioHdr.pFlexcontroller( (LocalFlexController_t)pOp->d.index )->localToGlobal;
  399. if ( ( globalIndex < MAXSTUDIOFLEXDESC ) && ( pRule->flex < MAXSTUDIOFLEXDESC ) && ( globalIndex >= 0 ) )
  400. {
  401. int controllerIndex = controllerTable[ globalIndex ];
  402. if ( controllerIndex >= 0 )
  403. {
  404. if ( controllerRuleTable[ controllerIndex ].Find( pRule->flex ) == CUtlVector< int >::InvalidIndex() )
  405. {
  406. controllerRuleTable[ controllerIndex ].AddToTail( pRule->flex );
  407. ruleDepTable[ pRule->flex ].AddToTail( controllerIndex );
  408. }
  409. }
  410. }
  411. }
  412. break;
  413. default:
  414. break;
  415. }
  416. }
  417. }
  418. // For each controller, find the other controllers that contribute to the same rules.
  419. bool dependencyTable[ MAXSTUDIOFLEXDESC ];
  420. memset( dependencyTable, 0, sizeof( dependencyTable ) );
  421. for ( int iCtrl = 0; iCtrl < nControllers; ++iCtrl )
  422. {
  423. memset( dependencyTable, 0, sizeof( bool ) * nControllers );
  424. // Get the list of rules that controller contributes to
  425. CUtlVector< int > &ruleList = controllerRuleTable[ iCtrl ];
  426. int nRules = ruleList.Count();
  427. int nDependencies = 0;
  428. for ( int iRule = 0; iRule < nRules; ++iRule )
  429. {
  430. int ruleIndex = ruleList[ iRule ];
  431. CUtlVector< int > &ruleControllerList = ruleDepTable[ ruleIndex ];
  432. int nRuleDep = ruleControllerList.Count();
  433. for ( int iDep = 0; iDep < nRuleDep; ++iDep )
  434. {
  435. int controllerIndex = ruleControllerList[ iDep ];
  436. if ( ( controllerIndex != iCtrl ) && ( dependencyTable[ controllerIndex ] == false ) )
  437. {
  438. dependencyTable[ controllerIndex ] = true;
  439. ++nDependencies;
  440. }
  441. }
  442. }
  443. if ( nDependencies > 0 )
  444. {
  445. dependencyList.AddToTail();
  446. CUtlVector< int > &dependencies = dependencyList.Tail();
  447. dependencies.EnsureCapacity( nDependencies + 1 );
  448. dependencies.AddToTail( iCtrl );
  449. for ( int iDepCtrl = 0; iDepCtrl < nControllers; ++iDepCtrl )
  450. {
  451. if ( dependencyTable[ iDepCtrl ] == true )
  452. {
  453. dependencies.AddToTail( iDepCtrl );
  454. --nDependencies;
  455. }
  456. }
  457. Assert( nDependencies == 0 );
  458. }
  459. }
  460. }
  461. //-----------------------------------------------------------------------------
  462. // accessors
  463. //-----------------------------------------------------------------------------
  464. void CDmeGameModel::AddBone( CDmeTransform* pTransform )
  465. {
  466. m_bones.AddToTail( pTransform );
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Is this dag under the game model?
  470. //-----------------------------------------------------------------------------
  471. static bool IsDagUnderGameModel( CDmeDag *pDag, CDmeGameModel *pGameModel )
  472. {
  473. if ( pDag == pGameModel )
  474. return true;
  475. DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pDag->GetHandle() );
  476. while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
  477. {
  478. CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
  479. CDmElement *pDmeParent = pAttribute->GetOwner();
  480. const static CUtlSymbolLarge symChildren = g_pDataModel->GetSymbol( "children" );
  481. if ( pDmeParent && pAttribute->GetNameSymbol() == symChildren )
  482. {
  483. CDmeDag *pParent = CastElement< CDmeDag >( pDmeParent );
  484. if ( pParent && ( pParent->GetFileId() == pDag->GetFileId() ) )
  485. {
  486. if ( IsDagUnderGameModel( pParent, pGameModel ) )
  487. return true;
  488. }
  489. }
  490. i = g_pDataModel->NextAttributeReferencingElement( i );
  491. }
  492. return false;
  493. }
  494. //-----------------------------------------------------------------------------
  495. // Finds existing dags
  496. //-----------------------------------------------------------------------------
  497. void CDmeGameModel::PopulateExistingDagList( CDmeDag** pDags, int nCount )
  498. {
  499. int nCurrentBoneCount = m_bones.Count();
  500. for ( int i = 0; i < nCount; ++i )
  501. {
  502. if ( i >= nCurrentBoneCount )
  503. {
  504. pDags[ i ] = NULL;
  505. continue;
  506. }
  507. CDmeTransform *pTransform = GetBone( i );
  508. Assert( pTransform );
  509. pDags[ i ] = pTransform ? pTransform->GetDag() : NULL;
  510. }
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Adds bones to the game model
  514. //-----------------------------------------------------------------------------
  515. void CDmeGameModel::AddBones( studiohdr_t *pStudioHdr, int nFirstBone, int nCount )
  516. {
  517. if ( nFirstBone + nCount > pStudioHdr->numbones )
  518. {
  519. nCount = pStudioHdr->numbones - nFirstBone;
  520. if ( nCount <= 0 )
  521. return;
  522. }
  523. // make room for bones
  524. CDmeDag** pDags = ( CDmeDag** )_alloca( pStudioHdr->numbones * sizeof(CDmeDag*) );
  525. int nDagCount = nFirstBone;
  526. PopulateExistingDagList( pDags, nFirstBone );
  527. char name[ 256 ];
  528. for ( int i = 0; i < nCount; ++i )
  529. {
  530. int bi = i + nFirstBone;
  531. // get parent
  532. const mstudiobone_t *pBone = pStudioHdr->pBone( bi );
  533. int parentIndex = pBone->parent;
  534. Assert( parentIndex < nDagCount );
  535. // build dag hierarchy to match bone hierarchy
  536. CDmeDag *pParent = ( parentIndex < 0 ) ? this : pDags[ parentIndex ];
  537. Q_snprintf( name, sizeof( name ), "bone %d (%s)", bi, pBone->pszName() );
  538. CDmeDag *pDag = CreateElement< CDmeDag >( name, GetFileId() );
  539. pDags[nDagCount++] = pDag;
  540. pParent->AddChild( pDag );
  541. CDmeTransform *pTransform = pDag->GetTransform();
  542. pTransform->SetName( name );
  543. // add different bone representations to dme model and input
  544. AddBone( pTransform );
  545. }
  546. }
  547. void CDmeGameModel::SetBone( uint index, const Vector& pos, const Quaternion& rot )
  548. {
  549. m_bones[ index ]->SetPosition( pos );
  550. m_bones[ index ]->SetOrientation( rot );
  551. }
  552. void CDmeGameModel::RemoveAllBones()
  553. {
  554. m_bones.RemoveAll();
  555. }
  556. uint CDmeGameModel::NumBones() const
  557. {
  558. return m_bones.Count();
  559. }
  560. CDmeTransform *CDmeGameModel::GetBone( uint index ) const
  561. {
  562. return m_bones[ index ];
  563. }
  564. int CDmeGameModel::FindBone( CDmeTransform *pTransform ) const
  565. {
  566. return m_bones.Find( pTransform );
  567. }
  568. uint CDmeGameModel::NumFlexWeights() const
  569. {
  570. return m_flexWeights.Count();
  571. }
  572. const CUtlVector< float >& CDmeGameModel::GetFlexWeights() const
  573. {
  574. return m_flexWeights.Get();
  575. }
  576. void CDmeGameModel::SetNumFlexWeights( uint nFlexWeights )
  577. {
  578. if ( nFlexWeights > (uint)m_flexWeights.Count() )
  579. {
  580. while ( (uint)m_flexWeights.Count() < nFlexWeights )
  581. {
  582. m_flexWeights.AddToTail( 0.0f );
  583. }
  584. }
  585. else
  586. {
  587. while ( (uint)m_flexWeights.Count() > nFlexWeights )
  588. {
  589. m_flexWeights.Remove( (uint)m_flexWeights.Count() - 1 );
  590. }
  591. }
  592. }
  593. void CDmeGameModel::SetFlexWeights( uint nFlexWeights, const float* flexWeights )
  594. {
  595. m_flexWeights.CopyArray( flexWeights, nFlexWeights );
  596. }
  597. void CDmeGameModel::SetFlags( int nFlags )
  598. {
  599. m_flags = nFlags;
  600. }
  601. void CDmeGameModel::SetSkin( int nSkin )
  602. {
  603. m_skin = nSkin;
  604. }
  605. void CDmeGameModel::SetBody( int nBody )
  606. {
  607. m_body = nBody;
  608. }
  609. void CDmeGameModel::SetSequence( int nSequence )
  610. {
  611. m_sequence = nSequence;
  612. }
  613. int CDmeGameModel::GetSkin() const
  614. {
  615. return m_skin;
  616. }
  617. int CDmeGameModel::GetBody() const
  618. {
  619. return m_body;
  620. }
  621. int CDmeGameModel::GetSequence() const
  622. {
  623. return m_sequence;
  624. }
  625. int CDmeGameModel::GetFlags() const
  626. {
  627. return m_flags;
  628. }
  629. const char *CDmeGameModel::GetModelName() const
  630. {
  631. return m_modelName.Get();
  632. }
  633. MDLHandle_t CDmeGameModel::GetModelHandle()
  634. {
  635. if ( m_bHMDLDirty )
  636. {
  637. UpdateHMDL();
  638. }
  639. return m_hMDL;
  640. }
  641. void CDmeGameModel::UpdateHMDL()
  642. {
  643. // Yes, we're intentionally referencing before we unref
  644. MDLHandle_t h = MDLHANDLE_INVALID;
  645. const char *pModelName = m_modelName.Get();
  646. if ( pModelName && *pModelName )
  647. {
  648. h = g_pMDLCache->FindMDL( pModelName );
  649. }
  650. if ( m_hMDL != MDLHANDLE_INVALID )
  651. {
  652. g_pMDLCache->Release( m_hMDL );
  653. }
  654. m_hMDL = h;
  655. m_bHMDLDirty = false;
  656. }
  657. int CDmeGameModel::FindAttachment( const char *pchAttachmentName ) const
  658. {
  659. if ( studiohdr_t *pStudioHdr = GetStudioHdr() )
  660. {
  661. CStudioHdr studioHdr( pStudioHdr );
  662. return Studio_FindAttachment( &studioHdr, pchAttachmentName ) + 1;
  663. }
  664. return 0;
  665. }
  666. //-----------------------------------------------------------------------------
  667. // Compute the world space position of the specified attachment.
  668. //-----------------------------------------------------------------------------
  669. Vector CDmeGameModel::ComputeAttachmentPosition( const char *pchAttachmentName ) const
  670. {
  671. studiohdr_t *pStudioHdr = GetStudioHdr();
  672. if ( pStudioHdr == NULL )
  673. return vec3_origin;
  674. // Find the index of the attachment by its name and verify
  675. // that the attachment was found and that the index is valid.
  676. CStudioHdr studioHdr( pStudioHdr );
  677. int attachmentIndex = Studio_FindAttachment( &studioHdr, pchAttachmentName );
  678. if ( ( attachmentIndex < 0 ) || ( attachmentIndex > studioHdr.GetNumAttachments() ) )
  679. return vec3_origin;
  680. // Get the bone to which in attachment position is defined
  681. // and then find the dag node using the bone transform.
  682. int boneIndex = studioHdr.GetAttachmentBone( attachmentIndex );
  683. CDmeTransform *pBoneTranform = GetBone( boneIndex );
  684. CDmeDag *pBoneDag = pBoneTranform->GetDag();
  685. if ( pBoneDag == NULL )
  686. return vec3_origin;
  687. // Get the local offset position of the attachment and then transform
  688. // it into world space using the transform of the associated dag node.
  689. const mstudioattachment_t &attachment = studioHdr.pAttachment( attachmentIndex );
  690. matrix3x4_t wsTransform;
  691. Vector localPosition;
  692. Vector worldPosition;
  693. pBoneDag->GetAbsTransform( wsTransform );
  694. MatrixPosition( attachment.local, localPosition );
  695. VectorTransform( localPosition, wsTransform, worldPosition );
  696. return worldPosition;
  697. }
  698. //-----------------------------------------------------------------------------
  699. // Create a dag node for the specified attachment and make it a child of the
  700. // the bone it is local to.
  701. //-----------------------------------------------------------------------------
  702. CDmeDag *CDmeGameModel::CreateDagForAttachment( const char *pchAttachmentName ) const
  703. {
  704. studiohdr_t *pStudioHdr = GetStudioHdr();
  705. if ( pStudioHdr == NULL )
  706. return NULL;
  707. // Find the index of the attachment by its name and verify
  708. // that the attachment was found and that the index is valid.
  709. CStudioHdr studioHdr( pStudioHdr );
  710. int attachmentIndex = Studio_FindAttachment( &studioHdr, pchAttachmentName );
  711. if ( ( attachmentIndex < 0 ) || ( attachmentIndex > studioHdr.GetNumAttachments() ) )
  712. return NULL;
  713. // Get the bone in which the attachment position is defined
  714. // and then find the dag node using the bone transform.
  715. int boneIndex = studioHdr.GetAttachmentBone( attachmentIndex );
  716. CDmeTransform *pBoneTranform = GetBone( boneIndex );
  717. CDmeDag *pBoneDag = pBoneTranform->GetDag();
  718. if ( pBoneDag == NULL )
  719. return NULL;
  720. CDmeDag *pDagNode = CreateElement< CDmeDag >( CFmtStr( "attach_%s", pchAttachmentName ), GetFileId() );
  721. if ( pDagNode )
  722. {
  723. // Position the node based on the attachment position
  724. const mstudioattachment_t &attachment = studioHdr.pAttachment( attachmentIndex );
  725. CDmeTransform *pTransform = pDagNode->GetTransform();
  726. if ( pTransform )
  727. {
  728. Vector vAttachmentPos;
  729. MatrixPosition( attachment.local, vAttachmentPos );
  730. pTransform->SetPosition( vAttachmentPos );
  731. }
  732. // Make the attachment dag node a child of bone it is associated with
  733. pBoneDag->AddChild( pDagNode );
  734. }
  735. return pDagNode;
  736. }
  737. //-----------------------------------------------------------------------------
  738. // Expose this class to the scene database
  739. //-----------------------------------------------------------------------------
  740. IMPLEMENT_ELEMENT_FACTORY( DmeGameSprite, CDmeGameSprite );
  741. //-----------------------------------------------------------------------------
  742. // Purpose:
  743. //-----------------------------------------------------------------------------
  744. void CDmeGameSprite::OnConstruction()
  745. {
  746. m_modelName .Init( this, "modelName" );
  747. m_frame .Init( this, "frame" );
  748. m_rendermode.Init( this, "rendermode" );
  749. m_renderfx .Init( this, "renderfx" );
  750. m_renderscale.Init( this, "renderscale" );
  751. m_color .Init( this, "color" );
  752. m_proxyRadius.Init( this, "proxyRadius" );
  753. }
  754. void CDmeGameSprite::OnDestruction()
  755. {
  756. }
  757. //-----------------------------------------------------------------------------
  758. // accessors
  759. //-----------------------------------------------------------------------------
  760. const char *CDmeGameSprite::GetModelName() const
  761. {
  762. return m_modelName.Get();
  763. }
  764. float CDmeGameSprite::GetScale() const
  765. {
  766. return m_renderscale;
  767. }
  768. float CDmeGameSprite::GetFrame() const
  769. {
  770. return m_frame;
  771. }
  772. int CDmeGameSprite::GetRenderMode() const
  773. {
  774. return m_rendermode;
  775. }
  776. int CDmeGameSprite::GetRenderFX() const
  777. {
  778. return m_renderfx;
  779. }
  780. const Color &CDmeGameSprite::GetColor() const
  781. {
  782. return m_color;
  783. }
  784. float CDmeGameSprite::GetProxyRadius() const
  785. {
  786. return m_proxyRadius;
  787. }
  788. void CDmeGameSprite::SetState( bool bVisible, float nFrame, int nRenderMode, int nRenderFX, float flRenderScale, float flProxyRadius,
  789. const Vector &pos, const Quaternion &rot, const Color &color )
  790. {
  791. m_Visible = bVisible;
  792. m_frame = nFrame;
  793. m_rendermode = nRenderMode;
  794. m_renderfx = nRenderFX;
  795. m_renderscale = flRenderScale;
  796. m_proxyRadius = flProxyRadius;
  797. m_color = color;
  798. CDmeTransform *pTransform = GetTransform();
  799. pTransform->SetPosition( pos );
  800. pTransform->SetOrientation( rot );
  801. }
  802. //-----------------------------------------------------------------------------
  803. // Expose this class to the scene database
  804. //-----------------------------------------------------------------------------
  805. IMPLEMENT_ELEMENT_FACTORY( DmeGamePortal, CDmeGamePortal );
  806. //-----------------------------------------------------------------------------
  807. // Purpose:
  808. //-----------------------------------------------------------------------------
  809. void CDmeGamePortal::OnConstruction()
  810. {
  811. m_flStaticAmount .Init( this, "staticAmount" );
  812. m_flSecondaryStaticAmount .Init( this, "secondaryStaticAmount" );
  813. m_flOpenAmount .Init( this, "openAmount" );
  814. m_flHalfWidth .Init( this, "halfWidth" );
  815. m_flHalfHeight .Init( this, "halfHeight" );
  816. m_nPortalId .Init( this, "portalId" );
  817. m_nLinkedPortalId .Init( this, "linkedPortalId" );
  818. m_bIsPortal2 .Init( this, "isPortal2" );
  819. m_PortalType .Init( this, "portalType" );
  820. }
  821. void CDmeGamePortal::OnDestruction()
  822. {
  823. }