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 }