summaryrefslogtreecommitdiff
path: root/engine/cl_pluginhelpers.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/cl_pluginhelpers.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/cl_pluginhelpers.cpp')
-rw-r--r--engine/cl_pluginhelpers.cpp637
1 files changed, 637 insertions, 0 deletions
diff --git a/engine/cl_pluginhelpers.cpp b/engine/cl_pluginhelpers.cpp
new file mode 100644
index 0000000..05394e2
--- /dev/null
+++ b/engine/cl_pluginhelpers.cpp
@@ -0,0 +1,637 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: baseclientstate.cpp: implementation of the CBaseClientState class.
+//
+//===========================================================================//
+
+#include "client_pch.h"
+#include "limits.h"
+#include "cl_pluginhelpers.h"
+
+#include <inetchannel.h>
+
+#include <vgui/ISurface.h>
+#include <vgui/IScheme.h>
+#include <vgui/ILocalize.h>
+#include <vgui/IVGui.h>
+#include <vgui/IPanel.h>
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/Frame.h>
+#include <vgui_controls/EditablePanel.h>
+#include <vgui_controls/Button.h>
+#include <vgui_controls/RichText.h>
+#include <vgui_controls/Label.h>
+#include <vgui_controls/TextEntry.h>
+#include <vgui_controls/ImagePanel.h>
+#include <vgui_controls/AnimationController.h>
+#include "vgui_baseui_interface.h"
+#include "vgui_askconnectpanel.h"
+#include "cmd.h"
+#include "tier1/convar.h"
+#include "baseclientstate.h"
+
+extern CClientState cl;
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays the options menu
+//-----------------------------------------------------------------------------
+class CPluginMenu : public vgui::EditablePanel
+{
+private:
+ DECLARE_CLASS_SIMPLE( CPluginMenu, vgui::EditablePanel );
+
+public:
+ CPluginMenu( vgui::Panel *parent );
+ virtual ~CPluginMenu();
+
+ void Show( KeyValues *kv );
+ void OnCommand(const char *command);
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CPluginMenu::CPluginMenu( vgui::Panel *parent ) : EditablePanel(parent, "PluginMenu" )
+{
+ LoadControlSettings("Resource/UI/PluginMenu.res");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CPluginMenu::~CPluginMenu()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Show the options menu after using key values to configure it
+//-----------------------------------------------------------------------------
+void CPluginMenu::Show( KeyValues *kv )
+{
+ vgui::Label *control = dynamic_cast<vgui::Label *>(FindChildByName("Text"));
+ if (control)
+ {
+ control->SetText( kv->GetWString( "msg" ) );
+ }
+
+
+ int i = 0;
+ // hide all the buttons
+ for ( i = 0; i < GetChildCount(); i++ )
+ {
+ vgui::Button *button = dynamic_cast<vgui::Button *>(GetChild(i));
+ if ( button )
+ {
+ button->SetVisible( false );
+ }
+ }
+
+ i = 1;
+ // now work out what buttons to display
+ for ( KeyValues *pCur=kv->GetFirstTrueSubKey(); pCur; pCur=pCur->GetNextTrueSubKey(), i++ )
+ {
+ char controlName[64];
+ Q_snprintf( controlName, sizeof(controlName), "option%i", i );
+ vgui::Button *button = dynamic_cast<vgui::Button *>(FindChildByName(controlName,true));
+ Assert( button );
+ if ( button )
+ {
+ button->SetText( pCur->GetWString( "msg" ));
+ button->SetCommand( pCur->GetString( "command" ));
+ button->SetVisible( true );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: when a button is pressed send that command back to the engine
+//-----------------------------------------------------------------------------
+void CPluginMenu::OnCommand( const char *command )
+{
+ Cbuf_AddText( command );
+ Cbuf_AddText( "\n" );
+
+ CallParentFunction( new KeyValues( "Command", "command", "close" ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays the gameui portion of plugin menus
+//-----------------------------------------------------------------------------
+class CPluginGameUIDialog : public vgui::Frame
+{
+private:
+ DECLARE_CLASS_SIMPLE( CPluginGameUIDialog, vgui::Frame );
+
+public:
+ CPluginGameUIDialog();
+ virtual ~CPluginGameUIDialog();
+
+ virtual void Show( DIALOG_TYPE type, KeyValues *kv );
+
+protected:
+ void OnCommand( const char *cmd );
+
+private:
+ CPluginMenu *m_Menu;
+ vgui::RichText *m_RichText;
+ vgui::Label *m_Message;
+ vgui::TextEntry *m_Entry;
+ vgui::Label *m_EntryLabel;
+ vgui::Button *m_CloseButton;
+ char m_szEntryCommand[ 255 ];
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor
+//-----------------------------------------------------------------------------
+CPluginGameUIDialog::CPluginGameUIDialog() : vgui::Frame( NULL, "Plugins" )
+{
+ // initialize dialog
+ SetTitle( "Plugins", true );
+ SetAlpha( 255 );
+
+ SetScheme( "Tracker" );
+
+ m_szEntryCommand[ 0 ] = 0;
+
+ m_Menu = new CPluginMenu( this );
+ m_RichText = new vgui::RichText( this, "Rich" );
+ m_Message = new vgui::Label( this, "Label", "" );
+ m_Entry = new vgui::TextEntry( this, "Entry" );
+ m_EntryLabel = new vgui::Label( this, "EntryLabel", "" );
+ m_CloseButton = new vgui::Button( this, "Close", "");
+
+ LoadControlSettings("Resource/UI/Plugin.res");
+ InvalidateLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor
+//-----------------------------------------------------------------------------
+CPluginGameUIDialog::~CPluginGameUIDialog()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: called when the close button is pressed
+//-----------------------------------------------------------------------------
+void CPluginGameUIDialog::OnCommand( const char *cmd )
+{
+ if ( !Q_stricmp( cmd, "close" ) )
+ {
+ if ( Q_strlen(m_szEntryCommand) > 0 )
+ {
+ // Check that we can add the two execution markers
+ if ( !Cbuf_HasRoomForExecutionMarkers( 2 ) )
+ {
+ AssertMsg( false, "CPluginGameUIDialog::OnCommand called but there is no room for the execution markers. Ignoring command." );
+ return;
+ }
+
+ char userCMD[ 512 ];
+ char entryText[ 255 ];
+ m_Entry->GetText( entryText, sizeof(entryText) );
+ Q_snprintf( userCMD, sizeof(userCMD), "%s %s\n", m_szEntryCommand, entryText );
+
+ // Only let them run commands marked with FCVAR_CLIENTCMD_CAN_EXECUTE.
+ Cbuf_AddTextWithMarkers( eCmdExecutionMarker_Enable_FCVAR_CLIENTCMD_CAN_EXECUTE, userCMD, eCmdExecutionMarker_Disable_FCVAR_CLIENTCMD_CAN_EXECUTE );
+ }
+ Close();
+ g_PluginManager->OnPanelClosed();
+ }
+ else
+ {
+ BaseClass::OnCommand( cmd );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: shows a precanned style of message in the GameUI
+//-----------------------------------------------------------------------------
+void CPluginGameUIDialog::Show( DIALOG_TYPE type, KeyValues *kv )
+{
+ m_Menu->SetVisible(false);
+ m_RichText->SetVisible(false);
+ m_Message->SetVisible(false);
+ m_Entry->SetVisible(false);
+ m_EntryLabel->SetVisible(false);
+ m_szEntryCommand[ 0 ] = 0;
+
+ SetTitle( kv->GetWString( "title" ), true );
+
+ switch ( type )
+ {
+ case DIALOG_MENU: // a options menu
+ m_Menu->Show( kv );
+ m_Menu->SetVisible( true );
+ break;
+ case DIALOG_TEXT: // a richtext dialog
+ m_RichText->SetText( kv->GetWString( "msg" ) );
+ m_RichText->SetVisible( true );
+ break;
+ case DIALOG_MSG: // just a msg to the screen, don't display in the gameui
+ SetVisible( false );
+ return;
+ break;
+ case DIALOG_ENTRY:
+ m_Entry->SetVisible( true );
+ m_EntryLabel->SetVisible( true );
+ m_EntryLabel->SetText( kv->GetWString( "msg" ) );
+ Q_strncpy( m_szEntryCommand, kv->GetString( "command" ), sizeof(m_szEntryCommand) );
+ m_CloseButton->SetText( "#GameUI_OK" );
+ break;
+ default:
+ Msg( "Invalid menu type (%i)\n", type );
+ break;
+ }
+ Activate();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: the individual message snippets
+//-----------------------------------------------------------------------------
+class CMessage : public vgui::Label
+{
+private:
+ DECLARE_CLASS_SIMPLE( CMessage, vgui::Label );
+public:
+ CMessage(vgui::Panel *parent, const char *panelName, const char *text);
+ ~CMessage();
+
+ bool HasExtraPanel() { return m_bHasExtraPanel; }
+
+protected:
+ void ApplySchemeSettings( vgui::IScheme *pScheme );
+
+private:
+ bool m_bHasExtraPanel;
+};
+
+CMessage::CMessage( vgui::Panel *parent, const char *panelName, const char *text ) : vgui::Label( parent, panelName, text )
+{
+ m_bHasExtraPanel = false;
+}
+
+CMessage::~CMessage()
+{
+}
+
+void CMessage::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ vgui::HFont font = pScheme->GetFont( "PluginText", false );
+ if ( font == vgui::INVALID_FONT )
+ {
+ font = pScheme->GetFont( "HudHintText", false );
+ }
+ SetFont(font);
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: the hud plugin message panel
+//-----------------------------------------------------------------------------
+class CPluginHudMessage : public vgui::Frame
+{
+private:
+ DECLARE_CLASS_SIMPLE( CPluginHudMessage, vgui::Frame );
+
+public:
+ CPluginHudMessage( vgui::VPANEL parent );
+ ~CPluginHudMessage();
+
+ void ShowMessage( const wchar_t *message, int time, Color clr, bool bHasExtraPanel );
+ void StartHiding();
+ void Hide();
+
+protected:
+ void ApplySchemeSettings( vgui::IScheme *pScheme );
+ void OnTick();
+ void OnSizeChanged( int newWide, int newTall );
+
+private:
+ enum { MESSAGE_X_INSET = 40, MAX_TEXT_LEN_PIXELS = 400 };
+
+ CMessage *m_Message;
+ vgui::ImagePanel *m_pExtraPanelIcon;
+ bool m_bHidingControl;
+ int m_iTargetH, m_iTargetW;
+ Color m_fgColor;
+
+ vgui::AnimationController *m_pAnimationController;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor
+//-----------------------------------------------------------------------------
+CPluginHudMessage::CPluginHudMessage( vgui::VPANEL parent ) : vgui::Frame( NULL, "PluginHudMessage" )
+{
+ SetParent( parent );
+ SetVisible( false );
+ SetAlpha( 255 );
+ SetMinimumSize( 10 , 10 );
+
+ SetScheme( "ClientScheme" );
+ SetMoveable(false);
+ SetSizeable(false);
+ SetKeyBoardInputEnabled( false );
+ SetMouseInputEnabled( false );
+ SetTitleBarVisible( false );
+
+ m_pExtraPanelIcon = new vgui::ImagePanel( this, "ExtraPanelIcon" );
+ m_pExtraPanelIcon->SetVisible( false );
+
+ m_Message = new CMessage( this, "Msg", "");
+ m_Message->SetVisible( false );
+
+ m_pAnimationController = new vgui::AnimationController( NULL );
+ m_pAnimationController->SetParent( parent );
+ m_pAnimationController->SetScriptFile( parent, "scripts/plugin_animations.txt" );
+ m_pAnimationController->SetProportional( false );
+
+ vgui::ivgui()->AddTickSignal(GetVPanel());
+
+ LoadControlSettings("Resource/UI/PluginHud.res");
+ InvalidateLayout();
+ GetSize( m_iTargetW, m_iTargetH );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor
+//-----------------------------------------------------------------------------
+CPluginHudMessage::~CPluginHudMessage()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: set the see through color and rounded corners
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ m_pExtraPanelIcon->SetImage( vgui::scheme()->GetImage( "plugin/message_waiting", true ) );
+ BaseClass::ApplySchemeSettings( pScheme );
+ SetBgColor( pScheme->GetColor( "Plugins.BgColor", pScheme->GetColor( "TransparentBlack", Color( 0, 0, 0, 192 ))) );
+ SetPaintBackgroundType( 2 );
+
+ m_Message->SetFgColor( m_fgColor );
+ m_pExtraPanelIcon->SetVisible( !m_bHidingControl );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: run the anim controller and hide the message label if the anim var says to
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::OnTick()
+{
+ m_pAnimationController->UpdateAnimations( Sys_FloatTime() );
+ BaseClass::OnTick();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: get the label size to track
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::OnSizeChanged( int newWide, int newTall )
+{
+ BaseClass::OnSizeChanged( newWide, newTall );
+ int w, h;
+ GetSize( w, h );
+ m_Message->SetBounds( MESSAGE_X_INSET, 5, w - MESSAGE_X_INSET - 10, h - 10 );
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: start the shrinking anim for the control if it should be showed, the hide anim otherwsise
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::StartHiding()
+{
+ if ( m_pExtraPanelIcon->IsVisible() )
+ {
+ m_pAnimationController->StartAnimationSequence( "PluginMessageSmall" );
+ }
+ else
+ {
+ Hide();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: starts the hide anim for the control
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::Hide()
+{
+ m_pAnimationController->StartAnimationSequence( "PluginMessageHide" );
+ m_pExtraPanelIcon->SetVisible( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: shows a text message on the hud
+//-----------------------------------------------------------------------------
+void CPluginHudMessage::ShowMessage( const wchar_t *text, int time, Color clr, bool bHasExtraPanel )
+{
+ m_Message->SetVisible( true );
+ m_Message->SetBounds( MESSAGE_X_INSET, 5, m_iTargetW - MESSAGE_X_INSET - 10, m_iTargetH - 10 );
+ m_Message->SetText( text );
+ m_Message->SetFgColor( clr );
+ m_fgColor = clr;
+ m_bHidingControl = !bHasExtraPanel;
+
+ if ( bHasExtraPanel )
+ {
+ m_pExtraPanelIcon->SetVisible( true );
+ }
+
+ m_pAnimationController->StartAnimationSequence( "PluginMessageShow" );
+
+ SetVisible( true );
+ InvalidateLayout();
+ int textW, textH;
+ m_Message->GetContentSize( textW, textH );
+
+ textW = min( textW + MESSAGE_X_INSET + 10, (int)MAX_TEXT_LEN_PIXELS );
+ SetSize( textW, m_iTargetH ); // the "small" animation event changes our size
+}
+
+
+
+
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor
+//-----------------------------------------------------------------------------
+CPluginUIManager::CPluginUIManager() : vgui::Panel( NULL, "PluginManager" )
+{
+ m_iCurPriority = INT_MAX;
+ m_iMessageDisplayUntil = 0;
+ m_iHudDisplayUntil = 0;
+ m_bShutdown = false;
+
+ m_pGameUIDialog = new CPluginGameUIDialog();
+ Assert( m_pGameUIDialog );
+ m_pGameUIDialog->SetParent( EngineVGui()->GetPanel( PANEL_GAMEUIDLL ) );
+
+ m_pHudMessage = new CPluginHudMessage(EngineVGui()->GetPanel( PANEL_CLIENTDLL ));
+ Assert( m_pHudMessage );
+
+ vgui::ivgui()->AddTickSignal(GetVPanel());
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor
+//-----------------------------------------------------------------------------
+CPluginUIManager::~CPluginUIManager()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: hides the two plugin dialogs at the appropriate times
+//-----------------------------------------------------------------------------
+void CPluginUIManager::OnTick()
+{
+ if ( m_bShutdown )
+ {
+ return;
+ }
+
+ if ( m_iMessageDisplayUntil != 0 && !EngineVGui()->IsGameUIVisible() && m_iMessageDisplayUntil < Sys_FloatTime() ) // check the GameUI large message
+ {
+ m_pGameUIDialog->SetVisible( false );
+ m_pHudMessage->Hide();
+ m_iMessageDisplayUntil = 0;
+ m_iCurPriority = INT_MAX;
+ }
+
+ if ( m_iHudDisplayUntil != 0 && m_iHudDisplayUntil < Sys_FloatTime() ) // check the hud panel
+ {
+ m_pHudMessage->StartHiding();
+ m_iHudDisplayUntil = 0;
+ }
+
+ BaseClass::OnTick();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: shuts down the plugin UI
+//-----------------------------------------------------------------------------
+void CPluginUIManager::Shutdown()
+{
+ vgui::ivgui()->RemoveTickSignal(GetVPanel());
+ m_pHudMessage->Hide();
+ m_pGameUIDialog->SetVisible( false );
+ MarkForDeletion();
+ m_bShutdown = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: shows a particular ui type and queues their lifetime
+//-----------------------------------------------------------------------------
+void CPluginUIManager::Show( DIALOG_TYPE type, KeyValues *kv )
+{
+ // Check for the special DIALOG_ASKCONNECT command.
+ if ( type == DIALOG_ASKCONNECT )
+ {
+ // Don't allow this prompt on QuickPlay servers
+ if ( cl.IsClientConnectionViaMatchMaking() )
+ return;
+
+ // Do the askconnect dialog.
+ float flDuration = kv->GetFloat( "time", 4.0f );
+ const char *pIP = kv->GetString( "title", NULL );
+ if ( !pIP )
+ {
+ DevMsg( "Ignoring DIALOG_ASKCONNECT message. No IP specified." );
+ return;
+ }
+
+ ShowAskConnectPanel( pIP, flDuration );
+ return;
+ }
+
+ int level = kv->GetInt( "level", INT_MAX );
+ if ( level < m_iCurPriority )
+ {
+ m_iCurPriority = level;
+ }
+ else
+ {
+ DevMsg( "Ignoring message %s, %i < %i\n", kv->GetName(), level, m_iCurPriority );
+ return;
+ }
+
+ if ( type != DIALOG_MSG )
+ {
+ m_iMessageDisplayUntil = Sys_FloatTime() + min(max( kv->GetInt( "time", 10 ),10),200);
+ }
+ else
+ {
+ m_iMessageDisplayUntil = Sys_FloatTime() + 10;
+ }
+
+ m_iHudDisplayUntil = Sys_FloatTime() + 10; // hud messages only get 10 seconds
+
+ m_pGameUIDialog->Show( type, kv );
+ Color clr( 255, 255, 255, 255 );
+ if ( !kv->IsEmpty( "color" ) )
+ {
+ clr = kv->GetColor( "color" );
+ }
+
+ m_pHudMessage->ShowMessage( kv->GetWString( "title" ), 10, clr, type != DIALOG_MSG );
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: called when the gameui panel is closed
+//-----------------------------------------------------------------------------
+void CPluginUIManager::OnPanelClosed()
+{
+ m_iCurPriority = INT_MAX;
+ m_iHudDisplayUntil = 0;
+ m_iMessageDisplayUntil = 0;
+ m_pGameUIDialog->SetVisible( false );
+ m_pHudMessage->Hide();
+}
+
+void CPluginUIManager::GetHudMessagePosition( int &x, int &y, int &wide, int &tall )
+{
+ if ( m_pHudMessage )
+ {
+ m_pHudMessage->GetBounds( x, y, wide, tall );
+ }
+ else
+ {
+ x = y = wide = tall = 0;
+ }
+}
+
+CPluginUIManager *g_PluginManager = NULL;
+
+
+//=============================================================================
+//
+// external interfaces
+//
+//=============================================================================
+ConVar cl_showpluginmessages ( "cl_showpluginmessages", "1", FCVAR_ARCHIVE, "Allow plugins to display messages to you" );
+
+void PluginHelpers_Menu( SVC_Menu *msg )
+{
+ if ( !msg->m_MenuKeyValues )
+ {
+ return;
+ }
+
+ if ( !cl_showpluginmessages.GetBool() )
+ {
+ return;
+ }
+
+ if ( !g_PluginManager )
+ {
+ g_PluginManager = new CPluginUIManager();
+ }
+
+ g_PluginManager->Show( msg->m_Type, msg->m_MenuKeyValues );
+}