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.

370 lines
8.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef CURVEEDITORHELPERS_H
  7. #define CURVEEDITORHELPERS_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "mxtk/mx.h"
  12. struct CExpressionSample;
  13. template< class T >
  14. class CCurveEditorHelper
  15. {
  16. public:
  17. CCurveEditorHelper( T *outer );
  18. int GetBestCurveTypeForSelectedSamples( bool reflect );
  19. int CountSelected( bool reflect );
  20. void ChangeCurveType( bool forward, bool shiftdown, bool altdown );
  21. void SetCurveTypeForSelectedSamples( bool reflect, int curvetype );
  22. void SetCurveTypeForSample( int curvetype, CExpressionSample *sample );
  23. void ToggleHoldTypeForSelectedSamples( bool reflect );
  24. void ToggleHoldTypeForSample( CExpressionSample *sample );
  25. bool HelperHandleEvent( mxEvent *event );
  26. private:
  27. T *GetOuter();
  28. private:
  29. T *m_pOuter;
  30. };
  31. template< class T >
  32. CCurveEditorHelper<T>::CCurveEditorHelper( T *pOuter ) :
  33. m_pOuter( pOuter )
  34. {
  35. Assert( pOuter );
  36. }
  37. template< class T >
  38. T *CCurveEditorHelper<T>::GetOuter()
  39. {
  40. return m_pOuter;
  41. }
  42. template< class T >
  43. int CCurveEditorHelper<T>::GetBestCurveTypeForSelectedSamples( bool reflect )
  44. {
  45. int numSelected = CountSelected( reflect );
  46. if ( !numSelected )
  47. return CURVE_DEFAULT;
  48. CUtlMap< int, int > counts( 0, 0, DefLessFunc( int ) );
  49. CUtlVector< T * > workList;
  50. GetOuter()->GetWorkList( reflect, workList );
  51. for ( int w = 0; w < workList.Count(); ++w )
  52. {
  53. int numSamples = workList[ w ]->NumSamples();
  54. if ( !numSamples )
  55. continue;
  56. for ( int i = numSamples - 1; i >= 0 ; i-- )
  57. {
  58. CExpressionSample *sample = workList[ w ]->GetSample( i );
  59. if ( !sample->selected )
  60. continue;
  61. int curveType = sample->GetCurveType();
  62. int idx = counts.Find( curveType );
  63. if ( idx == counts.InvalidIndex() )
  64. {
  65. idx = counts.Insert( curveType, 0 );
  66. }
  67. counts[ idx ]++;
  68. }
  69. }
  70. int maxType = CURVE_DEFAULT;
  71. int maxCount = -1;
  72. for ( int i = counts.FirstInorder(); i != counts.InvalidIndex(); i = counts.NextInorder( i ) )
  73. {
  74. if ( counts[ i ] > maxType )
  75. {
  76. maxCount = counts[ i ];
  77. maxType = counts.Key( i );
  78. }
  79. }
  80. return maxType;
  81. }
  82. template< class T >
  83. int CCurveEditorHelper<T>::CountSelected( bool reflect )
  84. {
  85. int numSelected = 0;
  86. CUtlVector< T * > workList;
  87. GetOuter()->GetWorkList( reflect, workList );
  88. for ( int w = 0; w < workList.Count(); ++w )
  89. {
  90. int numSamples = workList[ w ]->NumSamples();
  91. if ( !numSamples )
  92. continue;
  93. for ( int i = 0 ; i < numSamples; ++i )
  94. {
  95. CExpressionSample *sample = workList[ w ]->GetSample( i );
  96. if ( !sample || !sample->selected )
  97. continue;
  98. ++numSelected;
  99. }
  100. }
  101. return numSelected;
  102. }
  103. template< class T >
  104. void CCurveEditorHelper<T>::ChangeCurveType( bool forward, bool shiftdown, bool altdown )
  105. {
  106. // If holding ctrl and shift, only do inbound
  107. bool inbound = shiftdown;
  108. // if holding ctrl, shift + alt, do both inbound and outbound
  109. bool outbound = !shiftdown || altdown;
  110. // if holding ctrl + alt, do outbound
  111. // if holding just ctrl, do outbound
  112. int numSelected = CountSelected( false );
  113. if ( !numSelected )
  114. return;
  115. int curveType = GetBestCurveTypeForSelectedSamples( false );
  116. int sides[ 2 ];
  117. Interpolator_CurveInterpolatorsForType( curveType, sides[ 0 ], sides[ 1 ] );
  118. int dir = forward ? 1 : -1;
  119. for ( int i = 0; i < 2; ++i )
  120. {
  121. if ( i == 0 && !inbound )
  122. continue;
  123. if ( i == 1 && !outbound )
  124. continue;
  125. sides[ i ] += dir;
  126. if ( sides[ i ] < 0 )
  127. {
  128. sides[ i ] = NUM_INTERPOLATE_TYPES - 1;
  129. }
  130. else if ( sides[ i ] >= NUM_INTERPOLATE_TYPES )
  131. {
  132. sides[ i ] = INTERPOLATE_DEFAULT;
  133. }
  134. }
  135. curveType = MAKE_CURVE_TYPE( sides[ 0 ], sides[ 1 ] );
  136. SetCurveTypeForSelectedSamples( false, curveType );
  137. }
  138. template< class T >
  139. void CCurveEditorHelper<T>::SetCurveTypeForSelectedSamples( bool reflect, int curvetype )
  140. {
  141. int numSelected = CountSelected( reflect );
  142. if ( !numSelected )
  143. return;
  144. GetOuter()->PreDataChanged( "Set curve type" );
  145. CUtlVector< T * > workList;
  146. GetOuter()->GetWorkList( reflect, workList );
  147. for ( int w = 0; w < workList.Count(); ++w )
  148. {
  149. int numSamples = workList[ w ]->NumSamples();
  150. for ( int i = 0 ; i < numSamples; ++i )
  151. {
  152. CExpressionSample *sample = workList[ w ]->GetSample( i );
  153. if ( !sample->selected )
  154. continue;
  155. sample->SetCurveType( curvetype );
  156. }
  157. }
  158. GetOuter()->PostDataChanged( "Set curve type" );
  159. }
  160. template< class T >
  161. void CCurveEditorHelper<T>::SetCurveTypeForSample( int curvetype, CExpressionSample *sample )
  162. {
  163. GetOuter()->PreDataChanged( "Set curve type" );
  164. sample->SetCurveType( curvetype );
  165. GetOuter()->PostDataChanged( "Set curve type" );
  166. }
  167. template< class T >
  168. void CCurveEditorHelper<T>::ToggleHoldTypeForSelectedSamples( bool reflect )
  169. {
  170. int numSelected = CountSelected( reflect );
  171. if ( !numSelected )
  172. return;
  173. GetOuter()->PreDataChanged( "Set hold out value" );
  174. CUtlVector< T * > workList;
  175. GetOuter()->GetWorkList( reflect, workList );
  176. for ( int w = 0; w < workList.Count(); ++w )
  177. {
  178. int numSamples = workList[ w ]->NumSamples();
  179. int newValue = -1;
  180. for ( int i = 0 ; i < numSamples; ++i )
  181. {
  182. CExpressionSample *sample = workList[ w ]->GetSample( i );
  183. if ( !sample->selected )
  184. continue;
  185. // First one controls setting
  186. int l, r;
  187. Interpolator_CurveInterpolatorsForType( sample->GetCurveType(), l, r );
  188. if ( newValue == -1 )
  189. {
  190. newValue = ( r == INTERPOLATE_HOLD ) ? 0 : 1;
  191. }
  192. int newCurveType = MAKE_CURVE_TYPE( l, newValue == 1 ? INTERPOLATE_HOLD : l );
  193. sample->SetCurveType( newCurveType );
  194. }
  195. }
  196. GetOuter()->PostDataChanged( "Set hold out value" );
  197. }
  198. template< class T >
  199. void CCurveEditorHelper<T>::ToggleHoldTypeForSample( CExpressionSample *sample )
  200. {
  201. GetOuter()->PreDataChanged( "Set hold out value" );
  202. int l, r;
  203. Interpolator_CurveInterpolatorsForType( sample->GetCurveType(), l, r );
  204. if ( r == INTERPOLATE_HOLD )
  205. {
  206. r = l;
  207. }
  208. else
  209. {
  210. r = INTERPOLATE_HOLD;
  211. }
  212. int newCurveType = MAKE_CURVE_TYPE( l, r );
  213. sample->SetCurveType( newCurveType );
  214. GetOuter()->PostDataChanged( "Set hold out value" );
  215. }
  216. template< class T >
  217. bool CCurveEditorHelper<T>::HelperHandleEvent( mxEvent *event )
  218. {
  219. bool handled = false;
  220. switch ( event->event )
  221. {
  222. case mxEvent::KeyDown:
  223. {
  224. switch ( event->key )
  225. {
  226. default:
  227. // Hotkey pressed
  228. if ( event->key >= '0' &&
  229. event->key <= '9' )
  230. {
  231. bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
  232. handled = true;
  233. // Get curve type
  234. int curveType = Interpolator_CurveTypeForHotkey( event->key );
  235. if ( curveType >= 0 )
  236. {
  237. if ( CountSelected( shiftdown ) <= 0 )
  238. {
  239. GetOuter()->SetMousePositionForEvent( event );
  240. CExpressionSample *hover = GetOuter()->GetSampleUnderMouse( event->x, event->y, 0.0f );
  241. // Deal with highlighted item
  242. if ( hover )
  243. {
  244. SetCurveTypeForSample( curveType, hover );
  245. }
  246. }
  247. else
  248. {
  249. SetCurveTypeForSelectedSamples( shiftdown, curveType );
  250. }
  251. }
  252. }
  253. break;
  254. case 'H':
  255. {
  256. handled = true;
  257. bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
  258. if ( CountSelected( shiftdown ) <= 0 )
  259. {
  260. GetOuter()->SetMousePositionForEvent( event );
  261. CExpressionSample *hover = GetOuter()->GetSampleUnderMouse( event->x, event->y, 0.0f );
  262. // Deal with highlighted item
  263. if ( hover )
  264. {
  265. ToggleHoldTypeForSample( hover );
  266. }
  267. }
  268. else
  269. {
  270. ToggleHoldTypeForSelectedSamples( shiftdown );
  271. }
  272. }
  273. break;
  274. case VK_UP:
  275. {
  276. bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
  277. bool altdown = GetAsyncKeyState( VK_MENU ) ? true : false;
  278. if ( GetAsyncKeyState( VK_CONTROL ) )
  279. {
  280. ChangeCurveType( false, shiftdown, altdown );
  281. }
  282. }
  283. break;
  284. case VK_DOWN:
  285. {
  286. bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
  287. bool altdown = GetAsyncKeyState( VK_MENU ) ? true : false;
  288. if ( GetAsyncKeyState( VK_CONTROL ) )
  289. {
  290. ChangeCurveType( true, shiftdown, altdown );
  291. }
  292. }
  293. break;
  294. }
  295. }
  296. }
  297. return handled;
  298. }
  299. #endif // CURVEEDITORHELPERS_H