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.

201 lines
4.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "matsys_controls/manipulator.h"
  8. #include "materialsystem/imaterialsystem.h"
  9. #include "vgui/IVGui.h"
  10. #include "vgui/IInput.h"
  11. #include "vgui/ISystem.h"
  12. #include "vgui/MouseCode.h"
  13. #include "mathlib/vector.h"
  14. #include "mathlib/vmatrix.h"
  15. #include "mathlib/mathlib.h"
  16. #include <float.h>
  17. using namespace vgui;
  18. //-----------------------------------------------------------------------------
  19. // local helper functions
  20. //-----------------------------------------------------------------------------
  21. static float UpdateTime( float &flLastTime )
  22. {
  23. float flTime = vgui::system()->GetFrameTime();
  24. float dt = flTime - flLastTime;
  25. flLastTime = flTime;
  26. return dt;
  27. }
  28. //-----------------------------------------------------------------------------
  29. // Base class for manipulators which operate on transforms
  30. //-----------------------------------------------------------------------------
  31. CTransformManipulator::CTransformManipulator( matrix3x4_t *pTransform ) :
  32. m_pTransform( pTransform )
  33. {
  34. }
  35. void CTransformManipulator::SetTransform( matrix3x4_t *pTransform )
  36. {
  37. m_pTransform = pTransform;
  38. }
  39. matrix3x4_t *CTransformManipulator::GetTransform( void )
  40. {
  41. return m_pTransform;
  42. }
  43. //-----------------------------------------------------------------------------
  44. // CPotteryWheelManip - nendo-style camera manipulator
  45. //-----------------------------------------------------------------------------
  46. CPotteryWheelManip::CPotteryWheelManip( matrix3x4_t *pTransform ) :
  47. CTransformManipulator( pTransform ),
  48. m_lastx( -1 ), m_lasty( -1 ),
  49. m_zoom( 100.0f ), m_altitude( 0.0f ), m_azimuth( 0.0f ),
  50. m_prevZoom( 100.0f ), m_prevAltitude( 0.0f ), m_prevAzimuth( 0.0f ),
  51. m_flLastMouseTime( 0.0f ), m_flLastTickTime( 0.0f ),
  52. m_flSpin( 0.0f ), m_bSpin( false )
  53. {
  54. }
  55. void CPotteryWheelManip::OnBeginManipulation( void )
  56. {
  57. m_prevZoom = m_zoom;
  58. m_prevAltitude = m_altitude;
  59. m_prevAzimuth = m_azimuth;
  60. m_flLastMouseTime = m_flLastTickTime = vgui::system()->GetFrameTime();
  61. m_flSpin = 0.0f;
  62. m_bSpin = false;
  63. }
  64. // Sets the zoom level
  65. void CPotteryWheelManip::SetZoom( float flZoom )
  66. {
  67. m_prevZoom = m_zoom = flZoom;
  68. }
  69. void CPotteryWheelManip::OnAcceptManipulation( void )
  70. {
  71. m_flSpin = 0.0f;
  72. m_bSpin = false;
  73. }
  74. void CPotteryWheelManip::OnCancelManipulation( void )
  75. {
  76. m_zoom = m_prevZoom;
  77. m_altitude = m_prevAltitude;
  78. m_azimuth = m_prevAzimuth;
  79. m_flSpin = 0.0f;
  80. m_bSpin = false;
  81. UpdateTransform();
  82. }
  83. void CPotteryWheelManip::OnTick( void )
  84. {
  85. float dt = UpdateTime( m_flLastTickTime );
  86. if ( m_bSpin )
  87. {
  88. m_azimuth += dt * m_flSpin;
  89. UpdateTransform();
  90. }
  91. }
  92. void CPotteryWheelManip::OnCursorMoved( int x, int y )
  93. {
  94. float dt = UpdateTime( m_flLastMouseTime );
  95. if ( m_bSpin )
  96. {
  97. m_lastx = x;
  98. m_lasty = y;
  99. return;
  100. }
  101. if ( input()->IsMouseDown( MOUSE_MIDDLE ) )
  102. {
  103. int dy = y - m_lasty;
  104. int dx = x - m_lastx;
  105. if ( abs( dx ) < 2 * abs( dy ) )
  106. {
  107. UpdateZoom( 0.2f * dy );
  108. }
  109. else
  110. {
  111. m_flSpin = (dt != 0.0f) ? 0.002f * dx / dt : 0.0f;
  112. m_azimuth += 0.002f * dx;
  113. }
  114. }
  115. else
  116. {
  117. m_azimuth += 0.002f * ( x - m_lastx );
  118. m_altitude -= 0.002f * ( y - m_lasty );
  119. m_altitude = max( (float)-M_PI/2, min( (float)M_PI/2, m_altitude ) );
  120. }
  121. m_lastx = x;
  122. m_lasty = y;
  123. UpdateTransform();
  124. }
  125. void CPotteryWheelManip::OnMousePressed( vgui::MouseCode code, int x, int y )
  126. {
  127. UpdateTime( m_flLastMouseTime );
  128. m_lastx = x;
  129. m_lasty = y;
  130. m_bSpin = false;
  131. m_flSpin = 0.0f;
  132. }
  133. void CPotteryWheelManip::OnMouseReleased( vgui::MouseCode code, int x, int y )
  134. {
  135. UpdateTime( m_flLastMouseTime );
  136. if ( code == MOUSE_MIDDLE )
  137. {
  138. m_bSpin = ( fabs( m_flSpin ) > 1.0f );
  139. }
  140. m_lastx = x;
  141. m_lasty = y;
  142. }
  143. void CPotteryWheelManip::OnMouseWheeled( int delta )
  144. {
  145. UpdateTime( m_flLastMouseTime );
  146. UpdateZoom( -10.0f * delta );
  147. UpdateTransform();
  148. }
  149. void CPotteryWheelManip::UpdateTransform()
  150. {
  151. if ( !m_pTransform )
  152. return;
  153. float y = m_zoom * sin( m_altitude );
  154. float xz = m_zoom * cos( m_altitude );
  155. float x = xz * sin( m_azimuth );
  156. float z = xz * cos( m_azimuth );
  157. Vector position(x, y, z);
  158. AngleMatrix( RadianEuler( -m_altitude, m_azimuth, 0 ), position, *m_pTransform );
  159. }
  160. void CPotteryWheelManip::UpdateZoom( float delta )
  161. {
  162. m_zoom *= pow( 1.01f, delta );
  163. }