diff --git a/include/utils/config.hpp b/include/utils/config.hpp index c09ed28..08cae17 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -55,6 +55,9 @@ public: bool autoupdate() const { return this->v_autoUpdate; }; void autoupdate(bool v) { this->v_autoUpdate = v; if (!this->changesMade) this->changesMade = true; }; + bool _3dsxInFolder() const { return this->v_3dsxInFolder; }; + void _3dsxInFolder(bool v) { this->v_3dsxInFolder = v; if (!this->changesMade) this->changesMade = true; }; + std::string _3dsxPath() const { return this->v_3dsxPath; }; void _3dsxPath(const std::string &v) { this->v_3dsxPath = v; if (!this->changesMade) this->changesMade = true; }; @@ -117,7 +120,7 @@ private: v_shortcutPath = "sdmc:/3ds/Universal-Updater/shortcuts", v_firmPath = "sdmc:/luma/payloads"; bool v_list = false, v_autoUpdate = true, v_metadata = true, v_updateCheck = true, - v_showBg = false, v_customFont = false, v_changelog = true, v_prompt = true; + v_showBg = false, v_customFont = false, v_changelog = true, v_prompt = true, v_3dsxInFolder = false; }; #endif diff --git a/romfs/lang/en/app.json b/romfs/lang/en/app.json index eb3ab5f..dc15e2a 100644 --- a/romfs/lang/en/app.json +++ b/romfs/lang/en/app.json @@ -1,4 +1,6 @@ { + "3DSX_IN_FOLDER": "Put 3DSX files in folder", + "3DSX_IN_FOLDER_DESC": "If enabled, 3DSX files will be put in a folder with the same name instead of directly in the set folder.", "ACTION_CANCELED": "%s canceled!", "ACTION_FAILED": "%s failed!", "ACTION_REQUIRED": "Action required!", diff --git a/source/menu/settings.cpp b/source/menu/settings.cpp index 3e2d94b..d91a93e 100644 --- a/source/menu/settings.cpp +++ b/source/menu/settings.cpp @@ -59,12 +59,30 @@ static const std::vector toggleAbles = { { 288, 120, 24, 24 } }; +static const std::vector dirButtons = { + { 41, 34, 280, 24 }, + { 41, 64, 280, 24 }, + { 41, 120, 280, 24 }, + { 41, 150, 280, 24 }, + { 41, 180, 280, 24 }, + { 41, 210, 280, 24 } +}; + +static const std::vector dirIcons = { + { 288, 34, 24, 24 }, + { 288, 64, 24, 24 }, + { 288, 120, 24, 24 }, + { 288, 150, 24, 24 }, + { 288, 180, 24, 24 }, + { 288, 210, 24, 24 } +}; + static const Structs::ButtonPos back = { 45, 0, 24, 24 }; // Back arrow for directory. static const Structs::ButtonPos Themes = { 40, 220, 280, 24 }; // Themes. static const std::vector mainStrings = { "LANGUAGE", "SELECT_UNISTORE", "AUTO_UPDATE_SETTINGS_BTN", "GUI_SETTINGS_BTN", "DIRECTORY_SETTINGS_BTN", "CREDITS", "EXIT_APP" }; -static const std::vector dirStrings = { "CHANGE_3DSX_PATH", "CHANGE_NDS_PATH", "CHANGE_ARCHIVE_PATH", "CHANGE_SHORTCUT_PATH", "CHANGE_FIRM_PATH" }; +static const std::vector dirStrings = { "CHANGE_3DSX_PATH", "3DSX_IN_FOLDER", "CHANGE_NDS_PATH", "CHANGE_ARCHIVE_PATH", "CHANGE_SHORTCUT_PATH", "CHANGE_FIRM_PATH" }; /* Note: Украïнська is spelled using a latin i with dieresis to work in the system font */ //static const std::vector languages = { "Bruh", "Dansk", "Deutsch", "English", "Español", "Français", "Italiano", "Lietuvių", "Magyar", "Polski", "Português", "Português (Brasil)", "Русский", "Украïнська", "日本語" }; @@ -120,9 +138,15 @@ static void DrawSettingsDir(int selection) { GFX::DrawSprite(sprites_arrow_idx, back.x, back.y); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("DIRECTORY_SETTINGS"), 248, 0, font); - for (int i = 0; i < 5; i++) { - if (i == selection) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected); - Gui::DrawStringCentered(20, mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get(dirStrings[i]), 255, 0, font); + for (int i = 0; i < (int)dirButtons.size(); i++) { + Gui::Draw_Rect(dirButtons[i].x, dirButtons[i].y, dirButtons[i].w, dirButtons[i].h, (selection == i ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected)); + Gui::DrawString(dirButtons[i].x + 4, dirButtons[i].y + 4, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get(dirStrings[i]), 210, 0, font); + if(i == 1) { // Put 3DSX in folder has a toggle and description + GFX::DrawToggle(dirIcons[i].x, dirIcons[i].y, config->_3dsxInFolder()); + Gui::DrawString(dirButtons[i].x + 4, dirButtons[i].y + 28, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("3DSX_IN_FOLDER_DESC"), 265, 0, font, C2D_WordWrap); + } else { + GFX::DrawSprite(sprites_arrow_idx, dirIcons[i].x, dirIcons[i].y, -1.0f); + } } } @@ -310,7 +334,7 @@ static void SettingsHandleDir(int &page, int &selection) { } if (hRepeat & KEY_DOWN) { - if (selection < 4) selection++; + if (selection < (int)dirStrings.size() - 1) selection++; else selection = 0; } @@ -334,23 +358,26 @@ static void SettingsHandleDir(int &page, int &selection) { page = 0; selection = 4; - } else if (touching(touch, mainButtons[0])) { + } else if (touching(touch, dirButtons[0])) { const std::string path = Overlays::SelectDir(config->_3dsxPath(), Lang::get("SELECT_DIR")); if (path != "") config->_3dsxPath(path); - } else if (touching(touch, mainButtons[1])) { + } else if (touching(touch, dirButtons[1])) { + config->_3dsxInFolder(!config->_3dsxInFolder()); + + } else if (touching(touch, dirButtons[2])) { const std::string path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR")); if (path != "") config->ndsPath(path); - } else if (touching(touch, mainButtons[2])) { + } else if (touching(touch, dirButtons[3])) { const std::string path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR")); if (path != "") config->archPath(path); - } else if (touching(touch, mainButtons[3])) { + } else if (touching(touch, dirButtons[4])) { const std::string path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR")); if (path != "") config->shortcut(path); - } else if (touching(touch, mainButtons[4])) { + } else if (touching(touch, dirButtons[5])) { const std::string path = Overlays::SelectDir(config->firmPath(), Lang::get("SELECT_DIR")); if (path != "") config->firmPath(path); } @@ -366,21 +393,25 @@ static void SettingsHandleDir(int &page, int &selection) { break; case 1: + config->_3dsxInFolder(!config->_3dsxInFolder()); + break; + + case 2: path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR")); if (path != "") config->ndsPath(path); break; - case 2: + case 3: path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR")); if (path != "") config->archPath(path); break; - case 3: + case 4: path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR")); if (path != "") config->shortcut(path); break; - case 4: + case 5: path = Overlays::SelectDir(config->firmPath(), Lang::get("SELECT_DIR")); if (path != "") config->firmPath(path); break; diff --git a/source/utils/scriptUtils.cpp b/source/utils/scriptUtils.cpp index 221161a..4aeec02 100644 --- a/source/utils/scriptUtils.cpp +++ b/source/utils/scriptUtils.cpp @@ -51,6 +51,7 @@ bool ScriptUtils::matchPattern(const std::string &pattern, const std::string &te Result ScriptUtils::removeFile(const std::string &file, const std::string &message, bool isARG) { std::string out; out = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + out = std::regex_replace(out, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath()); @@ -96,11 +97,13 @@ Result ScriptUtils::copyFile(const std::string &source, const std::string &desti std::string _source, _dest; _source = std::regex_replace(source, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + _source = std::regex_replace(_source, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); _source = std::regex_replace(_source, std::regex("%3DSX%"), config->_3dsxPath()); _source = std::regex_replace(_source, std::regex("%NDS%"), config->ndsPath()); _source = std::regex_replace(_source, std::regex("%FIRM%"), config->firmPath()); _dest = std::regex_replace(destination, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + _dest = std::regex_replace(_dest, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); _dest = std::regex_replace(_dest, std::regex("%3DSX%"), config->_3dsxPath()); _dest = std::regex_replace(_dest, std::regex("%NDS%"), config->ndsPath()); _dest = std::regex_replace(_dest, std::regex("%FIRM%"), config->firmPath()); @@ -138,11 +141,13 @@ Result ScriptUtils::renameFile(const std::string &oldName, const std::string &ne std::string old, _new; old = std::regex_replace(oldName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + old = std::regex_replace(old, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); old = std::regex_replace(old, std::regex("%3DSX%"), config->_3dsxPath()); old = std::regex_replace(old, std::regex("%NDS%"), config->ndsPath()); old = std::regex_replace(old, std::regex("%FIRM%"), config->firmPath()); _new = std::regex_replace(newName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + _new = std::regex_replace(_new, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); _new = std::regex_replace(_new, std::regex("%3DSX%"), config->_3dsxPath()); _new = std::regex_replace(_new, std::regex("%NDS%"), config->ndsPath()); _new = std::regex_replace(_new, std::regex("%FIRM%"), config->firmPath()); @@ -158,7 +163,8 @@ Result ScriptUtils::renameFile(const std::string &oldName, const std::string &ne /* Download from GitHub Release. */ Result ScriptUtils::downloadRelease(const std::string &repo, const std::string &file, const std::string &output, bool includePrereleases, const std::string &message, bool isARG) { std::string out; - out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath()); + out = std::regex_replace(output, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); + out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath()); @@ -200,7 +206,8 @@ Result ScriptUtils::downloadRelease(const std::string &repo, const std::string & /* Download a file. */ Result ScriptUtils::downloadFile(const std::string &file, const std::string &output, const std::string &message, bool isARG) { std::string out; - out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath()); + out = std::regex_replace(output, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); + out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath()); @@ -244,6 +251,7 @@ Result ScriptUtils::downloadFile(const std::string &file, const std::string &out void ScriptUtils::installFile(const std::string &file, bool updatingSelf, const std::string &message, bool isARG) { std::string in; in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + in = std::regex_replace(in, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath()); in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath()); in = std::regex_replace(in, std::regex("%FIRM%"), config->firmPath()); @@ -273,10 +281,13 @@ void ScriptUtils::extractFile(const std::string &file, const std::string &input, std::string out, in; in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + in = std::regex_replace(in, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath()); in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath()); in = std::regex_replace(in, std::regex("%FIRM%"), config->firmPath()); + out = std::regex_replace(output, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); + out = std::regex_replace(out, std::regex("%3DSX%/(.*)\\.(.*)"), config->_3dsxPath() + (config->_3dsxInFolder() ? "/$1/$1.$2" : "/$1.$2")); out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath());