mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #22721 from hrydgard/settings-bugfixes
Assorted UI bugfixes
This commit is contained in:
24 files changed
+222
-205
No files matched your search
@@ -138,6 +138,10 @@ bool TabHolder::EnsureTab(int index) {
|
||||
|
||||
void TabHolder::SetInitialTab(int tab) {
|
||||
if (tab < 0 || tab >= (int)tabs_.size()) {
|
||||
// The tab may no longer exist (the search tab is hidden on small screens, for example).
|
||||
if (currentTab_ < (int)tabs_.size()) {
|
||||
EnsureTab(currentTab_);
|
||||
}
|
||||
return;
|
||||
}
|
||||
EnsureTab(tab);
|
||||
|
||||
@@ -1666,6 +1666,9 @@ void Config::PostLoadCleanup() {
|
||||
|
||||
// Three frames in flight showed no benefit over two, so the option is gone. Squash old values.
|
||||
iInflightFrames = std::clamp(iInflightFrames, 1, 2);
|
||||
|
||||
// The touch layout editor divides by this, and loops forever drawing the grid if it's 0.
|
||||
iTouchSnapGridSize = std::clamp(iTouchSnapGridSize, 2, 256);
|
||||
}
|
||||
|
||||
void Config::PreSaveCleanup() {
|
||||
|
||||
@@ -867,7 +867,8 @@ void AskToEditCurrentServer(int requestToken, ScreenManager *screenManager) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
static std::string editText = g_Config.sProAdhocServer;
|
||||
static std::string editText;
|
||||
editText = g_Config.sProAdhocServer;
|
||||
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(&editText, editText, n->T("Ad hoc server address"), 256);
|
||||
if (System_GetPropertyBool(SYSPROP_KEYBOARD_IS_SOFT)) {
|
||||
popupScreen->SetAlignTop(true);
|
||||
|
||||
@@ -308,20 +308,16 @@ void ControlMappingScreen::OnAutoConfigure(UI::EventParams ¶ms) {
|
||||
}
|
||||
auto km = GetI18NCategory(I18NCat::KEYMAPPING);
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
UI::ListPopupScreen *autoConfList = new UI::ListPopupScreen(km->T("Autoconfigure for device"), items, -1);
|
||||
// Uses a callback, since in portrait the settings are in a popup, which would get dialogFinished instead of us.
|
||||
UI::ListPopupScreen *autoConfList = new UI::ListPopupScreen(km->T("Autoconfigure for device"), items, -1, [items](int index) {
|
||||
KeyMap::AutoConfForPad(items[index]);
|
||||
});
|
||||
autoConfList->SetNotification(NoticeLevel::WARN, di->T("This will overwrite the existing configuration"));
|
||||
if (params.v)
|
||||
autoConfList->SetPopupOrigin(params.v);
|
||||
screenManager()->push(autoConfList);
|
||||
}
|
||||
|
||||
void ControlMappingScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
if (result == DR_OK && !strcmp(dialog->tag(), "listpopup")) {
|
||||
UI::ListPopupScreen *popup = (UI::ListPopupScreen *)dialog;
|
||||
KeyMap::AutoConfForPad(popup->GetChoiceString());
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
using namespace UI;
|
||||
|
||||
@@ -351,8 +347,11 @@ bool KeyMappingNewKeyDialog::key(const KeyInput &key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pspBtn_ == VIRTKEY_SPEED_ANALOG && !UI::IsEscapeKey(key)) {
|
||||
// Only map analog values to this mapping.
|
||||
if (pspBtn_ == VIRTKEY_SPEED_ANALOG) {
|
||||
// Only map analog values to this mapping. Escape cancels.
|
||||
if (UI::IsEscapeKey(key)) {
|
||||
TriggerFinish(DR_CANCEL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,6 @@ protected:
|
||||
private:
|
||||
void OnAutoConfigure(UI::EventParams ¶ms);
|
||||
|
||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||
|
||||
std::vector<SingleControlMapper *> mappers_;
|
||||
int keyMapGeneration_ = -1;
|
||||
|
||||
|
||||
@@ -136,14 +136,18 @@ void CustomButtonMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
|
||||
|
||||
ConfigCustomButton *cfg = nullptr;
|
||||
bool *show = nullptr;
|
||||
memset(array, 0, sizeof(array));
|
||||
cfg = &g_Config.CustomButton[id_];
|
||||
// This screen is reachable from the main menu, so neither GamepadEmu nor the layout screen
|
||||
// need have sanitized these yet - and everything below indexes the tables with them.
|
||||
CustomKeyData::Sanitize(*cfg);
|
||||
show = &touch.touchCustom[id_].show;
|
||||
for (int i = 0; i < ARRAY_SIZE(g_customKeyList); i++)
|
||||
array[i] = (0x01 == ((g_Config.CustomButton[id_].key >> i) & 0x01));
|
||||
// Only load once, since the views can be recreated (on rotation, for example) before the array is saved.
|
||||
if (!arrayLoaded_) {
|
||||
for (int i = 0; i < ARRAY_SIZE(g_customKeyList); i++) {
|
||||
array[i] = (0x01 == ((g_Config.CustomButton[id_].key >> i) & 0x01));
|
||||
}
|
||||
arrayLoaded_ = true;
|
||||
}
|
||||
|
||||
// TODO: Less hacky layout work
|
||||
const Bounds layoutBounds = GetLayoutBounds(*screenManager()->getUIContext());
|
||||
@@ -205,8 +209,9 @@ void CustomButtonMappingScreen::CreateDialogViews(UI::ViewGroup *parent) {
|
||||
choice = new Choice(mc->T(KeyMap::GetPspButtonNameCharPointer(g_customKeyList[i].c)), new LinearLayoutParams(1.0f));
|
||||
}
|
||||
|
||||
ChoiceEventHandler *choiceEventHandler = new ChoiceEventHandler(checkbox);
|
||||
choice->OnClick.Handle(choiceEventHandler, &ChoiceEventHandler::onChoiceClick);
|
||||
choice->OnClick.Add([checkbox](UI::EventParams &) {
|
||||
checkbox->Toggle();
|
||||
});
|
||||
|
||||
choice->SetCentered(true);
|
||||
|
||||
@@ -241,7 +246,3 @@ void CustomButtonMappingScreen::onFinish(DialogResult result) {
|
||||
saveArray();
|
||||
g_Config.Save("CustomButtonMappingScreen::onFinish");
|
||||
}
|
||||
|
||||
void CustomButtonMappingScreen::ChoiceEventHandler::onChoiceClick(UI::EventParams &e){
|
||||
checkbox_->Toggle();
|
||||
};
|
||||
@@ -46,15 +46,8 @@ private:
|
||||
void saveArray();
|
||||
|
||||
bool array[ARRAY_SIZE(CustomKeyData::g_customKeyList)]{};
|
||||
bool arrayLoaded_ = false;
|
||||
int id_;
|
||||
|
||||
class ChoiceEventHandler{
|
||||
public:
|
||||
ChoiceEventHandler(UI::CheckBox *checkbox) : checkbox_(checkbox) {}
|
||||
void onChoiceClick(UI::EventParams &e);
|
||||
private:
|
||||
UI::CheckBox *checkbox_;
|
||||
};
|
||||
|
||||
DeviceOrientation deviceOrientation_;
|
||||
};
|
||||
+11
-11
@@ -160,14 +160,11 @@ bool CwCheatScreen::WantsTextInput() const {
|
||||
|
||||
bool CwCheatScreen::TryLoadCheatInfo() {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
std::string gameID;
|
||||
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
return false;
|
||||
}
|
||||
gameID = info->GetParamSFO().GetValueString("DISC_ID");
|
||||
if ((info->id.empty() || !info->disc_total) && gamePath_.FilePathContainsNoCase("PSP/GAME/")) {
|
||||
gameID = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
}
|
||||
// The cache has already replaced the ID of homebrew with a generated one.
|
||||
const std::string &gameID = info->id;
|
||||
|
||||
if (!engine_ || gameID != gameID_) {
|
||||
gameID_ = gameID;
|
||||
@@ -205,6 +202,9 @@ bool CwCheatScreen::key(const KeyInput &input) {
|
||||
|
||||
void CwCheatScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
if (auto downloadScreen = dynamic_cast<const CwCheatDownloadPopupScreen *>(dialog)) {
|
||||
if (result != DR_OK || downloadScreen->ChosenUrl().empty()) {
|
||||
return;
|
||||
}
|
||||
if (downloadRequest_) {
|
||||
ERROR_LOG(Log::CwCheats, "Download already in progress, ignoring new download request.");
|
||||
return;
|
||||
@@ -429,7 +429,7 @@ void CwCheatScreen::ImportAndReport(const Path &cheatFile) {
|
||||
int cheatCount = 0;
|
||||
if (!ImportCheats(cheatFile, &cheatCount)) {
|
||||
// Show an error message?
|
||||
if (File::Exists(cheatFile)) {
|
||||
if (!File::Exists(cheatFile)) {
|
||||
auto er = GetI18NCategory(I18NCat::ERRORS);
|
||||
errorMessage_ = ApplySafeSubstitutions(er->T("File not found: %1"), "");
|
||||
errorLevel_ = NoticeLevel::WARN;
|
||||
@@ -474,14 +474,14 @@ void CwCheatScreen::OnImportCheat(UI::EventParams ¶ms) {
|
||||
}
|
||||
|
||||
bool CwCheatScreen::ImportCheats(const Path &cheatFile, int *cheatsFound) {
|
||||
FILE *in = File::OpenCFile(cheatFile, "rt");
|
||||
if (!in) {
|
||||
WARN_LOG(Log::CwCheats, "Unable to open %s\n", cheatFile.c_str());
|
||||
if (gameID_.length() != 9 || !engine_) {
|
||||
WARN_LOG(Log::CwCheats, "CWCHEAT: Incorrect ID(%s) - can't import cheats.", gameID_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gameID_.length() != 9 || !engine_) {
|
||||
WARN_LOG(Log::CwCheats, "CWCHEAT: Incorrect ID(%s) - can't import cheats.", gameID_.c_str());
|
||||
FILE *in = File::OpenCFile(cheatFile, "rt");
|
||||
if (!in) {
|
||||
WARN_LOG(Log::CwCheats, "Unable to open %s\n", cheatFile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -350,8 +350,7 @@ void DeveloperToolsScreen::CreateMIPSTracerTab(UI::LinearLayout *list) {
|
||||
return true;
|
||||
});
|
||||
|
||||
MIPSTracerPath_ = mipsTracer.get_logging_path();
|
||||
MIPSTracerPath = list->Add(new InfoItem(dev->T("Current log file"), MIPSTracerPath_));
|
||||
list->Add(new InfoItem(dev->T("Current log file"), mipsTracer.get_logging_path()));
|
||||
|
||||
PopupSliderChoice* storage_capacity = list->Add(
|
||||
new PopupSliderChoice(
|
||||
@@ -425,7 +424,8 @@ void DeveloperToolsScreen::CreateUITab(UI::LinearLayout *list) {
|
||||
list->Add(new ItemHeader(si->T("Slider test")));
|
||||
list->Add(new Slider(&testSliderValue_, 0, 100, 1, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
|
||||
static const char *positions[] = {"Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right", "None"};
|
||||
// Same encoding as in GameSettingsScreen: None is -1.
|
||||
static const char *positions[] = { "None", "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right" };
|
||||
|
||||
list->Add(new ItemHeader(si->T("Notification tests")));
|
||||
list->Add(new Choice(si->T("Error")))->OnClick.Add([&](UI::EventParams &) {
|
||||
@@ -476,8 +476,8 @@ void DeveloperToolsScreen::CreateUITab(UI::LinearLayout *list) {
|
||||
});
|
||||
|
||||
list->Add(new ItemHeader(ac->T("Notifications")));
|
||||
list->Add(new PopupMultiChoice(&g_Config.iNotificationPos, sy->T("Notification screen position"), positions, 0, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()));
|
||||
list->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardTrackerPos, ac->T("Leaderboard tracker"), positions, 0, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()));
|
||||
list->Add(new PopupMultiChoice(&g_Config.iNotificationPos, sy->T("Notification screen position"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()));
|
||||
list->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardTrackerPos, ac->T("Leaderboard tracker"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()));
|
||||
|
||||
#ifdef _DEBUG
|
||||
list->Add(new CheckBox(&pretendIngame_, ac->T("Pretend to be in-game (for testing)")));
|
||||
@@ -770,8 +770,8 @@ void DeveloperToolsScreen::OnMIPSTracerPathChanged(UI::EventParams &e) {
|
||||
BrowseFileType::ANY,
|
||||
[this](std::string_view value, int) {
|
||||
mipsTracer.set_logging_path(std::string(value));
|
||||
MIPSTracerPath_ = value;
|
||||
MIPSTracerPath->SetRightText(MIPSTracerPath_);
|
||||
// The views may have been recreated while the dialog was open, so don't keep a pointer to the path view.
|
||||
RecreateViews();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -53,8 +53,6 @@ private:
|
||||
HasIni hasTexturesIni_ = HasIni::MAYBE;
|
||||
|
||||
bool MIPSTracerEnabled_ = false;
|
||||
std::string MIPSTracerPath_ = "";
|
||||
UI::InfoItem* MIPSTracerPath = nullptr;
|
||||
|
||||
int testSliderValue_ = 0;
|
||||
bool pretendIngame_ = false;
|
||||
|
||||
@@ -268,7 +268,7 @@ void DisplayLayoutScreen::CreateViews() {
|
||||
|
||||
PopupSliderChoiceFloat *aspectRatio = new PopupSliderChoiceFloat(&config.fDisplayAspectRatio, 0.1f, 2.0f, 1.0f, gr->T("Aspect Ratio"), screenManager());
|
||||
rightColumn->Add(aspectRatio);
|
||||
aspectRatio->SetEnabledFunc([config]() {
|
||||
aspectRatio->SetEnabledFunc([&config]() {
|
||||
return !config.bDisplayStretch && !config.bDisplayIntegerScale;
|
||||
});
|
||||
aspectRatio->SetHasDropShadow(false);
|
||||
@@ -322,9 +322,11 @@ void DisplayLayoutScreen::CreateViews() {
|
||||
rightColumn->Add(new Spacer(12.0f));
|
||||
|
||||
Choice *center = new Choice(di->T("Reset"));
|
||||
center->OnClick.Add([&config, portrait](UI::EventParams &) {
|
||||
center->OnClick.Add([this, &config, portrait](UI::EventParams &) {
|
||||
// Hm, not really ideal to have to use strings here.
|
||||
config.ResetToDefault(portrait ? "DisplayLayout.Portrait" : "DisplayLayout.Landscape");
|
||||
// Which checkboxes are shown depends on the rotation.
|
||||
RecreateViews();
|
||||
});
|
||||
rightColumn->Add(center);
|
||||
|
||||
@@ -514,6 +516,7 @@ void PostProcScreen::CreateViews() {
|
||||
std::vector<std::string> items;
|
||||
int selected = -1;
|
||||
const std::string selectedName = id_ >= (int)g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[id_];
|
||||
indexTranslation_.clear();
|
||||
|
||||
for (int i = 0; i < (int)shaders_.size(); i++) {
|
||||
if (!shaders_[i].visible)
|
||||
|
||||
+7
-6
@@ -257,6 +257,11 @@ void GameScreen::RefreshInstalledUpdate() {
|
||||
hasInstalledUpdate_ = FindInstalledGameUpdate(info_->id, &installedUpdate_);
|
||||
}
|
||||
|
||||
// Both panes use isHomebrew_, and which is created first depends on orientation.
|
||||
void GameScreen::BeforeCreateViews() {
|
||||
isHomebrew_ = info_ && info_->region == GameRegion::HOMEBREW;
|
||||
}
|
||||
|
||||
void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
if (!info_) {
|
||||
// Shouldn't happen
|
||||
@@ -579,8 +584,6 @@ void GameScreen::CreateSettingsViews(UI::ViewGroup *rightColumn) {
|
||||
});
|
||||
}
|
||||
|
||||
isHomebrew_ = info_ && info_->region == GameRegion::HOMEBREW;
|
||||
|
||||
const bool packing = GamePacker::IsPacking(gamePath_);
|
||||
if (fileTypeSupportCRC && !isHomebrew_ && !Reporting::HasCRC(gamePath_) && !packing) {
|
||||
rightColumnItems->Add(new Choice(ga->T("Calculate CRC"), ImageID("I_CHECKMARK")))->OnClick.Add([this](UI::EventParams &) {
|
||||
@@ -799,10 +802,8 @@ void GameScreen::OnDeleteConfig(UI::EventParams &e) {
|
||||
void GameScreen::OnGameSettings(UI::EventParams &e) {
|
||||
std::shared_ptr<GameInfo> info_ = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info_ && info_->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
std::string discID = info_->GetParamSFO().GetValueString("DISC_ID");
|
||||
if ((discID.empty() || !info_->disc_total) && gamePath_.FilePathContainsNoCase("PSP/GAME/"))
|
||||
discID = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
screenManager()->push(new GameSettingsScreen(gamePath_, discID, true));
|
||||
// The cache has already replaced the ID of homebrew with a generated one.
|
||||
screenManager()->push(new GameSettingsScreen(gamePath_, info_->id, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
bool GameRemoved() const { return gameRemoved_; }
|
||||
|
||||
protected:
|
||||
void BeforeCreateViews() override;
|
||||
void CreateContentViews(UI::ViewGroup *parent) override;
|
||||
void CreateSettingsViews(UI::ViewGroup *parent) override;
|
||||
void CreateContextMenu(UI::ViewGroup *parent) override;
|
||||
|
||||
+108
-111
@@ -68,7 +68,6 @@
|
||||
#include "UI/AdhocServerScreen.h"
|
||||
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/AndroidContentURI.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
@@ -125,6 +124,13 @@ GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID,
|
||||
g_Config.LoadGameConfig(gameID_);
|
||||
}
|
||||
|
||||
ReadConfigTemporaries();
|
||||
}
|
||||
|
||||
// Also called after restoring defaults, so the old values aren't written back over them.
|
||||
void GameSettingsScreen::ReadConfigTemporaries() {
|
||||
// Written back on exit, so it must be read even if the System tab is never opened.
|
||||
enableReports_ = Reporting::IsEnabled();
|
||||
iAlternateSpeedPercent1_ = g_Config.iFpsLimit1 < 0 ? -1 : (g_Config.iFpsLimit1 * 100) / 60;
|
||||
iAlternateSpeedPercent2_ = g_Config.iFpsLimit2 < 0 ? -1 : (g_Config.iFpsLimit2 * 100) / 60;
|
||||
iAlternateSpeedPercentAnalog_ = (g_Config.iAnalogFpsLimit * 100) / 60;
|
||||
@@ -160,6 +166,9 @@ GameSettingsScreen::~GameSettingsScreen() {
|
||||
void GameSettingsScreen::PreCreateViews() {
|
||||
ReloadAllPostShaderInfo(screenManager()->getDrawContext());
|
||||
ReloadAllThemeInfo();
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
CheckMemstickInstallState();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool UsingHardwareTextureScaling() {
|
||||
@@ -188,30 +197,50 @@ static std::string *GPUDeviceNameSetting() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool PathToVisualUsbPath(Path path, std::string &outPath) {
|
||||
switch (path.Type()) {
|
||||
case PathType::NATIVE:
|
||||
if (path.StartsWith(g_Config.memStickDirectory)) {
|
||||
return g_Config.memStickDirectory.ComputePathTo(path, outPath);
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
// Works out where the memstick is (installed.txt next to the exe means My Documents or a custom
|
||||
// folder), and which of the two checkboxes can be changed.
|
||||
void GameSettingsScreen::CheckMemstickInstallState() {
|
||||
const Path &PPSSPPpath = File::GetExeDirectory();
|
||||
const Path installedFile = PPSSPPpath / "installed.txt";
|
||||
const bool myDocsExists = W32Util::UserDocumentsPath().size() != 0;
|
||||
|
||||
installed_ = File::Exists(installedFile);
|
||||
otherinstalled_ = false;
|
||||
memstickMyDocEnabled_ = !PSP_IsInited();
|
||||
memstickOtherEnabled_ = false;
|
||||
if (!installed_ && myDocsExists) {
|
||||
// Disable the setting if we can't create & delete a file next to the exe.
|
||||
if (File::CreateEmptyFile(PPSSPPpath / "installedTEMP.txt")) {
|
||||
if (!(File::Delete(PPSSPPpath / "installedTEMP.txt")))
|
||||
memstickMyDocEnabled_ = false;
|
||||
else
|
||||
memstickOtherEnabled_ = !PSP_IsInited();
|
||||
} else
|
||||
memstickMyDocEnabled_ = false;
|
||||
} else {
|
||||
if (installed_ && myDocsExists) {
|
||||
FILE *testInstalled = File::OpenCFile(installedFile, "rt");
|
||||
if (testInstalled) {
|
||||
char temp[2048];
|
||||
char *tempStr = fgets(temp, sizeof(temp), testInstalled);
|
||||
// Skip UTF-8 encoding bytes if there are any. There are 3 of them.
|
||||
if (tempStr && strncmp(tempStr, "\xEF\xBB\xBF", 3) == 0) {
|
||||
tempStr += 3;
|
||||
}
|
||||
memstickOtherEnabled_ = !PSP_IsInited();
|
||||
if (tempStr && strlen(tempStr) != 0 && strcmp(tempStr, "\n") != 0) {
|
||||
installed_ = false;
|
||||
otherinstalled_ = true;
|
||||
}
|
||||
fclose(testInstalled);
|
||||
}
|
||||
} else if (!myDocsExists) {
|
||||
memstickMyDocEnabled_ = false;
|
||||
}
|
||||
break;
|
||||
case PathType::CONTENT_URI:
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
{
|
||||
// Try to parse something sensible out of the content URI.
|
||||
AndroidContentURI uri(path.ToString());
|
||||
outPath = uri.RootPath();
|
||||
if (startsWith(outPath, "primary:")) {
|
||||
outPath = "/" + outPath.substr(8);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GameSettingsScreen::CreateTabs() {
|
||||
using namespace UI;
|
||||
@@ -355,8 +384,6 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
msaaChoice->SetChoiceIcon(i, ImageID("I_WARNING"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_Config.iMultiSampleLevel = 0;
|
||||
}
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
@@ -444,15 +471,24 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
altSpeed1->SetFormat("%i%%");
|
||||
altSpeed1->SetZeroLabel(gr->T("Unlimited"));
|
||||
altSpeed1->SetNegativeDisable(gr->T("Disabled"));
|
||||
altSpeed1->OnChange.Add([this](UI::EventParams &) {
|
||||
g_Config.iFpsLimit1 = iAlternateSpeedPercent1_ < 0 ? -1 : (iAlternateSpeedPercent1_ * 60) / 100;
|
||||
});
|
||||
|
||||
PopupSliderChoice *altSpeed2 = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent2_, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed 2", "Alternative speed 2 (in %, 0 = unlimited)"), 5, screenManager(), gr->T("%, 0:unlimited")));
|
||||
altSpeed2->SetFormat("%i%%");
|
||||
altSpeed2->SetZeroLabel(gr->T("Unlimited"));
|
||||
altSpeed2->SetNegativeDisable(gr->T("Disabled"));
|
||||
altSpeed2->OnChange.Add([this](UI::EventParams &) {
|
||||
g_Config.iFpsLimit2 = iAlternateSpeedPercent2_ < 0 ? -1 : (iAlternateSpeedPercent2_ * 60) / 100;
|
||||
});
|
||||
|
||||
if (analogSpeedMapped_) {
|
||||
PopupSliderChoice *analogSpeed = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercentAnalog_, 1, 1000, UI::NO_DEFAULT_INT, gr->T("Analog alternative speed", "Analog alternative speed (in %)"), 5, screenManager(), "%"));
|
||||
altSpeed2->SetFormat("%i%%");
|
||||
analogSpeed->SetFormat("%i%%");
|
||||
analogSpeed->OnChange.Add([this](UI::EventParams &) {
|
||||
g_Config.iAnalogFpsLimit = (iAlternateSpeedPercentAnalog_ * 60) / 100;
|
||||
});
|
||||
}
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Speed Hacks", "Speed Hacks (can cause rendering errors!)")));
|
||||
@@ -964,13 +1000,34 @@ MacAddressChooser::MacAddressChooser(RequesterToken token, Path gamePath, std::s
|
||||
});
|
||||
}
|
||||
|
||||
// The nickname is shown on both the Networking and System tabs.
|
||||
UI::View *GameSettingsScreen::AddNicknameChoice(UI::ViewGroup *parent) {
|
||||
using namespace UI;
|
||||
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
PopupTextInputChoice *nickname = parent->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sNickName, sy->T("Nickname"), "", 32, screenManager()));
|
||||
if (g_Config.sNickName == "PPSSPP") {
|
||||
nickname->SetIconRight(ImageID("I_WARNING"));
|
||||
}
|
||||
nickname->OnChange.Add([this](UI::EventParams &e) {
|
||||
// Copy to infrastructure name if valid and not already set.
|
||||
if (g_Config.sInfrastructureUsername.empty()) {
|
||||
if (g_Config.sNickName == SanitizeString(g_Config.sNickName, StringRestriction::AlphaNumDashUnderscore, 3, 16)) {
|
||||
g_Config.sInfrastructureUsername = g_Config.sNickName;
|
||||
}
|
||||
}
|
||||
// Updates the warning icon, and the username notice on the Networking tab.
|
||||
RecreateViews();
|
||||
});
|
||||
return nickname;
|
||||
}
|
||||
|
||||
void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSettings) {
|
||||
using namespace UI;
|
||||
|
||||
auto n = GetI18NCategory(I18NCat::NETWORKING);
|
||||
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
|
||||
networkingSettings->Add(new ItemHeader(ms->T("Networking")));
|
||||
|
||||
@@ -1028,28 +1085,20 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti
|
||||
relayModePopup->SetEnabled(!PSP_IsInited());
|
||||
networkingSettings->Add(new SettingHint(n->T("PacketRelayHint", "Available on servers that provide 'aemu_postoffice' packet relay, like socom.cc. Disable this for LAN or VPN play. Can be more reliable, but sometimes slower."), relayModePopup));
|
||||
|
||||
PopupTextInputChoice *nickname = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sNickName, sy->T("Nickname"), "", 32, screenManager()));
|
||||
if (g_Config.sNickName == "PPSSPP") {
|
||||
nickname->SetIconRight(ImageID("I_WARNING"));
|
||||
}
|
||||
nickname->OnChange.Add([this](UI::EventParams &e) {
|
||||
RecreateViews();
|
||||
});
|
||||
networkingSettings->Add(new SettingHint(n->T("Try to pick a unique nickname for ad hoc play"), nullptr));
|
||||
View *nicknameChoice = AddNicknameChoice(networkingSettings);
|
||||
networkingSettings->Add(new SettingHint(n->T("Try to pick a unique nickname for ad hoc play"), nicknameChoice));
|
||||
|
||||
networkingSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in ad hoc server")))->OnClick.Add(requestLocalNetwork);
|
||||
|
||||
CheckBox *relay_mode_enet = networkingSettings->Add(new CheckBox(&g_Config.bAdhocUseUdp, n->T("Connect to adhoc server using UDP (ENet) instead of TCP")));
|
||||
relay_mode_enet->SetEnabled(!PSP_IsInited());
|
||||
relay_mode_enet->OnClick.Add([this](UI::EventParams &e) {
|
||||
RecreateViews();
|
||||
});
|
||||
networkingSettings->Add(new SettingHint(n->T("Try switching between TCP/UDP if you suffer frequent adhoc server disconnects. Some network environments favor TCP and some UDP."), nullptr));
|
||||
networkingSettings->Add(new SettingHint(n->T("Try switching between TCP/UDP if you suffer frequent adhoc server disconnects. Some network environments favor TCP and some UDP."), relay_mode_enet));
|
||||
|
||||
CheckBox *relay_mode_enet_pdp_reliable = networkingSettings->Add(new CheckBox(&g_Config.bAdhocRelayModeEnetPdpReliable, n->T("Reliable datagram packet delivery on packet relay in UDP mode")));
|
||||
relay_mode_enet_pdp_reliable->SetEnabled(!PSP_IsInited() && g_Config.bAdhocUseUdp);
|
||||
networkingSettings->Add(new SettingHint(n->T("When disabled, packet loss on datagram adhoc sockets will be exposed to game's netcode. Keep this enabled if you don't know what that means."), nullptr));
|
||||
|
||||
relay_mode_enet_pdp_reliable->SetEnabledFunc([] {
|
||||
return !PSP_IsInited() && g_Config.bAdhocUseUdp;
|
||||
});
|
||||
networkingSettings->Add(new SettingHint(n->T("When disabled, packet loss on datagram adhoc sockets will be exposed to game's netcode. Keep this enabled if you don't know what that means."), relay_mode_enet_pdp_reliable));
|
||||
|
||||
networkingSettings->Add(new ItemHeader(n->T("Infrastructure")));
|
||||
if (g_Config.sInfrastructureUsername.empty()) {
|
||||
@@ -1298,74 +1347,31 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_VR) {
|
||||
memstickDisplay_ = g_Config.memStickDirectory.ToVisualString();
|
||||
auto memstickPath = systemSettings->Add(new ChoiceWithValueDisplay(&memstickDisplay_, sy->T("Memory Stick folder"), I18NCat::NONE));
|
||||
auto memstickPath = systemSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() {
|
||||
return g_Config.memStickDirectory.ToVisualString();
|
||||
}));
|
||||
memstickPath->SetEnabled(!PSP_IsInited());
|
||||
memstickPath->OnClick.Handle(this, &GameSettingsScreen::OnShowMemstickScreen);
|
||||
|
||||
// Display USB path for convenience.
|
||||
std::string usbPath;
|
||||
if (PathToVisualUsbPath(g_Config.memStickDirectory, usbPath)) {
|
||||
if (usbPath.empty()) {
|
||||
// Probably it's just the root. So let's add PSP to make it clear.
|
||||
usbPath = "/PSP";
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
memstickDisplay_ = g_Config.memStickDirectory.ToVisualString();
|
||||
auto memstickPath = systemSettings->Add(new ChoiceWithValueDisplay(&memstickDisplay_, sy->T("Memory Stick folder"), I18NCat::NONE));
|
||||
auto memstickPath = systemSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() {
|
||||
return g_Config.memStickDirectory.ToVisualString();
|
||||
}));
|
||||
memstickPath->SetEnabled(!PSP_IsInited());
|
||||
memstickPath->OnClick.Handle(this, &GameSettingsScreen::OnShowMemstickScreen);
|
||||
#else
|
||||
SavePathInMyDocumentChoice = systemSettings->Add(new CheckBox(&installed_, sy->T("Memory Stick in My Documents")));
|
||||
SavePathInMyDocumentChoice->SetEnabled(!PSP_IsInited());
|
||||
SavePathInMyDocumentChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickMyDoc);
|
||||
SavePathInOtherChoice = systemSettings->Add(new CheckBox(&otherinstalled_, sy->T("Memory Stick in installed.txt")));
|
||||
SavePathInOtherChoice->SetEnabled(false);
|
||||
SavePathInOtherChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickOther);
|
||||
const bool myDocsExists = W32Util::UserDocumentsPath().size() != 0;
|
||||
CheckBox *myDocsChoice = systemSettings->Add(new CheckBox(&installed_, sy->T("Memory Stick in My Documents")));
|
||||
myDocsChoice->SetEnabledPtr(&memstickMyDocEnabled_);
|
||||
myDocsChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickMyDoc);
|
||||
CheckBox *otherChoice = systemSettings->Add(new CheckBox(&otherinstalled_, sy->T("Memory Stick in installed.txt")));
|
||||
otherChoice->SetEnabledPtr(&memstickOtherEnabled_);
|
||||
otherChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickOther);
|
||||
|
||||
if (!System_GetPropertyBool(SYSPROP_CAN_GET_FREE_SPACE_FAST)) {
|
||||
// It might be slow, so use an option.
|
||||
systemSettings->Add(new CheckBox(&g_Config.bReportAccurateFreeStorageSpace, sy->T("Report free storage space accurately")));
|
||||
}
|
||||
|
||||
const Path &PPSSPPpath = File::GetExeDirectory();
|
||||
const Path installedFile = PPSSPPpath / "installed.txt";
|
||||
installed_ = File::Exists(installedFile);
|
||||
otherinstalled_ = false;
|
||||
if (!installed_ && myDocsExists) {
|
||||
if (File::CreateEmptyFile(PPSSPPpath / "installedTEMP.txt")) {
|
||||
// Disable the setting whether cannot create & delete file
|
||||
if (!(File::Delete(PPSSPPpath / "installedTEMP.txt")))
|
||||
SavePathInMyDocumentChoice->SetEnabled(false);
|
||||
else
|
||||
SavePathInOtherChoice->SetEnabled(!PSP_IsInited());
|
||||
} else
|
||||
SavePathInMyDocumentChoice->SetEnabled(false);
|
||||
} else {
|
||||
if (installed_ && myDocsExists) {
|
||||
FILE *testInstalled = File::OpenCFile(installedFile, "rt");
|
||||
if (testInstalled) {
|
||||
char temp[2048];
|
||||
char *tempStr = fgets(temp, sizeof(temp), testInstalled);
|
||||
// Skip UTF-8 encoding bytes if there are any. There are 3 of them.
|
||||
if (tempStr && strncmp(tempStr, "\xEF\xBB\xBF", 3) == 0) {
|
||||
tempStr += 3;
|
||||
}
|
||||
SavePathInOtherChoice->SetEnabled(!PSP_IsInited());
|
||||
if (tempStr && strlen(tempStr) != 0 && strcmp(tempStr, "\n") != 0) {
|
||||
installed_ = false;
|
||||
otherinstalled_ = true;
|
||||
}
|
||||
fclose(testInstalled);
|
||||
}
|
||||
} else if (!myDocsExists) {
|
||||
SavePathInMyDocumentChoice->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
systemSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted")));
|
||||
@@ -1373,9 +1379,6 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
|
||||
sizeChoice->SetFormat("%d GB");
|
||||
|
||||
systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team")));
|
||||
if (!enableReportsSet_)
|
||||
enableReports_ = Reporting::IsEnabled();
|
||||
enableReportsSet_ = true;
|
||||
CheckBox *enableReportsCheckbox;
|
||||
enableReportsCheckbox = new CheckBox(&enableReports_, sy->T("Enable Compatibility Server Reports"));
|
||||
enableReportsCheckbox->SetEnabledFunc([]() { return Reporting::IsSupported(); });
|
||||
@@ -1479,14 +1482,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iLanguage, psps->T("Game language"), defaultLanguages, -1, ARRAY_SIZE(defaultLanguages), I18NCat::PSPSETTINGS, screenManager()));
|
||||
static const char *models[] = { "PSP-1000", "PSP-2000/3000" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited());
|
||||
systemSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sNickName, sy->T("Nickname"), "", 32, screenManager()))->OnChange.Add([](UI::EventParams &e) {
|
||||
// Copy to infrastructure name if valid and not already set.
|
||||
if (g_Config.sInfrastructureUsername.empty()) {
|
||||
if (g_Config.sNickName == SanitizeString(g_Config.sNickName, StringRestriction::AlphaNumDashUnderscore, 3, 16)) {
|
||||
g_Config.sInfrastructureUsername = g_Config.sNickName;
|
||||
}
|
||||
}
|
||||
});
|
||||
UI::View *nicknameChoice = AddNicknameChoice(systemSettings);
|
||||
systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, sy->T("Daylight savings")));
|
||||
static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, sy->T("Date Format"), dateFormat, 0, ARRAY_SIZE(dateFormat), I18NCat::SYSTEM, screenManager()));
|
||||
@@ -1607,7 +1603,7 @@ void GameSettingsScreen::OnMemoryStickOther(UI::EventParams &e) {
|
||||
}
|
||||
else {
|
||||
File::Delete(PPSSPPpath / "installed.txt");
|
||||
SavePathInMyDocumentChoice->SetEnabled(true);
|
||||
memstickMyDocEnabled_ = true;
|
||||
otherinstalled_ = false;
|
||||
installed_ = false;
|
||||
g_Config.memStickDirectory = PPSSPPpath / "memstick";
|
||||
@@ -1697,9 +1693,9 @@ void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult resul
|
||||
}
|
||||
|
||||
if (result == DialogResult::DR_OK) {
|
||||
g_Config.iFpsLimit1 = iAlternateSpeedPercent1_ < 0 ? -1 : (iAlternateSpeedPercent1_ * 60) / 100;
|
||||
g_Config.iFpsLimit2 = iAlternateSpeedPercent2_ < 0 ? -1 : (iAlternateSpeedPercent2_ * 60) / 100;
|
||||
g_Config.iAnalogFpsLimit = (iAlternateSpeedPercentAnalog_ * 60) / 100;
|
||||
if (equals(dialog->tag(), "RestoreSettingsScreen")) {
|
||||
ReadConfigTemporaries();
|
||||
}
|
||||
recreate = true;
|
||||
}
|
||||
|
||||
@@ -1823,6 +1819,7 @@ void GameSettingsScreen::OnAudioDevice(UI::EventParams &e) {
|
||||
void GameSettingsScreen::CallbackRestoreDefaults(bool yes) {
|
||||
if (yes) {
|
||||
g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS);
|
||||
ReadConfigTemporaries();
|
||||
}
|
||||
System_Notify(SystemNotification::UI);
|
||||
}
|
||||
|
||||
@@ -57,18 +57,18 @@ private:
|
||||
void CreateToolsSettings(UI::ViewGroup *tools);
|
||||
void CreateSystemSettings(UI::ViewGroup *systemSettings);
|
||||
void CreateVRSettings(UI::ViewGroup *vrSettings);
|
||||
UI::View *AddNicknameChoice(UI::ViewGroup *parent);
|
||||
|
||||
std::string gameID_;
|
||||
#ifdef _WIN32
|
||||
UI::CheckBox *SavePathInMyDocumentChoice = nullptr;
|
||||
UI::CheckBox *SavePathInOtherChoice = nullptr;
|
||||
// Used to enable/disable the above two options.
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
void CheckMemstickInstallState();
|
||||
|
||||
bool installed_ = false;
|
||||
bool otherinstalled_ = false;
|
||||
bool memstickMyDocEnabled_ = false;
|
||||
bool memstickOtherEnabled_ = false;
|
||||
#endif
|
||||
|
||||
std::string memstickDisplay_;
|
||||
|
||||
// Global settings handlers
|
||||
void OnChangeBackground(UI::EventParams &e);
|
||||
void OnRestoreDefaultSettings(UI::EventParams &e);
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
void OnSustainedPerformanceModeChange(UI::EventParams &e);
|
||||
|
||||
void TriggerRestartOrDo(std::function<void()> callback);
|
||||
void ReadConfigTemporaries();
|
||||
|
||||
// Temporaries to convert setting types, cache enabled, etc.
|
||||
int iAlternateSpeedPercent1_ = 0;
|
||||
@@ -93,7 +94,6 @@ private:
|
||||
int iAlternateSpeedPercentAnalog_ = 0;
|
||||
int prevInflightFrames_ = -1;
|
||||
bool enableReports_ = false;
|
||||
bool enableReportsSet_ = false;
|
||||
bool analogSpeedMapped_ = false;
|
||||
|
||||
// edit the game-specific settings and restore the global settings after exiting
|
||||
|
||||
+6
-4
@@ -95,11 +95,12 @@ GamepadComponent::GamepadComponent(std::string_view key, UI::LayoutParams *layou
|
||||
static void rotateTouchHelper(float &dx, float &dy) {
|
||||
// rotates dx and dy depending on rotation count
|
||||
// modified from controlmapper.cpp
|
||||
if (!g_Config.displayLayoutLandscape.bRotateControlsWithScreen) {
|
||||
const DisplayLayoutConfig &layout = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
|
||||
if (!layout.bRotateControlsWithScreen) {
|
||||
return;
|
||||
}
|
||||
int rotations = 0;
|
||||
switch (g_Config.displayLayoutLandscape.iInternalScreenRotation) {
|
||||
switch (layout.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL180: rotations = 2; break;
|
||||
case ROTATION_LOCKED_VERTICAL: rotations = 3; break;
|
||||
case ROTATION_LOCKED_VERTICAL180: rotations = 1; break;
|
||||
@@ -459,8 +460,9 @@ void PSPDpad::Draw(UIContext &dc) {
|
||||
return;
|
||||
// from control mapper.cpp
|
||||
int rotations = 0;
|
||||
if (g_Config.displayLayoutLandscape.bRotateControlsWithScreen) {
|
||||
switch (g_Config.displayLayoutLandscape.iInternalScreenRotation) {
|
||||
const DisplayLayoutConfig &layout = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
|
||||
if (layout.bRotateControlsWithScreen) {
|
||||
switch (layout.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL180: rotations = 2; break;
|
||||
case ROTATION_LOCKED_VERTICAL: rotations = 3; break;
|
||||
case ROTATION_LOCKED_VERTICAL180: rotations = 1; break;
|
||||
|
||||
+7
-13
@@ -78,11 +78,6 @@ void InstallZipScreen::CreateSettingsViews(UI::ViewGroup *parent) {
|
||||
std::string shortFilename = zipPath_.GetFilename();
|
||||
|
||||
bool showDeleteCheckbox = false;
|
||||
returnToHomebrew_ = false;
|
||||
installChoice_ = nullptr;
|
||||
playChoice_ = nullptr;
|
||||
doneView_ = nullptr;
|
||||
existingSaveView_ = nullptr;
|
||||
|
||||
std::vector<Path> destOptions;
|
||||
|
||||
@@ -144,12 +139,6 @@ void InstallZipScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
|
||||
std::string shortFilename = zipPath_.GetFilename();
|
||||
|
||||
returnToHomebrew_ = false;
|
||||
installChoice_ = nullptr;
|
||||
playChoice_ = nullptr;
|
||||
doneView_ = nullptr;
|
||||
existingSaveView_ = nullptr;
|
||||
overwriteWarning_ = nullptr;
|
||||
destFolders_.clear();
|
||||
|
||||
std::vector<Path> destOptions;
|
||||
@@ -320,8 +309,13 @@ void InstallZipScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
}
|
||||
|
||||
void InstallZipScreen::BeforeCreateViews() {
|
||||
File::FileInfo fileInfo;
|
||||
File::GetFileInfo(zipPath_, &fileInfo);
|
||||
// The two panes are created in a different order depending on orientation, so neither can reset the other's views.
|
||||
returnToHomebrew_ = false;
|
||||
installChoice_ = nullptr;
|
||||
playChoice_ = nullptr;
|
||||
doneView_ = nullptr;
|
||||
existingSaveView_ = nullptr;
|
||||
overwriteWarning_ = nullptr;
|
||||
}
|
||||
|
||||
bool InstallZipScreen::key(const KeyInput &key) {
|
||||
|
||||
@@ -442,6 +442,9 @@ void MemStickScreen::Browse(UI::EventParams ¶ms) {
|
||||
nw->T("Error"), // from the networking category of strings.
|
||||
ms->T("MissingFileBrowserError", "This device is missing a file/folder browser. If you disabled the 'Files' app, please enable it and try again."),
|
||||
di->T("More info"), di->T("Cancel"), [](bool ok) {
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/troubleshooting/cant-pick-folder/");
|
||||
}
|
||||
));
|
||||
@@ -450,7 +453,8 @@ void MemStickScreen::Browse(UI::EventParams ¶ms) {
|
||||
}
|
||||
|
||||
void MemStickScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
if (result == DialogResult::DR_OK) {
|
||||
// Other popups, like the missing file browser error, also finish with DR_OK.
|
||||
if (result == DialogResult::DR_OK && !strcmp(dialog->tag(), "ConfirmMemstickMove")) {
|
||||
INFO_LOG(Log::System, "Confirmation screen done - moving on.");
|
||||
// There's a screen manager bug if we call TriggerFinish directly.
|
||||
// Can't be bothered right now, so we pick this up in update().
|
||||
@@ -658,6 +662,7 @@ void ConfirmMemstickMoveScreen::FinishFolderMove() {
|
||||
if (!SwitchMemstickFolderTo(newMemstickFolder_)) {
|
||||
// TODO: More precise errors.
|
||||
error_ = ms->T("That folder doesn't work as a memstick folder.");
|
||||
RecreateViews();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -133,8 +133,10 @@ protected:
|
||||
}
|
||||
|
||||
grid->Add(new Choice(pa->T("Save State"), ImageID("I_FILE_SAVE")))->OnClick.Handle(this, &ScreenshotViewScreen::OnSaveState);
|
||||
// We can unconditionally show the load state button, because you can only pop this dialog up if a state exists.
|
||||
grid->Add(new Choice(pa->T("Load State"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &ScreenshotViewScreen::OnLoadState);
|
||||
// You can only pop this dialog up if a state exists. Hardcore mode doesn't allow loading, like in SaveSlotView.
|
||||
if (!Achievements::HardcoreModeActive()) {
|
||||
grid->Add(new Choice(pa->T("Load State"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &ScreenshotViewScreen::OnLoadState);
|
||||
}
|
||||
grid->Add(new Choice(di->T("Delete"), ImageID("I_TRASHCAN")))->OnClick.Handle(this, &ScreenshotViewScreen::OnDeleteState);
|
||||
if (undoButton) {
|
||||
grid->Add(undoButton)->OnClick.Handle(this, &ScreenshotViewScreen::OnUndoState);
|
||||
|
||||
@@ -290,6 +290,11 @@ void RetroAchievementsLeaderboardScreen::FetchEntries() {
|
||||
void RetroAchievementsLeaderboardScreen::CreateTabs() {
|
||||
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
|
||||
const rc_client_leaderboard_t *leaderboard = rc_client_get_leaderboard_info(Achievements::GetClient(), leaderboardID_);
|
||||
if (!leaderboard) {
|
||||
// The game was unloaded. There has to be a tab, though.
|
||||
AddTab("AchievementsLeaderboard", "", [](UI::LinearLayout *parent) {});
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace UI;
|
||||
AddTab("AchievementsLeaderboard", leaderboard->title, [this, leaderboard](UI::LinearLayout *parent) {
|
||||
|
||||
+7
-1
@@ -354,7 +354,12 @@ void ProductView::OnLaunchClick(UI::EventParams &e) {
|
||||
|
||||
StoreScreen::StoreScreen() : UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::Default) {
|
||||
lang_ = g_Config.sLanguageIni;
|
||||
StartListingDownload();
|
||||
}
|
||||
|
||||
void StoreScreen::StartListingDownload() {
|
||||
loading_ = true;
|
||||
connectionError_ = false;
|
||||
|
||||
std::string indexPath = StoreBaseUrl() + "index.json";
|
||||
const char *acceptMime = "application/json, */*; q=0.8";
|
||||
@@ -480,7 +485,7 @@ void StoreScreen::CreateDialogViews(UI::ViewGroup *parent) {
|
||||
|
||||
// TODO: Similar apps, etc etc
|
||||
productPanel_ = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(0.5f));
|
||||
leftScroll->SetTag("StoreMainProduct");
|
||||
productPanel_->SetTag("StoreMainProduct");
|
||||
content->Add(productPanel_);
|
||||
|
||||
ProductItemView *selectedItem = GetSelectedItem();
|
||||
@@ -532,6 +537,7 @@ void StoreScreen::OnGameLaunch(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
void StoreScreen::OnRetry(UI::EventParams &e) {
|
||||
StartListingDownload();
|
||||
RecreateViews();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ protected:
|
||||
|
||||
std::string_view GetTitle() const override;
|
||||
private:
|
||||
void StartListingDownload();
|
||||
void ParseListing(const std::string &json);
|
||||
ProductItemView *GetSelectedItem();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ void SystemInfoScreen::update() {
|
||||
// TODO: How can we de-duplicate this and SystemInfoScreen::CreateTabs?
|
||||
static void CopySummaryToClipboard(Draw::DrawContext *draw) {
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto si = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
|
||||
char *summary = new char[100000];
|
||||
StringWriter w(summary, 100000);
|
||||
@@ -145,7 +145,7 @@ void SystemInfoScreen::CreateDeviceInfoTab(UI::LinearLayout *deviceSpecs) {
|
||||
UI::CollapsibleSection *cpuInfo = deviceSpecs->Add(new UI::CollapsibleSection(si->T("CPU Information")));
|
||||
|
||||
// Don't bother showing the CPU name if we don't have one.
|
||||
if (equals(cpu_info.brand_string, "Unknown")) {
|
||||
if (!equals(cpu_info.brand_string, "Unknown")) {
|
||||
cpuInfo->Add(new InfoItem(si->T("CPU Name"), cpu_info.brand_string));
|
||||
}
|
||||
|
||||
@@ -393,7 +393,8 @@ void SystemInfoScreen::CreateBuildConfigTab(UI::LinearLayout *buildConfig) {
|
||||
}
|
||||
System_CopyStringToClipboard(buildConfigStr.c_str());
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
g_OSD.Show(OSDType::MESSAGE_INFO, ApplySafeSubstitutions(di->T("Copied to clipboard: %1"), di->T("Build Configuration")), 0.0f, "copyToClip");
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
g_OSD.Show(OSDType::MESSAGE_INFO, ApplySafeSubstitutions(di->T("Copied to clipboard: %1"), si->T("Build Configuration")), 0.0f, "copyToClip");
|
||||
});
|
||||
|
||||
for (auto &item : buildConfigItems) {
|
||||
|
||||
@@ -114,11 +114,6 @@ void UITabbedBaseDialogScreen::CreateViews() {
|
||||
|
||||
// Let the subclass create its tabs.
|
||||
CreateTabs();
|
||||
if (currentTabSetting_) {
|
||||
tabHolder_->SetInitialTab(*currentTabSetting_);
|
||||
} else {
|
||||
tabHolder_->EnsureTab(tabHolder_->GetCurrentTab());
|
||||
}
|
||||
|
||||
tabHolder_->OnChangeTab.Add([this](UI::EventParams &e) {
|
||||
if (currentTabSetting_) {
|
||||
@@ -151,6 +146,13 @@ void UITabbedBaseDialogScreen::CreateViews() {
|
||||
}
|
||||
}
|
||||
|
||||
// After the search tab, which the saved tab can be.
|
||||
if (currentTabSetting_) {
|
||||
tabHolder_->SetInitialTab(*currentTabSetting_);
|
||||
} else {
|
||||
tabHolder_->EnsureTab(tabHolder_->GetCurrentTab());
|
||||
}
|
||||
|
||||
// Need to handle recreates, both important and accidental ones.
|
||||
if (!searchFilter_.empty()) {
|
||||
ApplySearchFilter();
|
||||
|
||||
Reference in new issue
Block a user