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.

306 lines
8.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "hud_crosshair.h"
  10. #include "iclientmode.h"
  11. #include "view.h"
  12. #include "vgui_controls/Controls.h"
  13. #include "vgui/ISurface.h"
  14. #include "ivrenderview.h"
  15. #include "materialsystem/imaterialsystem.h"
  16. #include "VGuiMatSurface/IMatSystemSurface.h"
  17. #include "client_virtualreality.h"
  18. #include "sourcevr/isourcevirtualreality.h"
  19. #ifdef SIXENSE
  20. #include "sixense/in_sixense.h"
  21. #endif
  22. #ifdef PORTAL
  23. #include "c_portal_player.h"
  24. #endif // PORTAL
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include "tier0/memdbgon.h"
  27. ConVar crosshair( "crosshair", "1", FCVAR_ARCHIVE );
  28. ConVar cl_observercrosshair( "cl_observercrosshair", "1", FCVAR_ARCHIVE );
  29. using namespace vgui;
  30. int ScreenTransform( const Vector& point, Vector& screen );
  31. #ifdef TF_CLIENT_DLL
  32. // If running TF, we use CHudTFCrosshair instead (which is derived from CHudCrosshair)
  33. #else
  34. DECLARE_HUDELEMENT( CHudCrosshair );
  35. #endif
  36. CHudCrosshair::CHudCrosshair( const char *pElementName ) :
  37. CHudElement( pElementName ), BaseClass( NULL, "HudCrosshair" )
  38. {
  39. vgui::Panel *pParent = g_pClientMode->GetViewport();
  40. SetParent( pParent );
  41. m_pCrosshair = 0;
  42. m_clrCrosshair = Color( 0, 0, 0, 0 );
  43. m_vecCrossHairOffsetAngle.Init();
  44. SetHiddenBits( HIDEHUD_PLAYERDEAD | HIDEHUD_CROSSHAIR );
  45. }
  46. CHudCrosshair::~CHudCrosshair()
  47. {
  48. }
  49. void CHudCrosshair::ApplySchemeSettings( IScheme *scheme )
  50. {
  51. BaseClass::ApplySchemeSettings( scheme );
  52. m_pDefaultCrosshair = gHUD.GetIcon("crosshair_default");
  53. SetPaintBackgroundEnabled( false );
  54. SetSize( ScreenWidth(), ScreenHeight() );
  55. SetForceStereoRenderToFrameBuffer( true );
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Save CPU cycles by letting the HUD system early cull
  59. // costly traversal. Called per frame, return true if thinking and
  60. // painting need to occur.
  61. //-----------------------------------------------------------------------------
  62. bool CHudCrosshair::ShouldDraw( void )
  63. {
  64. bool bNeedsDraw;
  65. if ( m_bHideCrosshair )
  66. return false;
  67. C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
  68. if ( !pPlayer )
  69. return false;
  70. C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
  71. if ( pWeapon && !pWeapon->ShouldDrawCrosshair() )
  72. return false;
  73. #ifdef PORTAL
  74. C_Portal_Player *portalPlayer = ToPortalPlayer(pPlayer);
  75. if ( portalPlayer && portalPlayer->IsSuppressingCrosshair() )
  76. return false;
  77. #endif // PORTAL
  78. /* disabled to avoid assuming it's an HL2 player.
  79. // suppress crosshair in zoom.
  80. if ( pPlayer->m_HL2Local.m_bZooming )
  81. return false;
  82. */
  83. // draw a crosshair only if alive or spectating in eye
  84. if ( IsX360() )
  85. {
  86. bNeedsDraw = m_pCrosshair &&
  87. !engine->IsDrawingLoadingImage() &&
  88. !engine->IsPaused() &&
  89. ( !pPlayer->IsSuitEquipped() || g_pGameRules->IsMultiplayer() ) &&
  90. g_pClientMode->ShouldDrawCrosshair() &&
  91. !( pPlayer->GetFlags() & FL_FROZEN ) &&
  92. ( pPlayer->entindex() == render->GetViewEntity() ) &&
  93. ( pPlayer->IsAlive() || ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
  94. }
  95. else
  96. {
  97. bNeedsDraw = m_pCrosshair &&
  98. crosshair.GetInt() &&
  99. !engine->IsDrawingLoadingImage() &&
  100. !engine->IsPaused() &&
  101. g_pClientMode->ShouldDrawCrosshair() &&
  102. !( pPlayer->GetFlags() & FL_FROZEN ) &&
  103. ( pPlayer->entindex() == render->GetViewEntity() ) &&
  104. !pPlayer->IsInVGuiInputMode() &&
  105. ( pPlayer->IsAlive() || ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
  106. }
  107. return ( bNeedsDraw && CHudElement::ShouldDraw() );
  108. }
  109. #ifdef TF_CLIENT_DLL
  110. extern ConVar cl_crosshair_red;
  111. extern ConVar cl_crosshair_green;
  112. extern ConVar cl_crosshair_blue;
  113. extern ConVar cl_crosshair_scale;
  114. #endif
  115. void CHudCrosshair::GetDrawPosition ( float *pX, float *pY, bool *pbBehindCamera, QAngle angleCrosshairOffset )
  116. {
  117. QAngle curViewAngles = CurrentViewAngles();
  118. Vector curViewOrigin = CurrentViewOrigin();
  119. int vx, vy, vw, vh;
  120. vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh );
  121. float screenWidth = vw;
  122. float screenHeight = vh;
  123. float x = screenWidth / 2;
  124. float y = screenHeight / 2;
  125. bool bBehindCamera = false;
  126. C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
  127. if ( ( pPlayer != NULL ) && ( pPlayer->GetObserverMode()==OBS_MODE_NONE ) )
  128. {
  129. bool bUseOffset = false;
  130. Vector vecStart;
  131. Vector vecEnd;
  132. if ( UseVR() )
  133. {
  134. // These are the correct values to use, but they lag the high-speed view data...
  135. vecStart = pPlayer->Weapon_ShootPosition();
  136. Vector vecAimDirection = pPlayer->GetAutoaimVector( 1.0f );
  137. // ...so in some aim modes, they get zapped by something completely up-to-date.
  138. g_ClientVirtualReality.OverrideWeaponHudAimVectors ( &vecStart, &vecAimDirection );
  139. vecEnd = vecStart + vecAimDirection * MAX_TRACE_LENGTH;
  140. bUseOffset = true;
  141. }
  142. #ifdef SIXENSE
  143. // TODO: actually test this Sixsense code interaction with things like HMDs & stereo.
  144. if ( g_pSixenseInput->IsEnabled() && !UseVR() )
  145. {
  146. // Never autoaim a predicted weapon (for now)
  147. vecStart = pPlayer->Weapon_ShootPosition();
  148. Vector aimVector;
  149. AngleVectors( CurrentViewAngles() - g_pSixenseInput->GetViewAngleOffset(), &aimVector );
  150. // calculate where the bullet would go so we can draw the cross appropriately
  151. vecEnd = vecStart + aimVector * MAX_TRACE_LENGTH;
  152. bUseOffset = true;
  153. }
  154. #endif
  155. if ( bUseOffset )
  156. {
  157. trace_t tr;
  158. UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
  159. Vector screen;
  160. screen.Init();
  161. bBehindCamera = ScreenTransform(tr.endpos, screen) != 0;
  162. x = 0.5f * ( 1.0f + screen[0] ) * screenWidth + 0.5f;
  163. y = 0.5f * ( 1.0f - screen[1] ) * screenHeight + 0.5f;
  164. }
  165. }
  166. // MattB - angleCrosshairOffset is the autoaim angle.
  167. // if we're not using autoaim, just draw in the middle of the
  168. // screen
  169. if ( angleCrosshairOffset != vec3_angle )
  170. {
  171. QAngle angles;
  172. Vector forward;
  173. Vector point, screen;
  174. // this code is wrong
  175. angles = curViewAngles + angleCrosshairOffset;
  176. AngleVectors( angles, &forward );
  177. VectorAdd( curViewOrigin, forward, point );
  178. ScreenTransform( point, screen );
  179. x += 0.5f * screen[0] * screenWidth + 0.5f;
  180. y += 0.5f * screen[1] * screenHeight + 0.5f;
  181. }
  182. *pX = x;
  183. *pY = y;
  184. *pbBehindCamera = bBehindCamera;
  185. }
  186. void CHudCrosshair::Paint( void )
  187. {
  188. if ( !m_pCrosshair )
  189. return;
  190. if ( !IsCurrentViewAccessAllowed() )
  191. return;
  192. C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
  193. if ( !pPlayer )
  194. return;
  195. float x, y;
  196. bool bBehindCamera;
  197. GetDrawPosition ( &x, &y, &bBehindCamera, m_vecCrossHairOffsetAngle );
  198. if( bBehindCamera )
  199. return;
  200. float flWeaponScale = 1.f;
  201. int iTextureW = m_pCrosshair->Width();
  202. int iTextureH = m_pCrosshair->Height();
  203. C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
  204. if ( pWeapon )
  205. {
  206. pWeapon->GetWeaponCrosshairScale( flWeaponScale );
  207. }
  208. float flPlayerScale = 1.0f;
  209. #ifdef TF_CLIENT_DLL
  210. Color clr( cl_crosshair_red.GetInt(), cl_crosshair_green.GetInt(), cl_crosshair_blue.GetInt(), 255 );
  211. flPlayerScale = cl_crosshair_scale.GetFloat() / 32.0f; // the player can change the scale in the options/multiplayer tab
  212. #else
  213. Color clr = m_clrCrosshair;
  214. #endif
  215. float flWidth = flWeaponScale * flPlayerScale * (float)iTextureW;
  216. float flHeight = flWeaponScale * flPlayerScale * (float)iTextureH;
  217. int iWidth = (int)( flWidth + 0.5f );
  218. int iHeight = (int)( flHeight + 0.5f );
  219. int iX = (int)( x + 0.5f );
  220. int iY = (int)( y + 0.5f );
  221. m_pCrosshair->DrawSelfCropped (
  222. iX-(iWidth/2), iY-(iHeight/2),
  223. 0, 0,
  224. iTextureW, iTextureH,
  225. iWidth, iHeight,
  226. clr );
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose:
  230. //-----------------------------------------------------------------------------
  231. void CHudCrosshair::SetCrosshairAngle( const QAngle& angle )
  232. {
  233. VectorCopy( angle, m_vecCrossHairOffsetAngle );
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose:
  237. //-----------------------------------------------------------------------------
  238. void CHudCrosshair::SetCrosshair( CHudTexture *texture, const Color& clr )
  239. {
  240. m_pCrosshair = texture;
  241. m_clrCrosshair = clr;
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose: Resets the crosshair back to the default
  245. //-----------------------------------------------------------------------------
  246. void CHudCrosshair::ResetCrosshair()
  247. {
  248. SetCrosshair( m_pDefaultCrosshair, Color(255, 255, 255, 255) );
  249. }