From 7632e5e16efa217529017531661f669f5acae2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Sep 2021 22:52:49 +0200 Subject: [PATCH 1/5] Minor polish to MemStickScreen --- UI/MemStickScreen.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index edacb553a8..59c71e8bb8 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -182,9 +182,12 @@ UI::EventReturn MemStickScreen::OnUseInternalStorage(UI::EventParams ¶ms) { } else { // This can't really happen?? Not worth making an error message. } - } else { + } else if (pendingMemStickFolder != g_Config.memStickDirectory) { // Always ask for confirmation when called from the UI. Likely there's already some data. screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); + } else { + // User chose the same directory it's already in. Let's just bail. + TriggerFinish(DialogResult::DR_OK); } return UI::EVENT_DONE; } @@ -200,9 +203,12 @@ UI::EventReturn MemStickScreen::OnUseStorageRoot(UI::EventParams ¶ms) { } else { // This can't really happen?? Not worth making an error message. } - } else { + } else if (pendingMemStickFolder != g_Config.memStickDirectory) { // Always ask for confirmation when called from the UI. Likely there's already some data. screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); + } else { + // User chose the same directory it's already in. Let's just bail. + TriggerFinish(DialogResult::DR_OK); } return UI::EVENT_DONE; } @@ -227,9 +233,6 @@ void MemStickScreen::sendMessage(const char *message, const char *value) { if (pendingMemStickFolder == g_Config.memStickDirectory) { auto iz = GetI18NCategory("MemStick"); -#if PPSSPP_PLATFORM(ANDROID) - SystemToast(iz->T("That's the folder being used!")); -#endif return; } From d3abcf1b56300f27f18552a4b48daaea556f67b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Sep 2021 23:41:44 +0200 Subject: [PATCH 2/5] Draw bullet points as circles for a consistent look regardless of system font. --- Common/Render/DrawBuffer.cpp | 32 ++++++++++++++++++------ Common/Render/DrawBuffer.h | 1 + Common/Render/Text/draw_text_android.cpp | 3 +++ Common/UI/View.cpp | 10 +++++--- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/Common/Render/DrawBuffer.cpp b/Common/Render/DrawBuffer.cpp index 742cb1a5fd..f1e3e9baa8 100644 --- a/Common/Render/DrawBuffer.cpp +++ b/Common/Render/DrawBuffer.cpp @@ -356,7 +356,6 @@ void DrawBuffer::DrawImageRotatedStretch(ImageID atlas_image, const Bounds &boun } } -// TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32_t color, float u_mul) { float angleDelta = PI * 2 / segments; float uDelta = 1.0f / segments; @@ -372,12 +371,31 @@ void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int s float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; - V(x[0], y[0], color, u1, 0); - V(x[1], y[1], color, u2, 0); - V(x[2], y[2], color, u1, 1); - V(x[1], y[1], color, u2, 0); - V(x[3], y[3], color, u2, 1); - V(x[2], y[2], color, u1, 1); + V(x[0], y[0], color, u1, 0.0f); + V(x[1], y[1], color, u2, 0.0f); + V(x[2], y[2], color, u1, 1.0f); + V(x[1], y[1], color, u2, 0.0f); + V(x[3], y[3], color, u2, 1.0f); + V(x[2], y[2], color, u1, 1.0f); + } +} + +void DrawBuffer::FillCircle(float xc, float yc, float radius, int segments, uint32_t color) { + float angleDelta = PI * 2 / segments; + float uDelta = 1.0f / segments; + float r1 = radius; + for (int i = 0; i < segments + 1; i++) { + float angle1 = i * angleDelta; + float angle2 = (i + 1) * angleDelta; + float u1 = i * uDelta; + float u2 = (i + 1) * uDelta; + // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration + float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); + const float x[2] = { c1 * r1 + xc, c2 * r1 + xc }; + const float y[2] = { s1 * r1 + yc, s2 * r1 + yc }; + V(xc, yc, color, 0.0f, 0.0f); + V(x[0], y[0], color, u1, 0.0f); + V(x[1], y[1], color, u2, 1.0f); } } diff --git a/Common/Render/DrawBuffer.h b/Common/Render/DrawBuffer.h index dcf2513c22..6190f3ecba 100644 --- a/Common/Render/DrawBuffer.h +++ b/Common/Render/DrawBuffer.h @@ -101,6 +101,7 @@ public: } void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32_t color, float u_mul); + void FillCircle(float x, float y, float radius, int segments, uint32_t color); // New drawing APIs diff --git a/Common/Render/Text/draw_text_android.cpp b/Common/Render/Text/draw_text_android.cpp index 16241818ad..7d0a1e2623 100644 --- a/Common/Render/Text/draw_text_android.cpp +++ b/Common/Render/Text/draw_text_android.cpp @@ -221,6 +221,9 @@ void TextDrawerAndroid::DrawStringBitmap(std::vector &bitmapData, TextS void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { using namespace Draw; + if (!str) + return; + std::string text(NormalizeString(std::string(str))); if (text.empty()) return; diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index 8d929056c0..435487b3f0 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -848,10 +848,12 @@ void TextView::Draw(UIContext &dc) { Bounds textBounds = bounds_; if (bullet_) { - // Possible alternatives: •●■ - // TODO: Maybe draw an actual circle if we don't have real unicode fonts. So far this is only - // used on Android. - dc.DrawTextRect("●", textBounds, textColor, ALIGN_LEFT); + float radius = 7.0f; + dc.Flush(); + dc.BeginNoTex(); + dc.Draw()->FillCircle(textBounds.x + radius, textBounds.centerY(), radius, 20, textColor); + dc.Flush(); + dc.Begin(); textBounds.x += bulletOffset; textBounds.w -= bulletOffset; } From e7214f4f6b26a44c45332a285b9a9b04340c0e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Sep 2021 23:42:21 +0200 Subject: [PATCH 3/5] Hide the folder selector for memstick directory on Android 9 and earlier. It just doesn't work. --- UI/MemStickScreen.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 59c71e8bb8..78ad8a7906 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -147,10 +147,16 @@ void MemStickScreen::CreateViews() { } #endif - leftColumn->Add(new Choice(iz->T("Create or Choose a PSP folder")))->OnClick.Handle(this, &MemStickScreen::OnBrowse); - leftColumn->Add(new TextView(iz->T("DataWillStay", "Data will stay even if you uninstall PPSSPP.")))->SetBullet(true); - leftColumn->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold.")))->SetBullet(true); - leftColumn->Add(new TextView(iz->T("EasyUSBAccess", "Easy USB access")))->SetBullet(true); + // Let's only offer the browse-for-folder choice on Android 10 or later. + // Earlier versions often don't really have working folder browsers. + bool storageBrowserWorking = System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 29; + + if (storageBrowserWorking) { + leftColumn->Add(new Choice(iz->T("Create or Choose a PSP folder")))->OnClick.Handle(this, &MemStickScreen::OnBrowse); + leftColumn->Add(new TextView(iz->T("DataWillStay", "Data will stay even if you uninstall PPSSPP.")))->SetBullet(true); + leftColumn->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold.")))->SetBullet(true); + leftColumn->Add(new TextView(iz->T("EasyUSBAccess", "Easy USB access")))->SetBullet(true); + } leftColumn->Add(new Choice(iz->T("Use App Private Directory")))->OnClick.Handle(this, &MemStickScreen::OnUseInternalStorage); // Consider https://www.compart.com/en/unicode/U+26A0 (unicode warning sign?)? or a graphic? From df0dd441c9a2d58046a1803d52040789376c01c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Sep 2021 23:59:54 +0200 Subject: [PATCH 4/5] Add back the ability to manually specify a folder, on Android 9 and earlier. --- UI/MemStickScreen.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ UI/MemStickScreen.h | 1 + 2 files changed, 43 insertions(+) diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 78ad8a7906..e5c58547a6 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -156,6 +156,10 @@ void MemStickScreen::CreateViews() { leftColumn->Add(new TextView(iz->T("DataWillStay", "Data will stay even if you uninstall PPSSPP.")))->SetBullet(true); leftColumn->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold.")))->SetBullet(true); leftColumn->Add(new TextView(iz->T("EasyUSBAccess", "Easy USB access")))->SetBullet(true); + } else { + leftColumn->Add(new Choice(iz->T("Manually specify PSP folder")))->OnClick.Handle(this, &MemStickScreen::OnSetFolderManually); + leftColumn->Add(new TextView(iz->T("DataWillStay", "Data will stay even if you uninstall PPSSPP.")))->SetBullet(true); + leftColumn->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold.")))->SetBullet(true); } leftColumn->Add(new Choice(iz->T("Use App Private Directory")))->OnClick.Handle(this, &MemStickScreen::OnUseInternalStorage); @@ -177,6 +181,44 @@ void MemStickScreen::CreateViews() { INFO_LOG(SYSTEM, "MemStickScreen: initialSetup=%d", (int)initialSetup_); } +UI::EventReturn MemStickScreen::OnSetFolderManually(UI::EventParams ¶ms) { + // The old way, from before scoped storage. + + auto sy = GetI18NCategory("System"); + System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](bool result, const std::string &value) { + auto sy = GetI18NCategory("System"); + auto di = GetI18NCategory("Dialog"); + + if (result) { + std::string newPath = value; + size_t pos = newPath.find_last_not_of("/"); + // Gotta have at least something but a /, and also needs to start with a /. + if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') { + settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr); + return; + } + if (pos != newPath.size() - 1) { + newPath = newPath.substr(0, pos + 1); + } + + Path pendingMemStickFolder(newPath); + if (pendingMemStickFolder == g_Config.memStickDirectory) { + // Same directory as before - all good. + TriggerFinish(DialogResult::DR_OK); + return; + } + + if (!File::Exists(pendingMemStickFolder)) { + SystemToast(sy->T("Path does not exist!")); + return; + } + + screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); + } + }); + return UI::EVENT_DONE; +} + UI::EventReturn MemStickScreen::OnUseInternalStorage(UI::EventParams ¶ms) { Path pendingMemStickFolder = Path(g_extFilesDir); diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index 2c248103f0..a320f017c8 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -59,6 +59,7 @@ private: UI::EventReturn OnBrowse(UI::EventParams &e); UI::EventReturn OnUseInternalStorage(UI::EventParams ¶ms); UI::EventReturn OnUseStorageRoot(UI::EventParams ¶ms); + UI::EventReturn OnSetFolderManually(UI::EventParams ¶ms); SettingInfoMessage *settingInfo_ = nullptr; From 08dbcf7f7907e62fbeda61ea235f37d039a56f6f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 10 Sep 2021 19:01:56 -0700 Subject: [PATCH 5/5] UI: Fix non-Android build error. --- UI/MemStickScreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index e5c58547a6..812a8e80c5 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -183,7 +183,7 @@ void MemStickScreen::CreateViews() { UI::EventReturn MemStickScreen::OnSetFolderManually(UI::EventParams ¶ms) { // The old way, from before scoped storage. - +#if PPSSPP_PLATFORM(ANDROID) auto sy = GetI18NCategory("System"); System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](bool result, const std::string &value) { auto sy = GetI18NCategory("System"); @@ -216,6 +216,7 @@ UI::EventReturn MemStickScreen::OnSetFolderManually(UI::EventParams ¶ms) { screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); } }); +#endif return UI::EVENT_DONE; }