Merge pull request #9501 from unknownbrackets/ui-background

UI: Add simple support for a custom background
This commit is contained in:
Henrik Rydgård 2017-03-29 11:11:43 +02:00 committed by GitHub
commit 84d7d5b8df
12 changed files with 262 additions and 97 deletions

View File

@ -63,65 +63,77 @@ struct ConfigSetting {
TYPE_TERMINATOR,
TYPE_BOOL,
TYPE_INT,
TYPE_UINT32,
TYPE_FLOAT,
TYPE_STRING,
};
union Value {
bool b;
int i;
uint32_t u;
float f;
const char *s;
};
union SettingPtr {
bool *b;
int *i;
uint32_t *u;
float *f;
std::string *s;
};
typedef bool (*BoolDefaultCallback)();
typedef int (*IntDefaultCallback)();
typedef uint32_t (*Uint32DefaultCallback)();
typedef float (*FloatDefaultCallback)();
typedef const char *(*StringDefaultCallback)();
union Callback {
BoolDefaultCallback b;
IntDefaultCallback i;
Uint32DefaultCallback u;
FloatDefaultCallback f;
StringDefaultCallback s;
};
ConfigSetting(bool v)
: ini_(""), type_(TYPE_TERMINATOR), report_(false), save_(false), perGame_(false) {
ptr_.b = NULL;
cb_.b = NULL;
ptr_.b = nullptr;
cb_.b = nullptr;
}
ConfigSetting(const char *ini, bool *v, bool def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_BOOL), report_(false), save_(save), perGame_(perGame) {
ptr_.b = v;
cb_.b = NULL;
cb_.b = nullptr;
default_.b = def;
}
ConfigSetting(const char *ini, int *v, int def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_INT), report_(false), save_(save), perGame_(perGame) {
ptr_.i = v;
cb_.i = NULL;
cb_.i = nullptr;
default_.i = def;
}
ConfigSetting(const char *ini, uint32_t *v, uint32_t def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_UINT32), report_(false), save_(save), perGame_(perGame) {
ptr_.u = v;
cb_.u = nullptr;
default_.u = def;
}
ConfigSetting(const char *ini, float *v, float def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_FLOAT), report_(false), save_(save), perGame_(perGame) {
ptr_.f = v;
cb_.f = NULL;
cb_.f = nullptr;
default_.f = def;
}
ConfigSetting(const char *ini, std::string *v, const char *def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_STRING), report_(false), save_(save), perGame_(perGame) {
ptr_.s = v;
cb_.s = NULL;
cb_.s = nullptr;
default_.s = def;
}
@ -133,10 +145,16 @@ struct ConfigSetting {
ConfigSetting(const char *ini, int *v, IntDefaultCallback def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_INT), report_(false), save_(save), perGame_(perGame) {
ptr_ .i= v;
ptr_ .i = v;
cb_.i = def;
}
ConfigSetting(const char *ini, uint32_t *v, Uint32DefaultCallback def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_UINT32), report_(false), save_(save), perGame_(perGame) {
ptr_ .u = v;
cb_.u = def;
}
ConfigSetting(const char *ini, float *v, FloatDefaultCallback def, bool save = true, bool perGame = false)
: ini_(ini), type_(TYPE_FLOAT), report_(false), save_(save), perGame_(perGame) {
ptr_.f = v;
@ -165,6 +183,11 @@ struct ConfigSetting {
default_.i = cb_.i();
}
return section->Get(ini_, ptr_.i, default_.i);
case TYPE_UINT32:
if (cb_.u) {
default_.u = cb_.u();
}
return section->Get(ini_, ptr_.u, default_.u);
case TYPE_FLOAT:
if (cb_.f) {
default_.f = cb_.f();
@ -190,6 +213,8 @@ struct ConfigSetting {
return section->Set(ini_, *ptr_.b);
case TYPE_INT:
return section->Set(ini_, *ptr_.i);
case TYPE_UINT32:
return section->Set(ini_, *ptr_.u);
case TYPE_FLOAT:
return section->Set(ini_, *ptr_.f);
case TYPE_STRING:
@ -209,6 +234,8 @@ struct ConfigSetting {
return data.Add(prefix + ini_, *ptr_.b);
case TYPE_INT:
return data.Add(prefix + ini_, *ptr_.i);
case TYPE_UINT32:
return data.Add(prefix + ini_, *ptr_.u);
case TYPE_FLOAT:
return data.Add(prefix + ini_, *ptr_.f);
case TYPE_STRING:
@ -770,6 +797,39 @@ static ConfigSetting upgradeSettings[] = {
ConfigSetting(false),
};
static ConfigSetting themeSettings[] = {
ConfigSetting("ItemStyleFg", &g_Config.uItemStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ItemStyleBg", &g_Config.uItemStyleBg, 0x55000000, true, false),
ConfigSetting("ItemFocusedStyleFg", &g_Config.uItemFocusedStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ItemFocusedStyleBg", &g_Config.uItemFocusedStyleBg, 0xFFEDC24C, true, false),
ConfigSetting("ItemDownStyleFg", &g_Config.uItemDownStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ItemDownStyleBg", &g_Config.uItemDownStyleBg, 0xFFBD9939, true, false),
ConfigSetting("ItemDisabledStyleFg", &g_Config.uItemDisabledStyleFg, 0x80EEEEEE, true, false),
ConfigSetting("ItemDisabledStyleBg", &g_Config.uItemDisabledStyleBg, 0x55E0D4AF, true, false),
ConfigSetting("ItemHighlightedStyleFg", &g_Config.uItemHighlightedStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ItemHighlightedStyleBg", &g_Config.uItemHighlightedStyleBg, 0x55BDBB39, true, false),
ConfigSetting("ButtonStyleFg", &g_Config.uButtonStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ButtonStyleBg", &g_Config.uButtonStyleBg, 0x55000000, true, false),
ConfigSetting("ButtonFocusedStyleFg", &g_Config.uButtonFocusedStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ButtonFocusedStyleBg", &g_Config.uButtonFocusedStyleBg, 0xFFEDC24C, true, false),
ConfigSetting("ButtonDownStyleFg", &g_Config.uButtonDownStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ButtonDownStyleBg", &g_Config.uButtonDownStyleBg, 0xFFBD9939, true, false),
ConfigSetting("ButtonDisabledStyleFg", &g_Config.uButtonDisabledStyleFg, 0x80EEEEEE, true, false),
ConfigSetting("ButtonDisabledStyleBg", &g_Config.uButtonDisabledStyleBg, 0x55E0D4AF, true, false),
ConfigSetting("ButtonHighlightedStyleFg", &g_Config.uButtonHighlightedStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("ButtonHighlightedStyleBg", &g_Config.uButtonHighlightedStyleBg, 0x55BDBB39, true, false),
ConfigSetting("HeaderStyleFg", &g_Config.uHeaderStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("InfoStyleFg", &g_Config.uInfoStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("InfoStyleBg", &g_Config.uInfoStyleBg, 0x00000000U, true, false),
ConfigSetting("PopupTitleStyleFg", &g_Config.uPopupTitleStyleFg, 0xFFE3BE59, true, false),
ConfigSetting("PopupStyleFg", &g_Config.uPopupStyleFg, 0xFFFFFFFF, true, false),
ConfigSetting("PopupStyleBg", &g_Config.uPopupStyleBg, 0xFF303030, true, false),
ConfigSetting(false),
};
static ConfigSectionSettings sections[] = {
{"General", generalSettings},
{"CPU", cpuSettings},
@ -782,6 +842,7 @@ static ConfigSectionSettings sections[] = {
{"SpeedHacks", speedHackSettings},
{"JIT", jitSettings},
{"Upgrade", upgradeSettings},
{"Theme", themeSettings},
};
static void IterateSettings(IniFile &iniFile, std::function<void(IniFile::Section *section, ConfigSetting *setting)> func) {

View File

@ -235,6 +235,36 @@ public:
bool bShowDebuggerOnLoad;
int iShowFPSCounter;
// TODO: Maybe move to a separate theme system.
uint32_t uItemStyleFg;
uint32_t uItemStyleBg;
uint32_t uItemFocusedStyleFg;
uint32_t uItemFocusedStyleBg;
uint32_t uItemDownStyleFg;
uint32_t uItemDownStyleBg;
uint32_t uItemDisabledStyleFg;
uint32_t uItemDisabledStyleBg;
uint32_t uItemHighlightedStyleFg;
uint32_t uItemHighlightedStyleBg;
uint32_t uButtonStyleFg;
uint32_t uButtonStyleBg;
uint32_t uButtonFocusedStyleFg;
uint32_t uButtonFocusedStyleBg;
uint32_t uButtonDownStyleFg;
uint32_t uButtonDownStyleBg;
uint32_t uButtonDisabledStyleFg;
uint32_t uButtonDisabledStyleBg;
uint32_t uButtonHighlightedStyleFg;
uint32_t uButtonHighlightedStyleBg;
uint32_t uHeaderStyleFg;
uint32_t uInfoStyleFg;
uint32_t uInfoStyleBg;
uint32_t uPopupTitleStyleFg;
uint32_t uPopupStyleFg;
uint32_t uPopupStyleBg;
bool bLogFrameDrops;
bool bShowDebugStats;
bool bShowAudioDebug;

View File

@ -985,8 +985,6 @@ UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) {
return UI::EVENT_DONE;
}
extern void DrawBackground(UIContext &dc, float alpha);
void MainScreen::DrawBackground(UIContext &dc) {
UIScreenWithBackground::DrawBackground(dc);
if (highlightedGamePath_.empty() && prevHighlightedGamePath_.empty()) {

View File

@ -69,7 +69,23 @@ static const uint32_t colors[4] = {
0xC0FFFFFF,
};
void DrawBackground(UIContext &dc, float alpha = 1.0f) {
static ManagedTexture *bgTexture = nullptr;
void UIBackgroundInit(UIContext &dc) {
const std::string bgPng = GetSysDirectory(DIRECTORY_SYSTEM) + "background.png";
const std::string bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) + "background.jpg";
if (File::Exists(bgPng) || File::Exists(bgJpg)) {
const std::string &bgFile = File::Exists(bgPng) ? bgPng : bgJpg;
bgTexture = CreateTextureFromFile(dc.GetDrawContext(), bgFile.c_str(), DETECT, true);
}
}
void UIBackgroundShutdown() {
delete bgTexture;
bgTexture = nullptr;
}
void DrawBackground(UIContext &dc, float alpha) {
static float xbase[100] = {0};
static float ybase[100] = {0};
float xres = dc.GetBounds().w;
@ -87,10 +103,20 @@ void DrawBackground(UIContext &dc, float alpha = 1.0f) {
last_yres = yres;
}
int img = I_BG;
uint32_t bgColor = whiteAlpha(alpha);
ui_draw2d.DrawImageStretch(img, dc.GetBounds(), bgColor);
if (bgTexture != nullptr) {
dc.Flush();
dc.GetDrawContext()->BindTexture(0, bgTexture->GetTexture());
dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, bgColor);
dc.Flush();
dc.RebindTexture();
} else {
ImageID img = I_BG;
ui_draw2d.DrawImageStretch(img, dc.GetBounds(), bgColor);
}
float t = time_now();
for (int i = 0; i < 100; i++) {
float x = xbase[i] + dc.GetBounds().x;
@ -216,7 +242,7 @@ UI::EventReturn UIDialogScreenWithBackground::OnLanguageChange(UI::EventParams &
}
void UIDialogScreenWithBackground::DrawBackground(UIContext &dc) {
::DrawBackground(dc);
::DrawBackground(dc, 1.0f);
dc.Flush();
}
@ -461,6 +487,7 @@ void LogoScreen::render() {
float alphaText = alpha;
if (t > 2.0f)
alphaText = 3.0f - t;
uint32_t textColor = colorAlpha(dc.theme->infoStyle.fgColor, alphaText);
::DrawBackground(dc, alpha);
@ -469,24 +496,24 @@ void LogoScreen::render() {
// Manually formatting utf-8 is fun. \xXX doesn't work everywhere.
snprintf(temp, sizeof(temp), "%s Henrik Rydg%c%crd", cr->T("created", "Created by"), 0xC3, 0xA5);
#ifdef GOLD
dc.Draw()->DrawImage(I_ICONGOLD, bounds.centerX() - 120, bounds.centerY() - 30, 1.2f, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.Draw()->DrawImage(I_ICONGOLD, bounds.centerX() - 120, bounds.centerY() - 30, 1.2f, textColor, ALIGN_CENTER);
#else
dc.Draw()->DrawImage(I_ICON, bounds.centerX() - 120, bounds.centerY() - 30, 1.2f, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.Draw()->DrawImage(I_ICON, bounds.centerX() - 120, bounds.centerY() - 30, 1.2f, textColor, ALIGN_CENTER);
#endif
dc.Draw()->DrawImage(I_LOGO, bounds.centerX() + 40, bounds.centerY() - 30, 1.5f, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
//dc.Draw()->DrawTextShadow(UBUNTU48, "PPSSPP", xres / 2, yres / 2 - 30, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.Draw()->DrawImage(I_LOGO, bounds.centerX() + 40, bounds.centerY() - 30, 1.5f, textColor, ALIGN_CENTER);
//dc.Draw()->DrawTextShadow(UBUNTU48, "PPSSPP", xres / 2, yres / 2 - 30, textColor, ALIGN_CENTER);
dc.SetFontScale(1.0f, 1.0f);
dc.SetFontStyle(dc.theme->uiFont);
dc.DrawText(temp, bounds.centerX(), bounds.centerY() + 40, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.DrawText(cr->T("license", "Free Software under GPL 2.0+"), bounds.centerX(), bounds.centerY() + 70, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.DrawText("www.ppsspp.org", bounds.centerX(), yres / 2 + 130, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.DrawText(temp, bounds.centerX(), bounds.centerY() + 40, textColor, ALIGN_CENTER);
dc.DrawText(cr->T("license", "Free Software under GPL 2.0+"), bounds.centerX(), bounds.centerY() + 70, textColor, ALIGN_CENTER);
dc.DrawText("www.ppsspp.org", bounds.centerX(), yres / 2 + 130, textColor, ALIGN_CENTER);
if (boot_filename.size()) {
dc.DrawTextShadow(boot_filename.c_str(), bounds.centerX(), bounds.centerY() + 180, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.DrawTextShadow(boot_filename.c_str(), bounds.centerX(), bounds.centerY() + 180, textColor, ALIGN_CENTER);
}
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
// Draw the graphics API, except on UWP where it's always D3D11
dc.DrawText(screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME).c_str(), bounds.centerX(), bounds.y2() - 100, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
dc.DrawText(screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME).c_str(), bounds.centerX(), bounds.y2() - 100, textColor, ALIGN_CENTER);
#endif
dc.End();
@ -691,9 +718,11 @@ void CreditsScreen::render() {
int y = bounds.y2() - (frames_ % totalHeight);
for (int i = 0; i < numItems; i++) {
float alpha = linearInOut(y+32, 64, bounds.y2() - 192, 64);
uint32_t textColor = colorAlpha(dc.theme->infoStyle.fgColor, alpha);
if (alpha > 0.0f) {
dc.SetFontScale(ease(alpha), ease(alpha));
dc.DrawText(credits[i], dc.GetBounds().centerX(), y, whiteAlpha(alpha), ALIGN_HCENTER);
dc.DrawText(credits[i], dc.GetBounds().centerX(), y, textColor, ALIGN_HCENTER);
dc.SetFontScale(1.0f, 1.0f);
}
y += itemHeight;

View File

@ -28,6 +28,8 @@
struct ShaderInfo;
extern std::string boot_filename;
void UIBackgroundInit(UIContext &dc);
void UIBackgroundShutdown();
inline void NoOpVoidBool(bool) {}
@ -147,7 +149,3 @@ private:
int frames_;
};
// Utility functions that create various popup screens
ListPopupScreen *CreateLanguageScreen();

View File

@ -534,18 +534,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
}
}
void NativeInitGraphics(GraphicsContext *graphicsContext) {
ILOG("NativeInitGraphics");
static UI::Style MakeStyle(uint32_t fg, uint32_t bg) {
UI::Style s;
s.background = UI::Drawable(bg);
s.fgColor = fg;
using namespace Draw;
Core_SetGraphicsContext(graphicsContext);
g_draw = graphicsContext->GetDrawContext();
return s;
}
ui_draw2d.SetAtlas(&ui_atlas);
ui_draw2d_front.SetAtlas(&ui_atlas);
// memset(&ui_theme, 0, sizeof(ui_theme));
// New style theme
static void UIThemeInit() {
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
ui_theme.uiFont = UI::FontStyle(UBUNTU24, g_Config.sFont.c_str(), 22);
ui_theme.uiFontSmall = UI::FontStyle(UBUNTU24, g_Config.sFont.c_str(), 15);
@ -562,23 +559,36 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
ui_theme.sliderKnob = I_CIRCLE;
ui_theme.dropShadow4Grid = I_DROP_SHADOW;
ui_theme.itemStyle.background = UI::Drawable(0x55000000);
ui_theme.itemStyle.fgColor = 0xFFFFFFFF;
ui_theme.itemFocusedStyle.background = UI::Drawable(0xFFedc24c);
ui_theme.itemDownStyle.background = UI::Drawable(0xFFbd9939);
ui_theme.itemDownStyle.fgColor = 0xFFFFFFFF;
ui_theme.itemDisabledStyle.background = UI::Drawable(0x55E0D4AF);
ui_theme.itemDisabledStyle.fgColor = 0x80EEEEEE;
ui_theme.itemHighlightedStyle.background = UI::Drawable(0x55bdBB39);
ui_theme.itemHighlightedStyle.fgColor = 0xFFFFFFFF;
ui_theme.itemStyle = MakeStyle(g_Config.uItemStyleFg, g_Config.uItemStyleBg);
ui_theme.itemFocusedStyle = MakeStyle(g_Config.uItemFocusedStyleFg, g_Config.uItemFocusedStyleBg);
ui_theme.itemDownStyle = MakeStyle(g_Config.uItemDownStyleFg, g_Config.uItemDownStyleBg);
ui_theme.itemDisabledStyle = MakeStyle(g_Config.uItemDisabledStyleFg, g_Config.uItemDisabledStyleBg);
ui_theme.itemHighlightedStyle = MakeStyle(g_Config.uItemHighlightedStyleFg, g_Config.uItemHighlightedStyleBg);
ui_theme.buttonStyle = ui_theme.itemStyle;
ui_theme.buttonFocusedStyle = ui_theme.itemFocusedStyle;
ui_theme.buttonDownStyle = ui_theme.itemDownStyle;
ui_theme.buttonDisabledStyle = ui_theme.itemDisabledStyle;
ui_theme.buttonHighlightedStyle = ui_theme.itemHighlightedStyle;
ui_theme.buttonStyle = MakeStyle(g_Config.uButtonStyleFg, g_Config.uButtonStyleBg);
ui_theme.buttonFocusedStyle = MakeStyle(g_Config.uButtonFocusedStyleFg, g_Config.uButtonFocusedStyleBg);
ui_theme.buttonDownStyle = MakeStyle(g_Config.uButtonDownStyleFg, g_Config.uButtonDownStyleBg);
ui_theme.buttonDisabledStyle = MakeStyle(g_Config.uButtonDisabledStyleFg, g_Config.uButtonDisabledStyleBg);
ui_theme.buttonHighlightedStyle = MakeStyle(g_Config.uButtonHighlightedStyleFg, g_Config.uButtonHighlightedStyleBg);
ui_theme.popupTitle.fgColor = 0xFFE3BE59;
ui_theme.headerStyle.fgColor = g_Config.uHeaderStyleFg;
ui_theme.infoStyle = MakeStyle(g_Config.uInfoStyleFg, g_Config.uInfoStyleBg);
ui_theme.popupTitle.fgColor = g_Config.uPopupTitleStyleFg;
ui_theme.popupStyle = MakeStyle(g_Config.uPopupStyleFg, g_Config.uPopupStyleBg);
}
void NativeInitGraphics(GraphicsContext *graphicsContext) {
ILOG("NativeInitGraphics");
using namespace Draw;
Core_SetGraphicsContext(graphicsContext);
g_draw = graphicsContext->GetDrawContext();
ui_draw2d.SetAtlas(&ui_atlas);
ui_draw2d_front.SetAtlas(&ui_atlas);
UIThemeInit();
uiTexture = CreateTextureFromFile(g_draw, "ui_atlas.zim", ImageFileType::ZIM);
if (!uiTexture) {
@ -633,6 +643,8 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
screenManager->setUIContext(uiContext);
screenManager->setDrawContext(g_draw);
UIBackgroundInit(*uiContext);
#ifdef _WIN32
winAudioBackend = CreateAudioBackend((AudioBackendType)g_Config.iAudioBackend);
#if PPSSPP_PLATFORM(UWP)
@ -651,17 +663,19 @@ void NativeShutdownGraphics() {
#ifdef _WIN32
delete winAudioBackend;
winAudioBackend = NULL;
winAudioBackend = nullptr;
#endif
delete g_gameInfoCache;
g_gameInfoCache = nullptr;
UIBackgroundShutdown();
delete uiTexture;
uiTexture = nullptr;
delete uiContext;
uiContext = NULL;
uiContext = nullptr;
ui_draw2d.Shutdown();
ui_draw2d_front.Shutdown();
@ -838,6 +852,10 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
g_Config.sNickName = setString;
inputboxValue.clear();
}
if (msg == "bgImage_updated") {
UIBackgroundShutdown();
UIBackgroundInit(*uiContext);
}
if (msg == "savestate_displayslot") {
I18NCategory *sy = GetI18NCategory("System");
std::string msg = StringFromFormat("%s: %d", sy->T("Savestate Slot"), SaveState::GetCurrentSlot() + 1);

View File

@ -67,6 +67,9 @@ public:
void CreatePopupContents(UI::ViewGroup *parent) override {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
const Style &textStyle = dc.theme->popupStyle;
GameInfo *ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
LinearLayout *content = new LinearLayout(ORIENT_VERTICAL);
parent->Add(content);
@ -85,12 +88,12 @@ public:
}
LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f));
topright->SetSpacing(1.0f);
topright->Add(new TextView(savedata_title, ALIGN_LEFT | FLAG_WRAP_TEXT, false));
topright->Add(new TextView(StringFromFormat("%d kB", ginfo->gameSize / 1024), 0, true));
topright->Add(new TextView(GetFileDateAsString(savePath_ + "/PARAM.SFO"), 0, true));
topright->Add(new TextView(savedata_title, ALIGN_LEFT | FLAG_WRAP_TEXT, false))->SetTextColor(textStyle.fgColor);
topright->Add(new TextView(StringFromFormat("%d kB", ginfo->gameSize / 1024), 0, true))->SetTextColor(textStyle.fgColor);
topright->Add(new TextView(GetFileDateAsString(savePath_ + "/PARAM.SFO"), 0, true))->SetTextColor(textStyle.fgColor);
toprow->Add(topright);
content->Add(new Spacer(3.0));
content->Add(new TextView(ReplaceAll(savedata_detail, "\r", ""), ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(Margins(10, 0))));
content->Add(new TextView(ReplaceAll(savedata_detail, "\r", ""), ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(Margins(10, 0))))->SetTextColor(textStyle.fgColor);
content->Add(new Spacer(3.0));
} else {
std::string image_path = ReplaceAll(savePath_, ".ppst", ".jpg");
@ -98,9 +101,9 @@ public:
PrioritizedWorkQueue *wq = g_gameInfoCache->WorkQueue();
toprow->Add(new AsyncImageFileView(image_path, IS_DEFAULT, wq, new LinearLayoutParams(480, 272, Margins(10, 0))));
} else {
toprow->Add(new TextView(sa->T("No screenshot"), new LinearLayoutParams(Margins(10, 5))));
toprow->Add(new TextView(sa->T("No screenshot"), new LinearLayoutParams(Margins(10, 5))))->SetTextColor(textStyle.fgColor);
}
content->Add(new TextView(GetFileDateAsString(savePath_), 0, true, new LinearLayoutParams(Margins(10, 5))));
content->Add(new TextView(GetFileDateAsString(savePath_), 0, true, new LinearLayoutParams(Margins(10, 5))))->SetTextColor(textStyle.fgColor);
}
I18NCategory *di = GetI18NCategory("Dialog");

View File

@ -117,7 +117,7 @@ public:
void MeasureImage(ImageID atlas_image, float *w, float *h);
void DrawImage(ImageID atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT);
void DrawImageStretch(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF));
void DrawImageStretch(int atlas_image, const Bounds &bounds, Color color = COLOR(0xFFFFFF)) {
void DrawImageStretch(ImageID atlas_image, const Bounds &bounds, Color color = COLOR(0xFFFFFF)) {
DrawImageStretch(atlas_image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), color);
}
void DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers

View File

@ -249,16 +249,10 @@ bool PopupScreen::key(const KeyInput &key) {
void PopupScreen::update() {
UIDialogScreen::update();
static const int FRAMES_LEAD_IN = 6;
static const int FRAMES_LEAD_OUT = 4;
float animatePos = 1.0f;
++frames_;
if (frames_ < FRAMES_LEAD_IN) {
float leadIn = bezierEaseInOut(frames_ * (1.0f / (float)FRAMES_LEAD_IN));
animatePos = leadIn;
} else if (finishFrame_ > 0) {
if (finishFrame_ >= 0) {
float leadOut = bezierEaseInOut((frames_ - finishFrame_) * (1.0f / (float)FRAMES_LEAD_OUT));
animatePos = 1.0f - leadOut;
@ -266,6 +260,9 @@ void PopupScreen::update() {
// Actual finish happens here.
screenManager()->finishDialog(this, finishResult_);
}
} else if (frames_ < FRAMES_LEAD_IN) {
float leadIn = bezierEaseInOut(frames_ * (1.0f / (float)FRAMES_LEAD_IN));
animatePos = leadIn;
}
if (animatePos < 1.0f) {
@ -306,7 +303,6 @@ void PopupScreen::TriggerFinish(DialogResult result) {
void PopupScreen::CreateViews() {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
@ -319,7 +315,7 @@ void PopupScreen::CreateViews() {
new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true));
root_->Add(box_);
box_->SetBG(UI::Drawable(0xFF303030));
box_->SetBG(dc.theme->popupStyle.background);
box_->SetHasDropShadow(true);
// Since we scale a bit, make the dropshadow bleed past the edges.
box_->SetDropShadowExpand(std::max(dp_xres, dp_yres));
@ -354,10 +350,13 @@ void PopupScreen::CreateViews() {
}
void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
std::vector<std::string> messageLines;
SplitString(message_, '\n', messageLines);
for (const auto& lineOfText : messageLines)
parent->Add(new UI::TextView(lineOfText, ALIGN_LEFT | ALIGN_VCENTER, false));
parent->Add(new UI::TextView(lineOfText, ALIGN_LEFT | ALIGN_VCENTER, false))->SetTextColor(dc.theme->popupStyle.fgColor);
}
void MessagePopupScreen::OnCompleted(DialogResult result) {
@ -621,23 +620,29 @@ EventReturn SliderPopupScreen::OnTextChange(EventParams &params) {
void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
sliderValue_ = *value_;
LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10))));
slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10)));
slider_->OnChange.Handle(this, &SliderPopupScreen::OnSliderChange);
vert->Add(slider_);
LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10))));
lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease);
lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease);
char temp[64];
sprintf(temp, "%d", sliderValue_);
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
edit_->SetMaxLen(16);
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
edit_->OnTextChange.Handle(this, &SliderPopupScreen::OnTextChange);
changing_ = false;
lin->Add(edit_);
if (!units_.empty())
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)))->SetTextColor(dc.theme->popupStyle.fgColor);
if (IsFocusMovementEnabled())
UI::SetFocusedView(slider_);
@ -645,23 +650,28 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
sliderValue_ = *value_;
LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10))));
slider_ = new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10)));
slider_->OnChange.Handle(this, &SliderFloatPopupScreen::OnSliderChange);
vert->Add(slider_);
LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10))));
lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnDecrease);
lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnIncrease);
char temp[64];
sprintf(temp, "%0.3f", sliderValue_);
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
edit_->SetMaxLen(16);
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange);
changing_ = false;
lin->Add(edit_);
if (!units_.empty())
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)))->SetTextColor(dc.theme->popupStyle.fgColor);
// slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5))));
if (IsFocusMovementEnabled())
@ -778,11 +788,13 @@ EventReturn PopupTextInputChoice::HandleChange(EventParams &e) {
void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
textEditValue_ = *value_;
LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams((UI::Size)300, WRAP_CONTENT)));
edit_ = new TextEdit(textEditValue_, placeholder_, new LinearLayoutParams(1.0f));
edit_->SetMaxLen(maxLen_);
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
lin->Add(edit_);
if (IsFocusMovementEnabled())

