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.
527 lines
16 KiB
527 lines
16 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "hud.h" |
|
#include "hudelement.h" |
|
#include "hud_macros.h" |
|
#include "hud_numericdisplay.h" |
|
#include "iclientmode.h" |
|
#include "c_tf_player.h" |
|
#include "VGuiMatSurface/IMatSystemSurface.h" |
|
#include "materialsystem/imaterial.h" |
|
#include "materialsystem/imesh.h" |
|
#include "materialsystem/imaterialvar.h" |
|
#include "client_virtualreality.h" |
|
#include "sourcevr/isourcevirtualreality.h" |
|
#include <vgui/IScheme.h> |
|
#include <vgui/ISurface.h> |
|
#include <KeyValues.h> |
|
#include <vgui_controls/AnimationController.h> |
|
|
|
//for screenfade |
|
#include "ivieweffects.h" |
|
#include "shake.h" |
|
#include "view_scene.h" |
|
|
|
#include "tf_weapon_sniperrifle.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Figure out where the sniper scope should be drawn. |
|
//----------------------------------------------------------------------------- |
|
void WhereToDrawSniperScope ( int *pX, int *pY, int screenWide, int screenTall ) |
|
{ |
|
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( pPlayer != NULL ) |
|
{ |
|
// These are the correct values to use, but they lag the high-speed view data... |
|
Vector vecStart = pPlayer->Weapon_ShootPosition(); |
|
Vector vecAimDirection = pPlayer->GetAutoaimVector( 1.0f ); |
|
// ...so in some aim modes, they get zapped by something completely up-to-date. |
|
g_ClientVirtualReality.OverrideWeaponHudAimVectors ( &vecStart, &vecAimDirection ); |
|
|
|
Vector vAimPoint; |
|
// Here we just put the aim point a set distance from the viewer - same depth as the HUD. |
|
float fVrHudDistance = g_ClientVirtualReality.GetHUDDistance(); |
|
vAimPoint = vecStart + vecAimDirection * fVrHudDistance; |
|
|
|
Vector screen; |
|
screen.Init(); |
|
ScreenTransform(vAimPoint, screen); |
|
|
|
// screen[0][1] are in range (-1, 1) |
|
float x = 0.5 * ( 1.0f + screen[0] ) * screenWide + 0.5; |
|
float y = 0.5 * ( 1.0f - screen[1] ) * screenTall + 0.5; |
|
|
|
*pX = (int)( x + 0.5f ); |
|
*pY = (int)( y + 0.5f ); |
|
} |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Draws the sniper chargeup meter |
|
//----------------------------------------------------------------------------- |
|
class CHudScopeCharge : public vgui::Panel, public CHudElement |
|
{ |
|
DECLARE_CLASS_SIMPLE( CHudScopeCharge, vgui::Panel ); |
|
|
|
public: |
|
CHudScopeCharge( const char *pElementName ); |
|
virtual ~CHudScopeCharge( void ); |
|
|
|
void Init( void ); |
|
|
|
protected: |
|
virtual void ApplySchemeSettings(vgui::IScheme *scheme); |
|
virtual void Paint( void ); |
|
|
|
private: |
|
int m_iChargeupTexture; |
|
int m_iChargeupTextureWidth; |
|
CPanelAnimationVarAliasType( float, m_iChargeup_xpos, "chargeup_xpos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_iChargeup_ypos, "chargeup_ypos", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_iChargeup_wide, "chargeup_wide", "0", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_iChargeup_tall, "chargeup_tall", "0", "proportional_float" ); |
|
|
|
bool m_bJarateMode; |
|
}; |
|
|
|
DECLARE_HUDELEMENT_DEPTH( CHudScopeCharge, 100 ); |
|
|
|
using namespace vgui; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CHudScopeCharge::CHudScopeCharge( const char *pElementName ) : CHudElement(pElementName), BaseClass(NULL, "HudScopeCharge") |
|
{ |
|
vgui::Panel *pParent = g_pClientMode->GetViewport(); |
|
SetParent( pParent ); |
|
|
|
SetHiddenBits( HIDEHUD_PLAYERDEAD ); |
|
|
|
m_bJarateMode = false; |
|
|
|
m_iChargeupTexture = -1; |
|
} |
|
|
|
CHudScopeCharge::~CHudScopeCharge( void ) |
|
{ |
|
if ( vgui::surface() && m_iChargeupTexture != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iChargeupTexture ); |
|
m_iChargeupTexture = -1; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: standard hud element init function |
|
//----------------------------------------------------------------------------- |
|
void CHudScopeCharge::Init( void ) |
|
{ |
|
if ( m_iChargeupTexture == -1 ) |
|
{ |
|
m_iChargeupTexture = vgui::surface()->CreateNewTextureID(); |
|
vgui::surface()->DrawSetTextureFile(m_iChargeupTexture, "HUD/sniperscope_numbers", true, false); |
|
} |
|
|
|
// Get the texture size |
|
int ignored; |
|
surface()->DrawGetTextureSize( m_iChargeupTexture, m_iChargeupTextureWidth, ignored ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: sets scheme colors |
|
//----------------------------------------------------------------------------- |
|
void CHudScopeCharge::ApplySchemeSettings( vgui::IScheme *scheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings(scheme); |
|
|
|
SetPaintBackgroundEnabled(false); |
|
SetPaintBorderEnabled(false); |
|
|
|
if ( UseVR() ) |
|
{ |
|
// Force it to go direct to the framebuffer. |
|
SetForceStereoRenderToFrameBuffer( true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: draws the zoom effect |
|
//----------------------------------------------------------------------------- |
|
void CHudScopeCharge::Paint( void ) |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
|
|
if ( GetSpectatorTarget() != 0 && GetSpectatorMode() == OBS_MODE_IN_EYE ) |
|
{ |
|
pPlayer = (C_TFPlayer *)UTIL_PlayerByIndex( GetSpectatorTarget() ); |
|
} |
|
|
|
if ( !pPlayer ) |
|
return; |
|
|
|
if ( !pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) ) |
|
return; |
|
|
|
// Make sure the current weapon is a sniper rifle |
|
CTFSniperRifle *pWeapon = assert_cast<CTFSniperRifle*>(pPlayer->GetActiveTFWeapon()); |
|
if ( !pWeapon ) |
|
return; |
|
|
|
if ( pWeapon->IsJarateRifle() && !m_bJarateMode ) |
|
{ |
|
vgui::surface()->DrawSetTextureFile(m_iChargeupTexture, "HUD/sniperscope_numbers_jar", true, false); |
|
m_bJarateMode = true; |
|
} |
|
else if ( !pWeapon->IsJarateRifle() && m_bJarateMode ) |
|
{ |
|
vgui::surface()->DrawSetTextureFile(m_iChargeupTexture, "HUD/sniperscope_numbers", true, false); |
|
m_bJarateMode = false; |
|
} |
|
|
|
// Actual charge value is set through a material proxy in the sniper rifle class |
|
|
|
int wide, tall; |
|
GetSize( wide, tall ); |
|
|
|
int x = 0; |
|
int y = 0; |
|
bool bDisableClipping = false; |
|
if ( UseVR() ) |
|
{ |
|
int vx, vy, vw, vh; |
|
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh ); |
|
|
|
int screenWide = vw; |
|
int screenTall = vh; |
|
bDisableClipping = true; |
|
WhereToDrawSniperScope ( &x, &y, screenWide, screenTall ); |
|
|
|
// The origin is wherever the property file put it, so (0,0) means "the right place, if the scope is in the middle of the screen" |
|
// So offset from there. But additional fun - the rendering coordinates are in the UI space, not the actual screen space. |
|
int UiScreenWide, UiScreenTall; |
|
GetHudSize(UiScreenWide, UiScreenTall); |
|
x -= ( UiScreenWide / 2 ); |
|
y -= ( UiScreenTall / 2 ); |
|
} |
|
|
|
if( bDisableClipping ) |
|
g_pMatSystemSurface->DisableClipping( true ); |
|
vgui::surface()->DrawSetColor(255,255,255,255); |
|
vgui::surface()->DrawSetTexture(m_iChargeupTexture); |
|
vgui::surface()->DrawTexturedRect( x, y, x+wide, y+tall ); |
|
if( bDisableClipping ) |
|
g_pMatSystemSurface->DisableClipping( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Draws the zoom screen |
|
//----------------------------------------------------------------------------- |
|
class CHudScope : public vgui::Panel, public CHudElement |
|
{ |
|
DECLARE_CLASS_SIMPLE( CHudScope, vgui::Panel ); |
|
|
|
public: |
|
CHudScope( const char *pElementName ); |
|
virtual ~CHudScope( void ); |
|
|
|
void Init( void ); |
|
|
|
protected: |
|
virtual void ApplySchemeSettings(vgui::IScheme *scheme); |
|
virtual void Paint( void ); |
|
virtual bool ShouldDraw( void ); |
|
|
|
private: |
|
int m_iScopeTexture[4]; |
|
int m_iScopeTextureAlt[4]; |
|
bool m_bAltScopeMode; |
|
}; |
|
|
|
DECLARE_HUDELEMENT_DEPTH( CHudScope, 100 ); |
|
|
|
using namespace vgui; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CHudScope::CHudScope( const char *pElementName ) : CHudElement(pElementName), BaseClass(NULL, "HudScope") |
|
{ |
|
vgui::Panel *pParent = g_pClientMode->GetViewport(); |
|
SetParent( pParent ); |
|
|
|
SetHiddenBits( HIDEHUD_PLAYERDEAD ); |
|
|
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTexture ); i++ ) |
|
{ |
|
m_iScopeTexture[ i ] = -1; |
|
} |
|
|
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTextureAlt ); i++ ) |
|
{ |
|
m_iScopeTextureAlt[i] = -1; |
|
} |
|
|
|
m_bAltScopeMode = false; |
|
} |
|
|
|
CHudScope::~CHudScope( void ) |
|
{ |
|
if ( vgui::surface() ) |
|
{ |
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTexture ); i++ ) |
|
{ |
|
if ( m_iScopeTexture[ i ] != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iScopeTexture[ i ] ); |
|
m_iScopeTexture[ i ] = -1; |
|
} |
|
} |
|
|
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTextureAlt ); i++ ) |
|
{ |
|
if ( m_iScopeTextureAlt[i] != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iScopeTextureAlt[i] ); |
|
m_iScopeTextureAlt[i] = -1; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: standard hud element init function |
|
//----------------------------------------------------------------------------- |
|
void CHudScope::Init( void ) |
|
{ |
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTexture ); i++ ) |
|
{ |
|
if ( m_iScopeTexture[ i ] == -1 ) |
|
{ |
|
m_iScopeTexture[ i ] = vgui::surface()->CreateNewTextureID(); |
|
} |
|
} |
|
|
|
vgui::surface()->DrawSetTextureFile( m_iScopeTexture[0], "HUD/scope_sniper_ul", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTexture[1], "HUD/scope_sniper_ur", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTexture[2], "HUD/scope_sniper_lr", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTexture[3], "HUD/scope_sniper_ll", true, false ); |
|
|
|
for ( int i = 0; i < ARRAYSIZE( m_iScopeTextureAlt ); i++ ) |
|
{ |
|
if ( m_iScopeTextureAlt[i] == -1 ) |
|
{ |
|
m_iScopeTextureAlt[i] = vgui::surface()->CreateNewTextureID(); |
|
} |
|
} |
|
|
|
vgui::surface()->DrawSetTextureFile( m_iScopeTextureAlt[0], "HUD/scope_sniper_alt_ul", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTextureAlt[1], "HUD/scope_sniper_alt_ur", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTextureAlt[2], "HUD/scope_sniper_alt_lr", true, false ); |
|
vgui::surface()->DrawSetTextureFile( m_iScopeTextureAlt[3], "HUD/scope_sniper_alt_ll", true, false ); |
|
|
|
// remove ourselves from the global group so the scoreboard doesn't hide us |
|
UnregisterForRenderGroup( "global" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: sets scheme colors |
|
//----------------------------------------------------------------------------- |
|
void CHudScope::ApplySchemeSettings( vgui::IScheme *scheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings(scheme); |
|
|
|
SetPaintBackgroundEnabled(false); |
|
SetPaintBorderEnabled(false); |
|
|
|
if ( UseVR() ) |
|
{ |
|
// Make it fill the screen. |
|
int iViewportWidth, iViewportHeight; |
|
g_pSourceVR->GetViewportBounds( ISourceVirtualReality::VREye_Left, NULL, NULL, &iViewportWidth, &iViewportHeight ); |
|
SetSize ( iViewportWidth, iViewportHeight ); |
|
SetBounds ( 0, 0, iViewportWidth, iViewportHeight ); |
|
// Force it to go direct to the framebuffer. |
|
SetForceStereoRenderToFrameBuffer( true ); |
|
} |
|
else |
|
{ |
|
int screenWide, screenTall; |
|
GetHudSize(screenWide, screenTall); |
|
SetBounds(0, 0, screenWide, screenTall); |
|
} |
|
|
|
// Move behind the spectator GUI, so we can be visible at the same time. |
|
SetZPos( -1 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CHudScope::ShouldDraw( void ) |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( GetSpectatorTarget() != 0 && GetSpectatorMode() == OBS_MODE_IN_EYE ) |
|
{ |
|
pPlayer = (C_TFPlayer *)UTIL_PlayerByIndex( GetSpectatorTarget() ); |
|
} |
|
|
|
if ( !pPlayer || !pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) ) |
|
return false; |
|
|
|
if ( pPlayer->GetActiveTFWeapon() ) |
|
{ |
|
m_bAltScopeMode = ( pPlayer->GetActiveTFWeapon()->GetWeaponID() == TF_WEAPON_SNIPERRIFLE_CLASSIC ); |
|
} |
|
|
|
return CHudElement::ShouldDraw(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: draws the zoom effect |
|
//----------------------------------------------------------------------------- |
|
void CHudScope::Paint( void ) |
|
{ |
|
// We need to update the refraction texture so the scope can refract it |
|
UpdateRefractTexture(); |
|
|
|
int screenWide; |
|
int screenTall; |
|
|
|
GetHudSize(screenWide, screenTall); |
|
|
|
// calculate the bounds in which we should draw the scope |
|
int xMid = screenWide / 2; |
|
int yMid = screenTall / 2; |
|
|
|
// width of the drawn scope. in widescreen, we draw the sides with primitives |
|
int wide, tall; |
|
if( screenWide > screenTall ) |
|
{ |
|
wide = ( screenTall * 4 ) / 3; |
|
tall = screenTall; |
|
} |
|
else |
|
{ |
|
wide = screenWide; |
|
tall = ( screenWide * 3 ) / 4; |
|
} |
|
|
|
bool bDisableClipping = false; |
|
if ( UseVR() ) |
|
{ |
|
int vx, vy, vw, vh; |
|
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh ); |
|
|
|
screenWide = vw; |
|
screenTall = vh; |
|
// This is actually awful - the scope is drawn in HUD-space, which is this completely |
|
// artifical 640*480 space that we invent for VR and which doesn't even have square pixels. Ugh. |
|
// Hacked good enough to ship. TODO: don't hack it. |
|
float fMagnification = 1.0f / g_ClientVirtualReality.GetZoomedModeMagnification(); |
|
wide = (int)( fMagnification * (float)screenWide ); |
|
tall = ( wide * 3 ) / 4; |
|
|
|
bDisableClipping = true; |
|
WhereToDrawSniperScope ( &xMid, &yMid, screenWide, screenTall ); |
|
} |
|
|
|
int xLeft = xMid - wide/2; |
|
int xRight = xMid + wide/2; |
|
int yTop = yMid - tall/2; |
|
int yBottom = yMid + tall/2; |
|
|
|
float uv1 = 0.5f / 256.0f, uv2 = 1.0f - uv1; |
|
|
|
vgui::Vertex_t vert[4]; |
|
|
|
Vector2D uv11( uv1, uv1 ); |
|
Vector2D uv12( uv1, uv2 ); |
|
Vector2D uv21( uv2, uv1 ); |
|
Vector2D uv22( uv2, uv2 ); |
|
|
|
vgui::surface()->DrawSetColor(0,0,0,255); |
|
|
|
if( bDisableClipping ) |
|
g_pMatSystemSurface->DisableClipping( true ); |
|
|
|
//upper left |
|
vgui::surface()->DrawSetTexture( m_bAltScopeMode ? m_iScopeTextureAlt[0] : m_iScopeTexture[0] ); |
|
vert[0].Init( Vector2D( xLeft, yTop ), uv11 ); |
|
vert[1].Init( Vector2D( xMid, yTop ), uv21 ); |
|
vert[2].Init( Vector2D( xMid, yMid ), uv22 ); |
|
vert[3].Init( Vector2D( xLeft, yMid ), uv12 ); |
|
vgui::surface()->DrawTexturedPolygon( 4, vert ); |
|
|
|
// top right |
|
if ( m_bAltScopeMode ) |
|
{ |
|
vgui::surface()->DrawSetTexture( m_iScopeTextureAlt[1] ); |
|
vert[0].Init( Vector2D( xMid, yTop ), uv11 ); |
|
vert[1].Init( Vector2D( xRight, yTop ), uv21 ); |
|
vert[2].Init( Vector2D( xRight, yMid ), uv22 ); |
|
vert[3].Init( Vector2D( xMid, yMid ), uv12 ); |
|
vgui::surface()->DrawTexturedPolygon( 4, vert ); |
|
} |
|
else |
|
{ |
|
vgui::surface()->DrawSetTexture( m_iScopeTexture[1] ); |
|
vert[0].Init( Vector2D( xMid - 1, yTop ), uv11 ); |
|
vert[1].Init( Vector2D( xRight, yTop ), uv21 ); |
|
vert[2].Init( Vector2D( xRight, yMid + 1 ), uv22 ); |
|
vert[3].Init( Vector2D( xMid - 1, yMid + 1 ), uv12 ); |
|
vgui::surface()->DrawTexturedPolygon( 4, vert ); |
|
} |
|
|
|
// bottom right |
|
vgui::surface()->DrawSetTexture( m_bAltScopeMode ? m_iScopeTextureAlt[2] : m_iScopeTexture[2] ); |
|
vert[0].Init( Vector2D( xMid, yMid ), uv11 ); |
|
vert[1].Init( Vector2D( xRight, yMid ), uv21 ); |
|
vert[2].Init( Vector2D( xRight, yBottom ), uv22 ); |
|
vert[3].Init( Vector2D( xMid, yBottom ), uv12 ); |
|
vgui::surface()->DrawTexturedPolygon( 4, vert ); |
|
|
|
// bottom left |
|
vgui::surface()->DrawSetTexture( m_bAltScopeMode ? m_iScopeTextureAlt[3] : m_iScopeTexture[3] ); |
|
vert[0].Init( Vector2D( xLeft, yMid ), uv11 ); |
|
vert[1].Init( Vector2D( xMid, yMid ), uv21 ); |
|
vert[2].Init( Vector2D( xMid, yBottom ), uv22 ); |
|
vert[3].Init( Vector2D( xLeft, yBottom), uv12 ); |
|
vgui::surface()->DrawTexturedPolygon( 4, vert ); |
|
|
|
if ( xLeft > 0 ) |
|
{ |
|
// Left block |
|
vgui::surface()->DrawFilledRect( 0, 0, xLeft, screenTall ); |
|
} |
|
if ( screenWide > xRight ) |
|
{ |
|
// Right block |
|
vgui::surface()->DrawFilledRect( xRight, 0, screenWide, screenTall ); |
|
} |
|
if ( yTop > 0 ) |
|
{ |
|
// top block |
|
vgui::surface()->DrawFilledRect( 0, 0, screenWide, yTop ); |
|
} |
|
if ( screenTall > yBottom ) |
|
{ |
|
// bottom block |
|
vgui::surface()->DrawFilledRect( 0, yBottom, screenWide, screenTall ); |
|
} |
|
|
|
if( bDisableClipping ) |
|
g_pMatSystemSurface->DisableClipping( false ); |
|
|
|
} |