| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: QuitMenu.cpp /////////////////////////////////////////////////////////////////////////////
- // Author: Colin Day, October 2001
- // Description: Quit menu window callbacks
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/GameEngine.h"
- #include "Common/GameState.h"
- #include "Common/MessageStream.h"
- #include "Common/Player.h"
- #include "Common/PlayerList.h"
- #include "Common/RandomValue.h"
- #include "Common/Recorder.h"
- #include "GameClient/GUICallbacks.h"
- #include "GameClient/WindowLayout.h"
- #include "GameClient/GameWindowManager.h"
- #include "GameClient/Gadget.h"
- #include "GameClient/GadgetPushButton.h"
- #include "GameClient/GameText.h"
- #include "GameClient/MessageBox.h"
- #include "GameClient/Shell.h"
- #include "GameClient/InGameUI.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/VictoryConditions.h"
- #include "GameClient/ControlBar.h"
- #include "GameClient/GameWindowTransitions.h"
- #include "GameClient/DisconnectMenu.h"
- #include "GameLogic/ScriptEngine.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
- static WindowLayout *quitMenuLayout = NULL;
- static WindowLayout *fullQuitMenuLayout = NULL;
- static WindowLayout *noSaveLoadQuitMenuLayout = NULL;
- static Bool isVisible = FALSE;
- static GameWindow *quitConfirmationWindow = NULL;
- //external declarations of the Gadgets the callbacks can use
- static WindowLayout *saveLoadMenuLayout = NULL;
- static GameWindow *buttonRestartWin = NULL;
- static GameWindow *buttonSaveLoadWin = NULL;
- static GameWindow *buttonOptionsWin = NULL;
- static GameWindow *buttonExitWin = NULL;
- static NameKeyType buttonExit = NAMEKEY_INVALID;
- static NameKeyType buttonRestart = NAMEKEY_INVALID;
- static NameKeyType buttonReturn = NAMEKEY_INVALID;
- static NameKeyType buttonOptions = NAMEKEY_INVALID;
- static NameKeyType buttonSaveLoad = NAMEKEY_INVALID;
- static void initGadgetsFullQuit( void )
- {
- buttonExit = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonExit" ) );
- buttonRestart = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonRestart" ) );
- buttonReturn = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonReturn" ) );
- buttonOptions = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonOptions" ) );
- buttonSaveLoad = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonSaveLoad" ) );
-
- buttonRestartWin = TheWindowManager->winGetWindowFromId( NULL, buttonRestart );
- buttonSaveLoadWin = TheWindowManager->winGetWindowFromId( NULL, buttonSaveLoad );
- buttonOptionsWin = TheWindowManager->winGetWindowFromId( NULL, buttonOptions );
- buttonExitWin = TheWindowManager->winGetWindowFromId( NULL, buttonExit );
- }
- static void initGadgetsNoSaveQuit( void )
- {
- buttonExit = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonExit" ) );
- buttonRestart = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonRestart" ) );
- buttonReturn = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonReturn" ) );
- buttonOptions = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonOptions" ) );
- buttonSaveLoad = NAMEKEY_INVALID;
-
- buttonRestartWin = TheWindowManager->winGetWindowFromId( NULL, buttonRestart );
- buttonOptionsWin = TheWindowManager->winGetWindowFromId( NULL, buttonOptions );
- buttonSaveLoadWin = NULL;
- buttonExitWin = TheWindowManager->winGetWindowFromId( NULL, buttonExit );
- }
- // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
- void destroyQuitMenu()
- {
- // destroy the quit menu
- quitConfirmationWindow = NULL;
- if(fullQuitMenuLayout)
- {
- fullQuitMenuLayout->destroyWindows();
- fullQuitMenuLayout->deleteInstance();
- }
- fullQuitMenuLayout = NULL;
- if(noSaveLoadQuitMenuLayout)
- {
- noSaveLoadQuitMenuLayout->destroyWindows();
- noSaveLoadQuitMenuLayout->deleteInstance();
- }
- noSaveLoadQuitMenuLayout = NULL;
- quitMenuLayout = NULL;
- isVisible = FALSE;
- }
- /**
- * quits the program
- */
- static void exitQuitMenu()
- {
- // destroy the quit menu
- destroyQuitMenu();
-
- // clear out all the game data
- if ( TheGameLogic->isInMultiplayerGame() && !TheGameLogic->isInSkirmishGame() && !TheGameInfo->isSandbox() )
- {
- GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT);
- msg->appendBooleanArgument(TRUE);
- }
- /*GameMessage *msg =*/ TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
- if ( !TheGameLogic->isInMultiplayerGame() )
- TheGameLogic->setGamePaused(FALSE);
- // TheGameLogic->clearGameData();
- // display the menu on top of the shell stack
- // TheShell->showShell();
- // this will trigger an exit
- // TheGameEngine->setQuitting( TRUE );
- TheInGameUI->setClientQuiet( TRUE );
- }
- static void noExitQuitMenu()
- {
- quitConfirmationWindow = NULL;
- }
- static void quitToDesktopQuitMenu()
- {
- // destroy the quit menu
- destroyQuitMenu();
- if (TheGameLogic->isInGame())
- {
- if (TheRecorder->getMode() == RECORDERMODETYPE_RECORD)
- {
- TheRecorder->stopRecording();
- }
- TheGameLogic->clearGameData();
- }
- TheGameEngine->setQuitting(TRUE);
- TheInGameUI->setClientQuiet( TRUE );
- }
- static void surrenderQuitMenu()
- {
- // destroy the quit menu
- destroyQuitMenu();
- if (TheVictoryConditions->isLocalAlliedVictory())
- return;
- GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT);
- msg->appendBooleanArgument(TRUE);
- TheInGameUI->setClientQuiet( TRUE );
- }
- static void restartMissionMenu()
- {
- // destroy the quit menu
- destroyQuitMenu();
- Int gameMode = TheGameLogic->getGameMode();
- AsciiString mapName = TheGlobalData->m_mapName;
- //
- // if the map name was from a save game it will have "Save/" at the front of it,
- // we want to go back to the original pristine map string for the map name when restarting
- //
- if (TheGameState->isInSaveDirectory(mapName))
- mapName = TheGameState->getPristineMapName();
- // End the current game
- AsciiString replayFile = TheRecorder->getCurrentReplayFilename();
- if (TheRecorder->getMode() == RECORDERMODETYPE_RECORD)
- {
- TheRecorder->stopRecording();
- }
-
- Int rankPointsStartedWith = TheGameLogic->getRankPointsToAddAtGameStart();// must write down before reset
- GameDifficulty diff = TheScriptEngine->getGlobalDifficulty();
- Int fps = TheGameEngine->getFramesPerSecondLimit();
- TheGameLogic->clearGameData(FALSE);
- TheGameEngine->setQuitting(FALSE);
- if (replayFile.isNotEmpty())
- {
- TheRecorder->playbackFile(replayFile);
- }
- else
- {
- // send a message to the logic for a new game
- TheWritableGlobalData->m_pendingFile = mapName;
- GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
- msg->appendIntegerArgument(gameMode);
- msg->appendIntegerArgument(diff);
- msg->appendIntegerArgument(rankPointsStartedWith);
- msg->appendIntegerArgument(fps);
- DEBUG_LOG(("Restarting game mode %d, Diff=%d, RankPoints=%d\n", gameMode,
- TheScriptEngine->getGlobalDifficulty(),
- rankPointsStartedWith)
- );
- //if (TheGlobalData->m_fixedSeed >= 0)
- //InitRandom(TheGlobalData->m_fixedSeed);
- InitRandom(0);
- //else
- // InitGameLogicRandom(GameClientRandomValue(0, INT_MAX - 1));
- }
- //TheTransitionHandler->remove("QuitFull"); //KRISMORNESS ADD
- //quitMenuLayout = NULL; //KRISMORNESS ADD
- //isVisible = TRUE; //KRISMORNESS ADD
- //HideQuitMenu(); //KRISMORNESS ADD
- TheInGameUI->setClientQuiet( TRUE );
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void HideQuitMenu( void )
- {
- // Note: This is called as a safety a lot, without checking for the prescence of the quit menu.
- // So don't do anything that counts on that menu actually being here.
- if(!isVisible)
- return;
- if(quitMenuLayout && quitMenuLayout == noSaveLoadQuitMenuLayout)
- TheTransitionHandler->reverse("QuitNoSaveBack");
- else if( quitMenuLayout && quitMenuLayout == fullQuitMenuLayout)
- TheTransitionHandler->reverse("QuitFullBack");
- TheInGameUI->setQuitMenuVisible( FALSE );
- isVisible = FALSE;
- if (quitConfirmationWindow)
- TheWindowManager->winDestroy(quitConfirmationWindow);
- quitConfirmationWindow = NULL;
- if ( !TheGameLogic->isInMultiplayerGame() )
- TheGameLogic->setGamePaused(FALSE);
- }
- //-------------------------------------------------------------------------------------------------
- /** Toggle visibility of the quit menu */
- //-------------------------------------------------------------------------------------------------
- void ToggleQuitMenu()
- {
-
- //Added By Sadullah Nader
- //Added a check to see if we're not in game yet
- if (TheGameLogic->isIntroMoviePlaying() || TheGameLogic->isLoadingGame() ||TheScriptEngine->isGameEnding())
- return;
- //End Add
- // BGC- If we are currently in the disconnect screen, don't let the quit menu come up.
- if (TheDisconnectMenu != NULL) {
- if (TheDisconnectMenu->isScreenVisible() == TRUE) {
- return;
- }
- }
- // BGC- this is kind of hackish, but its the safest way to do it I think.
- // Basically we're seeing if either the save/load window or the options window is up
- // and if one of them is, we quit out of them rather than toggle the quit menu.
- if (TheShell->getOptionsLayout(FALSE) != FALSE) {
- WindowLayout *optLayout = TheShell->getOptionsLayout(FALSE);
- GameWindow *optionsParent = optLayout->getFirstWindow();
- DEBUG_ASSERTCRASH(optionsParent != NULL, ("Not able to get the options layout parent window"));
- GameWindow *optionsBack = TheWindowManager->winGetWindowFromId(optionsParent, TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ButtonBack" ) ));
- DEBUG_ASSERTCRASH(optionsBack != NULL, ("Not able to get the back button window from the options menu"));
- TheWindowManager->winSendSystemMsg(optLayout->getFirstWindow(), GBM_SELECTED, (WindowMsgData)optionsBack, NULL);
- return;
- }
- if ((saveLoadMenuLayout != NULL) && (saveLoadMenuLayout->isHidden() == FALSE))
- {
- GameWindow *saveLoadParent = saveLoadMenuLayout->getFirstWindow();
- DEBUG_ASSERTCRASH(saveLoadParent != NULL, ("Not able to get the save/load layout parent window"));
- GameWindow *saveLoadBack = TheWindowManager->winGetWindowFromId(saveLoadParent, TheNameKeyGenerator->nameToKey( AsciiString( "PopupSaveLoad.wnd:ButtonBack" ) ));
- DEBUG_ASSERTCRASH(saveLoadBack != NULL, ("Not able to get the back button window from the save/load menu"));
- TheWindowManager->winSendSystemMsg(saveLoadMenuLayout->getFirstWindow(), GBM_SELECTED, (WindowMsgData)saveLoadBack, NULL);
- saveLoadMenuLayout = NULL;
- return;
- }
-
- // if we're visable hide our quit menu
- if(isVisible && quitMenuLayout)
- {
-
- isVisible = FALSE;
-
- //Added By Sadullah Nader
- //Bug: When Toggling the quit menu off, the quit confirmation should also go away
- if (quitConfirmationWindow)
- TheWindowManager->winDestroy(quitConfirmationWindow);
- quitConfirmationWindow = NULL;
- //
-
- if ( !TheGameLogic->isInMultiplayerGame() )
- TheGameLogic->setGamePaused(FALSE);
- if(quitMenuLayout && quitMenuLayout == noSaveLoadQuitMenuLayout)
- TheTransitionHandler->reverse("QuitNoSaveBack");
- else if( quitMenuLayout && quitMenuLayout == fullQuitMenuLayout )
- {
- TheTransitionHandler->reverse("QuitFullBack");
- //begin KRISMORNESS
- //TheTransitionHandler->reverse("QuitFull");
- //if( TheTransitionHandler->areTransitionsEnabled() )
- //else
- //{
- // TheTransitionHandler->remove("QuitFull");
- // quitMenuLayout = NULL;
- // isVisible = TRUE;
- // HideQuitMenu();
- //}
- //end KRISMORNESS
- }
- }
- else
- {
- //Added By Sadullah Nader
- //Added to compensate for the quit confirmation window pop-up
-
- TheMouse->setCursor( Mouse::ARROW );
- TheControlBar->hidePurchaseScience();
- if ( TheGameLogic->isInMultiplayerGame() || TheGameLogic->isInReplayGame() )
- {
- // we don't want to show the save load button.
- if(!noSaveLoadQuitMenuLayout)
- noSaveLoadQuitMenuLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/QuitNoSave.wnd" ) );
- quitMenuLayout = noSaveLoadQuitMenuLayout;
- initGadgetsNoSaveQuit();
- TheTransitionHandler->remove("QuitNoSave");
- TheTransitionHandler->setGroup("QuitNoSave");
- }
- else
- {
- if(!fullQuitMenuLayout)
- fullQuitMenuLayout= TheWindowManager->winCreateLayout( AsciiString( "Menus/QuitMenu.wnd" ) );
- quitMenuLayout = fullQuitMenuLayout;
- initGadgetsFullQuit();
- TheTransitionHandler->remove("QuitFull");
- TheTransitionHandler->setGroup("QuitFull");
- }
- // load the quit menu from the layout file if needed
- if( quitMenuLayout == NULL )
- {
- DEBUG_ASSERTCRASH(FALSE, ("Could not load a quit menu layout"));
- isVisible = FALSE;
- TheInGameUI->setQuitMenuVisible(FALSE);
- return;
- }
-
- //quitMenuLayout->hide(FALSE);
- // if we are watching a cinematic, we need to disable the save/load button
- // because the save load window doesn't fit in the screen in letterbox mode.
- if (TheInGameUI->getInputEnabled() == FALSE) {
- if(buttonSaveLoadWin)
- buttonSaveLoadWin->winEnable(FALSE);
- buttonOptionsWin->winEnable(FALSE);
- } else if (buttonSaveLoadWin)
- {
- if(buttonSaveLoadWin)
- buttonSaveLoadWin->winEnable(TRUE);
- buttonOptionsWin->winEnable(TRUE);
- }
- // Disable the restart, load, save, etc buttons in network games
- if ( TheGameLogic->isInMultiplayerGame() || TheGameLogic->isInSkirmishGame() )
- {
- buttonRestartWin->winEnable(TRUE);
- if (TheGameLogic->isInSkirmishGame() == FALSE) {
- GadgetButtonSetText(buttonRestartWin, TheGameText->fetch("GUI:Surrender"));
-
- }
-
- if (TheGameLogic->isInSkirmishGame() == TRUE) {
- TheGameLogic->setGamePaused(TRUE);
- }
- if ((!ThePlayerList->getLocalPlayer()->isPlayerActive() || TheVictoryConditions->isLocalAlliedVictory()) &&
- (TheGameLogic->isInSkirmishGame() == FALSE))
- {
- buttonRestartWin->winEnable(FALSE); // can't surrender when you're dead
- }
- }
- else
- {
- buttonRestartWin->winEnable(TRUE);
- if(!TheGameLogic->isInReplayGame())
- {
- GadgetButtonSetText(buttonRestartWin, TheGameText->fetch("GUI:RestartMission"));
- GadgetButtonSetText(buttonExitWin, TheGameText->fetch("GUI:ExitMission"));
-
- }
- //if we're not in a multiplayer game, pause the game
- TheGameLogic->setGamePaused(TRUE);
- }
- if (quitConfirmationWindow)
- TheWindowManager->winDestroy(quitConfirmationWindow);
- quitConfirmationWindow = NULL;
- HideDiplomacy();
- HideInGameChat();
- TheControlBar->hidePurchaseScience();
- isVisible = TRUE;
- }
-
- TheInGameUI->setQuitMenuVisible(isVisible);
-
- } // end ToggleQuitMenu
- //-------------------------------------------------------------------------------------------------
- /** Quit menu window system callback */
- //-------------------------------------------------------------------------------------------------
- WindowMsgHandledType QuitMenuSystem( GameWindow *window, UnsignedInt msg,
- WindowMsgData mData1, WindowMsgData mData2 )
- {
- switch( msg )
- {
- // --------------------------------------------------------------------------------------------
- case GWM_CREATE:
- {
- break;
- } // end create
- //---------------------------------------------------------------------------------------------
- case GWM_DESTROY:
- {
- break;
- } // end case
- //---------------------------------------------------------------------------------------------
- case GBM_SELECTED:
- {
- GameWindow *control = (GameWindow *)mData1;
- Int controlID = control->winGetWindowId();
- if( controlID == buttonSaveLoad )
- {
- //
- // these commented lines (12-11-2002) will allow access to load only when were
- // viewing an in-game cinema ... but it's brittle, so I'm disableing it for
- // now and just using the grey button for the whole save/load button for now
- // during a cinema
- //
-
- // SaveLoadLayoutType layoutType = SLLT_SAVE_AND_LOAD;
- //
- // if input is disabled we are in an in-game cinematic and can load only, since we
- // are in the quit menu we are paused and therefore input is disabled all
- // the time ... in order to figure out if the *game* has input disabled we need
- // to query for the input enabled memory in the game logic which represents the
- // input enabled status of the game if we were not currently paused
- //
- // if( TheGameLogic->getInputEnabledMemory() == FALSE )
- // layoutType = SLLT_LOAD_ONLY;
- saveLoadMenuLayout = TheShell->getSaveLoadMenuLayout();
- // saveLoadMenuLayout->runInit( &layoutType );
- saveLoadMenuLayout->runInit();
- saveLoadMenuLayout->hide( FALSE );
- saveLoadMenuLayout->bringForward();
- }
- else if( controlID == buttonExit )
- {
- quitConfirmationWindow = QuitMessageBoxYesNo(TheGameText->fetch("GUI:QuitPopupTitle"), TheGameText->fetch("GUI:QuitPopupMessage"),/*quitCallback*/exitQuitMenu,noExitQuitMenu);
- } // end if
- else if( controlID == buttonReturn )
- {
-
- // hide this menu
- ToggleQuitMenu();
- } // end else if
- else if( buttonOptions == controlID )
- {
- WindowLayout *optLayout = TheShell->getOptionsLayout(TRUE);
- DEBUG_ASSERTCRASH(optLayout != NULL, ("options menu layout is NULL"));
- optLayout->runInit();
- optLayout->hide(FALSE);
- optLayout->bringForward();
- }
- // else if( controlID == buttonQuitToDesktop )
- // {
- // quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:QuitPopupTitle"), TheGameText->fetch("GUI:QuitToDesktopConf"),/*quitCallback*/quitToDesktopQuitMenu,noExitQuitMenu);
- //
- // } // end else if
- else if( controlID == buttonRestart )
- {
- if ( TheGameLogic->isInMultiplayerGame() )
- {
- // we really want to surrender
- quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:SurrenderConfirmationTitle"),
- TheGameText->fetch("GUI:SurrenderConfirmation"),
- /*quitCallback*/surrenderQuitMenu,noExitQuitMenu);
- }
- else
- {
- //we really want to restart
- quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:RestartConfirmationTitle"),
- TheGameText->fetch("GUI:RestartConfirmation"),
- /*quitCallback*/restartMissionMenu,noExitQuitMenu);
- }
- } // end else if
- break;
- } // end selected
- default:
- return MSG_IGNORED;
- } // end switch
- return MSG_HANDLED;
- } // end QuitMenuSystem
|