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.

1092 lines
26 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "hlfaceposer.h"
  7. #include "FlexPanel.h"
  8. #include "ViewerSettings.h"
  9. #include "StudioModel.h"
  10. #include "MatSysWin.h"
  11. #include "ControlPanel.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <mxtk/mx.h>
  16. #include <mxtk/mxBmp.h>
  17. #include "mxbitmapwindow.h"
  18. #include "mxExpressionTray.h"
  19. #include "expressions.h"
  20. #include "expressiontool.h"
  21. #include "filesystem.h"
  22. #include "mdlviewer.h"
  23. #include "ExpressionProperties.h"
  24. #include "expclass.h"
  25. #include "choreowidgetdrawhelper.h"
  26. #include "choreoview.h"
  27. #include "choreoscene.h"
  28. #include "mxExpressionSlider.h"
  29. #include "faceposer_models.h"
  30. LocalFlexController_t FindFlexControllerIndexByName( StudioModel *model, char const *searchname );
  31. char const *GetGlobalFlexControllerName( int index );
  32. extern char g_appTitle[];
  33. #define LINE_HEIGHT 20
  34. #define FLEXSLIDER_INVALID_INDEX -1
  35. FlexPanel *g_pFlexPanel = 0;
  36. void FlexPanel::PositionControls( int width, int height )
  37. {
  38. int buttonwidth = 80;
  39. int buttonx = 3;
  40. int row = height - 18;
  41. int buttonheight = 18;
  42. btnResetSliders->setBounds( buttonx, row, buttonwidth, buttonheight );
  43. buttonx += buttonwidth + 5;
  44. btnCopyToSliders->setBounds( buttonx, row, buttonwidth, buttonheight );
  45. buttonx += buttonwidth + 5;
  46. buttonwidth = 100;
  47. btnCopyFromSliders->setBounds( buttonx, row, buttonwidth, buttonheight );
  48. buttonx += buttonwidth + 5;
  49. buttonwidth = 100;
  50. btnMenu->setBounds( buttonx, row, buttonwidth, buttonheight );
  51. }
  52. FlexPanel::FlexPanel (mxWindow *parent)
  53. : IFacePoserToolWindow( "FlexPanel", "Flex Sliders" ), mxWindow( parent, 0, 0, 0, 0 )
  54. {
  55. m_nViewableFlexControllerCount = 0;
  56. m_bNewExpressionMode = true;
  57. btnResetSliders = new mxButton( this, 0, 0, 100, 20, "Zero Sliders", IDC_EXPRESSIONRESET );
  58. btnCopyToSliders = new mxButton( this, 0, 0, 100, 20, "Get Tracks", IDC_COPY_TO_FLEX );
  59. btnCopyFromSliders = new mxButton( this, 0, 0, 100, 20, "Make Keyframe", IDC_COPY_FROM_FLEX );
  60. btnMenu = new mxButton( this, 0, 0, 100, 20, "Menu", IDC_FP_MENU );
  61. mxWindow *wFlex = this;
  62. for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++)
  63. {
  64. int w = 5; // (i / 4) * 156 + 5;
  65. int h = i * LINE_HEIGHT + 5; // (i % 4) * 20 + 5;
  66. slFlexScale[i] = new mxExpressionSlider (wFlex, w, h, 220, LINE_HEIGHT, IDC_FLEXSCALE + i);
  67. }
  68. slScrollbar = new mxScrollbar( wFlex, 0, 0, 18, 100, IDC_FLEXSCROLL, mxScrollbar::Vertical );
  69. slScrollbar->setRange( 0, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * LINE_HEIGHT );
  70. slScrollbar->setPagesize( 100 );
  71. }
  72. FlexPanel::~FlexPanel()
  73. {
  74. }
  75. void FlexPanel::redraw()
  76. {
  77. if ( !ToolCanDraw() )
  78. return;
  79. CChoreoWidgetDrawHelper helper( this, RGBToColor( GetSysColor( COLOR_BTNFACE ) ) );
  80. HandleToolRedraw( helper );
  81. BaseClass::redraw();
  82. }
  83. void FlexPanel::PositionSliders( int sboffset )
  84. {
  85. int reservedheight = GetCaptionHeight() + 5 /*gap at top*/ + 1 * 20 /* space for buttons/edit controls*/;
  86. int widthofslidercolumn = slFlexScale[ 0 ]->w() + 10;
  87. int colsavailable = ( this->w2() - 20 /*scrollbar*/ - 10 /*left edge gap + right gap*/ ) / widthofslidercolumn;
  88. // Need at least one column
  89. colsavailable = max( colsavailable, 1 );
  90. int rowsneeded = GLOBAL_STUDIO_FLEX_CONTROL_COUNT;
  91. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  92. if ( hdr )
  93. {
  94. rowsneeded = m_nViewableFlexControllerCount;
  95. }
  96. int rowsvisible = ( this->h2() - reservedheight ) / LINE_HEIGHT;
  97. int rowspercol = rowsvisible;
  98. if ( rowsvisible * colsavailable < rowsneeded )
  99. {
  100. // Figure out how many controls should go in each available column
  101. rowspercol = (rowsneeded + (colsavailable - 1)) / colsavailable;
  102. slScrollbar->setPagesize( rowsvisible * LINE_HEIGHT );
  103. slScrollbar->setRange( 0, rowspercol * LINE_HEIGHT );
  104. }
  105. int row = 0;
  106. int col = 0;
  107. for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++)
  108. {
  109. int x = 5 + col * widthofslidercolumn;
  110. int y = row * LINE_HEIGHT + 5 + GetCaptionHeight() - sboffset; // (i % 4) * 20 + 5;
  111. slFlexScale[ i ]->setBounds( x, y, slFlexScale[i]->w(), slFlexScale[i]->h() );
  112. if ( i >= rowsneeded ||
  113. ( y + LINE_HEIGHT - 5 > ( this->h2() - reservedheight ) ) )
  114. {
  115. slFlexScale[ i ]->setVisible( false );
  116. }
  117. else
  118. {
  119. slFlexScale[ i ]->setVisible( true );
  120. }
  121. row++;
  122. if ( row >= rowspercol )
  123. {
  124. col++;
  125. row = 0;
  126. }
  127. }
  128. }
  129. int FlexPanel::handleEvent (mxEvent *event)
  130. {
  131. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  132. int iret = 0;
  133. if ( HandleToolEvent( event ) )
  134. {
  135. return iret;
  136. }
  137. switch ( event->event )
  138. {
  139. case mxEvent::Size:
  140. {
  141. int trueh = h2() - GetCaptionHeight();
  142. PositionControls( w2(), h2() );
  143. slScrollbar->setPagesize( trueh );
  144. slScrollbar->setBounds( w2() - 18, GetCaptionHeight(), 18, trueh );
  145. PositionSliders( 0 );
  146. iret = 1;
  147. }
  148. break;
  149. case mxEvent::Action:
  150. {
  151. iret = 1;
  152. switch ( event->action )
  153. {
  154. default:
  155. iret = 0;
  156. break;
  157. case IDC_FLEXSCROLL:
  158. {
  159. if ( event->event == mxEvent::Action &&
  160. event->modifiers == SB_THUMBTRACK)
  161. {
  162. int offset = event->height; // ((mxScrollbar *) event->widget)->getValue( );
  163. slScrollbar->setValue( offset ); // if (offset > slScrollbar->getPagesize()
  164. PositionSliders( offset );
  165. IFacePoserToolWindow::SetActiveTool( this );
  166. }
  167. }
  168. break;
  169. case IDC_EXPRESSIONRESET:
  170. {
  171. ResetSliders( true, true );
  172. IFacePoserToolWindow::SetActiveTool( this );
  173. }
  174. break;
  175. case IDC_COPY_TO_FLEX:
  176. {
  177. g_pExpressionTool->OnCopyToFlex( g_pChoreoView->GetScene()->GetTime(), true );
  178. }
  179. break;
  180. case IDC_COPY_FROM_FLEX:
  181. {
  182. g_pExpressionTool->OnCopyFromFlex( g_pChoreoView->GetScene()->GetTime(), false );
  183. }
  184. break;
  185. case IDC_FP_UNCHECK_ALL:
  186. {
  187. OnSetAll( FP_STATE_UNCHECK );
  188. }
  189. break;
  190. case IDC_FP_CHECK_ALL:
  191. {
  192. OnSetAll( FP_STATE_CHECK );
  193. }
  194. break;
  195. case IDC_FP_INVERT:
  196. {
  197. OnSetAll( FP_STATE_INVERT );
  198. }
  199. break;
  200. case IDC_FP_MENU:
  201. {
  202. OnMenu();
  203. }
  204. break;
  205. }
  206. if ( event->action >= IDC_FLEXSCALE && event->action < IDC_FLEXSCALE + GLOBAL_STUDIO_FLEX_CONTROL_COUNT)
  207. {
  208. iret = 1;
  209. bool pushundo = false;
  210. mxExpressionSlider *slider = ( mxExpressionSlider * )event->widget;
  211. int barnumber = event->height;
  212. int slidernum = ( event->action - IDC_FLEXSCALE );
  213. float value = slider->getValue ( barnumber );
  214. float influ = slider->getInfluence( );
  215. switch( event->modifiers )
  216. {
  217. case SB_THUMBPOSITION:
  218. case SB_THUMBTRACK:
  219. break;
  220. case SB_ENDSCROLL:
  221. pushundo = true;
  222. break;
  223. }
  224. int flex = LookupFlex( slidernum, barnumber );
  225. int flex2 = LookupPairedFlex( flex );
  226. float value2 = GetSlider( flex2 );
  227. CExpClass *active = expressions->GetActiveClass();
  228. if ( active )
  229. {
  230. int index = active->GetSelectedExpression();
  231. if ( pushundo && index != -1 )
  232. {
  233. CExpression *exp = active->GetExpression( index );
  234. if ( exp )
  235. {
  236. float *settings = exp->GetSettings();
  237. float *weights = exp->GetWeights();
  238. Assert( settings );
  239. if ( settings[ flex ] != value ||
  240. settings[ flex2 ] != value2 ||
  241. weights[ flex ] != influ )
  242. {
  243. exp->PushUndoInformation();
  244. active->SetDirty( true );
  245. settings[ flex ] = value;
  246. settings[ flex2 ] = value2;
  247. weights[ flex ] = influ;
  248. weights[ flex2 ] = influ;
  249. exp->PushRedoInformation();
  250. g_pExpressionTrayTool->redraw();
  251. }
  252. }
  253. }
  254. }
  255. // FIXME: Needs to drive the current actor, not model
  256. // Go from global to local indices
  257. LocalFlexController_t localflex = FindFlexControllerIndexByName( models->GetActiveStudioModel(), GetGlobalFlexControllerName( flex ) );
  258. if ( localflex >= 0 )
  259. {
  260. // Update the face
  261. // FIXME: I'm not sure this is needed anymore....
  262. models->GetActiveStudioModel()->SetFlexController( localflex, value * influ );
  263. if (flex2 != flex)
  264. {
  265. LocalFlexController_t localflex2 = FindFlexControllerIndexByName( models->GetActiveStudioModel(), GetGlobalFlexControllerName( flex2 ) );
  266. if ( localflex2 >= 0 )
  267. {
  268. models->GetActiveStudioModel()->SetFlexController( localflex2, value2 * influ );
  269. }
  270. else
  271. {
  272. Assert( 0 );
  273. }
  274. }
  275. }
  276. else
  277. {
  278. Assert( 0 );
  279. }
  280. models->SetSolveHeadTurn( 1 );
  281. IFacePoserToolWindow::SetActiveTool( this );
  282. }
  283. }
  284. }
  285. return iret;
  286. }
  287. void FlexPanel::initFlexes()
  288. {
  289. m_nViewableFlexControllerCount = 0;
  290. memset( nFlexSliderIndex, 0, sizeof( nFlexSliderIndex ) );
  291. memset( nFlexSliderBarnum, 0, sizeof( nFlexSliderBarnum ) );
  292. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  293. if (hdr)
  294. {
  295. for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++)
  296. {
  297. slFlexScale[i]->setVisible( false );
  298. slFlexScale[i]->setLabel( "" );
  299. slFlexScale[i]->SetMode( false );
  300. // init to invalid slider index
  301. nFlexSliderIndex[i] = FLEXSLIDER_INVALID_INDEX;
  302. }
  303. // J is the slider number we're filling in
  304. int j = 0;
  305. for ( LocalFlexController_t k = LocalFlexController_t(0); k < hdr->numflexcontrollers(); k++ )
  306. {
  307. // Lookup global flex controller index
  308. int controller = hdr->pFlexcontroller( k )->localToGlobal;
  309. Assert( controller != -1 );
  310. // Con_Printf( "%i Setting up %s global %i\n", k, hdr->pFlexcontroller(k)->pszName(), controller );
  311. slFlexScale[j]->setLabel( hdr->pFlexcontroller(k)->pszName() );
  312. if ( nFlexSliderIndex[controller] == FLEXSLIDER_INVALID_INDEX )
  313. {
  314. //Con_Printf( "Assigning bar %i to barnum %i of slider %s for controller %i\n",
  315. // j, 0, hdr->pFlexcontroller(k)->pszName(), controller );
  316. nFlexSliderIndex[controller] = j;
  317. nFlexSliderBarnum[controller] = 0;
  318. }
  319. else
  320. {
  321. Assert( 0 );
  322. }
  323. if (hdr->pFlexcontroller(k)->min != hdr->pFlexcontroller(k)->max)
  324. slFlexScale[j]->setRange( 0, hdr->pFlexcontroller(k)->min, hdr->pFlexcontroller(k)->max );
  325. if (strncmp( "right_", hdr->pFlexcontroller(k)->pszName(), 6 ) == 0)
  326. {
  327. if (hdr->pFlexcontroller(k)->min != hdr->pFlexcontroller(k)->max)
  328. slFlexScale[j]->setRange( 1, 0.0f, 1.0f );
  329. slFlexScale[j]->setLabel( &hdr->pFlexcontroller(k)->pszName()[6] );
  330. slFlexScale[j]->SetMode( true );
  331. k++;
  332. controller = hdr->pFlexcontroller( k )->localToGlobal;
  333. Assert( controller != -1 );
  334. if ( nFlexSliderIndex[controller] == FLEXSLIDER_INVALID_INDEX )
  335. {
  336. nFlexSliderIndex[controller] = j;
  337. nFlexSliderBarnum[controller] = 1;
  338. //Con_Printf( "Assigning stereo side of bar %i to barnum %i of slider %s for controller\n",
  339. // j, 1, hdr->pFlexcontroller(k)->pszName(), controller );
  340. }
  341. else
  342. {
  343. Assert(0);
  344. }
  345. }
  346. m_nViewableFlexControllerCount++;
  347. slFlexScale[j]->setVisible( true );
  348. slFlexScale[j]->redraw();
  349. j++;
  350. }
  351. }
  352. slScrollbar->setRange( 0, m_nViewableFlexControllerCount * LINE_HEIGHT + 5 );
  353. int trueh = h2() - GetCaptionHeight();
  354. PositionControls( w2(), h2() );
  355. slScrollbar->setPagesize( trueh );
  356. slScrollbar->setBounds( w2() - 18, GetCaptionHeight(), 18, trueh );
  357. PositionSliders( 0 );
  358. }
  359. void FlexPanel::OnModelChanged()
  360. {
  361. ResetSliders( true, false );
  362. SetEvent( NULL );
  363. redraw();
  364. }
  365. void FlexPanel::SetEvent( CChoreoEvent *event )
  366. {
  367. bool bUpdateSliders = false;
  368. if ( event != NULL )
  369. {
  370. CChoreoScene *scene = event->GetScene();
  371. StudioModel *model = FindAssociatedModel( scene, event->GetActor() );
  372. if (model == models->GetActiveStudioModel())
  373. {
  374. bUpdateSliders = true;
  375. }
  376. }
  377. btnCopyToSliders->setEnabled( bUpdateSliders );
  378. btnCopyFromSliders->setEnabled( bUpdateSliders );
  379. return;
  380. }
  381. bool FlexPanel::IsValidSlider( int iFlexController ) const
  382. {
  383. if ( nFlexSliderIndex[ iFlexController ] == FLEXSLIDER_INVALID_INDEX )
  384. return false;
  385. return true;
  386. }
  387. float
  388. FlexPanel::GetSlider( int iFlexController )
  389. {
  390. if ( !IsValidSlider( iFlexController ) )
  391. {
  392. Msg( "GetSlider(%d) invalid controller index\n", iFlexController );
  393. return 0.0f;
  394. }
  395. return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getValue( nFlexSliderBarnum[ iFlexController ] );
  396. }
  397. float FlexPanel::GetSliderRawValue( int iFlexController )
  398. {
  399. if ( !IsValidSlider( iFlexController ) )
  400. {
  401. Msg( "GetSliderRawValue(%d) invalid controller index\n", iFlexController );
  402. return 0.0f;
  403. }
  404. return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getRawValue( nFlexSliderBarnum[ iFlexController ] );
  405. }
  406. void FlexPanel::GetSliderRange( int iFlexController, float& minvalue, float& maxvalue )
  407. {
  408. int barnum = nFlexSliderBarnum[ iFlexController ];
  409. if ( !IsValidSlider( iFlexController ) )
  410. {
  411. Msg( "GetSliderRange(%d) invalid controller index\n", iFlexController );
  412. minvalue = 0.0f;
  413. maxvalue = 1.0f;
  414. return;
  415. }
  416. mxExpressionSlider *sl = slFlexScale[ nFlexSliderIndex[ iFlexController ] ];
  417. Assert( sl );
  418. minvalue = sl->getMinValue( barnum );
  419. maxvalue = sl->getMaxValue( barnum );
  420. }
  421. void
  422. FlexPanel::SetSlider( int iFlexController, float value )
  423. {
  424. if ( !IsValidSlider( iFlexController ) )
  425. {
  426. Msg( "SetSlider(%d) invalid controller index\n", iFlexController );
  427. return;
  428. }
  429. slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setValue( nFlexSliderBarnum[ iFlexController ], value );
  430. }
  431. float
  432. FlexPanel::GetInfluence( int iFlexController )
  433. {
  434. if ( !IsValidSlider( iFlexController ) )
  435. {
  436. Msg( "GetInfluence(%d) invalid controller index\n", iFlexController );
  437. return 0.0f;
  438. }
  439. return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getInfluence( );
  440. }
  441. void
  442. FlexPanel::SetEdited( int iFlexController, bool isEdited )
  443. {
  444. if ( !IsValidSlider( iFlexController ) )
  445. {
  446. Msg( "IsEdited(%d) invalid controller index\n", iFlexController );
  447. return;
  448. }
  449. slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setEdited( nFlexSliderBarnum[ iFlexController ], isEdited );
  450. }
  451. bool
  452. FlexPanel::IsEdited( int iFlexController )
  453. {
  454. if ( !IsValidSlider( iFlexController ) )
  455. {
  456. Msg( "IsEdited(%d) invalid controller index\n", iFlexController );
  457. return 0.0f;
  458. }
  459. return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->isEdited( nFlexSliderBarnum[ iFlexController ] );
  460. }
  461. void
  462. FlexPanel::SetInfluence( int iFlexController, float value )
  463. {
  464. if ( !IsValidSlider( iFlexController ) )
  465. {
  466. Msg( "SetInfluence(%d) invalid controller index\n", iFlexController );
  467. return;
  468. }
  469. // Con_Printf( "SetInfluence( %d, %.0f ) : %d %d\n", iFlexController, value, nFlexSliderIndex[ iFlexController ], nFlexSliderBarnum[ iFlexController ] );
  470. if ( nFlexSliderBarnum[ iFlexController ] == 0)
  471. {
  472. slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setInfluence( value );
  473. }
  474. }
  475. int
  476. FlexPanel::LookupFlex( int iSlider, int barnum )
  477. {
  478. for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++)
  479. {
  480. if (nFlexSliderIndex[i] == iSlider && nFlexSliderBarnum[i] == barnum)
  481. {
  482. // char const *name = GetGlobalFlexControllerName( i );
  483. //Con_Printf( "lookup slider %i bar %i == %s\n",
  484. //iSlider, barnum, name );
  485. return i;
  486. }
  487. }
  488. Con_Printf( "lookup slider %i bar %i failed\n",
  489. iSlider, barnum);
  490. return 0;
  491. }
  492. int
  493. FlexPanel::LookupPairedFlex( int iFlexController )
  494. {
  495. if ( !IsValidSlider( iFlexController ) )
  496. {
  497. Msg( "LookupPairedFlex(%d) invalid controller index\n", iFlexController );
  498. return iFlexController;
  499. }
  500. if (nFlexSliderBarnum[ iFlexController ] == 1)
  501. {
  502. return iFlexController - 1;
  503. }
  504. else if (nFlexSliderIndex[ iFlexController + 1 ] == nFlexSliderIndex[ iFlexController ])
  505. {
  506. return iFlexController + 1;
  507. }
  508. return iFlexController;
  509. }
  510. void
  511. FlexPanel::setExpression( int index )
  512. {
  513. if ( !models->GetActiveStudioModel() )
  514. return;
  515. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  516. if ( !hdr )
  517. return;
  518. CExpClass *active = expressions->GetActiveClass();
  519. if ( !active )
  520. return;
  521. CExpression *exp = active->GetExpression( index );
  522. if ( !exp )
  523. return;
  524. // Con_Printf( "Setting expression to %i:'%s'\n", index, exp->name );
  525. float *settings = exp->GetSettings();
  526. float *weights = exp->GetWeights();
  527. Assert( settings );
  528. Assert( weights );
  529. for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++)
  530. {
  531. int j = hdr->pFlexcontroller( i )->localToGlobal;
  532. if ( j == -1 )
  533. continue;
  534. //if ( weights[j] > 0.0f )
  535. //{
  536. // Con_Printf( "%i Setting %s to %f\n", j, GetGlobalFlexControllerName( j ),
  537. // settings[ j ] );
  538. //}
  539. SetSlider( j, settings[j] );
  540. SetInfluence( j, weights[j] );
  541. models->GetActiveStudioModel()->SetFlexController( i, settings[j] * weights[j] );
  542. }
  543. }
  544. void FlexPanel::DeleteExpression( int index )
  545. {
  546. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  547. if ( !hdr )
  548. return;
  549. CExpClass *active = expressions->GetActiveClass();
  550. if ( !active )
  551. return;
  552. CExpression *exp = active->GetExpression( index );
  553. if ( !exp )
  554. return;
  555. active->DeleteExpression( exp->name );
  556. }
  557. //-----------------------------------------------------------------------------
  558. // Purpose:
  559. // Input : index -
  560. //-----------------------------------------------------------------------------
  561. void FlexPanel::RevertExpression( int index )
  562. {
  563. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  564. if ( !hdr )
  565. return;
  566. CExpClass *active = expressions->GetActiveClass();
  567. if ( !active )
  568. return;
  569. CExpression *exp = active->GetExpression( index );
  570. if ( !exp )
  571. return;
  572. exp->Revert();
  573. setExpression( index );
  574. g_pExpressionTrayTool->redraw();
  575. }
  576. void FlexPanel::SaveExpression( int index )
  577. {
  578. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  579. if ( !hdr )
  580. return;
  581. CExpClass *active = expressions->GetActiveClass();
  582. if ( !active )
  583. return;
  584. CExpression *exp = active->GetExpression( index );
  585. if ( !exp )
  586. return;
  587. int retval = mxMessageBox( this, "Overwrite existing expression?", g_appTitle, MX_MB_YESNO | MX_MB_QUESTION );
  588. if ( retval != 0 )
  589. return;
  590. float *settings = exp->GetSettings();
  591. float *weights = exp->GetWeights();
  592. Assert( settings );
  593. Assert( weights );
  594. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ )
  595. {
  596. int j = hdr->pFlexcontroller( i )->localToGlobal;
  597. settings[ j ] = GetSlider( j );
  598. weights[ j ] = GetInfluence( j );
  599. }
  600. exp->CreateNewBitmap( models->GetActiveModelIndex() );
  601. exp->ResetUndo();
  602. exp->SetDirty( false );
  603. g_pExpressionTrayTool->redraw();
  604. }
  605. void FlexPanel::CopyControllerSettingsToStructure( CExpression *exp )
  606. {
  607. Assert( exp );
  608. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  609. if ( hdr )
  610. {
  611. float *settings = exp->GetSettings();
  612. float *weights = exp->GetWeights();
  613. for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++)
  614. {
  615. int j = hdr->pFlexcontroller( i )->localToGlobal;
  616. settings[ j ] = GetSlider( j );
  617. weights[ j ] = GetInfluence( j );
  618. }
  619. }
  620. }
  621. void FlexPanel::OnSetAll( int state )
  622. {
  623. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  624. if ( hdr )
  625. {
  626. for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++)
  627. {
  628. int j = hdr->pFlexcontroller( i )->localToGlobal;
  629. float setting = GetSlider( j );
  630. float influence = GetInfluence( j );
  631. switch ( state )
  632. {
  633. default:
  634. Assert( 0 );
  635. break;
  636. case FP_STATE_UNCHECK:
  637. influence = 0.0f;
  638. break;
  639. case FP_STATE_CHECK:
  640. influence = 1.0f;
  641. break;
  642. case FP_STATE_INVERT:
  643. influence = 1.0f - influence;
  644. break;
  645. }
  646. SetInfluence( j, influence );
  647. models->GetActiveStudioModel()->SetFlexController( i, setting * influence );
  648. }
  649. }
  650. }
  651. void FlexPanel::ResetSliders( bool preserveundo, bool bDirtyClass )
  652. {
  653. CExpClass *active = expressions->GetActiveClass();
  654. bool needredo = false;
  655. CExpression zeroes;
  656. CExpression *exp = NULL;
  657. if ( active )
  658. {
  659. int index = active->GetSelectedExpression();
  660. if ( index != -1 )
  661. {
  662. exp = active->GetExpression( index );
  663. if ( exp )
  664. {
  665. float *settings = exp->GetSettings();
  666. Assert( settings );
  667. if ( memcmp( settings, zeroes.GetSettings(), GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ) )
  668. {
  669. if ( preserveundo )
  670. {
  671. exp->PushUndoInformation();
  672. needredo = true;
  673. }
  674. if ( bDirtyClass )
  675. {
  676. active->SetDirty( true );
  677. }
  678. g_pExpressionTrayTool->redraw();
  679. }
  680. }
  681. }
  682. }
  683. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  684. if ( hdr )
  685. {
  686. if( exp )
  687. {
  688. float *settings = exp->GetSettings();
  689. float *weights = exp->GetWeights();
  690. Assert( settings && weights );
  691. for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
  692. {
  693. settings[ i ] = 0.0f;
  694. weights[ i ] = 0.0f;
  695. }
  696. }
  697. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ )
  698. {
  699. int j = hdr->pFlexcontroller( i )->localToGlobal;
  700. if ( j == -1 )
  701. continue;
  702. SetSlider( j, 0.0f );
  703. SetInfluence( j, 0.0f );
  704. SetEdited( j, false );
  705. models->GetActiveStudioModel()->SetFlexController( i, 0.0f );
  706. }
  707. }
  708. if ( exp && needredo && preserveundo )
  709. {
  710. exp->PushRedoInformation();
  711. }
  712. }
  713. void FlexPanel::CopyControllerSettings( void )
  714. {
  715. CExpression *exp = expressions->GetCopyBuffer();
  716. memset( exp, 0, sizeof( *exp ) );
  717. CopyControllerSettingsToStructure( exp );
  718. }
  719. void FlexPanel::PasteControllerSettings( void )
  720. {
  721. CExpClass *active = expressions->GetActiveClass();
  722. if ( !active )
  723. return;
  724. bool needredo = false;
  725. CExpression *paste = expressions->GetCopyBuffer();
  726. if ( !paste )
  727. return;
  728. CExpression *exp = NULL;
  729. int index = active->GetSelectedExpression();
  730. if ( index != -1 )
  731. {
  732. exp = active->GetExpression( index );
  733. if ( exp )
  734. {
  735. float *settings = exp->GetSettings();
  736. Assert( settings );
  737. // UPDATEME
  738. if ( memcmp( settings, paste->GetSettings(), GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ) )
  739. {
  740. exp->PushUndoInformation();
  741. needredo = true;
  742. active->SetDirty( true );
  743. g_pExpressionTrayTool->redraw();
  744. }
  745. }
  746. }
  747. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  748. if ( hdr )
  749. {
  750. float *settings = paste->GetSettings();
  751. float *weights = paste->GetWeights();
  752. Assert( settings );
  753. Assert( weights );
  754. for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++)
  755. {
  756. int j = hdr->pFlexcontroller( i )->localToGlobal;
  757. SetSlider( j, settings[j] );
  758. SetInfluence( j, weights[j] );
  759. models->GetActiveStudioModel()->SetFlexController( i, settings[j] * weights[j] );
  760. }
  761. }
  762. if ( exp && needredo )
  763. {
  764. exp->PushRedoInformation();
  765. }
  766. }
  767. void FlexPanel::EditExpression( void )
  768. {
  769. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  770. if ( !hdr )
  771. {
  772. Con_ErrorPrintf( "Can't edit face pose, must load a model first!\n" );
  773. return;
  774. }
  775. CExpClass *active = expressions->GetActiveClass();
  776. if ( !active )
  777. return;
  778. int index = active->GetSelectedExpression();
  779. if ( index == -1 )
  780. {
  781. Con_ErrorPrintf( "Can't edit face pose, must select a face from list first!\n" );
  782. return;
  783. }
  784. CExpression *exp = active->GetExpression( index );
  785. if ( !exp )
  786. {
  787. return;
  788. }
  789. bool namechanged = false;
  790. CExpressionParams params;
  791. memset( &params, 0, sizeof( params ) );
  792. strcpy( params.m_szDialogTitle, "Edit Expression" );
  793. strcpy( params.m_szName, exp->name );
  794. strcpy( params.m_szDescription, exp->description );
  795. if ( !ExpressionProperties( &params ) )
  796. return;
  797. namechanged = stricmp( exp->name, params.m_szName ) ? true : false;
  798. if ( ( strlen( params.m_szName ) <= 0 ) ||
  799. !stricmp( params.m_szName, "unnamed" ) )
  800. {
  801. Con_ErrorPrintf( "You must type in a valid name\n" );
  802. return;
  803. }
  804. if ( ( strlen( params.m_szDescription ) <= 0 ) ||
  805. !stricmp( params.m_szDescription, "description" ) )
  806. {
  807. Con_ErrorPrintf( "You must type in a valid description\n" );
  808. return;
  809. }
  810. if ( namechanged )
  811. {
  812. Con_Printf( "Deleting old bitmap %s\n", exp->GetBitmapFilename( models->GetActiveModelIndex() ) );
  813. // Remove old bitmap
  814. _unlink( exp->GetBitmapFilename( models->GetActiveModelIndex() ) );
  815. }
  816. strcpy( exp->name, params.m_szName );
  817. strcpy( exp->description, params.m_szDescription );
  818. if ( namechanged )
  819. {
  820. exp->CreateNewBitmap( models->GetActiveModelIndex() );
  821. }
  822. active->SetDirty( true );
  823. g_pExpressionTrayTool->redraw();
  824. }
  825. void FlexPanel::NewExpression( void )
  826. {
  827. CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
  828. if ( !hdr )
  829. {
  830. Con_ErrorPrintf( "Can't create new face pose, must load a model first!\n" );
  831. return;
  832. }
  833. CExpClass *active = expressions->GetActiveClass();
  834. if ( !active )
  835. return;
  836. g_pExpressionTrayTool->Deselect();
  837. CExpressionParams params;
  838. memset( &params, 0, sizeof( params ) );
  839. strcpy( params.m_szDialogTitle, "Add Expression" );
  840. strcpy( params.m_szName, "" );
  841. strcpy( params.m_szDescription, "" );
  842. if ( !ExpressionProperties( &params ) )
  843. return;
  844. if ( ( strlen( params.m_szName ) <= 0 ) ||
  845. !stricmp( params.m_szName, "unnamed" ) )
  846. {
  847. Con_ErrorPrintf( "You must type in a valid name\n" );
  848. return;
  849. }
  850. if ( ( strlen( params.m_szDescription ) <= 0 ) ||
  851. !stricmp( params.m_szDescription, "description" ) )
  852. {
  853. Con_ErrorPrintf( "You must type in a valid description\n" );
  854. return;
  855. }
  856. float settings[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ];
  857. float weights[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ];
  858. memset( settings, 0, sizeof( settings ) );
  859. memset( weights, 0, sizeof( settings ) );
  860. for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ )
  861. {
  862. int j = hdr->pFlexcontroller( i )->localToGlobal;
  863. settings[ j ] = GetSlider( j );
  864. weights[ j ] = GetInfluence( j );
  865. }
  866. active->AddExpression( params.m_szName, params.m_szDescription, settings, weights, true, true );
  867. }
  868. //-----------------------------------------------------------------------------
  869. // Purpose:
  870. // Output : Returns true on success, false on failure.
  871. //-----------------------------------------------------------------------------
  872. bool FlexPanel::PaintBackground( void )
  873. {
  874. redraw();
  875. return false;
  876. }
  877. void FlexPanel::OnMenu()
  878. {
  879. POINT pt;
  880. pt.x = btnMenu->x();
  881. pt.y = btnMenu->y();
  882. pt.y -= 3 * btnMenu->h2();
  883. ScreenToClient( (HWND)getHandle(), &pt );
  884. mxPopupMenu *pop = new mxPopupMenu();
  885. pop->add( "Check All", IDC_FP_CHECK_ALL );
  886. pop->add( "Uncheck All", IDC_FP_UNCHECK_ALL );
  887. pop->add( "Invert Selection", IDC_FP_INVERT );
  888. pop->popup( this, pt.x, pt.y );
  889. }