Revamp button system and slightly revamp gui system

This commit is contained in:
cathery 2020-05-14 19:42:29 +03:00
parent 9a914919ba
commit b07293a685
21 changed files with 631 additions and 622 deletions

View File

@ -5,24 +5,20 @@
#include <functional>
#include <vector>
#include "gui.hpp"
class Gui;
enum AdjacentButtonDirection {
ADJ_UP,
ADJ_DOWN,
ADJ_LEFT,
ADJ_RIGHT,
};
class Button {
public:
static inline std::vector<Button *> g_buttons;
static inline u16 g_pageOffsetX = 0;
static inline u16 g_pageOffsetY = 0;
static inline u16 g_targetOffsetX = 0;
static inline u16 g_targetOffsetY = 0;
static inline u16 g_pageLeftmostBoundary = 100;
static inline u16 g_pageTopmostBoundary = 160;
static inline u16 g_pageRightmostBoundary = SCREEN_WIDTH - 100;
static inline u16 g_pageBottommostBoundary = SCREEN_HEIGHT - 160;
static inline bool g_scrollBlocked = false;
Button();
Button(u16 x, u16 y, u16 w, u16 h, std::function<void(Gui *, u16, u16, bool *)> drawAction, std::function<void(u32, bool *)> inputAction, std::vector<s32> adjacentButton, bool activatable, std::function<bool()> usableCondition);
void draw(Gui *gui);
void draw();
bool onInput(u32 kdown);
void onTouch(touchPosition &touch);
@ -34,20 +30,26 @@ public:
return m_isSelected;
}
static s16 getSelectedIndex();
private:
static void _defaultDrawAction(Gui *, u16, u16, bool *) {}
static void _defaultInputAction(u32, bool *) {}
static bool _defaultUsableCondition() { return true; }
static void select(s16 buttonIndex);
public:
std::pair<u16, u16> position{};
std::pair<u16, u16> volume{};
std::function<void(Gui *, u16, u16, bool *)> drawAction = _defaultDrawAction;
std::function<void(u32, bool *)> inputAction = _defaultInputAction;
std::function<bool()> usableCondition = _defaultUsableCondition;
std::array<s32, 4> adjacentButton = {-1, -1, -1, -1};
bool activatable = false;
private:
u16 m_x, m_y, m_w, m_h;
std::function<void(Gui *, u16, u16, bool *)> m_drawAction;
std::function<void(u32, bool *)> m_inputAction;
std::function<bool()> m_usableCondition;
bool m_isActivated;
bool m_isSelected;
bool m_activatable;
std::vector<s32> m_adjacentButton;
Gui *m_gui;
friend class Gui;
};

View File

