Merge pull request #22933 from hrydgard/more-ui-work

Fix a bunch of UI bugs
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-11-04 19:12:03 +01:00
commit 9366aa7dc2
29 files changed
+216 -136

No files matched your search

+13
View File
@@ -174,3 +174,16 @@ bool HitAnyAsserts() {
void ResetHitAnyAsserts() {
hitAnyAsserts = false;
}
void ShowMessageDialog(const char *title, const char *message, bool isError) {
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
const int msgBoxStyle = MB_ICONINFORMATION | MB_OK;
std::string text = message;
const char *caption = title;
std::wstring wcaption = ConvertUTF8ToWString(std::string(caption));
MessageBox(g_dialogParent, ConvertUTF8ToWString(text).c_str(), wcaption.c_str(), msgBoxStyle);
#else
// Just printf.
fprintf(stderr, "%s: %s\n", title, message);
#endif
}
+1
View File
@@ -154,6 +154,7 @@ void SetAssertCancelCallback(AssertNoCallbackFunc callback, void *userdata);
void SetCleanExitOnAssert();
void BreakIntoPSPDebugger(const char *reason = "(userbreak)");
void SetAssertDialogParent(void *handle); // HWND on windows. Ignored on other platforms.
void ShowMessageDialog(const char *title, const char *message, bool isError = false);
#if defined(__ANDROID__)
// Tricky macro to get the basename, that also works if *built* on Win32.
+2 -1
View File
@@ -21,7 +21,8 @@ ENUM_CLASS_BITOPS(FontStyleFlags);
enum class FontFamily : u8 {
SansSerif = 1,
Fixed = 2,
SansSerifWide = 2,
Fixed = 3,
};
struct FontStyle {
+4
View File
@@ -400,6 +400,10 @@ static const FontDesc g_fontDescs[] = {
{FontFamily::SansSerif, FontStyleFlags::Bold, "Roboto Condensed", "Roboto_Condensed-Bold"},
{FontFamily::SansSerif, FontStyleFlags::Italic, "Roboto Condensed", "Roboto_Condensed-Italic"},
{FontFamily::SansSerif, FontStyleFlags::Light, "Roboto Condensed", "Roboto_Condensed-Light"},
{FontFamily::SansSerifWide, FontStyleFlags::Default, "Roboto SemiCondensed", "Roboto_SemiCondensed-Regular"},
{FontFamily::SansSerifWide, FontStyleFlags::Bold, "Roboto SemiCondensed", "Roboto_SemiCondensed-Bold"},
{FontFamily::SansSerifWide, FontStyleFlags::Italic, "Roboto SemiCondensed", "Roboto_SemiCondensed-Italic"},
{FontFamily::SansSerifWide, FontStyleFlags::Light, "Roboto SemiCondensed", "Roboto_SemiCondensed-Light"},
{FontFamily::Fixed, FontStyleFlags::Default, "Inconsolata", "Inconsolata-Regular"},
};
+12 -17
View File
@@ -153,6 +153,7 @@ void PopupScreen::CreateViews() {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
// This places the actual popup in the center of the screen.
AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
anchor->Overflow(false);
root_ = anchor;
@@ -184,16 +185,16 @@ void PopupScreen::CreateViews() {
(layoutBounds.w - RootMargins().horiz()) * 0.5, y, NONE, NONE, vCentering | Centering::Horizontal);
}
box_ = new LinearLayout(ORIENT_VERTICAL, anchorParams);
// Box is the actual popup shape.
box_ = root_->Add(new LinearLayout(ORIENT_VERTICAL, anchorParams));
root_->Add(box_);
box_->SetBG(dc.GetTheme().popupStyle.background);
box_->SetHasDropShadow(hasDropShadow_);
box_->SetRadiusFactor(1.44f);
// Since we scale a bit, make the dropshadow bleed past the edges.
box_->SetDropShadowExpand(std::max(g_display.dp_xres, g_display.dp_yres));
box_->SetSpacing(0.0f);
box_->SetPadding(Margins(8));
box_->SetSpacing(12.0f);
box_->SetPadding(Margins(12));
if (!title_.empty()) {
View *title = new PopupHeader(title_);
@@ -214,21 +215,19 @@ void PopupScreen::CreateViews() {
if (ShowButtons() && !button1_.empty()) {
// And the two buttons at the bottom.
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT));
buttonRow->SetSpacing(0);
Margins buttonMargins(5, 5);
buttonRow->SetSpacing(8);
// Adjust button order to the platform default.
if (System_GetPropertyBool(SYSPROP_OK_BUTTON_LEFT)) {
defaultButton_ = buttonRow->Add(new Choice(button1_, button1Image_, new LinearLayoutParams(1.0f, buttonMargins)));
defaultButton_ = buttonRow->Add(new Choice(button1_, button1Image_, new LinearLayoutParams(1.0f)));
defaultButton_->OnClick.Handle<UIScreen>(this, &UIScreen::OnOK);
if (!button2_.empty()) {
buttonRow->Add(new Choice(button2_, button2Image_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnCancel);
buttonRow->Add(new Choice(button2_, button2Image_, new LinearLayoutParams(1.0f)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnCancel);
}
} else {
if (!button2_.empty()) {
buttonRow->Add(new Choice(button2_, button2Image_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnCancel);
buttonRow->Add(new Choice(button2_, button2Image_, new LinearLayoutParams(1.0f)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnCancel);
}
defaultButton_ = buttonRow->Add(new Choice(button1_, button1Image_, new LinearLayoutParams(1.0f, buttonMargins)));
defaultButton_ = buttonRow->Add(new Choice(button1_, button1Image_, new LinearLayoutParams(1.0f)));
defaultButton_->OnClick.Handle<UIScreen>(this, &UIScreen::OnOK);
}
@@ -256,12 +255,8 @@ void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
}
void MessagePopupScreen::OnCompleted(DialogResult result) {
if (result == DR_OK) {
if (callback_)
callback_(true);
} else {
if (callback_)
callback_(false);
if (callback_) {
callback_(result == DR_OK);
}
}
+53 -38
View File
@@ -641,6 +641,59 @@ std::string ItemHeader::DescribeText() const {
return ApplySafeSubstitutions(u->T("%1 heading"), text_);
}
PopupHeader::PopupHeader(std::string_view text, LayoutParams *layoutParams)
: Item(layoutParams), text_(text) {
layoutParams_->width = FILL_PARENT;
layoutParams_->height = 44;
}
void PopupHeader::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const {
float availWidth = layoutParams_->width;
if (availWidth < 0) {
// If there's no size, let's grow as big as we want.
availWidth = horiz.size == 0 ? MAX_ITEM_SIZE : horiz.size;
}
ApplyBoundBySpec(availWidth, horiz);
dc.MeasureTextRect(dc.GetTheme().uiFontBig, 1.0f, 1.0f, text_, availWidth, &w, &h, ALIGN_LEFT | ALIGN_VCENTER);
}
void PopupHeader::Draw(UIContext &dc) {
const float availableWidth = bounds_.w;
float tw, th;
dc.SetFontStyle(dc.GetTheme().uiFontBig);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text_, &tw, &th, 0);
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
float tx = 0;
if (availableWidth < tw) {
float overageRatio = 1.5f * availableWidth * 1.0f / tw;
tx -= (1.0f + sin(time_now_d() * overageRatio)) * sineWidth;
Bounds tb = bounds_;
tb.x = bounds_.x;
tb.w = bounds_.w;
dc.PushScissor(tb);
}
// Header background
dc.FillRoundRect(dc.GetTheme().popupTitleStyle.background, bounds_, dc.GetTheme().choiceRoundRadius, roundCorners_);
// Header title text
dc.DrawText(text_, bounds_.x + tx, bounds_.centerY(), dc.GetTheme().popupTitleStyle.fgColor, ALIGN_LEFT | ALIGN_VCENTER);
// Underline. Skipping it with the new style.
// dc.Draw()->DrawImageCenterTexel(dc.GetTheme().whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.GetTheme().popupTitleStyle.fgColor);
if (availableWidth < tw) {
dc.PopScissor();
}
}
std::string PopupHeader::DescribeText() const {
auto u = GetI18NCategory(I18NCat::UI_ELEMENTS);
return ApplySafeSubstitutions(u->T("%1 heading"), text_);
}
CollapsibleHeader::CollapsibleHeader(bool *toggle, std::string_view text, LayoutParams *layoutParams)
: CheckBox(toggle, text, "", layoutParams) {
layoutParams_->width = FILL_PARENT;
@@ -713,44 +766,6 @@ void BorderView::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec hor
h = (borderFlags_ & BORDER_HORIZ) != 0 ? bounds.h : 0;
}
void PopupHeader::Draw(UIContext &dc) {
const float paddingHorizontal = 12;
const float availableWidth = bounds_.w - paddingHorizontal * 2;
float tw, th;
dc.SetFontStyle(dc.GetTheme().uiFont);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text_, &tw, &th, 0);
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
float tx = paddingHorizontal;
if (availableWidth < tw) {
float overageRatio = 1.5f * availableWidth * 1.0f / tw;
tx -= (1.0f + sin(time_now_d() * overageRatio)) * sineWidth;
Bounds tb = bounds_;
tb.x = bounds_.x + paddingHorizontal;
tb.w = bounds_.w - paddingHorizontal * 2;
dc.PushScissor(tb);
}
// Header background
dc.FillRoundRect(dc.GetTheme().popupTitleStyle.background, bounds_, dc.GetTheme().choiceRoundRadius, roundCorners_);
// Header title text
dc.DrawText(text_, bounds_.x + tx, bounds_.centerY(), dc.GetTheme().popupTitleStyle.fgColor, ALIGN_LEFT | ALIGN_VCENTER);
// Underline. Skipping it with the new style.
// dc.Draw()->DrawImageCenterTexel(dc.GetTheme().whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.GetTheme().popupTitleStyle.fgColor);
if (availableWidth < tw) {
dc.PopScissor();
}
}
std::string PopupHeader::DescribeText() const {
auto u = GetI18NCategory(I18NCat::UI_ELEMENTS);
return ApplySafeSubstitutions(u->T("%1 heading"), text_);
}
void CheckBox::Toggle() {
if (toggle_) {
*toggle_ = !(*toggle_);
+2 -5
View File
@@ -939,12 +939,9 @@ private:
class PopupHeader : public Item {
public:
PopupHeader(std::string_view text, LayoutParams *layoutParams = 0)
: Item(layoutParams), text_(text) {
layoutParams_->width = FILL_PARENT;
layoutParams_->height = 64;
}
PopupHeader(std::string_view text, LayoutParams *layoutParams = 0);
void Draw(UIContext &dc) override;
void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override;
std::string DescribeText() const override;
private:
+8 -1
View File
@@ -885,7 +885,14 @@ ChoiceGroup::ChoiceGroup(std::string_view title, LayoutParams *layoutParams)
ChoiceGroupList::ChoiceGroupList(LayoutParams *layoutParams)
: LinearLayoutList(ORIENT_VERTICAL, layoutParams ? layoutParams : new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)) {
SetPadding(Margins(12, 12, 8, 12));
SetPadding(Margins(12, 12, 12, 12));
SetSpacing(24.0f);
}
PopupChoiceGroupList::PopupChoiceGroupList(LayoutParams *layoutParams)
: LinearLayoutList(ORIENT_VERTICAL, layoutParams ? layoutParams : new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)) {
// Padding is already present in the popup itself. Just add a little more.
SetPadding(Margins(0));
SetSpacing(24.0f);
}
+7
View File
@@ -276,6 +276,13 @@ public:
ChoiceGroupList(LayoutParams *layoutParams = nullptr);
};
// A vertical list that spaces out the ChoiceGroups in it and keeps them off its edges.
// This one is adjusted for popups (i.e. smaller margins and spacing).
class PopupChoiceGroupList : public LinearLayoutList {
public:
PopupChoiceGroupList(LayoutParams *layoutParams = nullptr);
};
// GridLayout is a little different from the Android layout. This one has fixed size
// rows and columns, filled row by row. Items are not allowed to deviate from the set sizes.
struct GridLayoutSettings {
+11
View File
@@ -557,6 +557,17 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C
}
} else if (startsWith(argv[i], "--")) {
PRINT_STDERR("Error: Unknown parameter: %s\n", argv[i]);
if (mode == CmdLineMode::Application) {
// Ignore bad parameters - but inform the user in the Windows debug output at least.
OutputDebugStringUTF8("Warning: Unknown parameter: ");
OutputDebugStringUTF8(argv[i]);
OutputDebugStringUTF8("\n");
std::string msg = StringFromFormat("Unknown command line parameter: %s\n\nProceeding anyway.", argv[i]);
ShowMessageDialog("Unknown Parameter", msg.c_str(), true);
return CommandLineParseResult::Continue;
}
return CommandLineParseResult::Error;
}
// To the next argument.
+2
View File
@@ -342,6 +342,8 @@ void GameButton::Draw(UIContext &dc) {
dc.PopScissor();
}
} else {
// The two list view modes, compat and large.
Bounds bounds = bounds_;
std::string_view rightText = g_Config.bShowIDOnGameIcon ? std::string_view(id_version) : std::string_view();
+14 -5
View File
@@ -396,17 +396,26 @@ bool GameInfo::DeleteAllSaveData() const {
void GameInfo::ParseParamSFO(IdentifiedFileType type) {
title = paramSFO.GetValueString("TITLE");
if (type != IdentifiedFileType::PSP_UMD_VIDEO_ISO) {
switch (type) {
case IdentifiedFileType::PSP_UMD_VIDEO_ISO:
id.clear();
id_version.clear();
region = GameRegion::UNKNOWN;
break;
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
// Sniff the ID from the folder name.
id = paramSFO.GetValueString("SAVEDATA_DIRECTORY").substr(0, 9);
id_version = id;
region = DetectGameRegionFromID(id);
break;
default:
id = paramSFO.GetValueString("DISC_ID");
id_version = id + "_" + paramSFO.GetValueString("DISC_VERSION");
disc_total = paramSFO.GetValueInt("DISC_TOTAL");
disc_number = paramSFO.GetValueInt("DISC_NUMBER");
// region = paramSFO.GetValueInt("REGION"); // Always seems to be 32768?
region = DetectGameRegionFromID(id);
} else {
id.clear();
id_version.clear();
region = GameRegion::UNKNOWN;
break;
}
}
+1 -1
View File
@@ -135,7 +135,7 @@ static const PageDef pageDefs[] = {
{ "GameSettingsNetworking", "Networking", "I_WIFI", "network", I18NCat::NETWORKING, &BuildNetworkingSettings },
{ "GameSettingsTools", "Tools", "I_TOOLS", "tools", I18NCat::MAINSETTINGS, &BuildToolsSettings },
{ "GameSettingsSystem", "System", "I_PSP", "system", I18NCat::SYSTEM, nullptr, &BuildSystemSettings },
{ "GameSettingsVR", "VR", nullptr, nullptr, I18NCat::VR, &BuildVRSettings },
{ "GameSettingsVR", "VR", "I_VR", nullptr, I18NCat::VR, &BuildVRSettings},
};
void GameSettingsScreen::CreateTabs() {
+6 -6
View File
@@ -1949,7 +1949,7 @@ static const char *VoiceTypeToString(VoiceType type) {
}
}
void DrawSasAudio(ImConfig &cfg) {
static void DrawSasAudio(ImConfig &cfg, ImControl &control) {
if (!ImGui::Begin("sasAudio", &cfg.sasAudioOpen)) {
ImGui::End();
return;
@@ -2012,8 +2012,8 @@ void DrawSasAudio(ImConfig &cfg) {
ImGui::TableNextColumn();
switch (voice.type) {
case VOICETYPE_OFF: ImGui::TextUnformatted("(off)"); break;
case VOICETYPE_VAG: ImGui::Text("%08x", voice.vagAddr); break;
case VOICETYPE_PCM: ImGui::Text("%08x", voice.pcmAddr); break;
case VOICETYPE_VAG: ImClickableValue("vagaddr", voice.vagAddr, control, ImCmd::SHOW_IN_MEMORY_VIEWER); break;
case VOICETYPE_PCM: ImClickableValue("pcmaddr", voice.pcmAddr, control, ImCmd::SHOW_IN_MEMORY_VIEWER); break;
case VOICETYPE_ATRAC3: ImGui::Text("atrac: %d", voice.atrac3.AtracID()); break;
default:
ImGui::TextUnformatted("N/A");
@@ -2022,8 +2022,8 @@ void DrawSasAudio(ImConfig &cfg) {
ImGui::TableNextColumn();
switch (voice.type) {
case VOICETYPE_OFF: ImGui::TextUnformatted("(off)"); break;
case VOICETYPE_VAG: ImGui::Text("%08x", voice.vagSize); break;
case VOICETYPE_PCM: ImGui::Text("%08x", voice.pcmSize); break;
case VOICETYPE_VAG: ImGui::Text("%x", voice.vagSize); break;
case VOICETYPE_PCM: ImGui::Text("%x", voice.pcmSize); break;
case VOICETYPE_ATRAC3: ImGui::Text("atrac: n/a"); break;
default:
ImGui::TextUnformatted("N/A");
@@ -3165,7 +3165,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUCommon *gpuDebug, Draw:
}
if (cfg_.sasAudioOpen) {
DrawSasAudio(cfg_);
DrawSasAudio(cfg_, control);
}
if (cfg_.kernelObjectsOpen) {
+1 -1
View File
@@ -1434,7 +1434,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
if (gstate.isModeClear()) {
ImGui::Text("(clear mode - texturing not used)");
} else if (!gstate.isTextureMapEnabled()) {
ImGui::Text("(texturing not enabled");
ImGui::Text("(texturing not enabled)");
} else if (TextureCacheCommon *texcache = gpuDebug->GetTextureCacheCommon()) { // We don't bother with the texture if previewCmd is BOUNDING_BOX - no texturing happens there.
TextureApplyResult result = texcache->ApplyTexture(false);
if (TexCacheEntry *tex = result.texCacheEntry) {
+28 -35
View File
@@ -145,7 +145,7 @@ static void LaunchFile(ScreenManager *screenManager, Screen *currentScreen, cons
// Show the savedata popup, why not?
waitForParamSFO();
std::string title = SanitizeString(info->GetTitle(), StringRestriction::NoLineBreaksOrSpecials, 0, 200);
screenManager->push(new SavedataPopupScreen(Path(), path, title));
screenManager->push(new SavedataPopupScreen(Path(), path, true, title));
return;
}
case IdentifiedFileType::PSP_PBP:
@@ -992,7 +992,9 @@ void UmdReplaceScreen::CreateViews() {
rightColumnItems->Add(new Choice(di->T("Cancel")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnCancel);
rightColumnItems->Add(new Spacer());
rightColumnItems->Add(new Choice(mm->T("Game Settings")))->OnClick.Handle(this, &UmdReplaceScreen::OnGameSettings);
rightColumnItems->Add(new Choice(mm->T("Game Settings")))->OnClick.Add([this](UI::EventParams &e) {
screenManager()->push(new GameSettingsScreen(Path()));
});
if (g_recentFiles.HasAny()) {
leftColumn->SetCurrentTab(0, true);
@@ -1026,10 +1028,6 @@ void UmdReplaceScreen::UseDisc(const Path &path) {
}
}
void UmdReplaceScreen::OnGameSettings(UI::EventParams &e) {
screenManager()->push(new GameSettingsScreen(Path()));
}
void GridSettingsPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
@@ -1037,41 +1035,36 @@ void GridSettingsPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
auto sy = GetI18NCategory(I18NCat::SYSTEM);
auto mm = GetI18NCategory(I18NCat::MAINMENU);
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
LinearLayout *items = new LinearLayoutList(ORIENT_VERTICAL);
items->SetSpacing(0.0f);
ScrollView *scroll = parent->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f)));
PopupChoiceGroupList *groupList = scroll->Add(new PopupChoiceGroupList());
ChoiceGroup *group = groupList->Add(new ChoiceGroup());
// Same order as GameBrowserViewMode.
static const char *defaultTabs[] = { "Recent", "Games", "Homebrew & Demos" };
items->Add(new PopupMultiChoice(&g_Config.iDefaultTab, sy->T("Default tab"), defaultTabs, 0, ARRAY_SIZE(defaultTabs), I18NCat::MAINMENU, screenManager()));
group->Add(new PopupMultiChoice(&g_Config.iDefaultTab, sy->T("Default tab"), defaultTabs, 0, ARRAY_SIZE(defaultTabs), I18NCat::MAINMENU, screenManager()));
items->Add(new ItemHeader(sy->T("Icon size")));
items->Add(new Choice(sy->T("Increase size")))->OnClick.Handle(this, &GridSettingsPopupScreen::GridPlusClick);
items->Add(new Choice(sy->T("Decrease size")))->OnClick.Handle(this, &GridSettingsPopupScreen::GridMinusClick);
ChoiceGroup *iconSizeGroup = groupList->Add(new ChoiceGroup(sy->T("Icon size")));
iconSizeGroup->Add(new Choice(sy->T("Increase size")))->OnClick.Add([this](UI::EventParams &e) {
g_Config.fGameGridScale = std::min(g_Config.fGameGridScale * 1.25f, MAX_GAME_GRID_SCALE);
screenManager()->RecreateAllViews();
});
iconSizeGroup->Add(new Choice(sy->T("Decrease size")))->OnClick.Add([this](UI::EventParams &e) {
g_Config.fGameGridScale = std::max(g_Config.fGameGridScale / 1.25f, MIN_GAME_GRID_SCALE);
screenManager()->RecreateAllViews();
});
items->Add(new ItemHeader(sy->T("Display Extra Info")));
items->Add(new CheckBox(&g_Config.bShowIDOnGameIcon, sy->T("Show ID")));
items->Add(new CheckBox(&g_Config.bShowRegionOnGameIcon, sy->T("Show region flag")));
ChoiceGroup *extraInfoGroup = groupList->Add(new ChoiceGroup(sy->T("Display Extra Info")));
extraInfoGroup->Add(new CheckBox(&g_Config.bShowIDOnGameIcon, sy->T("Show ID")));
extraInfoGroup->Add(new CheckBox(&g_Config.bShowRegionOnGameIcon, sy->T("Show region flag")));
if (g_Config.iMaxRecent > 0) {
items->Add(new ItemHeader(sy->T("Clear Recent")));
items->Add(new Choice(sy->T("Clear Recent Games List")))->OnClick.Handle(this, &GridSettingsPopupScreen::OnRecentClearClick);
ChoiceGroup *recentGroup = groupList->Add(new ChoiceGroup(sy->T("Clear Recent")));
recentGroup->Add(new Choice(sy->T("Clear Recent Games List")))->OnClick.Add([this](UI::EventParams &e) {
g_recentFiles.Clear();
OnRecentChanged.Trigger(e);
TriggerFinish(DR_OK);
});
}
scroll->Add(items);
parent->Add(scroll);
}
void GridSettingsPopupScreen::GridPlusClick(UI::EventParams &e) {
g_Config.fGameGridScale = std::min(g_Config.fGameGridScale*1.25f, MAX_GAME_GRID_SCALE);
}
void GridSettingsPopupScreen::GridMinusClick(UI::EventParams &e) {
g_Config.fGameGridScale = std::max(g_Config.fGameGridScale/1.25f, MIN_GAME_GRID_SCALE);
}
void GridSettingsPopupScreen::OnRecentClearClick(UI::EventParams &e) {
g_recentFiles.Clear();
OnRecentChanged.Trigger(e);
TriggerFinish(DR_OK);
}
-4
View File
@@ -115,7 +115,6 @@ protected:
private:
void OnGameSelected(UI::EventParams &e);
void OnGameSettings(UI::EventParams &e);
void UseDisc(const Path &path);
bool insert_;
@@ -130,9 +129,6 @@ public:
const char *tag() const override { return "GridSettings"; }
private:
void GridPlusClick(UI::EventParams &e);
void GridMinusClick(UI::EventParams &e);
void OnRecentClearClick(UI::EventParams &e);
const float MAX_GAME_GRID_SCALE = 3.0f;
const float MIN_GAME_GRID_SCALE = 0.8f;
};
+3 -1
View File
@@ -192,7 +192,7 @@ void MemStickScreen::CreateViews() {
ViewGroup *leftColumn = new LinearLayoutList(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
subColumns->Add(leftColumn);
ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(250, FILL_PARENT, actionMenuMargins));
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(250, FILL_PARENT, actionMenuMargins));
subColumns->Add(rightColumnItems);
// For legacy Android systems, so you can switch back to the old ways if you move to SD or something.
@@ -276,6 +276,8 @@ void MemStickScreen::CreateViews() {
rightColumnItems->Add(new UI::Choice(ms->T("WhatsThis", "What's this?"), ImageID("I_LINK_OUT_QUESTION")))->OnClick.Handle<MemStickScreen>(this, &MemStickScreen::OnHelp);
}
rightColumnItems->ApplyRoundCorners();
INFO_LOG(Log::System, "MemStickScreen: initialSetup=%d", (int)initialSetup_);
}
+12
View File
@@ -167,3 +167,15 @@ private:
int width_ = 0;
int height_ = 0;
};
class HintView : public UI::TextView {
public:
HintView(std::string_view str, UI::LayoutParams *layoutParams = nullptr) : TextView(str, FLAG_WRAP_TEXT, false, layoutParams) {
using namespace UI;
layoutParams_->width = FILL_PARENT;
layoutParams_->height = WRAP_CONTENT;
SetTextSize(TextSize::Small);
SetPadding(Margins(12));
SetFrame(true);
}
};
+4 -1
View File
@@ -373,7 +373,7 @@ void runImDebugger(Draw::DrawContext *draw) {
// Read the TTF font
size_t propSize = 0;
const uint8_t *propFontData = g_VFS.ReadFile("Roboto-Regular.ttf", &propSize);
const uint8_t *propFontData = g_VFS.ReadFile("Roboto_Condensed-Regular.ttf", &propSize);
size_t fixedSize = 0;
const uint8_t *fixedFontData = g_VFS.ReadFile("Inconsolata-Regular.ttf", &fixedSize);
// This call works even if fontData is nullptr, in which case the font just won't get loaded.
@@ -904,6 +904,9 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO
} else if (equals(cmdLineOptions.startScreen.value(), "firmware")) {
g_screenManager->switchScreen(new MainScreen());
g_screenManager->push(new FirmwareScreen(Path()));
} else if (equals(cmdLineOptions.startScreen.value(), "memsticksetup")) {
g_screenManager->switchScreen(new MainScreen());
g_screenManager->push(new MemStickScreen(true));
} else {
WARN_LOG(Log::System, "Unknown start screen '%s'", cmdLineOptions.startScreen.value().c_str());
g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT));
+6 -6
View File
@@ -497,14 +497,14 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems,
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(Margins(10, 0, 0, 10)));
if (g_Config.bEnableStateUndo && !Achievements::HardcoreModeActive() && NetworkAllowSaveState()) {
UI::Choice *saveUndoButton = buttonRow->Add(new Choice(pa->T("Undo last save"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
UI::Button *saveUndoButton = buttonRow->Add(new Button(pa->T("Undo last save"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(WRAP_CONTENT, ITEM_HEIGHT)));
saveUndoButton->SetEnabled(SaveState::HasUndoLastSave(saveStatePrefix_));
saveUndoButton->OnClick.Add([this](UI::EventParams &e) {
SaveState::UndoLastSave(saveStatePrefix_);
RecreateViews();
});
UI::Choice *loadUndoButton = buttonRow->Add(new Choice(pa->T("Undo last load"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
UI::Button *loadUndoButton = buttonRow->Add(new Button(pa->T("Undo last load"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(WRAP_CONTENT, ITEM_HEIGHT)));
loadUndoButton->SetEnabled(SaveState::HasUndoLoad(saveStatePrefix_));
loadUndoButton->OnClick.Add([this](UI::EventParams &e) {
CloseAfterStateLoad([this](SaveState::Callback callback) {
@@ -514,7 +514,7 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems,
}
if (g_Config.iRewindSnapshotInterval > 0 && !Achievements::HardcoreModeActive() && NetworkAllowSaveState()) {
UI::Choice *rewindButton = buttonRow->Add(new Choice(pa->T("Rewind"), ImageID("I_REWIND"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
UI::Button *rewindButton = buttonRow->Add(new Button(pa->T("Rewind"), ImageID("I_REWIND"), new LinearLayoutParams(WRAP_CONTENT, ITEM_HEIGHT)));
rewindButton->SetEnabled(SaveState::CanRewind());
rewindButton->OnClick.Add([this](UI::EventParams &e) {
CloseAfterStateLoad([](SaveState::Callback callback) {
@@ -661,12 +661,12 @@ void GamePauseScreen::CreateViews() {
if (showSavestateControls) {
if (PSP_CoreParameter().compat.flags().SaveStatesNotRecommended) {
LinearLayout *horiz = new LinearLayout(ORIENT_HORIZONTAL);
saveDataScrollItems->Add(horiz);
LinearLayout *horiz = saveDataScrollItems->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
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) {
horiz->Add(new Choice(di->T("More info"), ImageID("I_LINK_OUT_QUESTION"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add([](UI::EventParams &e) {
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/troubleshooting/save-state-time-warps");
});
horiz->ApplyRoundCorners();
}
LinearLayout *extraRow = nullptr;
CreateSavestateControls(saveDataScrollItems, &extraRow);
+15 -8
View File
@@ -132,7 +132,7 @@ SavedataView::SavedataView(UIContext &dc, GameInfo *ginfo, IdentifiedFileType ty
}
}
SavedataPopupScreen::SavedataPopupScreen(Path gamePath, Path savePath, std::string_view title) : PopupScreen(StripSpaces(title)), savePath_(savePath), gamePath_(gamePath) {}
SavedataPopupScreen::SavedataPopupScreen(Path gamePath, Path savePath, bool showHint, std::string_view title) : PopupScreen(StripSpaces(title)), savePath_(savePath), gamePath_(gamePath), showHint_(showHint) {}
void SavedataPopupScreen::update() {
PopupScreen::update();
@@ -158,17 +158,23 @@ void SavedataPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f, UI::Margins(0, 3)));
parent->Add(contentScroll);
LinearLayout *content = contentScroll->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
if (showHint_) {
auto g = GetI18NCategory(I18NCat::GAME);
content->Add(new HintView(g->T("SaveData")));
}
// TODO: If the game info wasn't already loaded, we'll get a bogus fileType here.
savedataView_ = contentScroll->Add(new SavedataView(dc, ginfo.get(), ginfo->fileType, true));
savedataView_ = content->Add(new SavedataView(dc, ginfo.get(), ginfo->fileType, true));
auto di = GetI18NCategory(I18NCat::DIALOG);
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
buttonRow->SetSpacing(0);
Margins buttonMargins(5, 5, 5, 13); // not sure why we need more at the bottom to make it look right
buttonRow->SetSpacing(12);
buttonRow->Add(new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
buttonRow->Add(new Choice(di->T("Delete"), ImageID("I_TRASHCAN"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
buttonRow->Add(new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(1.0f)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
buttonRow->Add(new Choice(di->T("Delete"), ImageID("I_TRASHCAN"), new LinearLayoutParams(1.0f)))->OnClick.Add([this](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
@@ -183,10 +189,11 @@ void SavedataPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
}));
});
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
buttonRow->Add(new Choice(di->T("Show in folder"), ImageID("I_FOLDER"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
buttonRow->Add(new Choice(di->T("Show in folder"), ImageID("I_FOLDER"), new LinearLayoutParams(1.0f)))->OnClick.Add([this](UI::EventParams &e) {
System_ShowFileInFolder(savePath_);
});
}
buttonRow->ApplyRoundCorners();
parent->Add(buttonRow);
}
@@ -690,7 +697,7 @@ void SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) {
// Sanitize the title.
std::string title = SanitizeString(ginfo->GetTitle(), StringRestriction::NoLineBreaksOrSpecials, 0, 200);
SavedataPopupScreen *popupScreen = new SavedataPopupScreen(gamePath_, Path(e.s), title);
SavedataPopupScreen *popupScreen = new SavedataPopupScreen(gamePath_, Path(e.s), false, title);
if (e.v) {
popupScreen->SetPopupOrigin(e.v);
}
+2 -1
View File
@@ -71,7 +71,7 @@ class SavedataView;
class SavedataPopupScreen : public UI::PopupScreen {
public:
SavedataPopupScreen(Path gamePath, Path savePath, std::string_view title);
SavedataPopupScreen(Path gamePath, Path savePath, bool showHint, std::string_view title);
const char *tag() const override { return "SavedataPopup"; }
void update() override;
@@ -84,6 +84,7 @@ private:
SavedataView *savedataView_ = nullptr;
Path savePath_;
Path gamePath_;
bool showHint_ = false;
};
class SavedataScreen : public UITabbedBaseDialogScreen {
+1
View File
@@ -208,6 +208,7 @@ static const ImageMeta g_uiImageIDs[] = {
{"I_DOWNLOAD", false},
{"I_NETWORK", false},
{"I_LANGUAGE", false},
{"I_VR", false},
};
static std::string PNGNameFromID(std::string_view id) {
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -5
View File
@@ -23,9 +23,9 @@
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="5.6568544"
inkscape:cx="181.63805"
inkscape:cy="75.041705"
inkscape:zoom="4.0000001"
inkscape:cx="234.87499"
inkscape:cy="537.87499"
inkscape:window-width="3840"
inkscape:window-height="2071"
inkscape:window-x="-9"
@@ -985,7 +985,7 @@
style="fill:#ffffff;stroke-width:4.93273"
d="m 94.191649,3.89538 a 2.5724686,2.5724686 0 0 1 2.57247,-2.57246 2.5724686,2.5724686 0 0 1 2.57247,2.57246 2.5724686,2.5724686 0 0 1 -2.57247,2.57247 2.5724686,2.5724686 0 0 1 -2.57247,-2.57247 z" /><g
id="I_DISPLAY"
transform="matrix(1.7225478,0,0,1.7225478,-109.02695,4.9970217)">
transform="matrix(1.8233708,0,0,1.8233708,-118.84776,-1.0582382)">
<path
d="m 94.898083,57.771045 h 5.016673 0.116084 v 0.116081 3.861938 0.116081 h -0.116084 -1.630619 v 0.193005 h 0.406285 v 0.287413 H 96.069104 V 62.05815 h 0.406285 v -0.193005 h -1.577306 -0.116082 v -0.116081 -3.861938 -0.116081 z m 4.694422,0.330476 H 95.2473 v 3.44158 h 4.344643 z"
@@ -1613,7 +1613,10 @@
sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc" /><path
id="I_CHEVRON_LEFT"
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 49.998024,36.583735 -3.7171,3.7172 3.7171,3.7172 -0.5656,0.5656 -4.2829,-4.2828 4.2829,-4.2828 z" /></g><style
d="m 49.998024,36.583735 -3.7171,3.7172 3.7171,3.7172 -0.5656,0.5656 -4.2829,-4.2828 4.2829,-4.2828 z" /><path
id="I_VR"
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke-width:0.622078;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;enable-background:accumulate;stop-color:#000000"
d="M 19.158394 183.69988 C 18.364409 183.69988 17.622057 184.09765 17.181632 184.75829 L 16.76199 185.38724 A 0.31107067 0.31107067 0 0 0 16.710309 185.53504 C 16.396114 185.78176 16.193509 186.16449 16.193509 186.5919 L 16.193509 190.20537 C 16.193509 190.94364 16.798938 191.54905 17.53719 191.54905 L 19.533591 191.54905 C 20.005017 191.54905 20.442989 191.30109 20.68554 190.89685 L 21.491232 189.5542 C 21.578042 189.40951 21.755333 189.40951 21.84214 189.5542 L 22.647832 190.89685 C 22.89037 191.30113 23.328361 191.54905 23.79978 191.54905 L 25.796181 191.54905 C 26.534444 191.54905 27.139863 190.94363 27.139863 190.20537 L 27.139863 186.5919 C 27.139863 186.16449 26.937259 185.78176 26.623062 185.53504 A 0.31107067 0.31107067 0 0 0 26.571382 185.38724 L 26.152257 184.75829 C 25.711819 184.09766 24.968954 183.69988 24.174978 183.69988 L 19.158394 183.69988 z M 19.158394 184.32263 L 24.174978 184.32263 C 24.761687 184.32263 25.308432 184.61481 25.633906 185.103 L 25.730548 185.24822 L 17.602824 185.24822 L 17.699466 185.103 C 18.024922 184.61482 18.571672 184.32263 19.158394 184.32263 z M 17.53719 185.87148 L 25.796181 185.87148 C 26.198263 185.87148 26.517118 186.18983 26.517118 186.5919 L 26.517118 190.20537 C 26.517118 190.60745 26.198269 190.9263 25.796181 190.9263 L 23.79978 190.9263 C 23.545964 190.9263 23.311729 190.79406 23.18117 190.57643 L 22.376511 189.2343 C 22.062347 188.71064 21.271024 188.71064 20.95686 189.2343 L 20.152202 190.57643 C 20.021604 190.79409 19.787421 190.9263 19.533591 190.9263 L 17.53719 190.9263 C 17.135122 190.9263 16.816254 190.60745 16.816254 190.20537 L 16.816254 186.5919 C 16.816254 186.18984 17.135128 185.87148 17.53719 185.87148 z " /></g><style
type="text/css"
id="style1">
.st0{fill:#000000;}

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 175 KiB