diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/game_controls/SpectatorGUI.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'game/client/game_controls/SpectatorGUI.cpp')
| -rw-r--r-- | game/client/game_controls/SpectatorGUI.cpp | 887 |
1 files changed, 887 insertions, 0 deletions
diff --git a/game/client/game_controls/SpectatorGUI.cpp b/game/client/game_controls/SpectatorGUI.cpp new file mode 100644 index 0000000..41b33a3 --- /dev/null +++ b/game/client/game_controls/SpectatorGUI.cpp @@ -0,0 +1,887 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "inputsystem/iinputsystem.h" +#include "input.h" +#include <cdll_client_int.h> +#include <globalvars_base.h> +#include <cdll_util.h> +#include <KeyValues.h> + +#include "spectatorgui.h" + +#include <vgui/IScheme.h> +#include <vgui/ILocalize.h> +#include <vgui/ISurface.h> +#include <vgui/IPanel.h> +#include <vgui_controls/ImageList.h> +#include <vgui_controls/MenuItem.h> +#include <vgui_controls/TextImage.h> + +#include <stdio.h> // _snprintf define + +#include <game/client/iviewport.h> +#include "commandmenu.h" +#include "hltvcamera.h" +#if defined( REPLAY_ENABLED ) +#include "replay/replaycamera.h" +#endif + +#include <vgui_controls/TextEntry.h> +#include <vgui_controls/Panel.h> +#include <vgui_controls/ImagePanel.h> +#include <vgui_controls/Menu.h> +#include "IGameUIFuncs.h" // for key bindings +#include <imapoverview.h> +#include <shareddefs.h> +#include <igameresources.h> + +#ifdef TF_CLIENT_DLL +#include "tf_gamerules.h" +void AddSubKeyNamed( KeyValues *pKeys, const char *pszName ); +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifndef _XBOX +extern IGameUIFuncs *gameuifuncs; // for key binding details +#endif + +// void DuckMessage(const char *str); // from vgui_teamfortressviewport.cpp + +ConVar spec_scoreboard( "spec_scoreboard", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE ); + +CSpectatorGUI *g_pSpectatorGUI = NULL; + + +// NB disconnect between localization text and observer mode enums +static const char *s_SpectatorModes[] = +{ + "#Spec_Mode0", // OBS_MODE_NONE = 0, + "#Spec_Mode1", // OBS_MODE_DEATHCAM, + "", // OBS_MODE_FREEZECAM, + "#Spec_Mode2", // OBS_MODE_FIXED, + "#Spec_Mode3", // OBS_MODE_IN_EYE, + "#Spec_Mode4", // OBS_MODE_CHASE, + "#Spec_Mode_POI", // OBS_MODE_POI, PASSTIME + "#Spec_Mode5", // OBS_MODE_ROAMING, +}; + +using namespace vgui; + +ConVar cl_spec_mode( + "cl_spec_mode", + "1", + FCVAR_ARCHIVE | FCVAR_USERINFO | FCVAR_SERVER_CAN_EXECUTE, + "spectator mode" ); + + + +//----------------------------------------------------------------------------- +// Purpose: left and right buttons pointing buttons +//----------------------------------------------------------------------------- +class CSpecButton : public Button +{ +public: + CSpecButton(Panel *parent, const char *panelName): Button(parent, panelName, "") {} + +private: + void ApplySchemeSettings(vgui::IScheme *pScheme) + { + Button::ApplySchemeSettings(pScheme); + SetFont(pScheme->GetFont("Marlett", IsProportional()) ); + } +}; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CSpectatorMenu::CSpectatorMenu( IViewPort *pViewPort ) : Frame( NULL, PANEL_SPECMENU ) +{ + m_iDuckKey = BUTTON_CODE_INVALID; + + m_pViewPort = pViewPort; + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + SetTitleBarVisible( false ); // don't draw a title bar + SetMoveable( false ); + SetSizeable( false ); + SetProportional(true); + + SetScheme("ClientScheme"); + + m_pPlayerList = new ComboBox(this, "playercombo", 10 , false); + HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false ); + if ( INVALID_FONT != hFallbackFont ) + { + m_pPlayerList->SetUseFallbackFont( true, hFallbackFont ); + } + + m_pViewOptions = new ComboBox(this, "viewcombo", 10 , false ); + m_pConfigSettings = new ComboBox(this, "settingscombo", 10 , false ); + + m_pLeftButton = new CSpecButton( this, "specprev"); + m_pLeftButton->SetText("3"); + m_pRightButton = new CSpecButton( this, "specnext"); + m_pRightButton->SetText("4"); + + m_pPlayerList->SetText(""); + m_pViewOptions->SetText("#Spec_Modes"); + m_pConfigSettings->SetText("#Spec_Options"); + + m_pPlayerList->SetOpenDirection( Menu::UP ); + m_pViewOptions->SetOpenDirection( Menu::UP ); + m_pConfigSettings->SetOpenDirection( Menu::UP ); + + // create view config menu + CommandMenu * menu = new CommandMenu(m_pConfigSettings, "spectatormenu", gViewPortInterface); + menu->LoadFromFile( "Resource/spectatormenu.res" ); + m_pConfigSettings->SetMenu( menu ); // attach menu to combo box + + // create view mode menu + menu = new CommandMenu(m_pViewOptions, "spectatormodes", gViewPortInterface); + menu->LoadFromFile("Resource/spectatormodes.res"); + m_pViewOptions->SetMenu( menu ); // attach menu to combo box + + LoadControlSettings( "Resource/UI/BottomSpectator.res" ); + + ListenForGameEvent( "spec_target_updated" ); +} + +void CSpectatorMenu::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + // need to MakeReadyForUse() on the menus so we can set their bg color before they are displayed + m_pConfigSettings->GetMenu()->MakeReadyForUse(); + m_pViewOptions->GetMenu()->MakeReadyForUse(); + m_pPlayerList->GetMenu()->MakeReadyForUse(); + + if ( g_pSpectatorGUI ) + { + m_pConfigSettings->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() ); + m_pViewOptions->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() ); + m_pPlayerList->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: makes the GUI fill the screen +//----------------------------------------------------------------------------- +void CSpectatorMenu::PerformLayout() +{ + int w,h; + GetHudSize(w, h); + + // fill the screen + SetSize(w,GetTall()); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles changes to combo boxes +//----------------------------------------------------------------------------- +void CSpectatorMenu::OnTextChanged(KeyValues *data) +{ + Panel *panel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") ); + + vgui::ComboBox *box = dynamic_cast<vgui::ComboBox *>( panel ); + + if( box == m_pConfigSettings) // don't change the text in the config setting combo + { + m_pConfigSettings->SetText("#Spec_Options"); + } + else if ( box == m_pPlayerList ) + { + KeyValues *kv = box->GetActiveItemUserData(); + if ( kv && GameResources() ) + { + const char *player = kv->GetString("player"); + + int currentPlayerNum = GetSpectatorTarget(); + const char *currentPlayerName = GameResources()->GetPlayerName( currentPlayerNum ); + + if ( !FStrEq( currentPlayerName, player ) ) + { + char command[128]; + Q_snprintf( command, sizeof(command), "spec_player \"%s\"", player ); + engine->ClientCmd( command ); + } + } + } +} + +void CSpectatorMenu::OnCommand( const char *command ) +{ + if (!stricmp(command, "specnext") ) + { + engine->ClientCmd("spec_next"); + } + else if (!stricmp(command, "specprev") ) + { + engine->ClientCmd("spec_prev"); + } +} + +void CSpectatorMenu::FireGameEvent( IGameEvent * event ) +{ + const char *pEventName = event->GetName(); + + if ( Q_strcmp( "spec_target_updated", pEventName ) == 0 ) + { + IGameResources *gr = GameResources(); + if ( !gr ) + return; + + // make sure the player combo box is up to date + int playernum = GetSpectatorTarget(); + if ( playernum < 1 || playernum > MAX_PLAYERS ) + return; + + const char *selectedPlayerName = gr->GetPlayerName( playernum ); + const char *currentPlayerName = ""; + KeyValues *kv = m_pPlayerList->GetActiveItemUserData(); + if ( kv ) + { + currentPlayerName = kv->GetString( "player" ); + } + if ( !FStrEq( currentPlayerName, selectedPlayerName ) ) + { + for ( int i=0; i<m_pPlayerList->GetItemCount(); ++i ) + { + KeyValues *pKv = m_pPlayerList->GetItemUserData( i ); + if ( pKv && FStrEq( pKv->GetString( "player" ), selectedPlayerName ) ) + { + m_pPlayerList->ActivateItemByRow( i ); + break; + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: when duck is pressed it hides the active part of the GUI +//----------------------------------------------------------------------------- +void CSpectatorMenu::OnKeyCodePressed(KeyCode code) +{ + if ( code == m_iDuckKey ) + { + // hide if DUCK is pressed again + m_pViewPort->ShowPanel( this, false ); + } +} + +void CSpectatorMenu::ShowPanel(bool bShow) +{ + if ( BaseClass::IsVisible() == bShow ) + return; + + if ( bShow ) + { + // Force relayout in case Steam Controller stuff has changed. + InvalidateLayout( true, true ); + Activate(); + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + } + else + { + SetVisible( false ); + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); + } + + bool bIsEnabled = true; + + if ( engine->IsHLTV() && HLTVCamera()->IsPVSLocked() ) + { + // when watching HLTV or Replay with a locked PVS, some elements are disabled + bIsEnabled = false; + } + + m_pLeftButton->SetVisible( bIsEnabled ); + m_pRightButton->SetVisible( bIsEnabled ); + m_pPlayerList->SetVisible( bIsEnabled ); + m_pViewOptions->SetVisible( bIsEnabled ); +} + +void CSpectatorMenu::Update( void ) +{ + IGameResources *gr = GameResources(); + + Reset(); + + if ( m_iDuckKey == BUTTON_CODE_INVALID ) + { + m_iDuckKey = gameuifuncs->GetButtonCodeForBind( "duck" ); + } + + if ( !gr ) + return; + + int iPlayerIndex; + for ( iPlayerIndex = 1 ; iPlayerIndex <= gpGlobals->maxClients; iPlayerIndex++ ) + { + + // does this slot in the array have a name? + if ( !gr->IsConnected( iPlayerIndex ) ) + continue; + + if ( gr->IsLocalPlayer( iPlayerIndex ) ) + continue; + + if ( !gr->IsAlive( iPlayerIndex ) ) + continue; + + wchar_t playerText[ 80 ], playerName[ 64 ], *team, teamText[ 64 ]; + char localizeTeamName[64]; + char szPlayerIndex[16]; + g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName( gr->GetPlayerName(iPlayerIndex) ), playerName, sizeof( playerName ) ); + const char * teamname = gr->GetTeamName( gr->GetTeam(iPlayerIndex) ); + if ( teamname ) + { + Q_snprintf( localizeTeamName, sizeof( localizeTeamName ), "#%s", teamname ); + team=g_pVGuiLocalize->Find( localizeTeamName ); + + if ( !team ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( teamname , teamText, sizeof( teamText ) ); + team = teamText; + } + + g_pVGuiLocalize->ConstructString_safe( playerText, g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, team ); + } + else + { + g_pVGuiLocalize->ConstructString_safe( playerText, g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName ); + } + + Q_snprintf( szPlayerIndex, sizeof( szPlayerIndex ), "%d", iPlayerIndex ); + + KeyValues *kv = new KeyValues( "UserData", "player", gr->GetPlayerName( iPlayerIndex ), "index", szPlayerIndex ); + m_pPlayerList->AddItem( playerText, kv ); + kv->deleteThis(); + } + + // make sure the player combo box is up to date + int playernum = GetSpectatorTarget(); + const char *selectedPlayerName = gr->GetPlayerName( playernum ); + for ( iPlayerIndex=0; iPlayerIndex<m_pPlayerList->GetItemCount(); ++iPlayerIndex ) + { + KeyValues *kv = m_pPlayerList->GetItemUserData( iPlayerIndex ); + if ( kv && FStrEq( kv->GetString( "player" ), selectedPlayerName ) ) + { + m_pPlayerList->ActivateItemByRow( iPlayerIndex ); + break; + } + } + + //============================================================================= + // HPE_BEGIN: + // [pfreese] make sure the view mode combo box is up to date - the spectator + // mode can be changed multiple ways + //============================================================================= + + int specmode = GetSpectatorMode(); + m_pViewOptions->SetText(s_SpectatorModes[specmode]); + + //============================================================================= + // HPE_END + //============================================================================= +} + +//----------------------------------------------------------------------------- +// main spectator panel + + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CSpectatorGUI::CSpectatorGUI(IViewPort *pViewPort) : EditablePanel( NULL, PANEL_SPECGUI ) +{ +// m_bHelpShown = false; +// m_bInsetVisible = false; +// m_iDuckKey = KEY_NONE; + SetSize( 10, 10 ); // Quiet "parent not sized yet" spew + m_bSpecScoreboard = false; + + m_pViewPort = pViewPort; + g_pSpectatorGUI = this; + + // initialize dialog + SetVisible(false); + SetProportional(true); + + // load the new scheme early!! + SetScheme("ClientScheme"); + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); + + m_pTopBar = new Panel( this, "topbar" ); + m_pBottomBarBlank = new Panel( this, "bottombarblank" ); + + // m_pBannerImage = new ImagePanel( m_pTopBar, NULL ); + m_pPlayerLabel = new Label( this, "playerlabel", "" ); + m_pPlayerLabel->SetVisible( false ); + TextImage *image = m_pPlayerLabel->GetTextImage(); + if ( image ) + { + HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false ); + if ( INVALID_FONT != hFallbackFont ) + { + image->SetUseFallbackFont( true, hFallbackFont ); + } + } + + SetPaintBorderEnabled(false); + SetPaintBackgroundEnabled(false); + + // m_pBannerImage->SetVisible(false); + InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CSpectatorGUI::~CSpectatorGUI() +{ + g_pSpectatorGUI = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the colour of the top and bottom bars +//----------------------------------------------------------------------------- +void CSpectatorGUI::ApplySchemeSettings(IScheme *pScheme) +{ + KeyValues *pConditions = NULL; + +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + { + pConditions = new KeyValues( "conditions" ); + AddSubKeyNamed( pConditions, "if_mvm" ); + } +#endif + + LoadControlSettings( GetResFile(), NULL, NULL, pConditions ); + + if ( pConditions ) + { + pConditions->deleteThis(); + } + + m_pBottomBarBlank->SetVisible( true ); + m_pTopBar->SetVisible( true ); + + BaseClass::ApplySchemeSettings( pScheme ); + SetBgColor(Color( 0,0,0,0 ) ); // make the background transparent + m_pTopBar->SetBgColor(GetBlackBarColor()); + m_pBottomBarBlank->SetBgColor(GetBlackBarColor()); + // m_pBottomBar->SetBgColor(Color( 0,0,0,0 )); + SetPaintBorderEnabled(false); + + SetBorder( NULL ); + +#ifdef CSTRIKE_DLL + SetZPos(80); // guarantee it shows above the scope +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: makes the GUI fill the screen +//----------------------------------------------------------------------------- +void CSpectatorGUI::PerformLayout() +{ + int w,h,x,y; + GetHudSize(w, h); + + // fill the screen + SetBounds(0,0,w,h); + + // stretch the bottom bar across the screen + m_pBottomBarBlank->GetPos(x,y); + m_pBottomBarBlank->SetSize( w, h - y ); +} + +//----------------------------------------------------------------------------- +// Purpose: checks spec_scoreboard cvar to see if the scoreboard should be displayed +//----------------------------------------------------------------------------- +void CSpectatorGUI::OnThink() +{ + BaseClass::OnThink(); + + if ( IsVisible() ) + { + if ( m_bSpecScoreboard != spec_scoreboard.GetBool() ) + { + if ( !spec_scoreboard.GetBool() || !gViewPortInterface->GetActivePanel() ) + { + m_bSpecScoreboard = spec_scoreboard.GetBool(); + gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, m_bSpecScoreboard ); + } + } + +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->ShowMatchSummary() ) + { + SetVisible( false ); + } +#endif + } +} + +//----------------------------------------------------------------------------- +// Purpose: sets the image to display for the banner in the top right corner +//----------------------------------------------------------------------------- +void CSpectatorGUI::SetLogoImage(const char *image) +{ + if ( m_pBannerImage ) + { + m_pBannerImage->SetImage( scheme()->GetImage(image, false) ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the text of a control by name +//----------------------------------------------------------------------------- +void CSpectatorGUI::SetLabelText(const char *textEntryName, const char *text) +{ + Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName)); + if (entry) + { + entry->SetText(text); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the text of a control by name +//----------------------------------------------------------------------------- +void CSpectatorGUI::SetLabelText(const char *textEntryName, wchar_t *text) +{ + Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName)); + if (entry) + { + entry->SetText(text); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the text of a control by name +//----------------------------------------------------------------------------- +void CSpectatorGUI::MoveLabelToFront(const char *textEntryName) +{ + Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName)); + if (entry) + { + entry->MoveToFront(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: shows/hides the buy menu +//----------------------------------------------------------------------------- +void CSpectatorGUI::ShowPanel(bool bShow) +{ + if ( bShow && !IsVisible() ) + { + InvalidateLayout( true, true ); + m_bSpecScoreboard = false; + } + + SetVisible( bShow ); + + if ( !bShow && m_bSpecScoreboard ) + { + gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, false ); + } +} + +bool CSpectatorGUI::ShouldShowPlayerLabel( int specmode ) +{ + return ( (specmode == OBS_MODE_IN_EYE) || (specmode == OBS_MODE_CHASE) ); +} +//----------------------------------------------------------------------------- +// Purpose: Updates the gui, rearranges elements +//----------------------------------------------------------------------------- +void CSpectatorGUI::Update() +{ + int wide, tall; + int bx, by, bwide, btall; + + GetHudSize(wide, tall); + m_pTopBar->GetBounds( bx, by, bwide, btall ); + + IGameResources *gr = GameResources(); + int specmode = GetSpectatorMode(); + int playernum = GetSpectatorTarget(); + + IViewPortPanel *overview = gViewPortInterface->FindPanelByName( PANEL_OVERVIEW ); + + if ( overview && overview->IsVisible() ) + { + int mx, my, mwide, mtall; + + VPANEL p = overview->GetVPanel(); + vgui::ipanel()->GetPos( p, mx, my ); + vgui::ipanel()->GetSize( p, mwide, mtall ); + + if ( my < btall ) + { + // reduce to bar + m_pTopBar->SetSize( wide - (mx + mwide), btall ); + m_pTopBar->SetPos( (mx + mwide), 0 ); + } + else + { + // full top bar + m_pTopBar->SetSize( wide , btall ); + m_pTopBar->SetPos( 0, 0 ); + } + } + else + { + // full top bar + m_pTopBar->SetSize( wide , btall ); // change width, keep height + m_pTopBar->SetPos( 0, 0 ); + } + + m_pPlayerLabel->SetVisible( ShouldShowPlayerLabel(specmode) ); + + // update player name filed, text & color + + if ( playernum > 0 && playernum <= gpGlobals->maxClients && gr ) + { + Color c = gr->GetTeamColor( gr->GetTeam(playernum) ); // Player's team color + + m_pPlayerLabel->SetFgColor( c ); + + wchar_t playerText[ 80 ], playerName[ 64 ], health[ 10 ]; + V_wcsncpy( playerText, L"Unable to find #Spec_PlayerItem*", sizeof( playerText ) ); + memset( playerName, 0x0, sizeof( playerName ) ); + + g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName(gr->GetPlayerName( playernum )), playerName, sizeof( playerName ) ); + int iHealth = gr->GetHealth( playernum ); + if ( iHealth > 0 && gr->IsAlive(playernum) ) + { + _snwprintf( health, ARRAYSIZE( health ), L"%i", iHealth ); + g_pVGuiLocalize->ConstructString_safe( playerText, g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, health ); + } + else + { + g_pVGuiLocalize->ConstructString_safe( playerText, g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName ); + } + + m_pPlayerLabel->SetText( playerText ); + } + else + { + m_pPlayerLabel->SetText( L"" ); + } + + // update extra info field + wchar_t szEtxraInfo[1024]; + wchar_t szTitleLabel[1024]; + char tempstr[128]; + + if ( engine->IsHLTV() ) + { + // set spectator number and HLTV title + Q_snprintf(tempstr,sizeof(tempstr),"Spectators : %d", HLTVCamera()->GetNumSpectators() ); + g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szEtxraInfo,sizeof(szEtxraInfo)); + + Q_strncpy( tempstr, HLTVCamera()->GetTitleText(), sizeof(tempstr) ); + g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szTitleLabel,sizeof(szTitleLabel)); + } + else + { + // otherwise show map name + Q_FileBase( engine->GetLevelName(), tempstr, sizeof(tempstr) ); + + wchar_t wMapName[64]; + g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,wMapName,sizeof(wMapName)); + g_pVGuiLocalize->ConstructString_safe( szEtxraInfo, g_pVGuiLocalize->Find("#Spec_Map" ),1, wMapName ); + + g_pVGuiLocalize->ConvertANSIToUnicode( "" ,szTitleLabel,sizeof(szTitleLabel)); + } + + SetLabelText("extrainfo", szEtxraInfo ); + SetLabelText("titlelabel", szTitleLabel ); +} + +//----------------------------------------------------------------------------- +// Purpose: Gets the res file we should use (depends on if we're in Steam Controller mode) +//----------------------------------------------------------------------------- +const char * CSpectatorGUI::GetResFile( void ) +{ + if ( ::input->IsSteamControllerActive() ) + { + return "Resource/UI/Spectator_SC.res"; + } + else + { + return "Resource/UI/Spectator.res"; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Updates the timer label if one exists +//----------------------------------------------------------------------------- +void CSpectatorGUI::UpdateTimer() +{ + wchar_t szText[ 63 ]; + + int timer = 0; + + V_swprintf_safe ( szText, L"%d:%02d\n", (timer / 60), (timer % 60) ); + + SetLabelText("timerlabel", szText ); +} + +static void ForwardSpecCmdToServer( const CCommand &args ) +{ + if ( engine->IsPlayingDemo() ) + return; + + if ( args.ArgC() == 1 ) + { + // just forward the command without parameters + engine->ServerCmd( args[ 0 ] ); + } + else if ( args.ArgC() == 2 ) + { + // forward the command with parameter + // XXX(JohnS): Whyyyyy + char command[128]; + Q_snprintf( command, sizeof(command), "%s \"%s\"", args[ 0 ], args[ 1 ] ); + engine->ServerCmd( command ); + } +} + +CON_COMMAND_F( spec_next, "Spectate next player", FCVAR_CLIENTCMD_CAN_EXECUTE ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if ( !pPlayer || !pPlayer->IsObserver() ) + return; + + if ( engine->IsHLTV() ) + { + // handle the command clientside + if ( !HLTVCamera()->IsPVSLocked() ) + { + HLTVCamera()->SpecNextPlayer( false ); + } + } + else + { + ForwardSpecCmdToServer( args ); + } +} + +CON_COMMAND_F( spec_prev, "Spectate previous player", FCVAR_CLIENTCMD_CAN_EXECUTE ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if ( !pPlayer || !pPlayer->IsObserver() ) + return; + + if ( engine->IsHLTV() ) + { + // handle the command clientside + if ( !HLTVCamera()->IsPVSLocked() ) + { + HLTVCamera()->SpecNextPlayer( true ); + } + } + else + { + ForwardSpecCmdToServer( args ); + } +} + +CON_COMMAND_F( spec_mode, "Set spectator mode", FCVAR_CLIENTCMD_CAN_EXECUTE ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if ( !pPlayer || !pPlayer->IsObserver() ) + return; + + if ( engine->IsHLTV() ) + { + if ( HLTVCamera()->IsPVSLocked() ) + { + // in locked mode we can only switch between first and 3rd person + HLTVCamera()->ToggleChaseAsFirstPerson(); + } + else + { + // we can choose any mode, not loked to PVS + int mode; + + if ( args.ArgC() == 2 ) + { + // set specifc mode + mode = Q_atoi( args[1] ); + } + else + { + // set next mode + mode = HLTVCamera()->GetMode()+1; + + if ( mode > LAST_PLAYER_OBSERVERMODE ) + mode = OBS_MODE_IN_EYE; + else if ( mode == OBS_MODE_POI ) // PASSTIME skip POI mode since hltv doesn't have the entity data required to make it work + mode = OBS_MODE_ROAMING; + } + + // handle the command clientside + HLTVCamera()->SetMode( mode ); + } + + // turn off auto director once user tried to change view settings + HLTVCamera()->SetAutoDirector( false ); + } + else + { + // we spectate on a game server, forward command + ForwardSpecCmdToServer( args ); + } +} + +CON_COMMAND_F( spec_player, "Spectate player by partial name, steamid, or userid", FCVAR_CLIENTCMD_CAN_EXECUTE ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if ( !pPlayer || !pPlayer->IsObserver() ) + return; + + if ( args.ArgC() != 2 ) + { + ConMsg( "Usage: spec_player { steamid | #userid | partial name match }\n" ); + return; + } + + if ( engine->IsHLTV() ) + { + // we can only switch primary spectator targets is PVS isnt locked by auto-director + if ( !HLTVCamera()->IsPVSLocked() ) + { + HLTVCamera()->SpecPlayerByPredicate( args[1] ); + } + } + else + { + ForwardSpecCmdToServer( args ); + } +} + + + |