@ -6,6 +6,7 @@
#include "list_selector.hpp"
#include "message_box.hpp"
#include "button.hpp"
extern "C" {
#include "theme.h"
@ -38,6 +39,20 @@ enum gui_t {
};
class Gui {
protected:
u16 m_pageOffsetX = 0;
u16 m_pageOffsetY = 0;
u16 m_targetOffsetX = 0;
u16 m_targetOffsetY = 0;
const u16 m_pageLeftmostBoundary = 100;
const u16 m_pageTopmostBoundary = 160;
const u16 m_pageRightmostBoundary = SCREEN_WIDTH - 100;
const u16 m_pageBottommostBoundary = SCREEN_HEIGHT - 160;
bool m_scrollBlocked = false;
std::vector<Button> m_buttons;
friend class Button;
public:
static inline enum gui_t g_nextGui = GUI_INVALID;
@ -50,14 +65,27 @@ public:
static inline ListSelector *g_currListSelector = nullptr;
static inline MessageBox *g_currMessageBox = nullptr;
public:
Gui();
virtual ~Gui();
virtual void update();
virtual void draw() = 0;
virtual void onInput(u32 kdown) = 0;
virtual void onTouch(touchPosition &touch) = 0;
virtual void onGesture(touchPosition &startPosition, touchPosition &endPosition) = 0;
virtual void draw() {
beginDraw();
drawButtons();
endDraw();
}
virtual void onInput(u32 kdown) {
inputButtons(kdown);
}
virtual void onTouch(touchPosition &touch) {
touchButtons(touch);
}
virtual void onGesture(touchPosition &startPosition, touchPosition &endPosition){};
s16 getSelectedButtonIndex();
void selectButton(s16 buttonIndex);
void selectButtonByRef(const Button *button);
void add(const Button &button);
static void resizeImage(u8 *in, u8 *out, size_t src_width, size_t src_height, size_t dest_width, size_t dest_height);
static std::vector<std::string> split(const std::string &s, const char &c);
@ -79,8 +107,30 @@ public:
void drawShadow(s16 x, s16 y, s16 width, s16 height);
protected:
void endInit() {
m_targetOffsetX = m_pageOffsetX;
m_targetOffsetY = m_pageOffsetY;
}
void beginDraw();
void endDraw();
void drawButtons() {
for (Button &btn : m_buttons)
btn.draw();
};
bool inputButtons(u32 kdown) {
for (Button &btn : m_buttons) {
if (btn.isSelected())
if (btn.onInput(kdown)) return true;
}
return false;
};
void touchButtons(touchPosition &touch) {
for (Button &btn : m_buttons) {
btn.onTouch(touch);
}
};
private:
FT_Error m_fontLibret, m_fontFacesRet[FONT_FACES_MAX];

View File

@ -11,14 +11,10 @@
class GuiHekate : public Gui {
public:
GuiHekate();
~GuiHekate();
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
~GuiHekate() override;
void draw() override;
void onInput(u32 kdown) override;
static inline BootEntry m_currRebootConfig{};
private:

View File

@ -11,13 +11,10 @@
class GuiHIDMitm : public Gui {
public:
GuiHIDMitm();
~GuiHIDMitm();
~GuiHIDMitm() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
private:
simpleIniParser::Ini *m_configFile;

View File

@ -11,13 +11,10 @@
class GuiMain : public Gui {
public:
GuiMain();
~GuiMain();
~GuiMain() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
private:
static inline int selection = 0;

View File

@ -6,13 +6,10 @@
class GuiOverrideKey : public Gui {
public:
GuiOverrideKey();
~GuiOverrideKey();
~GuiOverrideKey() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
void loadConfigFile();
private:

View File

@ -12,13 +12,10 @@ enum class OverrideButtonType {
class GuiOverridesMenu : public Gui {
public:
GuiOverridesMenu();
~GuiOverridesMenu();
~GuiOverridesMenu() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
void addButton(OverrideButtonType buttonType, OverrideKeyType keyType = OverrideKeyType::Invalid, const ProgramOverrideKey &key = ProgramOverrideKey{});
void loadConfigFile();

View File

@ -16,13 +16,10 @@ typedef struct {
class GuiSysmodule : public Gui {
public:
GuiSysmodule();
~GuiSysmodule();
~GuiSysmodule() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
private:
static inline int selection = 0;

View File

@ -5,13 +5,10 @@
class GuiTitleList : public Gui {
public:
GuiTitleList();
~GuiTitleList();
~GuiTitleList() override;
void update();
void draw();
void onInput(u32 kdown);
void onTouch(touchPosition &touch);
void onGesture(touchPosition &startPosition, touchPosition &endPosition);
void draw() override;
void onInput(u32 kdown) override;
void loadConfigFile();
static inline u64 selectedAppID = 0;

View File

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "types.h"
#include "SimpleIniParser.hpp"
#define LOADER_INI "sdmc:/atmosphere/config/override_config.ini"
#define HEKATE_INI "sdmc:/bootloader/hekate_ipl.ini"
@ -64,3 +65,6 @@ template <class T>
constexpr static T Lerp(T first, T second, float percent) {
return (first + (second - first) * percent);
}
// the version of simpleIniParser::Ini::parseOrCreateFile has a bug where it destroys the entire file if it doesn't start with a newline
simpleIniParser::Ini *parseOrCreateFileFixed(const std::string &path);

View File

@ -1,80 +1,35 @@
#include "button.hpp"
#include "gui.hpp"
extern "C" {
#include "theme.h"
}
Button::Button(u16 x, u16 y, u16 w, u16 h, std::function<void(Gui *, u16, u16, bool *)> drawAction, std::function<void(u32, bool *)> inputAction, std::vector<s32> adjacentButton, bool activatable, std::function<bool()> usableCondition)
: m_x(x), m_y(y), m_w(w), m_h(h), m_drawAction(drawAction), m_inputAction(inputAction), m_usableCondition(usableCondition), m_activatable(activatable), m_adjacentButton(adjacentButton) {
Button::g_buttons.push_back(this);
Button::Button() {
m_isActivated = false;
m_isSelected = false;
select(0);
}
s16 Button::getSelectedIndex() {
for (size_t i = 0; i != g_buttons.size(); ++i) {
if (g_buttons[i]->m_isSelected)
return i;
}
return -1;
}
void Button::select(s16 buttonIndex) {
if (buttonIndex < 0) return;
if (Button::g_buttons.size() <= static_cast<u16>(buttonIndex)) return;
for (Button *btn : Button::g_buttons) {
btn->m_isSelected = false;
btn->m_isActivated = false;
}
auto button = Button::g_buttons[buttonIndex];
button->m_isSelected = true;
if (g_scrollBlocked)
return;
auto leftmostDiff = (button->m_x) - (g_pageOffsetX)-g_pageLeftmostBoundary;
auto topmostDiff = (button->m_y) - (g_pageOffsetY)-g_pageTopmostBoundary;
auto rightmostDiff = (button->m_x + button->m_w) - (g_pageOffsetX)-g_pageRightmostBoundary;
auto bottommostDiff = (button->m_y + button->m_h) - (g_pageOffsetY)-g_pageBottommostBoundary;
if (leftmostDiff < 0)
g_pageOffsetX += leftmostDiff;
if (rightmostDiff > 0)
g_pageOffsetX += rightmostDiff;
if (topmostDiff < 0)
g_pageOffsetY += topmostDiff;
if (bottommostDiff > 0)
g_pageOffsetY += bottommostDiff;
}
void Button::draw(Gui *gui) {
void Button::draw() {
// Offset calculation
s32 resultX = m_x - g_targetOffsetX;
s32 resultY = m_y - g_targetOffsetY;
if (resultX + m_w < 0 || resultY + m_h < 0 || resultX > SCREEN_WIDTH || resultY > SCREEN_HEIGHT)
s32 resultX = position.first - m_gui->m_targetOffsetX;
s32 resultY = position.second - m_gui->m_targetOffsetY;
if (resultX + volume.first < 0 || resultY + volume.second < 0 || resultX > SCREEN_WIDTH || resultY > SCREEN_HEIGHT)
return;
s32 borderX = resultX - 5;
s32 borderY = resultY - 5;
if (m_isSelected) {
gui->drawRectangled(borderX, borderY, m_w + 10, m_h + 10, m_isActivated ? currTheme.activatedColor : currTheme.highlightColor);
gui->drawShadow(borderX, borderY, m_w + 10, m_h + 10);
m_gui->drawRectangled(borderX, borderY, volume.first + 10, volume.second + 10, m_isActivated ? currTheme.activatedColor : currTheme.highlightColor);
m_gui->drawShadow(borderX, borderY, volume.first + 10, volume.second + 10);
} else
gui->drawShadow(resultX, resultY, m_w, m_h);
m_gui->drawShadow(resultX, resultY, volume.first, volume.second);
gui->drawRectangled(resultX, resultY, m_w, m_h, currTheme.selectedButtonColor);
m_gui->drawRectangled(resultX, resultY, volume.first, volume.second, currTheme.selectedButtonColor);
m_drawAction(gui, resultX, resultY, &m_isActivated);
drawAction(m_gui, resultX, resultY, &m_isActivated);
if (!m_usableCondition())
gui->drawRectangled(resultX, resultY, m_w, m_h, gui->makeColor(0x80, 0x80, 0x80, 0x80));
if (!usableCondition())
m_gui->drawRectangled(resultX, resultY, volume.first, volume.second, m_gui->makeColor(0x80, 0x80, 0x80, 0x80));
}
bool Button::onInput(u32 kdown) {
@ -82,45 +37,40 @@ bool Button::onInput(u32 kdown) {
return false;
if (!m_isActivated) {
if ((kdown & KEY_A) && m_activatable) {
if ((kdown & KEY_A) && activatable) {
m_isActivated = true;
kdown = 0;
} else {
if (kdown & KEY_UP) Button::select(m_adjacentButton[0]);
if (kdown & KEY_DOWN) Button::select(m_adjacentButton[1]);
if (kdown & KEY_LEFT) Button::select(m_adjacentButton[2]);
if (kdown & KEY_RIGHT) Button::select(m_adjacentButton[3]);
if (kdown & KEY_UP) m_gui->selectButton(adjacentButton[0]);
if (kdown & KEY_DOWN) m_gui->selectButton(adjacentButton[1]);
if (kdown & KEY_LEFT) m_gui->selectButton(adjacentButton[2]);
if (kdown & KEY_RIGHT) m_gui->selectButton(adjacentButton[3]);
if (kdown & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) return true;
}
}
if (!m_usableCondition()) return false;
if (!usableCondition()) return false;
m_inputAction(kdown, &m_isActivated);
inputAction(kdown, &m_isActivated);
return false;
}
void Button::onTouch(touchPosition &touch) {
if (!m_usableCondition()) return;
if (!usableCondition()) return;
u16 resultX = m_x > g_targetOffsetX ? m_x - g_targetOffsetX : 0;
u16 resultY = m_y > g_targetOffsetY ? m_y - g_targetOffsetY : 0;
u16 resultX = position.first > m_gui->m_targetOffsetX ? position.first - m_gui->m_targetOffsetX : 0;
u16 resultY = position.second > m_gui->m_targetOffsetY ? position.second - m_gui->m_targetOffsetY : 0;
if (touch.px >= resultX && touch.px <= (resultX + m_w) && touch.py >= resultY && touch.py <= (resultY + m_h)) {
if (touch.px >= resultX && touch.px <= (resultX + volume.first) && touch.py >= resultY && touch.py <= (resultY + volume.second)) {
if (m_isSelected) {
if (m_activatable)
if (activatable)
m_isActivated = true;
else
m_inputAction(KEY_A, &m_isActivated);
inputAction(KEY_A, &m_isActivated);
return;
}
for (size_t i = 0; i != g_buttons.size(); ++i) {
if (g_buttons[i] == this) {
select(i);
break;
}
}
m_gui->selectButtonByRef(this);
}
}

View File

@ -2,11 +2,13 @@
#include <math.h>
#include <functional>
#include "utils.hpp"
static float menuTimer = 0.0F;
static u32 stride;
Gui::Gui() {
m_buttons.reserve(4);
Gui::g_currListSelector = nullptr;
Gui::g_currMessageBox = nullptr;
@ -532,6 +534,9 @@ void Gui::resizeImage(u8 *in, u8 *out, size_t src_width, size_t src_height, size
}
void Gui::beginDraw() {
//TODO: maybe move this to update()?
m_targetOffsetX = Lerp(m_targetOffsetX, m_pageOffsetX, SCROLL_SPEED);
m_targetOffsetY = Lerp(m_targetOffsetY, m_pageOffsetY, SCROLL_SPEED);
this->framebuffer = (u8 *)framebufferBegin(&Gui::g_fb_obj, &stride);
}
@ -543,4 +548,59 @@ void Gui::endDraw() {
Gui::g_currMessageBox->draw(this);
framebufferEnd(&Gui::g_fb_obj);
}
}
s16 Gui::getSelectedButtonIndex() {
for (size_t i = 0; i != m_buttons.size(); ++i) {
if (m_buttons[i].m_isSelected)
return i;
}
return -1;
}
void Gui::selectButtonByRef(const Button *button) {
for (size_t i = 0; i != m_buttons.size(); ++i) {
if (&m_buttons[i] == button) {
selectButton(i);
break;
}
}
}
void Gui::selectButton(s16 buttonIndex) {
if (buttonIndex < 0) return;
if (m_buttons.size() <= static_cast<u16>(buttonIndex)) return;
for (Button &btn : m_buttons) {
btn.m_isSelected = false;
btn.m_isActivated = false;
}
auto &button = m_buttons[buttonIndex];
button.m_isSelected = true;
if (m_scrollBlocked)
return;
auto leftmostDiff = (button.position.first) - (m_pageOffsetX)-m_pageLeftmostBoundary;
auto topmostDiff = (button.position.second) - (m_pageOffsetY)-m_pageTopmostBoundary;
auto rightmostDiff = (button.position.first + button.volume.first) - (m_pageOffsetX)-m_pageRightmostBoundary;
auto bottommostDiff = (button.position.second + button.volume.second) - (m_pageOffsetY)-m_pageBottommostBoundary;
if (leftmostDiff < 0)
m_pageOffsetX += leftmostDiff;
if (rightmostDiff > 0)
m_pageOffsetX += rightmostDiff;
if (topmostDiff < 0)
m_pageOffsetY += topmostDiff;
if (bottommostDiff > 0)
m_pageOffsetY += bottommostDiff;
}
void Gui::add(const Button &button) {
m_buttons.emplace_back(button).m_gui = this;
selectButton(0);
}

View File

@ -66,64 +66,72 @@ GuiHekate::GuiHekate() : Gui() {
getBootConfigs(m_rebootConfigs, currRebootEntryIndex);
//m_currRebootConfig = m_rebootConfigs[0];
new Button(
200, 250, Gui::g_framebuffer_width - 400, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Hekate profile", ALIGNED_LEFT);
std::string autoBootName = m_currRebootConfig.name;
auto profileButton = Button();
profileButton.position = {200, 250};
profileButton.adjacentButton[ADJ_DOWN] = 1;
profileButton.volume = {Gui::g_framebuffer_width - 400, 80};
profileButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Hekate profile", ALIGNED_LEFT);
std::string autoBootName = m_currRebootConfig.name;
if(autoBootName.length() >= 25) {
autoBootName = autoBootName.substr(0, 24);
autoBootName += "...";
}
if (autoBootName.length() >= 25) {
autoBootName = autoBootName.substr(0, 24);
autoBootName += "...";
}
gui->drawTextAligned(font20, x + 830, y + 50, currTheme.selectedColor, autoBootName.c_str(), ALIGNED_RIGHT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
rebootNames.clear();
gui->drawTextAligned(font20, x + 830, y + 50, currTheme.selectedColor, autoBootName.c_str(), ALIGNED_RIGHT);
};
profileButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
rebootNames.clear();
for(auto const& autoBootEntry : m_rebootConfigs)
rebootNames.push_back(autoBootEntry.name);
for (auto const &autoBootEntry : m_rebootConfigs)
rebootNames.push_back(autoBootEntry.name);
(new ListSelector("Hekate profile to reboot to", "\uE0E1 Back \uE0E0 OK", rebootNames, currRebootEntryIndex))->setInputAction([&](u32 k, u16 selectedItem){
if(k & KEY_A) {
currRebootEntryIndex = selectedItem;
m_currRebootConfig = m_rebootConfigs[selectedItem];
(new ListSelector("Hekate profile to reboot to", "\uE0E1 Back \uE0E0 OK", rebootNames, currRebootEntryIndex))
->setInputAction([&](u32 k, u16 selectedItem) {
if (k & KEY_A) {
currRebootEntryIndex = selectedItem;
m_currRebootConfig = m_rebootConfigs[selectedItem];
Gui::g_currListSelector->hide();
}
})->show();
} }, {-1, 1, -1, -1}, false, []() -> bool { return true; });
Gui::g_currListSelector->hide();
}
})
->show();
}
};
add(profileButton);
new Button(
400, 450, Gui::g_framebuffer_width - 800, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, Gui::g_framebuffer_width - 800, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 50, currTheme.textColor, "Reboot now!", ALIGNED_CENTER); },
[&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
FILE *f = fopen("sdmc:/bootloader/update.bin", "rb");
if (f) {
fread(g_reboot_payload, 1, sizeof(g_reboot_payload), f);
fclose(f);
auto rebootButton = Button();
rebootButton.position = {400, 450};
rebootButton.volume = {Gui::g_framebuffer_width - 800, 80};
rebootButton.adjacentButton[ADJ_UP] = 0;
rebootButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, Gui::g_framebuffer_width - 800, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 50, currTheme.textColor, "Reboot now!", ALIGNED_CENTER);
};
rebootButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
FILE *f = fopen("sdmc:/bootloader/update.bin", "rb");
if (f) {
fread(g_reboot_payload, 1, sizeof(g_reboot_payload), f);
fclose(f);
g_reboot_payload[0x94] = 1;
g_reboot_payload[0x95] = m_currRebootConfig.id;
g_reboot_payload[0x96] = m_currRebootConfig.autoBootList;
g_reboot_payload[0x94] = 1;
g_reboot_payload[0x95] = m_currRebootConfig.id;
g_reboot_payload[0x96] = m_currRebootConfig.autoBootList;
reboot_to_payload();
} else
(new MessageBox("Can't find \"bootloader/update.bin\"!", MessageBox::OKAY))->show();
}
},
{0, -1, -1, -1}, false, []() -> bool { return true; });
reboot_to_payload();
} else
(new MessageBox("Can't find \"bootloader/update.bin\"!", MessageBox::OKAY))->show();
}
};
add(rebootButton);
endInit();
}
GuiHekate::~GuiHekate() {
splExit();
Button::g_buttons.clear();
}
void GuiHekate::update() {
Gui::update();
}
void GuiHekate::draw() {
@ -138,27 +146,14 @@ void GuiHekate::draw() {
Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 150, currTheme.textColor, "Select the Hekate profile you want to reboot your Nintendo Switch into. \n Make sure to close all open titles beforehand as this will reboot your device immediately.", ALIGNED_CENTER);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
void GuiHekate::onInput(u32 kdown) {
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) break;
}
inputButtons(kdown);
if (kdown & KEY_B)
Gui::g_nextGui = GUI_MAIN;
}
void GuiHekate::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiHekate::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}
}

View File

@ -19,6 +19,7 @@ const char *const keyNames[16] = {"KEY_A", "KEY_B", "KEY_X", "KEY_Y", "KEY_LSTIC
GuiHIDMitm::GuiHIDMitm() : Gui() {
hidExtraPause();
//TODO: fix the whole iniparser thing if hid-mitm ever comes back
m_configFile = simpleIniParser::Ini::parseFile(HID_MITM_INI);
@ -28,25 +29,28 @@ GuiHIDMitm::GuiHIDMitm() : Gui() {
}
}
new Button(
400, 400, Gui::g_framebuffer_width - 800, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 50, currTheme.textColor, "Touch to save config", ALIGNED_CENTER);
},
[&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
Gui::g_nextGui = GUI_SM_SELECT;
auto configButton = Button();
configButton.position = {400, 400};
configButton.volume = {Gui::g_framebuffer_width - 800, 80};
configButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 50, currTheme.textColor, "Touch to save config", ALIGNED_CENTER);
};
configButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
Gui::g_nextGui = GUI_SM_SELECT;
for (u16 i = 0; i < m_hidConfig.size(); i++)
m_configFile->findSection("player1")->options[i]->value = m_hidConfig[m_configFile->findSection("player1")->options[i]->key];
}
},
{-1, -1, -1, -1}, false, []() -> bool { return true; });
for (u16 i = 0; i < m_hidConfig.size(); i++)
m_configFile->findSection("player1")->options[i]->value = m_hidConfig[m_configFile->findSection("player1")->options[i]->key];
}
};
add(configButton);
endInit();
}
GuiHIDMitm::~GuiHIDMitm() {
m_configFile->writeToFile(HID_MITM_INI);
delete m_configFile;
hidExtraReloadConfig();
Button::g_buttons.clear();
}
static std::string configToButtonName(std::string configName) {
@ -71,10 +75,6 @@ static std::string configToButtonName(std::string configName) {
// clang-format on
}
void GuiHIDMitm::update() {
Gui::update();
}
void GuiHIDMitm::draw() {
Gui::beginDraw();
Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor);
@ -106,10 +106,7 @@ void GuiHIDMitm::draw() {
Gui::drawTextAligned(font20, 253, 379, m_selectedButton == 14 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DRIGHT"]).c_str(), ALIGNED_CENTER);
Gui::drawTextAligned(font20, 218, 414, m_selectedButton == 15 ? currTheme.selectedColor : COLOR_WHITE, configToButtonName(m_hidConfig["KEY_DDOWN"]).c_str(), ALIGNED_CENTER);
// clang-format on
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
@ -123,13 +120,4 @@ void GuiHIDMitm::onInput(u32 kdown) {
m_selectedButton = -1;
}
}
}
void GuiHIDMitm::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiHIDMitm::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}
}

