diff --git a/Common/UI/PopupScreens.cpp b/Common/UI/PopupScreens.cpp index c7fbc8e2c0..3ce55f874f 100644 --- a/Common/UI/PopupScreens.cpp +++ b/Common/UI/PopupScreens.cpp @@ -261,12 +261,23 @@ void PopupContextMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { } // Hacky: Override the position to look like a popup menu. + AnchorLayoutParams *ap = (AnchorLayoutParams *)parent->GetLayoutParams(); ap->centering = Centering::None; - ap->left = sourceView_->GetBounds().x; + if (sourceView_->GetBounds().x2() > g_display.pixel_xres - 300) { + ap->right = sourceView_->GetBounds().x2(); + } else { + ap->left = sourceView_->GetBounds().x; + } ap->top = sourceView_->GetBounds().y2(); } +PopupCallbackScreen::PopupCallbackScreen(std::function createViews, UI::View *sourceView) : PopupScreen(""), createViews_(createViews) { + if (sourceView) { + SetPopupOrigin(sourceView); + } +} + void PopupCallbackScreen::CreatePopupContents(ViewGroup *parent) { createViews_(parent); for (int i = 0; i < parent->GetNumSubviews(); i++) { diff --git a/Common/UI/PopupScreens.h b/Common/UI/PopupScreens.h index bfd3879f7a..3507a9707a 100644 --- a/Common/UI/PopupScreens.h +++ b/Common/UI/PopupScreens.h @@ -241,7 +241,6 @@ struct ContextMenuItem { class PopupContextMenuScreen : public PopupScreen { public: PopupContextMenuScreen(const ContextMenuItem *items, size_t itemCount, I18NCat category, UI::View *sourceView); - const char *tag() const override { return "ContextMenuPopup"; } void SetEnabled(size_t index, bool enabled) { @@ -261,13 +260,8 @@ private: class PopupCallbackScreen : public PopupScreen { public: - PopupCallbackScreen(std::function createViews, UI::View *sourceView) : PopupScreen(""), createViews_(createViews) { - if (sourceView) { - SetPopupOrigin(sourceView); - } - } - - const char *tag() const override { return "ContextMenuPopup"; } + PopupCallbackScreen(std::function createViews, UI::View *sourceView); + const char *tag() const override { return "ContextMenuCallbackPopup"; } private: void CreatePopupContents(ViewGroup *parent) override; diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 4e34406bae..3c7b7bb324 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -211,7 +211,7 @@ void DisplayLayoutScreen::CreateViews() { root_->SetExclusiveTouch(true); // Add indicator of the current mode we're editing. Not sure why these strings are in Controls. - root_->Add(new TextView(portrait ? co->T("Portrait") : co->T("Landscape"), new AnchorLayoutParams(portrait ? 10.0f : NONE, 10.0f, NONE, NONE))); + root_->Add(new TextView(portrait ? co->T("Portrait") : co->T("Landscape"), new AnchorLayoutParams(portrait ? 10.0f : NONE, 10.0f, NONE, NONE)))->SetSmall(true); DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); bool internalPortrait = config.iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || config.iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180; diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 1a7657e108..7af9285835 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -40,6 +40,7 @@ #include "Core/ELF/PBPReader.h" #include "Core/SaveState.h" #include "Core/System.h" +#include "Core/Util/GameDB.h" #include "Core/Loaders.h" #include "Core/Util/GameManager.h" #include "Core/Util/RecentFiles.h" @@ -380,6 +381,21 @@ std::string GameInfo::GetTitle() { } } +std::string GameInfo::GetDBTitle() { + std::lock_guard guard(lock); + if (!(hasFlags & GameInfoFlags::PARAM_SFO) && !title.empty()) { + return filePath_.GetFilename(); + } + + std::vector dbInfos; + const bool inGameDB = g_gameDB.GetGameInfos(id_version, &dbInfos); + if (inGameDB) { + return std::string(dbInfos[0].title); + } else { + return title; + } +} + void GameInfo::SetTitle(const std::string &newTitle) { std::lock_guard guard(lock); title = newTitle; diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 42d69f2240..89e681f23f 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -105,6 +105,8 @@ public: std::vector GetSaveDataDirectories(); std::string GetTitle(); + std::string GetDBTitle(); // Falls back to GetTitle if not in the DB. + void SetTitle(const std::string &newTitle); const Path &GetFilePath() const { diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 0d66ed988d..a8ea552791 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -322,24 +322,18 @@ void GameScreen::CreateSettingsViews(UI::ViewGroup *rightColumn) { rightColumnItems->Add(new Choice(ga->T("Play"), ImageID("I_PLAY")))->OnClick.Handle(this, &GameScreen::OnPlay); } - if (!info_->id.empty()) { + if (!info_->id.empty() && !inGame_) { if (info_->hasConfig) { // Only show the Game Settings button here if the game has a config. Always showing it // is confusing since it'll just control the global settings. Choice *btnGameSettings = rightColumnItems->Add(new Choice(ga->T("Game Settings"), ImageID("I_GEAR"))); btnGameSettings->OnClick.Handle(this, &GameScreen::OnGameSettings); - if (inGame_) - btnGameSettings->SetEnabled(false); Choice *btnDeleteGameConfig = rightColumnItems->Add(new Choice(ga->T("Delete Game Config"))); btnDeleteGameConfig->OnClick.Handle(this, &GameScreen::OnDeleteConfig); - if (inGame_) - btnDeleteGameConfig->SetEnabled(false); } else { Choice *btnCreateGameConfig = rightColumnItems->Add(new Choice(ga->T("Create Game Config"))); btnCreateGameConfig->OnClick.Handle(this, &GameScreen::OnCreateConfig); - if (inGame_) - btnCreateGameConfig->SetEnabled(false); } } @@ -349,10 +343,9 @@ void GameScreen::CreateSettingsViews(UI::ViewGroup *rightColumn) { } // Don't want to be able to delete the game while it's running. - Choice *deleteChoice = rightColumnItems->Add(new Choice(ga->T("Delete Game"))); - deleteChoice->OnClick.Handle(this, &GameScreen::OnDeleteGame); - if (inGame_) { - deleteChoice->SetEnabled(false); + if (!inGame_) { + Choice *deleteChoice = rightColumnItems->Add(new Choice(ga->T("Delete Game"))); + deleteChoice->OnClick.Handle(this, &GameScreen::OnDeleteGame); } if ((knownFlags_ & GameInfoFlags::PARAM_SFO) && System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) { @@ -367,12 +360,9 @@ void GameScreen::CreateSettingsViews(UI::ViewGroup *rightColumn) { } // TODO: This is synchronous, bad! - if (g_recentFiles.ContainsFile(gamePath_.ToString())) { + if (!inGame_ && g_recentFiles.ContainsFile(gamePath_.ToString())) { Choice *removeButton = rightColumnItems->Add(new Choice(ga->T("Remove From Recent"))); removeButton->OnClick.Handle(this, &GameScreen::OnRemoveFromRecent); - if (inGame_) { - removeButton->SetEnabled(false); - } } if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { @@ -414,13 +404,7 @@ void GameScreen::OnCreateConfig(UI::EventParams &e) { std::string_view GameScreen::GetTitle() const { if (knownFlags_ & GameInfoFlags::PARAM_SFO) { - std::vector dbInfos; - const bool inGameDB = g_gameDB.GetGameInfos(info_->id_version, &dbInfos); - if (inGameDB) { - titleCache_ = dbInfos[0].title; - } else { - titleCache_ = std::string(info_->GetTitle()); - } + titleCache_ = info_->GetDBTitle(); } return titleCache_; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 20c579483a..8edcf98269 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -33,7 +33,6 @@ #include "Common/System/Request.h" #include "Common/VR/PPSSPPVR.h" #include "Common/UI/AsyncImageFileView.h" -#include "Common/UI/PopupScreens.h" #include "Core/KeyMap.h" #include "Core/Reporting.h" @@ -49,6 +48,7 @@ #include "Core/HLE/sceNet.h" #include "Core/HLE/sceNetInet.h" #include "Core/HLE/sceNetAdhoc.h" +#include "Core/Util/GameDB.h" #include "Core/HLE/NetAdhocCommon.h" #include "GPU/GPUCommon.h" @@ -66,6 +66,7 @@ #include "UI/DisplayLayoutScreen.h" #include "UI/RetroAchievementScreens.h" #include "UI/BackgroundAudio.h" +#include "UI/MiscViews.h" static void AfterSaveStateAction(SaveState::Status status, std::string_view message) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { @@ -186,7 +187,7 @@ void ScreenshotViewScreen::OnDeleteState(UI::EventParams &e) { class SaveSlotView : public UI::LinearLayout { public: - SaveSlotView(const Path &gamePath, int slot, bool vertical, UI::LayoutParams *layoutParams = nullptr); + SaveSlotView(const Path &gamePath, int slot, UI::LayoutParams *layoutParams = nullptr); void GetContentDimensions(const UIContext &dc, float &w, float &h) const override { w = 500; h = 90; @@ -223,7 +224,7 @@ private: Path screenshotFilename_; }; -SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, bool vertical, UI::LayoutParams *layoutParams) : UI::LinearLayout(ORIENT_HORIZONTAL, layoutParams), slot_(slot), gamePath_(gameFilename) { +SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, UI::LayoutParams *layoutParams) : UI::LinearLayout(ORIENT_HORIZONTAL, layoutParams), slot_(slot), gamePath_(gameFilename) { using namespace UI; screenshotFilename_ = SaveState::GenerateSaveSlotFilename(gamePath_, slot, SaveState::SCREENSHOT_EXTENSION); @@ -239,7 +240,7 @@ SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, bool vertical, UI Add(lines); - LinearLayout *buttons = new LinearLayout(vertical ? ORIENT_VERTICAL : ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + LinearLayout *buttons = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); buttons->SetSpacing(10.0f); lines->Add(buttons); @@ -258,9 +259,7 @@ SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, bool vertical, UI std::string dateStr = SaveState::GetSlotDateAsString(gamePath_, slot_); if (!dateStr.empty()) { TextView *dateView = new TextView(dateStr, new LinearLayoutParams(0.0, Gravity::G_VCENTER)); - if (vertical) { - dateView->SetSmall(true); - } + dateView->SetSmall(true); lines->Add(dateView)->SetShadow(true); } } else { @@ -323,8 +322,10 @@ void GamePauseScreen::update() { lastDNSConfigLoaded_ = dnsConfig.loaded; } - const bool mustRunBehind = MustRunBehind(); - playButton_->SetVisibility(mustRunBehind ? UI::V_GONE : UI::V_VISIBLE); + if (playButton_) { + const bool mustRunBehind = MustRunBehind(); + playButton_->SetVisibility(mustRunBehind ? UI::V_GONE : UI::V_VISIBLE); + } SetVRAppMode(VRAppMode::VR_MENU_MODE); } @@ -358,7 +359,7 @@ bool GamePauseScreen::key(const KeyInput &key) { return false; } -void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems, bool vertical) { +void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems) { auto pa = GetI18NCategory(I18NCat::PAUSE); static const int NUM_SAVESLOTS = 5; @@ -367,7 +368,7 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems, leftColumnItems->SetSpacing(10.0); for (int i = 0; i < NUM_SAVESLOTS; i++) { - SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(gamePath_, i, vertical, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(gamePath_, i, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); slot->OnStateLoaded.Handle(this, &GamePauseScreen::OnState); slot->OnStateSaved.Handle(this, &GamePauseScreen::OnState); slot->OnScreenshotClicked.Handle(this, &GamePauseScreen::OnScreenshotClicked); @@ -415,50 +416,69 @@ void GamePauseScreen::CreateViews() { auto nw = GetI18NCategory(I18NCat::NETWORKING); auto di = GetI18NCategory(I18NCat::DIALOG); - root_ = new LinearLayout(ORIENT_HORIZONTAL); + root_ = new LinearLayout(portrait ? ORIENT_VERTICAL : ORIENT_HORIZONTAL); - ViewGroup *leftColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0, scrollMargins)); - root_->Add(leftColumn); + if (portrait) { + // We have room for a title bar. Use the game DB title if available. + std::string title; + std::vector dbInfos; + const bool inGameDB = g_gameDB.GetGameInfos(g_paramSFO.GetDiscID(), &dbInfos); + if (inGameDB) { + title = dbInfos[0].title; + } else { + title = g_paramSFO.GetValueString("TITLE"); + } + TopBar *topBar = new TopBar(*screenManager()->getUIContext(), TopBarFlags::ContextMenuButton, title); + root_->Add(topBar); - LinearLayout *leftColumnItems = new LinearLayoutList(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); - leftColumn->Add(leftColumnItems); + topBar->OnContextMenuClick.Add([this](UI::EventParams &e) { + UI::View *srcView = e.v; + ShowContextMenu(srcView); + }); + } - leftColumnItems->SetSpacing(5.0f); + ViewGroup *saveStateScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f, scrollMargins)); + root_->Add(saveStateScroll); + + LinearLayout *saveDataScrollItems = new LinearLayoutList(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + saveStateScroll->Add(saveDataScrollItems); + + saveDataScrollItems->SetSpacing(5.0f); if (Achievements::IsActive()) { - leftColumnItems->Add(new GameAchievementSummaryView()); + saveDataScrollItems->Add(new GameAchievementSummaryView()); char buf[512]; size_t sz = Achievements::GetRichPresenceMessage(buf, sizeof(buf)); if (sz != (size_t)-1) { - leftColumnItems->Add(new TextView(std::string_view(buf, sz), FLAG_WRAP_TEXT, true, new UI::LinearLayoutParams(Margins(5, 5)))); + saveDataScrollItems->Add(new TextView(std::string_view(buf, sz), FLAG_WRAP_TEXT, true, new UI::LinearLayoutParams(Margins(5, 5)))); } } if (IsNetworkConnected()) { - leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, nw->T("Network connected"), "")); + saveDataScrollItems->Add(new NoticeView(NoticeLevel::INFO, nw->T("Network connected"), "")); const InfraDNSConfig &dnsConfig = GetInfraDNSConfig(); if (dnsConfig.loaded && __NetApctlConnected()) { - leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, nw->T("Infrastructure"), "")); + saveDataScrollItems->Add(new NoticeView(NoticeLevel::INFO, nw->T("Infrastructure"), "")); if (dnsConfig.state == InfraGameState::NotWorking) { - leftColumnItems->Add(new NoticeView(NoticeLevel::WARN, nw->T("Some network functionality in this game is not working"), "")); + saveDataScrollItems->Add(new NoticeView(NoticeLevel::WARN, nw->T("Some network functionality in this game is not working"), "")); if (!dnsConfig.workingIDs.empty()) { std::string str(nw->T("Other versions of this game that should work:")); for (auto &id : dnsConfig.workingIDs) { str.append("\n - "); str += id; } - leftColumnItems->Add(new TextView(str)); + saveDataScrollItems->Add(new TextView(str)); } } else if (dnsConfig.state == InfraGameState::Unknown) { - leftColumnItems->Add(new NoticeView(NoticeLevel::WARN, nw->T("Network functionality in this game is not guaranteed"), "")); + saveDataScrollItems->Add(new NoticeView(NoticeLevel::WARN, nw->T("Network functionality in this game is not guaranteed"), "")); } if (!dnsConfig.revivalTeam.empty()) { - leftColumnItems->Add(new TextView(std::string(nw->T("Infrastructure server provided by:")))); - leftColumnItems->Add(new TextView(dnsConfig.revivalTeam)); + saveDataScrollItems->Add(new TextView(std::string(nw->T("Infrastructure server provided by:")))); + saveDataScrollItems->Add(new TextView(dnsConfig.revivalTeam)); if (!dnsConfig.revivalTeamURL.empty()) { - leftColumnItems->Add(new Button(dnsConfig.revivalTeamURL))->OnClick.Add([&dnsConfig](UI::EventParams &e) { + saveDataScrollItems->Add(new Button(dnsConfig.revivalTeamURL))->OnClick.Add([&dnsConfig](UI::EventParams &e) { if (!dnsConfig.revivalTeamURL.empty()) { System_LaunchUrl(LaunchUrlType::BROWSER_URL, dnsConfig.revivalTeamURL.c_str()); } @@ -469,7 +489,7 @@ void GamePauseScreen::CreateViews() { if (NetAdhocctl_GetState() >= ADHOCCTL_STATE_CONNECTED) { // Awkwardly re-using a string here - leftColumnItems->Add(new TextView(std::string(nw->T("AdHoc server")) + ": " + std::string(nw->T("Connected")))); + saveDataScrollItems->Add(new TextView(std::string(nw->T("AdHoc server")) + ": " + std::string(nw->T("Connected")))); } } @@ -482,44 +502,51 @@ void GamePauseScreen::CreateViews() { if (showSavestateControls) { if (PSP_CoreParameter().compat.flags().SaveStatesNotRecommended) { LinearLayout *horiz = new LinearLayout(ORIENT_HORIZONTAL); - leftColumnItems->Add(horiz); + saveDataScrollItems->Add(horiz); horiz->Add(new NoticeView(NoticeLevel::WARN, pa->T("Using save states is not recommended in this game"), "", new LinearLayoutParams(1.0f))); horiz->Add(new Button(di->T("More info")))->OnClick.Add([](UI::EventParams &e) { System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/troubleshooting/save-state-time-warps"); }); } - CreateSavestateControls(leftColumnItems, portrait); + CreateSavestateControls(saveDataScrollItems); } else { // Let's show the active challenges. std::set ids = Achievements::GetActiveChallengeIDs(); if (!ids.empty()) { - leftColumnItems->Add(new ItemHeader(ac->T("Active Challenges"))); + saveDataScrollItems->Add(new ItemHeader(ac->T("Active Challenges"))); for (auto id : ids) { const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), id); if (!achievement) continue; - leftColumnItems->Add(new AchievementView(achievement)); + saveDataScrollItems->Add(new AchievementView(achievement)); } } // And tack on an explanation for why savestate options are not available. if (!achievementsAllowSavestates) { - leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, ac->T("Save states not available in Hardcore Mode"), "")); + saveDataScrollItems->Add(new NoticeView(NoticeLevel::INFO, ac->T("Save states not available in Hardcore Mode"), "")); } } - LinearLayout *middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64, FILL_PARENT, Margins(0, 10, 0, 15))); - root_->Add(middleColumn); - middleColumn->SetSpacing(0.0f); - ViewGroup *rightColumnHolder = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(portrait ? 200 : 300, FILL_PARENT, actionMenuMargins)); + LinearLayout *middleColumn = nullptr; + ViewGroup *buttonColumn = nullptr; + if (portrait) { + buttonColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, actionMenuMargins)); - ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); - rightColumnHolder->Add(rightColumn); + root_->Add(buttonColumn); + } else { + middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64, FILL_PARENT, Margins(0, 10, 0, 15))); + root_->Add(middleColumn); + middleColumn->SetSpacing(0.0f); - root_->Add(rightColumnHolder); + ViewGroup *buttonColumnScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(320, FILL_PARENT, actionMenuMargins)); + buttonColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + buttonColumnScroll->Add(buttonColumn); + root_->Add(buttonColumnScroll); + } LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL); - rightColumn->Add(rightColumnItems); + buttonColumn->Add(rightColumnItems); rightColumnItems->SetSpacing(0.0f); if (getUMDReplacePermit()) { @@ -528,9 +555,11 @@ void GamePauseScreen::CreateViews() { }); } - Choice *continueChoice = rightColumnItems->Add(new Choice(pa->T("Continue"), ImageID("I_PLAY"))); - root_->SetDefaultFocusView(continueChoice); - continueChoice->OnClick.Handle(this, &UIScreen::OnBack); + if (!portrait) { + Choice *continueChoice = rightColumnItems->Add(new Choice(pa->T("Continue"), ImageID("I_PLAY"))); + root_->SetDefaultFocusView(continueChoice); + continueChoice->OnClick.Handle(this, &UIScreen::OnBack); + } rightColumnItems->Add(new Spacer(20.0)); @@ -577,54 +606,61 @@ void GamePauseScreen::CreateViews() { exit->OnClick.Handle(this, &GamePauseScreen::OnExit); exit->SetEnabled(!bootPending_); - middleColumn->SetSpacing(20.0f); - playButton_ = middleColumn->Add(new Button("", g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"), new LinearLayoutParams(64, 64))); - playButton_->OnClick.Add([=](UI::EventParams &e) { - g_Config.bRunBehindPauseMenu = !g_Config.bRunBehindPauseMenu; - playButton_->SetImageID(g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY")); - }); + if (middleColumn) { + middleColumn->SetSpacing(20.0f); + playButton_ = middleColumn->Add(new Button("", g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"), new LinearLayoutParams(64, 64))); + playButton_->OnClick.Add([=](UI::EventParams &e) { + g_Config.bRunBehindPauseMenu = !g_Config.bRunBehindPauseMenu; + playButton_->SetImageID(g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY")); + }); - bool mustRunBehind = MustRunBehind(); - playButton_->SetVisibility(mustRunBehind ? UI::V_GONE : UI::V_VISIBLE); + bool mustRunBehind = MustRunBehind(); + playButton_->SetVisibility(mustRunBehind ? UI::V_GONE : UI::V_VISIBLE); - Button *infoButton = middleColumn->Add(new Button("", ImageID("I_INFO"), new LinearLayoutParams(64, 64))); - infoButton->OnClick.Add([=](UI::EventParams &e) { - screenManager()->push(new GameScreen(gamePath_, true)); - }); + Button *infoButton = middleColumn->Add(new Button("", ImageID("I_INFO"), new LinearLayoutParams(64, 64))); + infoButton->OnClick.Add([=](UI::EventParams &e) { + screenManager()->push(new GameScreen(gamePath_, true)); + }); - Button *menuButton = middleColumn->Add(new Button("", ImageID("I_THREE_DOTS"), new LinearLayoutParams(64, 64))); + Button *menuButton = middleColumn->Add(new Button("", ImageID("I_THREE_DOTS"), new LinearLayoutParams(64, 64))); - menuButton->OnClick.Add([this, menuButton](UI::EventParams &e) { - static const ContextMenuItem ingameContextMenu[] = { - { "Reset" }, - }; - PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(ingameContextMenu, ARRAY_SIZE(ingameContextMenu), I18NCat::DIALOG, menuButton); - screenManager()->push(contextMenu); - contextMenu->OnChoice.Add([=](EventParams &e) -> void { - switch (e.a) { - case 0: // Reset - { - std::string confirmMessage = GetConfirmExitMessage(); - if (!confirmMessage.empty()) { - auto di = GetI18NCategory(I18NCat::DIALOG); - screenManager()->push(new UI::MessagePopupScreen(di->T("Reset"), confirmMessage, di->T("Reset"), di->T("Cancel"), [=](bool result) { - if (result) { - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); - } - })); - } else { - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); - break; - } - } - default: + menuButton->OnClick.Add([this, menuButton](UI::EventParams &e) { + ShowContextMenu(menuButton); + }); + } else { + playButton_ = nullptr; + } +} + +void GamePauseScreen::ShowContextMenu(UI::View *menuButton) { + using namespace UI; + static const ContextMenuItem ingameContextMenu[] = { + { "Reset" }, + }; + PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(ingameContextMenu, ARRAY_SIZE(ingameContextMenu), I18NCat::DIALOG, menuButton); + screenManager()->push(contextMenu); + contextMenu->OnChoice.Add([=](EventParams &e) -> void { + switch (e.a) { + case 0: // Reset + { + std::string confirmMessage = GetConfirmExitMessage(); + if (!confirmMessage.empty()) { + auto di = GetI18NCategory(I18NCat::DIALOG); + screenManager()->push(new UI::MessagePopupScreen(di->T("Reset"), confirmMessage, di->T("Reset"), di->T("Cancel"), [=](bool result) { + if (result) { + System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + } + })); + } else { + System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); break; } - }); + break; + } + default: + break; + } }); - - // What's this for? - rightColumnHolder->Add(new Spacer(10.0f)); } void GamePauseScreen::OnGameSettings(UI::EventParams &e) { diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 4f091a2e3d..1141947e4c 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -25,6 +25,7 @@ #include "Common/UI/ViewGroup.h" #include "UI/BaseScreens.h" #include "UI/Screen.h" +#include "UI/GameInfoCache.h" class GamePauseScreen : public UIBaseDialogScreen { public: @@ -42,7 +43,7 @@ protected: UI::Margins RootMargins() const override; private: - void CreateSavestateControls(UI::LinearLayout *viewGroup, bool vertical); + void CreateSavestateControls(UI::LinearLayout *viewGroup); void OnGameSettings(UI::EventParams &e); void OnExit(UI::EventParams &e); @@ -58,6 +59,7 @@ private: void OnDeleteConfig(UI::EventParams &e); void OnState(UI::EventParams &e); + void ShowContextMenu(UI::View *menuButton); // hack bool finishNextFrame_ = false; diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 8a3ff439fd..e967a5d3de 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -45,7 +45,7 @@ public: RatingChoice *SetEnabledPtrs(bool *enabled); - Event OnChoice; + UI::Event OnChoice; protected: void Update() override;