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.

2379 lines
52 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include <stdio.h>
  9. #include "hlfaceposer.h"
  10. #include "RampTool.h"
  11. #include "mdlviewer.h"
  12. #include "choreowidgetdrawhelper.h"
  13. #include "TimelineItem.h"
  14. #include "expressions.h"
  15. #include "expclass.h"
  16. #include "choreoevent.h"
  17. #include "StudioModel.h"
  18. #include "choreoscene.h"
  19. #include "choreoactor.h"
  20. #include "choreochannel.h"
  21. #include "ChoreoView.h"
  22. #include "InputProperties.h"
  23. #include "ControlPanel.h"
  24. #include "FlexPanel.h"
  25. #include "mxExpressionTray.h"
  26. #include "ExpressionProperties.h"
  27. #include "tier1/strtools.h"
  28. #include "faceposer_models.h"
  29. #include "UtlBuffer.h"
  30. #include "filesystem.h"
  31. #include "iscenetokenprocessor.h"
  32. #include "choreoviewcolors.h"
  33. #include "MatSysWin.h"
  34. #include "curveeditorhelpers.h"
  35. #include "EdgeProperties.h"
  36. RampTool *g_pRampTool = 0;
  37. #define TRAY_HEIGHT 20
  38. #define TRAY_ITEM_INSET 10
  39. #define TAG_TOP ( TRAY_HEIGHT + 12 )
  40. #define TAG_BOTTOM ( TAG_TOP + 20 )
  41. #define MAX_TIME_ZOOM 1000
  42. // 10% per step
  43. #define TIME_ZOOM_STEP 2
  44. RampTool::RampTool( mxWindow *parent )
  45. : IFacePoserToolWindow( "RampTool", "Ramp" ), mxWindow( parent, 0, 0, 0, 0 )
  46. {
  47. m_pHelper = new CCurveEditorHelper< RampTool >( this );
  48. m_bSuppressLayout = false;
  49. SetAutoProcess( true );
  50. m_nFocusEventGlobalID = -1;
  51. m_flScrub = 0.0f;
  52. m_flScrubTarget = 0.0f;
  53. m_nDragType = DRAGTYPE_NONE;
  54. m_nClickedX = 0;
  55. m_nClickedY = 0;
  56. m_hPrevCursor = 0;
  57. m_nStartX = 0;
  58. m_nStartY = 0;
  59. m_pLastEvent = NULL;
  60. m_nMousePos[ 0 ] = m_nMousePos[ 1 ] = 0;
  61. m_nMinX = 0;
  62. m_nMaxX = 0;
  63. m_bUseBounds = false;
  64. m_bLayoutIsValid = false;
  65. m_flPixelsPerSecond = 500.0f;
  66. m_flLastDuration = 0.0f;
  67. m_nScrollbarHeight = 12;
  68. m_flLeftOffset = 0.0f;
  69. m_nLastHPixelsNeeded = -1;
  70. m_pHorzScrollBar = new mxScrollbar( this, 0, 0, 18, 100, IDC_RAMPHSCROLL, mxScrollbar::Horizontal );
  71. m_pHorzScrollBar->setVisible( false );
  72. m_bInSetEvent = false;
  73. m_flScrubberTimeOffset = 0.0f;
  74. m_nUndoSetup = 0;
  75. }
  76. RampTool::~RampTool( void )
  77. {
  78. delete m_pHelper;
  79. }
  80. void RampTool::SetEvent( CChoreoEvent *event )
  81. {
  82. if ( m_bInSetEvent )
  83. return;
  84. m_bInSetEvent = true;
  85. if ( event == m_pLastEvent )
  86. {
  87. if ( event )
  88. {
  89. if ( event->GetDuration() != m_flLastDuration )
  90. {
  91. m_flLastDuration = event->GetDuration();
  92. m_nLastHPixelsNeeded = -1;
  93. m_flLeftOffset = 0.0f;
  94. InvalidateLayout();
  95. }
  96. m_nFocusEventGlobalID = event->GetGlobalID();
  97. }
  98. m_bInSetEvent = false;
  99. return;
  100. }
  101. m_pLastEvent = event;
  102. m_nFocusEventGlobalID = -1;
  103. if ( event )
  104. {
  105. m_nFocusEventGlobalID = event->GetGlobalID();
  106. }
  107. if ( event )
  108. {
  109. m_flLastDuration = event->GetDuration();
  110. }
  111. else
  112. {
  113. m_flLastDuration = 0.0f;
  114. }
  115. m_flLeftOffset = 0.0f;
  116. m_nLastHPixelsNeeded = -1;
  117. InvalidateLayout();
  118. m_bInSetEvent = false;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. //-----------------------------------------------------------------------------
  123. CChoreoEvent *RampTool::GetSafeEvent( void )
  124. {
  125. if ( m_nFocusEventGlobalID == -1 )
  126. return NULL;
  127. if ( !g_pChoreoView )
  128. return NULL;
  129. CChoreoScene *scene = g_pChoreoView->GetScene();
  130. if ( !scene )
  131. return NULL;
  132. // Find event by name
  133. for ( int i = 0; i < scene->GetNumEvents() ; i++ )
  134. {
  135. CChoreoEvent *e = scene->GetEvent( i );
  136. if ( !e || !e->HasEndTime() )
  137. continue;
  138. if ( e->GetGlobalID() == m_nFocusEventGlobalID )
  139. {
  140. return e;
  141. }
  142. }
  143. return NULL;
  144. }
  145. //-----------------------------------------------------------------------------
  146. // Purpose:
  147. // Input : rcHandle -
  148. //-----------------------------------------------------------------------------
  149. void RampTool::GetScrubHandleRect( RECT& rcHandle, float scrub, bool clipped )
  150. {
  151. float pixel = 0.0f;
  152. if ( w2() > 0 )
  153. {
  154. pixel = GetPixelForTimeValue( scrub );
  155. if ( clipped )
  156. {
  157. pixel = clamp( pixel, SCRUBBER_HANDLE_WIDTH / 2, w2() - SCRUBBER_HANDLE_WIDTH / 2 );
  158. }
  159. }
  160. rcHandle.left = pixel- SCRUBBER_HANDLE_WIDTH / 2;
  161. rcHandle.right = pixel + SCRUBBER_HANDLE_WIDTH / 2;
  162. rcHandle.top = 2 + GetCaptionHeight();
  163. rcHandle.bottom = rcHandle.top + SCRUBBER_HANDLE_HEIGHT;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Purpose:
  167. // Input : drawHelper -
  168. // rcHandle -
  169. //-----------------------------------------------------------------------------
  170. void RampTool::DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper, RECT& rcHandle, float scrub, bool reference )
  171. {
  172. HBRUSH br = CreateSolidBrush( reference ? RGB( 150, 0, 0 ) : RGB( 0, 150, 100 ) );
  173. COLORREF areaBorder = RGB( 230, 230, 220 );
  174. drawHelper.DrawColoredLine( areaBorder,
  175. PS_SOLID, 1, 0, rcHandle.top, w2(), rcHandle.top );
  176. drawHelper.DrawColoredLine( areaBorder,
  177. PS_SOLID, 1, 0, rcHandle.bottom, w2(), rcHandle.bottom );
  178. drawHelper.DrawFilledRect( br, rcHandle );
  179. //
  180. char sz[ 32 ];
  181. sprintf( sz, "%.3f", scrub );
  182. CChoreoEvent *ev = GetSafeEvent();
  183. if ( ev )
  184. {
  185. float st, ed;
  186. st = ev->GetStartTime();
  187. ed = ev->GetEndTime();
  188. float dt = ed - st;
  189. if ( dt > 0.0f )
  190. {
  191. sprintf( sz, "%.3f", st + scrub );
  192. }
  193. }
  194. int len = drawHelper.CalcTextWidth( "Arial", 9, 500, sz );
  195. RECT rcText = rcHandle;
  196. int textw = rcText.right - rcText.left;
  197. rcText.left += ( textw - len ) / 2;
  198. drawHelper.DrawColoredText( "Arial", 9, 500, RGB( 255, 255, 255 ), rcText, sz );
  199. DeleteObject( br );
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Purpose:
  203. // Input : *event -
  204. // Output : Returns true on success, false on failure.
  205. //-----------------------------------------------------------------------------
  206. bool RampTool::IsMouseOverScrubHandle( mxEvent *event )
  207. {
  208. RECT rcHandle;
  209. GetScrubHandleRect( rcHandle, m_flScrub, true );
  210. InflateRect( &rcHandle, 2, 2 );
  211. POINT pt;
  212. pt.x = (short)event->x;
  213. pt.y = (short)event->y;
  214. if ( PtInRect( &rcHandle, pt ) )
  215. {
  216. return true;
  217. }
  218. return false;
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. // Output : Returns true on success, false on failure.
  223. //-----------------------------------------------------------------------------
  224. bool RampTool::IsProcessing( void )
  225. {
  226. if ( !GetSafeEvent() )
  227. return false;
  228. if ( m_flScrub != m_flScrubTarget )
  229. return true;
  230. return false;
  231. }
  232. bool RampTool::IsScrubbing( void ) const
  233. {
  234. bool scrubbing = ( m_nDragType == DRAGTYPE_SCRUBBER ) ? true : false;
  235. return scrubbing;
  236. }
  237. void RampTool::SetScrubTime( float t )
  238. {
  239. m_flScrub = t;
  240. CChoreoEvent *e = GetSafeEvent();
  241. if ( e && e->GetDuration() )
  242. {
  243. float realtime = e->GetStartTime() + m_flScrub;
  244. g_pChoreoView->SetScrubTime( realtime );
  245. g_pChoreoView->DrawScrubHandle();
  246. }
  247. }
  248. void RampTool::SetScrubTargetTime( float t )
  249. {
  250. m_flScrubTarget = t;
  251. CChoreoEvent *e = GetSafeEvent();
  252. if ( e && e->GetDuration() )
  253. {
  254. float realtime = e->GetStartTime() + m_flScrubTarget;
  255. g_pChoreoView->SetScrubTargetTime( realtime );
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. // Input : dt -
  261. //-----------------------------------------------------------------------------
  262. void RampTool::Think( float dt )
  263. {
  264. CChoreoEvent *event = GetSafeEvent();
  265. if ( !event )
  266. return;
  267. bool scrubbing = IsScrubbing();
  268. ScrubThink( dt, scrubbing );
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose:
  272. // Input : dt -
  273. //-----------------------------------------------------------------------------
  274. void RampTool::ScrubThink( float dt, bool scrubbing )
  275. {
  276. CChoreoEvent *event = GetSafeEvent();
  277. if ( !event )
  278. return;
  279. if ( m_flScrubTarget == m_flScrub && !scrubbing )
  280. return;
  281. float d = m_flScrubTarget - m_flScrub;
  282. int sign = d > 0.0f ? 1 : -1;
  283. float maxmove = dt;
  284. if ( sign > 0 )
  285. {
  286. if ( d < maxmove )
  287. {
  288. SetScrubTime( m_flScrubTarget );
  289. }
  290. else
  291. {
  292. SetScrubTime( m_flScrub + maxmove );
  293. }
  294. }
  295. else
  296. {
  297. if ( -d < maxmove )
  298. {
  299. SetScrubTime( m_flScrubTarget );
  300. }
  301. else
  302. {
  303. SetScrubTime( m_flScrub - maxmove );
  304. }
  305. }
  306. if ( scrubbing )
  307. {
  308. g_pMatSysWindow->Frame();
  309. }
  310. }
  311. void RampTool::DrawScrubHandles()
  312. {
  313. RECT rcTray;
  314. RECT rcHandle;
  315. GetScrubHandleRect( rcHandle, m_flScrub, true );
  316. rcTray = rcHandle;
  317. rcTray.left = 0;
  318. rcTray.right = w2();
  319. CChoreoWidgetDrawHelper drawHelper( this, rcTray );
  320. DrawScrubHandle( drawHelper, rcHandle, m_flScrub, false );
  321. }
  322. void RampTool::redraw()
  323. {
  324. if ( !ToolCanDraw() )
  325. return;
  326. CChoreoWidgetDrawHelper drawHelper( this );
  327. HandleToolRedraw( drawHelper );
  328. RECT rc;
  329. drawHelper.GetClientRect( rc );
  330. CChoreoEvent *ev = GetSafeEvent();
  331. if ( ev )
  332. {
  333. RECT rcText;
  334. drawHelper.GetClientRect( rcText );
  335. rcText.top += GetCaptionHeight()+1;
  336. rcText.bottom = rcText.top + 13;
  337. rcText.left += 5;
  338. rcText.right -= 5;
  339. OffsetRect( &rcText, 0, 12 );
  340. int current, total;
  341. g_pChoreoView->GetUndoLevels( current, total );
  342. if ( total > 0 )
  343. {
  344. RECT rcUndo = rcText;
  345. OffsetRect( &rcUndo, 0, 2 );
  346. drawHelper.DrawColoredText( "Small Fonts", 8, FW_NORMAL, RGB( 0, 100, 0 ), rcUndo,
  347. "Undo: %i/%i", current, total );
  348. }
  349. rcText.left += 60;
  350. // Found it, write out description
  351. //
  352. RECT rcTextLine = rcText;
  353. drawHelper.DrawColoredText( "Arial", 11, 900, RGB( 200, 0, 0 ), rcTextLine,
  354. "Event: %s",
  355. ev->GetName() );
  356. RECT rcTimeLine;
  357. drawHelper.GetClientRect( rcTimeLine );
  358. rcTimeLine.left = 0;
  359. rcTimeLine.right = w2();
  360. rcTimeLine.top += ( GetCaptionHeight() + 50 );
  361. float lefttime = GetTimeValueForMouse( 0 );
  362. float righttime = GetTimeValueForMouse( w2() );
  363. DrawTimeLine( drawHelper, rcTimeLine, lefttime, righttime );
  364. OffsetRect( &rcText, 0, 28 );
  365. rcText.left = 5;
  366. RECT timeRect = rcText;
  367. timeRect.right = timeRect.left + 100;
  368. char sz[ 32 ];
  369. Q_snprintf( sz, sizeof( sz ), "%.2f", lefttime + ev->GetStartTime() );
  370. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 0, 0 ), timeRect, sz );
  371. timeRect = rcText;
  372. Q_snprintf( sz, sizeof( sz ), "%.2f", righttime + ev->GetStartTime() );
  373. int textW = drawHelper.CalcTextWidth( "Arial", 9, FW_NORMAL, sz );
  374. timeRect.right = w2() - 10;
  375. timeRect.left = timeRect.right - textW;
  376. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 0, 0 ), timeRect, sz );
  377. }
  378. RECT rcHandle;
  379. GetScrubHandleRect( rcHandle, m_flScrub, true );
  380. DrawScrubHandle( drawHelper, rcHandle, m_flScrub, false );
  381. RECT rcSamples;
  382. GetSampleTrayRect( rcSamples );
  383. DrawSamples( drawHelper, rcSamples );
  384. DrawEventEnd( drawHelper );
  385. RECT rcTags = rc;
  386. rcTags.top = TAG_TOP + GetCaptionHeight();
  387. rcTags.bottom = TAG_BOTTOM + GetCaptionHeight();
  388. DrawTimingTags( drawHelper, rcTags );
  389. RECT rcPos;
  390. GetMouseOverPosRect( rcPos );
  391. DrawMouseOverPos( drawHelper, rcPos );
  392. }
  393. //-----------------------------------------------------------------------------
  394. // Purpose:
  395. //-----------------------------------------------------------------------------
  396. void RampTool::ShowContextMenu( mxEvent *event, bool include_track_menus )
  397. {
  398. // Construct main menu
  399. mxPopupMenu *pop = new mxPopupMenu();
  400. int current, total;
  401. g_pChoreoView->GetUndoLevels( current, total );
  402. if ( total > 0 )
  403. {
  404. if ( current > 0 )
  405. {
  406. pop->add( va( "Undo %s", g_pChoreoView->GetUndoDescription() ), IDC_UNDO_RT );
  407. }
  408. if ( current <= total - 1 )
  409. {
  410. pop->add( va( "Redo %s", g_pChoreoView->GetRedoDescription() ), IDC_REDO_RT );
  411. }
  412. pop->addSeparator();
  413. }
  414. CChoreoEvent *e = GetSafeEvent();
  415. if ( e )
  416. {
  417. if ( CountSelected() > 0 )
  418. {
  419. pop->add( va( "Delete" ), IDC_RT_DELETE );
  420. pop->add( "Deselect all", IDC_RT_DESELECT );
  421. }
  422. pop->add( "Select all", IDC_RT_SELECTALL );
  423. }
  424. pop->add( va( "Change scale..." ), IDC_RT_CHANGESCALE );
  425. pop->addSeparator();
  426. pop->add( "Edge Properties...", IDC_RT_EDGEPROPERTIES );
  427. pop->popup( this, (short)event->x, (short)event->y );
  428. }
  429. void RampTool::GetWorkspaceLeftRight( int& left, int& right )
  430. {
  431. left = 0;
  432. right = w2();
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Purpose:
  436. //-----------------------------------------------------------------------------
  437. void RampTool::DrawFocusRect( void )
  438. {
  439. HDC dc = GetDC( NULL );
  440. for ( int i = 0; i < m_FocusRects.Size(); i++ )
  441. {
  442. RECT rc = m_FocusRects[ i ].m_rcFocus;
  443. ::DrawFocusRect( dc, &rc );
  444. }
  445. ReleaseDC( NULL, dc );
  446. }
  447. void RampTool::SetClickedPos( int x, int y )
  448. {
  449. m_nClickedX = x;
  450. m_nClickedY = y;
  451. }
  452. float RampTool::GetTimeForClickedPos( void )
  453. {
  454. CChoreoEvent *e = GetSafeEvent();
  455. if ( !e )
  456. return 0.0f;
  457. float t = GetTimeValueForMouse( m_nClickedX );
  458. return t;
  459. }
  460. //-----------------------------------------------------------------------------
  461. // Purpose:
  462. // Input : dragtype -
  463. // startx -
  464. // cursor -
  465. //-----------------------------------------------------------------------------
  466. void RampTool::StartDragging( int dragtype, int startx, int starty, HCURSOR cursor )
  467. {
  468. m_nDragType = dragtype;
  469. m_nStartX = startx;
  470. m_nLastX = startx;
  471. m_nStartY = starty;
  472. m_nLastY = starty;
  473. if ( m_hPrevCursor )
  474. {
  475. SetCursor( m_hPrevCursor );
  476. m_hPrevCursor = NULL;
  477. }
  478. m_hPrevCursor = SetCursor( cursor );
  479. m_FocusRects.Purge();
  480. RECT rcStart;
  481. rcStart.left = startx;
  482. rcStart.right = startx;
  483. bool addrect = true;
  484. switch ( dragtype )
  485. {
  486. case DRAGTYPE_SCRUBBER:
  487. {
  488. RECT rcScrub;
  489. GetScrubHandleRect( rcScrub, m_flScrub, true );
  490. rcStart = rcScrub;
  491. rcStart.left = ( rcScrub.left + rcScrub.right ) / 2;
  492. rcStart.right = rcStart.left;
  493. rcStart.top = rcScrub.bottom;
  494. rcStart.bottom = h2();
  495. }
  496. break;
  497. default:
  498. {
  499. rcStart.top = starty;
  500. rcStart.bottom = starty;
  501. }
  502. break;
  503. }
  504. if ( addrect )
  505. {
  506. AddFocusRect( rcStart );
  507. }
  508. DrawFocusRect();
  509. }
  510. void RampTool::OnMouseMove( mxEvent *event )
  511. {
  512. int mx = (short)event->x;
  513. int my = (short)event->y;
  514. event->x = (short)mx;
  515. if ( m_nDragType != DRAGTYPE_NONE )
  516. {
  517. DrawFocusRect();
  518. for ( int i = 0; i < m_FocusRects.Size(); i++ )
  519. {
  520. CFocusRect *f = &m_FocusRects[ i ];
  521. f->m_rcFocus = f->m_rcOrig;
  522. switch ( m_nDragType )
  523. {
  524. default:
  525. {
  526. OffsetRect( &f->m_rcFocus, ( mx - m_nStartX ), ( my - m_nStartY ) );
  527. }
  528. break;
  529. case DRAGTYPE_SCRUBBER:
  530. {
  531. ApplyBounds( mx, my );
  532. if ( w2() > 0 )
  533. {
  534. float t = GetTimeValueForMouse( mx );
  535. t += m_flScrubberTimeOffset;
  536. ForceScrubPosition( t );
  537. }
  538. OffsetRect( &f->m_rcFocus, ( mx - m_nStartX ), 0 );
  539. }
  540. break;
  541. case DRAGTYPE_MOVEPOINTS_TIME:
  542. case DRAGTYPE_MOVEPOINTS_VALUE:
  543. {
  544. int dx = mx - m_nLastX;
  545. int dy = my - m_nLastY;
  546. if ( !( event->modifiers & mxEvent::KeyCtrl ) )
  547. {
  548. // Zero out motion on other axis
  549. if ( m_nDragType == DRAGTYPE_MOVEPOINTS_VALUE )
  550. {
  551. dx = 0;
  552. mx = m_nLastX;
  553. }
  554. else
  555. {
  556. dy = 0;
  557. my = m_nLastY;
  558. }
  559. }
  560. else
  561. {
  562. SetCursor( LoadCursor( NULL, IDC_SIZEALL ) );
  563. }
  564. RECT rcSamples;
  565. GetSampleTrayRect( rcSamples );
  566. int height = rcSamples.bottom - rcSamples.top;
  567. Assert( height > 0 );
  568. float dfdx = (float)dx / GetPixelsPerSecond();
  569. float dfdy = (float)dy / (float)height;
  570. MoveSelectedSamples( dfdx, dfdy );
  571. // Update the scrubber
  572. if ( w2() > 0 )
  573. {
  574. float t = GetTimeValueForMouse( mx );
  575. ForceScrubPosition( t );
  576. g_pMatSysWindow->Frame();
  577. }
  578. OffsetRect( &f->m_rcFocus, dx, dy );
  579. }
  580. break;
  581. case DRAGTYPE_SELECTION:
  582. {
  583. RECT rcFocus;
  584. rcFocus.left = m_nStartX < m_nLastX ? m_nStartX : m_nLastX;
  585. rcFocus.right = m_nStartX < m_nLastX ? m_nLastX : m_nStartX;
  586. rcFocus.top = m_nStartY < m_nLastY ? m_nStartY : m_nLastY;
  587. rcFocus.bottom = m_nStartY < m_nLastY ? m_nLastY : m_nStartY;
  588. POINT offset;
  589. offset.x = 0;
  590. offset.y = 0;
  591. ClientToScreen( (HWND)getHandle(), &offset );
  592. OffsetRect( &rcFocus, offset.x, offset.y );
  593. f->m_rcFocus = rcFocus;
  594. }
  595. break;
  596. }
  597. }
  598. DrawFocusRect();
  599. }
  600. else
  601. {
  602. if ( m_hPrevCursor )
  603. {
  604. SetCursor( m_hPrevCursor );
  605. m_hPrevCursor = NULL;
  606. }
  607. if ( IsMouseOverScrubHandle( event ) )
  608. {
  609. m_hPrevCursor = SetCursor( LoadCursor( NULL, IDC_SIZEWE ) );
  610. }
  611. /*
  612. else if ( IsMouseOverTag( mx, my ) )
  613. {
  614. m_hPrevCursor = SetCursor( LoadCursor( NULL, IDC_SIZEWE ) );
  615. }
  616. */
  617. // See if anything is selected
  618. if ( CountSelected() <= 0 )
  619. {
  620. // Nothing selected
  621. // Draw auto highlight
  622. DrawAutoHighlight( event );
  623. }
  624. }
  625. m_nLastX = (short)event->x;
  626. m_nLastY = (short)event->y;
  627. }
  628. int RampTool::handleEvent( mxEvent *event )
  629. {
  630. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  631. int iret = 0;
  632. if ( HandleToolEvent( event ) )
  633. {
  634. return iret;
  635. }
  636. // Give helper a shot at the event
  637. if ( m_pHelper->HelperHandleEvent( event ) )
  638. {
  639. return 1;
  640. }
  641. switch ( event->event )
  642. {
  643. case mxEvent::Size:
  644. {
  645. int w, h;
  646. w = event->width;
  647. h = event->height;
  648. m_nLastHPixelsNeeded = 0;
  649. InvalidateLayout();
  650. iret = 1;
  651. }
  652. break;
  653. case mxEvent::MouseWheeled:
  654. {
  655. CChoreoScene *scene = g_pChoreoView->GetScene();
  656. if ( scene )
  657. {
  658. int tz = g_pChoreoView->GetTimeZoom( GetToolName() );
  659. bool shiftdown = ( event->modifiers & mxEvent::KeyShift ) ? true : false;
  660. int stepMultipiler = shiftdown ? 5 : 1;
  661. // Zoom time in / out
  662. if ( event->height > 0 )
  663. {
  664. tz = min( tz + TIME_ZOOM_STEP * stepMultipiler, MAX_TIME_ZOOM );
  665. }
  666. else
  667. {
  668. tz = max( tz - TIME_ZOOM_STEP * stepMultipiler, TIME_ZOOM_STEP );
  669. }
  670. g_pChoreoView->SetPreservedTimeZoom( this, tz );
  671. }
  672. redraw();
  673. iret = 1;
  674. }
  675. break;
  676. case mxEvent::MouseDown:
  677. {
  678. bool ctrldown = ( event->modifiers & mxEvent::KeyCtrl ) ? true : false;
  679. bool shiftdown = ( event->modifiers & mxEvent::KeyShift ) ? true : false;
  680. bool rightbutton = ( event->buttons & mxEvent::MouseRightButton ) ? true : false;
  681. iret = 1;
  682. int mx = (short)event->x;
  683. int my = (short)event->y;
  684. SetClickedPos( mx, my );
  685. SetMouseOverPos( mx, my );
  686. DrawMouseOverPos();
  687. POINT pt;
  688. pt.x = mx;
  689. pt.y = my;
  690. RECT rcSamples;
  691. GetSampleTrayRect( rcSamples );
  692. bool insamplearea = PtInRect( &rcSamples, pt ) ? true : false;
  693. if ( m_nDragType == DRAGTYPE_NONE )
  694. {
  695. bool ctrlDown = ( event->modifiers & mxEvent::KeyCtrl ) ? true : false;
  696. CExpressionSample *sample = GetSampleUnderMouse( event->x, event->y, ctrlDown ? FP_RT_ADDSAMPLE_TOLERANCE : FP_RT_SELECTION_TOLERANCE );
  697. if ( IsMouseOverScrubHandle( event ) )
  698. {
  699. if ( w2() > 0 )
  700. {
  701. float t = GetTimeValueForMouse( (short)event->x );
  702. m_flScrubberTimeOffset = m_flScrub - t;
  703. float maxoffset = 0.5f * (float)SCRUBBER_HANDLE_WIDTH / GetPixelsPerSecond();
  704. m_flScrubberTimeOffset = clamp( m_flScrubberTimeOffset, -maxoffset, maxoffset );
  705. t += m_flScrubberTimeOffset;
  706. ForceScrubPosition( t );
  707. }
  708. StartDragging( DRAGTYPE_SCRUBBER, m_nClickedX, m_nClickedY, LoadCursor( NULL, IDC_SIZEWE ) );
  709. }
  710. else if ( insamplearea )
  711. {
  712. if ( sample )
  713. {
  714. if ( shiftdown )
  715. {
  716. sample->selected = !sample->selected;
  717. redraw();
  718. }
  719. else if ( sample->selected )
  720. {
  721. PreDataChanged( "move ramp points" );
  722. StartDragging(
  723. rightbutton ? DRAGTYPE_MOVEPOINTS_TIME : DRAGTYPE_MOVEPOINTS_VALUE,
  724. m_nClickedX, m_nClickedY,
  725. LoadCursor( NULL, rightbutton ? IDC_SIZEWE : IDC_SIZENS ) );
  726. }
  727. else
  728. {
  729. if ( !shiftdown )
  730. {
  731. DeselectAll();
  732. }
  733. StartDragging( DRAGTYPE_SELECTION, m_nClickedX, m_nClickedY, LoadCursor( NULL, IDC_ARROW ) );
  734. }
  735. }
  736. else if ( ctrldown )
  737. {
  738. CChoreoEvent *e = GetSafeEvent();
  739. if ( e )
  740. {
  741. // Add a sample point
  742. float t = GetTimeValueForMouse( mx );
  743. t = FacePoser_SnapTime( t );
  744. float value = 1.0f - (float)( (short)event->y - rcSamples.top ) / (float)( rcSamples.bottom - rcSamples.top );
  745. value = clamp( value, 0.0f, 1.0f );
  746. PreDataChanged( "Add ramp point" );
  747. e->AddRamp( t, value, false );
  748. e->ResortRamp();
  749. PostDataChanged( "Add ramp point" );
  750. }
  751. }
  752. else
  753. {
  754. if ( event->buttons & mxEvent::MouseRightButton )
  755. {
  756. ShowContextMenu( event, false );
  757. iret = 1;
  758. return iret;
  759. }
  760. else
  761. {
  762. if ( !shiftdown )
  763. {
  764. DeselectAll();
  765. }
  766. StartDragging( DRAGTYPE_SELECTION, m_nClickedX, m_nClickedY, LoadCursor( NULL, IDC_ARROW ) );
  767. }
  768. }
  769. }
  770. else
  771. {
  772. if ( event->buttons & mxEvent::MouseRightButton )
  773. {
  774. ShowContextMenu( event, false );
  775. iret = 1;
  776. return iret;
  777. }
  778. else
  779. {
  780. if ( w2() > 0 )
  781. {
  782. float t = GetTimeValueForMouse( (short)event->x );
  783. SetScrubTargetTime( t );
  784. }
  785. }
  786. }
  787. CalcBounds( m_nDragType );
  788. }
  789. }
  790. break;
  791. case mxEvent::MouseDrag:
  792. case mxEvent::MouseMove:
  793. {
  794. int mx = (short)event->x;
  795. int my = (short)event->y;
  796. SetMouseOverPos( mx, my );
  797. DrawMouseOverPos();
  798. OnMouseMove( event );
  799. iret = 1;
  800. }
  801. break;
  802. case mxEvent::MouseUp:
  803. {
  804. OnMouseMove( event );
  805. int mx = (short)event->x;
  806. int my = (short)event->y;
  807. if ( m_nDragType != DRAGTYPE_NONE )
  808. {
  809. DrawFocusRect();
  810. }
  811. if ( m_hPrevCursor )
  812. {
  813. SetCursor( m_hPrevCursor );
  814. m_hPrevCursor = 0;
  815. }
  816. switch ( m_nDragType )
  817. {
  818. case DRAGTYPE_NONE:
  819. break;
  820. case DRAGTYPE_SCRUBBER:
  821. {
  822. ApplyBounds( mx, my );
  823. if ( w2() > 0 )
  824. {
  825. float t = GetTimeValueForMouse( (short)event->x );
  826. t += m_flScrubberTimeOffset;
  827. ForceScrubPosition( t );
  828. m_flScrubberTimeOffset = 0.0f;
  829. }
  830. }
  831. break;
  832. case DRAGTYPE_MOVEPOINTS_VALUE:
  833. case DRAGTYPE_MOVEPOINTS_TIME:
  834. {
  835. PostDataChanged( "move ramp points" );
  836. }
  837. break;
  838. case DRAGTYPE_SELECTION:
  839. {
  840. SelectPoints();
  841. }
  842. break;
  843. }
  844. m_nDragType = DRAGTYPE_NONE;
  845. SetMouseOverPos( mx, my );
  846. DrawMouseOverPos();
  847. redraw();
  848. iret = 1;
  849. }
  850. break;
  851. case mxEvent::Action:
  852. {
  853. iret = 1;
  854. switch ( event->action )
  855. {
  856. default:
  857. iret = 0;
  858. break;
  859. case IDC_UNDO_RT:
  860. {
  861. OnUndo();
  862. }
  863. break;
  864. case IDC_REDO_RT:
  865. {
  866. OnRedo();
  867. }
  868. break;
  869. case IDC_RT_DELETE:
  870. {
  871. Delete();
  872. }
  873. break;
  874. case IDC_RT_DESELECT:
  875. {
  876. DeselectAll();
  877. }
  878. break;
  879. case IDC_RT_SELECTALL:
  880. {
  881. SelectAll();
  882. }
  883. break;
  884. case IDC_RAMPHSCROLL:
  885. {
  886. int offset = 0;
  887. bool processed = true;
  888. switch ( event->modifiers )
  889. {
  890. case SB_THUMBTRACK:
  891. offset = event->height;
  892. break;
  893. case SB_PAGEUP:
  894. offset = m_pHorzScrollBar->getValue();
  895. offset -= 20;
  896. offset = max( offset, m_pHorzScrollBar->getMinValue() );
  897. break;
  898. case SB_PAGEDOWN:
  899. offset = m_pHorzScrollBar->getValue();
  900. offset += 20;
  901. offset = min( offset, m_pHorzScrollBar->getMaxValue() );
  902. break;
  903. case SB_LINEUP:
  904. offset = m_pHorzScrollBar->getValue();
  905. offset -= 10;
  906. offset = max( offset, m_pHorzScrollBar->getMinValue() );
  907. break;
  908. case SB_LINEDOWN:
  909. offset = m_pHorzScrollBar->getValue();
  910. offset += 10;
  911. offset = min( offset, m_pHorzScrollBar->getMaxValue() );
  912. break;
  913. default:
  914. processed = false;
  915. break;
  916. }
  917. if ( processed )
  918. {
  919. MoveTimeSliderToPos( offset );
  920. }
  921. }
  922. break;
  923. case IDC_RT_CHANGESCALE:
  924. {
  925. OnChangeScale();
  926. }
  927. break;
  928. case IDC_RT_EDGEPROPERTIES:
  929. {
  930. OnEdgeProperties();
  931. }
  932. break;
  933. }
  934. }
  935. break;
  936. case mxEvent::KeyDown:
  937. {
  938. iret = 1;
  939. switch ( event->key )
  940. {
  941. default:
  942. iret = g_pChoreoView->HandleZoomKey( this, event->key );
  943. break;
  944. case VK_ESCAPE:
  945. DeselectAll();
  946. break;
  947. case VK_DELETE:
  948. Delete();
  949. break;
  950. }
  951. }
  952. }
  953. return iret;
  954. }
  955. void RampTool::ApplyBounds( int& mx, int& my )
  956. {
  957. if ( !m_bUseBounds )
  958. return;
  959. mx = clamp( mx, m_nMinX, m_nMaxX );
  960. }
  961. void RampTool::CalcBounds( int movetype )
  962. {
  963. switch ( movetype )
  964. {
  965. default:
  966. case DRAGTYPE_NONE:
  967. {
  968. m_bUseBounds = false;
  969. m_nMinX = 0;
  970. m_nMaxX = 0;
  971. }
  972. break;
  973. case DRAGTYPE_SCRUBBER:
  974. {
  975. m_bUseBounds = true;
  976. m_nMinX = 0;
  977. m_nMaxX = w2();
  978. }
  979. break;
  980. }
  981. }
  982. bool RampTool::PaintBackground()
  983. {
  984. redraw();
  985. return false;
  986. }
  987. void RampTool::OnUndo( void )
  988. {
  989. g_pChoreoView->Undo();
  990. }
  991. void RampTool::OnRedo( void )
  992. {
  993. g_pChoreoView->Redo();
  994. }
  995. void RampTool::ForceScrubPositionFromSceneTime( float scenetime )
  996. {
  997. CChoreoEvent *e = GetSafeEvent();
  998. if ( !e || !e->GetDuration() )
  999. return;
  1000. float t = scenetime - e->GetStartTime();
  1001. m_flScrub = t;
  1002. m_flScrubTarget = t;
  1003. DrawScrubHandles();
  1004. }
  1005. void RampTool::ForceScrubPosition( float t )
  1006. {
  1007. m_flScrub = t;
  1008. m_flScrubTarget = t;
  1009. CChoreoEvent *e = GetSafeEvent();
  1010. if ( e && e->GetDuration() )
  1011. {
  1012. float realtime = e->GetStartTime() + t;
  1013. g_pChoreoView->SetScrubTime( realtime );
  1014. g_pChoreoView->SetScrubTargetTime( realtime );
  1015. g_pChoreoView->DrawScrubHandle();
  1016. }
  1017. DrawScrubHandles();
  1018. }
  1019. void RampTool::SetMouseOverPos( int x, int y )
  1020. {
  1021. m_nMousePos[ 0 ] = x;
  1022. m_nMousePos[ 1 ] = y;
  1023. }
  1024. void RampTool::GetMouseOverPos( int &x, int& y )
  1025. {
  1026. x = m_nMousePos[ 0 ];
  1027. y = m_nMousePos[ 1 ];
  1028. }
  1029. //-----------------------------------------------------------------------------
  1030. // Purpose:
  1031. // Input : rcPos -
  1032. //-----------------------------------------------------------------------------
  1033. void RampTool::GetMouseOverPosRect( RECT& rcPos )
  1034. {
  1035. rcPos.top = GetCaptionHeight() + 12;
  1036. rcPos.left = w2() - 200;
  1037. rcPos.right = w2() - 5;
  1038. rcPos.bottom = rcPos.top + 13;
  1039. }
  1040. //-----------------------------------------------------------------------------
  1041. // Purpose:
  1042. // Input : drawHelper -
  1043. // rcPos -
  1044. //-----------------------------------------------------------------------------
  1045. void RampTool::DrawMouseOverPos( CChoreoWidgetDrawHelper& drawHelper, RECT& rcPos )
  1046. {
  1047. // Compute time for pixel x
  1048. float t = GetTimeValueForMouse( m_nMousePos[ 0 ] );
  1049. CChoreoEvent *e = GetSafeEvent();
  1050. if ( !e )
  1051. return;
  1052. t += e->GetStartTime();
  1053. float snapped = FacePoser_SnapTime( t );
  1054. // Found it, write out description
  1055. //
  1056. char sz[ 128 ];
  1057. if ( t != snapped )
  1058. {
  1059. Q_snprintf( sz, sizeof( sz ), "%s", FacePoser_DescribeSnappedTime( t ) );
  1060. }
  1061. else
  1062. {
  1063. Q_snprintf( sz, sizeof( sz ), "%.3f", t );
  1064. }
  1065. int len = drawHelper.CalcTextWidth( "Arial", 11, 900, sz );
  1066. RECT rcText = rcPos;
  1067. rcText.left = max( rcPos.left, rcPos.right - len );
  1068. drawHelper.DrawColoredText( "Arial", 11, 900, RGB( 255, 50, 70 ), rcText, sz );
  1069. }
  1070. //-----------------------------------------------------------------------------
  1071. // Purpose:
  1072. //-----------------------------------------------------------------------------
  1073. void RampTool::DrawMouseOverPos()
  1074. {
  1075. RECT rcPos;
  1076. GetMouseOverPosRect( rcPos );
  1077. CChoreoWidgetDrawHelper drawHelper( this, rcPos );
  1078. DrawMouseOverPos( drawHelper, rcPos );
  1079. }
  1080. void RampTool::AddFocusRect( RECT& rc )
  1081. {
  1082. RECT rcFocus = rc;
  1083. POINT offset;
  1084. offset.x = 0;
  1085. offset.y = 0;
  1086. ClientToScreen( (HWND)getHandle(), &offset );
  1087. OffsetRect( &rcFocus, offset.x, offset.y );
  1088. // Convert to screen space?
  1089. CFocusRect fr;
  1090. fr.m_rcFocus = rcFocus;
  1091. fr.m_rcOrig = rcFocus;
  1092. m_FocusRects.AddToTail( fr );
  1093. }
  1094. //-----------------------------------------------------------------------------
  1095. // Purpose:
  1096. // Input : drawHelper -
  1097. // rc -
  1098. // left -
  1099. // right -
  1100. //-----------------------------------------------------------------------------
  1101. void RampTool::DrawTimeLine( CChoreoWidgetDrawHelper& drawHelper, RECT& rc, float left, float right )
  1102. {
  1103. RECT rcLabel;
  1104. float granularity = 0.5f;
  1105. drawHelper.DrawColoredLine( RGB( 150, 150, 200 ), PS_SOLID, 1, rc.left, rc.top + 2, rc.right, rc.top + 2 );
  1106. float f = SnapTime( left, granularity );
  1107. while ( f < right )
  1108. {
  1109. float frac = ( f - left ) / ( right - left );
  1110. if ( frac >= 0.0f && frac <= 1.0f )
  1111. {
  1112. rcLabel.left = GetPixelForTimeValue( f );
  1113. rcLabel.top = rc.top + 5;
  1114. rcLabel.bottom = rcLabel.top + 10;
  1115. if ( f != left )
  1116. {
  1117. drawHelper.DrawColoredLine( RGB( 220, 220, 240 ), PS_DOT, 1,
  1118. rcLabel.left, rc.top, rcLabel.left, h2() );
  1119. }
  1120. char sz[ 32 ];
  1121. sprintf( sz, "%.2f", f );
  1122. int textWidth = drawHelper.CalcTextWidth( "Arial", 9, FW_NORMAL, sz );
  1123. rcLabel.right = rcLabel.left + textWidth;
  1124. OffsetRect( &rcLabel, -textWidth / 2, 0 );
  1125. RECT rcOut = rcLabel;
  1126. if ( rcOut.left <= 0 )
  1127. {
  1128. OffsetRect( &rcOut, -rcOut.left + 2, 0 );
  1129. }
  1130. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 50, 150 ), rcOut, sz );
  1131. }
  1132. f += granularity;
  1133. }
  1134. }
  1135. void RampTool::DrawTimingTags( CChoreoWidgetDrawHelper& drawHelper, RECT& rc )
  1136. {
  1137. CChoreoEvent *rampevent = GetSafeEvent();
  1138. if ( !rampevent )
  1139. return;
  1140. CChoreoScene *scene = rampevent->GetScene();
  1141. if ( !scene )
  1142. return;
  1143. float starttime = GetTimeValueForMouse( 0 );
  1144. float endtime = GetTimeValueForMouse( w2() );
  1145. if ( endtime - starttime <= 0.0f )
  1146. return;
  1147. RECT rcText = rc;
  1148. rcText.bottom = rcText.top + 10;
  1149. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 100, 200 ), rcText, "Timing Tags:" );
  1150. // Loop through all events in scene
  1151. int c = scene->GetNumEvents();
  1152. int i;
  1153. for ( i = 0; i < c; i++ )
  1154. {
  1155. CChoreoEvent *e = scene->GetEvent( i );
  1156. if ( !e )
  1157. continue;
  1158. // See if time overlaps
  1159. if ( !e->HasEndTime() )
  1160. continue;
  1161. if ( ( e->GetEndTime() - e->GetStartTime() ) < starttime )
  1162. continue;
  1163. if ( ( e->GetStartTime() - e->GetStartTime() ) > endtime )
  1164. continue;
  1165. if ( e->GetNumRelativeTags() > 0 )
  1166. {
  1167. DrawRelativeTagsForEvent( drawHelper, rc, rampevent, e, starttime, endtime );
  1168. }
  1169. if ( e->GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ) > 0 )
  1170. {
  1171. DrawAbsoluteTagsForEvent( drawHelper, rc, rampevent, e, starttime, endtime );
  1172. }
  1173. }
  1174. }
  1175. //-----------------------------------------------------------------------------
  1176. // Purpose:
  1177. // Input : drawHelper -
  1178. // &rc -
  1179. //-----------------------------------------------------------------------------
  1180. void RampTool::DrawAbsoluteTagsForEvent( CChoreoWidgetDrawHelper& drawHelper, RECT &rc, CChoreoEvent *rampevent, CChoreoEvent *event, float starttime, float endtime )
  1181. {
  1182. if ( !event )
  1183. return;
  1184. for ( int i = 0; i < event->GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); i++ )
  1185. {
  1186. CEventAbsoluteTag *tag = event->GetAbsoluteTag( CChoreoEvent::PLAYBACK, i );
  1187. if ( !tag )
  1188. continue;
  1189. float tagtime = ( event->GetStartTime() + tag->GetPercentage() * event->GetDuration() ) - rampevent->GetStartTime();
  1190. if ( tagtime < starttime || tagtime > endtime )
  1191. continue;
  1192. bool clipped = false;
  1193. int left = GetPixelForTimeValue( tagtime, &clipped );
  1194. if ( clipped )
  1195. continue;
  1196. // Don't add gesture tags except for the current event
  1197. if ( event != rampevent &&
  1198. event->GetType() == CChoreoEvent::GESTURE )
  1199. {
  1200. continue;
  1201. }
  1202. COLORREF clr = event == rampevent ? RGB( 0, 100, 250 ) : RGB( 100, 100, 100 );
  1203. RECT rcMark;
  1204. rcMark = rc;
  1205. rcMark.top = rc.bottom - 8;
  1206. rcMark.bottom = rc.bottom;
  1207. rcMark.left = left - 4;
  1208. rcMark.right = left + 4;
  1209. drawHelper.DrawTriangleMarker( rcMark, clr );
  1210. RECT rcText;
  1211. rcText = rcMark;
  1212. rcText.top -= 12;
  1213. int len = drawHelper.CalcTextWidth( "Arial", 9, FW_NORMAL, tag->GetName() );
  1214. rcText.left = left - len / 2;
  1215. rcText.right = rcText.left + len + 2;
  1216. rcText.bottom = rcText.top + 10;
  1217. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, clr, rcText, tag->GetName() );
  1218. }
  1219. }
  1220. //-----------------------------------------------------------------------------
  1221. // Purpose:
  1222. // Input : drawHelper -
  1223. // rc -
  1224. //-----------------------------------------------------------------------------
  1225. void RampTool::DrawRelativeTagsForEvent( CChoreoWidgetDrawHelper& drawHelper, RECT& rc, CChoreoEvent *rampevent, CChoreoEvent *event, float starttime, float endtime )
  1226. {
  1227. if ( !event )
  1228. return;
  1229. //drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, PEColor( COLOR_PHONEME_TIMING_TAG ), rc, "Timing Tags:" );
  1230. for ( int i = 0; i < event->GetNumRelativeTags(); i++ )
  1231. {
  1232. CEventRelativeTag *tag = event->GetRelativeTag( i );
  1233. if ( !tag )
  1234. continue;
  1235. //
  1236. float tagtime = ( event->GetStartTime() + tag->GetPercentage() * event->GetDuration() ) - rampevent->GetStartTime();
  1237. if ( tagtime < starttime || tagtime > endtime )
  1238. continue;
  1239. bool clipped = false;
  1240. int left = GetPixelForTimeValue( tagtime, &clipped );
  1241. if ( clipped )
  1242. continue;
  1243. //float frac = ( tagtime - starttime ) / ( endtime - starttime );
  1244. //int left = rc.left + (int)( frac * ( float )( rc.right - rc.left ) + 0.5f );
  1245. COLORREF clr = event == rampevent ? RGB( 0, 100, 250 ) : RGB( 100, 100, 100 );
  1246. RECT rcMark;
  1247. rcMark = rc;
  1248. rcMark.top = rc.bottom - 8;
  1249. rcMark.bottom = rc.bottom;
  1250. rcMark.left = left - 4;
  1251. rcMark.right = left + 4;
  1252. drawHelper.DrawTriangleMarker( rcMark, clr );
  1253. RECT rcText;
  1254. rcText = rc;
  1255. rcText.bottom = rc.bottom - 10;
  1256. rcText.top = rcText.bottom - 10;
  1257. int len = drawHelper.CalcTextWidth( "Arial", 9, FW_NORMAL, tag->GetName() );
  1258. rcText.left = left - len / 2;
  1259. rcText.right = rcText.left + len + 2;
  1260. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, clr, rcText, tag->GetName() );
  1261. }
  1262. }
  1263. //-----------------------------------------------------------------------------
  1264. // Purpose:
  1265. // Output : int
  1266. //-----------------------------------------------------------------------------
  1267. int RampTool::ComputeHPixelsNeeded( void )
  1268. {
  1269. CChoreoEvent *event = GetSafeEvent();
  1270. if ( !event )
  1271. return 0;
  1272. int pixels = 0;
  1273. float maxtime = event->GetDuration();
  1274. pixels = (int)( ( maxtime ) * GetPixelsPerSecond() + 10 );
  1275. return pixels;
  1276. }
  1277. //-----------------------------------------------------------------------------
  1278. // Purpose:
  1279. //-----------------------------------------------------------------------------
  1280. void RampTool::RepositionHSlider( void )
  1281. {
  1282. int pixelsneeded = ComputeHPixelsNeeded();
  1283. if ( pixelsneeded <= w2() - 10 )
  1284. {
  1285. m_pHorzScrollBar->setVisible( false );
  1286. }
  1287. else
  1288. {
  1289. m_pHorzScrollBar->setVisible( true );
  1290. }
  1291. m_pHorzScrollBar->setBounds( 0, h2() - m_nScrollbarHeight, w2() - m_nScrollbarHeight, m_nScrollbarHeight );
  1292. m_flLeftOffset = max( 0.f, m_flLeftOffset );
  1293. m_flLeftOffset = min( (float)pixelsneeded, m_flLeftOffset );
  1294. m_pHorzScrollBar->setRange( 0, pixelsneeded );
  1295. m_pHorzScrollBar->setValue( (int)m_flLeftOffset );
  1296. m_pHorzScrollBar->setPagesize( w2() - 10 );
  1297. m_nLastHPixelsNeeded = pixelsneeded;
  1298. }
  1299. //-----------------------------------------------------------------------------
  1300. // Purpose:
  1301. // Output : float
  1302. //-----------------------------------------------------------------------------
  1303. float RampTool::GetPixelsPerSecond( void )
  1304. {
  1305. return m_flPixelsPerSecond * (float)g_pChoreoView->GetTimeZoom( GetToolName() ) / 100.0f;
  1306. }
  1307. //-----------------------------------------------------------------------------
  1308. // Purpose:
  1309. // Input : x -
  1310. //-----------------------------------------------------------------------------
  1311. void RampTool::MoveTimeSliderToPos( int x )
  1312. {
  1313. m_flLeftOffset = (float)x;
  1314. m_pHorzScrollBar->setValue( (int)m_flLeftOffset );
  1315. InvalidateRect( (HWND)m_pHorzScrollBar->getHandle(), NULL, TRUE );
  1316. InvalidateLayout();
  1317. }
  1318. //-----------------------------------------------------------------------------
  1319. // Purpose:
  1320. //-----------------------------------------------------------------------------
  1321. void RampTool::InvalidateLayout( void )
  1322. {
  1323. if ( m_bSuppressLayout )
  1324. return;
  1325. if ( ComputeHPixelsNeeded() != m_nLastHPixelsNeeded )
  1326. {
  1327. RepositionHSlider();
  1328. }
  1329. m_bLayoutIsValid = false;
  1330. redraw();
  1331. }
  1332. //-----------------------------------------------------------------------------
  1333. // Purpose:
  1334. // Input : st -
  1335. // ed -
  1336. //-----------------------------------------------------------------------------
  1337. void RampTool::GetStartAndEndTime( float& st, float& ed )
  1338. {
  1339. st = m_flLeftOffset / GetPixelsPerSecond();
  1340. ed = st + (float)w2() / GetPixelsPerSecond();
  1341. }
  1342. //-----------------------------------------------------------------------------
  1343. // Purpose:
  1344. // Input : -
  1345. // Output : float
  1346. //-----------------------------------------------------------------------------
  1347. float RampTool::GetEventEndTime()
  1348. {
  1349. CChoreoEvent *ev = GetSafeEvent();
  1350. if ( !ev )
  1351. return 1.0f;
  1352. return ev->GetDuration();
  1353. }
  1354. //-----------------------------------------------------------------------------
  1355. // Purpose:
  1356. // Input : time -
  1357. // *clipped -
  1358. // Output : int
  1359. //-----------------------------------------------------------------------------
  1360. int RampTool::GetPixelForTimeValue( float time, bool *clipped /*=NULL*/ )
  1361. {
  1362. if ( clipped )
  1363. {
  1364. *clipped = false;
  1365. }
  1366. float st, ed;
  1367. GetStartAndEndTime( st, ed );
  1368. float frac = ( time - st ) / ( ed - st );
  1369. if ( frac < 0.0 || frac > 1.0 )
  1370. {
  1371. if ( clipped )
  1372. {
  1373. *clipped = true;
  1374. }
  1375. }
  1376. int pixel = ( int )( frac * w2() );
  1377. return pixel;
  1378. }
  1379. //-----------------------------------------------------------------------------
  1380. // Purpose:
  1381. // Input : mx -
  1382. // clip -
  1383. // Output : float
  1384. //-----------------------------------------------------------------------------
  1385. float RampTool::GetTimeValueForMouse( int mx, bool clip /*=false*/)
  1386. {
  1387. float st, ed;
  1388. GetStartAndEndTime( st, ed );
  1389. if ( clip )
  1390. {
  1391. if ( mx < 0 )
  1392. {
  1393. return st;
  1394. }
  1395. if ( mx > w2() )
  1396. {
  1397. return ed;
  1398. }
  1399. }
  1400. float frac = (float)( mx ) / (float)( w2() );
  1401. return st + frac * ( ed - st );
  1402. }
  1403. void RampTool::OnChangeScale( void )
  1404. {
  1405. CChoreoScene *scene = g_pChoreoView->GetScene();
  1406. if ( !scene )
  1407. {
  1408. return;
  1409. }
  1410. // Zoom time in / out
  1411. CInputParams params;
  1412. memset( &params, 0, sizeof( params ) );
  1413. strcpy( params.m_szDialogTitle, "Change Zoom" );
  1414. strcpy( params.m_szPrompt, "New scale (e.g., 2.5x):" );
  1415. Q_snprintf( params.m_szInputText, sizeof( params.m_szInputText ), "%.2f", (float)g_pChoreoView->GetTimeZoom( GetToolName() ) / 100.0f );
  1416. if ( !InputProperties( &params ) )
  1417. return;
  1418. g_pChoreoView->SetTimeZoom( GetToolName(), clamp( (int)( 100.0f * atof( params.m_szInputText ) ), 1, MAX_TIME_ZOOM ), false );
  1419. m_nLastHPixelsNeeded = -1;
  1420. m_flLeftOffset= 0.0f;
  1421. InvalidateLayout();
  1422. Con_Printf( "Zoom factor %i %%\n", g_pChoreoView->GetTimeZoom( GetToolName() ) );
  1423. }
  1424. void RampTool::DrawEventEnd( CChoreoWidgetDrawHelper& drawHelper )
  1425. {
  1426. CChoreoEvent *e = GetSafeEvent();
  1427. if ( !e )
  1428. return;
  1429. float duration = e->GetDuration();
  1430. if ( !duration )
  1431. return;
  1432. int leftx = GetPixelForTimeValue( duration );
  1433. if ( leftx >= w2() )
  1434. return;
  1435. RECT rcSample;
  1436. GetSampleTrayRect( rcSample );
  1437. drawHelper.DrawColoredLine(
  1438. COLOR_CHOREO_ENDTIME, PS_SOLID, 1,
  1439. leftx, rcSample.top, leftx, rcSample.bottom );
  1440. }
  1441. void RampTool::GetSampleTrayRect( RECT& rc )
  1442. {
  1443. rc.left = 0;
  1444. rc.right = w2();
  1445. rc.top = GetCaptionHeight() + 65;
  1446. rc.bottom = h2() - m_nScrollbarHeight-2;
  1447. }
  1448. void RampTool::DrawSamplesSimple( CChoreoWidgetDrawHelper& drawHelper, CChoreoEvent *e, bool clearbackground, COLORREF sampleColor, RECT &rcSamples )
  1449. {
  1450. if ( clearbackground )
  1451. {
  1452. drawHelper.DrawFilledRect( RGB( 230, 230, 215 ), rcSamples );
  1453. }
  1454. if ( !e )
  1455. return;
  1456. float starttime = e->GetStartTime();
  1457. COLORREF lineColor = sampleColor;
  1458. int width = rcSamples.right - rcSamples.left;
  1459. if ( width <= 0.0f )
  1460. return;
  1461. int height = rcSamples.bottom - rcSamples.top;
  1462. int bottom = rcSamples.bottom;
  1463. float timestepperpixel = e->GetDuration() / (float)width;
  1464. float prev_value = e->GetIntensity( starttime );
  1465. int prev_x = rcSamples.left;
  1466. float prev_t = 0.0f;
  1467. for ( float x = rcSamples.left; x < rcSamples.right; x+=3 )
  1468. {
  1469. float t = (float)( x - rcSamples.left ) * timestepperpixel;
  1470. float value = e->GetIntensity( starttime + t );
  1471. // Draw segment
  1472. drawHelper.DrawColoredLine( lineColor, PS_SOLID, 1,
  1473. prev_x, bottom - prev_value * height,
  1474. x, bottom - value * height );
  1475. prev_x = x;
  1476. prev_t = t;
  1477. prev_value = value;
  1478. }
  1479. }
  1480. void RampTool::DrawSamples( CChoreoWidgetDrawHelper& drawHelper, RECT &rcSamples )
  1481. {
  1482. drawHelper.DrawFilledRect( RGB( 230, 230, 215 ), rcSamples );
  1483. CChoreoEvent *e = GetSafeEvent();
  1484. if ( !e )
  1485. return;
  1486. int rampCount = e->GetRampCount();
  1487. if ( !rampCount )
  1488. return;
  1489. float starttime;
  1490. float endtime;
  1491. GetStartAndEndTime( starttime, endtime );
  1492. COLORREF lineColor = RGB( 0, 0, 255 );
  1493. COLORREF dotColor = RGB( 0, 0, 255 );
  1494. COLORREF dotColorSelected = RGB( 240, 80, 20 );
  1495. COLORREF shadowColor = RGB( 150, 150, 250 );
  1496. int height = rcSamples.bottom - rcSamples.top;
  1497. int bottom = rcSamples.bottom;
  1498. int top = rcSamples.top;
  1499. float timestepperpixel = 1.0f / GetPixelsPerSecond();
  1500. float stoptime = min( endtime, e->GetDuration() );
  1501. float prev_t = starttime;
  1502. float prev_value = e->GetIntensity( prev_t );
  1503. if ( 0 )
  1504. {
  1505. COLORREF shadowColor = RGB( 150, 150, 250 );
  1506. // draw hermite version of time step
  1507. float i0, i1, i2;
  1508. float time10hz = starttime;
  1509. i0 = e->GetIntensity( time10hz + e->GetStartTime() );
  1510. i1 = i0;
  1511. time10hz = starttime + 0.1;
  1512. i2 = e->GetIntensity( time10hz + e->GetStartTime() );;
  1513. for ( float t = starttime-timestepperpixel; t <= stoptime; t += timestepperpixel )
  1514. {
  1515. while (t >= time10hz)
  1516. {
  1517. time10hz += 0.1;
  1518. i0 = i1;
  1519. i1 = i2;
  1520. i2 = e->GetIntensity( time10hz + e->GetStartTime() );
  1521. bool clipped;
  1522. int x = GetPixelForTimeValue( time10hz, &clipped );
  1523. int y = bottom - i2 * height;
  1524. int dotsize = 4;
  1525. drawHelper.DrawCircle(
  1526. shadowColor,
  1527. x, y,
  1528. dotsize,
  1529. false );
  1530. }
  1531. float value = Hermite_Spline( i0, i1, i2, (t - time10hz + 0.1) / 0.1 );
  1532. int prevx, x;
  1533. bool clipped1, clipped2;
  1534. x = GetPixelForTimeValue( t, &clipped1 );
  1535. prevx = GetPixelForTimeValue( prev_t, &clipped2 );
  1536. if ( !clipped1 && !clipped2 )
  1537. {
  1538. // Draw segment
  1539. drawHelper.DrawColoredLine( shadowColor, PS_SOLID, 1,
  1540. prevx, clamp( bottom - prev_value * height, top, bottom ),
  1541. x, clamp( bottom - value * height, top, bottom ) );
  1542. }
  1543. prev_t = t;
  1544. prev_value = value;
  1545. }
  1546. }
  1547. for ( float t = starttime-timestepperpixel; t <= stoptime; t += timestepperpixel )
  1548. {
  1549. float value = e->GetIntensity( t + e->GetStartTime() );
  1550. int prevx, x;
  1551. bool clipped1, clipped2;
  1552. x = GetPixelForTimeValue( t, &clipped1 );
  1553. prevx = GetPixelForTimeValue( prev_t, &clipped2 );
  1554. if ( !clipped1 && !clipped2 )
  1555. {
  1556. // Draw segment
  1557. drawHelper.DrawColoredLine( lineColor, PS_SOLID, 1,
  1558. prevx, bottom - prev_value * height,
  1559. x, bottom - value * height );
  1560. }
  1561. prev_t = t;
  1562. prev_value = value;
  1563. }
  1564. for ( int sample = 0; sample < rampCount; sample++ )
  1565. {
  1566. CExpressionSample *start = e->GetRamp( sample );
  1567. /*
  1568. int pixel = (int)( ( start->time / event_time ) * width + 0.5f);
  1569. int x = m_rcBounds.left + pixel;
  1570. float roundedfrac = (float)pixel / (float)width;
  1571. */
  1572. float value = start->value;
  1573. bool clipped = false;
  1574. int x = GetPixelForTimeValue( start->time, &clipped );
  1575. if ( clipped )
  1576. continue;
  1577. int y = bottom - value * height;
  1578. int dotsize = 6;
  1579. int dotSizeSelected = 6;
  1580. COLORREF clr = dotColor;
  1581. COLORREF clrSelected = dotColorSelected;
  1582. drawHelper.DrawCircle(
  1583. start->selected ? clrSelected : clr,
  1584. x, y,
  1585. start->selected ? dotSizeSelected : dotsize,
  1586. true );
  1587. if ( !start->selected )
  1588. continue;
  1589. if ( start->GetCurveType() == CURVE_DEFAULT )
  1590. continue;
  1591. // Draw curve type indicator...
  1592. char sz[ 128 ];
  1593. Q_snprintf( sz, sizeof( sz ), "%s", Interpolator_NameForCurveType( start->GetCurveType(), true ) );
  1594. RECT rc;
  1595. int fontSize = 9;
  1596. rc.top = clamp( y + 5, rcSamples.top + 2, rcSamples.bottom - 2 - fontSize );
  1597. rc.bottom = rc.top + fontSize + 1;
  1598. rc.left = x - 75;
  1599. rc.right = x + 175;
  1600. drawHelper.DrawColoredText( "Arial", fontSize, 500, shadowColor, rc, sz );
  1601. }
  1602. }
  1603. void RampTool::DrawAutoHighlight( mxEvent *event )
  1604. {
  1605. CChoreoEvent *e = GetSafeEvent();
  1606. if ( !e )
  1607. return;
  1608. CExpressionSample *hover = GetSampleUnderMouse( event->x, event->y, 0.0f );
  1609. RECT rcSamples;
  1610. GetSampleTrayRect( rcSamples );
  1611. CChoreoWidgetDrawHelper drawHelper( this, rcSamples, true );
  1612. RECT rcClient = rcSamples;
  1613. COLORREF dotColor = RGB( 0, 0, 255 );
  1614. COLORREF dotColorSelected = RGB( 240, 80, 20 );
  1615. COLORREF clrHighlighted = RGB( 0, 200, 0 );
  1616. int height = rcClient.bottom - rcClient.top;
  1617. int bottom = rcClient.bottom;
  1618. int dotsize = 6;
  1619. int dotSizeSelected = 6;
  1620. int dotSizeHighlighted = 6;
  1621. COLORREF clr = dotColor;
  1622. COLORREF clrSelected = dotColorSelected;
  1623. COLORREF bgColor = RGB( 230, 230, 200 );
  1624. // Fixme, could look at 1st derivative and do more sampling at high rate of change?
  1625. // or near actual sample points!
  1626. int sampleCount = e->GetRampCount();
  1627. for ( int sample = 0; sample < sampleCount; sample++ )
  1628. {
  1629. CExpressionSample *start = e->GetRamp( sample );
  1630. float value = start->value;
  1631. bool clipped = false;
  1632. int x = GetPixelForTimeValue( start->time, &clipped );
  1633. if ( clipped )
  1634. continue;
  1635. int y = bottom - value * height;
  1636. if ( hover == start )
  1637. {
  1638. drawHelper.DrawCircle(
  1639. bgColor,
  1640. x, y,
  1641. dotSizeHighlighted,
  1642. true );
  1643. drawHelper.DrawCircle(
  1644. clrHighlighted,
  1645. x, y,
  1646. dotSizeHighlighted,
  1647. false );
  1648. }
  1649. else
  1650. {
  1651. drawHelper.DrawCircle(
  1652. start->selected ? clrSelected : clr,
  1653. x, y,
  1654. start->selected ? dotSizeSelected : dotsize,
  1655. true );
  1656. }
  1657. }
  1658. }
  1659. int RampTool::NumSamples()
  1660. {
  1661. CChoreoEvent *e = GetSafeEvent();
  1662. if ( !e )
  1663. return 0;
  1664. return e->GetRampCount();
  1665. }
  1666. CExpressionSample *RampTool::GetSample( int idx )
  1667. {
  1668. CChoreoEvent *e = GetSafeEvent();
  1669. if ( !e )
  1670. return NULL;
  1671. return e->GetRamp( idx );
  1672. }
  1673. CExpressionSample *RampTool::GetSampleUnderMouse( int mx, int my, float tolerance /*= FP_RT_SELECTION_TOLERANCE*/ )
  1674. {
  1675. CChoreoEvent *e = GetSafeEvent();
  1676. if ( !e )
  1677. return NULL;
  1678. RECT rcSamples;
  1679. GetSampleTrayRect( rcSamples );
  1680. POINT pt;
  1681. pt.x = mx;
  1682. pt.y = my;
  1683. if ( !PtInRect( &rcSamples, pt ) )
  1684. return NULL;
  1685. pt.y -= rcSamples.top;
  1686. float closest_dist = 9999999.f;
  1687. CExpressionSample *bestsample = NULL;
  1688. int height = rcSamples.bottom - rcSamples.top;
  1689. for ( int i = 0; i < e->GetRampCount(); i++ )
  1690. {
  1691. CExpressionSample *sample = e->GetRamp( i );
  1692. Assert( sample );
  1693. bool clipped = false;
  1694. int px = GetPixelForTimeValue( sample->time, &clipped );
  1695. int py = height * ( 1.0f - sample->value );
  1696. int dx = px - pt.x;
  1697. int dy = py - pt.y;
  1698. float dist = sqrt( (float)(dx * dx + dy * dy) );
  1699. if ( dist < closest_dist )
  1700. {
  1701. bestsample = sample;
  1702. closest_dist = dist;
  1703. }
  1704. }
  1705. // Not close to any of them!!!
  1706. if ( ( tolerance != 0.0f ) &&
  1707. ( closest_dist > tolerance ) )
  1708. return NULL;
  1709. return bestsample;
  1710. }
  1711. //-----------------------------------------------------------------------------
  1712. // Purpose:
  1713. //-----------------------------------------------------------------------------
  1714. void RampTool::SelectPoints( void )
  1715. {
  1716. RECT rcSelection;
  1717. rcSelection.left = m_nStartX < m_nLastX ? m_nStartX : m_nLastX;
  1718. rcSelection.right = m_nStartX < m_nLastX ? m_nLastX : m_nStartX;
  1719. rcSelection.top = m_nStartY < m_nLastY ? m_nStartY : m_nLastY;
  1720. rcSelection.bottom = m_nStartY < m_nLastY ? m_nLastY : m_nStartY;
  1721. int selW = rcSelection.right - rcSelection.left;
  1722. int selH = rcSelection.bottom - rcSelection.top;
  1723. float tolerance = FP_RT_SELECTION_RECTANGLE_TOLERANCE;
  1724. // If they are just clicking and releasing in one spot, capture any items w/in a larger tolerance
  1725. if ( selW <= 2 && selH <= 2 )
  1726. {
  1727. tolerance = FP_RT_SELECTION_TOLERANCE;
  1728. CExpressionSample *sample = GetSampleUnderMouse( rcSelection.left + selW * 0.5f, rcSelection.top + selH * 0.5f );
  1729. if ( sample )
  1730. {
  1731. sample->selected = true;
  1732. return;
  1733. }
  1734. }
  1735. else
  1736. {
  1737. InflateRect( &rcSelection, 3, 3 );
  1738. }
  1739. RECT rcSamples;
  1740. GetSampleTrayRect( rcSamples );
  1741. int height = rcSamples.bottom - rcSamples.top;
  1742. CChoreoEvent *e = GetSafeEvent();
  1743. if ( !e )
  1744. return;
  1745. float duration = e->GetDuration();
  1746. float fleft = (float)GetTimeValueForMouse( rcSelection.left );
  1747. float fright = (float)GetTimeValueForMouse( rcSelection.right );
  1748. //fleft *= duration;
  1749. //fright *= duration;
  1750. float ftop = (float)( rcSelection.top - rcSamples.top ) / (float)height;
  1751. float fbottom = (float)( rcSelection.bottom - rcSamples.top ) / (float)height;
  1752. fleft = clamp( fleft, 0.0f, duration );
  1753. fright = clamp( fright, 0.0f, duration );
  1754. ftop = clamp( ftop, 0.0f, 1.0f );
  1755. fbottom = clamp( fbottom, 0.0f, 1.0f );
  1756. float timestepperpixel = 1.0f / GetPixelsPerSecond();
  1757. float yfracstepperpixel = 1.0f / (float)height;
  1758. float epsx = tolerance*timestepperpixel;
  1759. float epsy = tolerance*yfracstepperpixel;
  1760. for ( int i = 0; i < e->GetRampCount(); i++ )
  1761. {
  1762. CExpressionSample *sample = e->GetRamp( i );
  1763. if ( sample->time + epsx < fleft )
  1764. continue;
  1765. if ( sample->time - epsx > fright )
  1766. continue;
  1767. if ( (1.0f - sample->value ) + epsy < ftop )
  1768. continue;
  1769. if ( (1.0f - sample->value ) - epsy > fbottom )
  1770. continue;
  1771. sample->selected = true;
  1772. }
  1773. redraw();
  1774. }
  1775. //-----------------------------------------------------------------------------
  1776. // Purpose:
  1777. // Output : int
  1778. //-----------------------------------------------------------------------------
  1779. int RampTool::CountSelected( void )
  1780. {
  1781. return m_pHelper->CountSelected( false );
  1782. }
  1783. void RampTool::MoveSelectedSamples( float dfdx, float dfdy )
  1784. {
  1785. int selecteditems = CountSelected();
  1786. if ( !selecteditems )
  1787. return;
  1788. CChoreoEvent *e = GetSafeEvent();
  1789. if ( !e )
  1790. return;
  1791. int c = e->GetRampCount();
  1792. float duration = e->GetDuration();
  1793. //dfdx *= duration;
  1794. for ( int i = 0; i < c; i++ )
  1795. {
  1796. CExpressionSample *sample = e->GetRamp( i );
  1797. if ( !sample || !sample->selected )
  1798. continue;
  1799. sample->time += dfdx;
  1800. sample->time = clamp( sample->time, 0.0f, duration );
  1801. sample->value -= dfdy;
  1802. sample->value = clamp( sample->value, 0.0f, 1.0f );
  1803. }
  1804. e->ResortRamp();
  1805. redraw();
  1806. }
  1807. //-----------------------------------------------------------------------------
  1808. // Purpose:
  1809. //-----------------------------------------------------------------------------
  1810. void RampTool::DeselectAll( void )
  1811. {
  1812. int i;
  1813. int selecteditems = CountSelected();
  1814. if ( !selecteditems )
  1815. return;
  1816. CChoreoEvent *e = GetSafeEvent();
  1817. Assert( e );
  1818. if ( !e )
  1819. return;
  1820. for ( i = e->GetRampCount() - 1; i >= 0 ; i-- )
  1821. {
  1822. CExpressionSample *sample = e->GetRamp( i );
  1823. sample->selected = false;
  1824. }
  1825. redraw();
  1826. }
  1827. void RampTool::SelectAll( void )
  1828. {
  1829. int i;
  1830. CChoreoEvent *e = GetSafeEvent();
  1831. Assert( e );
  1832. if ( !e )
  1833. return;
  1834. for ( i = e->GetRampCount() - 1; i >= 0 ; i-- )
  1835. {
  1836. CExpressionSample *sample = e->GetRamp( i );
  1837. sample->selected = true;
  1838. }
  1839. redraw();
  1840. }
  1841. void RampTool::Delete( void )
  1842. {
  1843. int i;
  1844. CChoreoEvent *e = GetSafeEvent();
  1845. if ( !e )
  1846. return;
  1847. int selecteditems = CountSelected();
  1848. if ( !selecteditems )
  1849. return;
  1850. PreDataChanged( "Delete ramp points" );
  1851. for ( i = e->GetRampCount() - 1; i >= 0 ; i-- )
  1852. {
  1853. CExpressionSample *sample = e->GetRamp( i );
  1854. if ( !sample->selected )
  1855. continue;
  1856. e->DeleteRamp( i );
  1857. }
  1858. PostDataChanged( "Delete ramp points" );
  1859. }
  1860. void RampTool::OnModelChanged()
  1861. {
  1862. redraw();
  1863. }
  1864. //-----------------------------------------------------------------------------
  1865. // Purpose:
  1866. // Input : *undodescription -
  1867. //-----------------------------------------------------------------------------
  1868. void RampTool::PreDataChanged( char const *undodescription )
  1869. {
  1870. if ( m_nUndoSetup == 0 )
  1871. {
  1872. g_pChoreoView->SetDirty( true );
  1873. g_pChoreoView->PushUndo( undodescription );
  1874. }
  1875. ++m_nUndoSetup;
  1876. }
  1877. //-----------------------------------------------------------------------------
  1878. // Purpose:
  1879. // Input : *redodescription -
  1880. //-----------------------------------------------------------------------------
  1881. void RampTool::PostDataChanged( char const *redodescription )
  1882. {
  1883. --m_nUndoSetup;
  1884. if ( m_nUndoSetup == 0 )
  1885. {
  1886. g_pChoreoView->PushRedo( redodescription );
  1887. redraw();
  1888. }
  1889. }
  1890. void RampTool::SetMousePositionForEvent( mxEvent *event )
  1891. {
  1892. POINT pt;
  1893. GetCursorPos( &pt );
  1894. ScreenToClient( (HWND)getHandle(), &pt );
  1895. event->x = pt.x;
  1896. event->y = pt.y;
  1897. }
  1898. void RampTool::OnEdgeProperties()
  1899. {
  1900. CChoreoEvent *e = GetSafeEvent();
  1901. if ( !e )
  1902. return;
  1903. CEdgePropertiesParams params;
  1904. Q_memset( &params, 0, sizeof( params ) );
  1905. Q_strcpy( params.m_szDialogTitle, "Edge Properties" );
  1906. params.SetFromCurve( e->GetRamp() );
  1907. if ( !EdgeProperties( &params ) )
  1908. {
  1909. return;
  1910. }
  1911. char *undotext = "Change Event Ramp Edge Properties";
  1912. PreDataChanged( undotext );
  1913. // Apply changes.
  1914. params.ApplyToCurve( e->GetRamp() );
  1915. PostDataChanged( undotext );
  1916. }
  1917. void RampTool::GetWorkList( bool reflect, CUtlVector< RampTool * >& list )
  1918. {
  1919. NOTE_UNUSED( reflect );
  1920. list.AddToTail( this );
  1921. }