View File

@ -23,7 +23,7 @@ static u16 currAutoBootEntryIndex;
GuiMain::GuiMain() : Gui() {
{
// Get the override keys, if any exist
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
m_albumOverrideKey = OverrideKey::StringToKeyCombo(ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption(OVERRIDE_KEY, "!R")->value);
delete ini;
}
@ -32,82 +32,113 @@ GuiMain::GuiMain() : Gui() {
m_currAutoBootConfig = m_autoBootConfigs[currAutoBootEntryIndex];
//0
new Button(
150, 230, 200, 200, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(fontHuge, x + 100, y + 100, currTheme.textColor, "...", ALIGNED_CENTER);
gui->drawTextAligned(font14, x + 100, y + 185, currTheme.textColor, "Change override keys", ALIGNED_CENTER); }, [&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A)
Gui::g_nextGui = GUI_OVERRIDES_MENU; }, {-1, 2, -1, 1}, false, []() -> bool { return true; });
auto overrideKeysMenuButton = Button();
overrideKeysMenuButton.position = {150, 230};
overrideKeysMenuButton.volume = {200, 200};
overrideKeysMenuButton.adjacentButton[ADJ_DOWN] = 2;
overrideKeysMenuButton.adjacentButton[ADJ_RIGHT] = 1;
overrideKeysMenuButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(fontHuge, x + 100, y + 100, currTheme.textColor, "...", ALIGNED_CENTER);
gui->drawTextAligned(font14, x + 100, y + 185, currTheme.textColor, "Change override keys", ALIGNED_CENTER);
};
overrideKeysMenuButton.inputAction = [&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A)
Gui::g_nextGui = GUI_OVERRIDES_MENU;
};
add(overrideKeysMenuButton);
//1
new Button(
370, 240, 700, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Hekate autoboot profile", ALIGNED_LEFT);
auto autobootSelectorButton = Button();
autobootSelectorButton.position = {370, 240};
autobootSelectorButton.volume = {700, 80};
autobootSelectorButton.adjacentButton[ADJ_DOWN] = 2;
autobootSelectorButton.adjacentButton[ADJ_LEFT] = 0;
autobootSelectorButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Hekate autoboot profile", ALIGNED_LEFT);
std::string autoBootName = m_currAutoBootConfig.name;
std::string autoBootName = m_currAutoBootConfig.name;
if(autoBootName.length() >= 25) {
autoBootName = autoBootName.substr(0, 24);
autoBootName += "...";
}
if (autoBootName.length() >= 25) {
autoBootName = autoBootName.substr(0, 24);
autoBootName += "...";
}
gui->drawTextAligned(font20, x + 660, y + 50, currTheme.selectedColor, autoBootName.c_str(), ALIGNED_RIGHT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
autobootNames.clear();
gui->drawTextAligned(font20, x + 660, y + 50, currTheme.selectedColor, autoBootName.c_str(), ALIGNED_RIGHT);
};
autobootSelectorButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
autobootNames.clear();
for (auto const &autoBootEntry : m_autoBootConfigs)
autobootNames.push_back(autoBootEntry.name);
for (auto const &autoBootEntry : m_autoBootConfigs)
autobootNames.push_back(autoBootEntry.name);
(new ListSelector("Hekate autoboot profile", "\uE0E1 Back \uE0E0 OK", autobootNames, currAutoBootEntryIndex))
->setInputAction([&](u32 k, u16 selectedItem) {
if (k & KEY_A) {
simpleIniParser::Ini *hekateIni = simpleIniParser::Ini::parseOrCreateFile(HEKATE_INI);
currAutoBootEntryIndex = selectedItem;
m_currAutoBootConfig = m_autoBootConfigs[selectedItem];
(new ListSelector("Hekate autoboot profile", "\uE0E1 Back \uE0E0 OK", autobootNames, currAutoBootEntryIndex))
->setInputAction([&](u32 k, u16 selectedItem) {
if (k & KEY_A) {
auto hekateIni = parseOrCreateFileFixed(HEKATE_INI);
auto configSection = hekateIni->findOrCreateSection("config");
currAutoBootEntryIndex = selectedItem;
m_currAutoBootConfig = m_autoBootConfigs[selectedItem];
auto ini_autoboot = configSection->findOrCreateFirstOption("autoboot", "0");
auto ini_autoboot_list = configSection->findOrCreateFirstOption("autoboot_list", "0");
auto configSection = hekateIni->findOrCreateSection("config");
ini_autoboot->value = std::to_string(m_currAutoBootConfig.id);
ini_autoboot_list->value = std::to_string(m_currAutoBootConfig.autoBootList);
auto ini_autoboot = configSection->findOrCreateFirstOption("autoboot", "0");
auto ini_autoboot_list = configSection->findOrCreateFirstOption("autoboot_list", "0");
hekateIni->writeToFile(HEKATE_INI);
Gui::g_currListSelector->hide();
}
})
->show();
} }, {-1, 2, 0, -1}, false, []() -> bool { return true; });
ini_autoboot->value = std::to_string(m_currAutoBootConfig.id);
ini_autoboot_list->value = std::to_string(m_currAutoBootConfig.autoBootList);
hekateIni->writeToFile(HEKATE_INI);
delete hekateIni;
Gui::g_currListSelector->hide();
}
})
->show();
}
};
add(autobootSelectorButton);
//2
new Button(
370, 340, 340, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, 340, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Background services", ALIGNED_LEFT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A)
Gui::g_nextGui = GUI_SM_SELECT; }, {1, -1, 0, 3}, false, []() -> bool { return true; });
auto backgroundServicesButton = Button();
backgroundServicesButton.position = {370, 340};
backgroundServicesButton.volume = {340, 80};
backgroundServicesButton.adjacentButton[ADJ_UP] = 1;
backgroundServicesButton.adjacentButton[ADJ_LEFT] = 0;
backgroundServicesButton.adjacentButton[ADJ_RIGHT] = 3;
backgroundServicesButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, 340, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, "Background services", ALIGNED_LEFT);
};
backgroundServicesButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A)
Gui::g_nextGui = GUI_SM_SELECT;
};
add(backgroundServicesButton);
//3
new Button(
735, 340, 335, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, 335, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, x + 55, y + 50, currTheme.textColor, "Reboot to Hekate", ALIGNED_LEFT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
Gui::g_nextGui = GUI_HEKATE;
GuiHekate::m_currRebootConfig = m_currAutoBootConfig;
} }, {1, -1, 2, -1}, false, []() -> bool { return true; });
auto rebootButton = Button();
rebootButton.position = {735, 340};
rebootButton.volume = {335, 80};
rebootButton.adjacentButton[ADJ_UP] = 1;
rebootButton.adjacentButton[ADJ_LEFT] = 2;
rebootButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawRectangled(x, y, 335, 80, currTheme.submenuButtonColor);
gui->drawTextAligned(font20, x + 55, y + 50, currTheme.textColor, "Reboot to Hekate", ALIGNED_LEFT);
};
rebootButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
Gui::g_nextGui = GUI_HEKATE;
GuiHekate::m_currRebootConfig = m_currAutoBootConfig;
}
};
add(rebootButton);
Button::select(selection);
selectButton(selection);
endInit();
}
GuiMain::~GuiMain() {
selection = Button::getSelectedIndex();
Button::g_buttons.clear();
}
void GuiMain::update() {
Gui::update();
selection = this->getSelectedButtonIndex();
}
void GuiMain::draw() {
@ -120,26 +151,13 @@ void GuiMain::draw() {
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT);
Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height - 130, currTheme.textColor, "Press \uE044 to save and return back to the home menu", ALIGNED_CENTER);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
void GuiMain::onInput(u32 kdown) {
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) return;
}
if (inputButtons(kdown)) return;
if (kdown & KEY_B && !exitDisabled)
g_exitApplet = true;
}
void GuiMain::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiMain::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}
}

