|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This is an entity that represents a vgui screen
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "vguiscreen.h"
#include "networkstringtable_gamedll.h"
#include "saverestore_stringtable.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// This is an entity that represents a vgui screen
//-----------------------------------------------------------------------------
IMPLEMENT_SERVERCLASS_ST(CVGuiScreen, DT_VGuiScreen) SendPropFloat(SENDINFO(m_flWidth), 0, SPROP_NOSCALE ), SendPropFloat(SENDINFO(m_flHeight), 0, SPROP_NOSCALE ), SendPropInt(SENDINFO(m_nAttachmentIndex), 5, SPROP_UNSIGNED ), SendPropInt(SENDINFO(m_nPanelName), MAX_VGUI_SCREEN_STRING_BITS, SPROP_UNSIGNED ), SendPropInt(SENDINFO(m_fScreenFlags), VGUI_SCREEN_MAX_BITS, SPROP_UNSIGNED ), SendPropInt(SENDINFO(m_nOverlayMaterial), MAX_MATERIAL_STRING_BITS, SPROP_UNSIGNED ), SendPropEHandle(SENDINFO(m_hPlayerOwner)), END_SEND_TABLE();
LINK_ENTITY_TO_CLASS( vgui_screen, CVGuiScreen ); LINK_ENTITY_TO_CLASS( vgui_screen_team, CVGuiScreen ); PRECACHE_REGISTER( vgui_screen );
//-----------------------------------------------------------------------------
// Save/load
//-----------------------------------------------------------------------------
BEGIN_DATADESC( CVGuiScreen )
DEFINE_CUSTOM_FIELD( m_nPanelName, &g_VguiScreenStringOps ), DEFINE_FIELD( m_nAttachmentIndex, FIELD_INTEGER ), // DEFINE_FIELD( m_nOverlayMaterial, FIELD_INTEGER ),
DEFINE_FIELD( m_fScreenFlags, FIELD_INTEGER ), DEFINE_KEYFIELD( m_flWidth, FIELD_FLOAT, "width" ), DEFINE_KEYFIELD( m_flHeight, FIELD_FLOAT, "height" ), DEFINE_KEYFIELD( m_strOverlayMaterial, FIELD_STRING, "overlaymaterial" ), DEFINE_FIELD( m_hPlayerOwner, FIELD_EHANDLE ),
DEFINE_INPUTFUNC( FIELD_VOID, "SetActive", InputSetActive ), DEFINE_INPUTFUNC( FIELD_VOID, "SetInactive", InputSetInactive ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVGuiScreen::CVGuiScreen() { m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING; m_hPlayerOwner = NULL; }
//-----------------------------------------------------------------------------
// Read in worldcraft data...
//-----------------------------------------------------------------------------
bool CVGuiScreen::KeyValue( const char *szKeyName, const char *szValue ) { //!! temp hack, until worldcraft is fixed
// strip the # tokens from (duplicate) key names
char *s = (char *)strchr( szKeyName, '#' ); if ( s ) { *s = '\0'; }
if ( FStrEq( szKeyName, "panelname" )) { SetPanelName( szValue ); return true; }
// NOTE: Have to do these separate because they set two values instead of one
if( FStrEq( szKeyName, "angles" ) ) { Assert( GetMoveParent() == NULL ); QAngle angles; UTIL_StringToVector( angles.Base(), szValue );
// Because the vgui screen basis is strange (z is front, y is up, x is right)
// we need to rotate the typical basis before applying it
VMatrix mat, rotation, tmp; MatrixFromAngles( angles, mat ); MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 ); MatrixMultiply( mat, rotation, tmp ); MatrixBuildRotateZ( rotation, 90 ); MatrixMultiply( tmp, rotation, mat ); MatrixToAngles( mat, angles ); SetAbsAngles( angles );
return true; }
return BaseClass::KeyValue( szKeyName, szValue ); }
//-----------------------------------------------------------------------------
// Precache...
//-----------------------------------------------------------------------------
void CVGuiScreen::Precache() { BaseClass::Precache(); if ( m_strOverlayMaterial != NULL_STRING ) { PrecacheMaterial( STRING(m_strOverlayMaterial) ); } }
//-----------------------------------------------------------------------------
// Spawn...
//-----------------------------------------------------------------------------
void CVGuiScreen::Spawn() { Precache();
// This has no model, but we want it to transmit if it's in the PVS anyways
AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); m_nAttachmentIndex = 0; SetSolid( SOLID_OBB ); AddSolidFlags( FSOLID_NOT_SOLID ); SetActualSize( m_flWidth, m_flHeight ); m_fScreenFlags.Set( VGUI_SCREEN_ACTIVE );
m_takedamage = DAMAGE_NO; AddFlag( FL_NOTARGET ); }
//-----------------------------------------------------------------------------
// Spawn...
//-----------------------------------------------------------------------------
void CVGuiScreen::Activate() { BaseClass::Activate();
if ( m_nOverlayMaterial == OVERLAY_MATERIAL_INVALID_STRING && m_strOverlayMaterial != NULL_STRING ) { SetOverlayMaterial( STRING(m_strOverlayMaterial) ); } }
void CVGuiScreen::OnRestore() { UpdateTransmitState();
BaseClass::OnRestore(); }
void CVGuiScreen::SetAttachmentIndex( int nIndex ) { m_nAttachmentIndex = nIndex; }
void CVGuiScreen::SetOverlayMaterial( const char *pMaterial ) { int iMaterial = GetMaterialIndex( pMaterial );
if ( iMaterial == 0 ) { m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING; } else { m_nOverlayMaterial = iMaterial; } }
bool CVGuiScreen::IsActive() const { return (m_fScreenFlags & VGUI_SCREEN_ACTIVE) != 0; }
void CVGuiScreen::SetActive( bool bActive ) { if (bActive != IsActive()) { if (!bActive) { m_fScreenFlags &= ~VGUI_SCREEN_ACTIVE; } else { m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ACTIVE ); } } }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVGuiScreen::IsAttachedToViewModel() const { return (m_fScreenFlags & VGUI_SCREEN_ATTACHED_TO_VIEWMODEL) != 0; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : bAttached -
//-----------------------------------------------------------------------------
void CVGuiScreen::SetAttachedToViewModel( bool bAttached ) { if (bAttached != IsActive()) { if (!bAttached) { m_fScreenFlags &= ~VGUI_SCREEN_ATTACHED_TO_VIEWMODEL; } else { m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ATTACHED_TO_VIEWMODEL );
// attached screens have different transmit rules
DispatchUpdateTransmitState(); }
// attached screens have different transmit rules
DispatchUpdateTransmitState(); } }
void CVGuiScreen::SetTransparency( bool bTransparent ) { if (!bTransparent) { m_fScreenFlags &= ~VGUI_SCREEN_TRANSPARENT; } else { m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_TRANSPARENT ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CVGuiScreen::InputSetActive( inputdata_t &inputdata ) { SetActive( true ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CVGuiScreen::InputSetInactive( inputdata_t &inputdata ) { SetActive( false ); }
bool CVGuiScreen::IsVisibleOnlyToTeammates() const { return (m_fScreenFlags & VGUI_SCREEN_VISIBLE_TO_TEAMMATES) != 0; }
void CVGuiScreen::MakeVisibleOnlyToTeammates( bool bActive ) { if (bActive != IsVisibleOnlyToTeammates()) { if (!bActive) { m_fScreenFlags &= ~VGUI_SCREEN_VISIBLE_TO_TEAMMATES; } else { m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_VISIBLE_TO_TEAMMATES ); } } }
bool CVGuiScreen::IsVisibleToTeam( int nTeam ) { // FIXME: Should this maybe go into a derived class of some sort?
// Don't bother with screens on the wrong team
if ( IsVisibleOnlyToTeammates() && (nTeam > 0) ) { // Hmmm... sort of a hack...
CBaseEntity *pOwner = GetOwnerEntity(); if ( pOwner && (nTeam != pOwner->GetTeamNumber()) ) return false; } return true; }
//-----------------------------------------------------------------------------
// Purpose: Screens attached to view models only go to client if viewmodel is being sent, too.
// Input : *recipient -
// *pvs -
// clientArea -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
int CVGuiScreen::UpdateTransmitState() { if ( IsAttachedToViewModel() ) { // only send to the owner, or someone spectating the owner.
return SetTransmitState( FL_EDICT_FULLCHECK ); } else if ( GetMoveParent() ) { // Let the parent object trigger the send. This is more efficient than having it call CBaseEntity::ShouldTransmit
// for all the vgui screens in the map.
return SetTransmitState( FL_EDICT_PVSCHECK ); } else { return BaseClass::UpdateTransmitState(); } }
int CVGuiScreen::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { Assert( IsAttachedToViewModel() );
CBaseEntity *pViewModel = GetOwnerEntity();
if ( pViewModel ) { return pViewModel->ShouldTransmit( pInfo ); }
return BaseClass::ShouldTransmit( pInfo ); }
//-----------------------------------------------------------------------------
// Convert the panel name into an integer
//-----------------------------------------------------------------------------
void CVGuiScreen::SetPanelName( const char *pPanelName ) { m_nPanelName = g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pPanelName ); }
const char *CVGuiScreen::GetPanelName() const { return g_pStringTableVguiScreen->GetString( m_nPanelName ); }
//-----------------------------------------------------------------------------
// Sets the screen size + resolution
//-----------------------------------------------------------------------------
void CVGuiScreen::SetActualSize( float flWidth, float flHeight ) { m_flWidth = flWidth; m_flHeight = flHeight;
Vector mins, maxs; mins.Init( 0.0f, 0.0f, -0.1f ); maxs.Init( 0.0f, 0.0f, 0.1f ); if (flWidth > 0) maxs.x = flWidth; else mins.x = flWidth; if (flHeight > 0) maxs.y = flHeight; else mins.y = flHeight;
UTIL_SetSize( this, mins, maxs ); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiScreen::SetPlayerOwner( CBasePlayer *pPlayer, bool bOwnerOnlyInput /* = false */ ) { m_hPlayerOwner = pPlayer;
if ( bOwnerOnlyInput ) { m_fScreenFlags.Set( VGUI_SCREEN_ONLY_USABLE_BY_OWNER ); } }
//-----------------------------------------------------------------------------
// Precaches a vgui screen
//-----------------------------------------------------------------------------
void PrecacheVGuiScreen( const char *pScreenType ) { g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pScreenType ); }
//-----------------------------------------------------------------------------
// Creates a vgui screen, attaches it to another player
//-----------------------------------------------------------------------------
CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex ) { Assert( pAttachedTo ); CVGuiScreen *pScreen = (CVGuiScreen *)CBaseEntity::Create( pScreenClassname, vec3_origin, vec3_angle, pAttachedTo );
pScreen->SetPanelName( pScreenType ); pScreen->FollowEntity( pAttachedTo ); pScreen->SetOwnerEntity( pOwner ); pScreen->SetAttachmentIndex( nAttachmentIndex );
return pScreen; }
void DestroyVGuiScreen( CVGuiScreen *pVGuiScreen ) { if (pVGuiScreen) { UTIL_Remove( pVGuiScreen ); } }
|