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.

301 lines
9.0 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "basepanel.h"
  7. #include "savegamedialog.h"
  8. #include "winlite.h" // FILETIME
  9. #include "vgui/ILocalize.h"
  10. #include "vgui/ISurface.h"
  11. #include "vgui/ISystem.h"
  12. #include "vgui/IVGui.h"
  13. #include "vgui_controls/AnimationController.h"
  14. #include "vgui_controls/ImagePanel.h"
  15. #include "filesystem.h"
  16. #include "keyvalues.h"
  17. #include "modinfo.h"
  18. #include "engineinterface.h"
  19. #include "gameui_interface.h"
  20. #include "vstdlib/random.h"
  21. #include "basesavegamedialog.h"
  22. #include "savegamebrowserdialog.h"
  23. using namespace vgui;
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. #include "vgui_controls/Frame.h"
  27. #include "utlvector.h"
  28. extern const char *COM_GetModDirectory();
  29. using namespace vgui;
  30. CSaveGameDialogXbox::CSaveGameDialogXbox( vgui::Panel *parent )
  31. : BaseClass( parent ),
  32. m_bGameSaving ( false ),
  33. m_bNewSaveAvailable( false )
  34. {
  35. m_bFilterAutosaves = true;
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Purpose:
  39. //-----------------------------------------------------------------------------
  40. void CSaveGameDialogXbox::PerformSelectedAction( void )
  41. {
  42. BaseClass::PerformSelectedAction();
  43. // If there are no panels, don't allow this
  44. if ( GetNumPanels() == 0 )
  45. return;
  46. SetControlDisabled( true );
  47. // Decide if this is an overwrite or a new save game
  48. bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable;
  49. if ( bNewSave )
  50. {
  51. OnCommand( "SaveGame" );
  52. }
  53. else
  54. {
  55. BasePanel()->ShowMessageDialog( MD_SAVE_OVERWRITE, this );
  56. }
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. // Input : bNewSaveSelected -
  61. //-----------------------------------------------------------------------------
  62. void CSaveGameDialogXbox::UpdateFooterOptions( void )
  63. {
  64. CFooterPanel *pFooter = GetFooterPanel();
  65. // Show available buttons
  66. pFooter->ClearButtons();
  67. bool bSavePanelsActive = ( GetNumPanels() != 0 );
  68. if ( bSavePanelsActive )
  69. {
  70. bool bNewSaveSelected = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable;
  71. if ( bNewSaveSelected )
  72. {
  73. pFooter->AddNewButtonLabel( "#GameUI_SaveGame_NewSave", "#GameUI_Icons_A_BUTTON" );
  74. }
  75. else
  76. {
  77. pFooter->AddNewButtonLabel( "#GameUI_SaveGame_Overwrite", "#GameUI_Icons_A_BUTTON" );
  78. }
  79. }
  80. // Always available
  81. pFooter->AddNewButtonLabel( "#GameUI_Close", "#GameUI_Icons_B_BUTTON" );
  82. pFooter->AddNewButtonLabel( "#GameUI_Console_StorageChange", "#GameUI_Icons_Y_BUTTON" );
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose: perfrom the save on a separate thread
  86. //-----------------------------------------------------------------------------
  87. class CAsyncCtxSaveGame : public CBaseModPanel::CAsyncJobContext
  88. {
  89. public:
  90. explicit CAsyncCtxSaveGame( CSaveGameDialogXbox *pDlg );
  91. ~CAsyncCtxSaveGame() {}
  92. public:
  93. virtual void ExecuteAsync();
  94. virtual void Completed();
  95. public:
  96. char m_szFilename[MAX_PATH];
  97. CSaveGameDialogXbox *m_pSaveGameDlg;
  98. };
  99. CAsyncCtxSaveGame::CAsyncCtxSaveGame( CSaveGameDialogXbox *pDlg ) :
  100. CBaseModPanel::CAsyncJobContext( 3.0f ), // Storage device info for at least 3 seconds
  101. m_pSaveGameDlg( pDlg )
  102. {
  103. NULL;
  104. }
  105. void CAsyncCtxSaveGame::ExecuteAsync()
  106. {
  107. // Sit and wait for the async save to finish
  108. for ( ; ; )
  109. {
  110. if ( !engine->IsSaveInProgress() )
  111. // Save operation is no longer in progress
  112. break;
  113. else
  114. ThreadSleep( 50 );
  115. }
  116. }
  117. void CAsyncCtxSaveGame::Completed()
  118. {
  119. m_pSaveGameDlg->SaveCompleted( this );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose: kicks off the async save (called on the main thread)
  123. //-----------------------------------------------------------------------------
  124. void CSaveGameDialogXbox::InitiateSaving()
  125. {
  126. // Determine whether this is a new save or overwrite
  127. bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable;
  128. // Allocate the async context for saving
  129. CAsyncCtxSaveGame *pAsyncCtx = new CAsyncCtxSaveGame( this );
  130. // If this is an overwrite then there was an overwrite warning displayed
  131. if ( !bNewSave )
  132. BasePanel()->CloseMessageDialog( DIALOG_STACK_IDX_WARNING );
  133. // Now display the saving warning
  134. BasePanel()->ShowMessageDialog( MD_SAVING_WARNING, this );
  135. // Kick off saving
  136. char *szFilename = pAsyncCtx->m_szFilename;
  137. const int maxFilenameLen = sizeof( pAsyncCtx->m_szFilename );
  138. char szCmd[MAX_PATH];
  139. // See if this is the "new save game" slot
  140. if ( bNewSave )
  141. {
  142. // dgoodenough - Stub out generation of a unique file name for now
  143. // PS3_BUILDFIX
  144. // FIXME - this will need a workover
  145. // @wge Same for OSX
  146. #if defined ( _PS3 ) || defined( _OSX ) || defined (LINUX)
  147. unsigned currentTime = 0;
  148. #else
  149. // Create a new save game (name is created from the current time, which should be pretty unique)
  150. FILETIME currentFileTime;
  151. GetSystemTimeAsFileTime( &currentFileTime );
  152. unsigned currentTime = currentFileTime.dwLowDateTime;
  153. #endif
  154. Q_snprintf( szFilename, maxFilenameLen, "%s_%u", COM_GetModDirectory(), currentTime );
  155. Q_snprintf( szCmd, sizeof( szCmd ), "xsave %s", szFilename );
  156. engine->ExecuteClientCmd( szCmd );
  157. Q_strncat( szFilename, ".360.sav", maxFilenameLen );
  158. }
  159. else
  160. {
  161. const SaveGameDescription_t *pDesc = GetActivePanelSaveDescription();
  162. Q_strncpy( szFilename, pDesc->szShortName, maxFilenameLen );
  163. Q_snprintf( szCmd, sizeof( szCmd ), "xsave %s", szFilename );
  164. engine->ExecuteClientCmd( szCmd );
  165. }
  166. // Enqueue waiting
  167. BasePanel()->ExecuteAsync( pAsyncCtx );
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose: handles the end of async save (called on the main thread)
  171. //-----------------------------------------------------------------------------
  172. void CSaveGameDialogXbox::SaveCompleted( CAsyncCtxSaveGame *pCtx )
  173. {
  174. char const *szFilename = pCtx->m_szFilename;
  175. // We should now be saved so get the new desciption back from the file
  176. char szDirectory[MAX_PATH];
  177. Q_snprintf( szDirectory, sizeof( szDirectory ), "%s:/%s", COM_GetModDirectory(), szFilename );
  178. ParseSaveData( szDirectory, szFilename, &m_NewSaveDesc );
  179. // Close the progress dialog
  180. BasePanel()->CloseMessageDialog( DIALOG_STACK_IDX_WARNING );
  181. bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable;
  182. if ( bNewSave )
  183. {
  184. AnimateInsertNewPanel( &m_NewSaveDesc );
  185. }
  186. else
  187. {
  188. AnimateOverwriteActivePanel( &m_NewSaveDesc );
  189. }
  190. m_bGameSaving = false;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: handles button commands
  194. //-----------------------------------------------------------------------------
  195. void CSaveGameDialogXbox::OnCommand( const char *command )
  196. {
  197. if ( !Q_stricmp( command, "SaveGame" ) )
  198. {
  199. if ( m_bGameSaving )
  200. return;
  201. m_bGameSaving = true;
  202. SetControlDisabled( true );
  203. // Initiate the saving operation
  204. InitiateSaving();
  205. }
  206. else if ( !Q_stricmp( command, "SaveSuccess" ) )
  207. {
  208. vgui::surface()->PlaySound( "UI/buttonclick.wav" );
  209. GameUI().SetSavedThisMenuSession( true );
  210. }
  211. else if ( !Q_stricmp( command, "CloseAndSelectResume" ) )
  212. {
  213. BasePanel()->ArmFirstMenuItem();
  214. OnCommand( "Close" );
  215. }
  216. else if ( !Q_stricmp( command, "OverwriteGameCancelled" ) )
  217. {
  218. SetControlDisabled( false );
  219. }
  220. else if ( !Q_stricmp( command, "RefreshSaveGames" ) )
  221. {
  222. RefreshSaveGames();
  223. }
  224. else if ( !Q_stricmp( command, "ReleaseModalWindow" ) )
  225. {
  226. vgui::surface()->RestrictPaintToSinglePanel( NULL );
  227. }
  228. else if ( !m_bGameSaving )
  229. {
  230. BaseClass::OnCommand(command);
  231. }
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose: On completion of scanning, prepend a utility slot on the stack
  235. //-----------------------------------------------------------------------------
  236. void CSaveGameDialogXbox::OnDoneScanningSaveGames( void )
  237. {
  238. ConVarRef save_history_count("save_history_count" );
  239. m_bNewSaveAvailable = false;
  240. // dgoodenough - limit this to _X360 for now.
  241. // PS3_BUILDFIX
  242. // FIXME - do we need something here on PS3?
  243. #ifdef _X360
  244. #pragma message( __FILE__ "(" __LINE__AS_STRING ") : warning custom: Slamming controller for xbox storage id to 0" )
  245. if ( XBX_GetStorageDeviceId( 0 ) == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId( 0 ) == XBX_STORAGE_DECLINED )
  246. return;
  247. // We only allow 10 save games minus the number of autosaves, autosavedangerous, and autosave0?'s at once
  248. if ( GetNumPanels() >= 10 - ( 2 + (unsigned)save_history_count.GetInt() ) )
  249. return;
  250. if ( GetStorageSpaceUsed() + XBX_SAVEGAME_BYTES > XBX_PERSISTENT_BYTES_NEEDED )
  251. return;
  252. m_bNewSaveAvailable = true;
  253. SaveGameDescription_t bogusDesc = { "#GameUI_SaveGame_NewSavedGame", "#GameUI_SaveGame_NewSave", "#GameUI_SaveGame_NewSave", "#GameUI_SaveGame_NewSave", "#GameUI_SaveGame_NewSave", "#GameUI_SaveGame_NewSave", "#GameUI_SaveGame_NewSave", 0, 0 };
  254. CGameSavePanel *newSavePanel = SETUP_PANEL( new CGameSavePanel( this, &bogusDesc, true ) );
  255. AddPanel( newSavePanel );
  256. #endif // _GAMECONSOLE
  257. }