View File

@ -9,133 +9,164 @@
#include "gui_title_list.hpp"
GuiOverrideKey::GuiOverrideKey() : Gui() {
Button::g_scrollBlocked = true;
m_scrollBlocked = true;
loadConfigFile();
//0
new Button(
640, 200, 380, 200, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
if (m_inputBlocked)
gui->drawTextAligned(font20, x + 190, y + 100, currTheme.textColor, "Press any key...", ALIGNED_CENTER);
else
if (m_override.key.key == 0)
gui->drawTextAligned(font24, x + 190, y + 100, currTheme.unselectedColor, "No key selected", ALIGNED_CENTER);
else
gui->drawTextAligned(fontHuge, x + 190, y + 136, currTheme.textColor, OverrideKey::KeyToUnicode(m_override.key.key), ALIGNED_CENTER);
gui->drawTextAligned(font14, x + 190, y + 185, currTheme.textColor, "Override key", ALIGNED_CENTER); }, [&](u64 kdown, bool *isActivated) {
if(*isActivated) {
auto keySelectButton = Button();
keySelectButton.position = {640, 200};
keySelectButton.volume = {380, 200};
keySelectButton.activatable = true;
keySelectButton.adjacentButton[ADJ_DOWN] = 1;
keySelectButton.adjacentButton[ADJ_LEFT] = 2;
keySelectButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
if (m_inputBlocked)
gui->drawTextAligned(font20, x + 190, y + 100, currTheme.textColor, "Press any key...", ALIGNED_CENTER);
else if (m_override.key.key == 0)
gui->drawTextAligned(font24, x + 190, y + 100, currTheme.unselectedColor, "No key selected", ALIGNED_CENTER);
else
gui->drawTextAligned(fontHuge, x + 190, y + 136, currTheme.textColor, OverrideKey::KeyToUnicode(m_override.key.key), ALIGNED_CENTER);
gui->drawTextAligned(font14, x + 190, y + 185, currTheme.textColor, "Override key", ALIGNED_CENTER);
};
keySelectButton.inputAction = [&](u64 kdown, bool *isActivated) {
if (*isActivated) {
// This is supposed to clear the key display, and block exit until a button is pressed.
// For some reason, it doesn't work
m_override.key.key = static_cast<HidControllerKeys>(0);
m_inputBlocked = true;
Gui::g_exitBlocked = true;
if(kdown && !(kdown & (kdown - 1)) && (kdown <= KEY_DDOWN || kdown >= KEY_SL) && kdown != KEY_TOUCH) {
m_override.key.key = static_cast<HidControllerKeys>(kdown);
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
auto keyValue = m_override.key.ToString();
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption(OverrideKey::getOverrideKeyString(g_keyType), "")->value = keyValue;
// This is supposed to clear the key display, and block exit until a button is pressed.
// For some reason, it doesn't work
m_override.key.key = static_cast<HidControllerKeys>(0);
m_inputBlocked = true;
Gui::g_exitBlocked = true;
if (kdown && !(kdown & (kdown - 1)) && (kdown <= KEY_DDOWN || kdown >= KEY_SL) && kdown != KEY_TOUCH) {
m_override.key.key = static_cast<HidControllerKeys>(kdown);
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
auto keyValue = m_override.key.ToString();
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption(OverrideKey::getOverrideKeyString(g_keyType), "")->value = keyValue;
ini->writeToFile(LOADER_INI);
*isActivated = false;
m_inputBlocked = false;
Gui::g_exitBlocked = false;
ini->writeToFile(LOADER_INI);
*isActivated = false;
m_inputBlocked = false;
Gui::g_exitBlocked = false;
delete ini;
delete ini;
}
}
} }, {-1, 1, 2, -1}, true, []() -> bool { return true; });
};
add(keySelectButton);
//1
new Button(
640, 420, 380, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 20, y + 50, currTheme.textColor, "Key must be:", ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 360, y + 50, currTheme.selectedColor, m_override.key.overrideByDefault ? "Unpressed" : "Pressed", ALIGNED_RIGHT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
m_override.key.overrideByDefault = !m_override.key.overrideByDefault;
if (m_override.key.key == static_cast<HidControllerKeys>(0))
return;
auto comboPressedButton = Button();
comboPressedButton.position = {640, 420};
comboPressedButton.volume = {380, 80};
comboPressedButton.adjacentButton[ADJ_UP] = 0;
comboPressedButton.adjacentButton[ADJ_DOWN] = g_keyType == OverrideKeyType::Any_App_Override ? 3 : -1;
comboPressedButton.adjacentButton[ADJ_LEFT] = 2;
comboPressedButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 20, y + 50, currTheme.textColor, "Key must be:", ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 360, y + 50, currTheme.selectedColor, m_override.key.overrideByDefault ? "Unpressed" : "Pressed", ALIGNED_RIGHT);
};
comboPressedButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
m_override.key.overrideByDefault = !m_override.key.overrideByDefault;
if (m_override.key.key == static_cast<HidControllerKeys>(0))
return;
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
auto keyValue = m_override.key.ToString();
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption(OverrideKey::getOverrideKeyString(g_keyType), "")->value = keyValue;
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
auto keyValue = m_override.key.ToString();
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption(OverrideKey::getOverrideKeyString(g_keyType), "")->value = keyValue;
ini->writeToFile(LOADER_INI);
delete ini;
} }, {0, (g_keyType == OverrideKeyType::Any_App_Override ? 3 : -1), 2, -1}, false, []() -> bool { return true; });
ini->writeToFile(LOADER_INI);
delete ini;
}
};
add(comboPressedButton);
switch (g_keyType) {
case OverrideKeyType::Any_App_Override:
case OverrideKeyType::Any_App_Override: {
//2
new Button(
220, 200, 300, 300, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(fontHuge, x + 150, y + 190, currTheme.textColor, "\uE135", ALIGNED_CENTER);
gui->drawTextAligned(font24, x, y - 60, currTheme.textColor, "Override when entering:", ALIGNED_LEFT);
gui->drawTextAligned(font24, x, y - 20, currTheme.textColor, "Any title", ALIGNED_LEFT); }, [&](u64 kdown, bool *isActivated) {}, {-1, -1, -1, 0}, false, []() -> bool { return false; });
auto anyTitleIconButton = Button();
anyTitleIconButton.position = {220, 200};
anyTitleIconButton.volume = {300, 300};
anyTitleIconButton.adjacentButton[ADJ_RIGHT] = 0;
anyTitleIconButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(fontHuge, x + 150, y + 190, currTheme.textColor, "\uE135", ALIGNED_CENTER);
gui->drawTextAligned(font24, x, y - 60, currTheme.textColor, "Override when entering:", ALIGNED_LEFT);
gui->drawTextAligned(font24, x, y - 20, currTheme.textColor, "Any title", ALIGNED_LEFT);
};
anyTitleIconButton.usableCondition = []() -> bool { return false; };
add(anyTitleIconButton);
//3
new Button(
640, 520, 380, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 20, y + 50, currTheme.textColor, "Enabled", ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 360, y + 50, m_overrideAnyApp ? currTheme.selectedColor : currTheme.unselectedColor, m_overrideAnyApp ? "On" : "Off", ALIGNED_RIGHT); }, [&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
m_overrideAnyApp = !m_overrideAnyApp;
auto overrideEnabledButton = Button();
overrideEnabledButton.position = {640, 520};
overrideEnabledButton.volume = {380, 80};
overrideEnabledButton.adjacentButton[ADJ_UP] = 1;
overrideEnabledButton.adjacentButton[ADJ_LEFT] = 2;
overrideEnabledButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 20, y + 50, currTheme.textColor, "Enabled", ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 360, y + 50, m_overrideAnyApp ? currTheme.selectedColor : currTheme.unselectedColor, m_overrideAnyApp ? "On" : "Off", ALIGNED_RIGHT);
};
overrideEnabledButton.inputAction = [&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
m_overrideAnyApp = !m_overrideAnyApp;
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption("override_any_app", "")->value = m_overrideAnyApp ? "true" : "false";
//Find or create a loader ini file with set override_key values, and write the result to the file.
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)->findOrCreateFirstOption("override_any_app", "")->value = m_overrideAnyApp ? "true" : "false";
ini->writeToFile(LOADER_INI);
delete ini;
} }, {1, -1, 2, -1}, false, []() -> bool { return true; });
ini->writeToFile(LOADER_INI);
delete ini;
}
};
add(overrideEnabledButton);
break;
default:
}
default: {
//2
new Button(
220, 200, 300, 300,
[&, title{DumpTitle(m_override.programID)}](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font24, x, y - 60, currTheme.textColor, "Override when entering:", ALIGNED_LEFT);
if (title.get() != nullptr && title->application_id != 0) {
auto appIconButton = Button();
appIconButton.position = {220, 200};
appIconButton.volume = {300, 300};
appIconButton.adjacentButton[ADJ_DOWN] = 1;
appIconButton.adjacentButton[ADJ_RIGHT] = 0;
appIconButton.drawAction = [&, title{DumpTitle(m_override.programID)}](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font24, x, y - 60, currTheme.textColor, "Override when entering:", ALIGNED_LEFT);
if (title.get() != nullptr && title->application_id != 0) {
auto appletName = GetAppletName(title->application_id);
if (appletName == nullptr) {
appletName = title->name;
} else {
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 350, currTheme.activatedColor, "Opening hbmenu through an applet may not leave enough memory for homebrew applications. \n It's recommended to open hbmenu from a game to gain full RAM access.", ALIGNED_CENTER);
}
gui->drawTextAligned(font24, x, y - 20, currTheme.textColor, appletName, ALIGNED_LEFT);
if (title->icon.get() != nullptr)
gui->drawImage(x + 22, y + 22, 256, 256, title->icon.get(), ImageMode::IMAGE_MODE_RGBA32);
else
gui->drawTextAligned(fontHuge, x + 150, y + 186, GetAppletColor(title->application_id), GetAppletIcon(title->application_id), ALIGNED_CENTER);
auto appletName = GetAppletName(title->application_id);
if (appletName == nullptr) {
appletName = title->name;
} else {
gui->drawTextAligned(fontHuge, x + 150, y + 186, currTheme.unselectedColor, "\uE06B", ALIGNED_CENTER);
gui->drawTextAligned(font24, x + 150, y + 280, currTheme.unselectedColor, "No title selected", ALIGNED_CENTER);
gui->drawTextAligned(font20, Gui::g_framebuffer_width / 2, y + 350, currTheme.activatedColor, "Opening hbmenu through an applet may not leave enough memory for homebrew applications. \n It's recommended to open hbmenu from a game to gain full RAM access.", ALIGNED_CENTER);
}
},
[&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
GuiTitleList::selectedAppID = m_override.programID;
Gui::g_nextGui = GUI_TITLE_LIST;
}
},
{-1, 1, -1, 0}, false, []() -> bool { return true; });
break;
}
Button::select(selection);
gui->drawTextAligned(font24, x, y - 20, currTheme.textColor, appletName, ALIGNED_LEFT);
if (title->icon.get() != nullptr)
gui->drawImage(x + 22, y + 22, 256, 256, title->icon.get(), ImageMode::IMAGE_MODE_RGBA32);
else
gui->drawTextAligned(fontHuge, x + 150, y + 186, GetAppletColor(title->application_id), GetAppletIcon(title->application_id), ALIGNED_CENTER);
} else {
gui->drawTextAligned(fontHuge, x + 150, y + 186, currTheme.unselectedColor, "\uE06B", ALIGNED_CENTER);
gui->drawTextAligned(font24, x + 150, y + 280, currTheme.unselectedColor, "No title selected", ALIGNED_CENTER);
}
};
appIconButton.inputAction = [&](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
GuiTitleList::selectedAppID = m_override.programID;
Gui::g_nextGui = GUI_TITLE_LIST;
}
};
add(appIconButton);
break;
}
}
selectButton(selection);
endInit();
}
GuiOverrideKey::~GuiOverrideKey() {
selection = Button::getSelectedIndex();
Button::g_buttons.clear();
}
void GuiOverrideKey::update() {
Gui::update();
selection = getSelectedButtonIndex();
}
void GuiOverrideKey::draw() {
@ -147,8 +178,7 @@ void GuiOverrideKey::draw() {
Gui::drawTextAligned(font24, 70, 58, currTheme.textColor, " Application override settings", ALIGNED_LEFT);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
@ -156,24 +186,12 @@ void GuiOverrideKey::onInput(u32 kdown) {
if (!m_inputBlocked && kdown & KEY_B)
Gui::g_nextGui = GUI_OVERRIDES_MENU;
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) return;
}
}
void GuiOverrideKey::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiOverrideKey::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
inputButtons(kdown);
}
void GuiOverrideKey::loadConfigFile() {
// Get the override keys, if any exist
auto ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
auto ini = parseOrCreateFileFixed(LOADER_INI);
auto iniSection = ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section);
// Get the override key and program for un-numbered override

