From 143ba22097dab9f0789657f153a1465f75cc2f79 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 21:21:16 -0700 Subject: [PATCH 1/6] PPGe: Handle text shadows more consistently. Don't really want them wrapping differently or etc. Let's handle centrally so we can make them consistent and better. --- Core/Dialog/PSPDialog.cpp | 24 +++++--- Core/Dialog/PSPDialog.h | 2 + Core/Dialog/PSPMsgDialog.cpp | 19 ++----- Core/Dialog/PSPNetconfDialog.cpp | 16 ++++-- Core/Dialog/PSPOskDialog.cpp | 78 +++++++++++++++----------- Core/Dialog/PSPSaveDialog.cpp | 48 ++++++++-------- Core/Util/PPGeDraw.cpp | 96 +++++++++++++++++++++----------- Core/Util/PPGeDraw.h | 16 ++++-- 8 files changed, 179 insertions(+), 120 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 8bc866c731..f77682848c 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -198,6 +198,16 @@ bool PSPDialog::IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThr return false; } +PPGeStyle PSPDialog::FadedStyle(PPGeAlign align, float scale) { + PPGeStyle textStyle; + textStyle.align = align; + textStyle.scale = scale; + textStyle.color = CalcFadedColor(textStyle.color); + textStyle.hasShadow = true; + textStyle.shadowColor = CalcFadedColor(textStyle.shadowColor); + return textStyle; +} + void PSPDialog::DisplayButtons(int flags, const char *caption) { bool useCaption = false; @@ -207,6 +217,8 @@ void PSPDialog::DisplayButtons(int flags, const char *caption) truncate_cpy(safeCaption, caption); } + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, FONT_SCALE); + auto di = GetI18NCategory("Dialog"); float x1 = 183.5f, x2 = 261.5f; if (GetCommonParam()->buttonSwap == 1) { @@ -215,16 +227,12 @@ void PSPDialog::DisplayButtons(int flags, const char *caption) } if (flags & DS_BUTTON_OK) { const char *text = useCaption ? safeCaption : di->T("Enter"); - PPGeDrawImage(okButtonImg, x2, 258, 11.5f, 11.5f, 0, CalcFadedColor(0x80000000)); - PPGeDrawImage(okButtonImg, x2, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(text, x2 + 15.5f, 254, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(text, x2 + 14.5f, 252, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(okButtonImg, x2, 256, 11.5f, 11.5f, textStyle); + PPGeDrawText(text, x2 + 14.5f, 252, textStyle); } if (flags & DS_BUTTON_CANCEL) { const char *text = useCaption ? safeCaption : di->T("Back"); - PPGeDrawText(text, x1 + 15.5f, 254, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(text, x1 + 14.5f, 252, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawImage(cancelButtonImg, x1, 258, 11.5f, 11.5f, 0, CalcFadedColor(0x80000000)); - PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, textStyle); + PPGeDrawText(text, x1 + 14.5f, 252, textStyle); } } diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index 4de49d27f0..8d88c5c1a7 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -22,6 +22,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" #include "Common/Swap.h" +#include "Core/Util/PPGeDraw.h" class PointerWrap; @@ -83,6 +84,7 @@ public: void StartDraw(); void EndDraw(); protected: + PPGeStyle FadedStyle(PPGeAlign align, float scale); void UpdateButtons(); bool IsButtonPressed(int checkButton); bool IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold = 30, int framesHeldRepeatRate = 10); diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 22960aa7a1..b40fc05857 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -153,23 +153,20 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) float h2 = h / 2.0f; ey = y + h2 + 20.0f; + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); + if (hasYesNo) { auto di = GetI18NCategory("Dialog"); const char *choiceText; - u32 yesColor, noColor; float x, w; if (yesnoChoice == 1) { choiceText = di->T("Yes"); x = 204.0f; - yesColor = 0xFFFFFFFF; - noColor = 0xFFFFFFFF; } else { choiceText = di->T("No"); x = 273.0f; - yesColor = 0xFFFFFFFF; - noColor = 0xFFFFFFFF; } PPGeMeasureText(&w, &h, choiceText, FONT_SCALE); w = 15.0f; @@ -178,10 +175,8 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) h2 += h + 5.0f; y = 135.0f - h; PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); - PPGeDrawText(di->T("Yes"), 204.0f, y2 + 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(di->T("Yes"), 203.0f, y2 - 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(yesColor)); - PPGeDrawText(di->T("No"), 273.0f, y2 + 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(di->T("No"), 272.0f, y2 - 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(noColor)); + PPGeDrawText(di->T("Yes"), 203.0f, y2 - 1.0f, textStyle); + PPGeDrawText(di->T("No"), 272.0f, y2 - 1.0f, textStyle); if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { yesnoChoice = 1; } @@ -201,13 +196,11 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) h2 += h + 5.0f; y = 135.0f - h; PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); - PPGeDrawText(di->T("OK"), 240.0f, y2 + 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(di->T("OK"), 239.0f, y2 - 1.0f, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(di->T("OK"), 239.0f, y2 - 1.0f, textStyle); ey = y2 + 25.0f; } - PPGeDrawTextWrapped(text.c_str(), 241.0f, y+2, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, 0, textStyle); sy = 125.0f - h2; PPGeDrawRect(40.0f, sy, 440.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(40.0f, ey, 440.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index 37332f926b..998f5745cf 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -65,10 +65,13 @@ void PSPNetconfDialog::DrawBanner() { PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358)); + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f); + textStyle.hasShadow = false; + // TODO: Draw a hexagon icon - PPGeDrawImage(10, 6, 12.0f, 12.0f, 1, 10, 1, 10, 10, 10, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(10, 6, 12.0f, 12.0f, 1, 10, 1, 10, 10, 10, textStyle.color); auto di = GetI18NCategory("Dialog"); - PPGeDrawText(di->T("Network Connection"), 30, 11, PPGeAlign::BOX_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(di->T("Network Connection"), 30, 11, textStyle); } int PSPNetconfDialog::Update(int animSpeed) { @@ -83,14 +86,17 @@ int PSPNetconfDialog::Update(int animSpeed) { const ImageID confirmBtnImage = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? ImageID("I_CROSS") : ImageID("I_CIRCLE"); const int confirmBtn = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE; + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, 0.5f); + PPGeStyle buttonStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); + if (request.netAction == NETCONF_CONNECT_APNET || request.netAction == NETCONF_STATUS_APNET || request.netAction == NETCONF_CONNECT_APNET_LAST) { UpdateFade(animSpeed); StartDraw(); DrawBanner(); PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0x63636363)); - PPGeDrawTextWrapped(err->T("PPSSPPDoesNotSupportInternet", "PPSSPP currently does not support connecting to the Internet for DLC, PSN, or game updates."), 241, 132, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawImage(confirmBtnImage, 195, 250, 20, 20, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(di->T("OK"), 225, 252, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawTextWrapped(err->T("PPSSPPDoesNotSupportInternet", "PPSSPP currently does not support connecting to the Internet for DLC, PSN, or game updates."), 241, 132, WRAP_WIDTH, 0, textStyle); + PPGeDrawImage(confirmBtnImage, 195, 250, 20, 20, buttonStyle); + PPGeDrawText(di->T("OK"), 225, 252, buttonStyle); if (IsButtonPressed(confirmBtn)) { StartFade(false); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index dbe5ae697b..f60f41ce5e 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -766,7 +766,18 @@ void PSPOskDialog::RenderKeyboard() float previewLeftSide = (480.0f - (12.0f * drawLimit)) / 2.0f; float title = (480.0f - (0.5f * drawLimit)) / 2.0f; - PPGeDrawText(oskDesc.c_str(), title , 20, PPGeAlign::BOX_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeStyle descStyle = FadedStyle(PPGeAlign::BOX_CENTER, 0.5f); + descStyle.hasShadow = false; + PPGeDrawText(oskDesc.c_str(), title, 20, descStyle); + + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.5f); + textStyle.hasShadow = false; + + PPGeStyle keyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f); + keyStyle.hasShadow = false; + PPGeStyle selectedKeyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f); + selectedKeyStyle.color = CalcFadedColor(0xFF3060FF); + selectedKeyStyle.hasShadow = false; std::u16string result; @@ -776,12 +787,11 @@ void PSPOskDialog::RenderKeyboard() drawIndex = result.size() == limit + 1 ? drawIndex - 1 : drawIndex; // When the length reached limit, the last character don't fade in and out. for (u32 i = 0; i < drawLimit; ++i, ++drawIndex) { - u32 color = CalcFadedColor(0xFFFFFFFF); if (drawIndex + 1 < result.size()) { temp[0] = result[drawIndex]; ConvertUCS2ToUTF8(buffer, temp); - PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); + PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, textStyle); } else { @@ -794,25 +804,25 @@ void PSPOskDialog::RenderKeyboard() float animStep = (float)(__DisplayGetNumVblanks() % 40) / 20.0f; // Fade in and out the next character so they know it's not part of the string yet. u32 alpha = (0.5f - (cosf(animStep * M_PI) / 2.0f)) * 128 + 127; - color = CalcFadedColor((alpha << 24) | 0xFFFFFF); + PPGeStyle animStyle = textStyle; + animStyle.color = CalcFadedColor((alpha << 24) | 0x00FFFFFF); ConvertUCS2ToUTF8(buffer, temp); - PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); + PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, animStyle); // Also draw the underline for the same reason. - color = CalcFadedColor(0xFFFFFFFF); - PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); + PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, textStyle); } else { ConvertUCS2ToUTF8(buffer, temp); - PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); + PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, textStyle); } } else { - PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); + PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, textStyle); } } } @@ -821,17 +831,16 @@ void PSPOskDialog::RenderKeyboard() { for (int col = 0; col < numKeyCols[currentKeyboard]; ++col) { - u32 color = CalcFadedColor(0xFFFFFFFF); - if (selectedRow == row && col == selectedCol) - color = CalcFadedColor(0xFF3060FF); - temp[0] = oskKeys[currentKeyboard][row][col]; ConvertUCS2ToUTF8(buffer, temp); - PPGeDrawText(buffer.c_str(), keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGeAlign::BOX_HCENTER, 0.6f, color); - if (selectedRow == row && col == selectedCol) - PPGeDrawText("_", keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGeAlign::BOX_HCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); + if (selectedRow == row && col == selectedCol) { + PPGeDrawText(buffer.c_str(), keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), selectedKeyStyle); + PPGeDrawText("_", keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), keyStyle); + } else { + PPGeDrawText(buffer.c_str(), keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), keyStyle); + } } } } @@ -944,22 +953,27 @@ int PSPOskDialog::Update(int animSpeed) { auto di = GetI18NCategory("Dialog"); - PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(di->T("Space"), 390, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeStyle actionStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); + actionStyle.hasShadow = false; + PPGeStyle guideStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.6f); + guideStyle.hasShadow = false; + + PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, guideStyle); + PPGeDrawText(di->T("Space"), 390, 222, actionStyle); if (g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE) { - PPGeDrawImage(ImageID("I_CROSS"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawImage(ImageID("I_CIRCLE"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(ImageID("I_CROSS"), 45, 222, 16, 16, guideStyle); + PPGeDrawImage(ImageID("I_CIRCLE"), 45, 247, 16, 16, guideStyle); } else { - PPGeDrawImage(ImageID("I_CIRCLE"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawImage(ImageID("I_CROSS"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(ImageID("I_CIRCLE"), 45, 222, 16, 16, guideStyle); + PPGeDrawImage(ImageID("I_CROSS"), 45, 247, 16, 16, guideStyle); } - PPGeDrawText(di->T("Select"), 75, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(di->T("Delete"), 75, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(di->T("Select"), 75, 222, actionStyle); + PPGeDrawText(di->T("Delete"), 75, 247, actionStyle); - PPGeDrawText("Start", 135, 220, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(di->T("Finish"), 185, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText("Start", 135, 220, guideStyle); + PPGeDrawText(di->T("Finish"), 185, 222, actionStyle); auto lookupLangName = [&](int direction) { // First, find the valid one... @@ -983,20 +997,20 @@ int PSPOskDialog::Update(int animSpeed) { }; if (OskKeyboardNames[currentKeyboardLanguage] != "ko_KR" && IsKeyboardShiftValid(oskParams->fields[0].inputtype, currentKeyboardLanguage, currentKeyboard)) { - PPGeDrawText("Select", 135, 245, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(di->T("Shift"), 185, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText("Select", 135, 245, guideStyle); + PPGeDrawText(di->T("Shift"), 185, 247, actionStyle); } const char *prevLang = lookupLangName(-1); if (prevLang) { - PPGeDrawText("L", 235, 220, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(prevLang, 255, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText("L", 235, 220, guideStyle); + PPGeDrawText(prevLang, 255, 222, actionStyle); } const char *nextLang = lookupLangName(1); if (nextLang) { - PPGeDrawText("R", 235, 245, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(nextLang, 255, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText("R", 235, 245, guideStyle); + PPGeDrawText(nextLang, 255, 247, actionStyle); } if (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index c78c6055bf..c2d3b0a8f7 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -282,6 +282,10 @@ void PSPSaveDialog::DisplayBanner(int which) { auto di = GetI18NCategory("Dialog"); PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358)); + + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f); + textStyle.hasShadow = false; + const char *title; switch (which) { @@ -299,8 +303,8 @@ void PSPSaveDialog::DisplayBanner(int which) break; } // TODO: Draw a hexagon icon - PPGeDrawImage(10, 6, 12.0f, 12.0f, 1, 10, 1, 10, 10, 10, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(title, 30, 11, PPGeAlign::BOX_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawImage(10, 6, 12.0f, 12.0f, 1, 10, 1, 10, 10, 10, textStyle.color); + PPGeDrawText(title, 30, 11, textStyle); } void PSPSaveDialog::DisplaySaveList(bool canMove) { @@ -395,7 +399,8 @@ void PSPSaveDialog::DisplaySaveDataInfo1() std::lock_guard guard(paramLock); if (param.GetFileInfo(currentSelectedSave).size == 0) { auto di = GetI18NCategory("Dialog"); - PPGeDrawText(di->T("NEW DATA"), 180, 136, PPGeAlign::BOX_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f); + PPGeDrawText(di->T("NEW DATA"), 180, 136, textStyle); } else { char title[512]; char time[512]; @@ -452,14 +457,15 @@ void PSPSaveDialog::DisplaySaveDataInfo1() std::string saveTitleTxt = saveTitle; std::string saveDetailTxt = saveDetail; - PPGeDrawText(titleTxt.c_str(), 181, 138, PPGeAlign::BOX_BOTTOM, 0.6f, CalcFadedColor(0x80000000)); - PPGeDrawText(titleTxt.c_str(), 180, 136, PPGeAlign::BOX_BOTTOM, 0.6f, CalcFadedColor(0xFFC0C0C0)); - PPGeDrawText(timeTxt.c_str(), 181, 139, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); - PPGeDrawText(timeTxt.c_str(), 180, 137, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(saveTitleTxt.c_str(), 176, 162, PPGeAlign::BOX_LEFT, 0.55f, CalcFadedColor(0x80000000)); - PPGeDrawText(saveTitleTxt.c_str(), 175, 159, PPGeAlign::BOX_LEFT, 0.55f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawTextWrapped(saveDetailTxt.c_str(), 176, 183, 480 - 175, 250 - 183, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); - PPGeDrawTextWrapped(saveDetailTxt.c_str(), 175, 181, 480 - 175, 250 - 181, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeStyle titleStyle = FadedStyle(PPGeAlign::BOX_BOTTOM, 0.6f); + PPGeStyle saveTitleStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.55f); + titleStyle.color = CalcFadedColor(0xFFC0C0C0); + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); + + PPGeDrawText(titleTxt.c_str(), 180, 136, titleStyle); + PPGeDrawText(timeTxt.c_str(), 180, 137, textStyle); + PPGeDrawText(saveTitleTxt.c_str(), 175, 159, saveTitleStyle); + PPGeDrawTextWrapped(saveDetailTxt.c_str(), 175, 181, 480 - 175, 250 - 181, textStyle); } } @@ -525,13 +531,15 @@ void PSPSaveDialog::DisplaySaveDataInfo2(bool showNewData) { snprintf(date, 256, "%d/%02d/%02d", year, month, day); } + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); std::string saveinfoTxt = StringFromFormat("%.128s\n%s %s\n%lld KB", save_title, date, hour_time, sizeK); - PPGeDrawText(saveinfoTxt.c_str(), 9, 202, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); - PPGeDrawText(saveinfoTxt.c_str(), 8, 200, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(saveinfoTxt.c_str(), 8, 200, textStyle); } void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) { + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); + const float WRAP_WIDTH = 254.0f; float y = 136.0f, h; PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); @@ -540,19 +548,14 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) { auto di = GetI18NCategory("Dialog"); const char *choiceText; - u32 yesColor, noColor; float x, w; if (yesnoChoice == 1) { choiceText = di->T("Yes"); x = 302.0f; - yesColor = 0xFFFFFFFF; - noColor = 0xFFFFFFFF; } else { choiceText = di->T("No"); x = 366.0f; - yesColor = 0xFFFFFFFF; - noColor = 0xFFFFFFFF; } PPGeMeasureText(&w, &h, choiceText, FONT_SCALE); w = w / 2.0f + 5.5f; @@ -561,10 +564,8 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) h2 += h + 4.0f; y = 132.0f - h; PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x40C0C0C0)); - PPGeDrawText(di->T("Yes"), 303.0f, y2+2, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(di->T("Yes"), 302.0f, y2, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(yesColor)); - PPGeDrawText(di->T("No"), 367.0f, y2+2, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(di->T("No"), 366.0f, y2, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(noColor)); + PPGeDrawText(di->T("Yes"), 302.0f, y2, textStyle); + PPGeDrawText(di->T("No"), 366.0f, y2, textStyle); if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { yesnoChoice = 1; } @@ -572,8 +573,7 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) yesnoChoice = 0; } } - PPGeDrawTextWrapped(text.c_str(), 335.0f, y+2, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawTextWrapped(text.c_str(), 334.0f, y, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawTextWrapped(text.c_str(), 334.0f, y, WRAP_WIDTH, 0, textStyle); float sy = 122.0f - h2, ey = 150.0f + h2; PPGeDrawRect(202.0f, sy, 466.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(202.0f, ey, 466.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 3e4efc8afb..688d11cb42 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -789,14 +789,14 @@ int GetPow2(int x) { return ret; } -static PPGeTextDrawerImage PPGeGetTextImage(const char *text, PPGeAlign align, float scale, float maxWidth, bool wrap) { +static PPGeTextDrawerImage PPGeGetTextImage(const char *text, const PPGeStyle &style, float maxWidth, bool wrap) { int tdalign = 0; tdalign |= FLAG_ELLIPSIZE_TEXT; if (wrap) { tdalign |= FLAG_WRAP_TEXT; } - PPGeTextDrawerCacheKey key{ text, tdalign, maxWidth / scale }; + PPGeTextDrawerCacheKey key{ text, tdalign, maxWidth / style.scale }; PPGeTextDrawerImage im{}; auto cacheItem = textDrawerImages.find(key); @@ -805,7 +805,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(const char *text, PPGeAlign align, f cacheItem->second.entry.lastUsedFrame = gpuStats.numFlips; } else { std::vector bitmapData; - textDrawer->SetFontScale(scale, scale); + textDrawer->SetFontScale(style.scale, style.scale); Bounds b(0, 0, maxWidth, 272.0f); std::string cleaned = ReplaceAll(text, "\r", ""); textDrawer->DrawStringBitmapRect(bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign); @@ -842,7 +842,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(const char *text, PPGeAlign align, f return im; } -static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, PPGeAlign align, float scale, u32 color) { +static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, const PPGeStyle &style) { if (!im.ptr) { return; } @@ -855,41 +855,50 @@ static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, PPGeAlig WriteCmd(GE_CMD_TEXSIZE0, wp2 | (hp2 << 8)); WriteCmd(GE_CMD_TEXFLUSH, 0); - float w = im.entry.width * scale; - float h = im.entry.height * scale; + float w = im.entry.width * style.scale; + float h = im.entry.height * style.scale; - if (align & PPGeAlign::BOX_HCENTER) + if (style.align & PPGeAlign::BOX_HCENTER) x -= w / 2.0f; - else if (align & PPGeAlign::BOX_RIGHT) + else if (style.align & PPGeAlign::BOX_RIGHT) x -= w; - if (align & PPGeAlign::BOX_VCENTER) + if (style.align & PPGeAlign::BOX_VCENTER) y -= h / 2.0f; - else if (align & PPGeAlign::BOX_BOTTOM) + else if (style.align & PPGeAlign::BOX_BOTTOM) y -= h; BeginVertexData(); float u1 = (float)im.entry.width / (1 << wp2); float v1 = (float)im.entry.height / (1 << hp2); - Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, color); - Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, color); + if (style.hasShadow) { + Vertex(x + 1, y + 2, 0, 0, 1 << wp2, 1 << hp2, style.shadowColor); + Vertex(x + 1 + w, y + 2 + h, u1, v1, 1 << wp2, 1 << hp2, style.shadowColor); + } + Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, style.color); + Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, style.color); EndVertexDataAndDraw(GE_PRIM_RECTANGLES); PPGeSetDefaultTexture(); } -void PPGeDrawText(const char *text, float x, float y, PPGeAlign align, float scale, u32 color) { +void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { if (!text || !strlen(text)) { return; } if (HasTextDrawer()) { - PPGeTextDrawerImage im = PPGeGetTextImage(text, align, scale, 480.0f - x, false); - PPGeDrawTextImage(im, x, y, align, scale, color); + PPGeTextDrawerImage im = PPGeGetTextImage(text, style, 480.0f - x, false); + PPGeDrawTextImage(im, x, y, style); return; } - PPGePrepareText(text, x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS); - PPGeDrawCurrentText(color); + if (style.hasShadow) { + PPGePrepareText(text, x + 1, y + 2, style.align, style.scale, style.scale, PPGE_LINE_USE_ELLIPSIS); + PPGeDrawCurrentText(style.shadowColor); + } + + PPGePrepareText(text, x, y, style.align, style.scale, style.scale, PPGE_LINE_USE_ELLIPSIS); + PPGeDrawCurrentText(style.color); } static std::string StripTrailingWhite(const std::string &s) { @@ -915,7 +924,7 @@ static std::string CropLinesToCount(const std::string &s, int numLines) { return s.substr(0, len); } -void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, PPGeAlign align, float scale, u32 color) { +void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, const PPGeStyle &style) { std::string s = text; if (wrapHeight != 0.0f) { s = StripTrailingWhite(s); @@ -928,8 +937,11 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl float actualWidth, actualHeight; Bounds b(0, 0, wrapWidth <= 0 ? 480.0f - x : wrapWidth, wrapHeight); int tdalign = 0; - textDrawer->SetFontScale(scale, scale); + textDrawer->SetFontScale(style.scale, style.scale); textDrawer->MeasureStringRect(s.c_str(), s.size(), b, &actualWidth, &actualHeight, tdalign | FLAG_WRAP_TEXT); + + // Check if we need to scale the text down to fit better. + PPGeStyle adjustedStyle = style; if (wrapHeight != 0.0f && actualHeight > wrapHeight) { // Cheap way to get the line height. float oneLine, twoLines; @@ -945,16 +957,20 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl s = StripTrailingWhite(CropLinesToCount(s, (int)maxLines)) + "\n..."; } - scale *= wrapHeight / actualHeight; + adjustedStyle.scale *= wrapHeight / actualHeight; } - PPGeTextDrawerImage im = PPGeGetTextImage(s.c_str(), align, scale, wrapWidth <= 0 ? 480.0f - x : wrapWidth, true); - PPGeDrawTextImage(im, x, y, align, scale, color); + PPGeTextDrawerImage im = PPGeGetTextImage(s.c_str(), adjustedStyle, wrapWidth <= 0 ? 480.0f - x : wrapWidth, true); + PPGeDrawTextImage(im, x, y, adjustedStyle); return; } - PPGePrepareText(s.c_str(), x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); + int sx = style.hasShadow ? 1 : 0; + int sy = style.hasShadow ? 2 : 0; + PPGePrepareText(s.c_str(), x + sx, y + sy, style.align, style.scale, style.scale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); + float scale = style.scale; + float lineHeightScale = style.scale; float actualHeight = char_lines_metrics.lineHeight * char_lines_metrics.numLines; if (wrapHeight != 0.0f && actualHeight > wrapHeight) { if (actualHeight > wrapHeight * maxScaleDown) { @@ -967,11 +983,17 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl // Measure the text again after scaling down. PPGeResetCurrentText(); - float reduced = scale * wrapHeight / actualHeight; + float reduced = style.scale * wrapHeight / actualHeight; // Try to keep the font as large as possible, so reduce the line height some. - PPGePrepareText(s.c_str(), x, y, align, reduced * 1.15, reduced, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); + scale = reduced * 1.15f; + lineHeightScale = reduced; + PPGePrepareText(s.c_str(), x + sx, y + sy, style.align, scale, lineHeightScale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); } - PPGeDrawCurrentText(color); + if (style.hasShadow) { + PPGeDrawCurrentText(style.shadowColor); + PPGePrepareText(s.c_str(), x, y, style.align, scale, lineHeightScale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); + } + PPGeDrawCurrentText(style.color); } // Draws a "4-patch" for button-like things that can be resized @@ -1031,8 +1053,7 @@ void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color) { } // Just blits an image to the screen, multiplied with the color. -void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color) -{ +void PPGeDrawImage(ImageID atlasImage, float x, float y, const PPGeStyle &style) { if (!dlPtr) return; @@ -1043,13 +1064,16 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color) float w = img->w; float h = img->h; BeginVertexData(); - Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color); - Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color); + if (style.hasShadow) { + Vertex(x + 1, y + 2, img->u1, img->v1, atlasWidth, atlasHeight, style.shadowColor); + Vertex(x + 1 + w, y + 2 + h, img->u2, img->v2, atlasWidth, atlasHeight, style.shadowColor); + } + Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, style.color); + Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, style.color); EndVertexDataAndDraw(GE_PRIM_RECTANGLES); } -void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int align, u32 color) -{ +void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, const PPGeStyle &style) { if (!dlPtr) return; @@ -1058,8 +1082,12 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int a return; } BeginVertexData(); - Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color); - Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color); + if (style.hasShadow) { + Vertex(x + 1, y + 2, img->u1, img->v1, atlasWidth, atlasHeight, style.shadowColor); + Vertex(x + 1 + w, y + 2 + h, img->u2, img->v2, atlasWidth, atlasHeight, style.shadowColor); + } + Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, style.color); + Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, style.color); EndVertexDataAndDraw(GE_PRIM_RECTANGLES); } diff --git a/Core/Util/PPGeDraw.h b/Core/Util/PPGeDraw.h index 38eddea82c..b309a29a38 100644 --- a/Core/Util/PPGeDraw.h +++ b/Core/Util/PPGeDraw.h @@ -69,20 +69,28 @@ enum { PPGE_LINE_WRAP_CHAR = 4, }; +struct PPGeStyle { + PPGeAlign align = PPGeAlign::BOX_LEFT; + float scale = 1.0f; + uint32_t color = 0xFFFFFFFF; + bool hasShadow = false; + uint32_t shadowColor = 0x80000000; +}; + // Get the metrics of the bounding box of the text without changing the buffer or state. void PPGeMeasureText(float *w, float *h, const char *text, float scale, int WrapType = PPGE_LINE_NONE, int wrapWidth = 0); // Draws some text using the one font we have. // Clears the text buffer when done. -void PPGeDrawText(const char *text, float x, float y, PPGeAlign align, float scale = 1.0f, u32 color = 0xFFFFFFFF); -void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, PPGeAlign align, float scale = 1.0f, u32 color = 0xFFFFFFFF); +void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style); +void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, const PPGeStyle &style); // Draws a "4-patch" for button-like things that can be resized. void PPGeDraw4Patch(ImageID atlasImage, float x, float y, float w, float h, u32 color = 0xFFFFFFFF); // Just blits an image to the screen, multiplied with the color. -void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color = 0xFFFFFFFF); -void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int align, u32 color = 0xFFFFFFFF); +void PPGeDrawImage(ImageID atlasImage, float x, float y, const PPGeStyle &style); +void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, const PPGeStyle &style); void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float u2, float v2, int tw, int th, u32 color); void PPGeNotifyFrame(); From 3586128d8d532e6bec39fde1a54457e9ff926980 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 21:42:30 -0700 Subject: [PATCH 2/6] PPGe: Draw nicer drop shadows. Only when we have a text drawer for text, because it really adds up. --- Core/Util/PPGeDraw.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 688d11cb42..ce03f15e8f 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -17,6 +17,7 @@ #include +#include "base/colorutil.h" #include "base/stringutil.h" #include "file/vfs.h" #include "gfx/texture_atlas.h" @@ -140,6 +141,7 @@ void PPGeSetTexture(u32 dataAddr, int width, int height); static void WriteCmd(u8 cmd, u32 data) { Memory::Write_U32((cmd << 24) | (data & 0xFFFFFF), dlWritePtr); dlWritePtr += 4; + assert(dlWritePtr <= dlPtr + dlSize); } static void WriteCmdAddrWithBase(u8 cmd, u32 addr) { @@ -178,6 +180,7 @@ static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color Memory::WriteStruct(dataWritePtr, &vtx); dataWritePtr += sizeof(vtx); } + assert(dataWritePtr <= dataPtr + dataSize); vertexCount++; } @@ -871,8 +874,15 @@ static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, const PP float u1 = (float)im.entry.width / (1 << wp2); float v1 = (float)im.entry.height / (1 << hp2); if (style.hasShadow) { - Vertex(x + 1, y + 2, 0, 0, 1 << wp2, 1 << hp2, style.shadowColor); - Vertex(x + 1 + w, y + 2 + h, u1, v1, 1 << wp2, 1 << hp2, style.shadowColor); + // Draw more shadows for a blurrier shadow. + for (float dy = 0.0f; dy <= 2.0f; dy += 1.0f) { + for (float dx = 0.0f; dx <= 1.0f; dx += 0.5f) { + if (dx == 0.0f && dy == 0.0f) + continue; + Vertex(x + dx, y + dy, 0, 0, 1 << wp2, 1 << hp2, alphaMul(style.shadowColor, 0.35f)); + Vertex(x + dx + w, y + dy + h, u1, v1, 1 << wp2, 1 << hp2, alphaMul(style.shadowColor, 0.35f)); + } + } } Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, style.color); Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, style.color); @@ -893,6 +903,7 @@ void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { } if (style.hasShadow) { + // This doesn't have the nicer shadow because it's so many verts. PPGePrepareText(text, x + 1, y + 2, style.align, style.scale, style.scale, PPGE_LINE_USE_ELLIPSIS); PPGeDrawCurrentText(style.shadowColor); } @@ -990,6 +1001,7 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl PPGePrepareText(s.c_str(), x + sx, y + sy, style.align, scale, lineHeightScale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); } if (style.hasShadow) { + // This doesn't have the nicer shadow because it's so many verts. PPGeDrawCurrentText(style.shadowColor); PPGePrepareText(s.c_str(), x, y, style.align, scale, lineHeightScale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth); } @@ -1065,8 +1077,14 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, const PPGeStyle &style) float h = img->h; BeginVertexData(); if (style.hasShadow) { - Vertex(x + 1, y + 2, img->u1, img->v1, atlasWidth, atlasHeight, style.shadowColor); - Vertex(x + 1 + w, y + 2 + h, img->u2, img->v2, atlasWidth, atlasHeight, style.shadowColor); + for (float dy = 0.0f; dy <= 2.0f; dy += 1.0f) { + for (float dx = 0.0f; dx <= 1.0f; dx += 0.5f) { + if (dx == 0.0f && dy == 0.0f) + continue; + Vertex(x + dx, y + dy, img->u1, img->v1, atlasWidth, atlasHeight, alphaMul(style.shadowColor, 0.35f)); + Vertex(x + dx + w, y + dy + h, img->u2, img->v2, atlasWidth, atlasHeight, alphaMul(style.shadowColor, 0.35f)); + } + } } Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, style.color); Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, style.color); @@ -1083,8 +1101,14 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, const } BeginVertexData(); if (style.hasShadow) { - Vertex(x + 1, y + 2, img->u1, img->v1, atlasWidth, atlasHeight, style.shadowColor); - Vertex(x + 1 + w, y + 2 + h, img->u2, img->v2, atlasWidth, atlasHeight, style.shadowColor); + for (float dy = 0.0f; dy <= 2.0f; dy += 1.0f) { + for (float dx = 0.0f; dx <= 1.0f; dx += 0.5f) { + if (dx == 0.0f && dy == 0.0f) + continue; + Vertex(x + dx, y + dy, img->u1, img->v1, atlasWidth, atlasHeight, alphaMul(style.shadowColor, 0.35f)); + Vertex(x + dx + w, y + dy + h, img->u2, img->v2, atlasWidth, atlasHeight, alphaMul(style.shadowColor, 0.35f)); + } + } } Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, style.color); Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, style.color); From b181a93e5ea36bdf08921890c0a1daec3579ebf7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 22:38:02 -0700 Subject: [PATCH 3/6] MsgDialog: Add scrollbar when message is long. Some games hard wrap their messages, and PSP firmware also showed a scrollbar. Let's do the same. One intentional difference: trying to ensure we always show part of a hidden line to make it clear to the user that there's more text. --- Core/Dialog/PSPMsgDialog.cpp | 122 +++++++++++++++++++++++------------ Core/Dialog/PSPMsgDialog.h | 3 + Core/Util/PPGeDraw.cpp | 14 +++- Core/Util/PPGeDraw.h | 4 ++ 4 files changed, 98 insertions(+), 45 deletions(-) diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index b40fc05857..1f0dabe46d 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "Core/Dialog/PSPMsgDialog.h" #include "Core/Util/PPGeDraw.h" #include "Core/HLE/sceCtrl.h" @@ -66,6 +67,9 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { } flag = 0; + scrollPos_ = 0.0f; + framesUpHeld_ = 0; + framesDownHeld_ = 0; // Check request invalidity if(messageDialog.type == 0 && !(messageDialog.errorNum & 0x80000000)) @@ -141,67 +145,92 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { return 0; } -void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) -{ +void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { + auto di = GetI18NCategory("Dialog"); + float WRAP_WIDTH = 300.0f; if (UTF8StringNonASCIICount(text.c_str()) > 3) WRAP_WIDTH = 372.0f; - float y = 140.0f; - float h, sy, ey; - PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); - float h2 = h / 2.0f; - ey = y + h2 + 20.0f; + float totalHeight = 0.0f; + PPGeMeasureText(nullptr, &totalHeight, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); + // The PSP normally only shows about 8 lines at a time. + // For improved UX, we intentionally show part of the next line. + float visibleHeight = std::min(totalHeight, 175.0f); + float h2 = visibleHeight / 2.0f; + + float centerY = 135.0f; + float sy = centerY - h2 - 15.0f; + float ey = centerY + h2 + 20.0f; + float buttonY = centerY + h2 + 5.0f; PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); + PPGeStyle messageStyle = FadedStyle(PPGeAlign::BOX_HCENTER, FONT_SCALE); - if (hasYesNo) - { - auto di = GetI18NCategory("Dialog"); - const char *choiceText; - float x, w; + auto drawSelectionBoxAndAdjust = [&](float x) { + // Box has a fixed size. + float w = 15.0f; + float h = 8.0f; + PPGeDrawRect(x - w, buttonY - h, x + w, buttonY + h, CalcFadedColor(0x6DCFCFCF)); + + centerY -= h + 5.0f; + sy -= h + 5.0f; + ey = buttonY + h * 2.0f + 5.0f; + }; + + if (hasYesNo) { if (yesnoChoice == 1) { - choiceText = di->T("Yes"); - x = 204.0f; + drawSelectionBoxAndAdjust(204.0f); + } else { + drawSelectionBoxAndAdjust(273.0f); } - else { - choiceText = di->T("No"); - x = 273.0f; - } - PPGeMeasureText(&w, &h, choiceText, FONT_SCALE); - w = 15.0f; - h = 8.0f; - float y2 = y + h2 + 8.0f; - h2 += h + 5.0f; - y = 135.0f - h; - PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); - PPGeDrawText(di->T("Yes"), 203.0f, y2 - 1.0f, textStyle); - PPGeDrawText(di->T("No"), 272.0f, y2 - 1.0f, textStyle); + + PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, textStyle); + PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, textStyle); if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { yesnoChoice = 1; - } - else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) { + } else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) { yesnoChoice = 0; } - ey = y2 + 25.0f; + buttonY += 8.0f + 5.0f; } if (hasOK) { - auto di = GetI18NCategory("Dialog"); - float x, w; - x = 240.0f; - w = 15.0f; - h = 8.0f; - float y2 = y + h2 + 8.0f; - h2 += h + 5.0f; - y = 135.0f - h; - PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); - PPGeDrawText(di->T("OK"), 239.0f, y2 - 1.0f, textStyle); - ey = y2 + 25.0f; + drawSelectionBoxAndAdjust(240.0f); + + PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, textStyle); + buttonY += 8.0f + 5.0f; + } + + PPGeScissor(0, (int)(centerY - h2 - 2), 480, (int)(centerY + h2 + 2)); + PPGeDrawTextWrapped(text.c_str(), 240.0f, centerY - h2 - scrollPos_, WRAP_WIDTH, 0, messageStyle); + PPGeScissorReset(); + + // Do we need a scrollbar? + if (visibleHeight < totalHeight) { + float scrollSpeed = 5.0f; + float scrollMax = totalHeight - visibleHeight; + + float bobHeight = (visibleHeight / totalHeight) * visibleHeight; + float bobOffset = (scrollPos_ / scrollMax) * (visibleHeight - bobHeight); + float bobY1 = centerY - h2 + bobOffset; + PPGeDrawRect(435.0f, bobY1, 440.0f, bobY1 + bobHeight, CalcFadedColor(0xFFCCCCCC)); + + auto buttonDown = [this](int btn, int &held) { + if (IsButtonPressed(btn)) { + held = 0; + return true; + } + return IsButtonHeld(btn, held, 1, 1); + }; + if (buttonDown(CTRL_DOWN, framesDownHeld_) && scrollPos_ < scrollMax) { + scrollPos_ = std::min(scrollMax, scrollPos_ + scrollSpeed); + } + if (buttonDown(CTRL_UP, framesUpHeld_) && scrollPos_ > 0.0f) { + scrollPos_ = std::max(0.0f, scrollPos_ - scrollSpeed); + } } - PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, 0, textStyle); - sy = 125.0f - h2; PPGeDrawRect(40.0f, sy, 440.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(40.0f, ey, 440.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); } @@ -314,6 +343,13 @@ void PSPMsgDialog::DoState(PointerWrap &p) p.Do(messageDialogAddr); p.DoArray(msgText, sizeof(msgText)); p.Do(yesnoChoice); + + // We don't save state this, you'll just have to scroll down again. + if (p.mode == p.MODE_READ) { + scrollPos_ = 0.0f; + framesUpHeld_ = 0; + framesDownHeld_ = 0; + } } pspUtilityDialogCommon *PSPMsgDialog::GetCommonParam() diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index 864420f0f0..64309f4659 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -98,5 +98,8 @@ private : char msgText[512]; int yesnoChoice; + float scrollPos_ = 0.0f; + int framesUpHeld_ = 0; + int framesDownHeld_ = 0; }; diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index ce03f15e8f..964dd45f0b 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -387,8 +387,7 @@ void PPGeBegin() PPGeSetDefaultTexture(); - WriteCmd(GE_CMD_SCISSOR1, (0 << 10) | 0); - WriteCmd(GE_CMD_SCISSOR2, (271 << 10) | 479); + PPGeScissor(0, 0, 480, 272); WriteCmd(GE_CMD_MINZ, 0); WriteCmd(GE_CMD_MAXZ, 0xFFFF); @@ -420,6 +419,17 @@ void PPGeEnd() } } +void PPGeScissor(int x1, int y1, int x2, int y2) { + assert(x1 >= 0 && x1 <= 480 && x2 >= 0 && x2 <= 480); + assert(y1 >= 0 && y1 <= 272 && y2 >= 0 && y2 <= 272); + WriteCmd(GE_CMD_SCISSOR1, (y1 << 10) | x1); + WriteCmd(GE_CMD_SCISSOR2, ((y2 - 1) << 10) | (x2 - 1)); +} + +void PPGeScissorReset() { + PPGeScissor(0, 0, 480, 272); +} + static const AtlasChar *PPGeGetChar(const AtlasFont &atlasfont, unsigned int cval) { const AtlasChar *c = atlasfont.getChar(cval); diff --git a/Core/Util/PPGeDraw.h b/Core/Util/PPGeDraw.h index b309a29a38..c9b625f40f 100644 --- a/Core/Util/PPGeDraw.h +++ b/Core/Util/PPGeDraw.h @@ -93,6 +93,10 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, const PPGeStyle &style) void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, const PPGeStyle &style); void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float u2, float v2, int tw, int th, u32 color); +// Note: x2/y2 are exclusive. +void PPGeScissor(int x1, int y1, int x2, int y2); +void PPGeScissorReset(); + void PPGeNotifyFrame(); class PPGeImage { From 3daf536e3c0db460a9b427cdd30c70878aa0b536 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 22:52:08 -0700 Subject: [PATCH 4/6] MsgDialog: Allow text to be wider. Our font is a bit different, let's add a bit more as long as the spacing looks okay. Reduce scale if there's a lot of non-ASCII, since the PSP's font seemed to use smaller glyphs than ours for those chars. --- Core/Dialog/PSPMsgDialog.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 1f0dabe46d..d90354f70f 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -148,9 +148,17 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { auto di = GetI18NCategory("Dialog"); - float WRAP_WIDTH = 300.0f; - if (UTF8StringNonASCIICount(text.c_str()) > 3) - WRAP_WIDTH = 372.0f; + PPGeStyle buttonStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); + PPGeStyle messageStyle = FadedStyle(PPGeAlign::BOX_HCENTER, FONT_SCALE); + + // Without the scrollbar, we have 390 total pixels. + float WRAP_WIDTH = 340.0f; + if (UTF8StringNonASCIICount(text.c_str()) >= text.size() / 4) { + WRAP_WIDTH = 376.0f; + if (text.size() > 12) { + messageStyle.scale = 0.6f; + } + } float totalHeight = 0.0f; PPGeMeasureText(nullptr, &totalHeight, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); @@ -164,9 +172,6 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { float ey = centerY + h2 + 20.0f; float buttonY = centerY + h2 + 5.0f; - PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); - PPGeStyle messageStyle = FadedStyle(PPGeAlign::BOX_HCENTER, FONT_SCALE); - auto drawSelectionBoxAndAdjust = [&](float x) { // Box has a fixed size. float w = 15.0f; @@ -185,8 +190,8 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { drawSelectionBoxAndAdjust(273.0f); } - PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, textStyle); - PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, textStyle); + PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, buttonStyle); + PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, buttonStyle); if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { yesnoChoice = 1; } else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) { @@ -198,7 +203,7 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { if (hasOK) { drawSelectionBoxAndAdjust(240.0f); - PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, textStyle); + PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, buttonStyle); buttonY += 8.0f + 5.0f; } From f16a6b8abdcb9055f81a96f74df4fc809ca2f355 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 23:11:03 -0700 Subject: [PATCH 5/6] MsgDialog: Show better error messages. I think the PSP really did just show error codes, but that's not a reason to keep that confusion going. For common save errors, let's show the messages. Some games, for example, simply show the no data found error when you play for the first time and trigger anything to check for data. --- Core/Dialog/PSPMsgDialog.cpp | 37 +++++++++++++++++++++++++++++++++++- Core/Dialog/PSPMsgDialog.h | 3 ++- Core/Dialog/SavedataParam.h | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index d90354f70f..7ddd1f8a73 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -17,6 +17,7 @@ #include #include "Core/Dialog/PSPMsgDialog.h" +#include "Core/Dialog/PSPSaveDialog.h" #include "Core/Util/PPGeDraw.h" #include "Core/HLE/sceCtrl.h" #include "Core/MemMapHelpers.h" @@ -133,7 +134,7 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { } if (flag & DS_ERRORMSG) { - snprintf(msgText, 512, "Error code: %08x", messageDialog.errorNum); + FormatErrorCode(messageDialog.errorNum); } else { truncate_cpy(msgText, messageDialog.string); } @@ -145,6 +146,40 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { return 0; } + +void PSPMsgDialog::FormatErrorCode(uint32_t code) { + auto di = GetI18NCategory("Dialog"); + + switch (code) { + case SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN: + snprintf(msgText, 512, "%s (%08x)", di->T("MsgErrorSavedataDataBroken", "Save data was corrupt."), code); + break; + + case SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_MS: + case SCE_UTILITY_SAVEDATA_ERROR_RW_NO_MEMSTICK: + case SCE_UTILITY_SAVEDATA_ERROR_SAVE_NO_MS: + case SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_MS: + case SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_MS: + snprintf(msgText, 512, "%s (%08x)", di->T("MsgErrorSavedataNoMS", "Memory stick not inserted."), code); + break; + + case SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA: + case SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA: + case SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_DATA: + case SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA: + snprintf(msgText, 512, "%s (%08x)", di->T("MsgErrorSavedataNoData", "Warning: no save data was found."), code); + break; + + case SCE_UTILITY_SAVEDATA_ERROR_RW_MEMSTICK_FULL: + case SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE: + snprintf(msgText, 512, "%s (%08x)", di->T("MsgErrorSavedataMSFull", "Memory stick full. Check your storage space."), code); + break; + + default: + snprintf(msgText, 512, "%s %08x", di->T("MsgErrorCode", "Error code:"), code); + } +} + void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK) { auto di = GetI18NCategory("Dialog"); diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index 64309f4659..78490393f8 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -74,7 +74,8 @@ protected: return false; } -private : +private: + void FormatErrorCode(uint32_t code); void DisplayMessage(std::string text, bool hasYesNo = false, bool hasOK = false); enum Flags diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index e509463712..857c69779b 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -17,6 +17,7 @@ #pragma once +#include #include "Common/CommonTypes.h" #include "Core/MemMap.h" #include "Core/HLE/sceRtc.h" From dd909d36cccbb9f2e84d42b71c8c494355e1555c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 May 2020 23:27:20 -0700 Subject: [PATCH 6/6] Osk: Draw shadows on all the letters. --- Core/Dialog/PSPOskDialog.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index f60f41ce5e..3041cae300 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -767,17 +767,13 @@ void PSPOskDialog::RenderKeyboard() float title = (480.0f - (0.5f * drawLimit)) / 2.0f; PPGeStyle descStyle = FadedStyle(PPGeAlign::BOX_CENTER, 0.5f); - descStyle.hasShadow = false; PPGeDrawText(oskDesc.c_str(), title, 20, descStyle); PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.5f); - textStyle.hasShadow = false; PPGeStyle keyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f); - keyStyle.hasShadow = false; PPGeStyle selectedKeyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f); selectedKeyStyle.color = CalcFadedColor(0xFF3060FF); - selectedKeyStyle.hasShadow = false; std::u16string result; @@ -954,9 +950,7 @@ int PSPOskDialog::Update(int animSpeed) { auto di = GetI18NCategory("Dialog"); PPGeStyle actionStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); - actionStyle.hasShadow = false; PPGeStyle guideStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.6f); - guideStyle.hasShadow = false; PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, guideStyle); PPGeDrawText(di->T("Space"), 390, 222, actionStyle);