Counter Strike : Global Offensive Source Code
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.

843 lines
26 KiB

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