View File

@ -12,7 +12,6 @@
#include <algorithm>
GuiOverridesMenu::GuiOverridesMenu() : Gui() {
Button::g_buttons.clear();
loadConfigFile();
displayDefaultOption = true;
@ -30,16 +29,12 @@ GuiOverridesMenu::GuiOverridesMenu() : Gui() {
if (m_addConfigs.size() != 0 || displayDefaultOption || displayAnyTitleOption)
addButton(OverrideButtonType::Add_New);
Button::select(selection);
selectButton(selection);
endInit();
}
GuiOverridesMenu::~GuiOverridesMenu() {
selection = Button::getSelectedIndex();
Button::g_buttons.clear();
}
void GuiOverridesMenu::update() {
Gui::update();
selection = getSelectedButtonIndex();
}
void GuiOverridesMenu::draw() {
@ -52,23 +47,19 @@ void GuiOverridesMenu::draw() {
Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 25, currTheme.textColor, "\uE0E2 Delete \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT);
Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 150, currTheme.textColor, "Add key override options for each title. \n Opening that title while holding that key combination will override it with hbmenu.", ALIGNED_CENTER);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
void GuiOverridesMenu::onInput(u32 kdown) {
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) return;
}
if (inputButtons(kdown)) return;
if (kdown & KEY_B)
Gui::g_nextGui = GUI_MAIN;
if (kdown & KEY_X) {
//Get the button options based on selection
auto tuple = m_buttons[Button::getSelectedIndex()];
auto tuple = m_buttons[getSelectedButtonIndex()];
auto buttonType = std::get<0>(tuple);
auto keyType = std::get<1>(tuple);
if (buttonType != OverrideButtonType::Add_New) {
@ -125,15 +116,6 @@ void GuiOverridesMenu::onInput(u32 kdown) {
}
}
void GuiOverridesMenu::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiOverridesMenu::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}
void GuiOverridesMenu::addButton(OverrideButtonType buttonType, OverrideKeyType keyType, const ProgramOverrideKey &key) {
static std::vector<std::string> configNames;
configNames.reserve(static_cast<int>(OverrideKeyType::Num_OverrideKey_Types));
@ -213,8 +195,14 @@ void GuiOverridesMenu::addButton(OverrideButtonType buttonType, OverrideKeyType
default:
break;
}
new Button((220 * m_buttonCount) + 150, 250, 200, 300, drawAction, inputAction,
{-1, -1, m_buttonCount - 1, m_buttonCount + 1}, false, []() -> bool { return true; });
auto resultButton = Button();
resultButton.position = {(220 * m_buttonCount) + 150, 250};
resultButton.volume = {200, 300};
resultButton.drawAction = drawAction;
resultButton.inputAction = inputAction;
resultButton.adjacentButton[ADJ_LEFT] = m_buttonCount - 1;
resultButton.adjacentButton[ADJ_RIGHT] = m_buttonCount + 1;
add(resultButton);
if (keyType == OverrideKeyType::Default)
displayDefaultOption = false;
@ -232,7 +220,7 @@ void GuiOverridesMenu::loadConfigFile() {
m_addConfigs.push_back(static_cast<OverrideKeyType>(i));
}
// If it doesn't find the config with a section [hbl_config], it stops, as there is nothing more to read.
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
auto section = ini->findSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section);
if (section == nullptr)

View File

@ -90,68 +90,70 @@ GuiSysmodule::GuiSysmodule() : Gui() {
anyModulesPresent = true;
new Button(
100 + xOffset, 250 + yOffset, 500, 80, [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, sysmodule.second.name.c_str(), ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 420, y + 50, this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? currTheme.selectedColor : Gui::makeColor(0xB8, 0xBB, 0xC2, 0xFF), this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? "On" : "Off", ALIGNED_LEFT); }, [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
u64 pid;
u64 tid = std::stol(sysmodule.first.c_str(), nullptr, 16);
auto sysmoduleButton = Button();
sysmoduleButton.position = {100 + xOffset, 250 + yOffset};
sysmoduleButton.volume = {500, 80};
sysmoduleButton.drawAction = [&](Gui *gui, u16 x, u16 y, bool *isActivated) {
gui->drawTextAligned(font20, x + 37, y + 50, currTheme.textColor, sysmodule.second.name.c_str(), ALIGNED_LEFT);
gui->drawTextAligned(font20, x + 420, y + 50, this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? currTheme.selectedColor : Gui::makeColor(0xB8, 0xBB, 0xC2, 0xFF), this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end() ? "On" : "Off", ALIGNED_LEFT);
};
sysmoduleButton.inputAction = [&](u32 kdown, bool *isActivated) {
if (kdown & KEY_A) {
u64 pid;
u64 tid = std::stol(sysmodule.first.c_str(), nullptr, 16);
mkdir(std::string(CONTENTS_PATH + sysmodule.second.titleID + "/flags").c_str(), 777);
std::stringstream path;
path << CONTENTS_PATH << sysmodule.first << "/flags/boot2.flag";
mkdir(std::string(CONTENTS_PATH + sysmodule.second.titleID + "/flags").c_str(), 777);
std::stringstream path;
path << CONTENTS_PATH << sysmodule.first << "/flags/boot2.flag";
if (this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end()) {
if (!sysmodule.second.requiresReboot) {
pmshellTerminateProgram(tid);
} else {
(new MessageBox("This sysmodule requires a reboot to fully work. \n Please restart your console in order use it.", MessageBox::OKAY))->show();
}
if (this->m_runningSysmodules.find(sysmodule.first) != this->m_runningSysmodules.end()) {
if (!sysmodule.second.requiresReboot) {
pmshellTerminateProgram(tid);
} else {
(new MessageBox("This sysmodule requires a reboot to fully work. \n Please restart your console in order use it.", MessageBox::OKAY))->show();
}
remove(path.str().c_str());
} else {
if (sysmodule.second.requiresReboot) {
(new MessageBox("This sysmodule requires a reboot to fully work. \n Please restart your console in order use it.", MessageBox::OKAY))->show();
FILE *fptr = fopen(path.str().c_str(), "wb+");
if (fptr != nullptr) fclose(fptr);
} else {
NcmProgramLocation programLocation{
.program_id = tid,
.storageID = NcmStorageId_None,
};
if (R_SUCCEEDED(pmshellLaunchProgram(0, &programLocation, &pid))) {
FILE *fptr = fopen(path.str().c_str(), "wb+");
if (fptr != nullptr) fclose(fptr);
}
}
}
remove(path.str().c_str());
}
else {
if (sysmodule.second.requiresReboot) {
(new MessageBox("This sysmodule requires a reboot to fully work. \n Please restart your console in order use it.", MessageBox::OKAY))->show();
FILE *fptr = fopen(path.str().c_str(), "wb+");
if (fptr != nullptr) fclose(fptr);
} else {
NcmProgramLocation programLocation{
.program_id = tid,
.storageID = NcmStorageId_None,
};
if (R_SUCCEEDED(pmshellLaunchProgram(0, &programLocation, &pid))) {
FILE *fptr = fopen(path.str().c_str(), "wb+");
if (fptr != nullptr) fclose(fptr);
pid = 0;
pmdmntGetProcessId(&pid, tid);
if (!sysmodule.second.requiresReboot) {
if (pid != 0)
this->m_runningSysmodules.insert(sysmodule.first);
else
this->m_runningSysmodules.erase(sysmodule.first);
} else {
if (access(path.str().c_str(), F_OK) == 0)
this->m_runningSysmodules.insert(sysmodule.first);
else
this->m_runningSysmodules.erase(sysmodule.first);
}
}
}
}
pid = 0;
pmdmntGetProcessId(&pid, tid);
if (!sysmodule.second.requiresReboot) {
if (pid != 0)
this->m_runningSysmodules.insert(sysmodule.first);
else
this->m_runningSysmodules.erase(sysmodule.first);
} else {
if (access(path.str().c_str(), F_OK) == 0)
this->m_runningSysmodules.insert(sysmodule.first);
else
this->m_runningSysmodules.erase(sysmodule.first);
}
} },
{
(cnt % ROWS) != 0 ? (cnt - 1) : -1, //UP
(cnt % ROWS) != ROWS - 1 ? (cnt + 1) : -1, //DOWN
(cnt - ROWS), //LEFT
(cnt + ROWS) //RIGHT
},
false,
[&]() -> bool { return true; });
};
sysmoduleButton.adjacentButton = {
(cnt % ROWS) != 0 ? (cnt - 1) : -1, //UP
(cnt % ROWS) != ROWS - 1 ? (cnt + 1) : -1, //DOWN
(cnt - ROWS), //LEFT
(cnt + ROWS) //RIGHT
};
add(sysmoduleButton);
yOffset += 100;
@ -162,19 +164,14 @@ GuiSysmodule::GuiSysmodule() : Gui() {
cnt++;
}
Button::select(selection);
selectButton(selection);
endInit();
}
GuiSysmodule::~GuiSysmodule() {
selection = Button::getSelectedIndex();
selection = getSelectedButtonIndex();
pmshellExit();
pmdmntExit();
Button::g_buttons.clear();
}
void GuiSysmodule::update() {
Gui::update();
}
void GuiSysmodule::draw() {
@ -195,30 +192,16 @@ void GuiSysmodule::draw() {
else
Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 550, currTheme.textColor, "You currently don't have any supported sysmodules installed. To use this \n feature, please install any supported sysmodule as an NSP.", ALIGNED_CENTER);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::endDraw();
}
void GuiSysmodule::onInput(u32 kdown) {
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) break;
}
inputButtons(kdown);
if (kdown & KEY_B)
Gui::g_nextGui = GUI_MAIN;
if (hidMitmInstalled() && kdown & KEY_X)
Gui::g_nextGui = GUI_HID_MITM;
}
void GuiSysmodule::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiSysmodule::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}
}

