DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

MenuScreen_Shell_Save.cpp (16795B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 #pragma hdrstop
     29 #include "../../idLib/precompiled.h"
     30 #include "../Game_local.h"
     31 
     32 
     33 const static int NUM_SAVE_OPTIONS = 10;
     34 
     35 /*
     36 ========================
     37 idMenuScreen_Shell_Save::Initialize
     38 ========================
     39 */
     40 void idMenuScreen_Shell_Save::Initialize( idMenuHandler * data ) {
     41 	idMenuScreen::Initialize( data );
     42 
     43 	if ( data != NULL ) {
     44 		menuGUI = data->GetGUI();
     45 	}
     46 
     47 	SetSpritePath( "menuSave" );
     48 
     49 	saveInfo = new (TAG_SWF) idMenuWidget_Shell_SaveInfo();
     50 	saveInfo->SetSpritePath( GetSpritePath(), "info", "details" );
     51 	saveInfo->Initialize( data );
     52 	saveInfo->SetForSaveScreen( true );
     53 
     54 	options = new (TAG_SWF) idMenuWidget_DynamicList();
     55 	options->SetNumVisibleOptions( NUM_SAVE_OPTIONS );
     56 	options->SetSpritePath( GetSpritePath(), "info", "options" );
     57 	options->SetWrappingAllowed( true );
     58 	while ( options->GetChildren().Num() < NUM_SAVE_OPTIONS ) {
     59 		idMenuWidget_Button * const buttonWidget = new (TAG_SWF) idMenuWidget_Button();
     60 		buttonWidget->AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_PRESS_FOCUSED, options->GetChildren().Num() );
     61 		buttonWidget->RegisterEventObserver( saveInfo );
     62 		buttonWidget->Initialize( data );
     63 		options->AddChild( buttonWidget );
     64 	}
     65 	options->Initialize( data );
     66 
     67 	AddChild( options );
     68 	AddChild( saveInfo );
     69 
     70 	btnBack = new (TAG_SWF) idMenuWidget_Button();
     71 	btnBack->Initialize( data );
     72 	btnBack->SetLabel( "#str_swf_pause_menu" );
     73 	btnBack->SetSpritePath( GetSpritePath(), "info", "btnBack" );
     74 	btnBack->AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_GO_BACK );
     75 
     76 	AddChild( btnBack );
     77 
     78 	btnDelete = new idMenuWidget_Button();
     79 	btnDelete->Initialize( data );
     80 	btnDelete->SetLabel( "" );
     81 	btnDelete->AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_JOY3_ON_PRESS );
     82 	btnDelete->SetSpritePath( GetSpritePath(), "info", "btnDelete" );
     83 
     84 	AddChild( btnDelete );
     85 
     86 	options->AddEventAction( WIDGET_EVENT_SCROLL_DOWN ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER, WIDGET_EVENT_SCROLL_DOWN ) );
     87 	options->AddEventAction( WIDGET_EVENT_SCROLL_UP ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER, WIDGET_EVENT_SCROLL_UP ) );
     88 	options->AddEventAction( WIDGET_EVENT_SCROLL_DOWN_RELEASE ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_STOP_REPEATER, WIDGET_EVENT_SCROLL_DOWN_RELEASE ) );
     89 	options->AddEventAction( WIDGET_EVENT_SCROLL_UP_RELEASE ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_STOP_REPEATER, WIDGET_EVENT_SCROLL_UP_RELEASE ) );
     90 	options->AddEventAction( WIDGET_EVENT_SCROLL_DOWN_LSTICK ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER, WIDGET_EVENT_SCROLL_DOWN_LSTICK ) );
     91 	options->AddEventAction( WIDGET_EVENT_SCROLL_UP_LSTICK ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER, WIDGET_EVENT_SCROLL_UP_LSTICK ) );
     92 	options->AddEventAction( WIDGET_EVENT_SCROLL_DOWN_LSTICK_RELEASE ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_STOP_REPEATER, WIDGET_EVENT_SCROLL_DOWN_LSTICK_RELEASE ) );
     93 	options->AddEventAction( WIDGET_EVENT_SCROLL_UP_LSTICK_RELEASE ).Set( new (TAG_SWF) idWidgetActionHandler( options, WIDGET_ACTION_EVENT_STOP_REPEATER, WIDGET_EVENT_SCROLL_UP_LSTICK_RELEASE ) );
     94 }
     95 
     96 /*
     97 ========================
     98 idMenuScreen_Shell_Save::Update
     99 ========================
    100 */
    101 void idMenuScreen_Shell_Save::Update() {
    102 
    103 	UpdateSaveEnumerations();
    104 
    105 	idSWFScriptObject & root = GetSWFObject()->GetRootObject();
    106 	if ( BindSprite( root ) ) {
    107 		idSWFTextInstance * heading = GetSprite()->GetScriptObject()->GetNestedText( "info", "txtHeading" );
    108 		if ( heading != NULL ) {
    109 			heading->SetText( "#str_02179" );	// SAVE GAME
    110 			heading->SetStrokeInfo( true, 0.75f, 1.75f );
    111 		}
    112 
    113 		idSWFSpriteInstance * gradient = GetSprite()->GetScriptObject()->GetNestedSprite( "info", "gradient" );
    114 		if ( gradient != NULL && heading != NULL ) {
    115 			gradient->SetXPos( heading->GetTextLength() );
    116 		}
    117 	}
    118 
    119 	if ( btnBack != NULL ) {
    120 		btnBack->BindSprite( root );
    121 	}
    122 
    123 	idMenuScreen::Update();
    124 }
    125 
    126 /*
    127 ========================
    128 idMenuScreen_Shell_Save::UpdateSaveEnumerations
    129 ========================
    130 */
    131 void idMenuScreen_Shell_Save::UpdateSaveEnumerations() {
    132 
    133 	const saveGameDetailsList_t & saveGameInfo = session->GetSaveGameManager().GetEnumeratedSavegames();
    134 	sortedSaves = saveGameInfo;
    135 	idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU > saveList;
    136 	int newSaveOffset = 1;
    137 	bool hasAutosave = false;
    138 
    139 	if ( session->GetSaveGameManager().IsWorking() ) {
    140 		idList< idStr > saveName;
    141 		saveName.Append( "#str_dlg_refreshing" );
    142 		saveList.Append( saveName );
    143 
    144 		if ( options != NULL ) {	
    145 			options->SetListData( saveList );
    146 			options->Update();
    147 		}
    148 	} else {
    149 
    150 		for ( int i = 0; i < saveGameInfo.Num(); ++i ) {
    151 			if ( saveGameInfo[i].slotName.Icmp( "autosave" ) == 0 ) {
    152 				hasAutosave = true;
    153 				break;
    154 			}
    155 		}
    156 
    157 		if ( saveGameInfo.Num() == MAX_SAVEGAMES || ( !hasAutosave && saveGameInfo.Num() == MAX_SAVEGAMES - 1 ) ) {
    158 			newSaveOffset = 0;
    159 		}
    160 		
    161 		if ( newSaveOffset != 0 ) {
    162 			idList< idStr > newSave;
    163 			newSave.Append( "#str_swf_new_save_game" );
    164 			saveList.Append( newSave );
    165 		}
    166 
    167 		if ( options != NULL ) {			
    168 			sortedSaves.Sort( idSort_SavesByDate() );
    169 
    170 			for ( int slot = 0; slot < sortedSaves.Num(); ++slot ) {
    171 				const idSaveGameDetails & details = sortedSaves[slot];	
    172 				if ( details.slotName.Icmp( "autosave" ) == 0 ) {
    173 					sortedSaves.RemoveIndex( slot );
    174 					slot--;
    175 				}
    176 			}
    177 			// +1 because the first item is "New Save"
    178 			saveList.SetNum( sortedSaves.Num() + newSaveOffset );
    179 			for ( int slot = 0; slot < sortedSaves.Num(); ++slot ) {
    180 				idStr & slotSaveName = saveList[ slot + newSaveOffset ].Alloc();
    181 				const idSaveGameDetails & details = sortedSaves[slot];
    182 				if ( details.damaged ) {
    183 					slotSaveName =  va( S_COLOR_RED "%s", idLocalization::GetString( "#str_swf_corrupt_file" ) );
    184 				} else if ( details.GetSaveVersion() > BUILD_NUMBER ) {
    185 					slotSaveName =  va( S_COLOR_RED "%s", idLocalization::GetString( "#str_swf_wrong_version" ) );
    186 				} else {
    187 					if ( details.slotName.Icmp( "autosave" ) == 0 ) {
    188 						slotSaveName.Append( S_COLOR_YELLOW );
    189 					} else if ( details.slotName.Icmp( "quick" ) == 0 ) {
    190 						slotSaveName.Append( S_COLOR_ORANGE );
    191 					}
    192 					slotSaveName.Append( details.GetMapName() );
    193 				}
    194 			}
    195 
    196 			options->SetListData( saveList );
    197 			options->Update();
    198 		}
    199 	}
    200 
    201 	if ( menuData != NULL ) {
    202 		idMenuWidget_CommandBar * cmdBar = menuData->GetCmdBar();
    203 		if ( cmdBar != NULL ) {
    204 			cmdBar->ClearAllButtons();
    205 			idMenuWidget_CommandBar::buttonInfo_t * buttonInfo;
    206 			buttonInfo = cmdBar->GetButton( idMenuWidget_CommandBar::BUTTON_JOY2 );
    207 			if ( menuData->GetPlatform() != 2 ) {
    208 				buttonInfo->label = "#str_00395";	// BACK
    209 			}
    210 			buttonInfo->action.Set( WIDGET_ACTION_GO_BACK );
    211 
    212 
    213 			if ( !session->GetSaveGameManager().IsWorking() ) {
    214 				buttonInfo = cmdBar->GetButton( idMenuWidget_CommandBar::BUTTON_JOY1 );
    215 				if ( menuData->GetPlatform() != 2 ) {
    216 					buttonInfo->label = "#str_02179";	// SAVE GAME
    217 				}
    218 				buttonInfo->action.Set( WIDGET_ACTION_PRESS_FOCUSED );
    219 			
    220 				if ( options != NULL ) {
    221 					if ( options->GetViewIndex() != 0 || ( options->GetViewIndex() == 0 && newSaveOffset == 0 ) )  {
    222 						buttonInfo = cmdBar->GetButton( idMenuWidget_CommandBar::BUTTON_JOY3 );
    223 						if ( menuData->GetPlatform() != 2 ) {
    224 							buttonInfo->label = "#str_02315";	// DELETE
    225 						}
    226 						buttonInfo->action.Set( WIDGET_ACTION_JOY3_ON_PRESS );
    227 
    228 						if ( btnDelete != NULL ) {
    229 							idSWFScriptObject & root = GetSWFObject()->GetRootObject();
    230 							if ( btnDelete->BindSprite( root ) ) {
    231 								if ( menuData->GetPlatform() != 2 ) {
    232 									btnDelete->SetLabel( "" );
    233 								} else {
    234 									btnDelete->GetSprite()->SetVisible( true );
    235 									btnDelete->SetLabel( "#str_02315" );
    236 								}
    237 							}
    238 							btnDelete->Update();
    239 						}
    240 					} else {
    241 						if ( btnDelete != NULL ) {
    242 							idSWFScriptObject & root = GetSWFObject()->GetRootObject();
    243 							if ( btnDelete->BindSprite( root ) ) {
    244 								btnDelete->SetLabel( "" );
    245 								btnDelete->Update();
    246 							}
    247 						}
    248 					}
    249 				}
    250 			}
    251 			cmdBar->Update();
    252 		}		
    253 	}
    254 
    255 	if ( saveInfo != NULL ) {
    256 		saveInfo->Update();
    257 	}
    258 
    259 	if ( options != NULL && options->GetTotalNumberOfOptions() > 0 && options->GetViewIndex() >= options->GetTotalNumberOfOptions() ) {
    260 		options->SetViewIndex( options->GetTotalNumberOfOptions() - newSaveOffset );
    261 		if ( options->GetViewOffset() > options->GetViewIndex() ) {
    262 			options->SetViewOffset( options->GetViewIndex() );
    263 		}
    264 		options->SetFocusIndex( options->GetViewIndex() - options->GetViewOffset() );
    265 	}
    266 }
    267 
    268 /*
    269 ========================
    270 idMenuScreen_Shell_Save::ShowScreen
    271 ========================
    272 */
    273 void idMenuScreen_Shell_Save::ShowScreen( const mainMenuTransition_t transitionType ) {
    274 	idMenuScreen::ShowScreen( transitionType );
    275 }
    276 
    277 /*
    278 ========================
    279 idMenuScreen_Shell_Save::HideScreen
    280 ========================
    281 */
    282 void idMenuScreen_Shell_Save::HideScreen( const mainMenuTransition_t transitionType ) {
    283 	idMenuScreen::HideScreen( transitionType );
    284 }
    285 
    286 /*
    287 ========================
    288 idMenuScreen_Shell_Save::SaveGame
    289 ========================
    290 */
    291 void idMenuScreen_Shell_Save::SaveGame( int index ) {
    292 	const saveGameDetailsList_t & saveGameInfo = session->GetSaveGameManager().GetEnumeratedSavegames();
    293 	int newSaveOffset = 1;
    294 
    295 	bool hasAutosave = false;
    296 	for ( int i = 0; i < saveGameInfo.Num(); ++i ) {
    297 		if ( saveGameInfo[i].slotName.Icmp( "autosave" ) == 0 ) {
    298 			hasAutosave = true;
    299 			break;
    300 		}
    301 	}
    302 
    303 	if ( saveGameInfo.Num() == MAX_SAVEGAMES || ( ( saveGameInfo.Num() == MAX_SAVEGAMES - 1 ) && !hasAutosave ) ) {
    304 		newSaveOffset = 0;
    305 	}
    306 
    307 	if ( index == 0 && newSaveOffset == 1 ) {
    308 		// New save...
    309 
    310 		// Scan all the savegames for the first doom3_xxx slot.
    311 		const idStr savePrefix = "doom3_";
    312 		uint64 slotMask = 0;
    313 		for ( int slot = 0; slot < saveGameInfo.Num(); ++slot ) {
    314 			const idSaveGameDetails & details = saveGameInfo[slot];
    315 
    316 			if ( details.slotName.Icmp( "autosave" ) == 0 ) {
    317 				continue;
    318 			}
    319 
    320 			idStr name = details.slotName;
    321 
    322 			name.ToLower();		// PS3 saves are uppercase ... we need to lower case-ify them for comparison here
    323 			name.StripLeading( savePrefix.c_str() );
    324 			if ( name.IsNumeric() ) {
    325 				int slotNumber = atoi( name.c_str() );
    326 				slotMask |= ( 1ULL << slotNumber );
    327 			}
    328 		}
    329 
    330 		int slotNumber = 0;
    331 		for ( slotNumber = 0; slotNumber < ( sizeof( slotMask ) * 8 ); slotNumber++ ) {
    332 			// If the slot isn't used, grab it
    333 			if ( !( slotMask & ( 1ULL << slotNumber ) ) ) {
    334 				break;
    335 			}
    336 		}
    337 
    338 		assert( slotNumber < ( sizeof( slotMask ) * 8 ) );
    339 		idStr name = va( "%s%d", savePrefix.c_str(), slotNumber );
    340 		cmdSystem->AppendCommandText( va( "savegame %s\n", name.c_str() ) );
    341 
    342 		// Throw up the saving message...
    343 		common->Dialog().ShowSaveIndicator( true );
    344 	} else {
    345 
    346 		class idSWFScriptFunction_OverwriteSave : public idSWFScriptFunction_RefCounted {
    347 		public:
    348 			idSWFScriptFunction_OverwriteSave( gameDialogMessages_t _msg, bool _accept, int _index, idMenuScreen_Shell_Save * _screen ) {
    349 				msg = _msg;
    350 				accept = _accept;
    351 				index = _index;
    352 				screen = _screen;
    353 			}
    354 			idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
    355 				common->Dialog().ClearDialog( msg );
    356 				if ( accept && screen != NULL ) {
    357 					// Replace the save
    358 					if ( index < screen->GetSortedSaves().Num() ) {
    359 						idStr name = screen->GetSortedSaves()[ index ].slotName;
    360 						cmdSystem->AppendCommandText( va( "savegame %s\n", name.c_str() ) );
    361 
    362 						// Throw up the saving message...
    363 						common->Dialog().ShowSaveIndicator( true );
    364 					}
    365 				}
    366 				return idSWFScriptVar();
    367 			}
    368 		private:
    369 			gameDialogMessages_t msg;
    370 			int index;
    371 			bool accept;
    372 			idMenuScreen_Shell_Save * screen;
    373 		};
    374 
    375 		if ( newSaveOffset == 1 ) {
    376 			index--;
    377 		}
    378 
    379 		common->Dialog().AddDialog( GDM_OVERWRITE_SAVE, DIALOG_ACCEPT_CANCEL, new idSWFScriptFunction_OverwriteSave( GDM_OVERWRITE_SAVE, true, index, this ), new idSWFScriptFunction_OverwriteSave( GDM_OVERWRITE_SAVE, false, index, this ), false );
    380 	}
    381 	
    382 }
    383 
    384 /*
    385 ========================
    386 idMenuScreen_Shell_Save::DeleteGame
    387 ========================
    388 */
    389 void idMenuScreen_Shell_Save::DeleteGame( int index ) {
    390 	
    391 	class idSWFScriptFunction_DeleteGame : public idSWFScriptFunction_RefCounted {
    392 	public:
    393 		idSWFScriptFunction_DeleteGame( gameDialogMessages_t _msg, bool _accept, int _index, idMenuScreen_Shell_Save * _screen ) {
    394 			msg = _msg;
    395 			accept = _accept;
    396 			index = _index;
    397 			screen = _screen;
    398 		}
    399 		idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
    400 			common->Dialog().ClearDialog( msg );
    401 			if ( accept && screen != NULL ) {
    402 				if ( index < screen->GetSortedSaves().Num() ) {
    403 					session->DeleteSaveGameSync( screen->GetSortedSaves()[ index ].slotName );
    404 				}
    405 			}
    406 			return idSWFScriptVar();
    407 		}
    408 	private:
    409 		gameDialogMessages_t msg;
    410 		int index;
    411 		bool accept;
    412 		idMenuScreen_Shell_Save * screen;
    413 	};
    414 
    415 	bool hasAutosave = false;
    416 	const saveGameDetailsList_t & saveInfo = session->GetSaveGameManager().GetEnumeratedSavegames();
    417 	for ( int i = 0; i < saveInfo.Num(); ++i ) {
    418 		if ( saveInfo[i].slotName.Icmp( "autosave" ) == 0 ) {
    419 			hasAutosave = true;
    420 			break;
    421 		}
    422 	}
    423 
    424 	if ( ( saveInfo.Num() < MAX_SAVEGAMES - 1 ) || ( ( saveInfo.Num() == MAX_SAVEGAMES - 1 ) && hasAutosave ) )  {
    425 		index--;	// Subtract 1 from the index for 'New Game'
    426 	}
    427 
    428 	common->Dialog().AddDialog( GDM_DELETE_SAVE, DIALOG_ACCEPT_CANCEL, new idSWFScriptFunction_DeleteGame( GDM_DELETE_SAVE, true, index, this ), new idSWFScriptFunction_DeleteGame( GDM_DELETE_SAVE, false, index, this ), false );
    429 
    430 }
    431 
    432 /*
    433 ========================
    434 idMenuScreen_Shell_Save::HandleAction
    435 ========================
    436 */
    437 bool idMenuScreen_Shell_Save::HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled ) {
    438 
    439 	if ( menuData == NULL ) {
    440 		return true;
    441 	}
    442 		
    443 	if ( menuData->ActiveScreen() != SHELL_AREA_SAVE ) {
    444 		return false;
    445 	}
    446 
    447 	widgetAction_t actionType = action.GetType();
    448 	const idSWFParmList & parms = action.GetParms();
    449 
    450 	switch ( actionType ) {
    451 		case WIDGET_ACTION_JOY4_ON_PRESS: {
    452 			return true;
    453 		}
    454 		case WIDGET_ACTION_JOY3_ON_PRESS: {
    455 
    456 			if ( options == NULL ) {
    457 				return true;
    458 			}
    459 
    460 			DeleteGame( options->GetViewIndex() );
    461 			return true;
    462 		}
    463 		case WIDGET_ACTION_GO_BACK: {
    464 			menuData->SetNextScreen( SHELL_AREA_ROOT, MENU_TRANSITION_SIMPLE );
    465 			return true;
    466 		}
    467 		case WIDGET_ACTION_PRESS_FOCUSED: {
    468 			if ( options == NULL ) {
    469 				return true;
    470 			}
    471 		
    472 			if ( session->GetSaveGameManager().IsWorking() ) {
    473 				return true;
    474 			}
    475 
    476 			if ( parms.Num() == 1 ) {
    477 				int selectionIndex = parms[0].ToInteger();
    478 				if ( selectionIndex != options->GetFocusIndex() ) {
    479 					options->SetViewIndex( options->GetViewOffset() + selectionIndex );
    480 					options->SetFocusIndex( selectionIndex );
    481 					return true;
    482 				}
    483 			}
    484 
    485 			SaveGame( options->GetViewIndex() );
    486 			return true;
    487 		}
    488 		case WIDGET_ACTION_SCROLL_VERTICAL: {
    489 			return true;
    490 		}
    491 	}
    492 
    493 	return idMenuWidget::HandleAction( action, event, widget, forceHandled );
    494 }