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.
419 lines
12 KiB
419 lines
12 KiB
//========= 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 ); |
|
} |
|
}
|
|
|