diff options
Diffstat (limited to 'gameui/SaveGameDialog_Xbox.cpp')
| -rw-r--r-- | gameui/SaveGameDialog_Xbox.cpp | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/gameui/SaveGameDialog_Xbox.cpp b/gameui/SaveGameDialog_Xbox.cpp new file mode 100644 index 0000000..610c0a0 --- /dev/null +++ b/gameui/SaveGameDialog_Xbox.cpp @@ -0,0 +1,295 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BasePanel.h" +#include "SaveGameDialog.h" + +#include "winlite.h" // FILETIME +#include "vgui/ILocalize.h" +#include "vgui/ISurface.h" +#include "vgui/ISystem.h" +#include "vgui/IVGui.h" + +#include "vgui_controls/AnimationController.h" +#include "vgui_controls/ImagePanel.h" +#include "filesystem.h" +#include "KeyValues.h" +#include "ModInfo.h" +#include "EngineInterface.h" +#include "GameUI_Interface.h" +#include "vstdlib/random.h" + +#include "BaseSaveGameDialog.h" +#include "SaveGameBrowserDialog.h" + +using namespace vgui; + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#include "vgui_controls/Frame.h" +#include "utlvector.h" + +extern const char *COM_GetModDirectory(); + +using namespace vgui; + +CSaveGameDialogXbox::CSaveGameDialogXbox( vgui::Panel *parent ) +: BaseClass( parent ), + m_bGameSaving ( false ), + m_bNewSaveAvailable( false ) +{ + m_bFilterAutosaves = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::PerformSelectedAction( void ) +{ + BaseClass::PerformSelectedAction(); + + // If there are no panels, don't allow this + if ( GetNumPanels() == 0 ) + return; + + SetControlDisabled( true ); + + // Decide if this is an overwrite or a new save game + bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable; + if ( bNewSave ) + { + OnCommand( "SaveGame" ); + } + else + { + BasePanel()->ShowMessageDialog( MD_SAVE_OVERWRITE, this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bNewSaveSelected - +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::UpdateFooterOptions( void ) +{ + CFooterPanel *pFooter = GetFooterPanel(); + + // Show available buttons + pFooter->ClearButtons(); + + bool bSavePanelsActive = ( GetNumPanels() != 0 ); + if ( bSavePanelsActive ) + { + bool bNewSaveSelected = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable; + if ( bNewSaveSelected ) + { + pFooter->AddNewButtonLabel( "#GameUI_SaveGame_NewSave", "#GameUI_Icons_A_BUTTON" ); + } + else + { + pFooter->AddNewButtonLabel( "#GameUI_SaveGame_Overwrite", "#GameUI_Icons_A_BUTTON" ); + } + } + + // Always available + pFooter->AddNewButtonLabel( "#GameUI_Close", "#GameUI_Icons_B_BUTTON" ); + pFooter->AddNewButtonLabel( "#GameUI_Console_StorageChange", "#GameUI_Icons_Y_BUTTON" ); +} + +//----------------------------------------------------------------------------- +// Purpose: perfrom the save on a separate thread +//----------------------------------------------------------------------------- +class CAsyncCtxSaveGame : public CBasePanel::CAsyncJobContext +{ +public: + explicit CAsyncCtxSaveGame( CSaveGameDialogXbox *pDlg ); + ~CAsyncCtxSaveGame() {} + +public: + virtual void ExecuteAsync(); + virtual void Completed(); + +public: + char m_szFilename[MAX_PATH]; + CSaveGameDialogXbox *m_pSaveGameDlg; +}; + +CAsyncCtxSaveGame::CAsyncCtxSaveGame( CSaveGameDialogXbox *pDlg ) : + CBasePanel::CAsyncJobContext( 3.0f ), // Storage device info for at least 3 seconds + m_pSaveGameDlg( pDlg ) +{ + NULL; +} + +void CAsyncCtxSaveGame::ExecuteAsync() +{ + // Sit and wait for the async save to finish + for ( ; ; ) + { + if ( !engine->IsSaveInProgress() ) + // Save operation is no longer in progress + break; + else + ThreadSleep( 50 ); + } +} + +void CAsyncCtxSaveGame::Completed() +{ + m_pSaveGameDlg->SaveCompleted( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: kicks off the async save (called on the main thread) +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::InitiateSaving() +{ + // Determine whether this is a new save or overwrite + bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable; + + // Allocate the async context for saving + CAsyncCtxSaveGame *pAsyncCtx = new CAsyncCtxSaveGame( this ); + + // If this is an overwrite then there was an overwrite warning displayed + if ( !bNewSave ) + BasePanel()->CloseMessageDialog( DIALOG_STACK_IDX_WARNING ); + // Now display the saving warning + BasePanel()->ShowMessageDialog( MD_SAVING_WARNING, this ); + + // Kick off saving + char *szFilename = pAsyncCtx->m_szFilename; + const int maxFilenameLen = sizeof( pAsyncCtx->m_szFilename ); + char szCmd[MAX_PATH]; + + // See if this is the "new save game" slot + if ( bNewSave ) + { + // Create a new save game (name is created from the current time, which should be pretty unique) +#ifdef WIN32 + FILETIME currentTime; + GetSystemTimeAsFileTime( ¤tTime ); + Q_snprintf( szFilename, maxFilenameLen, "%s_%u", COM_GetModDirectory(), currentTime.dwLowDateTime ); +#else + time_t currentTime = time( NULL ); + Q_snprintf( szFilename, maxFilenameLen, "%s_%u", COM_GetModDirectory(), (unsigned)currentTime ); +#endif + Q_snprintf( szCmd, sizeof( szCmd ), "xsave %s", szFilename ); + engine->ExecuteClientCmd( szCmd ); + Q_strncat( szFilename, ".360.sav", maxFilenameLen ); + } + else + { + const SaveGameDescription_t *pDesc = GetActivePanelSaveDescription(); + Q_strncpy( szFilename, pDesc->szShortName, maxFilenameLen ); + Q_snprintf( szCmd, sizeof( szCmd ), "xsave %s", szFilename ); + engine->ExecuteClientCmd( szCmd ); + } + + // Enqueue waiting + BasePanel()->ExecuteAsync( pAsyncCtx ); +} + +//----------------------------------------------------------------------------- +// Purpose: handles the end of async save (called on the main thread) +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::SaveCompleted( CAsyncCtxSaveGame *pCtx ) +{ + char const *szFilename = pCtx->m_szFilename; + + // We should now be saved so get the new desciption back from the file + char szDirectory[MAX_PATH]; + Q_snprintf( szDirectory, sizeof( szDirectory ), "%s:/%s", COM_GetModDirectory(), szFilename ); + + ParseSaveData( szDirectory, szFilename, &m_NewSaveDesc ); + + // Close the progress dialog + BasePanel()->CloseMessageDialog( DIALOG_STACK_IDX_WARNING ); + + bool bNewSave = ( GetActivePanelIndex() == 0 ) && m_bNewSaveAvailable; + if ( bNewSave ) + { + AnimateInsertNewPanel( &m_NewSaveDesc ); + } + else + { + AnimateOverwriteActivePanel( &m_NewSaveDesc ); + } + + m_bGameSaving = false; +} + +//----------------------------------------------------------------------------- +// Purpose: handles button commands +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::OnCommand( const char *command ) +{ + m_KeyRepeat.Reset(); + + if ( !Q_stricmp( command, "SaveGame" ) ) + { + if ( m_bGameSaving ) + return; + m_bGameSaving = true; + + SetControlDisabled( true ); + + // Initiate the saving operation + InitiateSaving(); + } + else if ( !Q_stricmp( command, "SaveSuccess" ) ) + { + vgui::surface()->PlaySound( "UI/buttonclick.wav" ); + GameUI().SetSavedThisMenuSession( true ); + } + else if ( !Q_stricmp( command, "CloseAndSelectResume" ) ) + { + BasePanel()->ArmFirstMenuItem(); + OnCommand( "Close" ); + } + else if ( !Q_stricmp( command, "OverwriteGameCancelled" ) ) + { + SetControlDisabled( false ); + } + else if ( !Q_stricmp( command, "RefreshSaveGames" ) ) + { + RefreshSaveGames(); + } + else if ( !Q_stricmp( command, "ReleaseModalWindow" ) ) + { + vgui::surface()->RestrictPaintToSinglePanel( NULL ); + } + else if ( !m_bGameSaving ) + { + BaseClass::OnCommand(command); + } +} + +//----------------------------------------------------------------------------- +// Purpose: On completion of scanning, prepend a utility slot on the stack +//----------------------------------------------------------------------------- +void CSaveGameDialogXbox::OnDoneScanningSaveGames( void ) +{ + ConVarRef save_history_count("save_history_count" ); + + m_bNewSaveAvailable = false; +#ifdef _X360 + if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED ) + return; + + // We only allow 10 save games minus the number of autosaves, autosavedangerous, and autosave0?'s at once + if ( GetNumPanels() >= 10 - ( 2 + (unsigned)save_history_count.GetInt() ) ) + return; + + if ( GetStorageSpaceUsed() + XBX_SAVEGAME_BYTES > XBX_PERSISTENT_BYTES_NEEDED ) + return; + + m_bNewSaveAvailable = true; + 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 }; + CGameSavePanel *newSavePanel = SETUP_PANEL( new CGameSavePanel( this, &bogusDesc, true ) ); + AddPanel( newSavePanel ); +#endif // _X360 +} |