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

746 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "hlfaceposer.h"
  8. #include "faceposertoolwindow.h"
  9. #include "utlvector.h"
  10. #include "tier1/strtools.h"
  11. #include "MDLViewer.h"
  12. #include "choreowidgetdrawhelper.h"
  13. #include "StudioModel.h"
  14. #include "faceposer_models.h"
  15. extern MDLViewer *g_MDLViewer;
  16. static CUtlVector< IFacePoserToolWindow * > g_Tools;
  17. IFacePoserToolWindow *IFacePoserToolWindow::s_pActiveTool = NULL;
  18. bool IFacePoserToolWindow::s_bToolsCanDraw;
  19. static CUtlVector< IFacePoserToolWindow * > s_NeedRedraw;
  20. IFacePoserToolWindow::IFacePoserToolWindow( char const *toolname, char const *displaynameroot )
  21. {
  22. m_bAutoProcess = false;
  23. m_bUseForMainWindowTitle = false;
  24. SetToolName( toolname );
  25. m_szPrefix[0]=0;
  26. m_szSuffix[0]=0;
  27. SetDisplayNameRoot( displaynameroot );
  28. g_Tools.AddToTail( this );
  29. m_nToolFrameCount = 0;
  30. }
  31. mxWindow *IFacePoserToolWindow::GetMxWindow( void )
  32. {
  33. return dynamic_cast< mxWindow * >( this );
  34. }
  35. IFacePoserToolWindow *IFacePoserToolWindow::GetActiveTool( void )
  36. {
  37. if ( s_pActiveTool )
  38. return s_pActiveTool;
  39. if ( GetToolCount() > 0 )
  40. return GetTool( 0 );
  41. return NULL;
  42. }
  43. void IFacePoserToolWindow::SetActiveTool( IFacePoserToolWindow *tool )
  44. {
  45. if ( tool != s_pActiveTool && s_pActiveTool )
  46. {
  47. InvalidateRect( (HWND)s_pActiveTool->GetMxWindow()->getHandle(), NULL, TRUE );
  48. InvalidateRect( (HWND)tool->GetMxWindow()->getHandle(), NULL, TRUE );
  49. }
  50. s_pActiveTool = tool;
  51. }
  52. void IFacePoserToolWindow::Think( float dt )
  53. {
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose:
  57. // Input : *name -
  58. //-----------------------------------------------------------------------------
  59. void IFacePoserToolWindow::SetToolName( char const *name )
  60. {
  61. Q_strncpy( m_szToolName, name, sizeof( m_szToolName ) );
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose:
  65. // Output : char const
  66. //-----------------------------------------------------------------------------
  67. char const *IFacePoserToolWindow::GetToolName( void ) const
  68. {
  69. return m_szToolName;
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose:
  73. // Input : *name -
  74. //-----------------------------------------------------------------------------
  75. void IFacePoserToolWindow::SetDisplayNameRoot( char const *name )
  76. {
  77. Q_snprintf( m_szDisplayRoot, sizeof( m_szDisplayRoot ), "%s", name );
  78. ComputeNewTitle();
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose:
  82. // Output : char const
  83. //-----------------------------------------------------------------------------
  84. char const *IFacePoserToolWindow::GetDisplayNameRoot( void ) const
  85. {
  86. return m_szDisplayRoot;
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose:
  90. // Input : *suffix -
  91. //-----------------------------------------------------------------------------
  92. void IFacePoserToolWindow::SetSuffix( char const *suffix )
  93. {
  94. Q_snprintf( m_szSuffix, sizeof( m_szSuffix ), "%s", suffix );
  95. ComputeNewTitle();
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose:
  99. // Input : *prefix -
  100. //-----------------------------------------------------------------------------
  101. void IFacePoserToolWindow::SetPrefix( char const *prefix )
  102. {
  103. Q_snprintf( m_szPrefix, sizeof( m_szPrefix ), "%s", prefix );
  104. ComputeNewTitle();
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose:
  108. // Output : char const
  109. //-----------------------------------------------------------------------------
  110. char const *IFacePoserToolWindow::GetWindowTitle( void ) const
  111. {
  112. return m_szWindowTitle;
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Purpose:
  116. // Input : use -
  117. //-----------------------------------------------------------------------------
  118. void IFacePoserToolWindow::SetUseForMainWindowTitle( bool use )
  119. {
  120. m_bUseForMainWindowTitle = use;
  121. if ( use )
  122. {
  123. g_MDLViewer->setLabel( m_szWindowTitle );
  124. }
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Purpose:
  128. //-----------------------------------------------------------------------------
  129. void IFacePoserToolWindow::ComputeNewTitle( void )
  130. {
  131. Q_snprintf( m_szWindowTitle, sizeof( m_szWindowTitle ), "%s%s%s", m_szPrefix, m_szDisplayRoot, m_szSuffix );
  132. if ( GetMxWindow() )
  133. {
  134. GetMxWindow()->setLabel( m_szWindowTitle );
  135. }
  136. if ( !m_bUseForMainWindowTitle )
  137. return;
  138. g_MDLViewer->setLabel( m_szWindowTitle );
  139. }
  140. IFacePoserToolWindow::~IFacePoserToolWindow( void )
  141. {
  142. g_Tools.FindAndRemove( this );
  143. }
  144. struct ToolTranslate
  145. {
  146. char const *toolname;
  147. float xfrac;
  148. float yfrac;
  149. float wfrac;
  150. float hfrac;
  151. bool locked;
  152. };
  153. static ToolTranslate s_ToolTranslate[]=
  154. {
  155. { "3D View", 0.0, 0.0, 0.4, 0.5, false },
  156. { "ControlPanel", 0.4, 0.0, 0.2, 0.25, false },
  157. { "FlexPanel", 0.6, 0.0, 0.4, 0.25, false },
  158. { "RampTool", 0.4, 0.25, 0.6, 0.25, false },
  159. { "CChoreoView", 0.0, 0.5, 1.0, 0.45, false },
  160. // { "Status Window", 0.0, 0.85, 1.0, 0.15, false },
  161. };
  162. static bool TranslateToolPos( char const *toolname, int workspacew, int workspaceh, int& x, int& y, int &w, int &h, bool& locked )
  163. {
  164. int c = ARRAYSIZE( s_ToolTranslate );
  165. for ( int i = 0; i < c; ++i )
  166. {
  167. ToolTranslate& tt = s_ToolTranslate[ i ];
  168. if ( !Q_stricmp( toolname, tt.toolname ) )
  169. {
  170. x = (int)((float)workspacew * tt.xfrac + 0.5f );
  171. y = (int)((float)workspaceh * tt.yfrac + 0.5f );
  172. w = (int)((float)workspacew * tt.wfrac + 0.5f );
  173. h = (int)((float)workspaceh * tt.hfrac + 0.5f );
  174. locked = tt.locked;
  175. return true;
  176. }
  177. }
  178. return false;
  179. }
  180. static int s_nToolCount = 0;
  181. void IFacePoserToolWindow::LoadPosition( void )
  182. {
  183. bool visible;
  184. bool locked;
  185. bool zoomed;
  186. int x, y, w, h;
  187. FacePoser_LoadWindowPositions( GetToolName(), visible, x, y, w, h, locked, zoomed );
  188. if ( w == 0 || h == 0 )
  189. {
  190. int idx = g_Tools.Find( this );
  191. Assert( idx != g_Tools.InvalidIndex() );
  192. if ( idx == 0 )
  193. {
  194. s_nToolCount = 0;
  195. }
  196. zoomed = false;
  197. locked = false;
  198. visible = true;
  199. // Just do a simple tiling
  200. w = g_MDLViewer->w2() * 0.5;
  201. h = g_MDLViewer->h2() * 0.5;
  202. x = g_MDLViewer->w2() * 0.25f + s_nToolCount * 20;
  203. y = s_nToolCount * 20;
  204. bool translated = TranslateToolPos
  205. (
  206. GetToolName(),
  207. g_MDLViewer->w2(),
  208. g_MDLViewer->h2(),
  209. x,
  210. y,
  211. w,
  212. h,
  213. locked
  214. );
  215. if ( !translated )
  216. {
  217. ++s_nToolCount;
  218. visible = false;
  219. }
  220. }
  221. GetMxWindow()->setBounds( x, y, w, h );
  222. if ( locked ^ IsLocked() )
  223. {
  224. ToggleLockedState();
  225. }
  226. GetMxWindow()->setVisible( visible );
  227. }
  228. void IFacePoserToolWindow::SavePosition( void )
  229. {
  230. bool visible;
  231. int xpos, ypos, width, height;
  232. visible = GetMxWindow()->isVisible();
  233. xpos = GetMxWindow()->x();
  234. ypos = GetMxWindow()->y();
  235. width = GetMxWindow()->w();
  236. height = GetMxWindow()->h();
  237. // xpos and ypos are screen space
  238. POINT pt;
  239. pt.x = xpos;
  240. pt.y = ypos;
  241. // Convert from screen space to relative to client area of parent window so
  242. // the setBounds == MoveWindow call will offset to the same location
  243. if ( GetMxWindow()->getParent() )
  244. {
  245. ScreenToClient( (HWND)GetMxWindow()->getParent()->getHandle(), &pt );
  246. xpos = (short)pt.x;
  247. ypos = (short)pt.y;
  248. }
  249. FacePoser_SaveWindowPositions( GetToolName(), visible, xpos, ypos, width, height, IsLocked(), false );
  250. }
  251. int IFacePoserToolWindow::GetToolCount( void )
  252. {
  253. return g_Tools.Count();
  254. }
  255. IFacePoserToolWindow *IFacePoserToolWindow::GetTool( int index )
  256. {
  257. return g_Tools[ index ];
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose:
  261. //-----------------------------------------------------------------------------
  262. void IFacePoserToolWindow::InitTools( void )
  263. {
  264. int c = GetToolCount();
  265. int i;
  266. for ( i = 0; i < c ; i++ )
  267. {
  268. IFacePoserToolWindow *tool = GetTool( i );
  269. FacePoser_MakeToolWindow( tool->GetMxWindow(), true );
  270. tool->GetMxWindow()->setLabel( tool->GetWindowTitle() );
  271. }
  272. }
  273. void IFacePoserToolWindow::ShutdownTools( void )
  274. {
  275. int c = GetToolCount();
  276. int i;
  277. for ( i = 0; i < c ; i++ )
  278. {
  279. IFacePoserToolWindow *tool = GetTool( i );
  280. tool->Shutdown();
  281. }
  282. }
  283. //-----------------------------------------------------------------------------
  284. // Purpose:
  285. // Input : dt -
  286. //-----------------------------------------------------------------------------
  287. void IFacePoserToolWindow::ToolThink( float dt )
  288. {
  289. int c = GetToolCount();
  290. int i;
  291. for ( i = 0; i < c ; i++ )
  292. {
  293. IFacePoserToolWindow *tool = GetTool( i );
  294. tool->Think( dt );
  295. }
  296. // Don't self animate, all animation driven by thinking of various tools now
  297. if ( !ShouldAutoProcess() )
  298. {
  299. c = models->Count();
  300. for ( i = 0; i < c; i++ )
  301. {
  302. StudioModel *m = models->GetStudioModel( i );
  303. if ( m )
  304. {
  305. m->AdvanceFrame ( dt );
  306. }
  307. }
  308. }
  309. }
  310. bool IFacePoserToolWindow::IsLocked( void )
  311. {
  312. mxWindow *w = GetMxWindow();
  313. if ( !w )
  314. return false;
  315. return !FacePoser_HasWindowStyle( w, WS_SYSMENU );
  316. }
  317. void IFacePoserToolWindow::ToggleLockedState( void )
  318. {
  319. mxWindow *w = GetMxWindow();
  320. if ( !w )
  321. return;
  322. bool visible = w->isVisible();
  323. bool islocked = IsLocked();
  324. if ( islocked )
  325. {
  326. FacePoser_MakeToolWindow( w, true );
  327. }
  328. else
  329. {
  330. FacePoser_RemoveWindowStyle( w, WS_OVERLAPPEDWINDOW );
  331. FacePoser_AddWindowExStyle( w, WS_EX_OVERLAPPEDWINDOW );
  332. }
  333. w->setVisible( false );
  334. // If visible, force it to redraw, etc.
  335. if ( visible )
  336. {
  337. w->setVisible( true );
  338. }
  339. }
  340. #define LOCK_INSET 2
  341. #define LOCK_SIZE 8
  342. void IFacePoserToolWindow:: GetLockRect( RECT& rc )
  343. {
  344. mxWindow *w = GetMxWindow();
  345. Assert( w );
  346. if ( !w )
  347. return;
  348. GetCloseRect( rc );
  349. OffsetRect( &rc, - ( LOCK_SIZE + 2 * LOCK_INSET ), 0 );
  350. }
  351. void IFacePoserToolWindow::GetCloseRect( RECT& rc )
  352. {
  353. mxWindow *w = GetMxWindow();
  354. Assert( w );
  355. if ( !w )
  356. return;
  357. rc.right = w->w2() - LOCK_INSET;
  358. rc.left = rc.right - LOCK_SIZE;
  359. rc.top = LOCK_INSET;
  360. rc.bottom = rc.top + LOCK_SIZE;
  361. }
  362. bool IFacePoserToolWindow::HandleToolEvent( mxEvent *event )
  363. {
  364. bool handled = false;
  365. switch ( event->event )
  366. {
  367. default:
  368. break;
  369. case mxEvent::Close:
  370. {
  371. g_MDLViewer->UpdateWindowMenu();
  372. handled = true;
  373. }
  374. break;
  375. case mxEvent::ParentNotify:
  376. {
  377. mxWindow *w = GetMxWindow();
  378. if ( w )
  379. {
  380. HWND wnd = (HWND)w->getHandle();
  381. SetFocus( wnd );
  382. SetWindowPos( wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  383. SetActiveTool( this );
  384. }
  385. handled = true;
  386. }
  387. break;
  388. case mxEvent::PosChanged:
  389. {
  390. SetActiveTool( this );
  391. mxWindow *w = GetMxWindow();
  392. if ( w )
  393. {
  394. SetFocus( (HWND)w->getHandle() );
  395. }
  396. handled = true;
  397. }
  398. break;
  399. case mxEvent::MouseDown:
  400. case mxEvent::MouseUp:
  401. {
  402. bool isup = event->event == mxEvent::MouseUp;
  403. mxWindow *w = GetMxWindow();
  404. if ( !isup && w )
  405. {
  406. SetFocus( (HWND)w->getHandle() );
  407. SetWindowPos( (HWND)w->getHandle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  408. SetActiveTool( this );
  409. }
  410. if ( w && IsLocked() )
  411. {
  412. RECT captionRect;
  413. captionRect.left = 0;
  414. captionRect.right = w->w2();
  415. captionRect.top = 0;
  416. captionRect.bottom = GetCaptionHeight();
  417. POINT pt;
  418. pt.x = (short)event->x;
  419. pt.y = (short)event->y;
  420. if ( PtInRect( &captionRect, pt ) )
  421. {
  422. handled = !isup;
  423. // Right button anywhere
  424. if ( event->buttons & mxEvent::MouseRightButton )
  425. {
  426. if ( isup )
  427. {
  428. ToggleLockedState();
  429. }
  430. }
  431. // Left button on lock icon
  432. RECT lockRect, closeRect;
  433. GetLockRect( lockRect );
  434. GetCloseRect( closeRect );
  435. if ( PtInRect( &lockRect, pt ) )
  436. {
  437. if ( isup )
  438. {
  439. ToggleLockedState();
  440. }
  441. }
  442. if ( PtInRect( &closeRect, pt ) )
  443. {
  444. if ( isup )
  445. {
  446. w->setVisible( !w->isVisible() );
  447. g_MDLViewer->UpdateWindowMenu();
  448. }
  449. }
  450. }
  451. }
  452. }
  453. break;
  454. case mxEvent::NCMouseUp:
  455. {
  456. if ( event->buttons & mxEvent::MouseRightButton )
  457. {
  458. ToggleLockedState();
  459. handled = true;
  460. }
  461. }
  462. break;
  463. case mxEvent::NCMouseDown:
  464. case mxEvent::Focus:
  465. {
  466. SetActiveTool( this );
  467. // don't mark handled = true, do this passively
  468. }
  469. break;
  470. }
  471. return handled;
  472. }
  473. void IFacePoserToolWindow::HandleToolRedraw( CChoreoWidgetDrawHelper& helper )
  474. {
  475. if ( !IsLocked() )
  476. return;
  477. mxWindow *w = GetMxWindow();
  478. if ( !w )
  479. return;
  480. ++m_nToolFrameCount;
  481. RECT lockRect, closeRect;
  482. GetLockRect( lockRect );
  483. GetCloseRect( closeRect );
  484. RECT captionRect;
  485. helper.GetClientRect( captionRect );
  486. RECT rcClient = captionRect;
  487. captionRect.bottom = captionRect.top + LOCK_SIZE + 2 * LOCK_INSET;
  488. COLORREF textColor = GetSysColor( COLOR_MENUTEXT ); //GetSysColor( COLOR_INACTIVECAPTIONTEXT );
  489. if ( IsActiveTool() )
  490. {
  491. helper.DrawFilledRect( GetSysColor( COLOR_ACTIVECAPTION ), captionRect );
  492. }
  493. else
  494. {
  495. helper.DrawFilledRect( GetSysColor( COLOR_INACTIVECAPTION ), captionRect );
  496. }
  497. captionRect.top += 1;
  498. InflateRect( &captionRect, -LOCK_INSET, 0 );
  499. helper.DrawColoredText( "Small Fonts", 9, FW_NORMAL, textColor, captionRect,
  500. GetWindowTitle() );
  501. //RECT rcFrame = captionRect;
  502. //rcFrame.left = rcFrame.right - 50;
  503. //rcFrame.right = rcFrame.left + 30;
  504. // helper.DrawColoredText( "Small Fonts", 9, FW_NORMAL, textColor, rcFrame, va( "%i", m_nToolFrameCount ) );
  505. lockRect.bottom++;
  506. OffsetRect( &lockRect, 1, 1 );
  507. helper.DrawColoredTextCharset( "Marlett", 8, FW_NORMAL, SYMBOL_CHARSET, textColor, lockRect, "v" );
  508. closeRect.bottom++;
  509. helper.DrawOutlinedRect( textColor, PS_SOLID, 1, closeRect );
  510. OffsetRect( &closeRect, 1, 1 );
  511. helper.DrawColoredTextCharset( "Marlett", 8, FW_NORMAL, SYMBOL_CHARSET, textColor, closeRect, "r" );
  512. rcClient.top += captionRect.bottom;
  513. helper.StartClipping( rcClient );
  514. }
  515. int IFacePoserToolWindow::GetCaptionHeight( void )
  516. {
  517. if ( !IsLocked() )
  518. return 0;
  519. return LOCK_SIZE + 2 * LOCK_INSET;
  520. }
  521. //-----------------------------------------------------------------------------
  522. // Purpose:
  523. // Input : autoprocess -
  524. //-----------------------------------------------------------------------------
  525. void IFacePoserToolWindow::SetAutoProcess( bool autoprocess )
  526. {
  527. m_bAutoProcess = autoprocess;
  528. }
  529. //-----------------------------------------------------------------------------
  530. // Purpose:
  531. // Output : Returns true on success, false on failure.
  532. //-----------------------------------------------------------------------------
  533. bool IFacePoserToolWindow::GetAutoProcess( void ) const
  534. {
  535. return m_bAutoProcess;
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. // Output : Returns true on success, false on failure.
  540. //-----------------------------------------------------------------------------
  541. bool IFacePoserToolWindow::IsActiveTool( void )
  542. {
  543. if ( this == s_pActiveTool )
  544. return true;
  545. return false;
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Purpose:
  549. // Output : Returns true on success, false on failure.
  550. //-----------------------------------------------------------------------------
  551. bool IFacePoserToolWindow::IsAnyToolScrubbing( void )
  552. {
  553. int c = GetToolCount();
  554. int i;
  555. for ( i = 0; i < c ; i++ )
  556. {
  557. IFacePoserToolWindow *tool = GetTool( i );
  558. if ( tool->IsScrubbing() )
  559. return true;
  560. }
  561. return false;
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Purpose:
  565. // Output : Returns true on success, false on failure.
  566. //-----------------------------------------------------------------------------
  567. bool IFacePoserToolWindow::IsAnyToolProcessing( void )
  568. {
  569. int c = GetToolCount();
  570. int i;
  571. for ( i = 0; i < c ; i++ )
  572. {
  573. IFacePoserToolWindow *tool = GetTool( i );
  574. if ( tool->IsProcessing() )
  575. return true;
  576. }
  577. return false;
  578. }
  579. //-----------------------------------------------------------------------------
  580. // Purpose:
  581. // Output : Returns true on success, false on failure.
  582. //-----------------------------------------------------------------------------
  583. bool IFacePoserToolWindow::ShouldAutoProcess( void )
  584. {
  585. IFacePoserToolWindow *tool = GetActiveTool();
  586. if ( !tool )
  587. return false;
  588. return tool->GetAutoProcess();
  589. }
  590. void IFacePoserToolWindow::EnableToolRedraw( bool enabled )
  591. {
  592. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  593. s_bToolsCanDraw = enabled;
  594. if ( s_bToolsCanDraw )
  595. {
  596. int c = s_NeedRedraw.Count();
  597. int i;
  598. for ( i = 0; i < c; i++ )
  599. {
  600. IFacePoserToolWindow *tool = s_NeedRedraw[ i ];
  601. tool->GetMxWindow()->redraw();
  602. }
  603. s_NeedRedraw.Purge();
  604. }
  605. }
  606. bool IFacePoserToolWindow::ToolCanDraw()
  607. {
  608. if ( !s_bToolsCanDraw )
  609. {
  610. if ( s_NeedRedraw.Find( this ) == s_NeedRedraw.InvalidIndex() )
  611. {
  612. s_NeedRedraw.AddToTail( this );
  613. }
  614. return false;
  615. }
  616. return true;
  617. }
  618. void IFacePoserToolWindow::OnModelChanged()
  619. {
  620. }
  621. void IFacePoserToolWindow::ModelChanged()
  622. {
  623. int c = GetToolCount();
  624. int i;
  625. for ( i = 0; i < c ; i++ )
  626. {
  627. IFacePoserToolWindow *tool = GetTool( i );
  628. tool->OnModelChanged();
  629. }
  630. }