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.

777 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Mouse input routines
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #if defined( WIN32 ) && !defined( _X360 )
  10. #define _WIN32_WINNT 0x0502
  11. #include <windows.h>
  12. #endif
  13. #include "cbase.h"
  14. #include "hud.h"
  15. #include "cdll_int.h"
  16. #include "kbutton.h"
  17. #include "basehandle.h"
  18. #include "usercmd.h"
  19. #include "input.h"
  20. #include "iviewrender.h"
  21. #include "iclientmode.h"
  22. #include "tier0/icommandline.h"
  23. #include "vgui/ISurface.h"
  24. #include "vgui_controls/Controls.h"
  25. #include "vgui/Cursor.h"
  26. #include "cdll_client_int.h"
  27. #include "cdll_util.h"
  28. #include "tier1/convar_serverbounded.h"
  29. #include "cam_thirdperson.h"
  30. #include "inputsystem/iinputsystem.h"
  31. #if defined( _X360 )
  32. #include "xbox/xbox_win32stubs.h"
  33. #endif
  34. // memdbgon must be the last include file in a .cpp file!!!
  35. #include "tier0/memdbgon.h"
  36. // up / down
  37. #define PITCH 0
  38. // left / right
  39. #define YAW 1
  40. #ifdef PORTAL
  41. bool g_bUpsideDown = false; // Set when the player is upside down in Portal to invert the mouse.
  42. #endif //#ifdef PORTAL
  43. extern ConVar lookstrafe;
  44. extern ConVar cl_pitchdown;
  45. extern ConVar cl_pitchup;
  46. extern const ConVar *sv_cheats;
  47. class ConVar_m_pitch : public ConVar_ServerBounded
  48. {
  49. public:
  50. ConVar_m_pitch() :
  51. ConVar_ServerBounded( "m_pitch","0.022", FCVAR_ARCHIVE, "Mouse pitch factor." )
  52. {
  53. }
  54. virtual float GetFloat() const
  55. {
  56. if ( !sv_cheats )
  57. sv_cheats = cvar->FindVar( "sv_cheats" );
  58. // If sv_cheats is on then it can be anything.
  59. float flBaseValue = GetBaseFloatValue();
  60. if ( !sv_cheats || sv_cheats->GetBool() )
  61. return flBaseValue;
  62. // If sv_cheats is off than it can only be 0.022 or -0.022 (if they've reversed the mouse in the options).
  63. if ( flBaseValue > 0 )
  64. return 0.022f;
  65. else
  66. return -0.022f;
  67. }
  68. } cvar_m_pitch;
  69. ConVar_ServerBounded *m_pitch = &cvar_m_pitch;
  70. extern ConVar cam_idealyaw;
  71. extern ConVar cam_idealpitch;
  72. extern ConVar thirdperson_platformer;
  73. static ConVar m_filter( "m_filter","0", FCVAR_ARCHIVE, "Mouse filtering (set this to 1 to average the mouse over 2 frames)." );
  74. ConVar sensitivity( "sensitivity","3", FCVAR_ARCHIVE, "Mouse sensitivity.", true, 0.0001f, true, 10000000 );
  75. static ConVar m_side( "m_side","0.8", FCVAR_ARCHIVE, "Mouse side factor." );
  76. static ConVar m_yaw( "m_yaw","0.022", FCVAR_ARCHIVE, "Mouse yaw factor." );
  77. static ConVar m_forward( "m_forward","1", FCVAR_ARCHIVE, "Mouse forward factor." );
  78. static ConVar m_customaccel( "m_customaccel", "0", FCVAR_ARCHIVE, "Custom mouse acceleration:"
  79. "\n0: custom accelaration disabled"
  80. "\n1: mouse_acceleration = min(m_customaccel_max, pow(raw_mouse_delta, m_customaccel_exponent) * m_customaccel_scale + sensitivity)"
  81. "\n2: Same as 1, with but x and y sensitivity are scaled by m_pitch and m_yaw respectively."
  82. "\n3: mouse_acceleration = pow(raw_mouse_delta, m_customaccel_exponent - 1) * sensitivity"
  83. );
  84. static ConVar m_customaccel_scale( "m_customaccel_scale", "0.04", FCVAR_ARCHIVE, "Custom mouse acceleration value.", true, 0, false, 0.0f );
  85. static ConVar m_customaccel_max( "m_customaccel_max", "0", FCVAR_ARCHIVE, "Max mouse move scale factor, 0 for no limit" );
  86. static ConVar m_customaccel_exponent( "m_customaccel_exponent", "1", FCVAR_ARCHIVE, "Mouse move is raised to this power before being scaled by scale factor.", true, 1.0f, false, 0.0f);
  87. static ConVar m_mousespeed( "m_mousespeed", "1", FCVAR_ARCHIVE, "Windows mouse acceleration (0 to disable, 1 to enable [Windows 2000: enable initial threshold], 2 to enable secondary threshold [Windows 2000 only]).", true, 0, true, 2 );
  88. static ConVar m_mouseaccel1( "m_mouseaccel1", "0", FCVAR_ARCHIVE, "Windows mouse acceleration initial threshold (2x movement).", true, 0, false, 0.0f );
  89. static ConVar m_mouseaccel2( "m_mouseaccel2", "0", FCVAR_ARCHIVE, "Windows mouse acceleration secondary threshold (4x movement).", true, 0, false, 0.0f );
  90. #ifdef OSX
  91. static ConVar m_rawinput( "m_rawinput", "1", FCVAR_ARCHIVE, "Use Raw Input for mouse input.");
  92. #else
  93. static ConVar m_rawinput( "m_rawinput", "0", FCVAR_ARCHIVE, "Use Raw Input for mouse input.");
  94. #endif
  95. #if DEBUG
  96. ConVar cl_mouselook( "cl_mouselook", "1", FCVAR_ARCHIVE, "Set to 1 to use mouse for look, 0 for keyboard look." );
  97. #else
  98. ConVar cl_mouselook( "cl_mouselook", "1", FCVAR_ARCHIVE | FCVAR_NOT_CONNECTED, "Set to 1 to use mouse for look, 0 for keyboard look. Cannot be set while connected to a server." );
  99. #endif
  100. ConVar cl_mouseenable( "cl_mouseenable", "1" );
  101. // From other modules...
  102. void GetVGUICursorPos( int& x, int& y );
  103. void SetVGUICursorPos( int x, int y );
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Hides cursor and starts accumulation/re-centering
  106. //-----------------------------------------------------------------------------
  107. void CInput::ActivateMouse (void)
  108. {
  109. if ( m_fMouseActive )
  110. return;
  111. if ( m_fMouseInitialized )
  112. {
  113. if ( m_fMouseParmsValid )
  114. {
  115. #if defined( PLATFORM_WINDOWS )
  116. m_fRestoreSPI = SystemParametersInfo (SPI_SETMOUSE, 0, m_rgNewMouseParms, 0) ? true : false;
  117. #endif
  118. }
  119. m_fMouseActive = true;
  120. ResetMouse();
  121. #if !defined( PLATFORM_WINDOWS )
  122. int dx, dy;
  123. engine->GetMouseDelta( dx, dy, true );
  124. #endif
  125. // Clear accumulated error, too
  126. m_flAccumulatedMouseXMovement = 0;
  127. m_flAccumulatedMouseYMovement = 0;
  128. // clear raw mouse accumulated data
  129. int rawX, rawY;
  130. inputsystem->GetRawMouseAccumulators(rawX, rawY);
  131. }
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Purpose: Gives back the cursor and stops centering of mouse
  135. //-----------------------------------------------------------------------------
  136. void CInput::DeactivateMouse (void)
  137. {
  138. // This gets called whenever the mouse should be inactive. We only respond to it if we had
  139. // previously activated the mouse. We'll show the cursor in here.
  140. if ( !m_fMouseActive )
  141. return;
  142. if ( m_fMouseInitialized )
  143. {
  144. if ( m_fRestoreSPI )
  145. {
  146. #if defined( PLATFORM_WINDOWS )
  147. SystemParametersInfo( SPI_SETMOUSE, 0, m_rgOrigMouseParms, 0 );
  148. #endif
  149. }
  150. m_fMouseActive = false;
  151. vgui::surface()->SetCursor( vgui::dc_arrow );
  152. #if !defined( PLATFORM_WINDOWS )
  153. // now put the mouse back in the middle of the screen
  154. ResetMouse();
  155. #endif
  156. // Clear accumulated error, too
  157. m_flAccumulatedMouseXMovement = 0;
  158. m_flAccumulatedMouseYMovement = 0;
  159. }
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. void CInput::CheckMouseAcclerationVars()
  165. {
  166. // Don't change them if the mouse is inactive, invalid, or not using parameters for restore
  167. if ( !m_fMouseActive ||
  168. !m_fMouseInitialized ||
  169. !m_fMouseParmsValid ||
  170. !m_fRestoreSPI )
  171. {
  172. return;
  173. }
  174. int values[ NUM_MOUSE_PARAMS ];
  175. values[ MOUSE_SPEED_FACTOR ] = m_mousespeed.GetInt();
  176. values[ MOUSE_ACCEL_THRESHHOLD1 ] = m_mouseaccel1.GetInt();
  177. values[ MOUSE_ACCEL_THRESHHOLD2 ] = m_mouseaccel2.GetInt();
  178. bool dirty = false;
  179. int i;
  180. for ( i = 0; i < NUM_MOUSE_PARAMS; i++ )
  181. {
  182. if ( !m_rgCheckMouseParam[ i ] )
  183. continue;
  184. if ( values[ i ] != m_rgNewMouseParms[ i ] )
  185. {
  186. dirty = true;
  187. m_rgNewMouseParms[ i ] = values[ i ];
  188. char const *name = "";
  189. switch ( i )
  190. {
  191. default:
  192. case MOUSE_SPEED_FACTOR:
  193. name = "m_mousespeed";
  194. break;
  195. case MOUSE_ACCEL_THRESHHOLD1:
  196. name = "m_mouseaccel1";
  197. break;
  198. case MOUSE_ACCEL_THRESHHOLD2:
  199. name = "m_mouseaccel2";
  200. break;
  201. }
  202. char sz[ 256 ];
  203. Q_snprintf( sz, sizeof( sz ), "Mouse parameter '%s' set to %i\n", name, values[ i ] );
  204. DevMsg( "%s", sz );
  205. }
  206. }
  207. if ( dirty )
  208. {
  209. // Update them
  210. #ifdef WIN32
  211. m_fRestoreSPI = SystemParametersInfo( SPI_SETMOUSE, 0, m_rgNewMouseParms, 0 ) ? true : false;
  212. #endif
  213. }
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose: One-time initialization
  217. //-----------------------------------------------------------------------------
  218. void CInput::Init_Mouse (void)
  219. {
  220. if ( CommandLine()->FindParm("-nomouse" ) )
  221. return;
  222. m_flPreviousMouseXPosition = 0.0f;
  223. m_flPreviousMouseYPosition = 0.0f;
  224. m_fMouseInitialized = true;
  225. m_fMouseParmsValid = false;
  226. if ( CommandLine()->FindParm ("-useforcedmparms" ) )
  227. {
  228. #ifdef WIN32
  229. m_fMouseParmsValid = SystemParametersInfo( SPI_GETMOUSE, 0, m_rgOrigMouseParms, 0 ) ? true : false;
  230. #else
  231. m_fMouseParmsValid = false;
  232. #endif
  233. if ( m_fMouseParmsValid )
  234. {
  235. if ( CommandLine()->FindParm ("-noforcemspd" ) )
  236. {
  237. m_rgNewMouseParms[ MOUSE_SPEED_FACTOR ] = m_rgOrigMouseParms[ MOUSE_SPEED_FACTOR ];
  238. /*
  239. int mouseAccel[3];
  240. SystemParametersInfo(SPI_GETMOUSE, 0, &mouseAccel, 0); mouseAccel[2] = 0;
  241. bool ok = SystemParametersInfo(SPI_SETMOUSE, 0, &mouseAccel, SPIF_UPDATEINIFILE);
  242. // Now check registry and close/re-open Control Panel > Mouse and see 'Enhance pointer precision' is OFF
  243. mouseAccel[2] = 1;
  244. ok = SystemParametersInfo(SPI_SETMOUSE, 0, &mouseAccel, SPIF_UPDATEINIFILE);
  245. // Now check registry and close/re-open Control Panel > Mouse and see 'Enhance pointer precision' is ON
  246. */
  247. }
  248. else
  249. {
  250. m_rgCheckMouseParam[ MOUSE_SPEED_FACTOR ] = 1;
  251. }
  252. if ( CommandLine()->FindParm ("-noforcemaccel" ) )
  253. {
  254. m_rgNewMouseParms[ MOUSE_ACCEL_THRESHHOLD1 ] = m_rgOrigMouseParms[ MOUSE_ACCEL_THRESHHOLD1 ];
  255. m_rgNewMouseParms[ MOUSE_ACCEL_THRESHHOLD2 ] = m_rgOrigMouseParms[ MOUSE_ACCEL_THRESHHOLD2 ];
  256. }
  257. else
  258. {
  259. m_rgCheckMouseParam[ MOUSE_ACCEL_THRESHHOLD1 ] = true;
  260. m_rgCheckMouseParam[ MOUSE_ACCEL_THRESHHOLD2 ] = true;
  261. }
  262. }
  263. }
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose: Get the center point of the engine window
  267. // Input : int&x -
  268. // y -
  269. //-----------------------------------------------------------------------------
  270. void CInput::GetWindowCenter( int&x, int& y )
  271. {
  272. int w, h;
  273. engine->GetScreenSize( w, h );
  274. x = w >> 1;
  275. y = h >> 1;
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Purpose: Recenter the mouse
  279. //-----------------------------------------------------------------------------
  280. void CInput::ResetMouse( void )
  281. {
  282. int x, y;
  283. GetWindowCenter( x, y );
  284. SetMousePos( x, y );
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose: GetAccumulatedMouse -- the mouse can be sampled multiple times per frame and
  288. // these results are accumulated each time. This function gets the accumulated mouse changes and resets the accumulators
  289. // Input : *mx -
  290. // *my -
  291. //-----------------------------------------------------------------------------
  292. void CInput::GetAccumulatedMouseDeltasAndResetAccumulators( float *mx, float *my )
  293. {
  294. Assert( mx );
  295. Assert( my );
  296. *mx = m_flAccumulatedMouseXMovement;
  297. *my = m_flAccumulatedMouseYMovement;
  298. if ( m_rawinput.GetBool() )
  299. {
  300. int rawMouseX, rawMouseY;
  301. if ( inputsystem->GetRawMouseAccumulators(rawMouseX, rawMouseY) )
  302. {
  303. *mx = (float)rawMouseX;
  304. *my = (float)rawMouseY;
  305. }
  306. }
  307. m_flAccumulatedMouseXMovement = 0;
  308. m_flAccumulatedMouseYMovement = 0;
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose: GetMouseDelta -- Filters the mouse and stores results in old position
  312. // Input : mx -
  313. // my -
  314. // *oldx -
  315. // *oldy -
  316. // *x -
  317. // *y -
  318. //-----------------------------------------------------------------------------
  319. void CInput::GetMouseDelta( float inmousex, float inmousey, float *pOutMouseX, float *pOutMouseY )
  320. {
  321. // Apply filtering?
  322. if ( m_filter.GetBool() )
  323. {
  324. // Average over last two samples
  325. *pOutMouseX = ( inmousex + m_flPreviousMouseXPosition ) * 0.5f;
  326. *pOutMouseY = ( inmousey + m_flPreviousMouseYPosition ) * 0.5f;
  327. }
  328. else
  329. {
  330. *pOutMouseX = inmousex;
  331. *pOutMouseY = inmousey;
  332. }
  333. // Latch previous
  334. m_flPreviousMouseXPosition = inmousex;
  335. m_flPreviousMouseYPosition = inmousey;
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Purpose: Multiplies mouse values by sensitivity. Note that for windows mouse settings
  339. // the input x,y offsets are already scaled based on that. The custom acceleration, therefore,
  340. // is totally engine-specific and applies as a post-process to allow more user tuning.
  341. // Input : *x -
  342. // *y -
  343. //-----------------------------------------------------------------------------
  344. void CInput::ScaleMouse( float *x, float *y )
  345. {
  346. float mx = *x;
  347. float my = *y;
  348. float mouse_sensitivity = ( gHUD.GetSensitivity() != 0 )
  349. ? gHUD.GetSensitivity() : sensitivity.GetFloat();
  350. if ( m_customaccel.GetInt() == 1 || m_customaccel.GetInt() == 2 )
  351. {
  352. float raw_mouse_movement_distance = sqrt( mx * mx + my * my );
  353. float acceleration_scale = m_customaccel_scale.GetFloat();
  354. float accelerated_sensitivity_max = m_customaccel_max.GetFloat();
  355. float accelerated_sensitivity_exponent = m_customaccel_exponent.GetFloat();
  356. float accelerated_sensitivity = ( (float)pow( raw_mouse_movement_distance, accelerated_sensitivity_exponent ) * acceleration_scale + mouse_sensitivity );
  357. if ( accelerated_sensitivity_max > 0.0001f &&
  358. accelerated_sensitivity > accelerated_sensitivity_max )
  359. {
  360. accelerated_sensitivity = accelerated_sensitivity_max;
  361. }
  362. *x *= accelerated_sensitivity;
  363. *y *= accelerated_sensitivity;
  364. // Further re-scale by yaw and pitch magnitude if user requests alternate mode 2/4
  365. // This means that they will need to up their value for m_customaccel_scale greatly (>40x) since m_pitch/yaw default
  366. // to 0.022
  367. if ( m_customaccel.GetInt() == 2 || m_customaccel.GetInt() == 4 )
  368. {
  369. *x *= m_yaw.GetFloat();
  370. *y *= m_pitch->GetFloat();
  371. }
  372. }
  373. else if ( m_customaccel.GetInt() == 3 )
  374. {
  375. float raw_mouse_movement_distance_squared = mx * mx + my * my;
  376. float fExp = MAX(0.0f, (m_customaccel_exponent.GetFloat() - 1.0f) / 2.0f);
  377. float accelerated_sensitivity = powf( raw_mouse_movement_distance_squared, fExp ) * mouse_sensitivity;
  378. *x *= accelerated_sensitivity;
  379. *y *= accelerated_sensitivity;
  380. }
  381. else
  382. {
  383. *x *= mouse_sensitivity;
  384. *y *= mouse_sensitivity;
  385. }
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Purpose: ApplyMouse -- applies mouse deltas to CUserCmd
  389. // Input : viewangles -
  390. // *cmd -
  391. // mouse_x -
  392. // mouse_y -
  393. //-----------------------------------------------------------------------------
  394. void CInput::ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y )
  395. {
  396. if ( !((in_strafe.state & 1) || lookstrafe.GetInt()) )
  397. {
  398. #ifdef PORTAL
  399. if ( g_bUpsideDown )
  400. {
  401. viewangles[ YAW ] += m_yaw.GetFloat() * mouse_x;
  402. }
  403. else
  404. #endif //#ifdef PORTAL
  405. {
  406. if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
  407. {
  408. if ( mouse_x )
  409. {
  410. Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
  411. // use the mouse to orbit the camera around the player, and update the idealAngle
  412. vTempOffset[ YAW ] -= m_yaw.GetFloat() * mouse_x;
  413. cam_idealyaw.SetValue( vTempOffset[ YAW ] - viewangles[ YAW ] );
  414. g_ThirdPersonManager.SetCameraOffsetAngles( vTempOffset );
  415. // why doesn't this work??? CInput::AdjustYaw is why
  416. //cam_idealyaw.SetValue( cam_idealyaw.GetFloat() - m_yaw.GetFloat() * mouse_x );
  417. }
  418. }
  419. else
  420. {
  421. // Otherwize, use mouse to spin around vertical axis
  422. viewangles[YAW] -= CAM_CapYaw( m_yaw.GetFloat() * mouse_x );
  423. }
  424. }
  425. }
  426. else
  427. {
  428. // If holding strafe key or mlooking and have lookstrafe set to true, then apply
  429. // horizontal mouse movement to sidemove.
  430. cmd->sidemove += m_side.GetFloat() * mouse_x;
  431. }
  432. // If mouselooking and not holding strafe key, then use vertical mouse
  433. // to adjust view pitch.
  434. if (!(in_strafe.state & 1))
  435. {
  436. #ifdef PORTAL
  437. if ( g_bUpsideDown )
  438. {
  439. viewangles[PITCH] -= m_pitch->GetFloat() * mouse_y;
  440. }
  441. else
  442. #endif //#ifdef PORTAL
  443. {
  444. if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
  445. {
  446. if ( mouse_y )
  447. {
  448. Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
  449. // use the mouse to orbit the camera around the player, and update the idealAngle
  450. vTempOffset[ PITCH ] += m_pitch->GetFloat() * mouse_y;
  451. cam_idealpitch.SetValue( vTempOffset[ PITCH ] - viewangles[ PITCH ] );
  452. g_ThirdPersonManager.SetCameraOffsetAngles( vTempOffset );
  453. // why doesn't this work??? CInput::AdjustYaw is why
  454. //cam_idealpitch.SetValue( cam_idealpitch.GetFloat() + m_pitch->GetFloat() * mouse_y );
  455. }
  456. }
  457. else
  458. {
  459. viewangles[PITCH] += CAM_CapPitch( m_pitch->GetFloat() * mouse_y );
  460. }
  461. // Check pitch bounds
  462. if (viewangles[PITCH] > cl_pitchdown.GetFloat())
  463. {
  464. viewangles[PITCH] = cl_pitchdown.GetFloat();
  465. }
  466. if (viewangles[PITCH] < -cl_pitchup.GetFloat())
  467. {
  468. viewangles[PITCH] = -cl_pitchup.GetFloat();
  469. }
  470. }
  471. }
  472. else
  473. {
  474. // Otherwise if holding strafe key and noclipping, then move upward
  475. /* if ((in_strafe.state & 1) && IsNoClipping() )
  476. {
  477. cmd->upmove -= m_forward.GetFloat() * mouse_y;
  478. }
  479. else */
  480. {
  481. // Default is to apply vertical mouse movement as a forward key press.
  482. cmd->forwardmove -= m_forward.GetFloat() * mouse_y;
  483. }
  484. }
  485. // Finally, add mouse state to usercmd.
  486. // NOTE: Does rounding to int cause any issues? ywb 1/17/04
  487. cmd->mousedx = (int)mouse_x;
  488. cmd->mousedy = (int)mouse_y;
  489. }
  490. //-----------------------------------------------------------------------------
  491. // Purpose: AccumulateMouse
  492. //-----------------------------------------------------------------------------
  493. void CInput::AccumulateMouse( void )
  494. {
  495. if( !cl_mouseenable.GetBool() )
  496. {
  497. return;
  498. }
  499. if( !cl_mouselook.GetBool() )
  500. {
  501. return;
  502. }
  503. if ( m_rawinput.GetBool() )
  504. {
  505. return;
  506. }
  507. int w, h;
  508. engine->GetScreenSize( w, h );
  509. // x,y = screen center
  510. int x = w >> 1; x;
  511. int y = h >> 1; y;
  512. //only accumulate mouse if we are not moving the camera with the mouse
  513. if ( !m_fCameraInterceptingMouse && vgui::surface()->IsCursorLocked() )
  514. {
  515. //Assert( !vgui::surface()->IsCursorVisible() );
  516. // By design, we follow the old mouse path even when using SDL for Windows, to retain old mouse behavior.
  517. #if defined( PLATFORM_WINDOWS )
  518. int current_posx, current_posy;
  519. GetMousePos(current_posx, current_posy);
  520. m_flAccumulatedMouseXMovement += current_posx - x;
  521. m_flAccumulatedMouseYMovement += current_posy - y;
  522. #elif defined( USE_SDL )
  523. int dx, dy;
  524. engine->GetMouseDelta( dx, dy );
  525. m_flAccumulatedMouseXMovement += dx;
  526. m_flAccumulatedMouseYMovement += dy;
  527. #else
  528. #error
  529. #endif
  530. // force the mouse to the center, so there's room to move
  531. ResetMouse();
  532. }
  533. else if ( m_fMouseActive )
  534. {
  535. // Clamp
  536. int ox, oy;
  537. GetMousePos( ox, oy );
  538. ox = clamp( ox, 0, w - 1 );
  539. oy = clamp( oy, 0, h - 1 );
  540. SetMousePos( ox, oy );
  541. }
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose: Get raw mouse position
  545. // Input : &ox -
  546. // &oy -
  547. //-----------------------------------------------------------------------------
  548. void CInput::GetMousePos(int &ox, int &oy)
  549. {
  550. GetVGUICursorPos( ox, oy );
  551. }
  552. //-----------------------------------------------------------------------------
  553. // Purpose: Force raw mouse position
  554. // Input : x -
  555. // y -
  556. //-----------------------------------------------------------------------------
  557. void CInput::SetMousePos(int x, int y)
  558. {
  559. SetVGUICursorPos(x, y);
  560. }
  561. //-----------------------------------------------------------------------------
  562. // Purpose: MouseMove -- main entry point for applying mouse
  563. // Input : *cmd -
  564. //-----------------------------------------------------------------------------
  565. void CInput::MouseMove( CUserCmd *cmd )
  566. {
  567. float mouse_x, mouse_y;
  568. float mx, my;
  569. QAngle viewangles;
  570. // Get view angles from engine
  571. engine->GetViewAngles( viewangles );
  572. // Validate mouse speed/acceleration settings
  573. CheckMouseAcclerationVars();
  574. // Don't drift pitch at all while mouselooking.
  575. view->StopPitchDrift ();
  576. //jjb - this disables normal mouse control if the user is trying to
  577. // move the camera, or if the mouse cursor is visible
  578. if ( !m_fCameraInterceptingMouse &&
  579. !vgui::surface()->IsCursorVisible() )
  580. {
  581. // Sample mouse one more time
  582. AccumulateMouse();
  583. // Latch accumulated mouse movements and reset accumulators
  584. GetAccumulatedMouseDeltasAndResetAccumulators( &mx, &my );
  585. // Filter, etc. the delta values and place into mouse_x and mouse_y
  586. GetMouseDelta( mx, my, &mouse_x, &mouse_y );
  587. // Apply scaling factor
  588. ScaleMouse( &mouse_x, &mouse_y );
  589. // Let the client mode at the mouse input before it's used
  590. g_pClientMode->OverrideMouseInput( &mouse_x, &mouse_y );
  591. // Add mouse X/Y movement to cmd
  592. ApplyMouse( viewangles, cmd, mouse_x, mouse_y );
  593. // Re-center the mouse.
  594. ResetMouse();
  595. }
  596. // Store out the new viewangles.
  597. engine->SetViewAngles( viewangles );
  598. }
  599. //-----------------------------------------------------------------------------
  600. // Purpose:
  601. // Input : *mx -
  602. // *my -
  603. // *unclampedx -
  604. // *unclampedy -
  605. //-----------------------------------------------------------------------------
  606. void CInput::GetFullscreenMousePos( int *mx, int *my, int *unclampedx /*=NULL*/, int *unclampedy /*=NULL*/ )
  607. {
  608. Assert( mx );
  609. Assert( my );
  610. if ( !vgui::surface()->IsCursorVisible() )
  611. {
  612. return;
  613. }
  614. int x, y;
  615. GetWindowCenter( x, y );
  616. int current_posx, current_posy;
  617. GetMousePos(current_posx, current_posy);
  618. current_posx -= x;
  619. current_posy -= y;
  620. // Now need to add back in mid point of viewport
  621. //
  622. int w, h;
  623. vgui::surface()->GetScreenSize( w, h );
  624. current_posx += w / 2;
  625. current_posy += h / 2;
  626. if ( unclampedx )
  627. {
  628. *unclampedx = current_posx;
  629. }
  630. if ( unclampedy )
  631. {
  632. *unclampedy = current_posy;
  633. }
  634. // Clamp
  635. current_posx = MAX( 0, current_posx );
  636. current_posx = MIN( ScreenWidth(), current_posx );
  637. current_posy = MAX( 0, current_posy );
  638. current_posy = MIN( ScreenHeight(), current_posy );
  639. *mx = current_posx;
  640. *my = current_posy;
  641. }
  642. //-----------------------------------------------------------------------------
  643. // Purpose:
  644. // Input : mx -
  645. // my -
  646. //-----------------------------------------------------------------------------
  647. void CInput::SetFullscreenMousePos( int mx, int my )
  648. {
  649. SetMousePos( mx, my );
  650. }
  651. //-----------------------------------------------------------------------------
  652. // Purpose: ClearStates -- Resets mouse accumulators so you don't get a pop when returning to trapped mouse
  653. //-----------------------------------------------------------------------------
  654. void CInput::ClearStates (void)
  655. {
  656. if ( !m_fMouseActive )
  657. return;
  658. m_flAccumulatedMouseXMovement = 0;
  659. m_flAccumulatedMouseYMovement = 0;
  660. // clear raw mouse accumulated data
  661. int rawX, rawY;
  662. inputsystem->GetRawMouseAccumulators(rawX, rawY);
  663. }