source-sdk-2013-mapbase/sp/src/game/client/hud_crosshair.cpp
Joe Ludwig beaae8ac45 Updated the SDK with the latest code from the TF and HL2 branches
* Adds support for Visual Studio 2012 and 2013
* VR Mode:
. Switches from headtrack.dll to sourcevr.dll
. Improved readability of the UI in VR
. Removed the IPD calibration tool. TF2 will now obey the Oculus
configuration file. Use the Oculus calibration tool in your SDK or
install and run "OpenVR" under Tools in Steam to calibrate your IPD.
. Added dropdown to enable VR mode in the Video options. Removed the -vr
command line option.
. Added the ability to switch in and out of VR mode without quitting the
game
. By default VR mode will run full screen. To switch back to a
borderless window set the vr_force_windowed convar.
. Added support for VR mode on Linux
* Many assorted bug fixes and other changes from Team Fortress in
various shared files
2013-12-03 08:54:16 -08:00

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) );
}