Merge branch 'ppge-scroll' of https://github.com/unknownbrackets/ppsspp into unknownbrackets-ppge-scroll

This commit is contained in:
Henrik Rydgård 2020-07-19 14:09:24 +02:00
commit 79b3352b67
10 changed files with 338 additions and 166 deletions

View File

@ -198,6 +198,16 @@ bool PSPDialog::IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThr
return false; 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) void PSPDialog::DisplayButtons(int flags, const char *caption)
{ {
bool useCaption = false; bool useCaption = false;
@ -207,6 +217,8 @@ void PSPDialog::DisplayButtons(int flags, const char *caption)
truncate_cpy(safeCaption, caption); truncate_cpy(safeCaption, caption);
} }
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, FONT_SCALE);
auto di = GetI18NCategory("Dialog"); auto di = GetI18NCategory("Dialog");
float x1 = 183.5f, x2 = 261.5f; float x1 = 183.5f, x2 = 261.5f;
if (GetCommonParam()->buttonSwap == 1) { if (GetCommonParam()->buttonSwap == 1) {
@ -215,16 +227,12 @@ void PSPDialog::DisplayButtons(int flags, const char *caption)
} }
if (flags & DS_BUTTON_OK) { if (flags & DS_BUTTON_OK) {
const char *text = useCaption ? safeCaption : di->T("Enter"); 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, textStyle);
PPGeDrawImage(okButtonImg, x2, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(text, x2 + 14.5f, 252, textStyle);
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));
} }
if (flags & DS_BUTTON_CANCEL) { if (flags & DS_BUTTON_CANCEL) {
const char *text = useCaption ? safeCaption : di->T("Back"); const char *text = useCaption ? safeCaption : di->T("Back");
PPGeDrawText(text, x1 + 15.5f, 254, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, textStyle);
PPGeDrawText(text, x1 + 14.5f, 252, PPGeAlign::BOX_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(text, x1 + 14.5f, 252, textStyle);
PPGeDrawImage(cancelButtonImg, x1, 258, 11.5f, 11.5f, 0, CalcFadedColor(0x80000000));
PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF));
} }
} }

View File

@ -22,6 +22,7 @@
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Swap.h" #include "Common/Swap.h"
#include "Core/Util/PPGeDraw.h"
class PointerWrap; class PointerWrap;
@ -83,6 +84,7 @@ public:
void StartDraw(); void StartDraw();
void EndDraw(); void EndDraw();
protected: protected:
PPGeStyle FadedStyle(PPGeAlign align, float scale);
void UpdateButtons(); void UpdateButtons();
bool IsButtonPressed(int checkButton); bool IsButtonPressed(int checkButton);
bool IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold = 30, int framesHeldRepeatRate = 10); bool IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold = 30, int framesHeldRepeatRate = 10);

View File