View File

@ -91,8 +91,13 @@ private:
std::string button1_;
std::string button2_;
enum {
FRAMES_LEAD_IN = 6,
FRAMES_LEAD_OUT = 4,
};
int frames_ = 0;
int finishFrame_ = 0;
int finishFrame_ = -1;
DialogResult finishResult_;
bool hasPopupOrigin_ = false;
Point popupOrigin_;

View File

@ -522,16 +522,16 @@ void Choice::Draw(UIContext &dc) {
void InfoItem::Draw(UIContext &dc) {
Item::Draw(dc);
if (HasFocus()) {
UI::Style style = dc.theme->itemFocusedStyle;
style.background.color &= 0x7fffffff;
dc.FillRect(style.background, bounds_);
}
UI::Style style = HasFocus() ? dc.theme->itemFocusedStyle : dc.theme->infoStyle;
style.background.color &= 0x7fffffff;
dc.FillRect(style.background, bounds_);
int paddingX = 12;
dc.SetFontStyle(dc.theme->uiFont);
dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER);
dc.DrawText(rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT);
dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
dc.DrawText(rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER | ALIGN_RIGHT);
// dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor);
}
@ -543,8 +543,8 @@ ItemHeader::ItemHeader(const std::string &text, LayoutParams *layoutParams)
void ItemHeader::Draw(UIContext &dc) {
dc.SetFontStyle(dc.theme->uiFontSmall);
dc.DrawText(text_.c_str(), bounds_.x + 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF);
dc.DrawText(text_.c_str(), bounds_.x + 4, bounds_.centerY(), dc.theme->headerStyle.fgColor, ALIGN_LEFT | ALIGN_VCENTER);
dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->headerStyle.fgColor);
}
void PopupHeader::Draw(UIContext &dc) {
@ -756,14 +756,16 @@ void TextView::Draw(UIContext &dc) {
uint32_t shadowColor = 0x80000000;
dc.DrawTextRect(text_.c_str(), bounds_, shadowColor, textAlign_);
}
dc.DrawTextRect(text_.c_str(), bounds_, textColor_, textAlign_);
uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor;
dc.DrawTextRect(text_.c_str(), bounds_, textColor, textAlign_);
if (clip) {
dc.PopScissor();
}
}
TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams)
: View(layoutParams), text_(text), undo_(text), placeholderText_(placeholderText), maxLen_(255), ctrlDown_(false) {
: View(layoutParams), text_(text), undo_(text), placeholderText_(placeholderText),
textColor_(0xFFFFFFFF), maxLen_(255) {
caret_ = (int)text_.size();
}
@ -772,6 +774,7 @@ void TextEdit::Draw(UIContext &dc) {
dc.SetFontStyle(dc.theme->uiFont);
dc.FillRect(HasFocus() ? UI::Drawable(0x80000000) : UI::Drawable(0x30000000), bounds_);
uint32_t textColor = hasTextColor_ ? textColor_ : dc.theme->infoStyle.fgColor;
float textX = bounds_.x;
float w, h;
@ -780,10 +783,11 @@ void TextEdit::Draw(UIContext &dc) {
if (text_.empty()) {
if (placeholderText_.size()) {
dc.DrawTextRect(placeholderText_.c_str(), bounds_, 0x50FFFFFF, ALIGN_CENTER);
uint32_t c = textColor & 0x50FFFFFF;
dc.DrawTextRect(placeholderText_.c_str(), bounds_, c, ALIGN_CENTER);
}
} else {
dc.DrawTextRect(text_.c_str(), textBounds, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_LEFT);
dc.DrawTextRect(text_.c_str(), textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT);
}
if (HasFocus()) {
@ -796,7 +800,7 @@ void TextEdit::Draw(UIContext &dc) {
// Scroll text to the left if the caret won't fit. Not ideal but looks better than not scrolling it.
textX -= caretX - bounds_.w;
}
dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4));
dc.FillRect(UI::Drawable(textColor), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4));
}
dc.PopScissor();
}
@ -1094,18 +1098,19 @@ void Slider::Clamp() {
void Slider::Draw(UIContext &dc) {
bool focus = HasFocus();
uint32_t linecolor = dc.theme->popupTitle.fgColor;
uint32_t knobcolor = (down_ || focus) ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF;
Style knobStyle = (down_ || focus) ? dc.theme->popupTitle : dc.theme->popupStyle;
float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_);
dc.FillRect(Drawable(linecolor), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4));
dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4));
dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobcolor, ALIGN_CENTER);
dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobStyle.fgColor, ALIGN_CENTER);
char temp[64];
if (showPercent_)
sprintf(temp, "%i%%", *value_);
else
sprintf(temp, "%i", *value_);
dc.SetFontStyle(dc.theme->uiFont);
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER);
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER);
}
void Slider::Update() {
@ -1205,16 +1210,16 @@ void SliderFloat::Clamp() {
void SliderFloat::Draw(UIContext &dc) {
bool focus = HasFocus();
uint32_t linecolor = dc.theme->popupTitle.fgColor;
uint32_t knobcolor = (down_ || focus) ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF;
Style knobStyle = (down_ || focus) ? dc.theme->popupTitle : dc.theme->popupStyle;
float knobX = (*value_ - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_);
dc.FillRect(Drawable(linecolor), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4));
dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4));
dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobcolor, ALIGN_CENTER);
dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobStyle.fgColor, ALIGN_CENTER);
char temp[64];
sprintf(temp, "%0.2f", *value_);
dc.SetFontStyle(dc.theme->uiFont);
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER);
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER);
}
void SliderFloat::Update() {

View File

@ -117,8 +117,10 @@ struct Theme {
Style itemHighlightedStyle;
Style headerStyle;
Style infoStyle;
Style popupTitle;
Style popupStyle;
};
// The four cardinal directions should be enough, plus Prev/Next in "element order".
@ -759,7 +761,7 @@ public:
void SetText(const std::string &text) { text_ = text; }
const std::string &GetText() const { return text_; }
void SetSmall(bool small) { small_ = small; }
void SetTextColor(uint32_t color) { textColor_ = color; }
void SetTextColor(uint32_t color) { textColor_ = color; hasTextColor_ = true; }
void SetShadow(bool shadow) { shadow_ = shadow; }
void SetFocusable(bool focusable) { focusable_ = focusable; }
void SetClip(bool clip) { clip_ = clip; }
@ -770,6 +772,7 @@ private:
std::string text_;
int textAlign_;
uint32_t textColor_;
bool hasTextColor_ = false;
bool small_;
bool shadow_;
bool focusable_;
@ -780,6 +783,7 @@ class TextEdit : public View {
public:
TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams = 0);
void SetText(const std::string &text) { text_ = text; caret_ = (int)text_.size(); }
void SetTextColor(uint32_t color) { textColor_ = color; hasTextColor_ = true; }
const std::string &GetText() const { return text_; }
void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; }
@ -797,9 +801,11 @@ private:
std::string text_;
std::string undo_;
std::string placeholderText_;
uint32_t textColor_;
bool hasTextColor_ = false;
int caret_;
size_t maxLen_;
bool ctrlDown_; // TODO: Make some global mechanism for this.
bool ctrlDown_ = false; // TODO: Make some global mechanism for this.
// TODO: Selections
};