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.
669 lines
18 KiB
669 lines
18 KiB
//========= 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(); |
|
}
|
|
|