diff options
Diffstat (limited to 'gameui/LoadingDialog.cpp')
| -rw-r--r-- | gameui/LoadingDialog.cpp | 669 |
1 files changed, 669 insertions, 0 deletions
diff --git a/gameui/LoadingDialog.cpp b/gameui/LoadingDialog.cpp new file mode 100644 index 0000000..b0d6be6 --- /dev/null +++ b/gameui/LoadingDialog.cpp @@ -0,0 +1,669 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + + +#include "LoadingDialog.h" +#include "EngineInterface.h" +#include "IGameUIFuncs.h" + +#include <vgui/IInput.h> +#include <vgui/ISurface.h> +#include <vgui/ILocalize.h> +#include <vgui/IScheme.h> +#include <vgui/ISystem.h> +#include <vgui_controls/ProgressBar.h> +#include <vgui_controls/Label.h> +#include <vgui_controls/Button.h> +#include <vgui_controls/HTML.h> +#include <vgui_controls/RichText.h> +#include "tier0/icommandline.h" + +#include "GameUI_Interface.h" +#include "ModInfo.h" +#include "BasePanel.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CLoadingDialog::CLoadingDialog( vgui::Panel *parent ) : Frame(parent, "LoadingDialog") +{ + SetDeleteSelfOnClose(true); + + // Use console style + m_bConsoleStyle = GameUI().IsConsoleUI(); + + if ( !m_bConsoleStyle ) + { + SetSize( 416, 100 ); + SetTitle( "#GameUI_Loading", true ); + } + + // center the loading dialog, unless we have another dialog to show in the background + m_bCenter = !GameUI().HasLoadingBackgroundDialog(); + + m_bShowingSecondaryProgress = false; + m_flSecondaryProgress = 0.0f; + m_flLastSecondaryProgressUpdateTime = 0.0f; + m_flSecondaryProgressStartTime = 0.0f; + + m_pProgress = new ProgressBar( this, "Progress" ); + m_pProgress2 = new ProgressBar( this, "Progress2" ); + m_pInfoLabel = new Label( this, "InfoLabel", "" ); + m_pCancelButton = new Button( this, "CancelButton", "#GameUI_Cancel" ); + m_pTimeRemainingLabel = new Label( this, "TimeRemainingLabel", "" ); + m_pCancelButton->SetCommand( "Cancel" ); + + if ( ModInfo().IsSinglePlayerOnly() == false && m_bConsoleStyle == true ) + { + m_pLoadingBackground = new Panel( this, "LoadingDialogBG" ); + } + else + { + m_pLoadingBackground = NULL; + } + + SetMinimizeButtonVisible( false ); + SetMaximizeButtonVisible( false ); + SetCloseButtonVisible( false ); + SetSizeable( false ); + SetMoveable( false ); + + if ( m_bConsoleStyle ) + { + m_bCenter = false; + m_pProgress->SetVisible( false ); + m_pProgress2->SetVisible( false ); + m_pInfoLabel->SetVisible( false ); + m_pCancelButton->SetVisible( false ); + m_pTimeRemainingLabel->SetVisible( false ); + m_pCancelButton->SetVisible( false ); + + SetMinimumSize( 0, 0 ); + SetTitleBarVisible( false ); + + m_flProgressFraction = 0; + } + else + { + m_pInfoLabel->SetBounds(20, 32, 392, 24); + m_pProgress->SetBounds(20, 64, 300, 24); + m_pCancelButton->SetBounds(330, 64, 72, 24); + m_pProgress2->SetVisible(false); + } + + SetupControlSettings( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CLoadingDialog::~CLoadingDialog() +{ + if ( input()->GetAppModalSurface() == GetVPanel() ) + { + vgui::surface()->RestrictPaintToSinglePanel( NULL ); + } +} + +void CLoadingDialog::PaintBackground() +{ + if ( !m_bConsoleStyle ) + { + BaseClass::PaintBackground(); + return; + } + + // draw solid progress bar with curved endcaps + int panelWide, panelTall; + GetSize( panelWide, panelTall ); + int barWide, barTall; + m_pProgress->GetSize( barWide, barTall ); + int x = ( panelWide - barWide )/2; + int y = panelTall - barTall; + + if ( m_pLoadingBackground ) + { + vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); + Color color = GetSchemeColor( "TanDarker", Color(255, 255, 255, 255), vgui::scheme()->GetIScheme(scheme) ); + + m_pLoadingBackground->SetFgColor( color ); + m_pLoadingBackground->SetBgColor( color ); + + m_pLoadingBackground->SetPaintBackgroundEnabled( true ); + } + + if ( ModInfo().IsSinglePlayerOnly() ) + { + DrawBox( x, y, barWide, barTall, Color( 0, 0, 0, 255 ), 1.0f ); + } + + DrawBox( x+2, y+2, barWide-4, barTall-4, Color( 100, 100, 100, 255 ), 1.0f ); + + barWide = m_flProgressFraction * ( barWide - 4 ); + if ( barWide >= 12 ) + { + // cannot draw a curved box smaller than 12 without artifacts + DrawBox( x+2, y+2, barWide, barTall-4, Color( 200, 100, 0, 255 ), 1.0f ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: sets up dialog layout +//----------------------------------------------------------------------------- +void CLoadingDialog::SetupControlSettings( bool bForceShowProgressText ) +{ + m_bShowingVACInfo = false; + + if ( GameUI().IsConsoleUI() ) + { + KeyValues *pControlSettings = BasePanel()->GetConsoleControlSettings()->FindKey( "LoadingDialogNoBanner.res" ); + LoadControlSettings( "null", NULL, pControlSettings ); + return; + } + + if ( ModInfo().IsSinglePlayerOnly() && !bForceShowProgressText ) + { + LoadControlSettings("Resource/LoadingDialogNoBannerSingle.res"); + } + else if ( gameuifuncs->IsConnectedToVACSecureServer() ) + { + LoadControlSettings("Resource/LoadingDialogVAC.res"); + m_bShowingVACInfo = true; + } + else + { + LoadControlSettings("Resource/LoadingDialogNoBanner.res"); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Activates the loading screen, initializing and making it visible +//----------------------------------------------------------------------------- +void CLoadingDialog::Open() +{ + if ( !m_bConsoleStyle ) + { + SetTitle( "#GameUI_Loading", true ); + } + + HideOtherDialogs( true ); + BaseClass::Activate(); + + if ( !m_bConsoleStyle ) + { + m_pProgress->SetVisible( true ); + if ( !ModInfo().IsSinglePlayerOnly() ) + { + m_pInfoLabel->SetVisible( true ); + } + m_pInfoLabel->SetText(""); + + m_pCancelButton->SetText("#GameUI_Cancel"); + m_pCancelButton->SetCommand("Cancel"); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: error display file +//----------------------------------------------------------------------------- +void CLoadingDialog::SetupControlSettingsForErrorDisplay( const char *settingsFile ) +{ + if ( m_bConsoleStyle ) + { + return; + } + + m_bCenter = true; + SetTitle("#GameUI_Disconnected", true); + m_pInfoLabel->SetText(""); + LoadControlSettings( settingsFile ); + HideOtherDialogs( true ); + + BaseClass::Activate(); + + m_pProgress->SetVisible(false); + + m_pInfoLabel->SetVisible(true); + m_pCancelButton->SetText("#GameUI_Close"); + m_pCancelButton->SetCommand("Close"); + m_pInfoLabel->InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: shows or hides other top-level dialogs +//----------------------------------------------------------------------------- +void CLoadingDialog::HideOtherDialogs( bool bHide ) +{ + if ( bHide ) + { + if ( GameUI().HasLoadingBackgroundDialog() ) + { + // if we have a loading background dialog, hide any other dialogs by moving the full-screen background dialog to the + // front, then moving ourselves in front of it + GameUI().ShowLoadingBackgroundDialog(); + vgui::ipanel()->MoveToFront( GetVPanel() ); + vgui::input()->SetAppModalSurface( GetVPanel() ); + } + else + { + // if there is no loading background dialog, use VGUI paint restrictions to hide other dialogs + vgui::surface()->RestrictPaintToSinglePanel(GetVPanel()); + } + } + else + { + if ( GameUI().HasLoadingBackgroundDialog() ) + { + GameUI().HideLoadingBackgroundDialog(); + vgui::input()->SetAppModalSurface( NULL ); + } + else + { + // remove any rendering restrictions + vgui::surface()->RestrictPaintToSinglePanel(NULL); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Turns dialog into error display +//----------------------------------------------------------------------------- +void CLoadingDialog::DisplayGenericError(const char *failureReason, const char *extendedReason) +{ + if ( m_bConsoleStyle ) + { + return; + } + + // In certain race conditions, DisplayGenericError can get called AFTER OnClose() has been called. + // If that happens and we don't call Activate(), then it'll continue closing when we don't want it to. + Activate(); + + SetupControlSettingsForErrorDisplay("Resource/LoadingDialogError.res"); + + if ( extendedReason && strlen( extendedReason ) > 0 ) + { + wchar_t compositeReason[256], finalMsg[512], formatStr[256]; + if ( extendedReason[0] == '#' ) + { + wcsncpy(compositeReason, g_pVGuiLocalize->Find(extendedReason), sizeof( compositeReason ) / sizeof( wchar_t ) ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode(extendedReason, compositeReason, sizeof( compositeReason )); + } + + if ( failureReason[0] == '#' ) + { + wcsncpy(formatStr, g_pVGuiLocalize->Find(failureReason), sizeof( formatStr ) / sizeof( wchar_t ) ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode(failureReason, formatStr, sizeof( formatStr )); + } + + g_pVGuiLocalize->ConstructString(finalMsg, sizeof( finalMsg ), formatStr, 1, compositeReason); + m_pInfoLabel->SetText(finalMsg); + } + else + { + m_pInfoLabel->SetText(failureReason); + } + + int wide, tall; + int x,y; + m_pInfoLabel->GetContentSize( wide, tall ); + m_pInfoLabel->GetPos( x, y ); + SetTall( tall + y + 50 ); + + int buttonX, buttonY; + m_pCancelButton->GetPos( buttonX, buttonY ); + m_pCancelButton->SetPos( buttonX, tall + y + 6 ); + + m_pCancelButton->RequestFocus(); +} + + +//----------------------------------------------------------------------------- +// Purpose: explain to the user they can't join secure servers due to a VAC ban +//----------------------------------------------------------------------------- +void CLoadingDialog::DisplayVACBannedError() +{ + if ( m_bConsoleStyle ) + { + return; + } + + SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorVACBanned.res"); + SetTitle("#VAC_ConnectionRefusedTitle", true); +} + + +//----------------------------------------------------------------------------- +// Purpose: explain to the user they can't connect to public servers due to +// not having a valid connection to Steam +// this should only happen if they are a pirate +//----------------------------------------------------------------------------- +void CLoadingDialog::DisplayNoSteamConnectionError() +{ + if ( m_bConsoleStyle ) + { + return; + } + + SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorNoSteamConnection.res"); +} + + +//----------------------------------------------------------------------------- +// Purpose: explain to the user they got kicked from a server due to that same account +// logging in from another location. This also triggers the refresh login dialog on OK +// being pressed. +//----------------------------------------------------------------------------- +void CLoadingDialog::DisplayLoggedInElsewhereError() +{ + if ( m_bConsoleStyle ) + { + return; + } + + SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorLoggedInElsewhere.res"); + m_pCancelButton->SetText("#GameUI_RefreshLogin_Login"); + m_pCancelButton->SetCommand("Login"); +} + + +//----------------------------------------------------------------------------- +// Purpose: sets status info text +//----------------------------------------------------------------------------- +void CLoadingDialog::SetStatusText(const char *statusText) +{ + if ( m_bConsoleStyle ) + { + return; + } + + m_pInfoLabel->SetText(statusText); +} + +//----------------------------------------------------------------------------- +// Purpose: returns the previous state +//----------------------------------------------------------------------------- +bool CLoadingDialog::SetShowProgressText( bool show ) +{ + if ( m_bConsoleStyle ) + { + return false; + } + + bool bret = m_pInfoLabel->IsVisible(); + if ( bret != show ) + { + SetupControlSettings( show ); + m_pInfoLabel->SetVisible( show ); + } + return bret; +} + +//----------------------------------------------------------------------------- +// Purpose: updates time remaining +//----------------------------------------------------------------------------- +void CLoadingDialog::OnThink() +{ + BaseClass::OnThink(); + + if ( !m_bConsoleStyle && m_bShowingSecondaryProgress ) + { + // calculate the time remaining string + wchar_t unicode[512]; + if (m_flSecondaryProgress >= 1.0f) + { + m_pTimeRemainingLabel->SetText("complete"); + } + else if (ProgressBar::ConstructTimeRemainingString(unicode, sizeof(unicode), m_flSecondaryProgressStartTime, (float)system()->GetFrameTime(), m_flSecondaryProgress, m_flLastSecondaryProgressUpdateTime, true)) + { + m_pTimeRemainingLabel->SetText(unicode); + } + else + { + m_pTimeRemainingLabel->SetText(""); + } + } + + SetAlpha( 255 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLoadingDialog::PerformLayout() +{ + if ( m_bConsoleStyle ) + { + // place in lower center + int screenWide, screenTall; + surface()->GetScreenSize( screenWide, screenTall ); + int wide,tall; + GetSize( wide, tall ); + int x = 0; + int y = 0; + + if ( ModInfo().IsSinglePlayerOnly() ) + { + x = ( screenWide - wide ) * 0.50f; + y = ( screenTall - tall ) * 0.86f; + } + else + { + x = ( screenWide - ( wide * 1.30f ) ); + y = ( ( screenTall * 0.875f ) ); + } + + SetPos( x, y ); + } + else if ( m_bCenter ) + { + MoveToCenterOfScreen(); + } + else + { + // if we're not supposed to be centered, move ourselves to the lower right hand corner of the screen + int x, y, screenWide, screenTall; + surface()->GetWorkspaceBounds( x, y, screenWide, screenTall ); + int wide,tall; + GetSize( wide, tall ); + + if ( IsPC() ) + { + x = screenWide - ( wide + 10 ); + y = screenTall - ( tall + 10 ); + } + else + { + // Move farther in so we're title safe + x = screenWide - wide - (screenWide * 0.05); + y = screenTall - tall - (screenTall * 0.05); + } + + x -= m_iAdditionalIndentX; + y -= m_iAdditionalIndentY; + + SetPos( x, y ); + } + + BaseClass::PerformLayout(); + + vgui::ipanel()->MoveToFront( GetVPanel() ); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the number of ticks has changed +//----------------------------------------------------------------------------- +bool CLoadingDialog::SetProgressPoint( float fraction ) +{ + if ( m_bConsoleStyle ) + { + if ( fraction >= 0.99f ) + { + // show the progress artifically completed to fill in 100% + fraction = 1.0f; + } + fraction = clamp( fraction, 0.0f, 1.0f ); + if ( (int)(fraction * 25) != (int)(m_flProgressFraction * 25) ) + { + m_flProgressFraction = fraction; + return true; + } + return IsX360(); + } + + if ( !m_bShowingVACInfo && gameuifuncs->IsConnectedToVACSecureServer() ) + { + SetupControlSettings( false ); + } + + int nOldDrawnSegments = m_pProgress->GetDrawnSegmentCount(); + m_pProgress->SetProgress( fraction ); + int nNewDrawSegments = m_pProgress->GetDrawnSegmentCount(); + return (nOldDrawnSegments != nNewDrawSegments) || IsX360(); +} + +//----------------------------------------------------------------------------- +// Purpose: sets and shows the secondary progress bar +//----------------------------------------------------------------------------- +void CLoadingDialog::SetSecondaryProgress( float progress ) +{ + if ( m_bConsoleStyle ) + return; + + // don't show the progress if we've jumped right to completion + if (!m_bShowingSecondaryProgress && progress > 0.99f) + return; + + // if we haven't yet shown secondary progress then reconfigure the dialog + if (!m_bShowingSecondaryProgress) + { + LoadControlSettings("Resource/LoadingDialogDualProgress.res"); + m_bShowingSecondaryProgress = true; + m_pProgress2->SetVisible(true); + m_flSecondaryProgressStartTime = (float)system()->GetFrameTime(); + } + + // if progress has increased then update the progress counters + if (progress > m_flSecondaryProgress) + { + m_pProgress2->SetProgress(progress); + m_flSecondaryProgress = progress; + m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime(); + } + + // if progress has decreased then reset progress counters + if (progress < m_flSecondaryProgress) + { + m_pProgress2->SetProgress(progress); + m_flSecondaryProgress = progress; + m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime(); + m_flSecondaryProgressStartTime = (float)system()->GetFrameTime(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLoadingDialog::SetSecondaryProgressText(const char *statusText) +{ + if ( m_bConsoleStyle ) + { + return; + } + + SetControlString( "SecondaryProgressLabel", statusText ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLoadingDialog::OnClose() +{ + // remove any rendering restrictions + HideOtherDialogs( false ); + + BaseClass::OnClose(); +} + +//----------------------------------------------------------------------------- +// Purpose: command handler +//----------------------------------------------------------------------------- +void CLoadingDialog::OnCommand(const char *command) +{ + if ( !stricmp(command, "Cancel") ) + { + // disconnect from the server + engine->ClientCmd_Unrestricted("disconnect\n"); + + // close + Close(); + } + else + { + BaseClass::OnCommand(command); + } +} + +void CLoadingDialog::OnKeyCodeTyped(KeyCode code) +{ + if ( m_bConsoleStyle ) + { + return; + } + + if ( code == KEY_ESCAPE ) + { + OnCommand("Cancel"); + } + else + { + BaseClass::OnKeyCodeTyped(code); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Maps ESC to quiting loading +//----------------------------------------------------------------------------- +void CLoadingDialog::OnKeyCodePressed(KeyCode code) +{ + if ( m_bConsoleStyle ) + { + return; + } + + ButtonCode_t nButtonCode = GetBaseButtonCode( code ); + + if ( nButtonCode == KEY_XBUTTON_B || nButtonCode == KEY_XBUTTON_A || nButtonCode == STEAMCONTROLLER_A || nButtonCode == STEAMCONTROLLER_B ) + { + OnCommand("Cancel"); + } + else + { + BaseClass::OnKeyCodePressed(code); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Singleton accessor +//----------------------------------------------------------------------------- +extern vgui::DHANDLE<CLoadingDialog> g_hLoadingDialog; +CLoadingDialog *LoadingDialog() +{ + return g_hLoadingDialog.Get(); +} |