420 lines
12 KiB
C++
420 lines
12 KiB
C++
//========= 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 );
|
|
}
|
|
}
|