daybreak: various ux improvements (#1080)

This commit is contained in:
Adubbz 2020-07-09 21:33:52 +10:00 committed by GitHub
parent 8d6e076b77
commit 084dd3232e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 281 additions and 21 deletions

View file

@ -26,10 +26,6 @@ extern "C" {
void userAppInit(void) {
Result rc = 0;
if (R_FAILED(rc = amssuInitialize())) {
fatalThrow(rc);
}
if (R_FAILED(rc = romfsInit())) {
fatalThrow(rc);
}
@ -42,6 +38,10 @@ extern "C" {
fatalThrow(rc);
}
if (R_FAILED(rc = splInitialize())) {
fatalThrow(rc);
}
if (R_FAILED(rc = hiddbgInitialize())) {
fatalThrow(rc);
}
@ -50,6 +50,7 @@ extern "C" {
void userAppExit(void) {
hiddbgExit();
splExit();
plExit();
spsmExit();
romfsExit();

View file

@ -26,6 +26,10 @@ namespace dbk {
namespace {
static constexpr u32 ExosphereApiVersionConfigItem = 65000;
static constexpr u32 ExosphereHasRcmBugPatch = 65004;
static constexpr u32 ExosphereEmummcType = 65007;
u32 g_screen_width;
u32 g_screen_height;
@ -313,6 +317,132 @@ namespace dbk {
return m_prev_menu;
}
ErrorMenu::ErrorMenu(const char *text, const char *subtext, Result rc) : Menu(nullptr), m_text{}, m_subtext{}, m_result_text{}, m_rc(rc) {
const float window_height = WindowHeight + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
/* Copy the input text. */
strncpy(m_text, text, sizeof(m_text)-1);
strncpy(m_subtext, subtext, sizeof(m_subtext)-1);
/* Copy result text if there is a result. */
if (R_FAILED(rc)) {
snprintf(m_result_text, sizeof(m_result_text)-1, "Result: 0x%08x", rc);
}
const float button_y = y + TitleGap + SubTextHeight + VerticalGap + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
this->AddButton(ExitButtonId, "Exit", x + HorizontalGap, button_y, ButtonWidth, ButtonHeight);
this->SetButtonSelected(ExitButtonId, true);
}
void ErrorMenu::Update(u64 ns) {
u64 k_down = hidKeysDown(CONTROLLER_P1_AUTO);
/* Go back if B is pressed. */
if (k_down & KEY_B) {
g_exit_requested = true;
return;
}
/* Take action if a button has been activated. */
if (const Button *activated_button = this->GetActivatedButton(); activated_button != nullptr) {
switch (activated_button->id) {
case ExitButtonId:
g_exit_requested = true;
break;
}
}
this->UpdateButtons();
/* Fallback on selecting the exfat button. */
if (const Button *selected_button = this->GetSelectedButton(); k_down && selected_button == nullptr) {
this->SetButtonSelected(ExitButtonId, true);
}
}
void ErrorMenu::Draw(NVGcontext *vg, u64 ns) {
const float window_height = WindowHeight + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
DrawWindow(vg, m_text, x, y, WindowWidth, window_height);
DrawText(vg, x + HorizontalGap, y + TitleGap, WindowWidth - HorizontalGap * 2.0f, m_subtext);
/* Draw the result if there is one. */
if (R_FAILED(m_rc)) {
DrawText(vg, x + HorizontalGap, y + TitleGap + SubTextHeight, WindowWidth - HorizontalGap * 2.0f, m_result_text);
}
this->DrawButtons(vg, ns);
}
WarningMenu::WarningMenu(std::shared_ptr<Menu> prev_menu, std::shared_ptr<Menu> next_menu, const char *text, const char *subtext, Result rc) : Menu(prev_menu), m_next_menu(next_menu), m_text{}, m_subtext{}, m_result_text{}, m_rc(rc) {
const float window_height = WindowHeight + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
/* Copy the input text. */
strncpy(m_text, text, sizeof(m_text)-1);
strncpy(m_subtext, subtext, sizeof(m_subtext)-1);
/* Copy result text if there is a result. */
if (R_FAILED(rc)) {
snprintf(m_result_text, sizeof(m_result_text)-1, "Result: 0x%08x", rc);
}
const float button_y = y + TitleGap + SubTextHeight + VerticalGap + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
this->AddButton(BackButtonId, "Back", x + HorizontalGap, button_y, ButtonWidth, ButtonHeight);
this->AddButton(ContinueButtonId, "Continue", x + HorizontalGap + ButtonWidth + ButtonHorizontalGap, button_y, ButtonWidth, ButtonHeight);
this->SetButtonSelected(ContinueButtonId, true);
}
void WarningMenu::Update(u64 ns) {
u64 k_down = hidKeysDown(CONTROLLER_P1_AUTO);
/* Go back if B is pressed. */
if (k_down & KEY_B) {
ReturnToPreviousMenu();
return;
}
/* Take action if a button has been activated. */
if (const Button *activated_button = this->GetActivatedButton(); activated_button != nullptr) {
switch (activated_button->id) {
case BackButtonId:
ReturnToPreviousMenu();
return;
case ContinueButtonId:
ChangeMenu(m_next_menu);
return;
}
}
this->UpdateButtons();
/* Fallback on selecting the exfat button. */
if (const Button *selected_button = this->GetSelectedButton(); k_down && selected_button == nullptr) {
this->SetButtonSelected(ContinueButtonId, true);
}
}
void WarningMenu::Draw(NVGcontext *vg, u64 ns) {
const float window_height = WindowHeight + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
DrawWindow(vg, m_text, x, y, WindowWidth, window_height);
DrawText(vg, x + HorizontalGap, y + TitleGap, WindowWidth - HorizontalGap * 2.0f, m_subtext);
/* Draw the result if there is one. */
if (R_FAILED(m_rc)) {
DrawText(vg, x + HorizontalGap, y + TitleGap + SubTextHeight, WindowWidth - HorizontalGap * 2.0f, m_result_text);
}
this->DrawButtons(vg, ns);
}
MainMenu::MainMenu() : Menu(nullptr) {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
@ -333,11 +463,42 @@ namespace dbk {
if (const Button *activated_button = this->GetActivatedButton(); activated_button != nullptr) {
switch (activated_button->id) {
case InstallButtonId:
ChangeMenu(std::make_shared<FileMenu>(g_current_menu, "/"));
break;
{
const auto file_menu = std::make_shared<FileMenu>(g_current_menu, "/");
Result rc = 0;
u64 hardware_type;
u64 has_rcm_bug_patch;
u64 is_emummc;
if (R_FAILED(rc = splGetConfig(SplConfigItem_HardwareType, &hardware_type))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to get hardware type.", rc));
return;
}
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereHasRcmBugPatch), &has_rcm_bug_patch))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to check RCM bug status.", rc));
return;
}
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereEmummcType), &is_emummc))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to chech emuMMC status.", rc));
return;
}
/* Warn if we're working with a patched unit. */
const bool is_erista = hardware_type == 0 || hardware_type == 1;
if (is_erista && has_rcm_bug_patch && !is_emummc) {
ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, file_menu, "Warning: Patched unit detected", "You may burn fuses or render your switch inoperable."));
} else {
ChangeMenu(file_menu);
}
return;
}
case ExitButtonId:
g_exit_requested = true;
break;
return;
}
}
@ -737,9 +898,18 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
this->AddButton(Fat32ButtonId, "FAT32", x + ButtonHorizontalInset, y + TitleGap, ButtonWidth, ButtonHeight);
this->AddButton(ExFatButtonId, "exFAT", x + ButtonHorizontalInset + ButtonWidth + ButtonHorizontalGap, y + TitleGap, ButtonWidth, ButtonHeight);
this->SetButtonSelected(ExFatButtonId, true);
this->AddButton(Fat32ButtonId, "Install (FAT32)", x + ButtonHorizontalInset, y + TitleGap, ButtonWidth, ButtonHeight);
this->AddButton(ExFatButtonId, "Install (exFAT/FAT32)", x + ButtonHorizontalInset + ButtonWidth + ButtonHorizontalGap, y + TitleGap, ButtonWidth, ButtonHeight);
/* Set the default selected button based on the user's current install. We aren't particularly concerned if fsIsExFatSupported fails. */
bool exfat_supported = false;
fsIsExFatSupported(&exfat_supported);
if (exfat_supported) {
this->SetButtonSelected(ExFatButtonId, true);
} else {
this->SetButtonSelected(Fat32ButtonId, true);
}
}
void ChooseExfatMenu::Update(u64 ns) {
@ -930,15 +1100,40 @@ namespace dbk {
}
void InitializeMenu(u32 screen_width, u32 screen_height) {
Result rc = 0;
/* Set the screen width and height. */
g_screen_width = screen_width;
g_screen_height = screen_height;
/* Change the current menu to the main menu. */
g_current_menu = std::make_shared<MainMenu>();
/* Mark as initialized. */
g_initialized = true;
/* Attempt to get the exosphere version. */
u64 version;
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereApiVersionConfigItem), &version))) {
ChangeMenu(std::make_shared<ErrorMenu>("Atmosphere not found", "Daybreak requires Atmosphere to be installed.", rc));
return;
}
const u32 version_micro = (version >> 40) & 0xff;
const u32 version_minor = (version >> 48) & 0xff;
const u32 version_major = (version >> 56) & 0xff;
/* Validate the exosphere version. */
const bool ams_supports_sysupdate_api = version_major >= 0 && version_minor >= 14 && version_micro >= 0;
if (!ams_supports_sysupdate_api) {
ChangeMenu(std::make_shared<ErrorMenu>("Outdated Atmosphere version", "Daybreak requires Atmosphere 0.14.0 or later.", rc));
return;
}
/* Initialize ams:su. */
if (R_FAILED(rc = amssuInitialize())) {
fatalThrow(rc);
}
/* Change the current menu to the main menu. */
g_current_menu = std::make_shared<MainMenu>();
}
void UpdateMenu(u64 ns) {

View file

@ -82,6 +82,58 @@ namespace dbk {
virtual void Draw(NVGcontext *vg, u64 ns) = 0;
};
class ErrorMenu : public Menu {
private:
static constexpr u32 ExitButtonId = 0;
static constexpr float WindowWidth = 600.0f;
static constexpr float WindowHeight = 214.0f;
static constexpr float TitleGap = 90.0f;
static constexpr float SubTextHeight = 24.0f;
static constexpr float HorizontalGap = 20.0f;
static constexpr float VerticalGap = 20.0f;
static constexpr float ButtonHeight = 60.0f;
static constexpr float ButtonHorizontalGap = 10.0f;
static constexpr float ButtonWidth = (WindowWidth - HorizontalGap * 2.0f);
private:
char m_text[0x100];
char m_subtext[0x100];
char m_result_text[0x20];
Result m_rc;
public:
ErrorMenu(const char *text, const char *subtext, Result rc = 0);
virtual void Update(u64 ns) override;
virtual void Draw(NVGcontext *vg, u64 ns) override;
};
class WarningMenu : public Menu {
private:
static constexpr u32 BackButtonId = 0;
static constexpr u32 ContinueButtonId = 1;
static constexpr float WindowWidth = 600.0f;
static constexpr float WindowHeight = 214.0f;
static constexpr float TitleGap = 90.0f;
static constexpr float SubTextHeight = 24.0f;
static constexpr float HorizontalGap = 20.0f;
static constexpr float VerticalGap = 20.0f;
static constexpr float ButtonHeight = 60.0f;
static constexpr float ButtonHorizontalGap = 10.0f;
static constexpr float ButtonWidth = (WindowWidth - HorizontalGap * 2.0f) / 2.0f - ButtonHorizontalGap;
private:
std::shared_ptr<Menu> m_next_menu;
char m_text[0x100];
char m_subtext[0x100];
char m_result_text[0x20];
Result m_rc;
public:
WarningMenu(std::shared_ptr<Menu> prev_menu, std::shared_ptr<Menu> next_menu, const char *text, const char *subtext, Result rc = 0);
virtual void Update(u64 ns) override;
virtual void Draw(NVGcontext *vg, u64 ns) override;
};
class MainMenu : public Menu {
private:
static constexpr u32 InstallButtonId = 0;
@ -148,8 +200,8 @@ namespace dbk {
static constexpr float BottomGap = 20.0f;
static constexpr float HorizontalGap = 20.0f;
static constexpr float TextAreaHeight = 410.0f;
static constexpr float TextHorizontalInset = 6.0f;
static constexpr float TextVerticalInset = 6.0f;
static constexpr float TextHorizontalInset = 8.0f;
static constexpr float TextVerticalInset = 8.0f;
static constexpr float ButtonHeight = 60.0f;
static constexpr float ButtonHorizontalGap = 10.0f;
static constexpr float ButtonWidth = (WindowWidth - HorizontalGap * 2.0f) / 2.0f - ButtonHorizontalGap;
@ -211,8 +263,8 @@ namespace dbk {
static constexpr float ProgressBarHeight = 30.0f;
static constexpr float VerticalGap = 10.0f;
static constexpr float TextAreaHeight = 320.0f;
static constexpr float TextHorizontalInset = 6.0f;
static constexpr float TextVerticalInset = 6.0f;
static constexpr float TextHorizontalInset = 8.0f;
static constexpr float TextVerticalInset = 8.0f;
static constexpr float ButtonHeight = 60.0f;
static constexpr float ButtonHorizontalGap = 10.0f;
static constexpr float ButtonWidth = (WindowWidth - HorizontalGap * 2.0f) / 2.0f - ButtonHorizontalGap;

View file

@ -30,9 +30,9 @@ namespace dbk {
/* Calculate the rgb values for the breathing colour effect. */
const double t = static_cast<double>(ns) / 1'000'000'000.0d;
const float d = -0.5 * cos(3.0f*t) + 0.5f;
const int r2 = 83 + (float)(144 - 83) * (d * 0.7f + 0.3f);
const int g2 = 71 + (float)(185 - 71) * (d * 0.7f + 0.3f);
const int b2 = 185 + (float)(217 - 185) * (d * 0.7f + 0.3f);
const int r2 = 83 + (float)(128 - 83) * (d * 0.7f + 0.3f);
const int g2 = 71 + (float)(126 - 71) * (d * 0.7f + 0.3f);
const int b2 = 185 + (float)(230 - 185) * (d * 0.7f + 0.3f);
return nvgRGB(r2, g2, b2);
}
@ -135,6 +135,16 @@ namespace dbk {
nvgFill(vg);
}
void DrawText(NVGcontext *vg, float x, float y, float w, const char *text) {
nvgFontSize(vg, 20.0f);
nvgFontFace(vg, SwitchStandardFont);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGB(0, 0, 0));
const float tw = nvgTextBounds(vg, 0, 0, text, nullptr, nullptr);
nvgText(vg, x + w * 0.5f - tw * 0.5f, y, text, nullptr);
}
void DrawProgressText(NVGcontext *vg, float x, float y, float progress) {
char progress_text[32] = {};
snprintf(progress_text, sizeof(progress_text)-1, "%d%% complete", static_cast<int>(progress * 100.0f));
@ -155,7 +165,7 @@ namespace dbk {
/* Draw the progress bar fill. */
if (progress > 0.0f) {
NVGpaint progress_fill_paint = nvgLinearGradient(vg, x, y + 0.5f * h, x + w, y + 0.5f * h, nvgRGB(83, 71, 185), nvgRGB(144, 185, 217));
NVGpaint progress_fill_paint = nvgLinearGradient(vg, x, y + 0.5f * h, x + w, y + 0.5f * h, nvgRGB(83, 71, 185), nvgRGB(128, 126, 230));
nvgBeginPath(vg);
nvgRoundedRect(vg, x, y, WindowCornerRadius + (w - WindowCornerRadius) * progress, h, WindowCornerRadius);
nvgFillPaint(vg, progress_fill_paint);
@ -171,6 +181,7 @@ namespace dbk {
/* Configure the text. */
nvgFontSize(vg, 18.0f);
nvgFontFace(vg, SwitchStandardFont);
nvgTextLineHeight(vg, 1.3f);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGB(0, 0, 0));

View file

@ -32,6 +32,7 @@ namespace dbk {
void DrawWindow(NVGcontext *vg, const char *title, float x, float y, float w, float h);
void DrawButton(NVGcontext *vg, const char *text, float x, float y, float w, float h, ButtonStyle style, u64 ns);
void DrawTextBackground(NVGcontext *vg, float x, float y, float w, float h);
void DrawText(NVGcontext *vg, float x, float y, float w, const char *text);
void DrawProgressText(NVGcontext *vg, float x, float y, float progress);
void DrawProgressBar(NVGcontext *vg, float x, float y, float w, float h, float progress);
void DrawTextBlock(NVGcontext *vg, const char *text, float x, float y, float w, float h);