backport widget changes from totalsms
This commit is contained in:
@@ -302,7 +302,7 @@ public:
|
||||
option::OptionBool m_install_sysmmc{INI_SECTION, "install_sysmmc", false};
|
||||
option::OptionBool m_install_emummc{INI_SECTION, "install_emummc", false};
|
||||
option::OptionBool m_install_sd{INI_SECTION, "install_sd", true};
|
||||
option::OptionLong m_install_prompt{INI_SECTION, "install_prompt", true};
|
||||
option::OptionBool m_install_prompt{INI_SECTION, "install_prompt", true};
|
||||
option::OptionBool m_allow_downgrade{INI_SECTION, "allow_downgrade", false};
|
||||
option::OptionBool m_skip_if_already_installed{INI_SECTION, "skip_if_already_installed", true};
|
||||
option::OptionBool m_ticket_only{INI_SECTION, "ticket_only", false};
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
namespace sphaira::ui::gfx {
|
||||
|
||||
void drawImage(NVGcontext*, float x, float y, float w, float h, int texture, float rounded = 0.F);
|
||||
void drawImage(NVGcontext*, const Vec4& v, int texture, float rounded = 0.F);
|
||||
void drawImage(NVGcontext*, float x, float y, float w, float h, int texture, float rounded = 0.F, float alpha = 1.0F);
|
||||
void drawImage(NVGcontext*, const Vec4& v, int texture, float rounded = 0.F, float alpha = 1.0F);
|
||||
|
||||
void dimBackground(NVGcontext*);
|
||||
|
||||
|
||||
@@ -32,9 +32,10 @@ public:
|
||||
using Options = std::vector<Option>;
|
||||
|
||||
public:
|
||||
OptionBox(const std::string& message, const Option& a, Callback cb = [](auto){}, int image = 0); // confirm
|
||||
OptionBox(const std::string& message, const Option& a, const Option& b, Callback cb, int image = 0); // yesno
|
||||
OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, Callback cb, int image = 0); // yesno
|
||||
OptionBox(const std::string& message, const Option& a, const Callback& cb = [](auto){}, int image = 0, bool own_image = false); // confirm
|
||||
OptionBox(const std::string& message, const Option& a, const Option& b, const Callback& cb, int image = 0, bool own_image = false); // yesno
|
||||
OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, const Callback& cb, int image = 0, bool own_image = false); // yesno
|
||||
~OptionBox();
|
||||
|
||||
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||
@@ -46,9 +47,10 @@ private:
|
||||
void SetIndex(s64 index);
|
||||
|
||||
private:
|
||||
std::string m_message{};
|
||||
Callback m_callback{};
|
||||
int m_image{};
|
||||
const std::string m_message;
|
||||
const Callback m_callback;
|
||||
const int m_image;
|
||||
const bool m_own_image;
|
||||
|
||||
Vec4 m_spacer_line{};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ private:
|
||||
|
||||
private:
|
||||
static constexpr Vec2 m_title_pos{70.f, 28.f};
|
||||
static constexpr Vec4 m_block{280.f, 110.f, 720.f, 60.f};
|
||||
static constexpr Vec4 m_block{280.f, 110.f, SCREEN_HEIGHT, 60.f};
|
||||
static constexpr float m_text_xoffset{15.f};
|
||||
static constexpr float m_line_width{1220.f};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "ui/widget.hpp"
|
||||
#include "ui/list.hpp"
|
||||
#include "ui/scrolling_text.hpp"
|
||||
#include "option.hpp"
|
||||
#include <memory>
|
||||
#include <concepts>
|
||||
#include <utility>
|
||||
@@ -34,6 +35,8 @@ public:
|
||||
public:
|
||||
explicit SidebarEntryBool(const std::string& title, bool option, Callback cb, const std::string& info = "", const std::string& true_str = "On", const std::string& false_str = "Off");
|
||||
explicit SidebarEntryBool(const std::string& title, bool& option, const std::string& info = "", const std::string& true_str = "On", const std::string& false_str = "Off");
|
||||
explicit SidebarEntryBool(const std::string& title, option::OptionBool& option, const Callback& cb, const std::string& info = "", const std::string& true_str = "On", const std::string& false_str = "Off");
|
||||
explicit SidebarEntryBool(const std::string& title, option::OptionBool& option, const std::string& info = "", const std::string& true_str = "On", const std::string& false_str = "Off");
|
||||
|
||||
private:
|
||||
void Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) override;
|
||||
|
||||
@@ -274,6 +274,13 @@ enum class Button : u64 {
|
||||
START = static_cast<u64>(HidNpadButton_Plus),
|
||||
SELECT = static_cast<u64>(HidNpadButton_Minus),
|
||||
|
||||
SL_LEFT = static_cast<u64>(HidNpadButton_LeftSL),
|
||||
SR_LEFT = static_cast<u64>(HidNpadButton_LeftSR),
|
||||
SL_RIGHT = static_cast<u64>(HidNpadButton_RightSL),
|
||||
SR_RIGHT = static_cast<u64>(HidNpadButton_RightSR),
|
||||
SL_ANY = SL_LEFT | SL_RIGHT,
|
||||
SR_ANY = SR_LEFT | SR_RIGHT,
|
||||
|
||||
// todo:
|
||||
DPAD_LEFT = static_cast<u64>(HidNpadButton_Left),
|
||||
DPAD_RIGHT = static_cast<u64>(HidNpadButton_Right),
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
namespace sphaira::ui {
|
||||
|
||||
struct uiButton final : Object {
|
||||
uiButton(Button button, Action action) : m_button{button}, m_action{action} {}
|
||||
uiButton(Button button, const std::string& button_str, const std::string& action_str);
|
||||
uiButton(Button button, const std::string& action_str);
|
||||
|
||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||
|
||||
Button m_button;
|
||||
Action m_action;
|
||||
std::string m_button_str;
|
||||
std::string m_action_str;
|
||||
Vec4 m_button_pos{};
|
||||
Vec4 m_hint_pos{};
|
||||
};
|
||||
@@ -84,6 +87,8 @@ struct Widget : public Object {
|
||||
}
|
||||
|
||||
auto GetUiButtons() const -> uiButtons;
|
||||
static void SetupUiButtons(uiButtons& buttons, const Vec2& button_pos = {1220, 675});
|
||||
static auto GetUiButtons(const Actions& actions, const Vec2& button_pos = {1220, 675}) -> uiButtons;
|
||||
|
||||
Actions m_actions{};
|
||||
Vec2 m_button_pos{1220, 675};
|
||||
|
||||
@@ -1710,10 +1710,9 @@ void App::DisplayAdvancedOptions(bool left_side) {
|
||||
}, "When enabled, it replaces /hbmenu.nro with Sphaira, creating a backup of hbmenu to /switch/hbmenu.nro\n\n" \
|
||||
"Disabling will give you the option to restore hbmenu."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Boost CPU during transfer"_i18n, App::GetApp()->m_progress_boost_mode.Get(), [](bool& enable){
|
||||
App::GetApp()->m_progress_boost_mode.Set(enable);
|
||||
}, "Enables boost mode during transfers which can improve transfer speed. "\
|
||||
"This sets the CPU to 1785mhz and lowers the GPU 76mhz"_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Boost CPU during transfer"_i18n, App::GetApp()->m_progress_boost_mode,
|
||||
"Enables boost mode during transfers which can improve transfer speed. "\
|
||||
"This sets the CPU to 1785mhz and lowers the GPU 76mhz"_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryArray>("Text scroll speed"_i18n, text_scroll_speed_items, [](s64& index_out){
|
||||
App::SetTextScrollSpeed(index_out);
|
||||
@@ -1797,124 +1796,90 @@ void App::DisplayInstallOptions(bool left_side) {
|
||||
App::SetInstallEmummcEnable(enable);
|
||||
}, "Enables installing whilst in emuMMC mode."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Show install warning"_i18n, App::GetApp()->m_install_prompt.Get(), [](bool& enable){
|
||||
App::GetApp()->m_install_prompt.Set(enable);
|
||||
}, "When enabled, a warning is show when attempting to install a forwarder."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Show install warning"_i18n, App::GetApp()->m_install_prompt,
|
||||
"When enabled, a warning is show when attempting to install a forwarder."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryArray>("Install location"_i18n, install_items, [](s64& index_out){
|
||||
App::SetInstallSdEnable(index_out);
|
||||
}, (s64)App::GetInstallSdEnable());
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Allow downgrade"_i18n, App::GetApp()->m_allow_downgrade.Get(), [](bool& enable){
|
||||
App::GetApp()->m_allow_downgrade.Set(enable);
|
||||
}, "Allows for installing title updates that are lower than the currently installed update."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Allow downgrade"_i18n, App::GetApp()->m_allow_downgrade,
|
||||
"Allows for installing title updates that are lower than the currently installed update."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip if already installed"_i18n, App::GetApp()->m_skip_if_already_installed.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_if_already_installed.Set(enable);
|
||||
}, "Skips installing titles / ncas if they're already installed."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip if already installed"_i18n, App::GetApp()->m_skip_if_already_installed,
|
||||
"Skips installing titles / ncas if they're already installed."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Ticket only"_i18n, App::GetApp()->m_ticket_only.Get(), [](bool& enable){
|
||||
App::GetApp()->m_ticket_only.Set(enable);
|
||||
}, "Installs tickets only, useful if the title was already installed however the tickets were missing or corrupted."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Ticket only"_i18n, App::GetApp()->m_ticket_only,
|
||||
"Installs tickets only, useful if the title was already installed however the tickets were missing or corrupted."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip base"_i18n, App::GetApp()->m_skip_base.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_base.Set(enable);
|
||||
}, "Skips installing the base application."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip base"_i18n, App::GetApp()->m_skip_base,
|
||||
"Skips installing the base application."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip patch"_i18n, App::GetApp()->m_skip_patch.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_patch.Set(enable);
|
||||
}, "Skips installing updates."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip patch"_i18n, App::GetApp()->m_skip_patch,
|
||||
"Skips installing updates."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip dlc"_i18n, App::GetApp()->m_skip_addon.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_addon.Set(enable);
|
||||
}, "Skips installing DLC."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip dlc"_i18n, App::GetApp()->m_skip_addon,
|
||||
"Skips installing DLC."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip data patch"_i18n, App::GetApp()->m_skip_data_patch.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_data_patch.Set(enable);
|
||||
}, "Skips installing DLC update (data patch)."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip data patch"_i18n, App::GetApp()->m_skip_data_patch,
|
||||
"Skips installing DLC update (data patch)."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip ticket"_i18n, App::GetApp()->m_skip_ticket.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_ticket.Set(enable);
|
||||
}, "Skips installing tickets, not recommended."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip ticket"_i18n, App::GetApp()->m_skip_ticket,
|
||||
"Skips installing tickets, not recommended."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip NCA hash verify"_i18n, App::GetApp()->m_skip_nca_hash_verify.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_nca_hash_verify.Set(enable);
|
||||
}, "Enables the option to skip sha256 verification. This is a hash over the entire NCA. "\
|
||||
"It is used to verify that the NCA is valid / not corrupted. "\
|
||||
"You may have seen the option for \"checking for corrupted data\" when a corrupted game is installed. "\
|
||||
"That check performs various hash checks, including the hash over the NCA.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip NCA hash verify"_i18n, App::GetApp()->m_skip_nca_hash_verify,
|
||||
"Enables the option to skip sha256 verification. This is a hash over the entire NCA. "\
|
||||
"It is used to verify that the NCA is valid / not corrupted. "\
|
||||
"You may have seen the option for \"checking for corrupted data\" when a corrupted game is installed. "\
|
||||
"That check performs various hash checks, including the hash over the NCA.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip RSA header verify"_i18n, App::GetApp()->m_skip_rsa_header_fixed_key_verify.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_rsa_header_fixed_key_verify.Set(enable);
|
||||
}, "Enables the option to skip RSA NCA fixed key verification. "\
|
||||
"This is a hash over the NCA header. It is used to verify that the header has not been modified. "\
|
||||
"The header is signed by nintendo, thus it cannot be forged, and is reliable to detect modified NCA headers (such as NSP/XCI converts).\n\n"\
|
||||
"It is recommended to keep this disabled, unless you need to install nsp/xci converts."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip RSA header verify"_i18n, App::GetApp()->m_skip_rsa_header_fixed_key_verify,
|
||||
"Enables the option to skip RSA NCA fixed key verification. "\
|
||||
"This is a hash over the NCA header. It is used to verify that the header has not been modified. "\
|
||||
"The header is signed by nintendo, thus it cannot be forged, and is reliable to detect modified NCA headers (such as NSP/XCI converts).\n\n"\
|
||||
"It is recommended to keep this disabled, unless you need to install nsp/xci converts."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Skip RSA NPDM verify"_i18n, App::GetApp()->m_skip_rsa_npdm_fixed_key_verify.Get(), [](bool& enable){
|
||||
App::GetApp()->m_skip_rsa_npdm_fixed_key_verify.Set(enable);
|
||||
}, "Enables the option to skip RSA NPDM fixed key verification.\n\n"\
|
||||
"Currently, this option is stubbed (not implemented)."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Skip RSA NPDM verify"_i18n, App::GetApp()->m_skip_rsa_npdm_fixed_key_verify,
|
||||
"Enables the option to skip RSA NPDM fixed key verification.\n\n"\
|
||||
"Currently, this option is stubbed (not implemented)."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Ignore distribution bit"_i18n, App::GetApp()->m_ignore_distribution_bit.Get(), [](bool& enable){
|
||||
App::GetApp()->m_ignore_distribution_bit.Set(enable);
|
||||
}, "If set, it will ignore the distribution bit in the NCA header. "\
|
||||
"The distribution bit is used to signify whether a NCA is Eshop or GameCard. "\
|
||||
"You cannot (normally) launch install games that have the distruction bit set to GameCard.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Ignore distribution bit"_i18n, App::GetApp()->m_ignore_distribution_bit,
|
||||
"If set, it will ignore the distribution bit in the NCA header. "\
|
||||
"The distribution bit is used to signify whether a NCA is Eshop or GameCard. "\
|
||||
"You cannot (normally) launch install games that have the distruction bit set to GameCard.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Convert to common ticket"_i18n, App::GetApp()->m_convert_to_common_ticket.Get(), [](bool& enable){
|
||||
App::GetApp()->m_convert_to_common_ticket.Set(enable);
|
||||
}, "[Requires keys] Converts personalised tickets to common (fake) tickets.\n\n"\
|
||||
"It is recommended to keep this enabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Convert to common ticket"_i18n, App::GetApp()->m_convert_to_common_ticket,
|
||||
"[Requires keys] Converts personalised tickets to common (fake) tickets.\n\n"\
|
||||
"It is recommended to keep this enabled."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Convert to standard crypto"_i18n, App::GetApp()->m_convert_to_standard_crypto.Get(), [](bool& enable){
|
||||
App::GetApp()->m_convert_to_standard_crypto.Set(enable);
|
||||
}, "[Requires keys] Converts titlekey to standard crypto, also known as \"ticketless\".\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Convert to standard crypto"_i18n, App::GetApp()->m_convert_to_standard_crypto,
|
||||
"[Requires keys] Converts titlekey to standard crypto, also known as \"ticketless\".\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Lower master key"_i18n, App::GetApp()->m_lower_master_key.Get(), [](bool& enable){
|
||||
App::GetApp()->m_lower_master_key.Set(enable);
|
||||
}, "[Requires keys] Encrypts the keak (key area key) with master key 0, which allows the game to be launched on every fw. "\
|
||||
"Implicitly performs standard crypto.\n\n"\
|
||||
"Do note that just because the game can be launched on any fw (as it can be decrypted), doesn't mean it will work. It is strongly recommened to update your firmware and Atmosphere version in order to play the game, rather than enabling this option.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Lower master key"_i18n, App::GetApp()->m_lower_master_key,
|
||||
"[Requires keys] Encrypts the keak (key area key) with master key 0, which allows the game to be launched on every fw. "\
|
||||
"Implicitly performs standard crypto.\n\n"\
|
||||
"Do note that just because the game can be launched on any fw (as it can be decrypted), doesn't mean it will work. It is strongly recommened to update your firmware and Atmosphere version in order to play the game, rather than enabling this option.\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Lower system version"_i18n, App::GetApp()->m_lower_system_version.Get(), [](bool& enable){
|
||||
App::GetApp()->m_lower_system_version.Set(enable);
|
||||
}, "Sets the system_firmware field in the cnmt extended header to 0. "\
|
||||
"Note: if the master key is higher than fw version, the game still won't launch as the fw won't have the key to decrypt keak (see above).\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
options->Add<ui::SidebarEntryBool>("Lower system version"_i18n, App::GetApp()->m_lower_system_version,
|
||||
"Sets the system_firmware field in the cnmt extended header to 0. "\
|
||||
"Note: if the master key is higher than fw version, the game still won't launch as the fw won't have the key to decrypt keak (see above).\n\n"\
|
||||
"It is recommended to keep this disabled."_i18n);
|
||||
}
|
||||
|
||||
void App::DisplayDumpOptions(bool left_side) {
|
||||
auto options = std::make_unique<ui::Sidebar>("Dump Options"_i18n, left_side ? ui::Sidebar::Side::LEFT : ui::Sidebar::Side::RIGHT);
|
||||
ON_SCOPE_EXIT(App::Push(std::move(options)));
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Created nested folder"_i18n, App::GetApp()->m_dump_app_folder.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_app_folder.Set(enable);
|
||||
});
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Append folder with .xci"_i18n, App::GetApp()->m_dump_append_folder_with_xci.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_append_folder_with_xci.Set(enable);
|
||||
});
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Trim XCI"_i18n, App::GetApp()->m_dump_trim_xci.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_trim_xci.Set(enable);
|
||||
});
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Label trimmed XCI"_i18n, App::GetApp()->m_dump_label_trim_xci.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_label_trim_xci.Set(enable);
|
||||
});
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Multi-threaded USB transfer"_i18n, App::GetApp()->m_dump_usb_transfer_stream.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_usb_transfer_stream.Set(enable);
|
||||
});
|
||||
|
||||
options->Add<ui::SidebarEntryBool>("Convert to common ticket"_i18n, App::GetApp()->m_dump_convert_to_common_ticket.Get(), [](bool& enable){
|
||||
App::GetApp()->m_dump_convert_to_common_ticket.Set(enable);
|
||||
});
|
||||
options->Add<ui::SidebarEntryBool>("Created nested folder"_i18n, App::GetApp()->m_dump_app_folder);
|
||||
options->Add<ui::SidebarEntryBool>("Append folder with .xci"_i18n, App::GetApp()->m_dump_append_folder_with_xci);
|
||||
options->Add<ui::SidebarEntryBool>("Trim XCI"_i18n, App::GetApp()->m_dump_trim_xci);
|
||||
options->Add<ui::SidebarEntryBool>("Label trimmed XCI"_i18n, App::GetApp()->m_dump_label_trim_xci);
|
||||
options->Add<ui::SidebarEntryBool>("Multi-threaded USB transfer"_i18n, App::GetApp()->m_dump_usb_transfer_stream);
|
||||
options->Add<ui::SidebarEntryBool>("Convert to common ticket"_i18n, App::GetApp()->m_dump_convert_to_common_ticket);
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
|
||||
@@ -79,7 +79,8 @@ void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, con
|
||||
float gradientX, gradientY, color;
|
||||
getHighlightAnimation(&gradientX, &gradientY, &color);
|
||||
|
||||
const auto strokeWidth = 5.F;
|
||||
const auto strokeWidth = size;
|
||||
// const auto strokeWidth = 5.F;
|
||||
auto v2 = v;
|
||||
v2.x -= strokeWidth / 2.F;
|
||||
v2.y -= strokeWidth / 2.F;
|
||||
@@ -209,13 +210,13 @@ void drawTextArgs(NVGcontext* vg, float x, float y, float size, int align, const
|
||||
drawText(vg, x, y, size, buffer, nullptr, align, c);
|
||||
}
|
||||
|
||||
void drawImage(NVGcontext* vg, const Vec4& v, int texture, float rounded) {
|
||||
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
|
||||
void drawImage(NVGcontext* vg, const Vec4& v, int texture, float rounded, float alpha) {
|
||||
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, alpha);
|
||||
drawRect(vg, v, paint, rounded);
|
||||
}
|
||||
|
||||
void drawImage(NVGcontext* vg, float x, float y, float w, float h, int texture, float rounded) {
|
||||
drawImage(vg, Vec4(x, y, w, h), texture, rounded);
|
||||
void drawImage(NVGcontext* vg, float x, float y, float w, float h, int texture, float rounded, float alpha) {
|
||||
drawImage(vg, Vec4(x, y, w, h), texture, rounded, alpha);
|
||||
}
|
||||
|
||||
void drawTextBox(NVGcontext* vg, float x, float y, float size, float bound, const NVGcolor& c, const char* str, int align, const char* end) {
|
||||
|
||||
@@ -23,14 +23,16 @@ auto OptionBoxEntry::Selected(bool enable) -> void {
|
||||
m_selected = enable;
|
||||
}
|
||||
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, Callback cb, int image)
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Callback& cb, int image, bool own_image)
|
||||
: m_message{message}
|
||||
, m_callback{cb} {
|
||||
, m_callback{cb}
|
||||
, m_image{image}
|
||||
, m_own_image{own_image} {
|
||||
|
||||
m_pos.w = 770.f;
|
||||
m_pos.h = 295.f;
|
||||
m_pos.x = (1280.f / 2.f) - (m_pos.w / 2.f);
|
||||
m_pos.y = (720.f / 2.f) - (m_pos.h / 2.f);
|
||||
m_pos.x = (SCREEN_WIDTH / 2.f) - (m_pos.w / 2.f);
|
||||
m_pos.y = (SCREEN_HEIGHT / 2.f) - (m_pos.h / 2.f);
|
||||
|
||||
auto box = m_pos;
|
||||
box.y += 220.f;
|
||||
@@ -40,15 +42,16 @@ OptionBox::OptionBox(const std::string& message, const Option& a, Callback cb, i
|
||||
Setup(0);
|
||||
}
|
||||
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, Callback cb, int image)
|
||||
: OptionBox{message, a, b, 0, cb, image} {
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, const Callback& cb, int image, bool own_image)
|
||||
: OptionBox{message, a, b, 0, cb, image, own_image} {
|
||||
|
||||
}
|
||||
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, Callback cb, int image)
|
||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, const Callback& cb, int image, bool own_image)
|
||||
: m_message{message}
|
||||
, m_callback{cb}
|
||||
, m_image{image} {
|
||||
, m_image{image}
|
||||
, m_own_image{own_image} {
|
||||
|
||||
m_pos.w = 770.f;
|
||||
m_pos.h = 295.f;
|
||||
@@ -66,6 +69,12 @@ OptionBox::OptionBox(const std::string& message, const Option& a, const Option&
|
||||
Setup(index);
|
||||
}
|
||||
|
||||
OptionBox::~OptionBox() {
|
||||
if (m_image && m_own_image) {
|
||||
nvgDeleteImage(App::GetVg(), m_image);
|
||||
}
|
||||
}
|
||||
|
||||
auto OptionBox::Update(Controller* controller, TouchInfo* touch) -> void {
|
||||
Widget::Update(controller, touch);
|
||||
|
||||
|
||||
@@ -76,16 +76,16 @@ PopupList::PopupList(std::string title, Items items, Callback cb, s64 index)
|
||||
|
||||
m_starting_index = m_index;
|
||||
|
||||
m_pos.w = 1280.f;
|
||||
m_pos.w = SCREEN_WIDTH;
|
||||
const float a = std::min(370.f, (60.f * static_cast<float>(m_items.size())));
|
||||
m_pos.h = 80.f + 140.f + a;
|
||||
m_pos.y = 720.f - m_pos.h;
|
||||
m_pos.y = SCREEN_HEIGHT - m_pos.h;
|
||||
m_line_top = m_pos.y + 70.f;
|
||||
m_line_bottom = 720.f - 73.f;
|
||||
m_line_bottom = SCREEN_HEIGHT - 73.f;
|
||||
|
||||
Vec4 v{m_block};
|
||||
v.y = m_line_top + 1.f + 42.f;
|
||||
const Vec4 pos{0, m_line_top, 1280.f, m_line_bottom - m_line_top};
|
||||
const Vec4 pos{0, m_line_top, SCREEN_WIDTH, m_line_bottom - m_line_top};
|
||||
m_list = std::make_unique<List>(1, 6, pos, v);
|
||||
m_list->SetScrollBarPos(1250, m_line_top + 20, m_line_bottom - m_line_top - 40);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ void DrawClipped(NVGcontext* vg, const Vec4& clip, float x, float y, float size,
|
||||
} // namespace
|
||||
|
||||
void ScrollingText::Draw(NVGcontext* vg, bool focus, float x, float y, float w, float size, int align, const NVGcolor& colour, const std::string& text_entry) {
|
||||
const Vec4 clip{x, 0, w, 720};
|
||||
const Vec4 clip{x, 0, w, SCREEN_HEIGHT};
|
||||
|
||||
if (!focus) {
|
||||
DrawClipped(vg, clip, x, y, size, align, colour, text_entry);
|
||||
|
||||
@@ -99,11 +99,25 @@ SidebarEntryBool::SidebarEntryBool(const std::string& title, bool option, Callba
|
||||
|
||||
SidebarEntryBool::SidebarEntryBool(const std::string& title, bool& option, const std::string& info, const std::string& true_str, const std::string& false_str)
|
||||
: SidebarEntryBool{title, option, Callback{}, info, true_str, false_str} {
|
||||
m_callback = [](bool& option){
|
||||
m_callback = [&option](bool&){
|
||||
option ^= 1;
|
||||
};
|
||||
}
|
||||
|
||||
SidebarEntryBool::SidebarEntryBool(const std::string& title, option::OptionBool& option, const Callback& cb, const std::string& info, const std::string& true_str, const std::string& false_str)
|
||||
: SidebarEntryBool{title, option.Get(), Callback{}, info, true_str, false_str} {
|
||||
m_callback = [&option, cb](bool& v_out){
|
||||
if (cb) {
|
||||
cb(v_out);
|
||||
}
|
||||
option.Set(v_out);
|
||||
};
|
||||
}
|
||||
|
||||
SidebarEntryBool::SidebarEntryBool(const std::string& title, option::OptionBool& option, const std::string& info, const std::string& true_str, const std::string& false_str)
|
||||
: SidebarEntryBool{title, option, Callback{}, info, true_str, false_str} {
|
||||
}
|
||||
|
||||
void SidebarEntryBool::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) {
|
||||
SidebarEntryBase::Draw(vg, theme, root_pos, left);
|
||||
|
||||
@@ -271,11 +285,11 @@ Sidebar::Sidebar(const std::string& title, const std::string& sub, Side side, It
|
||||
, m_items{std::forward<decltype(items)>(items)} {
|
||||
switch (m_side) {
|
||||
case Side::LEFT:
|
||||
SetPos(Vec4{0.f, 0.f, 450.f, 720.f});
|
||||
SetPos(Vec4{0.f, 0.f, 450.f, SCREEN_HEIGHT});
|
||||
break;
|
||||
|
||||
case Side::RIGHT:
|
||||
SetPos(Vec4{1280.f - 450.f, 0.f, 450.f, 720.f});
|
||||
SetPos(Vec4{SCREEN_WIDTH - 450.f, 0.f, 450.f, SCREEN_HEIGHT});
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
|
||||
namespace sphaira::ui {
|
||||
|
||||
uiButton::uiButton(Button button, const std::string& button_str, const std::string& action_str)
|
||||
: m_button{button}
|
||||
, m_button_str{button_str}
|
||||
, m_action_str{action_str} {
|
||||
|
||||
}
|
||||
|
||||
uiButton::uiButton(Button button, const std::string& action_str)
|
||||
: uiButton{button, gfx::getButton(button), action_str} {
|
||||
|
||||
}
|
||||
|
||||
auto uiButton::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||
// enable to see button region
|
||||
// gfx::drawRect(vg, m_pos, gfx::Colour::RED);
|
||||
@@ -12,9 +24,9 @@ auto uiButton::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
|
||||
nvgFillColor(vg, theme->GetColour(ThemeEntryID_TEXT));
|
||||
nvgFontSize(vg, 20);
|
||||
nvgText(vg, m_hint_pos.x, m_hint_pos.y, m_action.m_hint.c_str(), nullptr);
|
||||
nvgText(vg, m_hint_pos.x, m_hint_pos.y, m_action_str.c_str(), nullptr);
|
||||
nvgFontSize(vg, 26);
|
||||
nvgText(vg, m_button_pos.x, m_button_pos.y, gfx::getButton(m_button), nullptr);
|
||||
nvgText(vg, m_button_pos.x, m_button_pos.y, m_button_str.c_str(), nullptr);
|
||||
}
|
||||
|
||||
void Widget::Update(Controller* controller, TouchInfo* touch) {
|
||||
@@ -39,7 +51,7 @@ void Widget::Update(Controller* controller, TouchInfo* touch) {
|
||||
auto draw_actions = GetUiButtons();
|
||||
for (auto& e : draw_actions) {
|
||||
if (touch->is_clicked && touch->in_range(e.GetPos())) {
|
||||
log_write("got click: %s\n", e.m_action.m_hint.c_str());
|
||||
log_write("got click: %s\n", e.m_action_str.c_str());
|
||||
FireAction(e.m_button);
|
||||
break;
|
||||
}
|
||||
@@ -79,12 +91,37 @@ auto Widget::FireAction(Button b, u8 type) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Widget::GetUiButtons() const -> uiButtons {
|
||||
void Widget::SetupUiButtons(uiButtons& buttons, const Vec2& button_pos) {
|
||||
auto vg = App::GetVg();
|
||||
auto [x, y] = m_button_pos;
|
||||
auto [x, y] = button_pos;
|
||||
|
||||
float bounds[4]{};
|
||||
for (auto& e : buttons) {
|
||||
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
|
||||
|
||||
nvgFontSize(vg, 20.f);
|
||||
nvgTextBounds(vg, x, y, e.m_action_str.c_str(), nullptr, bounds);
|
||||
auto len = bounds[2] - bounds[0];
|
||||
e.m_hint_pos = {x, y, len, 20};
|
||||
|
||||
x -= len + 8.f;
|
||||
nvgFontSize(vg, 26.f);
|
||||
nvgTextBounds(vg, x, y - 7.f, e.m_button_str.c_str(), nullptr, bounds);
|
||||
len = bounds[2] - bounds[0];
|
||||
e.m_button_pos = {x, y - 4.f, len, 26};
|
||||
x -= len + 34.f;
|
||||
|
||||
e.SetPos(e.m_button_pos);
|
||||
e.SetX(e.GetX() - 40);
|
||||
e.SetW(e.m_hint_pos.x - e.m_button_pos.x + len + 25);
|
||||
e.SetY(e.GetY() - 18);
|
||||
e.SetH(26 + 18 * 2);
|
||||
}
|
||||
}
|
||||
|
||||
auto Widget::GetUiButtons(const Actions& actions, const Vec2& button_pos) -> uiButtons {
|
||||
uiButtons draw_actions;
|
||||
draw_actions.reserve(m_actions.size());
|
||||
draw_actions.reserve(actions.size());
|
||||
|
||||
const std::pair<Button, Button> swap_buttons[] = {
|
||||
{Button::L, Button::R},
|
||||
@@ -92,19 +129,20 @@ auto Widget::GetUiButtons() const -> uiButtons {
|
||||
};
|
||||
|
||||
// build array
|
||||
for (const auto& [button, action] : m_actions) {
|
||||
for (const auto& [button, action] : actions) {
|
||||
if (action.IsHidden() || action.m_hint.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uiButton ui_button{button, action};
|
||||
uiButton ui_button{button, action.m_hint};
|
||||
|
||||
bool should_swap = false;
|
||||
for (auto [left, right] : swap_buttons) {
|
||||
if (button == right && draw_actions.size() && draw_actions.back().m_button == left) {
|
||||
const auto s = draw_actions.back();
|
||||
draw_actions.back().m_button = button;
|
||||
draw_actions.back().m_action = action;
|
||||
draw_actions.back().m_button_str = gfx::getButton(button);
|
||||
draw_actions.back().m_action_str = action.m_hint;
|
||||
draw_actions.emplace_back(s);
|
||||
should_swap = true;
|
||||
break;
|
||||
@@ -116,30 +154,14 @@ auto Widget::GetUiButtons() const -> uiButtons {
|
||||
}
|
||||
}
|
||||
|
||||
float bounds[4]{};
|
||||
for (auto& e : draw_actions) {
|
||||
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
|
||||
|
||||
nvgFontSize(vg, 20.f);
|
||||
nvgTextBounds(vg, x, y, e.m_action.m_hint.c_str(), nullptr, bounds);
|
||||
auto len = bounds[2] - bounds[0];
|
||||
e.m_hint_pos = {x, 675, len, 20};
|
||||
|
||||
x -= len + 8.f;
|
||||
nvgFontSize(vg, 26.f);
|
||||
nvgTextBounds(vg, x, y - 7.f, gfx::getButton(e.m_button), nullptr, bounds);
|
||||
len = bounds[2] - bounds[0];
|
||||
e.m_button_pos = {x, 675 - 4.f, len, 26};
|
||||
x -= len + 34.f;
|
||||
|
||||
e.SetPos(e.m_button_pos);
|
||||
e.SetX(e.GetX() - 40);
|
||||
e.SetW(e.m_hint_pos.x - e.m_button_pos.x + len + 25);
|
||||
e.SetY(e.GetY() - 18);
|
||||
e.SetH(26 + 18 * 2);
|
||||
}
|
||||
// setup positions.
|
||||
SetupUiButtons(draw_actions, button_pos);
|
||||
|
||||
return draw_actions;
|
||||
}
|
||||
|
||||
auto Widget::GetUiButtons() const -> uiButtons {
|
||||
return GetUiButtons(m_actions, m_button_pos);
|
||||
}
|
||||
|
||||
} // namespace sphaira::ui
|
||||
|
||||
Reference in New Issue
Block a user