View File

@ -35,63 +35,58 @@ GuiTitleList::GuiTitleList() : Gui() {
for (auto &&app : apps) {
new Button(
GRIDPOS + xOffset, 194 + yOffset, ICON_SIZE, ICON_SIZE,
auto appButton = Button();
appButton.position = {GRIDPOS + xOffset, 194 + yOffset};
appButton.volume = {ICON_SIZE, ICON_SIZE};
appButton.drawAction = [app, buttonIndex](Gui *gui, u16 x, u16 y, bool *isActivated) {
if (app != nullptr && app->application_id != 0) {
[app, buttonIndex](Gui *gui, u16 x, u16 y, bool *isActivated) {
if (app != nullptr && app->application_id != 0) {
auto appletName = GetAppletName(app->application_id);
if (appletName == nullptr)
appletName = app->name;
if (app->icon.get() != nullptr) {
gui->drawImage(x, y, ICON_SIZE, ICON_SIZE, app->icon.get(), ImageMode::IMAGE_MODE_RGBA32);
} else {
gui->drawTextAligned(fontIcons, x + ICON_SIZE / 2, y + ICON_SIZE / 2 + 24, GetAppletColor(app->application_id), GetAppletIcon(app->application_id), ALIGNED_CENTER);
}
if (Button::getSelectedIndex() == buttonIndex) {
u32 textWidth, textHeight;
gui->getTextDimensions(font20, appletName, &textWidth, &textHeight);
gui->drawRectangled((x + ICON_SIZE / 2 - textWidth / 2) - TEXT_BORDER * 2, (y - 32 - textHeight) - TEXT_BORDER, textWidth + TEXT_BORDER * 4, textHeight + TEXT_BORDER * 2, currTheme.overlayColor);
gui->drawTextAligned(font20, x + ICON_SIZE / 2, y - 36, currTheme.highlightTextColor, appletName, ALIGNED_CENTER);
}
auto appletName = GetAppletName(app->application_id);
if (appletName == nullptr)
appletName = app->name;
if (app->icon.get() != nullptr) {
gui->drawImage(x, y, ICON_SIZE, ICON_SIZE, app->icon.get(), ImageMode::IMAGE_MODE_RGBA32);
} else {
gui->drawTextAligned(fontHuge, x + ICON_SIZE / 2, y + ICON_SIZE / 2 + 48, currTheme.textColor, "\uE06B", ALIGNED_CENTER);
gui->drawTextAligned(fontIcons, x + ICON_SIZE / 2, y + ICON_SIZE / 2 + 24, GetAppletColor(app->application_id), GetAppletIcon(app->application_id), ALIGNED_CENTER);
}
},
[&, app](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
//convert title id to a hex string
char buffer[17];
sprintf(buffer, "%016lx", app->application_id);
//write title id to config
simpleIniParser::Ini *ini = simpleIniParser::Ini::parseOrCreateFile(LOADER_INI);
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)
->findOrCreateFirstOption(OverrideKey::getOverrideProgramString(GuiOverrideKey::g_keyType), "")
->value = buffer;
ini->writeToFile(LOADER_INI);
delete ini;
Gui::g_nextGui = GUI_OVERRIDE_KEY;
if (gui->getSelectedButtonIndex() == buttonIndex) {
u32 textWidth, textHeight;
gui->getTextDimensions(font20, appletName, &textWidth, &textHeight);
gui->drawRectangled((x + ICON_SIZE / 2 - textWidth / 2) - TEXT_BORDER * 2, (y - 32 - textHeight) - TEXT_BORDER, textWidth + TEXT_BORDER * 4, textHeight + TEXT_BORDER * 2, currTheme.overlayColor);
gui->drawTextAligned(font20, x + ICON_SIZE / 2, y - 36, currTheme.highlightTextColor, appletName, ALIGNED_CENTER);
}
},
{
(buttonIndex - COLUMNS), //UP
(buttonIndex + COLUMNS), //DOWN
(buttonIndex % COLUMNS) != 0 ? (buttonIndex - 1) : -1, //LEFT
(buttonIndex % COLUMNS) != COLUMNS - 1 ? (buttonIndex + 1) : -1, //RIGHT
} else {
gui->drawTextAligned(fontHuge, x + ICON_SIZE / 2, y + ICON_SIZE / 2 + 48, currTheme.textColor, "\uE06B", ALIGNED_CENTER);
}
};
appButton.inputAction = [&, app](u64 kdown, bool *isActivated) {
if (kdown & KEY_A) {
//{ -1, -1, buttonIndex - 1, buttonIndex + 1 }
,
false, []() -> bool { return true; });
//convert title id to a hex string
char buffer[17];
sprintf(buffer, "%016lx", app->application_id);
//write title id to config
simpleIniParser::Ini *ini = parseOrCreateFileFixed(LOADER_INI);
ini->findOrCreateSection(HBL_CONFIG, true, simpleIniParser::IniSectionType::Section)
->findOrCreateFirstOption(OverrideKey::getOverrideProgramString(GuiOverrideKey::g_keyType), "")
->value = buffer;
ini->writeToFile(LOADER_INI);
delete ini;
Gui::g_nextGui = GUI_OVERRIDE_KEY;
}
};
appButton.adjacentButton = {
(buttonIndex - COLUMNS), //UP
(buttonIndex + COLUMNS), //DOWN
(buttonIndex % COLUMNS) != 0 ? (buttonIndex - 1) : -1, //LEFT
(buttonIndex % COLUMNS) != COLUMNS - 1 ? (buttonIndex + 1) : -1, //RIGHT
};
add(appButton);
if (app->application_id == selectedAppID) {
buttonSelection = buttonIndex;
@ -105,25 +100,19 @@ GuiTitleList::GuiTitleList() : Gui() {
buttonIndex++;
}
Button::select(buttonSelection);
selectButton(buttonSelection);
endInit();
}
GuiTitleList::~GuiTitleList() {
Button::g_buttons.clear();
}
void GuiTitleList::update() {
Gui::update();
}
GuiTitleList::~GuiTitleList() {}
void GuiTitleList::draw() {
Gui::beginDraw();
Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor);
Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2 - Button::g_targetOffsetX, 150 - Button::g_targetOffsetY, currTheme.textColor, "Select the title you wish to override.", ALIGNED_CENTER);
Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2 - m_targetOffsetX, 150 - m_targetOffsetY, currTheme.textColor, "Select the title you wish to override.", ALIGNED_CENTER);
for (Button *btn : Button::g_buttons)
btn->draw(this);
drawButtons();
Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, 88, currTheme.backgroundColor);
Gui::drawRectangle(0, Gui::g_framebuffer_height - 73, Gui::g_framebuffer_width, 73, currTheme.backgroundColor);
@ -136,20 +125,8 @@ void GuiTitleList::draw() {
}
void GuiTitleList::onInput(u32 kdown) {
for (Button *btn : Button::g_buttons) {
if (btn->isSelected())
if (btn->onInput(kdown)) return;
}
if (inputButtons(kdown)) return;
if (kdown & KEY_B)
Gui::g_nextGui = GUI_OVERRIDE_KEY;
}
void GuiTitleList::onTouch(touchPosition &touch) {
for (Button *btn : Button::g_buttons) {
btn->onTouch(touch);
}
}
void GuiTitleList::onGesture(touchPosition &startPosition, touchPosition &endPosition) {
}

