Counter Strike : Global Offensive Source Code
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.

637 lines
18 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "LoadingDialog.h"
  8. #include "EngineInterface.h"
  9. #include "igameuifuncs.h"
  10. #include <vgui/IInput.h>
  11. #include <vgui/ISurface.h>
  12. #include <vgui/ILocalize.h>
  13. #include <vgui/IScheme.h>
  14. #include <vgui/ISystem.h>
  15. #include <vgui_controls/ProgressBar.h>
  16. #include <vgui_controls/Label.h>
  17. #include <vgui_controls/Button.h>
  18. #include <vgui_controls/HTML.h>
  19. #include <vgui_controls/RichText.h>
  20. #include "tier0/icommandline.h"
  21. #include "GameUI_Interface.h"
  22. #include "ModInfo.h"
  23. #include "basepanel.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include <tier0/memdbgon.h>
  26. using namespace vgui;
  27. //-----------------------------------------------------------------------------
  28. // Purpose: Constructor
  29. //-----------------------------------------------------------------------------
  30. CLoadingDialog::CLoadingDialog( vgui::Panel *parent ) : Frame(parent, "LoadingDialog")
  31. {
  32. SetDeleteSelfOnClose(true);
  33. // Use console style
  34. m_bConsoleStyle = GameUI().IsConsoleUI();
  35. if ( !m_bConsoleStyle )
  36. {
  37. SetSize( 416, 100 );
  38. SetTitle( "#GameUI_Loading", true );
  39. }
  40. // center the loading dialog, unless we have another dialog to show in the background
  41. m_bCenter = !GameUI().HasLoadingBackgroundDialog();
  42. m_bShowingSecondaryProgress = false;
  43. m_flSecondaryProgress = 0.0f;
  44. m_flLastSecondaryProgressUpdateTime = 0.0f;
  45. m_flSecondaryProgressStartTime = 0.0f;
  46. m_pProgress = new ProgressBar( this, "Progress" );
  47. m_pProgress2 = new ProgressBar( this, "Progress2" );
  48. m_pInfoLabel = new Label( this, "InfoLabel", "" );
  49. m_pCancelButton = new Button( this, "CancelButton", "#GameUI_Cancel" );
  50. m_pTimeRemainingLabel = new Label( this, "TimeRemainingLabel", "" );
  51. m_pCancelButton->SetCommand( "Cancel" );
  52. if ( ModInfo().IsSinglePlayerOnly() == false && m_bConsoleStyle == true )
  53. {
  54. m_pLoadingBackground = new Panel( this, "LoadingDialogBG" );
  55. }
  56. else
  57. {
  58. m_pLoadingBackground = NULL;
  59. }
  60. SetMinimizeButtonVisible( false );
  61. SetMaximizeButtonVisible( false );
  62. SetCloseButtonVisible( false );
  63. SetSizeable( false );
  64. SetMoveable( false );
  65. if ( m_bConsoleStyle )
  66. {
  67. m_bCenter = false;
  68. m_pProgress->SetVisible( false );
  69. m_pProgress2->SetVisible( false );
  70. m_pInfoLabel->SetVisible( false );
  71. m_pCancelButton->SetVisible( false );
  72. m_pTimeRemainingLabel->SetVisible( false );
  73. m_pCancelButton->SetVisible( false );
  74. SetMinimumSize( 0, 0 );
  75. SetTitleBarVisible( false );
  76. m_flProgressFraction = 0;
  77. }
  78. else
  79. {
  80. m_pInfoLabel->SetBounds(20, 32, 392, 24);
  81. m_pProgress->SetBounds(20, 64, 300, 24);
  82. m_pCancelButton->SetBounds(330, 64, 72, 24);
  83. m_pInfoLabel->SetTextColorState(Label::CS_DULL);
  84. m_pProgress2->SetVisible(false);
  85. }
  86. SetupControlSettings( false );
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose: Destructor
  90. //-----------------------------------------------------------------------------
  91. CLoadingDialog::~CLoadingDialog()
  92. {
  93. }
  94. void CLoadingDialog::PaintBackground()
  95. {
  96. if ( !m_bConsoleStyle )
  97. {
  98. BaseClass::PaintBackground();
  99. return;
  100. }
  101. // draw solid progress bar with curved endcaps
  102. int panelWide, panelTall;
  103. GetSize( panelWide, panelTall );
  104. int barWide, barTall;
  105. m_pProgress->GetSize( barWide, barTall );
  106. int x = ( panelWide - barWide )/2;
  107. int y = panelTall - barTall;
  108. if ( m_pLoadingBackground )
  109. {
  110. vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
  111. Color color = GetSchemeColor( "TanDarker", Color(255, 255, 255, 255), vgui::scheme()->GetIScheme(scheme) );
  112. m_pLoadingBackground->SetFgColor( color );
  113. m_pLoadingBackground->SetBgColor( color );
  114. m_pLoadingBackground->SetPaintBackgroundEnabled( true );
  115. }
  116. if ( ModInfo().IsSinglePlayerOnly() )
  117. {
  118. DrawBox( x, y, barWide, barTall, Color( 0, 0, 0, 255 ), 1.0f );
  119. }
  120. DrawBox( x+2, y+2, barWide-4, barTall-4, Color( 100, 100, 100, 255 ), 1.0f );
  121. barWide = m_flProgressFraction * ( barWide - 4 );
  122. if ( barWide >= 12 )
  123. {
  124. // cannot draw a curved box smaller than 12 without artifacts
  125. DrawBox( x+2, y+2, barWide, barTall-4, Color( 200, 100, 0, 255 ), 1.0f );
  126. }
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose: sets up dialog layout
  130. //-----------------------------------------------------------------------------
  131. void CLoadingDialog::SetupControlSettings( bool bForceShowProgressText )
  132. {
  133. m_bShowingVACInfo = false;
  134. #if defined( BASEPANEL_LEGACY_SOURCE1 )
  135. if ( GameUI().IsConsoleUI() )
  136. {
  137. KeyValues *pControlSettings = BasePanel()->GetConsoleControlSettings()->FindKey( "LoadingDialogNoBanner.res" );
  138. LoadControlSettings( "null", NULL, pControlSettings );
  139. return;
  140. }
  141. #endif
  142. if ( ModInfo().IsSinglePlayerOnly() && !bForceShowProgressText )
  143. {
  144. LoadControlSettings("Resource/LoadingDialogNoBannerSingle.res");
  145. }
  146. else if ( gameuifuncs->IsConnectedToVACSecureServer() )
  147. {
  148. LoadControlSettings("Resource/LoadingDialogVAC.res");
  149. m_bShowingVACInfo = true;
  150. }
  151. else
  152. {
  153. LoadControlSettings("Resource/LoadingDialogNoBanner.res");
  154. }
  155. }
  156. //-----------------------------------------------------------------------------
  157. // Purpose: Activates the loading screen, initializing and making it visible
  158. //-----------------------------------------------------------------------------
  159. void CLoadingDialog::Open()
  160. {
  161. if ( !m_bConsoleStyle )
  162. {
  163. SetTitle( "#GameUI_Loading", true );
  164. }
  165. HideOtherDialogs( true );
  166. BaseClass::Activate();
  167. if ( !m_bConsoleStyle )
  168. {
  169. m_pProgress->SetVisible( true );
  170. if ( !ModInfo().IsSinglePlayerOnly() )
  171. {
  172. m_pInfoLabel->SetVisible( true );
  173. }
  174. m_pInfoLabel->SetText("");
  175. m_pCancelButton->SetText("#GameUI_Cancel");
  176. m_pCancelButton->SetCommand("Cancel");
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Purpose: error display file
  181. //-----------------------------------------------------------------------------
  182. void CLoadingDialog::SetupControlSettingsForErrorDisplay( const char *settingsFile )
  183. {
  184. if ( m_bConsoleStyle )
  185. {
  186. return;
  187. }
  188. m_bCenter = true;
  189. SetTitle("#GameUI_Disconnected", true);
  190. m_pInfoLabel->SetText("");
  191. LoadControlSettings( settingsFile );
  192. HideOtherDialogs( true );
  193. BaseClass::Activate();
  194. m_pProgress->SetVisible(false);
  195. m_pInfoLabel->SetVisible(true);
  196. m_pCancelButton->SetText("#GameUI_Close");
  197. m_pCancelButton->SetCommand("Close");
  198. m_pInfoLabel->InvalidateLayout();
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Purpose: shows or hides other top-level dialogs
  202. //-----------------------------------------------------------------------------
  203. void CLoadingDialog::HideOtherDialogs( bool bHide )
  204. {
  205. if ( bHide )
  206. {
  207. if ( GameUI().HasLoadingBackgroundDialog() )
  208. {
  209. // if we have a loading background dialog, hide any other dialogs by moving the full-screen background dialog to the
  210. // front, then moving ourselves in front of it
  211. GameUI().ShowLoadingBackgroundDialog();
  212. vgui::ipanel()->MoveToFront( GetVPanel() );
  213. vgui::input()->SetAppModalSurface( GetVPanel() );
  214. }
  215. else
  216. {
  217. // if there is no loading background dialog, use VGUI paint restrictions to hide other dialogs
  218. vgui::surface()->RestrictPaintToSinglePanel(GetVPanel());
  219. }
  220. }
  221. else
  222. {
  223. if ( GameUI().HasLoadingBackgroundDialog() )
  224. {
  225. GameUI().HideLoadingBackgroundDialog();
  226. vgui::input()->SetAppModalSurface( NULL );
  227. }
  228. else
  229. {
  230. // remove any rendering restrictions
  231. vgui::surface()->RestrictPaintToSinglePanel(NULL);
  232. }
  233. }
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose: Turns dialog into error display
  237. //-----------------------------------------------------------------------------
  238. void CLoadingDialog::DisplayGenericError(const char *failureReason, const char *extendedReason)
  239. {
  240. if ( m_bConsoleStyle )
  241. {
  242. return;
  243. }
  244. // In certain race conditions, DisplayGenericError can get called AFTER OnClose() has been called.
  245. // If that happens and we don't call Activate(), then it'll continue closing when we don't want it to.
  246. Activate();
  247. SetupControlSettingsForErrorDisplay("Resource/LoadingDialogError.res");
  248. if ( extendedReason && strlen( extendedReason ) > 0 )
  249. {
  250. wchar_t compositeReason[256], finalMsg[512], formatStr[256];
  251. if ( extendedReason[0] == '#' )
  252. {
  253. wcsncpy(compositeReason, g_pVGuiLocalize->Find(extendedReason), sizeof( compositeReason ) / sizeof( wchar_t ) );
  254. }
  255. else
  256. {
  257. g_pVGuiLocalize->ConvertANSIToUnicode(extendedReason, compositeReason, sizeof( compositeReason ));
  258. }
  259. if ( failureReason[0] == '#' )
  260. {
  261. wcsncpy(formatStr, g_pVGuiLocalize->Find(failureReason), sizeof( formatStr ) / sizeof( wchar_t ) );
  262. }
  263. else
  264. {
  265. g_pVGuiLocalize->ConvertANSIToUnicode(failureReason, formatStr, sizeof( formatStr ));
  266. }
  267. g_pVGuiLocalize->ConstructString(finalMsg, sizeof( finalMsg ), formatStr, 1, compositeReason);
  268. m_pInfoLabel->SetText(finalMsg);
  269. }
  270. else
  271. {
  272. m_pInfoLabel->SetText(failureReason);
  273. }
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Purpose: explain to the user they can't join secure servers due to a VAC ban
  277. //-----------------------------------------------------------------------------
  278. void CLoadingDialog::DisplayVACBannedError()
  279. {
  280. if ( m_bConsoleStyle )
  281. {
  282. return;
  283. }
  284. SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorVACBanned.res");
  285. SetTitle("#VAC_ConnectionRefusedTitle", true);
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: explain to the user they can't connect to public servers due to
  289. // not having a valid connection to Steam
  290. // this should only happen if they are a pirate
  291. //-----------------------------------------------------------------------------
  292. void CLoadingDialog::DisplayNoSteamConnectionError()
  293. {
  294. if ( m_bConsoleStyle )
  295. {
  296. return;
  297. }
  298. SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorNoSteamConnection.res");
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: explain to the user they got kicked from a server due to that same account
  302. // logging in from another location. This also triggers the refresh login dialog on OK
  303. // being pressed.
  304. //-----------------------------------------------------------------------------
  305. void CLoadingDialog::DisplayLoggedInElsewhereError()
  306. {
  307. if ( m_bConsoleStyle )
  308. {
  309. return;
  310. }
  311. SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorLoggedInElsewhere.res");
  312. m_pCancelButton->SetText("#GameUI_RefreshLogin_Login");
  313. m_pCancelButton->SetCommand("Login");
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose: sets status info text
  317. //-----------------------------------------------------------------------------
  318. void CLoadingDialog::SetStatusText(const char *statusText)
  319. {
  320. if ( m_bConsoleStyle )
  321. {
  322. return;
  323. }
  324. m_pInfoLabel->SetText(statusText);
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose: returns the previous state
  328. //-----------------------------------------------------------------------------
  329. bool CLoadingDialog::SetShowProgressText( bool show )
  330. {
  331. if ( m_bConsoleStyle )
  332. {
  333. return false;
  334. }
  335. bool bret = m_pInfoLabel->IsVisible();
  336. if ( bret != show )
  337. {
  338. SetupControlSettings( show );
  339. m_pInfoLabel->SetVisible( show );
  340. }
  341. return bret;
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose: updates time remaining
  345. //-----------------------------------------------------------------------------
  346. void CLoadingDialog::OnThink()
  347. {
  348. BaseClass::OnThink();
  349. if ( !m_bConsoleStyle && m_bShowingSecondaryProgress )
  350. {
  351. // calculate the time remaining string
  352. wchar_t unicode[512];
  353. if (m_flSecondaryProgress >= 1.0f)
  354. {
  355. m_pTimeRemainingLabel->SetText("complete");
  356. }
  357. else if (ProgressBar::ConstructTimeRemainingString(unicode, sizeof(unicode), m_flSecondaryProgressStartTime, (float)system()->GetFrameTime(), m_flSecondaryProgress, m_flLastSecondaryProgressUpdateTime, true))
  358. {
  359. m_pTimeRemainingLabel->SetText(unicode);
  360. }
  361. else
  362. {
  363. m_pTimeRemainingLabel->SetText("");
  364. }
  365. }
  366. SetAlpha( 255 );
  367. }
  368. //-----------------------------------------------------------------------------
  369. // Purpose:
  370. //-----------------------------------------------------------------------------
  371. void CLoadingDialog::PerformLayout()
  372. {
  373. if ( m_bConsoleStyle )
  374. {
  375. // place in lower center
  376. int screenWide, screenTall;
  377. surface()->GetScreenSize( screenWide, screenTall );
  378. int wide,tall;
  379. GetSize( wide, tall );
  380. int x = 0;
  381. int y = 0;
  382. if ( ModInfo().IsSinglePlayerOnly() )
  383. {
  384. x = ( screenWide - wide ) * 0.50f;
  385. y = ( screenTall - tall ) * 0.86f;
  386. }
  387. else
  388. {
  389. x = ( screenWide - ( wide * 1.30f ) );
  390. y = ( ( screenTall * 0.875f ) );
  391. }
  392. SetPos( x, y );
  393. }
  394. else if ( m_bCenter )
  395. {
  396. MoveToCenterOfScreen();
  397. }
  398. else
  399. {
  400. // if we're not supposed to be centered, move ourselves to the lower right hand corner of the screen
  401. int x, y, screenWide, screenTall;
  402. surface()->GetWorkspaceBounds( x, y, screenWide, screenTall );
  403. int wide,tall;
  404. GetSize( wide, tall );
  405. if ( IsPC() )
  406. {
  407. x = screenWide - ( wide + 10 );
  408. y = screenTall - ( tall + 10 );
  409. }
  410. else
  411. {
  412. // Move farther in so we're title safe
  413. x = screenWide - wide - (screenWide * 0.05);
  414. y = screenTall - tall - (screenTall * 0.05);
  415. }
  416. x -= m_iAdditionalIndentX;
  417. y -= m_iAdditionalIndentY;
  418. SetPos( x, y );
  419. }
  420. BaseClass::PerformLayout();
  421. vgui::ipanel()->MoveToFront( GetVPanel() );
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Purpose: returns true if the number of ticks has changed
  425. //-----------------------------------------------------------------------------
  426. bool CLoadingDialog::SetProgressPoint( float fraction )
  427. {
  428. if ( m_bConsoleStyle )
  429. {
  430. if ( fraction >= 0.99f )
  431. {
  432. // show the progress artifically completed to fill in 100%
  433. fraction = 1.0f;
  434. }
  435. fraction = clamp( fraction, 0.0f, 1.0f );
  436. if ( (int)(fraction * 25) != (int)(m_flProgressFraction * 25) )
  437. {
  438. m_flProgressFraction = fraction;
  439. return true;
  440. }
  441. return IsGameConsole();
  442. }
  443. if ( !m_bShowingVACInfo && gameuifuncs->IsConnectedToVACSecureServer() )
  444. {
  445. SetupControlSettings( false );
  446. }
  447. int nOldDrawnSegments = m_pProgress->GetDrawnSegmentCount();
  448. m_pProgress->SetProgress( fraction );
  449. int nNewDrawSegments = m_pProgress->GetDrawnSegmentCount();
  450. return (nOldDrawnSegments != nNewDrawSegments) || IsGameConsole();
  451. }
  452. //-----------------------------------------------------------------------------
  453. // Purpose: sets and shows the secondary progress bar
  454. //-----------------------------------------------------------------------------
  455. void CLoadingDialog::SetSecondaryProgress( float progress )
  456. {
  457. if ( m_bConsoleStyle )
  458. return;
  459. // don't show the progress if we've jumped right to completion
  460. if (!m_bShowingSecondaryProgress && progress > 0.99f)
  461. return;
  462. // if we haven't yet shown secondary progress then reconfigure the dialog
  463. if (!m_bShowingSecondaryProgress)
  464. {
  465. LoadControlSettings("Resource/LoadingDialogDualProgress.res");
  466. m_bShowingSecondaryProgress = true;
  467. m_pProgress2->SetVisible(true);
  468. m_flSecondaryProgressStartTime = (float)system()->GetFrameTime();
  469. }
  470. // if progress has increased then update the progress counters
  471. if (progress > m_flSecondaryProgress)
  472. {
  473. m_pProgress2->SetProgress(progress);
  474. m_flSecondaryProgress = progress;
  475. m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime();
  476. }
  477. // if progress has decreased then reset progress counters
  478. if (progress < m_flSecondaryProgress)
  479. {
  480. m_pProgress2->SetProgress(progress);
  481. m_flSecondaryProgress = progress;
  482. m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime();
  483. m_flSecondaryProgressStartTime = (float)system()->GetFrameTime();
  484. }
  485. }
  486. //-----------------------------------------------------------------------------
  487. // Purpose:
  488. //-----------------------------------------------------------------------------
  489. void CLoadingDialog::SetSecondaryProgressText(const char *statusText)
  490. {
  491. if ( m_bConsoleStyle )
  492. {
  493. return;
  494. }
  495. SetControlString( "SecondaryProgressLabel", statusText );
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose:
  499. //-----------------------------------------------------------------------------
  500. void CLoadingDialog::OnClose()
  501. {
  502. // remove any rendering restrictions
  503. HideOtherDialogs( false );
  504. BaseClass::OnClose();
  505. }
  506. //-----------------------------------------------------------------------------
  507. // Purpose: command handler
  508. //-----------------------------------------------------------------------------
  509. void CLoadingDialog::OnCommand(const char *command)
  510. {
  511. if ( !stricmp(command, "Cancel") )
  512. {
  513. // disconnect from the server
  514. engine->ClientCmd_Unrestricted("disconnect\n");
  515. // close
  516. Close();
  517. }
  518. else
  519. {
  520. BaseClass::OnCommand(command);
  521. }
  522. }
  523. //-----------------------------------------------------------------------------
  524. // Purpose: Maps ESC to quiting loading
  525. //-----------------------------------------------------------------------------
  526. void CLoadingDialog::OnKeyCodePressed(KeyCode code)
  527. {
  528. if ( m_bConsoleStyle )
  529. {
  530. return;
  531. }
  532. if ( code == KEY_ESCAPE )
  533. {
  534. OnCommand("Cancel");
  535. }
  536. else
  537. {
  538. BaseClass::OnKeyCodePressed(code);
  539. }
  540. }
  541. //-----------------------------------------------------------------------------
  542. // Purpose: Singleton accessor
  543. //-----------------------------------------------------------------------------
  544. extern vgui::DHANDLE<CLoadingDialog> g_hLoadingDialog;
  545. CLoadingDialog *LoadingDialog()
  546. {
  547. return g_hLoadingDialog.Get();
  548. }