307 lines
8.6 KiB
C++
307 lines
8.6 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "hud.h"
|
||
|
#include "hud_crosshair.h"
|
||
|
#include "iclientmode.h"
|
||
|
#include "view.h"
|
||
|
#include "vgui_controls/Controls.h"
|
||
|
#include "vgui/ISurface.h"
|
||
|
#include "ivrenderview.h"
|
||
|
#include "materialsystem/imaterialsystem.h"
|
||
|
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||
|
#include "client_virtualreality.h"
|
||
|
#include "sourcevr/isourcevirtualreality.h"
|
||
|
|
||
|
#ifdef SIXENSE
|
||
|
#include "sixense/in_sixense.h"
|
||
|
#endif
|
||
|
|
||
|
#ifdef PORTAL
|
||
|
#include "c_portal_player.h"
|
||
|
#endif // PORTAL
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
ConVar crosshair( "crosshair", "1", FCVAR_ARCHIVE );
|
||
|
ConVar cl_observercrosshair( "cl_observercrosshair", "1", FCVAR_ARCHIVE );
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
int ScreenTransform( const Vector& point, Vector& screen );
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
// If running TF, we use CHudTFCrosshair instead (which is derived from CHudCrosshair)
|
||
|
#else
|
||
|
DECLARE_HUDELEMENT( CHudCrosshair );
|
||
|
#endif
|
||
|
|
||
|
CHudCrosshair::CHudCrosshair( const char *pElementName ) :
|
||
|
CHudElement( pElementName ), BaseClass( NULL, "HudCrosshair" )
|
||
|
{
|
||
|
vgui::Panel *pParent = g_pClientMode->GetViewport();
|
||
|
SetParent( pParent );
|
||
|
|
||
|
m_pCrosshair = 0;
|
||
|
|
||
|
m_clrCrosshair = Color( 0, 0, 0, 0 );
|
||
|
|
||
|
m_vecCrossHairOffsetAngle.Init();
|
||
|
|
||
|
SetHiddenBits( HIDEHUD_PLAYERDEAD | HIDEHUD_CROSSHAIR );
|
||
|
}
|
||
|
|
||
|
CHudCrosshair::~CHudCrosshair()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CHudCrosshair::ApplySchemeSettings( IScheme *scheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( scheme );
|
||
|
|
||
|
m_pDefaultCrosshair = gHUD.GetIcon("crosshair_default");
|
||
|
SetPaintBackgroundEnabled( false );
|
||
|
|
||
|
SetSize( ScreenWidth(), ScreenHeight() );
|
||
|
|
||
|
SetForceStereoRenderToFrameBuffer( true );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Save CPU cycles by letting the HUD system early cull
|
||
|
// costly traversal. Called per frame, return true if thinking and
|
||
|
// painting need to occur.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CHudCrosshair::ShouldDraw( void )
|
||
|
{
|
||
|
bool bNeedsDraw;
|
||
|
|
||
|
if ( m_bHideCrosshair )
|
||
|
return false;
|
||
|
|
||
|
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
|
||
|
if ( !pPlayer )
|
||
|
return false;
|
||
|
|
||
|
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
|
||
|
if ( pWeapon && !pWeapon->ShouldDrawCrosshair() )
|
||
|
return false;
|
||
|
|
||
|
#ifdef PORTAL
|
||
|
C_Portal_Player *portalPlayer = ToPortalPlayer(pPlayer);
|
||
|
if ( portalPlayer && portalPlayer->IsSuppressingCrosshair() )
|
||
|
return false;
|
||
|
#endif // PORTAL
|
||
|
|
||
|
/* disabled to avoid assuming it's an HL2 player.
|
||
|
// suppress crosshair in zoom.
|
||
|
if ( pPlayer->m_HL2Local.m_bZooming )
|
||
|
return false;
|
||
|
*/
|
||
|
|
||
|
// draw a crosshair only if alive or spectating in eye
|
||
|
if ( IsX360() )
|
||
|
{
|
||
|
bNeedsDraw = m_pCrosshair &&
|
||
|
!engine->IsDrawingLoadingImage() &&
|
||
|
!engine->IsPaused() &&
|
||
|
( !pPlayer->IsSuitEquipped() || g_pGameRules->IsMultiplayer() ) &&
|
||
|
g_pClientMode->ShouldDrawCrosshair() &&
|
||
|
!( pPlayer->GetFlags() & FL_FROZEN ) &&
|
||
|
( pPlayer->entindex() == render->GetViewEntity() ) &&
|
||
|
( pPlayer->IsAlive() || ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bNeedsDraw = m_pCrosshair &&
|
||
|
crosshair.GetInt() &&
|
||
|
!engine->IsDrawingLoadingImage() &&
|
||
|
!engine->IsPaused() &&
|
||
|
g_pClientMode->ShouldDrawCrosshair() &&
|
||
|
!( pPlayer->GetFlags() & FL_FROZEN ) &&
|
||
|
( pPlayer->entindex() == render->GetViewEntity() ) &&
|
||
|
!pPlayer->IsInVGuiInputMode() &&
|
||
|
( pPlayer->IsAlive() || ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) || ( cl_observercrosshair.GetBool() && pPlayer->GetObserverMode() == OBS_MODE_ROAMING ) );
|
||
|
}
|
||
|
|
||
|
return ( bNeedsDraw && CHudElement::ShouldDraw() );
|
||
|
}
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
extern ConVar cl_crosshair_red;
|
||
|
extern ConVar cl_crosshair_green;
|
||
|
extern ConVar cl_crosshair_blue;
|
||
|
extern ConVar cl_crosshair_scale;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void CHudCrosshair::GetDrawPosition ( float *pX, float *pY, bool *pbBehindCamera, QAngle angleCrosshairOffset )
|
||
|
{
|
||
|
QAngle curViewAngles = CurrentViewAngles();
|
||
|
Vector curViewOrigin = CurrentViewOrigin();
|
||
|
|
||
|
int vx, vy, vw, vh;
|
||
|
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh );
|
||
|
|
||
|
float screenWidth = vw;
|
||
|
float screenHeight = vh;
|
||
|
|
||
|
float x = screenWidth / 2;
|
||
|
float y = screenHeight / 2;
|
||
|
|
||
|
bool bBehindCamera = false;
|
||
|
|
||
|
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
|
||
|
if ( ( pPlayer != NULL ) && ( pPlayer->GetObserverMode()==OBS_MODE_NONE ) )
|
||
|
{
|
||
|
bool bUseOffset = false;
|
||
|
|
||
|
Vector vecStart;
|
||
|
Vector vecEnd;
|
||
|
|
||
|
if ( UseVR() )
|
||
|
{
|
||
|
// These are the correct values to use, but they lag the high-speed view data...
|
||
|
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 );
|
||
|
vecEnd = vecStart + vecAimDirection * MAX_TRACE_LENGTH;
|
||
|
|
||
|
bUseOffset = true;
|
||
|
}
|
||
|
|
||
|
#ifdef SIXENSE
|
||
|
// TODO: actually test this Sixsense code interaction with things like HMDs & stereo.
|
||
|
if ( g_pSixenseInput->IsEnabled() && !UseVR() )
|
||
|
{
|
||
|
// Never autoaim a predicted weapon (for now)
|
||
|
vecStart = pPlayer->Weapon_ShootPosition();
|
||
|
Vector aimVector;
|
||
|
AngleVectors( CurrentViewAngles() - g_pSixenseInput->GetViewAngleOffset(), &aimVector );
|
||
|
// calculate where the bullet would go so we can draw the cross appropriately
|
||
|
vecEnd = vecStart + aimVector * MAX_TRACE_LENGTH;
|
||
|
bUseOffset = true;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if ( bUseOffset )
|
||
|
{
|
||
|
trace_t tr;
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
Vector screen;
|
||
|
screen.Init();
|
||
|
bBehindCamera = ScreenTransform(tr.endpos, screen) != 0;
|
||
|
|
||
|
x = 0.5f * ( 1.0f + screen[0] ) * screenWidth + 0.5f;
|
||
|
y = 0.5f * ( 1.0f - screen[1] ) * screenHeight + 0.5f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MattB - angleCrosshairOffset is the autoaim angle.
|
||
|
// if we're not using autoaim, just draw in the middle of the
|
||
|
// screen
|
||
|
if ( angleCrosshairOffset != vec3_angle )
|
||
|
{
|
||
|
QAngle angles;
|
||
|
Vector forward;
|
||
|
Vector point, screen;
|
||
|
|
||
|
// this code is wrong
|
||
|
angles = curViewAngles + angleCrosshairOffset;
|
||
|
AngleVectors( angles, &forward );
|
||
|
VectorAdd( curViewOrigin, forward, point );
|
||
|
ScreenTransform( point, screen );
|
||
|
|
||
|
x += 0.5f * screen[0] * screenWidth + 0.5f;
|
||
|
y += 0.5f * screen[1] * screenHeight + 0.5f;
|
||
|
}
|
||
|
|
||
|
*pX = x;
|
||
|
*pY = y;
|
||
|
*pbBehindCamera = bBehindCamera;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CHudCrosshair::Paint( void )
|
||
|
{
|
||
|
if ( !m_pCrosshair )
|
||
|
return;
|
||
|
|
||
|
if ( !IsCurrentViewAccessAllowed() )
|
||
|
return;
|
||
|
|
||
|
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
float x, y;
|
||
|
bool bBehindCamera;
|
||
|
GetDrawPosition ( &x, &y, &bBehindCamera, m_vecCrossHairOffsetAngle );
|
||
|
|
||
|
if( bBehindCamera )
|
||
|
return;
|
||
|
|
||
|
float flWeaponScale = 1.f;
|
||
|
int iTextureW = m_pCrosshair->Width();
|
||
|
int iTextureH = m_pCrosshair->Height();
|
||
|
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
|
||
|
if ( pWeapon )
|
||
|
{
|
||
|
pWeapon->GetWeaponCrosshairScale( flWeaponScale );
|
||
|
}
|
||
|
|
||
|
float flPlayerScale = 1.0f;
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
Color clr( cl_crosshair_red.GetInt(), cl_crosshair_green.GetInt(), cl_crosshair_blue.GetInt(), 255 );
|
||
|
flPlayerScale = cl_crosshair_scale.GetFloat() / 32.0f; // the player can change the scale in the options/multiplayer tab
|
||
|
#else
|
||
|
Color clr = m_clrCrosshair;
|
||
|
#endif
|
||
|
float flWidth = flWeaponScale * flPlayerScale * (float)iTextureW;
|
||
|
float flHeight = flWeaponScale * flPlayerScale * (float)iTextureH;
|
||
|
int iWidth = (int)( flWidth + 0.5f );
|
||
|
int iHeight = (int)( flHeight + 0.5f );
|
||
|
int iX = (int)( x + 0.5f );
|
||
|
int iY = (int)( y + 0.5f );
|
||
|
|
||
|
m_pCrosshair->DrawSelfCropped (
|
||
|
iX-(iWidth/2), iY-(iHeight/2),
|
||
|
0, 0,
|
||
|
iTextureW, iTextureH,
|
||
|
iWidth, iHeight,
|
||
|
clr );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudCrosshair::SetCrosshairAngle( const QAngle& angle )
|
||
|
{
|
||
|
VectorCopy( angle, m_vecCrossHairOffsetAngle );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudCrosshair::SetCrosshair( CHudTexture *texture, const Color& clr )
|
||
|
{
|
||
|
m_pCrosshair = texture;
|
||
|
m_clrCrosshair = clr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Resets the crosshair back to the default
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudCrosshair::ResetCrosshair()
|
||
|
{
|
||
|
SetCrosshair( m_pDefaultCrosshair, Color(255, 255, 255, 255) );
|
||
|
}
|