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.

1156 lines
39 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "matsys_controls/sequencepicker.h"
  7. #include "tier1/utldict.h"
  8. #include "tier1/keyvalues.h"
  9. #include "studio.h"
  10. #include "bone_setup.h"
  11. #include "vgui/IInput.h"
  12. #include "vgui/ISurface.h"
  13. #include "vgui_controls/Splitter.h"
  14. #include "vgui_controls/PropertyPage.h"
  15. #include "vgui_controls/PropertySheet.h"
  16. #include "vgui_controls/ListPanel.h"
  17. #include "vgui_controls/Button.h"
  18. #include "vgui_controls/Slider.h"
  19. #include "vgui_controls/TextEntry.h"
  20. #include "vgui_controls/ComboBox.h"
  21. #include "vgui_controls/CheckButton.h"
  22. #include "matsys_controls/matsyscontrols.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. using namespace vgui;
  26. //-----------------------------------------------------------------------------
  27. //
  28. // Sequence Picker
  29. //
  30. //-----------------------------------------------------------------------------
  31. static const int POSE_PARAMETER_SLIDER_RANGE = 100;
  32. static const int LAYER_WEIGHT_SLIDER_RANGE = 100;
  33. //-----------------------------------------------------------------------------
  34. // Sort by sequence name
  35. //-----------------------------------------------------------------------------
  36. static int __cdecl SequenceSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  37. {
  38. const char *string1 = item1.kv->GetString("sequence");
  39. const char *string2 = item2.kv->GetString("sequence");
  40. return stricmp( string1, string2 );
  41. }
  42. static int __cdecl ActivitySortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  43. {
  44. const char *string1 = item1.kv->GetString("activity");
  45. const char *string2 = item2.kv->GetString("activity");
  46. return stricmp( string1, string2 );
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose: Constructor
  50. //-----------------------------------------------------------------------------
  51. CSequencePicker::CSequencePicker( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePicker" )
  52. {
  53. int nAdvSequenceFlags = PICK_SEQUENCES | PICK_SEQUENCE_PARAMETERS;
  54. m_bSequenceParams = ( ( nFlags & nAdvSequenceFlags ) == nAdvSequenceFlags );
  55. m_hSelectedMDL = MDLHANDLE_INVALID;
  56. m_pRootMotionCheckBox = NULL;
  57. m_pPoseDefaultButton = NULL;
  58. V_memset( m_pLayerSequenceSelectors, 0, sizeof( m_pLayerSequenceSelectors ) );
  59. V_memset( m_pLayerSequenceSliders, 0, sizeof( m_pLayerSequenceSliders ) );
  60. V_memset( m_pPoseValueSliders, 0, sizeof( m_pPoseValueSliders ) );
  61. V_memset( m_pPoseValueEntries, 0, sizeof( m_pPoseValueEntries ) );
  62. V_memset( m_pPoseParameterName, 0, sizeof( m_pPoseParameterName ) );
  63. V_memset( m_SequenceLayers, 0, sizeof( m_SequenceLayers) );
  64. V_memset( m_PoseControlMap, -1, sizeof( m_PoseControlMap) );
  65. V_memset( m_PoseParameters, 0, sizeof( m_PoseParameters ) );
  66. // property sheet - revisions, changes, etc.
  67. m_pPreviewSplitter = new Splitter( this, "PreviewSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
  68. vgui::Panel *pSplitterTopSide = m_pPreviewSplitter->GetChild( 0 );
  69. vgui::Panel *pSplitterBottomSide = m_pPreviewSplitter->GetChild( 1 );
  70. // MDL preview
  71. m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
  72. SetSkipChildDuringPainting( m_pMDLPreview );
  73. m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
  74. m_pViewsSheet->AddActionSignalTarget( this );
  75. // sequences
  76. m_pSequencesPage = NULL;
  77. m_pSequencesList = NULL;
  78. if ( nFlags & PICK_SEQUENCES )
  79. {
  80. m_pSequencesPage = new PropertyPage( m_pViewsSheet, "SequencesPage" );
  81. m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
  82. if ( m_bSequenceParams )
  83. {
  84. char controlName[ 64 ];
  85. const int nNumSeqLines = 32;
  86. const int nSeqSelectorWidth = 180;
  87. int yPos = 10;
  88. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  89. {
  90. V_snprintf( controlName, sizeof( controlName ), "LayerSequence%i", i );
  91. m_pLayerSequenceSelectors[ i ] = new vgui::ComboBox( m_pSequencesPage, controlName, nNumSeqLines, false );
  92. m_pLayerSequenceSelectors[ i ]->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 10, yPos, 0, 0 );
  93. m_pLayerSequenceSelectors[ i ]->SetWide( nSeqSelectorWidth );
  94. m_pLayerSequenceSelectors[ i ]->AddActionSignalTarget( this );
  95. // No slider for the first sequence
  96. if ( i > 0 )
  97. {
  98. yPos += 24;
  99. V_snprintf( controlName, sizeof( controlName ), "LayerSequenceWeight%i", i );
  100. m_pLayerSequenceSliders[ i ] = new vgui::Slider( m_pSequencesPage, controlName );
  101. m_pLayerSequenceSliders[ i ]->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 10, yPos, 0, 0 );
  102. m_pLayerSequenceSliders[ i ]->SetWide( nSeqSelectorWidth );
  103. m_pLayerSequenceSliders[ i ]->SetRange( 0, LAYER_WEIGHT_SLIDER_RANGE );
  104. m_pLayerSequenceSliders[ i ]->AddActionSignalTarget( this );
  105. }
  106. yPos += 40;
  107. }
  108. // Create the pose parameter controls
  109. yPos = 10;
  110. for ( int i = 0; i < NUM_POSE_CONTROLS; ++i )
  111. {
  112. V_snprintf( controlName, sizeof( controlName ), "PoseValueSlider%i", i );
  113. m_pPoseValueSliders[ i ] = new vgui::Slider( m_pSequencesPage, controlName );
  114. m_pPoseValueSliders[ i ]->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 210, yPos, 0, 0 );
  115. m_pPoseValueSliders[ i ]->SetWide( 120 );
  116. m_pPoseValueSliders[ i ]->SetRange( 0, POSE_PARAMETER_SLIDER_RANGE );
  117. m_pPoseValueSliders[ i ]->AddActionSignalTarget( this );
  118. V_snprintf( controlName, sizeof( controlName ), "PoseValueEntry%i", i );
  119. m_pPoseValueEntries[ i ] = new vgui::TextEntry( m_pSequencesPage, controlName );
  120. m_pPoseValueEntries[ i ]->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 330, yPos, 0, 0 );
  121. m_pPoseValueEntries[ i ]->SetWide( 40 );
  122. m_pPoseValueEntries[ i ]->SendNewLine( true );
  123. m_pPoseValueEntries[ i ]->AddActionSignalTarget( this );
  124. V_snprintf( controlName, sizeof( controlName ), "PoseParameterName%i", i );
  125. m_pPoseParameterName[ i ] = new vgui::ComboBox( m_pSequencesPage, controlName, 8, false );
  126. m_pPoseParameterName[ i ]->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 380, yPos, 0, 0 );
  127. m_pPoseParameterName[ i ]->SetWide( 120 );
  128. m_pPoseParameterName[ i ]->AddActionSignalTarget( this );
  129. yPos += 32;
  130. }
  131. // Add a button to reset the the pose parameters to their defaults
  132. m_pPoseDefaultButton = new vgui::Button( m_pSequencesPage, "DefaultsButton", "#SequencePicker_Defaults", this, "ResetToDefaults" );
  133. m_pPoseDefaultButton->SetContentAlignment( Label::a_center );
  134. m_pPoseDefaultButton->SetWide( 100 );
  135. m_pPoseDefaultButton->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 210, yPos, 0, 0 );
  136. m_pPoseDefaultButton->SetEnabled( false );
  137. // A check box for specifying if root motion is to be generated.
  138. m_pRootMotionCheckBox = new vgui::CheckButton( m_pSequencesPage, "RootMotionCheckBox", "#SequencePicker_RootMotion" );
  139. m_pRootMotionCheckBox->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_NO, 324, yPos, 0, 0 );
  140. m_pRootMotionCheckBox->SetWide( 150 );
  141. m_pRootMotionCheckBox->SetSelected( true );
  142. }
  143. else
  144. {
  145. m_pSequencesList = new ListPanel( m_pSequencesPage, "SequencesList" );
  146. m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
  147. m_pSequencesList->AddActionSignalTarget( this );
  148. m_pSequencesList->SetSelectIndividualCells( true );
  149. m_pSequencesList->SetEmptyListText(".MDL file contains no activities");
  150. m_pSequencesList->SetDragEnabled( true );
  151. m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  152. m_pSequencesList->SetSortFunc( 0, SequenceSortFunc );
  153. m_pSequencesList->SetSortColumn( 0 );
  154. }
  155. }
  156. // Activities
  157. m_pActivitiesPage = NULL;
  158. m_pActivitiesList = NULL;
  159. if ( nFlags & PICK_ACTIVITIES )
  160. {
  161. m_pActivitiesPage = new PropertyPage( m_pViewsSheet, "ActivitiesPage" );
  162. m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
  163. m_pActivitiesList = new ListPanel( m_pActivitiesPage, "ActivitiesList" );
  164. m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
  165. m_pActivitiesList->AddActionSignalTarget( this );
  166. m_pActivitiesList->SetSelectIndividualCells( true );
  167. m_pActivitiesList->SetEmptyListText( ".MDL file contains no activities" );
  168. m_pActivitiesList->SetDragEnabled( true );
  169. m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  170. m_pActivitiesList->SetSortFunc( 0, ActivitySortFunc );
  171. m_pActivitiesList->SetSortColumn( 0 );
  172. }
  173. // Load layout settings; has to happen before pinning occurs in code
  174. LoadControlSettingsAndUserConfig( "resource/sequencepicker.res" );
  175. SETUP_PANEL( this );
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose: Destructor
  179. //-----------------------------------------------------------------------------
  180. CSequencePicker::~CSequencePicker()
  181. {
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Performs layout
  185. //-----------------------------------------------------------------------------
  186. void CSequencePicker::PerformLayout()
  187. {
  188. // NOTE: This call should cause auto-resize to occur
  189. // which should fix up the width of the panels
  190. BaseClass::PerformLayout();
  191. int w, h;
  192. GetSize( w, h );
  193. // Layout the mdl splitter
  194. m_pPreviewSplitter->SetBounds( 0, 0, w, h );
  195. }
  196. int CompareSequenceDesc( mstudioseqdesc_t *const *pDescA, mstudioseqdesc_t *const *pDescB )
  197. {
  198. if ( ( pDescA == NULL ) || ( pDescB == NULL ) )
  199. return 0;
  200. if ( ( *pDescA == NULL ) || ( *pDescB == NULL ) )
  201. return 0;
  202. const char *pNameA = (*pDescA)->pszLabel();
  203. const char *pNameB = (*pDescB)->pszLabel();
  204. if ( ( pNameA == NULL) || ( pNameB == NULL ) )
  205. return 0;
  206. return V_stricmp( pNameA, pNameB );
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose: rebuilds the list of activities + sequences
  210. //-----------------------------------------------------------------------------
  211. void CSequencePicker::RefreshActivitiesAndSequencesList()
  212. {
  213. if ( m_pActivitiesList )
  214. {
  215. m_pActivitiesList->RemoveAll();
  216. }
  217. if ( m_pSequencesList )
  218. {
  219. m_pSequencesList->RemoveAll();
  220. }
  221. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  222. {
  223. if ( m_pLayerSequenceSelectors[ i ] )
  224. {
  225. m_pLayerSequenceSelectors[ i ]->RemoveAll();
  226. }
  227. }
  228. m_pMDLPreview->SetSequence( 0, false );
  229. if ( m_hSelectedMDL == MDLHANDLE_INVALID )
  230. return;
  231. studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  232. CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
  233. for (int j = 0; j < hdr->GetNumSeq(); j++)
  234. {
  235. if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
  236. {
  237. const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
  238. if ( m_pActivitiesList && pActivityName && pActivityName[0] )
  239. {
  240. // Multiple sequences can have the same activity name; only add unique activity names
  241. if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
  242. {
  243. KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
  244. int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
  245. KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
  246. pDrag->SetString( "texttype", "activityName" );
  247. pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
  248. m_pActivitiesList->SetItemDragData( nItemID, pDrag );
  249. activityNames.Insert( pActivityName, j );
  250. }
  251. }
  252. const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
  253. if ( m_pSequencesList && pSequenceName && pSequenceName[0] )
  254. {
  255. KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
  256. int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
  257. KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
  258. pDrag->SetString( "texttype", "sequenceName" );
  259. pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
  260. m_pSequencesList->SetItemDragData( nItemID, pDrag );
  261. }
  262. }
  263. }
  264. if ( m_pSequencesList )
  265. {
  266. m_pSequencesList->SortList();
  267. }
  268. if ( m_pActivitiesList )
  269. {
  270. m_pActivitiesList->SortList();
  271. }
  272. // If using the advanced sequence parameters update the
  273. // sequence list for each of the sequence layer drop down boxes.
  274. if ( m_bSequenceParams )
  275. {
  276. int nNumSequences = hdr->GetNumSeq();
  277. CUtlVector< mstudioseqdesc_t * > sequenceList( 0, nNumSequences );
  278. for ( int i = 0; i < nNumSequences; ++i )
  279. {
  280. mstudioseqdesc_t *pSeqDesc = &hdr->pSeqdesc( i );
  281. if ( pSeqDesc->flags & STUDIO_HIDDEN )
  282. continue;
  283. sequenceList.AddToTail( pSeqDesc );
  284. }
  285. sequenceList.Sort( CompareSequenceDesc );
  286. // Clear the existing sequence lists.
  287. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  288. {
  289. if ( m_pLayerSequenceSelectors[ i ] )
  290. {
  291. m_pLayerSequenceSelectors[ i ]->RemoveAll();
  292. }
  293. }
  294. // Add all of the sequences to each of the drop down lists
  295. for ( int i = 0; i < sequenceList.Count(); ++i )
  296. {
  297. mstudioseqdesc_t *pSeqDesc = sequenceList[ i ];
  298. const char *pSequenceName = pSeqDesc->pszLabel();
  299. if ( pSequenceName == NULL )
  300. continue;
  301. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  302. {
  303. if ( m_pLayerSequenceSelectors[ i ] )
  304. {
  305. m_pLayerSequenceSelectors[ i ]->AddItem( pSequenceName, new KeyValues( "sequenceItem", "sequence", pSequenceName ) );
  306. }
  307. }
  308. }
  309. }
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Gets the selected activity/sequence
  313. //-----------------------------------------------------------------------------
  314. CSequencePicker::PickType_t CSequencePicker::GetSelectedSequenceType( )
  315. {
  316. if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
  317. return PICK_SEQUENCES;
  318. if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
  319. return PICK_ACTIVITIES;
  320. return PICK_NONE;
  321. }
  322. const char *CSequencePicker::GetSelectedSequenceName()
  323. {
  324. if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
  325. {
  326. if ( m_pSequencesList )
  327. {
  328. int nIndex = m_pSequencesList->GetSelectedItem( 0 );
  329. if ( nIndex >= 0 )
  330. {
  331. KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
  332. return pkv->GetString( "sequence", NULL );
  333. }
  334. }
  335. else if ( m_bSequenceParams )
  336. {
  337. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  338. if ( pstudiohdr )
  339. {
  340. CStudioHdr studioHdr( pstudiohdr );
  341. int nSeqIndex = m_SequenceLayers[ 0 ].m_nSequenceIndex;
  342. if ( ( nSeqIndex >= 0 ) && ( nSeqIndex < studioHdr.GetNumSeq() ) )
  343. {
  344. mstudioseqdesc_t &seqDesc = studioHdr.pSeqdesc( nSeqIndex );
  345. return seqDesc.pszLabel();
  346. }
  347. }
  348. }
  349. return NULL;
  350. }
  351. if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
  352. {
  353. int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
  354. if ( nIndex >= 0 )
  355. {
  356. KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
  357. return pkv->GetString( "activity", NULL );
  358. }
  359. return NULL;
  360. }
  361. return NULL;
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Get the array of pose parameter values
  365. //-----------------------------------------------------------------------------
  366. void CSequencePicker::GetPoseParameters( CUtlVector< float > &poseParameters ) const
  367. {
  368. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  369. CStudioHdr studioHdr( pstudiohdr );
  370. int nNumParams = studioHdr.GetNumPoseParameters();
  371. for ( int i = 0; i < nNumParams; ++i )
  372. {
  373. poseParameters.AddToTail( m_PoseParameters[ i ] );
  374. }
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Get the array of sequence layers
  378. //-----------------------------------------------------------------------------
  379. void CSequencePicker::GetSeqenceLayers( CUtlVector< MDLSquenceLayer_t > &sequenceLayers ) const
  380. {
  381. // Add each of the layers to the array that has a valid sequence and
  382. // a weight greater than 0. Skip the base layer, it is handled differently.
  383. for ( int i = 1; i < NUM_SEQUENCE_LAYERS; ++i )
  384. {
  385. const MDLSquenceLayer_t &seqLayer = m_SequenceLayers[ i ];
  386. if ( ( seqLayer.m_nSequenceIndex >= 0 ) && ( seqLayer.m_flWeight > 0.0f ) )
  387. {
  388. sequenceLayers.AddToTail( seqLayer );
  389. }
  390. }
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Get the root motion generation state
  394. //-----------------------------------------------------------------------------
  395. bool CSequencePicker::GetGenerateRootMotion() const
  396. {
  397. if ( m_pRootMotionCheckBox == NULL )
  398. return false;
  399. return m_pRootMotionCheckBox->IsSelected();
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Plays the selected activity
  403. //-----------------------------------------------------------------------------
  404. void CSequencePicker::PlayActivity( const char *pActivityName )
  405. {
  406. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  407. for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
  408. {
  409. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  410. if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
  411. {
  412. // FIXME: Add weighted sequence selection logic?
  413. m_pMDLPreview->SetSequence( i, false );
  414. break;
  415. }
  416. }
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Plays the selected sequence
  420. //-----------------------------------------------------------------------------
  421. void CSequencePicker::UpdateActiveSequence( const char *pSequenceName )
  422. {
  423. int seqIndex = FindSequence( pSequenceName );
  424. if ( seqIndex < 0 )
  425. return;
  426. if ( m_bSequenceParams )
  427. {
  428. SetSequenceLayer( 0, seqIndex, 1.0f );
  429. // Update the available set of pose parameters
  430. UpdateAvailablePoseParmeters();
  431. }
  432. // Play the sequence
  433. m_pMDLPreview->SetSequence( seqIndex, false );
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Find the index of the sequence with the specified name
  437. //-----------------------------------------------------------------------------
  438. int CSequencePicker::FindSequence( const char *pSequenceName ) const
  439. {
  440. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  441. for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++)
  442. {
  443. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  444. if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
  445. {
  446. return i;
  447. }
  448. }
  449. return -1;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Update the set of available pose parameters
  453. //-----------------------------------------------------------------------------
  454. void CSequencePicker::UpdateAvailablePoseParmeters()
  455. {
  456. if ( m_bSequenceParams )
  457. {
  458. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  459. CStudioHdr studioHdr( pstudiohdr );
  460. // Determine which of the pose parameters are active for the current sequence
  461. bool activePoseParameters[ MAXSTUDIOPOSEPARAM ] = { false };
  462. for ( int iLayer = 0; iLayer < NUM_SEQUENCE_LAYERS; ++iLayer )
  463. {
  464. int nSeqIndex = m_SequenceLayers[ iLayer ].m_nSequenceIndex;
  465. if ( ( nSeqIndex >= 0 ) && ( nSeqIndex < studioHdr.GetNumSeq() ) )
  466. {
  467. FindSequencePoseParameters( studioHdr, nSeqIndex, activePoseParameters, MAXSTUDIOPOSEPARAM );
  468. }
  469. }
  470. // Build a list of the active pose parameters
  471. int nNumMdlParameters = studioHdr.GetNumPoseParameters();
  472. int sequencePoseParameters[ MAXSTUDIOPOSEPARAM ];
  473. int nNumSequenceParameters = 0;
  474. V_memset( sequencePoseParameters, 0xff, sizeof( sequencePoseParameters ) );
  475. for ( int iParam = 0; iParam < nNumMdlParameters; ++iParam )
  476. {
  477. if ( activePoseParameters[ iParam ] )
  478. {
  479. sequencePoseParameters[ nNumSequenceParameters++ ] = iParam;
  480. }
  481. }
  482. // Assign the controls the parameters which are active for the current sequence
  483. int nNumActiveControls = MIN( NUM_POSE_CONTROLS, nNumSequenceParameters );
  484. for ( int iControl = 0; iControl < nNumActiveControls; ++iControl )
  485. {
  486. m_PoseControlMap[ iControl ] = sequencePoseParameters[ iControl ];
  487. m_pPoseValueSliders[ iControl ]->SetEnabled( true );
  488. m_pPoseValueEntries[ iControl ]->SetEnabled( true );
  489. vgui::ComboBox *pPoseNameComboBox = m_pPoseParameterName[ iControl ];
  490. pPoseNameComboBox->SetEnabled( true );
  491. pPoseNameComboBox->RemoveAll();
  492. pPoseNameComboBox->SetNumberOfEditLines( nNumSequenceParameters );
  493. // Add the parameters to the combo box list
  494. for ( int iParam = 0; iParam < nNumSequenceParameters; ++iParam )
  495. {
  496. int nParamIndex = sequencePoseParameters[ iParam ];
  497. const mstudioposeparamdesc_t &poseParameter = studioHdr.pPoseParameter( nParamIndex );
  498. int itemId = pPoseNameComboBox->AddItem( poseParameter.pszName(), new KeyValues( "ParameterItem", "paramIndex", nParamIndex ) );
  499. if ( iParam == iControl )
  500. {
  501. pPoseNameComboBox->ActivateItem( itemId );
  502. }
  503. }
  504. }
  505. // De-activate the controls for which there are not parameters
  506. for ( int iControl = nNumActiveControls; iControl < NUM_POSE_CONTROLS; ++iControl )
  507. {
  508. m_PoseControlMap[ iControl ] = -1;
  509. m_pPoseValueSliders[ iControl ]->SetEnabled( false );
  510. m_pPoseValueSliders[ iControl ]->SetValue( 0 );
  511. m_pPoseValueEntries[ iControl ]->SetEnabled( false );
  512. m_pPoseValueEntries[ iControl ]->SetText( "" );
  513. m_pPoseParameterName[ iControl ]->SetEnabled( false );
  514. m_pPoseParameterName[ iControl ]->RemoveAll();
  515. m_pPoseParameterName[ iControl ]->SetText( "" );
  516. }
  517. // Disable the reset to defaults button if there are no active controls
  518. m_pPoseDefaultButton->SetEnabled( ( nNumActiveControls > 0 ) );
  519. // Update the active controls to match the pose parameters
  520. UpdatePoseControlsFromParameters();
  521. }
  522. }
  523. //-----------------------------------------------------------------------------
  524. // Update the value of the specified control control group
  525. //-----------------------------------------------------------------------------
  526. void CSequencePicker::SetPoseParameterValue( float flPoseParameterValue, int nParameterIndex )
  527. {
  528. if ( ( nParameterIndex < 0 ) || ( nParameterIndex >= MAXSTUDIOPOSEPARAM ) )
  529. return;
  530. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  531. CStudioHdr studioHdr( pstudiohdr );
  532. // Update the the actual pose parameter value
  533. const mstudioposeparamdesc_t &poseParameter = studioHdr.pPoseParameter( nParameterIndex );
  534. m_PoseParameters[ nParameterIndex ] = flPoseParameterValue;
  535. m_pMDLPreview->SetPoseParameters( m_PoseParameters, MAXSTUDIOPOSEPARAM );
  536. for ( int iControl = 0; iControl < NUM_POSE_CONTROLS; ++iControl )
  537. {
  538. if ( m_PoseControlMap[ iControl ] == nParameterIndex )
  539. {
  540. // Compute the slider position, since the slider to parameter value mapping is
  541. // exponential the parameter value must go through the inverse of the transform
  542. // that is used to compute the parameter value from the slider value
  543. float flRangeValue = flPoseParameterValue * 2.0f - 1.0f;
  544. float flNormalized = ( flRangeValue >= 0 ) ? sqrtf( flRangeValue ) : -( sqrtf( -flRangeValue ) );
  545. int nSliderValue = ( ( flNormalized * 0.5f + 0.5f ) * ( float )( POSE_PARAMETER_SLIDER_RANGE ) ) + 0.5f;
  546. m_pPoseValueSliders[ iControl ]->SetValue( nSliderValue, false );
  547. // Update the text entry using the the pose parameter range
  548. float flFullRangeValue = ( poseParameter.end - poseParameter.start ) * flPoseParameterValue + poseParameter.start;
  549. char valueText[ 32 ];
  550. V_snprintf( valueText, sizeof( valueText ), "%0.2f", flFullRangeValue );
  551. m_pPoseValueEntries[ iControl ]->SetText( valueText );
  552. }
  553. }
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Set all pose parameters to their default values
  557. //-----------------------------------------------------------------------------
  558. void CSequencePicker::ResetPoseParametersToDefault()
  559. {
  560. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  561. CStudioHdr studioHdr( pstudiohdr );
  562. // Re-compute the default pose parameters for the model, and update the
  563. // controls, clearing any changes that were made previously.
  564. Studio_CalcDefaultPoseParameters( &studioHdr, m_PoseParameters, MAXSTUDIOPOSEPARAM );
  565. UpdatePoseControlsFromParameters();
  566. }
  567. //-----------------------------------------------------------------------------
  568. // Update the pose parameter controls using the stored pose parameter values
  569. //-----------------------------------------------------------------------------
  570. void CSequencePicker::UpdatePoseControlsFromParameters()
  571. {
  572. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  573. CStudioHdr studioHdr( pstudiohdr );
  574. int nNumParams = studioHdr.GetNumPoseParameters();
  575. for ( int iParam = 0; iParam < nNumParams; ++iParam )
  576. {
  577. float flParameterValue = m_PoseParameters[ iParam ];
  578. SetPoseParameterValue( flParameterValue, iParam );
  579. }
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Update the pose parameter controls to match the set of pose parameters for
  583. // the current mdl
  584. //-----------------------------------------------------------------------------
  585. void CSequencePicker::UpdatePoseParameterControlsForMdl()
  586. {
  587. if ( m_bSequenceParams )
  588. {
  589. // De-activate all pose controls
  590. for ( int iControl = 0; iControl < NUM_POSE_CONTROLS; ++iControl )
  591. {
  592. m_PoseControlMap[ iControl ] = -1;
  593. m_pPoseValueSliders[ iControl ]->SetEnabled( false );
  594. m_pPoseValueEntries[ iControl ]->SetEnabled( false );
  595. m_pPoseParameterName[ iControl ]->SetEnabled( false );
  596. }
  597. }
  598. // Reset all pose parameters and controls to the default values
  599. ResetPoseParametersToDefault();
  600. }
  601. //-----------------------------------------------------------------------------
  602. // Update the sequence and weighting of the specified layer
  603. //-----------------------------------------------------------------------------
  604. void CSequencePicker::SetSequenceLayer( int nLayerIndex, int nSequenceIndex, float flWeight )
  605. {
  606. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  607. if ( pstudiohdr == NULL )
  608. return;
  609. int nNumSequences = pstudiohdr->GetNumSeq();
  610. if ( ( nLayerIndex < 0 ) || ( nLayerIndex >= NUM_SEQUENCE_LAYERS ) || ( nSequenceIndex >= nNumSequences ) )
  611. return;
  612. m_SequenceLayers[ nLayerIndex ].m_nSequenceIndex = nSequenceIndex;
  613. m_SequenceLayers[ nLayerIndex ].m_flWeight = MIN( MAX( flWeight, 0.0f ), 1.0f );
  614. m_pMDLPreview->SetSequenceLayers( m_SequenceLayers + 1, NUM_SEQUENCE_LAYERS - 1 );
  615. // Update the associated sequence selection combo box to show the new sequence for the specified layer
  616. vgui::ComboBox *pSequenceSelector = m_pLayerSequenceSelectors[ nLayerIndex ];
  617. if ( pSequenceSelector )
  618. {
  619. // Find the item with the specified sequence
  620. if ( nSequenceIndex < 0 )
  621. {
  622. pSequenceSelector->SetText( "" );
  623. }
  624. else
  625. {
  626. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( nSequenceIndex );
  627. const char *pSequenceName = seqdesc.pszLabel();
  628. // Find the item with the selected sequence
  629. int nItems = pSequenceSelector->GetItemCount();
  630. for ( int i = 0; i < nItems; ++i )
  631. {
  632. KeyValues *pItemData = pSequenceSelector->GetItemUserData( i );
  633. if ( pItemData )
  634. {
  635. const char *pItemSeqName = pItemData->GetString( "sequence", "invalidItem" );
  636. if ( V_stricmp( pSequenceName, pItemSeqName ) == 0 )
  637. {
  638. pSequenceSelector->ActivateItem( i );
  639. }
  640. }
  641. }
  642. }
  643. }
  644. // Update the slider for the layer to match the current value
  645. vgui::Slider *pWeightSlider = m_pLayerSequenceSliders[ nLayerIndex ];
  646. if ( pWeightSlider )
  647. {
  648. int nSliderValue = m_SequenceLayers[ nLayerIndex ].m_flWeight * LAYER_WEIGHT_SLIDER_RANGE;
  649. pWeightSlider->SetValue( nSliderValue, false );
  650. }
  651. // Update the available set of pose parameters
  652. UpdateAvailablePoseParmeters();
  653. }
  654. //-----------------------------------------------------------------------------
  655. // Update the sequence layer controls to match the current layer data set
  656. //-----------------------------------------------------------------------------
  657. void CSequencePicker::UpdateLayerControls()
  658. {
  659. for ( int iLayer = 0; iLayer < NUM_SEQUENCE_LAYERS; ++iLayer )
  660. {
  661. SetSequenceLayer( iLayer, m_SequenceLayers[ iLayer ].m_nSequenceIndex, m_SequenceLayers[ iLayer ].m_flWeight );
  662. }
  663. }
  664. //-----------------------------------------------------------------------------
  665. // Clear all the layer information and update the controls
  666. //-----------------------------------------------------------------------------
  667. void CSequencePicker::ResetLayers()
  668. {
  669. for ( int iLayer = 0; iLayer < NUM_SEQUENCE_LAYERS; ++iLayer )
  670. {
  671. m_SequenceLayers[ iLayer ].m_nSequenceIndex = ( iLayer == 0 ) ? 0 : -1;
  672. m_SequenceLayers[ iLayer ].m_flWeight = ( iLayer == 0 ) ? 1.0f : 0.0f;
  673. }
  674. UpdateLayerControls();
  675. }
  676. //-----------------------------------------------------------------------------
  677. // Sets the MDL to select sequences in
  678. //-----------------------------------------------------------------------------
  679. void CSequencePicker::SetMDL( const char *pMDLName )
  680. {
  681. m_hSelectedMDL = pMDLName ? vgui::MDLCache()->FindMDL( pMDLName ) : MDLHANDLE_INVALID;
  682. if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL ) )
  683. {
  684. m_hSelectedMDL = MDLHANDLE_INVALID;
  685. }
  686. m_pMDLPreview->SetMDL( m_hSelectedMDL );
  687. m_pMDLPreview->LookAtMDL();
  688. ResetLayers();
  689. RefreshActivitiesAndSequencesList();
  690. UpdateLayerControls();
  691. UpdatePoseParameterControlsForMdl();
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Purpose: Called when a page is shown
  695. //-----------------------------------------------------------------------------
  696. void CSequencePicker::OnPageChanged( )
  697. {
  698. if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
  699. {
  700. const char *pSequenceName = GetSelectedSequenceName();
  701. if ( pSequenceName )
  702. {
  703. UpdateActiveSequence( pSequenceName );
  704. PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
  705. }
  706. return;
  707. }
  708. if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
  709. {
  710. const char *pActivityName = GetSelectedSequenceName();
  711. if ( pActivityName )
  712. {
  713. PlayActivity( pActivityName );
  714. PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
  715. }
  716. return;
  717. }
  718. }
  719. //-----------------------------------------------------------------------------
  720. // Purpose: refreshes dialog on text changing
  721. //-----------------------------------------------------------------------------
  722. void CSequencePicker::OnItemSelected( KeyValues *kv )
  723. {
  724. Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
  725. if ( m_pSequencesList && (pPanel == m_pSequencesList ) )
  726. {
  727. const char *pSequenceName = GetSelectedSequenceName();
  728. if ( pSequenceName )
  729. {
  730. UpdateActiveSequence( pSequenceName );
  731. PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
  732. }
  733. return;
  734. }
  735. if ( m_pActivitiesList && ( pPanel == m_pActivitiesList ) )
  736. {
  737. const char *pActivityName = GetSelectedSequenceName();
  738. if ( pActivityName )
  739. {
  740. PlayActivity( pActivityName );
  741. PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
  742. }
  743. return;
  744. }
  745. }
  746. //-----------------------------------------------------------------------------
  747. // Process the slider moved message, determine which slider was moved and
  748. // update the corresponding pose parameter value.
  749. //-----------------------------------------------------------------------------
  750. void CSequencePicker::OnSliderMoved( KeyValues *pData )
  751. {
  752. vgui::Panel *pPanel = reinterpret_cast<vgui::Panel *>( const_cast<KeyValues*>(pData)->GetPtr("panel") );
  753. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  754. {
  755. if ( pPanel == m_pLayerSequenceSliders[ i ] )
  756. {
  757. int nValue = m_pLayerSequenceSliders[ i ]->GetValue();
  758. float flWeight = ( float )( nValue ) / ( float )( LAYER_WEIGHT_SLIDER_RANGE );
  759. SetSequenceLayer( i, m_SequenceLayers[ i ].m_nSequenceIndex, flWeight );
  760. return;
  761. }
  762. }
  763. for ( int i = 0; i < NUM_POSE_CONTROLS; ++i )
  764. {
  765. if ( pPanel == m_pPoseValueSliders[ i ] )
  766. {
  767. int nControlIndex = i;
  768. // Use an exponential mapping around which provides the
  769. // most precision around the 0.5 of the pose parameter
  770. int nValue = m_pPoseValueSliders[ nControlIndex ]->GetValue();
  771. float flHalfRange = ( float )( POSE_PARAMETER_SLIDER_RANGE / 2 );
  772. float flScaledValue = ( ( float )( nValue ) - flHalfRange ) / flHalfRange;
  773. float flPoseParameterValue = ( flScaledValue * fabs( flScaledValue ) ) * 0.5f + 0.5f;
  774. int nParameterIndex = m_PoseControlMap[ nControlIndex ];
  775. SetPoseParameterValue( flPoseParameterValue, nParameterIndex );
  776. return;
  777. }
  778. }
  779. }
  780. //-----------------------------------------------------------------------------
  781. // Process the text entry notification messages. Determine which text
  782. // entry was changed and update the value of the corresponding pose parameter.
  783. //-----------------------------------------------------------------------------
  784. void CSequencePicker::OnTextKillFocus( KeyValues *pData )
  785. {
  786. vgui::Panel *pPanel = reinterpret_cast<vgui::Panel *>( const_cast<KeyValues*>(pData)->GetPtr("panel") );
  787. int nControlIndex = -1;
  788. for ( int i = 0; i < NUM_POSE_CONTROLS; ++i )
  789. {
  790. if ( pPanel == m_pPoseValueEntries[ i ] )
  791. {
  792. nControlIndex = i;
  793. break;
  794. }
  795. }
  796. if ( nControlIndex < 0 )
  797. return;
  798. // Get the value from the text entry and re-map using the pose parameter range
  799. float flValue = m_pPoseValueEntries[ nControlIndex ]->GetValueAsFloat();
  800. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
  801. CStudioHdr studioHdr( pstudiohdr );
  802. int nParameterIndex = m_PoseControlMap[ nControlIndex ];
  803. const mstudioposeparamdesc_t &poseParameter = studioHdr.pPoseParameter( nParameterIndex );
  804. float flMinVal = MIN( poseParameter.start, poseParameter.end );
  805. float flMaxVal = MAX( poseParameter.start, poseParameter.end );
  806. float flRangeValue = MIN( flMaxVal, MAX( flMinVal, flValue ) );
  807. float flNormalized = ( flRangeValue - flMinVal ) / ( flMaxVal - flMinVal );
  808. SetPoseParameterValue( flNormalized, nParameterIndex );
  809. }
  810. void CSequencePicker::OnTextNewLine( KeyValues *pData )
  811. {
  812. OnTextKillFocus( pData );
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Handle changes to the combo box selection
  816. //-----------------------------------------------------------------------------
  817. void CSequencePicker::OnTextChanged( KeyValues *pData )
  818. {
  819. vgui::Panel *pPanel = reinterpret_cast<vgui::Panel *>( const_cast<KeyValues*>(pData)->GetPtr("panel") );
  820. // Check to see if a new sequence layer was selected
  821. for ( int i = 0; i < NUM_SEQUENCE_LAYERS; ++i )
  822. {
  823. if ( pPanel == m_pLayerSequenceSelectors[ i ] )
  824. {
  825. const char *pSequenceName = pData->GetString( "text" );
  826. if ( i == 0 )
  827. {
  828. UpdateActiveSequence( pSequenceName );
  829. }
  830. else
  831. {
  832. int nSequenceIndex = FindSequence( pSequenceName );
  833. SetSequenceLayer( i, nSequenceIndex, m_SequenceLayers[ i ].m_flWeight );
  834. }
  835. return;
  836. }
  837. }
  838. // Determine which combo box has changed if any, this message will also be sent by the
  839. // text entry but is ignored because it sent every time any change is made, even a just
  840. // one character not necessarily a whole value change, so it is ignored.
  841. int nControlIndex = -1;
  842. for ( int i = 0; i < NUM_POSE_CONTROLS; ++i )
  843. {
  844. if ( pPanel == m_pPoseParameterName[ i ] )
  845. {
  846. nControlIndex = i;
  847. KeyValues *pItemData = m_pPoseParameterName[ nControlIndex ]->GetActiveItemUserData();
  848. int nParameterIndex = pItemData->GetInt( "paramIndex", -1 );
  849. if ( ( nParameterIndex >= 0 ) && ( nParameterIndex < MAXSTUDIOPOSEPARAM ) )
  850. {
  851. m_PoseControlMap[ nControlIndex ] = nParameterIndex;
  852. SetPoseParameterValue( m_PoseParameters[ nParameterIndex ], nParameterIndex );
  853. }
  854. return;
  855. }
  856. }
  857. }
  858. //-----------------------------------------------------------------------------
  859. // Process command messages
  860. //-----------------------------------------------------------------------------
  861. void CSequencePicker::OnCommand( const char *pCommand )
  862. {
  863. if ( !V_strcmp( "ResetToDefaults", pCommand ) )
  864. {
  865. ResetPoseParametersToDefault();
  866. }
  867. }
  868. //-----------------------------------------------------------------------------
  869. //
  870. // Purpose: Modal picker frame
  871. //
  872. //-----------------------------------------------------------------------------
  873. CSequencePickerFrame::CSequencePickerFrame( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePickerFrame" )
  874. {
  875. SetDeleteSelfOnClose( true );
  876. m_pPicker = new CSequencePicker( this, nFlags );
  877. m_pPicker->AddActionSignalTarget( this );
  878. m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
  879. m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
  880. SetBlockDragChaining( true );
  881. LoadControlSettingsAndUserConfig( "resource/sequencepickerframe.res" );
  882. m_pOpenButton->SetEnabled( false );
  883. }
  884. //-----------------------------------------------------------------------------
  885. // Purpose: Activate the dialog
  886. //-----------------------------------------------------------------------------
  887. void CSequencePickerFrame::DoModal( const char *pMDLName )
  888. {
  889. m_pPicker->SetMDL( pMDLName );
  890. BaseClass::DoModal();
  891. }
  892. //-----------------------------------------------------------------------------
  893. // On mdl preview changed
  894. //-----------------------------------------------------------------------------
  895. void CSequencePickerFrame::OnSequencePreviewChanged( KeyValues *pKeyValues )
  896. {
  897. const char *pSequence = pKeyValues->GetString( "sequence", NULL );
  898. const char *pActivity = pKeyValues->GetString( "activity", NULL );
  899. m_pOpenButton->SetEnabled( pSequence || pActivity );
  900. }
  901. //-----------------------------------------------------------------------------
  902. // On command
  903. //-----------------------------------------------------------------------------
  904. void CSequencePickerFrame::OnCommand( const char *pCommand )
  905. {
  906. if ( !Q_stricmp( pCommand, "Open" ) )
  907. {
  908. CSequencePicker::PickType_t type = m_pPicker->GetSelectedSequenceType( );
  909. if (( type == CSequencePicker::PICK_SEQUENCES ) || ( type == CSequencePicker::PICK_ACTIVITIES ))
  910. {
  911. const char *pSequenceName = m_pPicker->GetSelectedSequenceName();
  912. if ( pSequenceName )
  913. {
  914. if ( type == CSequencePicker::PICK_SEQUENCES )
  915. {
  916. // Create the key values with the sequence name
  917. KeyValues *pKV = new KeyValues( "SequenceSelected", "sequence", pSequenceName );
  918. // Add a set of keys descibing the sequence layers
  919. CUtlVector< MDLSquenceLayer_t > sequenceLayers;
  920. m_pPicker->GetSeqenceLayers( sequenceLayers );
  921. int nNumLayers = sequenceLayers.Count();
  922. pKV->SetInt( "numLayers", nNumLayers );
  923. char layerName[ 32 ];
  924. for ( int i = 0; i < nNumLayers; ++i )
  925. {
  926. V_snprintf( layerName, sizeof( layerName ), "layer%i", i );
  927. KeyValues *pLayerData = new KeyValues( layerName );
  928. pLayerData->SetInt( "sequence", sequenceLayers[ i ].m_nSequenceIndex );
  929. pLayerData->SetFloat( "weight", sequenceLayers[ i ].m_flWeight );
  930. pKV->AddSubKey( pLayerData );
  931. }
  932. // Add the pose parameters for the sequence, there is a key
  933. // for the number of parameters and then a key for each parameter.
  934. CUtlVector< float > poseParameters( 0, MAXSTUDIOPOSEPARAM );
  935. m_pPicker->GetPoseParameters( poseParameters );
  936. int nNumParams = poseParameters.Count();
  937. pKV->SetInt( "numPoseParameters", nNumParams );
  938. char poseParameterName[ 32 ];
  939. for ( int i = 0; i < nNumParams; ++i )
  940. {
  941. V_snprintf( poseParameterName, sizeof( poseParameterName ), "poseParameter%i", i );
  942. pKV->SetFloat( poseParameterName, poseParameters[ i ] );
  943. }
  944. // Set the value indicating if root motion should be generated.
  945. bool bRootMoition = m_pPicker->GetGenerateRootMotion();
  946. pKV->SetBool( "rootMotion", bRootMoition );
  947. PostActionSignal( pKV );
  948. }
  949. else
  950. {
  951. PostActionSignal( new KeyValues("SequenceSelected", "activity", pSequenceName ) );
  952. }
  953. CloseModal();
  954. return;
  955. }
  956. }
  957. return;
  958. }
  959. if ( !Q_stricmp( pCommand, "Cancel" ) )
  960. {
  961. CloseModal();
  962. return;
  963. }
  964. BaseClass::OnCommand( pCommand );
  965. }