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.

408 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "hud.h"
  10. #include "hudelement.h"
  11. #include "iclientmode.h"
  12. #include "engine/IEngineSound.h"
  13. #include "vgui_controls/AnimationController.h"
  14. #include "vgui_controls/Controls.h"
  15. #include "vgui_controls/Panel.h"
  16. #include "vgui/ISurface.h"
  17. #include "../hud_crosshair.h"
  18. #include "VGuiMatSurface/IMatSystemSurface.h"
  19. #ifdef SIXENSE
  20. #include "sixense/in_sixense.h"
  21. #include "view.h"
  22. int ScreenTransform( const Vector& point, Vector& screen );
  23. #endif
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. #define HEALTH_WARNING_THRESHOLD 25
  27. static ConVar hud_quickinfo( "hud_quickinfo", "1", FCVAR_ARCHIVE );
  28. extern ConVar crosshair;
  29. #define QUICKINFO_EVENT_DURATION 1.0f
  30. #define QUICKINFO_BRIGHTNESS_FULL 255
  31. #define QUICKINFO_BRIGHTNESS_DIM 64
  32. #define QUICKINFO_FADE_IN_TIME 0.5f
  33. #define QUICKINFO_FADE_OUT_TIME 2.0f
  34. /*
  35. ==================================================
  36. CHUDQuickInfo
  37. ==================================================
  38. */
  39. using namespace vgui;
  40. class CHUDQuickInfo : public CHudElement, public vgui::Panel
  41. {
  42. DECLARE_CLASS_SIMPLE( CHUDQuickInfo, vgui::Panel );
  43. public:
  44. CHUDQuickInfo( const char *pElementName );
  45. void Init( void );
  46. void VidInit( void );
  47. bool ShouldDraw( void );
  48. virtual void OnThink();
  49. virtual void Paint();
  50. virtual void ApplySchemeSettings( IScheme *scheme );
  51. private:
  52. void DrawWarning( int x, int y, CHudTexture *icon, float &time );
  53. void UpdateEventTime( void );
  54. bool EventTimeElapsed( void );
  55. int m_lastAmmo;
  56. int m_lastHealth;
  57. float m_ammoFade;
  58. float m_healthFade;
  59. bool m_warnAmmo;
  60. bool m_warnHealth;
  61. bool m_bFadedOut;
  62. bool m_bDimmed; // Whether or not we are dimmed down
  63. float m_flLastEventTime; // Last active event (controls dimmed state)
  64. CHudTexture *m_icon_c;
  65. CHudTexture *m_icon_rbn; // right bracket
  66. CHudTexture *m_icon_lbn; // left bracket
  67. CHudTexture *m_icon_rb; // right bracket, full
  68. CHudTexture *m_icon_lb; // left bracket, full
  69. CHudTexture *m_icon_rbe; // right bracket, empty
  70. CHudTexture *m_icon_lbe; // left bracket, empty
  71. };
  72. DECLARE_HUDELEMENT( CHUDQuickInfo );
  73. CHUDQuickInfo::CHUDQuickInfo( const char *pElementName ) :
  74. CHudElement( pElementName ), BaseClass( NULL, "HUDQuickInfo" )
  75. {
  76. vgui::Panel *pParent = g_pClientMode->GetViewport();
  77. SetParent( pParent );
  78. SetHiddenBits( HIDEHUD_CROSSHAIR );
  79. }
  80. void CHUDQuickInfo::ApplySchemeSettings( IScheme *scheme )
  81. {
  82. BaseClass::ApplySchemeSettings( scheme );
  83. SetPaintBackgroundEnabled( false );
  84. SetForceStereoRenderToFrameBuffer( true );
  85. }
  86. void CHUDQuickInfo::Init( void )
  87. {
  88. m_ammoFade = 0.0f;
  89. m_healthFade = 0.0f;
  90. m_lastAmmo = 0;
  91. m_lastHealth = 100;
  92. m_warnAmmo = false;
  93. m_warnHealth = false;
  94. m_bFadedOut = false;
  95. m_bDimmed = false;
  96. m_flLastEventTime = 0.0f;
  97. }
  98. void CHUDQuickInfo::VidInit( void )
  99. {
  100. Init();
  101. m_icon_c = gHUD.GetIcon( "crosshair" );
  102. m_icon_rb = gHUD.GetIcon( "crosshair_right_full" );
  103. m_icon_lb = gHUD.GetIcon( "crosshair_left_full" );
  104. m_icon_rbe = gHUD.GetIcon( "crosshair_right_empty" );
  105. m_icon_lbe = gHUD.GetIcon( "crosshair_left_empty" );
  106. m_icon_rbn = gHUD.GetIcon( "crosshair_right" );
  107. m_icon_lbn = gHUD.GetIcon( "crosshair_left" );
  108. }
  109. void CHUDQuickInfo::DrawWarning( int x, int y, CHudTexture *icon, float &time )
  110. {
  111. float scale = (int)( fabs(sin(gpGlobals->curtime*8.0f)) * 128.0);
  112. // Only fade out at the low point of our blink
  113. if ( time <= (gpGlobals->frametime * 200.0f) )
  114. {
  115. if ( scale < 40 )
  116. {
  117. time = 0.0f;
  118. return;
  119. }
  120. else
  121. {
  122. // Counteract the offset below to survive another frame
  123. time += (gpGlobals->frametime * 200.0f);
  124. }
  125. }
  126. // Update our time
  127. time -= (gpGlobals->frametime * 200.0f);
  128. Color caution = gHUD.m_clrCaution;
  129. caution[3] = scale * 255;
  130. icon->DrawSelf( x, y, caution );
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose: Save CPU cycles by letting the HUD system early cull
  134. // costly traversal. Called per frame, return true if thinking and
  135. // painting need to occur.
  136. //-----------------------------------------------------------------------------
  137. bool CHUDQuickInfo::ShouldDraw( void )
  138. {
  139. if ( !m_icon_c || !m_icon_rb || !m_icon_rbe || !m_icon_lb || !m_icon_lbe )
  140. return false;
  141. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  142. if ( player == NULL )
  143. return false;
  144. if ( !crosshair.GetBool() && !IsX360() )
  145. return false;
  146. return ( CHudElement::ShouldDraw() && !engine->IsDrawingLoadingImage() );
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Purpose: Checks if the hud element needs to fade out
  150. //-----------------------------------------------------------------------------
  151. void CHUDQuickInfo::OnThink()
  152. {
  153. BaseClass::OnThink();
  154. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  155. if ( player == NULL )
  156. return;
  157. // see if we should fade in/out
  158. bool bFadeOut = player->IsZoomed();
  159. // check if the state has changed
  160. if ( m_bFadedOut != bFadeOut )
  161. {
  162. m_bFadedOut = bFadeOut;
  163. m_bDimmed = false;
  164. if ( bFadeOut )
  165. {
  166. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "Alpha", 0.0f, 0.0f, 0.25f, vgui::AnimationController::INTERPOLATOR_LINEAR );
  167. }
  168. else
  169. {
  170. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "Alpha", QUICKINFO_BRIGHTNESS_FULL, 0.0f, QUICKINFO_FADE_IN_TIME, vgui::AnimationController::INTERPOLATOR_LINEAR );
  171. }
  172. }
  173. else if ( !m_bFadedOut )
  174. {
  175. // If we're dormant, fade out
  176. if ( EventTimeElapsed() )
  177. {
  178. if ( !m_bDimmed )
  179. {
  180. m_bDimmed = true;
  181. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "Alpha", QUICKINFO_BRIGHTNESS_DIM, 0.0f, QUICKINFO_FADE_OUT_TIME, vgui::AnimationController::INTERPOLATOR_LINEAR );
  182. }
  183. }
  184. else if ( m_bDimmed )
  185. {
  186. // Fade back up, we're active
  187. m_bDimmed = false;
  188. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "Alpha", QUICKINFO_BRIGHTNESS_FULL, 0.0f, QUICKINFO_FADE_IN_TIME, vgui::AnimationController::INTERPOLATOR_LINEAR );
  189. }
  190. }
  191. }
  192. void CHUDQuickInfo::Paint()
  193. {
  194. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  195. if ( player == NULL )
  196. return;
  197. C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
  198. if ( pWeapon == NULL )
  199. return;
  200. float fX, fY;
  201. bool bBehindCamera = false;
  202. CHudCrosshair::GetDrawPosition( &fX, &fY, &bBehindCamera );
  203. // if the crosshair is behind the camera, don't draw it
  204. if( bBehindCamera )
  205. return;
  206. int xCenter = (int)fX;
  207. int yCenter = (int)fY - m_icon_lb->Height() / 2;
  208. float scalar = 138.0f/255.0f;
  209. // Check our health for a warning
  210. int health = player->GetHealth();
  211. if ( health != m_lastHealth )
  212. {
  213. UpdateEventTime();
  214. m_lastHealth = health;
  215. if ( health <= HEALTH_WARNING_THRESHOLD )
  216. {
  217. if ( m_warnHealth == false )
  218. {
  219. m_healthFade = 255;
  220. m_warnHealth = true;
  221. CLocalPlayerFilter filter;
  222. C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HUDQuickInfo.LowHealth" );
  223. }
  224. }
  225. else
  226. {
  227. m_warnHealth = false;
  228. }
  229. }
  230. // Check our ammo for a warning
  231. int ammo = pWeapon->Clip1();
  232. if ( ammo != m_lastAmmo )
  233. {
  234. UpdateEventTime();
  235. m_lastAmmo = ammo;
  236. // Find how far through the current clip we are
  237. float ammoPerc = (float) ammo / (float) pWeapon->GetMaxClip1();
  238. // Warn if we're below a certain percentage of our clip's size
  239. if (( pWeapon->GetMaxClip1() > 1 ) && ( ammoPerc <= ( 1.0f - CLIP_PERC_THRESHOLD )))
  240. {
  241. if ( m_warnAmmo == false )
  242. {
  243. m_ammoFade = 255;
  244. m_warnAmmo = true;
  245. CLocalPlayerFilter filter;
  246. C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HUDQuickInfo.LowAmmo" );
  247. }
  248. }
  249. else
  250. {
  251. m_warnAmmo = false;
  252. }
  253. }
  254. Color clrNormal = gHUD.m_clrNormal;
  255. clrNormal[3] = 255 * scalar;
  256. m_icon_c->DrawSelf( xCenter, yCenter, clrNormal );
  257. if( IsX360() )
  258. {
  259. // Because the fixed reticle draws on half-texels, this rather unsightly hack really helps
  260. // center the appearance of the quickinfo on 360 displays.
  261. xCenter += 1;
  262. }
  263. if ( !hud_quickinfo.GetInt() )
  264. return;
  265. int sinScale = (int)( fabs(sin(gpGlobals->curtime*8.0f)) * 128.0f );
  266. // Update our health
  267. if ( m_healthFade > 0.0f )
  268. {
  269. DrawWarning( xCenter - (m_icon_lb->Width() * 2), yCenter, m_icon_lb, m_healthFade );
  270. }
  271. else
  272. {
  273. float healthPerc = (float) health / 100.0f;
  274. healthPerc = clamp( healthPerc, 0.0f, 1.0f );
  275. Color healthColor = m_warnHealth ? gHUD.m_clrCaution : gHUD.m_clrNormal;
  276. if ( m_warnHealth )
  277. {
  278. healthColor[3] = 255 * sinScale;
  279. }
  280. else
  281. {
  282. healthColor[3] = 255 * scalar;
  283. }
  284. gHUD.DrawIconProgressBar( xCenter - (m_icon_lb->Width() * 2), yCenter, m_icon_lb, m_icon_lbe, ( 1.0f - healthPerc ), healthColor, CHud::HUDPB_VERTICAL );
  285. }
  286. // Update our ammo
  287. if ( m_ammoFade > 0.0f )
  288. {
  289. DrawWarning( xCenter + m_icon_rb->Width(), yCenter, m_icon_rb, m_ammoFade );
  290. }
  291. else
  292. {
  293. float ammoPerc;
  294. if ( pWeapon->GetMaxClip1() <= 0 )
  295. {
  296. ammoPerc = 0.0f;
  297. }
  298. else
  299. {
  300. ammoPerc = 1.0f - ( (float) ammo / (float) pWeapon->GetMaxClip1() );
  301. ammoPerc = clamp( ammoPerc, 0.0f, 1.0f );
  302. }
  303. Color ammoColor = m_warnAmmo ? gHUD.m_clrCaution : gHUD.m_clrNormal;
  304. if ( m_warnAmmo )
  305. {
  306. ammoColor[3] = 255 * sinScale;
  307. }
  308. else
  309. {
  310. ammoColor[3] = 255 * scalar;
  311. }
  312. gHUD.DrawIconProgressBar( xCenter + m_icon_rb->Width(), yCenter, m_icon_rb, m_icon_rbe, ammoPerc, ammoColor, CHud::HUDPB_VERTICAL );
  313. }
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose:
  317. //-----------------------------------------------------------------------------
  318. void CHUDQuickInfo::UpdateEventTime( void )
  319. {
  320. m_flLastEventTime = gpGlobals->curtime;
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose:
  324. // Output : Returns true on success, false on failure.
  325. //-----------------------------------------------------------------------------
  326. bool CHUDQuickInfo::EventTimeElapsed( void )
  327. {
  328. if (( gpGlobals->curtime - m_flLastEventTime ) > QUICKINFO_EVENT_DURATION )
  329. return true;
  330. return false;
  331. }