View File

@ -101,10 +101,6 @@ int main(int argc, char **argv) {
delete currGui;
Button::g_pageOffsetX = 0;
Button::g_pageOffsetY = 0;
Button::g_scrollBlocked = false;
switch (Gui::g_nextGui) {
case GUI_MAIN:
currGui = new GuiMain();
@ -130,15 +126,11 @@ int main(int argc, char **argv) {
break;
}
Button::g_targetOffsetX = Button::g_pageOffsetX;
Button::g_targetOffsetY = Button::g_pageOffsetY;
mutexUnlock(&mutexCurrGui);
Gui::g_nextGui = GUI_INVALID;
}
if (currGui != nullptr) {
Button::g_targetOffsetX = Lerp(Button::g_targetOffsetX, Button::g_pageOffsetX, SCROLL_SPEED);
Button::g_targetOffsetY = Lerp(Button::g_targetOffsetY, Button::g_pageOffsetY, SCROLL_SPEED);
currGui->draw();
if (kdown) {

View File

@ -115,3 +115,9 @@ color_t GetAppletColor(u64 appID) {
return currTheme.textColor;
}
}
simpleIniParser::Ini *parseOrCreateFileFixed(const std::string &path) {
auto file = simpleIniParser::Ini::parseFile(path);
if (!file) file = new simpleIniParser::Ini;
return file;
}