@ -15,7 +15,9 @@
// Official git repository and contact information can be found at // Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include "Core/Dialog/PSPMsgDialog.h" #include "Core/Dialog/PSPMsgDialog.h"
#include "Core/Dialog/PSPSaveDialog.h"
#include "Core/Util/PPGeDraw.h" #include "Core/Util/PPGeDraw.h"
#include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceCtrl.h"
#include "Core/MemMapHelpers.h" #include "Core/MemMapHelpers.h"
@ -66,6 +68,9 @@ int PSPMsgDialog::Init(unsigned int paramAddr) {
} }
flag = 0; flag = 0;
scrollPos_ = 0.0f;
framesUpHeld_ = 0;
framesDownHeld_ = 0;
// Check request invalidity // Check request invalidity
if(messageDialog.type == 0 && !(messageDialog.errorNum & 0x80000000)) if(messageDialog.type == 0 && !(messageDialog.errorNum & 0x80000000))
@ -129,7 +134,7 @@ int PSPMsgDialog::Init(unsigned int paramAddr) {
} }
if (flag & DS_ERRORMSG) { if (flag & DS_ERRORMSG) {
snprintf(msgText, 512, "Error code: %08x", messageDialog.errorNum); FormatErrorCode(messageDialog.errorNum);
} else { } else {
truncate_cpy(msgText, messageDialog.string); truncate_cpy(msgText, messageDialog.string);
} }
@ -141,74 +146,131 @@ int PSPMsgDialog::Init(unsigned int paramAddr) {
return 0; return 0;
} }
void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK)
{
float WRAP_WIDTH = 300.0f;
if (UTF8StringNonASCIICount(text.c_str()) > 3)
WRAP_WIDTH = 372.0f;
float y = 140.0f; void PSPMsgDialog::FormatErrorCode(uint32_t code) {
float h, sy, ey; auto di = GetI18NCategory("Dialog");
PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
float h2 = h / 2.0f;
ey = y + h2 + 20.0f;
if (hasYesNo) switch (code) {
{ case SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN:
auto di = GetI18NCategory("Dialog"); snprintf(msgText, 512, "%s (%08x)", di->T("MsgErrorSavedataDataBroken", "Save data was corrupt."), code);
const char *choiceText; break;
u32 yesColor, noColor;
float x, w; 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");
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);
// 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;
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) { if (yesnoChoice == 1) {
choiceText = di->T("Yes"); drawSelectionBoxAndAdjust(204.0f);
x = 204.0f; } else {
yesColor = 0xFFFFFFFF; drawSelectionBoxAndAdjust(273.0f);
noColor = 0xFFFFFFFF;
} }
else {
choiceText = di->T("No"); PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, buttonStyle);
x = 273.0f; PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, buttonStyle);
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
}
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"), 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));
if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) {
yesnoChoice = 1; yesnoChoice = 1;
} } else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) {
else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) {
yesnoChoice = 0; yesnoChoice = 0;
} }
ey = y2 + 25.0f; buttonY += 8.0f + 5.0f;
} }
if (hasOK) { if (hasOK) {
auto di = GetI18NCategory("Dialog"); drawSelectionBoxAndAdjust(240.0f);
float x, w;
x = 240.0f; PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, buttonStyle);
w = 15.0f; buttonY += 8.0f + 5.0f;
h = 8.0f; }
float y2 = y + h2 + 8.0f;
h2 += h + 5.0f; PPGeScissor(0, (int)(centerY - h2 - 2), 480, (int)(centerY + h2 + 2));
y = 135.0f - h; PPGeDrawTextWrapped(text.c_str(), 240.0f, centerY - h2 - scrollPos_, WRAP_WIDTH, 0, messageStyle);
PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); PPGeScissorReset();
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)); // Do we need a scrollbar?
ey = y2 + 25.0f; 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(), 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));
sy = 125.0f - h2;
PPGeDrawRect(40.0f, sy, 440.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(40.0f, sy, 440.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawRect(40.0f, ey, 440.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(40.0f, ey, 440.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF));
} }
@ -321,6 +383,13 @@ void PSPMsgDialog::DoState(PointerWrap &p)
p.Do(messageDialogAddr); p.Do(messageDialogAddr);
p.DoArray(msgText, sizeof(msgText)); p.DoArray(msgText, sizeof(msgText));
p.Do(yesnoChoice); 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() pspUtilityDialogCommon *PSPMsgDialog::GetCommonParam()

View File

@ -74,7 +74,8 @@ protected:
return false; return false;
} }
private : private:
void FormatErrorCode(uint32_t code);
void DisplayMessage(std::string text, bool hasYesNo = false, bool hasOK = false); void DisplayMessage(std::string text, bool hasYesNo = false, bool hasOK = false);
enum Flags enum Flags
@ -98,5 +99,8 @@ private :
char msgText[512]; char msgText[512];
int yesnoChoice; int yesnoChoice;
float scrollPos_ = 0.0f;
int framesUpHeld_ = 0;
int framesDownHeld_ = 0;
}; };

View File

