mirror of
https://github.com/Team-Neptune/DeepSea-Toolbox.git
synced 2024-11-23 04:19:42 +00:00
Revamp button system and slightly revamp gui system
This commit is contained in:
parent
9a914919ba
commit
b07293a685
@ -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;
|
||||
};
|
||||
|
@ -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];
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user