diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index 243324f1..911f4ffb 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -57,6 +57,7 @@ $Project $File "mapbase\c_func_fake_worldportal.cpp" $File "mapbase\c_func_fake_worldportal.h" $File "mapbase\c_point_glow.cpp" + $File "mapbase\c_vgui_text_display.cpp" } $Folder "HL2 DLL" diff --git a/sp/src/game/client/mapbase/c_vgui_text_display.cpp b/sp/src/game/client/mapbase/c_vgui_text_display.cpp new file mode 100644 index 00000000..5d424682 --- /dev/null +++ b/sp/src/game/client/mapbase/c_vgui_text_display.cpp @@ -0,0 +1,259 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Displays easy, flexible VGui text. Mapbase equivalent of point_worldtext. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "panelmetaclassmgr.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include +#include +#include +#include "ienginevgui.h" +#include "c_vguiscreen.h" +#include "vgui_bitmapbutton.h" +#include "vgui_bitmappanel.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + +//----------------------------------------------------------------------------- +// vgui_text_display +//----------------------------------------------------------------------------- +class C_VGuiTextDisplay : public C_BaseEntity +{ +public: + DECLARE_CLASS( C_VGuiTextDisplay, C_BaseEntity ); + DECLARE_CLIENTCLASS(); + + C_VGuiTextDisplay(); + ~C_VGuiTextDisplay(); + + virtual void PostDataUpdate( DataUpdateType_t updateType ); + + bool IsEnabled( void ) const { return m_bEnabled; } + + const char *GetDisplayText( void ) const { return m_szDisplayText; } + const char *GetFontName( void ) const { return m_szFont; } + int GetResolution( void ) const { return m_iResolution; } + vgui::Label::Alignment GetContentAlignment() const { return m_iContentAlignment; } + + bool NeedsTextUpdate() { return m_bTextNeedsUpdate; } + void UpdatedText() { m_bTextNeedsUpdate = false; } + +private: + bool m_bEnabled; + char m_szDisplayText[256]; + vgui::Label::Alignment m_iContentAlignment; + char m_szFont[64]; + int m_iResolution; + + bool m_bTextNeedsUpdate; +}; + +IMPLEMENT_CLIENTCLASS_DT( C_VGuiTextDisplay, DT_VGuiTextDisplay, CVGuiTextDisplay ) + RecvPropBool( RECVINFO( m_bEnabled ) ), + RecvPropString( RECVINFO( m_szDisplayText ) ), + RecvPropInt( RECVINFO( m_iContentAlignment ) ), + RecvPropString( RECVINFO( m_szFont ) ), + RecvPropInt( RECVINFO( m_iResolution ) ), +END_RECV_TABLE() + +C_VGuiTextDisplay::C_VGuiTextDisplay() +{ +} + +C_VGuiTextDisplay::~C_VGuiTextDisplay() +{ +} + +void C_VGuiTextDisplay::PostDataUpdate( DataUpdateType_t updateType ) +{ + BaseClass::PostDataUpdate( updateType ); + + // For now, always update + m_bTextNeedsUpdate = true; +} + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Control screen +//----------------------------------------------------------------------------- +class C_TextDisplayPanel : public CVGuiScreenPanel +{ + DECLARE_CLASS( C_TextDisplayPanel, CVGuiScreenPanel ); + +public: + C_TextDisplayPanel( vgui::Panel *parent, const char *panelName ); + ~C_TextDisplayPanel( void ); + + virtual void ApplySchemeSettings( IScheme *pScheme ); + + void UpdateText(); + + virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ); + virtual void OnTick( void ); + virtual void Paint( void ); + +private: + + CHandle m_hVGUIScreen; + CHandle m_hScreenEntity; + + // VGUI specifics + Label *m_pDisplayTextLabel; +}; + +DECLARE_VGUI_SCREEN_FACTORY( C_TextDisplayPanel, "text_display_panel" ); + +CUtlVector g_WorldTextDisplays; + +//----------------------------------------------------------------------------- +// Constructor: +//----------------------------------------------------------------------------- +C_TextDisplayPanel::C_TextDisplayPanel( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, "C_TextDisplayPanel"/*, vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/WorldTextPanel.res", "WorldTextPanel" )*/ ) +{ + // Add ourselves to the global list of movie displays + g_WorldTextDisplays.AddToTail( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: Clean up the movie +//----------------------------------------------------------------------------- +C_TextDisplayPanel::~C_TextDisplayPanel( void ) +{ + // Remove ourselves from the global list of movie displays + g_WorldTextDisplays.FindAndRemove( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: Setup our scheme +//----------------------------------------------------------------------------- +void C_TextDisplayPanel::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + /* + m_pDisplayTextLabel->SetFgColor( Color( 255, 255, 255, 255 ) ); + m_pDisplayTextLabel->SetText( "" ); + m_pDisplayTextLabel->SetVisible( false ); + */ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_TextDisplayPanel::UpdateText() +{ + color32 clr = m_hScreenEntity->GetRenderColor(); + + m_pDisplayTextLabel->SetFgColor( Color( clr.r, clr.g, clr.b, clr.a ) ); + m_pDisplayTextLabel->SetText( m_hScreenEntity->GetDisplayText() ); + + //SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() ); + SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() ); + m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() ); + //m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() ); + + Label::Alignment iAlignment = m_hScreenEntity->GetContentAlignment(); + m_pDisplayTextLabel->SetContentAlignment( iAlignment ); + + bool bWrap = true; + bool bCenterWrap = false; + switch (iAlignment) + { + // Center wrap if centered + case Label::Alignment::a_north: + case Label::Alignment::a_center: + case Label::Alignment::a_south: + bCenterWrap = true; + break; + + // HACKHACK: Don't wrap if using an east alignment + case Label::Alignment::a_northeast: + case Label::Alignment::a_east: + case Label::Alignment::a_southeast: + bWrap = false; + break; + } + + m_pDisplayTextLabel->SetWrap( bWrap ); + m_pDisplayTextLabel->SetCenterWrap( bCenterWrap ); + + Msg( "Resolution is %i\n", m_hScreenEntity->GetResolution() ); + + const char *pszFontName = m_hScreenEntity->GetFontName(); + if (pszFontName && pszFontName[0] != '\0') + { + HFont font = scheme()->GetIScheme( GetScheme() )->GetFont( pszFontName ); + m_pDisplayTextLabel->SetFont( font ); + } + + m_pDisplayTextLabel->SetVisible( true ); +} + +//----------------------------------------------------------------------------- +// Initialization +//----------------------------------------------------------------------------- +bool C_TextDisplayPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ) +{ + if ( !BaseClass::Init( pKeyValues, pInitData ) ) + return false; + + // Make sure we get ticked... + vgui::ivgui()->AddTickSignal( GetVPanel() ); + + m_pDisplayTextLabel = dynamic_cast(FindChildByName( "TextDisplay" )); + + // Save this for simplicity later on + m_hVGUIScreen = dynamic_cast( GetEntity() ); + if ( m_hVGUIScreen != NULL ) + { + // Also get the associated entity + m_hScreenEntity = dynamic_cast(m_hVGUIScreen->GetOwnerEntity()); + UpdateText(); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Update the display string +//----------------------------------------------------------------------------- +void C_TextDisplayPanel::OnTick() +{ + if (m_hScreenEntity->NeedsTextUpdate()) + { + UpdateText(); + m_hScreenEntity->UpdatedText(); + } + + BaseClass::OnTick(); +} + +ConVar r_vguitext_bg( "r_vguitext_bg", "0" ); + +//----------------------------------------------------------------------------- +// Purpose: Update and draw the frame +//----------------------------------------------------------------------------- +void C_TextDisplayPanel::Paint( void ) +{ + // Black out the background (we could omit drawing under the video surface, but this is straight-forward) + if ( r_vguitext_bg.GetBool() ) + { + surface()->DrawSetColor( 0, 0, 0, 255 ); + surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() ); + + //surface()->DrawSetColor( 64, 64, 64, 255 ); + //surface()->DrawFilledRect( 0, 0, m_pDisplayTextLabel->GetWide(), m_pDisplayTextLabel->GetTall() ); + } + + // Parent's turn + BaseClass::Paint(); +} diff --git a/sp/src/game/server/mapbase/vgui_text_display.cpp b/sp/src/game/server/mapbase/vgui_text_display.cpp new file mode 100644 index 00000000..fc490e67 --- /dev/null +++ b/sp/src/game/server/mapbase/vgui_text_display.cpp @@ -0,0 +1,427 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Displays easy, flexible VGui text. Mapbase equivalent of point_worldtext. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "vguiscreen.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define SF_TESTDISPLAY_START_DISABLED (1 << 0) + +//----------------------------------------------------------------------------- +// vgui_text_display +//----------------------------------------------------------------------------- +class CVGuiTextDisplay : public CBaseEntity +{ +public: + + DECLARE_CLASS( CVGuiTextDisplay, CBaseEntity ); + DECLARE_DATADESC(); + DECLARE_SERVERCLASS(); + + CVGuiTextDisplay(); + virtual ~CVGuiTextDisplay(); + + virtual bool KeyValue( const char *szKeyName, const char *szValue ); + + virtual int UpdateTransmitState(); + virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); + + virtual void Spawn( void ); + virtual void Precache( void ); + virtual void OnRestore( void ); + + void ScreenVisible( bool bVisible ); + + void Disable( void ); + void Enable( void ); + + void InputDisable( inputdata_t &inputdata ); + void InputEnable( inputdata_t &inputdata ); + + void InputSetMessage( inputdata_t &inputdata ); + void InputSetTextAlignment( inputdata_t &inputdata ); + void InputSetFont( inputdata_t &inputdata ); + void InputSetResolution( inputdata_t &inputdata ); + void InputSetTextSize( inputdata_t &inputdata ); + +private: + + // Control panel + void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ); + void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ); + void SpawnControlPanels( void ); + void RestoreControlPanels( void ); + +private: + CNetworkVar( bool, m_bEnabled ); + + CNetworkString( m_szDisplayText, 256 ); + CNetworkVar( int, m_iContentAlignment ); + CNetworkString( m_szFont, 64 ); + CNetworkVar( int, m_iResolution ); + float m_flTextSize; + + //CNetworkColor32( m_DisplayColor ); // Use render color + + bool m_bDoFullTransmit; + + CHandle m_hScreen; +}; + +LINK_ENTITY_TO_CLASS( vgui_text_display, CVGuiTextDisplay ); + +//----------------------------------------------------------------------------- +// Save/load +//----------------------------------------------------------------------------- +BEGIN_DATADESC( CVGuiTextDisplay ) + + DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), + + DEFINE_AUTO_ARRAY_KEYFIELD( m_szDisplayText, FIELD_CHARACTER, "message" ), + DEFINE_KEYFIELD( m_iContentAlignment, FIELD_INTEGER, "alignment" ), + DEFINE_AUTO_ARRAY_KEYFIELD( m_szFont, FIELD_CHARACTER, "font" ), + DEFINE_KEYFIELD( m_iResolution, FIELD_INTEGER, "resolution" ), + DEFINE_KEYFIELD( m_flTextSize, FIELD_FLOAT, "textsize" ), + + DEFINE_FIELD( m_bDoFullTransmit, FIELD_BOOLEAN ), + + DEFINE_FIELD( m_hScreen, FIELD_EHANDLE ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + + DEFINE_INPUTFUNC( FIELD_STRING, "SetMessage", InputSetMessage ), + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTextAlignment", InputSetTextAlignment ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetFont", InputSetFont ), + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetResolution", InputSetResolution ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPanelSize", InputSetTextSize ), + +END_DATADESC() + +IMPLEMENT_SERVERCLASS_ST( CVGuiTextDisplay, DT_VGuiTextDisplay ) + SendPropBool( SENDINFO( m_bEnabled ) ), + SendPropString( SENDINFO( m_szDisplayText ) ), + SendPropInt( SENDINFO( m_iContentAlignment ) ), + SendPropString( SENDINFO( m_szFont ) ), + SendPropInt( SENDINFO( m_iResolution ) ), +END_SEND_TABLE() + +CVGuiTextDisplay::CVGuiTextDisplay() +{ + m_flTextSize = 100.0f; + m_iResolution = 200; + m_iContentAlignment = 6; // a_southwest +} + +CVGuiTextDisplay::~CVGuiTextDisplay() +{ + DestroyVGuiScreen( m_hScreen.Get() ); +} + +//----------------------------------------------------------------------------- +// Read in Hammer data +//----------------------------------------------------------------------------- +bool CVGuiTextDisplay::KeyValue( const char *szKeyName, const char *szValue ) +{ + // 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 ); + } + else if( FStrEq( szKeyName, "message" ) ) + { + Q_strcpy( m_szDisplayText.GetForModify(), szValue ); + } + else if( FStrEq( szKeyName, "font" ) ) + { + Q_strcpy( m_szFont.GetForModify(), szValue ); + } + else if( FStrEq( szKeyName, "color" ) ) + { + // Use render color + return BaseClass::KeyValue( "rendercolor", szValue ); + } + else + return BaseClass::KeyValue( szKeyName, szValue ); + + return true; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int CVGuiTextDisplay::UpdateTransmitState() +{ + if ( m_bDoFullTransmit ) + { + m_bDoFullTransmit = false; + return SetTransmitState( FL_EDICT_ALWAYS ); + } + + return SetTransmitState( FL_EDICT_FULLCHECK ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) +{ + // Are we already marked for transmission? + if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) + return; + + BaseClass::SetTransmit( pInfo, bAlways ); + + // Force our screen to be sent too. + m_hScreen->SetTransmit( pInfo, bAlways ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::Spawn( void ) +{ + Precache(); + + BaseClass::Spawn(); + + m_bEnabled = !HasSpawnFlags( SF_TESTDISPLAY_START_DISABLED ); + + SpawnControlPanels(); + + ScreenVisible( m_bEnabled ); + + m_bDoFullTransmit = true; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::Precache( void ) +{ + BaseClass::Precache(); + + PrecacheVGuiScreen( "text_display_panel" ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::OnRestore( void ) +{ + BaseClass::OnRestore(); + + RestoreControlPanels(); + + ScreenVisible( m_bEnabled ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::ScreenVisible( bool bVisible ) +{ + // Set its active state + m_hScreen->SetActive( bVisible ); + + if ( bVisible ) + { + m_hScreen->RemoveEffects( EF_NODRAW ); + } + else + { + m_hScreen->AddEffects( EF_NODRAW ); + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::Disable( void ) +{ + if ( !m_bEnabled ) + return; + + m_bEnabled = false; + + ScreenVisible( false ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::Enable( void ) +{ + if ( m_bEnabled ) + return; + + m_bEnabled = true; + + ScreenVisible( true ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputDisable( inputdata_t &inputdata ) +{ + Disable(); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputEnable( inputdata_t &inputdata ) +{ + Enable(); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputSetMessage( inputdata_t &inputdata ) +{ + Q_strcpy( m_szDisplayText.GetForModify(), inputdata.value.String() ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputSetTextAlignment( inputdata_t &inputdata ) +{ + m_iContentAlignment = inputdata.value.Int(); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputSetFont( inputdata_t &inputdata ) +{ + Q_strcpy( m_szFont.GetForModify(), inputdata.value.String() ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputSetResolution( inputdata_t &inputdata ) +{ + m_iResolution = inputdata.value.Int(); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::InputSetTextSize( inputdata_t &inputdata ) +{ + m_flTextSize = inputdata.value.Float(); + + if (m_hScreen) + { + m_hScreen->SetActualSize( m_flTextSize, m_flTextSize ); + m_hScreen->SetLocalOrigin( m_hScreen->CollisionProp()->OBBCenter() * -1.0f ); + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) +{ + pPanelName = "text_display_panel"; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ) +{ + pPanelName = "vgui_screen"; +} + +//----------------------------------------------------------------------------- +// This is called by the base object when it's time to spawn the control panels +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::SpawnControlPanels() +{ + int nPanel; + for ( nPanel = 0; true; ++nPanel ) + { + const char *pScreenName; + GetControlPanelInfo( nPanel, pScreenName ); + if (!pScreenName) + continue; + + const char *pScreenClassname; + GetControlPanelClassName( nPanel, pScreenClassname ); + if ( !pScreenClassname ) + continue; + + float flWidth = m_flTextSize; + float flHeight = m_flTextSize; + + CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, this, this, 0 ); + pScreen->ChangeTeam( GetTeamNumber() ); + pScreen->SetActualSize( flWidth, flHeight ); + pScreen->SetLocalOrigin( pScreen->CollisionProp()->OBBCenter() * -1.0f ); + pScreen->SetActive( true ); + pScreen->MakeVisibleOnlyToTeammates( false ); + pScreen->SetTransparency( true ); + m_hScreen = pScreen; + + return; + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CVGuiTextDisplay::RestoreControlPanels( void ) +{ + int nPanel; + for ( nPanel = 0; true; ++nPanel ) + { + const char *pScreenName; + GetControlPanelInfo( nPanel, pScreenName ); + if (!pScreenName) + continue; + + const char *pScreenClassname; + GetControlPanelClassName( nPanel, pScreenClassname ); + if ( !pScreenClassname ) + continue; + + CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname ); + + while ( ( pScreen && pScreen->GetOwnerEntity() != this ) || Q_strcmp( pScreen->GetPanelName(), pScreenName ) != 0 ) + { + pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname ); + } + + if ( pScreen ) + { + m_hScreen = pScreen; + m_hScreen->SetActive( true ); + } + + return; + } +} diff --git a/sp/src/game/server/server_mapbase.vpc b/sp/src/game/server/server_mapbase.vpc index 37146238..bbb17d88 100644 --- a/sp/src/game/server/server_mapbase.vpc +++ b/sp/src/game/server/server_mapbase.vpc @@ -74,6 +74,7 @@ $Project $File "mapbase\SystemConvarMod.cpp" $File "mapbase\SystemConvarMod.h" $File "mapbase\variant_tools.h" + $File "mapbase\vgui_text_display.cpp" $File "mapbase\logic_eventlistener.cpp" $File "mapbase\logic_register_activator.cpp"