@ -65,10 +65,13 @@ void PSPNetconfDialog::DrawBanner() {
PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358)); PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358));
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f);
textStyle.hasShadow = false;
// TODO: Draw a hexagon icon // 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"); 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) { 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 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; 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) { if (request.netAction == NETCONF_CONNECT_APNET || request.netAction == NETCONF_STATUS_APNET || request.netAction == NETCONF_CONNECT_APNET_LAST) {
UpdateFade(animSpeed); UpdateFade(animSpeed);
StartDraw(); StartDraw();
DrawBanner(); DrawBanner();
PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0x63636363)); 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)); 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, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(confirmBtnImage, 195, 250, 20, 20, buttonStyle);
PPGeDrawText(di->T("OK"), 225, 252, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(di->T("OK"), 225, 252, buttonStyle);
if (IsButtonPressed(confirmBtn)) { if (IsButtonPressed(confirmBtn)) {
StartFade(false); StartFade(false);

View File

@ -766,7 +766,14 @@ void PSPOskDialog::RenderKeyboard()
float previewLeftSide = (480.0f - (12.0f * drawLimit)) / 2.0f; float previewLeftSide = (480.0f - (12.0f * drawLimit)) / 2.0f;
float title = (480.0f - (0.5f * 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);
PPGeDrawText(oskDesc.c_str(), title, 20, descStyle);
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.5f);
PPGeStyle keyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f);
PPGeStyle selectedKeyStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f);
selectedKeyStyle.color = CalcFadedColor(0xFF3060FF);
std::u16string result; std::u16string result;
@ -776,12 +783,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. 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) for (u32 i = 0; i < drawLimit; ++i, ++drawIndex)
{ {
u32 color = CalcFadedColor(0xFFFFFFFF);
if (drawIndex + 1 < result.size()) if (drawIndex + 1 < result.size())
{ {
temp[0] = result[drawIndex]; temp[0] = result[drawIndex];
ConvertUCS2ToUTF8(buffer, temp); 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 else
{ {
@ -794,25 +800,25 @@ void PSPOskDialog::RenderKeyboard()
float animStep = (float)(__DisplayGetNumVblanks() % 40) / 20.0f; 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. // 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; 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); 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. // Also draw the underline for the same reason.
color = CalcFadedColor(0xFFFFFFFF); PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, textStyle);
PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color);
} }
else else
{ {
ConvertUCS2ToUTF8(buffer, temp); 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 else
{ {
PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, PPGeAlign::BOX_HCENTER, 0.5f, color); PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, textStyle);
} }
} }
} }
@ -821,17 +827,16 @@ void PSPOskDialog::RenderKeyboard()
{ {
for (int col = 0; col < numKeyCols[currentKeyboard]; ++col) 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]; temp[0] = oskKeys[currentKeyboard][row][col];
ConvertUCS2ToUTF8(buffer, temp); 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) 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)); 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 +949,25 @@ int PSPOskDialog::Update(int animSpeed) {
auto di = GetI18NCategory("Dialog"); auto di = GetI18NCategory("Dialog");
PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); PPGeStyle actionStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f);
PPGeDrawText(di->T("Space"), 390, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeStyle guideStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.6f);
PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, guideStyle);
PPGeDrawText(di->T("Space"), 390, 222, actionStyle);
if (g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE) { if (g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE) {
PPGeDrawImage(ImageID("I_CROSS"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(ImageID("I_CROSS"), 45, 222, 16, 16, guideStyle);
PPGeDrawImage(ImageID("I_CIRCLE"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(ImageID("I_CIRCLE"), 45, 247, 16, 16, guideStyle);
} else { } else {
PPGeDrawImage(ImageID("I_CIRCLE"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(ImageID("I_CIRCLE"), 45, 222, 16, 16, guideStyle);
PPGeDrawImage(ImageID("I_CROSS"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF)); 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("Select"), 75, 222, actionStyle);
PPGeDrawText(di->T("Delete"), 75, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(di->T("Delete"), 75, 247, actionStyle);
PPGeDrawText("Start", 135, 220, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText("Start", 135, 220, guideStyle);
PPGeDrawText(di->T("Finish"), 185, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(di->T("Finish"), 185, 222, actionStyle);
auto lookupLangName = [&](int direction) { auto lookupLangName = [&](int direction) {
// First, find the valid one... // First, find the valid one...
@ -983,20 +991,20 @@ int PSPOskDialog::Update(int animSpeed) {
}; };
if (OskKeyboardNames[currentKeyboardLanguage] != "ko_KR" && IsKeyboardShiftValid(oskParams->fields[0].inputtype, currentKeyboardLanguage, currentKeyboard)) { if (OskKeyboardNames[currentKeyboardLanguage] != "ko_KR" && IsKeyboardShiftValid(oskParams->fields[0].inputtype, currentKeyboardLanguage, currentKeyboard)) {
PPGeDrawText("Select", 135, 245, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText("Select", 135, 245, guideStyle);
PPGeDrawText(di->T("Shift"), 185, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(di->T("Shift"), 185, 247, actionStyle);
} }
const char *prevLang = lookupLangName(-1); const char *prevLang = lookupLangName(-1);
if (prevLang) { if (prevLang) {
PPGeDrawText("L", 235, 220, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText("L", 235, 220, guideStyle);
PPGeDrawText(prevLang, 255, 222, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(prevLang, 255, 222, actionStyle);
} }
const char *nextLang = lookupLangName(1); const char *nextLang = lookupLangName(1);
if (nextLang) { if (nextLang) {
PPGeDrawText("R", 235, 245, PPGeAlign::BOX_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText("R", 235, 245, guideStyle);
PPGeDrawText(nextLang, 255, 247, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(nextLang, 255, 247, actionStyle);
} }
if (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) { if (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate)) {

View File

@ -283,6 +283,10 @@ void PSPSaveDialog::DisplayBanner(int which)
{ {
auto di = GetI18NCategory("Dialog"); auto di = GetI18NCategory("Dialog");
PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358)); PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358));
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f);
textStyle.hasShadow = false;
const char *title; const char *title;
switch (which) switch (which)
{ {
@ -300,8 +304,8 @@ void PSPSaveDialog::DisplayBanner(int which)
break; break;
} }
// TODO: Draw a hexagon icon // 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);
PPGeDrawText(title, 30, 11, PPGeAlign::BOX_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(title, 30, 11, textStyle);
} }
void PSPSaveDialog::DisplaySaveList(bool canMove) { void PSPSaveDialog::DisplaySaveList(bool canMove) {
@ -436,7 +440,8 @@ void PSPSaveDialog::DisplaySaveDataInfo1() {
if (saveInfo.size == 0) { if (saveInfo.size == 0) {
auto di = GetI18NCategory("Dialog"); 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 { } else {
char hour_time[32]; char hour_time[32];
FormatSaveHourMin(hour_time, sizeof(hour_time), saveInfo.modif_time); FormatSaveHourMin(hour_time, sizeof(hour_time), saveInfo.modif_time);
@ -452,14 +457,15 @@ void PSPSaveDialog::DisplaySaveDataInfo1() {
std::string saveTitleTxt = saveInfo.saveTitle; std::string saveTitleTxt = saveInfo.saveTitle;
std::string saveDetailTxt = saveInfo.saveDetail; std::string saveDetailTxt = saveInfo.saveDetail;
PPGeDrawText(titleTxt.c_str(), 181, 138, PPGeAlign::BOX_BOTTOM, 0.6f, CalcFadedColor(0x80000000)); PPGeStyle titleStyle = FadedStyle(PPGeAlign::BOX_BOTTOM, 0.6f);
PPGeDrawText(titleTxt.c_str(), 180, 136, PPGeAlign::BOX_BOTTOM, 0.6f, CalcFadedColor(0xFFC0C0C0)); PPGeStyle saveTitleStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.55f);
PPGeDrawText(timeTxt.c_str(), 181, 139, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); titleStyle.color = CalcFadedColor(0xFFC0C0C0);
PPGeDrawText(timeTxt.c_str(), 180, 137, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f);
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)); PPGeDrawText(titleTxt.c_str(), 180, 136, titleStyle);
PPGeDrawTextWrapped(saveDetailTxt.c_str(), 176, 183, 480 - 175, 250 - 183, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); PPGeDrawText(timeTxt.c_str(), 180, 137, textStyle);
PPGeDrawTextWrapped(saveDetailTxt.c_str(), 175, 181, 480 - 175, 250 - 181, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawText(saveTitleTxt.c_str(), 175, 159, saveTitleStyle);
PPGeDrawTextWrapped(saveDetailTxt.c_str(), 175, 181, 480 - 175, 250 - 181, textStyle);
} }
} }
@ -491,13 +497,15 @@ void PSPSaveDialog::DisplaySaveDataInfo2(bool showNewData) {
s64 sizeK = data_size / 1024; s64 sizeK = data_size / 1024;
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f);
std::string saveinfoTxt = StringFromFormat("%.128s\n%s %s\n%lld KB", save_title, date_year, hour_time, sizeK); std::string saveinfoTxt = StringFromFormat("%.128s\n%s %s\n%lld KB", save_title, date_year, hour_time, sizeK);
PPGeDrawText(saveinfoTxt.c_str(), 9, 202, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0x80000000)); PPGeDrawText(saveinfoTxt.c_str(), 8, 200, textStyle);
PPGeDrawText(saveinfoTxt.c_str(), 8, 200, PPGeAlign::BOX_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
} }
void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
{ {
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE);
const float WRAP_WIDTH = 254.0f; const float WRAP_WIDTH = 254.0f;
float y = 136.0f, h; float y = 136.0f, h;
PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
@ -506,19 +514,14 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
{ {
auto di = GetI18NCategory("Dialog"); auto di = GetI18NCategory("Dialog");
const char *choiceText; const char *choiceText;
u32 yesColor, noColor;
float x, w; float x, w;
if (yesnoChoice == 1) { if (yesnoChoice == 1) {
choiceText = di->T("Yes"); choiceText = di->T("Yes");
x = 302.0f; x = 302.0f;
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
} }
else { else {
choiceText = di->T("No"); choiceText = di->T("No");
x = 366.0f; x = 366.0f;
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
} }
PPGeMeasureText(&w, &h, choiceText, FONT_SCALE); PPGeMeasureText(&w, &h, choiceText, FONT_SCALE);
w = w / 2.0f + 5.5f; w = w / 2.0f + 5.5f;
@ -527,10 +530,8 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
h2 += h + 4.0f; h2 += h + 4.0f;
y = 132.0f - h; y = 132.0f - h;
PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x40C0C0C0)); 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, textStyle);
PPGeDrawText(di->T("Yes"), 302.0f, y2, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(yesColor)); PPGeDrawText(di->T("No"), 366.0f, y2, textStyle);
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));
if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) {
yesnoChoice = 1; yesnoChoice = 1;
} }
@ -538,8 +539,7 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
yesnoChoice = 0; 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, textStyle);
PPGeDrawTextWrapped(text.c_str(), 334.0f, y, WRAP_WIDTH, 0, PPGeAlign::BOX_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF));
float sy = 122.0f - h2, ey = 150.0f + h2; float sy = 122.0f - h2, ey = 150.0f + h2;
PPGeDrawRect(202.0f, sy, 466.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(202.0f, sy, 466.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawRect(202.0f, ey, 466.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(202.0f, ey, 466.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF));

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include <set>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/MemMap.h" #include "Core/MemMap.h"
#include "Core/HLE/sceRtc.h" #include "Core/HLE/sceRtc.h"

View File

@ -17,6 +17,7 @@
#include <algorithm> #include <algorithm>
#include "base/colorutil.h"
#include "base/stringutil.h" #include "base/stringutil.h"
#include "file/vfs.h" #include "file/vfs.h"
#include "gfx/texture_atlas.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) { static void WriteCmd(u8 cmd, u32 data) {
Memory::Write_U32((cmd << 24) | (data & 0xFFFFFF), dlWritePtr); Memory::Write_U32((cmd << 24) | (data & 0xFFFFFF), dlWritePtr);
dlWritePtr += 4; dlWritePtr += 4;
assert(dlWritePtr <= dlPtr + dlSize);
} }
static void WriteCmdAddrWithBase(u8 cmd, u32 addr) { 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); Memory::WriteStruct(dataWritePtr, &vtx);
dataWritePtr += sizeof(vtx); dataWritePtr += sizeof(vtx);
} }
assert(dataWritePtr <= dataPtr + dataSize);
vertexCount++; vertexCount++;
} }
@ -384,8 +387,7 @@ void PPGeBegin()
PPGeSetDefaultTexture(); PPGeSetDefaultTexture();
WriteCmd(GE_CMD_SCISSOR1, (0 << 10) | 0); PPGeScissor(0, 0, 480, 272);
WriteCmd(GE_CMD_SCISSOR2, (271 << 10) | 479);
WriteCmd(GE_CMD_MINZ, 0); WriteCmd(GE_CMD_MINZ, 0);
WriteCmd(GE_CMD_MAXZ, 0xFFFF); WriteCmd(GE_CMD_MAXZ, 0xFFFF);
@ -417,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) static const AtlasChar *PPGeGetChar(const AtlasFont &atlasfont, unsigned int cval)
{ {
const AtlasChar *c = atlasfont.getChar(cval); const AtlasChar *c = atlasfont.getChar(cval);
@ -789,14 +802,14 @@ int GetPow2(int x) {
return ret; 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; int tdalign = 0;
tdalign |= FLAG_ELLIPSIZE_TEXT; tdalign |= FLAG_ELLIPSIZE_TEXT;
if (wrap) { if (wrap) {
tdalign |= FLAG_WRAP_TEXT; tdalign |= FLAG_WRAP_TEXT;
} }
PPGeTextDrawerCacheKey key{ text, tdalign, maxWidth / scale }; PPGeTextDrawerCacheKey key{ text, tdalign, maxWidth / style.scale };
PPGeTextDrawerImage im{}; PPGeTextDrawerImage im{};
auto cacheItem = textDrawerImages.find(key); auto cacheItem = textDrawerImages.find(key);
@ -805,7 +818,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(const char *text, PPGeAlign align, f
cacheItem->second.entry.lastUsedFrame = gpuStats.numFlips; cacheItem->second.entry.lastUsedFrame = gpuStats.numFlips;
} else { } else {
std::vector<uint8_t> bitmapData; std::vector<uint8_t> bitmapData;
textDrawer->SetFontScale(scale, scale); textDrawer->SetFontScale(style.scale, style.scale);
Bounds b(0, 0, maxWidth, 272.0f); Bounds b(0, 0, maxWidth, 272.0f);
std::string cleaned = ReplaceAll(text, "\r", ""); std::string cleaned = ReplaceAll(text, "\r", "");
textDrawer->DrawStringBitmapRect(bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign); textDrawer->DrawStringBitmapRect(bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign);
@ -842,7 +855,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(const char *text, PPGeAlign align, f
return im; 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) { if (!im.ptr) {
return; return;
} }
@ -855,41 +868,58 @@ static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, PPGeAlig
WriteCmd(GE_CMD_TEXSIZE0, wp2 | (hp2 << 8)); WriteCmd(GE_CMD_TEXSIZE0, wp2 | (hp2 << 8));
WriteCmd(GE_CMD_TEXFLUSH, 0); WriteCmd(GE_CMD_TEXFLUSH, 0);
float w = im.entry.width * scale; float w = im.entry.width * style.scale;
float h = im.entry.height * scale; float h = im.entry.height * style.scale;
if (align & PPGeAlign::BOX_HCENTER) if (style.align & PPGeAlign::BOX_HCENTER)
x -= w / 2.0f; x -= w / 2.0f;
else if (align & PPGeAlign::BOX_RIGHT) else if (style.align & PPGeAlign::BOX_RIGHT)
x -= w; x -= w;
if (align & PPGeAlign::BOX_VCENTER) if (style.align & PPGeAlign::BOX_VCENTER)
y -= h / 2.0f; y -= h / 2.0f;
else if (align & PPGeAlign::BOX_BOTTOM) else if (style.align & PPGeAlign::BOX_BOTTOM)
y -= h; y -= h;
BeginVertexData(); BeginVertexData();
float u1 = (float)im.entry.width / (1 << wp2); float u1 = (float)im.entry.width / (1 << wp2);
float v1 = (float)im.entry.height / (1 << hp2); float v1 = (float)im.entry.height / (1 << hp2);
Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, color); if (style.hasShadow) {
Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, color); // 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);
EndVertexDataAndDraw(GE_PRIM_RECTANGLES); EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
PPGeSetDefaultTexture(); 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)) { if (!text || !strlen(text)) {
return; return;
} }
if (HasTextDrawer()) { if (HasTextDrawer()) {
PPGeTextDrawerImage im = PPGeGetTextImage(text, align, scale, 480.0f - x, false); PPGeTextDrawerImage im = PPGeGetTextImage(text, style, 480.0f - x, false);
PPGeDrawTextImage(im, x, y, align, scale, color); PPGeDrawTextImage(im, x, y, style);
return; return;
} }
PPGePrepareText(text, x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS); if (style.hasShadow) {
PPGeDrawCurrentText(color); // 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);
}
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) { static std::string StripTrailingWhite(const std::string &s) {
@ -915,7 +945,7 @@ static std::string CropLinesToCount(const std::string &s, int numLines) {
return s.substr(0, len); 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; std::string s = text;
if (wrapHeight != 0.0f) { if (wrapHeight != 0.0f) {
s = StripTrailingWhite(s); s = StripTrailingWhite(s);
@ -928,8 +958,11 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl
float actualWidth, actualHeight; float actualWidth, actualHeight;
Bounds b(0, 0, wrapWidth <= 0 ? 480.0f - x : wrapWidth, wrapHeight); Bounds b(0, 0, wrapWidth <= 0 ? 480.0f - x : wrapWidth, wrapHeight);
int tdalign = 0; 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); 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) { if (wrapHeight != 0.0f && actualHeight > wrapHeight) {
// Cheap way to get the line height. // Cheap way to get the line height.
float oneLine, twoLines; float oneLine, twoLines;
@ -945,16 +978,20 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl
s = StripTrailingWhite(CropLinesToCount(s, (int)maxLines)) + "\n..."; 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); PPGeTextDrawerImage im = PPGeGetTextImage(s.c_str(), adjustedStyle, wrapWidth <= 0 ? 480.0f - x : wrapWidth, true);
PPGeDrawTextImage(im, x, y, align, scale, color); PPGeDrawTextImage(im, x, y, adjustedStyle);
return; 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; float actualHeight = char_lines_metrics.lineHeight * char_lines_metrics.numLines;
if (wrapHeight != 0.0f && actualHeight > wrapHeight) { if (wrapHeight != 0.0f && actualHeight > wrapHeight) {
if (actualHeight > wrapHeight * maxScaleDown) { if (actualHeight > wrapHeight * maxScaleDown) {
@ -967,11 +1004,18 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl
// Measure the text again after scaling down. // Measure the text again after scaling down.
PPGeResetCurrentText(); 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. // 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) {
// 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);
}
PPGeDrawCurrentText(style.color);
} }
// Draws a "4-patch" for button-like things that can be resized // Draws a "4-patch" for button-like things that can be resized
@ -1031,8 +1075,7 @@ void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color) {
} }
// Just blits an image to the screen, multiplied with the 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) if (!dlPtr)
return; return;
@ -1043,13 +1086,22 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color)
float w = img->w; float w = img->w;
float h = img->h; float h = img->h;
BeginVertexData(); BeginVertexData();
Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color); if (style.hasShadow) {
Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color); 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);
EndVertexDataAndDraw(GE_PRIM_RECTANGLES); 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) if (!dlPtr)
return; return;
@ -1058,8 +1110,18 @@ void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int a
return; return;
} }
BeginVertexData(); BeginVertexData();
Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color); if (style.hasShadow) {
Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color); 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);
EndVertexDataAndDraw(GE_PRIM_RECTANGLES); EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
} }

View File

@ -69,22 +69,34 @@ enum {
PPGE_LINE_WRAP_CHAR = 4, 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. // 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); 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. // Draws some text using the one font we have.
// Clears the text buffer when done. // 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 PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style);
void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, PPGeAlign align, float scale = 1.0f, u32 color = 0xFFFFFFFF); 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. // 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); 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. // 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, const PPGeStyle &style);
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, 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 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(); void PPGeNotifyFrame();
class PPGeImage { class PPGeImage {