From 89d4472d073d87fd9fbdaa4c1db102f83a50b9ae Mon Sep 17 00:00:00 2001 From: J-D-K Date: Sat, 10 Aug 2024 13:28:30 -0400 Subject: [PATCH] Fix up menus a bit --- inc/data/data.hpp | 2 +- inc/data/user.hpp | 1 - inc/data/userSaveInfo.hpp | 1 - inc/filesystem/directoryListing.hpp | 1 + inc/graphics/systemFont.hpp | 1 - inc/ui/menu.hpp | 2 + src/appStates/backupMenuState.cpp | 37 +++++----- src/appStates/confirmState.cpp | 55 ++++++++------- src/appStates/mainMenuState.cpp | 29 ++++---- src/appStates/progressState.cpp | 11 ++- src/appStates/taskState.cpp | 9 ++- src/appStates/titleOptionState.cpp | 29 ++++---- src/appStates/titleSelectionState.cpp | 21 +++--- src/appStates/userOptionState.cpp | 97 ++++++++++++++++----------- src/data/data.cpp | 40 +++++------ src/data/titleInfo.cpp | 15 ++--- src/data/user.cpp | 64 +++++++++--------- src/data/userSaveInfo.cpp | 7 +- src/filesystem/directoryListing.cpp | 5 +- src/filesystem/filesystem.cpp | 4 +- src/graphics/systemFont.cpp | 31 +++++---- src/ui/menu.cpp | 49 +++++++++----- 22 files changed, 269 insertions(+), 242 deletions(-) diff --git a/inc/data/data.hpp b/inc/data/data.hpp index b32c634..df50f9f 100755 --- a/inc/data/data.hpp +++ b/inc/data/data.hpp @@ -11,7 +11,7 @@ namespace data { // Makes stuff easier to type. using titleMap = std::unordered_map; - + // Loads users and titles from switch records. This is the initial loading routine and can run as a task. bool init(void); // Loads save data for users diff --git a/inc/data/user.hpp b/inc/data/user.hpp index 8b37200..7d9c002 100755 --- a/inc/data/user.hpp +++ b/inc/data/user.hpp @@ -53,6 +53,5 @@ namespace data data::userType m_UserType; // Vector of save info for user std::vector m_UserSaveInfo; - }; } \ No newline at end of file diff --git a/inc/data/userSaveInfo.hpp b/inc/data/userSaveInfo.hpp index 7f7e416..3dd653e 100755 --- a/inc/data/userSaveInfo.hpp +++ b/inc/data/userSaveInfo.hpp @@ -11,7 +11,6 @@ namespace data public: // Inits data userSaveInfo(uint64_t titleID, const FsSaveDataInfo &saveDataInfo, const PdmPlayStatistics &playStats); - // These do not return references or pointers so they can't be changed uint64_t getTitleID(void) const; // Not sure how I feel about returning references, but I don't wanna make copies to get the data from these. diff --git a/inc/filesystem/directoryListing.hpp b/inc/filesystem/directoryListing.hpp index a681d82..693170a 100755 --- a/inc/filesystem/directoryListing.hpp +++ b/inc/filesystem/directoryListing.hpp @@ -8,6 +8,7 @@ namespace fs class directoryListing { public: + directoryListing(void) = default; // Gets and stores a listing for directoryPath directoryListing(const std::string &directoryPath); // This is the function that actually loads the directory list. Vector is cleared at beginning. diff --git a/inc/graphics/systemFont.hpp b/inc/graphics/systemFont.hpp index c9ec958..3fffce2 100755 --- a/inc/graphics/systemFont.hpp +++ b/inc/graphics/systemFont.hpp @@ -10,7 +10,6 @@ namespace graphics // Inits freetype2 bool init(void); void exit(void); - // Renders text with system font void renderText(const std::string &text, SDL_Texture *target, int x, int y, int fontSize, uint32_t color); // Renders text, but wraps to new line if maxWidth is hit or exeeded diff --git a/inc/ui/menu.hpp b/inc/ui/menu.hpp index 948d667..0c27f43 100755 --- a/inc/ui/menu.hpp +++ b/inc/ui/menu.hpp @@ -48,6 +48,8 @@ namespace ui bool m_ColorShift = true; // Amount to add/subtract from color to pulse int m_ColorMod = 0; + // Render target for menu options + graphics::sdlTexture m_OptionRenderTarget; private: // Vector of options diff --git a/src/appStates/backupMenuState.cpp b/src/appStates/backupMenuState.cpp index e053bcc..aae977a 100755 --- a/src/appStates/backupMenuState.cpp +++ b/src/appStates/backupMenuState.cpp @@ -27,7 +27,7 @@ namespace const std::string POP_MESSAGE_SAVE_EMPTY = "popSaveIsEmpty"; const std::string CONFIRM_OVERWRITE = "confirmOverwrite"; const std::string CONFIRM_RESTORE = "confirmRestore"; - const std::string CONFIRM_DELETE = "confirmDelete"; + const std::string CONFIRM_DELETE = "confirmDelete"; const std::string BACKUP_MENU_NEW = "folderMenuNew"; const std::string SWKBD_PROMPT_TEXT = "swkbdEnterName"; } @@ -66,7 +66,7 @@ static void createNewBackup(sys::task *task, sys::sharedTaskData sharedData) // Set task status, cast args to backupArgs std::shared_ptr dataIn = std::static_pointer_cast(sharedData); - + // To do: Maybe find a better way to do this without rewriting everything sys::progressTask *progress = reinterpret_cast(task); @@ -183,14 +183,14 @@ static void restoreBackup(sys::task *task, sys::sharedTaskData sharedData) // Get extension before we try to unzip something that isn't a zip std::string fileExtension = stringUtil::getExtensionFromString(dataIn->source); - if(std::filesystem::is_directory(dataIn->source)) + if (std::filesystem::is_directory(dataIn->source)) { // Add trailing slash std::string source = dataIn->source + "/"; // Get a test listing first to prevent writing an empty folder to save fs::directoryListing testListing(source); - if(testListing.getListingCount() > 0) + if (testListing.getListingCount() > 0) { // Folder isn't empty, erase fs::io::deleteDirectoryRecursively(fs::DEFAULT_SAVE_MOUNT_DEVICE); @@ -198,12 +198,12 @@ static void restoreBackup(sys::task *task, sys::sharedTaskData sharedData) fs::io::copyDirectoryCommit(source, fs::DEFAULT_SAVE_MOUNT_DEVICE, dataIn->journalSize, progress); } } - else if(std::filesystem::is_directory(dataIn->source) == false && fileExtension == "zip") + else if (std::filesystem::is_directory(dataIn->source) == false && fileExtension == "zip") { // Open zip for decompressing unzFile unzip = unzOpen64(dataIn->source.c_str()); // Check if opening was successful and not empty first - if(unzip != NULL && fs::zip::zipFileIsNotEmpty(unzip)) + if (unzip != NULL && fs::zip::zipFileIsNotEmpty(unzip)) { fs::zip::copyZipToDirectory(unzip, fs::DEFAULT_SAVE_MOUNT_DEVICE, dataIn->journalSize, progress); } @@ -244,22 +244,21 @@ static void deleteBackup(sys::task *task, sys::sharedTaskData sharedData) task->finished(); } -backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : -m_CurrentUser(currentUser), -m_CurrentUserSaveInfo(currentUserSaveInfo), -m_CurrentTitleInfo(currentTitleInfo), -m_BackupMenuControlGuide(ui::strings::getString(FOLDER_MENU_CONTROL_GUIDE, 0)), -m_OutputBasePath(config::getWorkingDirectory() + m_CurrentTitleInfo->getPathSafeTitle() + "/"), -m_PanelWidth(graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18)), -m_BackupPanel(std::make_unique(BACKUP_PANEL_NAME, m_PanelWidth + 64, ui::PANEL_SIDE_RIGHT)), -m_BackupListing(std::make_unique(m_OutputBasePath)), -m_SaveListing(std::make_unique(fs::DEFAULT_SAVE_MOUNT_DEVICE)), -m_BackupMenu(std::make_unique(10, 4, m_PanelWidth + 44, 18, 6)) +backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : m_CurrentUser(currentUser), + m_CurrentUserSaveInfo(currentUserSaveInfo), + m_CurrentTitleInfo(currentTitleInfo), + m_BackupMenuControlGuide(ui::strings::getString(FOLDER_MENU_CONTROL_GUIDE, 0)), + m_OutputBasePath(config::getWorkingDirectory() + m_CurrentTitleInfo->getPathSafeTitle() + "/"), + m_PanelWidth(graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18)), + m_BackupPanel(std::make_unique(BACKUP_PANEL_NAME, m_PanelWidth + 64, ui::PANEL_SIDE_RIGHT)), + m_BackupListing(std::make_unique(m_OutputBasePath)), + m_SaveListing(std::make_unique(fs::DEFAULT_SAVE_MOUNT_DEVICE)), + m_BackupMenu(std::make_unique(10, 4, m_PanelWidth + 44, 18, 6)) { // Make sure path exists std::filesystem::create_directories(m_OutputBasePath); // Render target that menu is rendered to - m_BackupMenuRenderTarget = graphics::textureManager::createTexture(BACKUP_MENU_TARGET_NAME, m_PanelWidth + 64, 720, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); + m_BackupMenuRenderTarget = graphics::textureManager::createTexture(BACKUP_MENU_TARGET_NAME, m_PanelWidth + 64, 647, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); // Call this just to be sure. backupMenuState::loadDirectoryList(); } @@ -320,7 +319,7 @@ void backupMenuState::update(void) // Setup confirmation arg pointer std::shared_ptr paths = std::make_shared(); - paths->source = m_BackupListing->getFullPathToItemAt(selected - 1); // Need to subtract one to account for 'New' option + paths->source = m_BackupListing->getFullPathToItemAt(selected - 1); // Need to subtract one to account for 'New' option paths->journalSize = m_CurrentTitleInfo->getJournalSize(static_cast(m_CurrentUserSaveInfo->getSaveDataInfo().save_data_type)); // Needed to prevent commit errors // Create confirmation diff --git a/src/appStates/confirmState.cpp b/src/appStates/confirmState.cpp index f025583..75af640 100755 --- a/src/appStates/confirmState.cpp +++ b/src/appStates/confirmState.cpp @@ -13,36 +13,35 @@ namespace constexpr int HOLD_TICKS = 1000; // Strings used here const std::string DIALOG_YES = "dialogYes"; - const std::string DIALOG_NO = "dialogNo"; + const std::string DIALOG_NO = "dialogNo"; const std::string HOLDING_TEXT = "holdingText"; } -confirmState::confirmState(const std::string &message, sys::taskFunction onConfirmation, sys::sharedTaskData sharedData, sys::taskTypes taskType) : -m_Message(message), -m_Yes(ui::strings::getString(DIALOG_YES, 0)), -m_No(ui::strings::getString(DIALOG_NO, 0)), -m_HoldTimer(std::make_unique(HOLD_TICKS)), -m_OnConfirmation(onConfirmation), -m_SharedData(sharedData), -m_TaskType(taskType) { } +confirmState::confirmState(const std::string &message, sys::taskFunction onConfirmation, sys::sharedTaskData sharedData, sys::taskTypes taskType) : m_Message(message), + m_Yes(ui::strings::getString(DIALOG_YES, 0)), + m_No(ui::strings::getString(DIALOG_NO, 0)), + m_HoldTimer(std::make_unique(HOLD_TICKS)), + m_OnConfirmation(onConfirmation), + m_SharedData(sharedData), + m_TaskType(taskType) {} -confirmState::~confirmState() { } +confirmState::~confirmState() {} // To do: I don't like the way this looks, but not sure if it can get much better void confirmState::update(void) { // If A is first pressed, and stage is 0, restart timer - if(sys::input::buttonDown(HidNpadButton_A) && m_HoldStage == 0) + if (sys::input::buttonDown(HidNpadButton_A) && m_HoldStage == 0) { m_HoldTimer->restartTimer(); } - else if(sys::input::buttonHeld(HidNpadButton_A) && m_HoldStage < 3 && m_HoldTimer->triggered()) + else if (sys::input::buttonHeld(HidNpadButton_A) && m_HoldStage < 3 && m_HoldTimer->triggered()) { // Confirmed, create new task. - if(++m_HoldStage == 3) + if (++m_HoldStage == 3) { // Spawn task according to m_TaskType - switch(m_TaskType) + switch (m_TaskType) { case sys::taskTypes::TASK_TYPE_TASK: { @@ -65,30 +64,30 @@ void confirmState::update(void) switch (m_HoldStage) { case 0: - { - m_Yes = ui::strings::getString(HOLDING_TEXT, 0); - } - break; + { + m_Yes = ui::strings::getString(HOLDING_TEXT, 0); + } + break; case 1: - { - m_Yes = ui::strings::getString(HOLDING_TEXT, 1); - } - break; + { + m_Yes = ui::strings::getString(HOLDING_TEXT, 1); + } + break; case 2: - { - m_Yes = ui::strings::getString(HOLDING_TEXT, 2); - } - break; + { + m_Yes = ui::strings::getString(HOLDING_TEXT, 2); + } + break; } } } - else if(sys::input::buttonReleased(HidNpadButton_A)) + else if (sys::input::buttonReleased(HidNpadButton_A)) { m_Yes = ui::strings::getString(DIALOG_YES, 0); } - else if(sys::input::buttonDown(HidNpadButton_B)) + else if (sys::input::buttonDown(HidNpadButton_B)) { // Party's over. Just stop appState::deactivateState(); diff --git a/src/appStates/mainMenuState.cpp b/src/appStates/mainMenuState.cpp index 2244d99..2f13d64 100755 --- a/src/appStates/mainMenuState.cpp +++ b/src/appStates/mainMenuState.cpp @@ -41,14 +41,14 @@ static void backupAllUserSaves(sys::task *task, sys::sharedTaskData sharedData) // Loop through users int totalUserCount = data::getTotalUsers(); - for(int i = 0; i < totalUserCount; i++) + for (int i = 0; i < totalUserCount; i++) { // Get pointer to user data::user *currentUser = data::getUserAtPosition(i); // Loop through titles int totalUserGameCount = currentUser->getTotalUserSaveInfo(); - for(int j = 0; j < totalUserGameCount; j++) + for (int j = 0; j < totalUserGameCount; j++) { // Get pointer to userSaveInfo data::userSaveInfo *currentUserSaveInfo = currentUser->getUserSaveInfoAt(j); @@ -60,20 +60,20 @@ static void backupAllUserSaves(sys::task *task, sys::sharedTaskData sharedData) bool saveIsMounted = fs::mountSaveData(currentUserSaveInfo->getSaveDataInfo()); // Make sure full path for title exists fs::createTitleDirectoryByTID(currentUserSaveInfo->getTitleID()); - if(saveIsMounted && fs::directoryContainsFiles(fs::DEFAULT_SAVE_MOUNT_DEVICE) && config::getByKey(CONFIG_USE_ZIP)) + if (saveIsMounted && fs::directoryContainsFiles(fs::DEFAULT_SAVE_MOUNT_DEVICE) && config::getByKey(CONFIG_USE_ZIP)) { // Path to zip we're backing up. It's a biggin' - std::string outputZipPath = config::getWorkingDirectory() + currentTitleInfo->getPathSafeTitle() + "/" + currentUser->getPathSafeUsername() + \ + std::string outputZipPath = config::getWorkingDirectory() + currentTitleInfo->getPathSafeTitle() + "/" + currentUser->getPathSafeUsername() + " - " + stringUtil::getTimeAndDateString(stringUtil::DATE_FORMAT_YMD) + ".zip"; // Open zip zipFile newZip = zipOpen64(outputZipPath.c_str(), 0); // Copy to it fs::zip::copyDirectoryToZip(fs::DEFAULT_SAVE_MOUNT_DEVICE, newZip, progress); } - else if(saveIsMounted && fs::directoryContainsFiles(fs::DEFAULT_SAVE_MOUNT_DEVICE) && config::getByKey(CONFIG_USE_ZIP) == false) + else if (saveIsMounted && fs::directoryContainsFiles(fs::DEFAULT_SAVE_MOUNT_DEVICE) && config::getByKey(CONFIG_USE_ZIP) == false) { // Output path - std::string newSaveBackupPath = config::getWorkingDirectory() + currentTitleInfo->getPathSafeTitle() + "/" + currentUser->getPathSafeUsername() + \ + std::string newSaveBackupPath = config::getWorkingDirectory() + currentTitleInfo->getPathSafeTitle() + "/" + currentUser->getPathSafeUsername() + " - " + stringUtil::getTimeAndDateString(stringUtil::DATE_FORMAT_YMD) + "/"; // Make sure it exists std::filesystem::create_directories(newSaveBackupPath); @@ -86,10 +86,9 @@ static void backupAllUserSaves(sys::task *task, sys::sharedTaskData sharedData) progress->finished(); } -mainMenuState::mainMenuState(void) : -m_MainControlGuide(ui::strings::getString(MAIN_MENU_CONTROL_GUIDE, 0)), -m_MainControlGuideX(1220 - graphics::systemFont::getTextWidth(m_MainControlGuide, 18)), -m_MainMenu(std::make_unique(50, 16, 1)) +mainMenuState::mainMenuState(void) : m_MainControlGuide(ui::strings::getString(MAIN_MENU_CONTROL_GUIDE, 0)), + m_MainControlGuideX(1220 - graphics::systemFont::getTextWidth(m_MainControlGuide, 18)), + m_MainMenu(std::make_unique(50, 16, 1)) { // Render target m_RenderTarget = graphics::textureManager::createTexture(MAIN_MENU_RENDER_TARGET, 200, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); @@ -119,11 +118,11 @@ void mainMenuState::update(void) m_MainMenu->update(); int selected = m_MainMenu->getSelected(); - if(sys::input::buttonDown(HidNpadButton_A) && selected < m_UserEnd) + if (sys::input::buttonDown(HidNpadButton_A) && selected < m_UserEnd) { data::user *selectedUser = data::getUserAtPosition(selected); // Normally wouldn't do this - if(selectedUser->getTotalUserSaveInfo() > 0) + if (selectedUser->getTotalUserSaveInfo() > 0) { std::unique_ptr titleSelection = std::make_unique(selectedUser); jksv::pushNewState(titleSelection); @@ -134,12 +133,12 @@ void mainMenuState::update(void) ui::popMessage::newMessage(noSavesMessage, ui::popMessage::POPMESSAGE_DEFAULT_TICKS); } } - else if(sys::input::buttonDown(HidNpadButton_Y)) + else if (sys::input::buttonDown(HidNpadButton_Y)) { // This doesn't need any input createAndPushNewProgressState(backupAllUserSaves, nullptr); } - else if(sys::input::buttonDown(HidNpadButton_X) && selected < m_UserEnd) + else if (sys::input::buttonDown(HidNpadButton_X) && selected < m_UserEnd) { // Get selected user data::user *selectedUser = data::getUserAtPosition(selected); @@ -159,7 +158,7 @@ void mainMenuState::render(void) // Render render target to framebuffer graphics::textureRender(m_RenderTarget.get(), NULL, 0, 91); - if(appState::hasFocus()) + if (appState::hasFocus()) { graphics::systemFont::renderText(m_MainControlGuide, NULL, m_MainControlGuideX, 673, 18, COLOR_WHITE); } diff --git a/src/appStates/progressState.cpp b/src/appStates/progressState.cpp index 7fc7519..8adfb87 100755 --- a/src/appStates/progressState.cpp +++ b/src/appStates/progressState.cpp @@ -15,7 +15,7 @@ namespace const double PROG_BAR_WIDTH = 648.0f; const int PROG_BAR_X = 312; const int PROG_BAR_Y = 471; - //static const int PROG_BAR_WIDTH = 484; Where'd this come from? Try to figure it out later... + // static const int PROG_BAR_WIDTH = 484; Where'd this come from? Try to figure it out later... const int PROG_BAR_HEIGHT = 32; // These are for the status string const int STATUS_TEXT_X = PROG_DIALOG_X + 16; @@ -27,14 +27,13 @@ namespace const int PROGRESS_STATUS_FONT_SIZE = 18; } -progressState::progressState(sys::taskFunction threadFunction, sys::sharedTaskData sharedData) : -m_Task(std::make_unique(threadFunction, sharedData)) { } +progressState::progressState(sys::taskFunction threadFunction, sys::sharedTaskData sharedData) : m_Task(std::make_unique(threadFunction, sharedData)) {} -progressState::~progressState() { } +progressState::~progressState() {} void progressState::update(void) { - if(m_Task->isRunning() == false) + if (m_Task->isRunning() == false) { appState::deactivateState(); } @@ -63,7 +62,7 @@ void progressState::render() graphics::renderRect(NULL, PROG_BAR_X, PROG_BAR_Y, PROG_BAR_WIDTH, PROG_BAR_HEIGHT, COLOR_BLACK); graphics::renderRect(NULL, PROG_BAR_X, PROG_BAR_Y, m_BarWidth, PROG_BAR_HEIGHT, COLOR_GREEN); graphics::systemFont::renderTextWrap(m_TaskStatus, NULL, STATUS_TEXT_X, STATUS_TEXT_Y, STATUS_TEXT_FONT_SIZE, STATUS_TEXT_MAX_WIDTH, COLOR_WHITE); // Status - graphics::systemFont::renderText(m_ProgressStatus, NULL, m_ProgressStatusX, PROGRESS_STATUS_Y, PROGRESS_STATUS_FONT_SIZE, COLOR_WHITE); // Actual progress + graphics::systemFont::renderText(m_ProgressStatus, NULL, m_ProgressStatusX, PROGRESS_STATUS_Y, PROGRESS_STATUS_FONT_SIZE, COLOR_WHITE); // Actual progress } void createAndPushNewProgressState(sys::taskFunction threadFunction, sys::sharedTaskData sharedData) diff --git a/src/appStates/taskState.cpp b/src/appStates/taskState.cpp index d296ec3..8cb7cc3 100755 --- a/src/appStates/taskState.cpp +++ b/src/appStates/taskState.cpp @@ -12,14 +12,13 @@ namespace static const int STATUS_TEXT_FONT_SIZE = 24; } -taskState::taskState(sys::taskFunction threadFunction, sys::sharedTaskData sharedData) : -m_Task(std::make_unique(threadFunction, sharedData)) { } +taskState::taskState(sys::taskFunction threadFunction, sys::sharedTaskData sharedData) : m_Task(std::make_unique(threadFunction, sharedData)) {} -taskState::~taskState() { } +taskState::~taskState() {} void taskState::update(void) { - if(m_Task->isRunning() == false) + if (m_Task->isRunning() == false) { appState::deactivateState(); } @@ -33,7 +32,7 @@ void taskState::render(void) // Render glyph in bottom left corner ui::renderLoadingGlyph(); - + // Dim background and render text to screen graphics::renderRect(NULL, 0, 0, 1280, 720, COLOR_DIM_BACKGROUND); graphics::systemFont::renderText(taskStatus, NULL, taskStatusX, STATUS_TEXT_Y, STATUS_TEXT_FONT_SIZE, COLOR_WHITE); diff --git a/src/appStates/titleOptionState.cpp b/src/appStates/titleOptionState.cpp index f6d9577..f803214 100755 --- a/src/appStates/titleOptionState.cpp +++ b/src/appStates/titleOptionState.cpp @@ -57,7 +57,7 @@ struct titleOptsData : sys::taskData // This was needed to debug something. Only one for now. void resetSaveData(sys::task *task, sys::sharedTaskData sharedData) { - if(sharedData == nullptr) + if (sharedData == nullptr) { task->finished(); return; @@ -68,11 +68,11 @@ void resetSaveData(sys::task *task, sys::sharedTaskData sharedData) // Set status task->setThreadStatus(ui::strings::getString(THREAD_STATUS_RESETTING_SAVE, 0)); - + // Cast args std::shared_ptr dataIn = std::static_pointer_cast(sharedData); - if(fs::mountSaveData(dataIn->currentUserSaveInfo->getSaveDataInfo())) + if (fs::mountSaveData(dataIn->currentUserSaveInfo->getSaveDataInfo())) { // Erase save data in container // To do: remove_all keeps failing if the folder has sub dirs. Maybe I should just stick with my own? @@ -94,21 +94,20 @@ void resetSaveData(sys::task *task, sys::sharedTaskData sharedData) task->finished(); } -titleOptionState::titleOptionState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : -m_CurrentUser(currentUser), -m_CurrentUserSaveInfo(currentUserSaveInfo), -m_CurrentTitleInfo(currentTitleInfo), -m_SlidePanel(std::make_unique(PANEL_RENDER_TARGET_NAME, PANEL_WIDTH, ui::PANEL_SIDE_RIGHT)), -m_OptionsMenu(std::make_unique(MENU_X, MENU_Y, MENU_WIDTH, MENU_FONT_SIZE, MENU_SCROLL_LENGTH)) +titleOptionState::titleOptionState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : m_CurrentUser(currentUser), + m_CurrentUserSaveInfo(currentUserSaveInfo), + m_CurrentTitleInfo(currentTitleInfo), + m_SlidePanel(std::make_unique(PANEL_RENDER_TARGET_NAME, PANEL_WIDTH, ui::PANEL_SIDE_RIGHT)), + m_OptionsMenu(std::make_unique(MENU_X, MENU_Y, MENU_WIDTH, MENU_FONT_SIZE, MENU_SCROLL_LENGTH)) { // Setup menu - for(int i = 0; i < 9; i++) + for (int i = 0; i < 9; i++) { m_OptionsMenu->addOption(ui::strings::getString(TITLE_OPTIONS_MENU_STRINGS, i)); } } -titleOptionState::~titleOptionState() { } +titleOptionState::~titleOptionState() {} void titleOptionState::update(void) { @@ -116,9 +115,9 @@ void titleOptionState::update(void) m_SlidePanel->update(); m_OptionsMenu->update(); - if(sys::input::buttonDown(HidNpadButton_A)) + if (sys::input::buttonDown(HidNpadButton_A)) { - switch(m_OptionsMenu->getSelected()) + switch (m_OptionsMenu->getSelected()) { // This is needed to debug something... and itself. case RESET_SAVE_DATA: @@ -142,11 +141,11 @@ void titleOptionState::update(void) break; } } - else if(sys::input::buttonDown(HidNpadButton_B)) + else if (sys::input::buttonDown(HidNpadButton_B)) { m_SlidePanel->closePanel(); } - else if(m_SlidePanel->isClosed()) + else if (m_SlidePanel->isClosed()) { appState::deactivateState(); } diff --git a/src/appStates/titleSelectionState.cpp b/src/appStates/titleSelectionState.cpp index d4607df..700cbe2 100755 --- a/src/appStates/titleSelectionState.cpp +++ b/src/appStates/titleSelectionState.cpp @@ -18,11 +18,10 @@ namespace const std::string TITLE_SELECTION_CONTROL_GUIDE = "helpTitle"; } -titleSelectionState::titleSelectionState(data::user *currentUser) : -m_CurrentUser(currentUser), -m_TitleSelection(std::make_unique(m_CurrentUser)), -m_TitleControlGuide(ui::strings::getString(TITLE_SELECTION_CONTROL_GUIDE, 0)), -m_TitleControlGuideX(1220 - graphics::systemFont::getTextWidth(m_TitleControlGuide, 18)) +titleSelectionState::titleSelectionState(data::user *currentUser) : m_CurrentUser(currentUser), + m_TitleSelection(std::make_unique(m_CurrentUser)), + m_TitleControlGuide(ui::strings::getString(TITLE_SELECTION_CONTROL_GUIDE, 0)), + m_TitleControlGuideX(1220 - graphics::systemFont::getTextWidth(m_TitleControlGuide, 18)) { // Render target to render everything too m_RenderTarget = graphics::textureManager::createTexture(TITLE_SELECT_RENDER_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); @@ -34,13 +33,13 @@ void titleSelectionState::update(void) { m_TitleSelection->update(); - if(sys::input::buttonDown(HidNpadButton_A)) + if (sys::input::buttonDown(HidNpadButton_A)) { int selected = m_TitleSelection->getSelected(); data::userSaveInfo *currentUserSaveInfo = m_CurrentUser->getUserSaveInfoAt(selected); - if(fs::mountSaveData(currentUserSaveInfo->getSaveDataInfo())) + if (fs::mountSaveData(currentUserSaveInfo->getSaveDataInfo())) { - data::titleInfo *currentTitleInfo = data::getTitleInfoByTitleID(currentUserSaveInfo->getTitleID()); + data::titleInfo *currentTitleInfo = data::getTitleInfoByTitleID(currentUserSaveInfo->getTitleID()); std::unique_ptr backupState = std::make_unique(m_CurrentUser, currentUserSaveInfo, currentTitleInfo); jksv::pushNewState(backupState); } @@ -49,7 +48,7 @@ void titleSelectionState::update(void) logger::log("Error mounting save for %016lX", currentUserSaveInfo->getTitleID()); } } - else if(sys::input::buttonDown(HidNpadButton_X)) + else if (sys::input::buttonDown(HidNpadButton_X)) { // Get some stuff needed int selected = m_TitleSelection->getSelected(); @@ -61,7 +60,7 @@ void titleSelectionState::update(void) // Push it jksv::pushNewState(optionState); } - else if(sys::input::buttonDown(HidNpadButton_B)) + else if (sys::input::buttonDown(HidNpadButton_B)) { appState::deactivateState(); } @@ -77,7 +76,7 @@ void titleSelectionState::render(void) // Render to screen graphics::textureRender(m_RenderTarget.get(), NULL, 201, 91); - if(appState::hasFocus()) + if (appState::hasFocus()) { graphics::systemFont::renderText(m_TitleControlGuide, NULL, m_TitleControlGuideX, 673, 18, COLOR_WHITE); } diff --git a/src/appStates/userOptionState.cpp b/src/appStates/userOptionState.cpp index bab939e..fce8178 100644 --- a/src/appStates/userOptionState.cpp +++ b/src/appStates/userOptionState.cpp @@ -1,6 +1,7 @@ #include "appStates/userOptionState.hpp" #include "appStates/progressState.hpp" #include "appStates/saveCreateState.hpp" +#include "appStates/confirmState.hpp" #include "system/progressTask.hpp" #include "filesystem/filesystem.hpp" #include "jksv.hpp" @@ -17,6 +18,7 @@ namespace const std::string OPTION_MENU_STRING_NAME = "userOptions"; const std::string THREAD_STATUS_CREATING_SAVE_DATA = "threadStatusCreatingSaveData"; const std::string THREAD_STATUS_DELETING_SAVE_DATA = "threadStatusDeletingSaveData"; + const std::string CONFIRM_DELETE_ALL_USER_SAVES = "saveDataDeleteAllUser"; // Enum for menu opts enum { @@ -81,7 +83,7 @@ void dumpAllForUser(sys::task *task, sys::sharedTaskData sharedData) void createAllSaveDataForUser(sys::task *task, sys::sharedTaskData sharedData) { - if(sharedData == nullptr) + if (sharedData == nullptr) { task->finished(); return; @@ -94,9 +96,9 @@ void createAllSaveDataForUser(sys::task *task, sys::sharedTaskData sharedData) data::titleMap &titleMap = data::getTitleMap(); // Loop through map. Have to be careful though. - for(auto ¤tTitle : titleMap) + for (auto ¤tTitle : titleMap) { - if(dataIn->currentUser->getUserType() == data::userType::TYPE_USER && currentTitle.second.hasAccountSaveData()) + if (dataIn->currentUser->getUserType() == data::userType::TYPE_USER && currentTitle.second.hasAccountSaveData()) { // Set status string. std::string threadStatus = stringUtil::getFormattedString(ui::strings::getCString(THREAD_STATUS_CREATING_SAVE_DATA, 0), currentTitle.second.getTitle().c_str()); @@ -114,7 +116,7 @@ void createAllSaveDataForUser(sys::task *task, sys::sharedTaskData sharedData) void deleteAllSaveDataForUser(sys::task *task, sys::sharedTaskData sharedData) { - if(sharedData == nullptr) + if (sharedData == nullptr) { task->finished(); return; @@ -124,7 +126,7 @@ void deleteAllSaveDataForUser(sys::task *task, sys::sharedTaskData sharedData) // Loop through and nuke them int totalUserSaves = dataIn->currentUser->getTotalUserSaveInfo(); - for(int i = 0; i < totalUserSaves; i++) + for (int i = 0; i < totalUserSaves; i++) { // Save info is needed first for titleID data::userSaveInfo *currentUserSaveInfo = dataIn->currentUser->getUserSaveInfoAt(i); @@ -171,60 +173,75 @@ void userOptionState::update(void) { switch (m_OptionsMenu->getSelected()) { - case OPTION_BACKUP_ALL_FOR_USER: - { - // Data to send - std::shared_ptr optionsData = std::make_shared(); - optionsData->currentUser = m_CurrentUser; - // Push new state/task - createAndPushNewProgressState(dumpAllForUser, optionsData); - } - break; + case OPTION_BACKUP_ALL_FOR_USER: + { + // Data to send + std::shared_ptr optionsData = std::make_shared(); + optionsData->currentUser = m_CurrentUser; + // Push new state/task + createAndPushNewProgressState(dumpAllForUser, optionsData); + } + break; - case OPTION_CREATE_SAVE_DATA: + case OPTION_CREATE_SAVE_DATA: + { + // What save type we're working with. Using UserID to figure it out. + FsSaveDataType saveDataType; + switch (m_CurrentUser->getAccountIDU128()) { - // What save type we're working with. Using UserID to figure it out. - FsSaveDataType saveDataType; - if (m_CurrentUser->getAccountIDU128() == 2) + case 2: { saveDataType = FsSaveDataType_Bcat; } - else if (m_CurrentUser->getAccountIDU128() == 3) + break; + + case 3: { saveDataType = FsSaveDataType_Device; } - else if (m_CurrentUser->getAccountIDU128() == 5) + break; + + case 5: { saveDataType = FsSaveDataType_Cache; } - else + break; + + default: { saveDataType = FsSaveDataType_Account; } - - // Push the state - std::unique_ptr saveCreationState = std::make_unique(m_CurrentUser, saveDataType); - jksv::pushNewState(saveCreationState); + break; } - break; - case OPTION_CREATE_ALL_SAVE_DATA: // This needs to be fixed up... - { - std::shared_ptr userData = std::make_shared(); - userData->currentUser = m_CurrentUser; + // Push the state + std::unique_ptr saveCreationState = std::make_unique(m_CurrentUser, saveDataType); + jksv::pushNewState(saveCreationState); + } + break; - createAndPushNewTask(createAllSaveDataForUser, userData); - } - break; + case OPTION_CREATE_ALL_SAVE_DATA: // This needs to be fixed up... + { + std::shared_ptr userData = std::make_shared(); + userData->currentUser = m_CurrentUser; - case OPTION_DELETE_ALL_SAVES_FOR_USER: - { - std::shared_ptr userData = std::make_shared(); - userData->currentUser = m_CurrentUser; + createAndPushNewTask(createAllSaveDataForUser, userData); + } + break; - createAndPushNewTask(deleteAllSaveDataForUser, userData); - } - break; + case OPTION_DELETE_ALL_SAVES_FOR_USER: + { + // Create confirmation string + std::string confirmDeleteAll = stringUtil::getFormattedString(ui::strings::getCString(CONFIRM_DELETE_ALL_USER_SAVES, 0), m_CurrentUser->getUsername().c_str()); + + // Shared data + std::shared_ptr userData = std::make_shared(); + userData->currentUser = m_CurrentUser; + + // Confirm it first. + confirmAction(confirmDeleteAll, deleteAllSaveDataForUser, userData, sys::taskTypes::TASK_TYPE_TASK); + } + break; } } else if (sys::input::buttonDown(HidNpadButton_B)) diff --git a/src/data/data.cpp b/src/data/data.cpp index 5667fab..aacadf6 100755 --- a/src/data/data.cpp +++ b/src/data/data.cpp @@ -42,14 +42,15 @@ static u128 accountUIDToU128(AccountUid accountID) // Same as above, but reversed static AccountUid u128ToAccountUID(u128 accountID) { - return (AccountUid){ (uint64_t)(accountID >> 64), (uint64_t)accountID }; + return (AccountUid){(uint64_t)(accountID >> 64), (uint64_t)accountID}; } // Checks if user exists in vector static bool userExistsInVector(u128 accountID) { // This is kind of hard to follow, but search the vector and see if accountID exists - auto findUser = std::find_if(s_UserVector.begin(), s_UserVector.end(), [accountID] ( const userIDPair &userPair ) { return userPair.first == accountID; } ); + auto findUser = std::find_if(s_UserVector.begin(), s_UserVector.end(), [accountID](const userIDPair &userPair) + { return userPair.first == accountID; }); return findUser != s_UserVector.end(); } @@ -74,7 +75,7 @@ static bool isAccountSystemSave(const FsSaveDataInfo &saveDataInfo) { uint8_t saveDataType = saveDataInfo.save_data_type; u128 accountID = accountUIDToU128(saveDataInfo.uid); - if(saveDataType == FsSaveDataType_System && accountID != 0) + if (saveDataType == FsSaveDataType_System && accountID != 0) { return true; } @@ -114,7 +115,7 @@ bool data::init(void) NsApplicationRecord currentRecord; int entryCount = 0; int entryOffset = 0; - while(R_SUCCEEDED(nsListApplicationRecord(¤tRecord, 1, entryOffset++, &entryCount)) && entryCount > 0) + while (R_SUCCEEDED(nsListApplicationRecord(¤tRecord, 1, entryOffset++, &entryCount)) && entryCount > 0) { // This is logged for when JKSV gets stuck on things logger::log("Add title 0x%016lX.", currentRecord.application_id); @@ -127,7 +128,7 @@ bool data::init(void) void data::loadUserSaveInfo(void) { // Clear userSaveInfo before JIC - for(auto &u : s_UserVector) + for (auto &u : s_UserVector) { u.second.clearUserSaveInfo(); } @@ -138,18 +139,18 @@ void data::loadUserSaveInfo(void) int64_t entries = 0; Result openSaveInfoReader = fsOpenSaveDataInfoReader(&saveDataInfoReader, FsSaveDataSpaceId_All); - if(R_FAILED(openSaveInfoReader)) + if (R_FAILED(openSaveInfoReader)) { logger::log("fsOpenSaveDataInfoReader failed: 0x%X", openSaveInfoReader); return; } // Loop and load all saves and push them to users - while(R_SUCCEEDED(fsSaveDataInfoReaderRead(&saveDataInfoReader, &saveDataInfo, 1, &entries)) && entries > 0) + while (R_SUCCEEDED(fsSaveDataInfoReaderRead(&saveDataInfoReader, &saveDataInfo, 1, &entries)) && entries > 0) { // Title id depends on save type uint64_t titleID = 0; - if(saveDataInfo.save_data_type == FsSaveDataType_System || saveDataInfo.save_data_type == FsSaveDataType_SystemBcat) + if (saveDataInfo.save_data_type == FsSaveDataType_System || saveDataInfo.save_data_type == FsSaveDataType_SystemBcat) { titleID = saveDataInfo.system_save_data_id; } @@ -159,14 +160,14 @@ void data::loadUserSaveInfo(void) } // Just in case it doesn't have and entry - if(titleIsLoadedInMap(titleID) == false) + if (titleIsLoadedInMap(titleID) == false) { logger::log("Save found for for title not in records: 0x%016lX", titleID); s_TitleMap.emplace(std::make_pair(titleID, data::titleInfo(titleID))); } // Just skip this stuff. Comes after above JIC we need to load something. - if(isAccountSystemSave(saveDataInfo) && config::getByKey(CONFIG_LIST_ACCOUNT_SYSTEM_SAVES) == false) + if (isAccountSystemSave(saveDataInfo) && config::getByKey(CONFIG_LIST_ACCOUNT_SYSTEM_SAVES) == false) { continue; } @@ -189,7 +190,7 @@ void data::loadUserSaveInfo(void) case FsSaveDataType_Temporary: { // This is special for compatibility just in case. - if(userExistsInVector(TEMPORARY_SAVE_USER_ID) == false) + if (userExistsInVector(TEMPORARY_SAVE_USER_ID) == false) { createAddSystemUser(TEMPORARY_SAVE_USER_ID); } @@ -206,7 +207,7 @@ void data::loadUserSaveInfo(void) // I've never seen this used before... case FsSaveDataType_SystemBcat: { - if(userExistsInVector(SYSTEM_BCAT_USER_ID) == false) + if (userExistsInVector(SYSTEM_BCAT_USER_ID) == false) { createAddSystemUser(SYSTEM_BCAT_USER_ID); } @@ -217,7 +218,7 @@ void data::loadUserSaveInfo(void) // Play stats PdmPlayStatistics playStatistics; - if(saveDataInfo.save_data_type == FsSaveDataType_Account || saveDataInfo.save_data_type == FsSaveDataType_Device) + if (saveDataInfo.save_data_type == FsSaveDataType_Account || saveDataInfo.save_data_type == FsSaveDataType_Device) { pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(titleID, saveDataInfo.uid, false, &playStatistics); } @@ -228,7 +229,7 @@ void data::loadUserSaveInfo(void) // Finally push it to user data::user *targetUser = data::getUserByAccountID(accountUIDToU128(saveDataInfo.uid)); - if(targetUser != NULL) + if (targetUser != NULL) { targetUser->addNewUserSaveInfo(titleID, saveDataInfo, playStatistics); } @@ -240,7 +241,7 @@ void data::loadUserSaveInfo(void) void data::sortUserSaveInfo(void) { - for(userIDPair &userPair : s_UserVector) + for (userIDPair &userPair : s_UserVector) { userPair.second.sortUserSaveInfo(); } @@ -253,8 +254,9 @@ int data::getTotalUsers(void) data::user *data::getUserByAccountID(u128 accountID) { - auto userPosition = std::find_if(s_UserVector.begin(), s_UserVector.end(), [accountID](const userIDPair &u){ return u.first == accountID; }); - if(userPosition != s_UserVector.end()) + auto userPosition = std::find_if(s_UserVector.begin(), s_UserVector.end(), [accountID](const userIDPair &u) + { return u.first == accountID; }); + if (userPosition != s_UserVector.end()) { return &userPosition->second; } @@ -263,7 +265,7 @@ data::user *data::getUserByAccountID(u128 accountID) data::user *data::getUserAtPosition(int position) { - if(position >= 0 && position < static_cast(s_UserVector.size())) + if (position >= 0 && position < static_cast(s_UserVector.size())) { return &s_UserVector.at(position).second; } @@ -282,7 +284,7 @@ int data::getTotalTitleCount(void) data::titleInfo *data::getTitleInfoByTitleID(uint64_t titleID) { - if(s_TitleMap.find(titleID) != s_TitleMap.end()) + if (s_TitleMap.find(titleID) != s_TitleMap.end()) { return &s_TitleMap.at(titleID); } diff --git a/src/data/titleInfo.cpp b/src/data/titleInfo.cpp index a453746..b08ef2d 100755 --- a/src/data/titleInfo.cpp +++ b/src/data/titleInfo.cpp @@ -9,8 +9,7 @@ #include "stringUtil.hpp" #include "log.hpp" -data::titleInfo::titleInfo(uint64_t titleID) : -m_TitleID(titleID) +data::titleInfo::titleInfo(uint64_t titleID) : m_TitleID(titleID) { // This is the size of the control data. Used for getting icon size uint64_t nsAppControlSize = 0; @@ -22,7 +21,7 @@ m_TitleID(titleID) std::string titleIDHexString = stringUtil::getFormattedString("%016lX", m_TitleID); Result nsAppControlRes = nsGetApplicationControlData(NsApplicationControlSource_Storage, m_TitleID, nsAppConrolData.get(), sizeof(NsApplicationControlData), &nsAppControlSize); - if(R_SUCCEEDED(nsAppControlRes) && !(nsAppControlSize < sizeof(nsAppConrolData->nacp))) + if (R_SUCCEEDED(nsAppControlRes) && !(nsAppControlSize < sizeof(nsAppConrolData->nacp))) { appIconSize = nsAppControlSize - sizeof(nsAppConrolData->nacp); @@ -49,7 +48,7 @@ std::string data::titleInfo::getTitle(void) NacpLanguageEntry *entry; nacpGetLanguageEntry(&m_Nacp, &entry); // If it fails, return title ID as hex string - if(entry == NULL) + if (entry == NULL) { return stringUtil::getFormattedString("%016lX", m_TitleID); } @@ -62,7 +61,7 @@ std::string data::titleInfo::getPathSafeTitle(void) // Try to get a pathSafeTitle std::string pathSafeTitle = stringUtil::getPathSafeString(data::titleInfo::getTitle()); // If that fails, it will be empty. Just return ID hex string - if(pathSafeTitle.empty()) + if (pathSafeTitle.empty()) { return stringUtil::getFormattedString("%016lX", m_TitleID); } @@ -77,7 +76,7 @@ graphics::sdlTexture data::titleInfo::getIcon(void) int64_t data::titleInfo::getSaveDataSize(FsSaveDataType saveType) { int64_t saveDataSize = 0; - switch(saveType) + switch (saveType) { case FsSaveDataType_Account: { @@ -110,7 +109,7 @@ int64_t data::titleInfo::getSaveDataSizeMax(FsSaveDataType saveType) int64_t saveSize = 0; int64_t saveSizeMax = 0; - switch(saveType) + switch (saveType) { case FsSaveDataType_Account: { @@ -148,7 +147,7 @@ int64_t data::titleInfo::getJournalSize(FsSaveDataType saveType) int64_t journalSize = 0; // Different save types have different journal limits - switch(saveType) + switch (saveType) { case FsSaveDataType_Account: { diff --git a/src/data/user.cpp b/src/data/user.cpp index 76677e7..cdcecd9 100755 --- a/src/data/user.cpp +++ b/src/data/user.cpp @@ -30,39 +30,39 @@ bool compareTitles(const data::userSaveInfo &a, const data::userSaveInfo &b) data::titleInfo *titleInfoB = data::getTitleInfoByTitleID(b.getTitleID()); switch (config::getByKey(CONFIG_TITLE_SORT_TYPE)) { - case config::SORT_TYPE_ALPHA: - { - uint32_t codepointA, codepointB; - std::string titleA = titleInfoA->getTitle(); - std::string titleB = titleInfoB->getTitle(); - int titleLength = titleA.length(); - for (int i = 0, j = 0; i < titleLength;) + case config::SORT_TYPE_ALPHA: { - ssize_t aCount = decode_utf8(&codepointA, reinterpret_cast(&titleA.c_str()[i])); - ssize_t bCount = decode_utf8(&codepointB, reinterpret_cast(&titleB.c_str()[j])); - codepointA = std::tolower(codepointA); - codepointB = std::tolower(codepointB); - if (codepointA != codepointB) + uint32_t codepointA, codepointB; + std::string titleA = titleInfoA->getTitle(); + std::string titleB = titleInfoB->getTitle(); + int titleLength = titleA.length(); + for (int i = 0, j = 0; i < titleLength;) { - return codepointA < codepointB; + ssize_t aCount = decode_utf8(&codepointA, reinterpret_cast(&titleA.c_str()[i])); + ssize_t bCount = decode_utf8(&codepointB, reinterpret_cast(&titleB.c_str()[j])); + codepointA = std::tolower(codepointA); + codepointB = std::tolower(codepointB); + if (codepointA != codepointB) + { + return codepointA < codepointB; + } + i += aCount; + j += bCount; } - i += aCount; - j += bCount; } - } - break; + break; - case config::SORT_TYPE_MOST_PLAYED: - { - return a.getPlayStatistics().playtime > b.getPlayStatistics().playtime; - } - break; + case config::SORT_TYPE_MOST_PLAYED: + { + return a.getPlayStatistics().playtime > b.getPlayStatistics().playtime; + } + break; - case config::SORT_TYPE_LAST_PLAYED: - { - return a.getPlayStatistics().last_timestamp_user > b.getPlayStatistics().last_timestamp_user; - } - break; + case config::SORT_TYPE_LAST_PLAYED: + { + return a.getPlayStatistics().last_timestamp_user > b.getPlayStatistics().last_timestamp_user; + } + break; } return false; } @@ -115,10 +115,10 @@ data::user::user(AccountUid accountID, data::userType userType) : m_AccountID(ac } data::user::user(AccountUid accountID, const std::string &username, const std::string &pathSafeUsername, data::userType userType) : m_AccountID(accountID), - m_Username(username), - m_PathSafeUsername(pathSafeUsername), - m_Icon(graphics::createIcon(m_Username, m_Username, 42)), - m_UserType(userType) {} + m_Username(username), + m_PathSafeUsername(pathSafeUsername), + m_Icon(graphics::createIcon(m_Username, m_Username, 42)), + m_UserType(userType) {} void data::user::addNewUserSaveInfo(uint64_t titleID, const FsSaveDataInfo &saveInfo, const PdmPlayStatistics &playStats) { @@ -160,7 +160,7 @@ graphics::sdlTexture data::user::getUserIcon(void) const return m_Icon; } -data::userType data::user::getUserType(void) const +data::userType data::user::getUserType(void) const { return m_UserType; } diff --git a/src/data/userSaveInfo.cpp b/src/data/userSaveInfo.cpp index 54312bb..d4813ea 100755 --- a/src/data/userSaveInfo.cpp +++ b/src/data/userSaveInfo.cpp @@ -1,9 +1,8 @@ #include "data/userSaveInfo.hpp" -data::userSaveInfo::userSaveInfo(uint64_t titleID, const FsSaveDataInfo &saveInfo, const PdmPlayStatistics &playStats) : -m_TitleID(titleID), -m_SaveDataInfo(saveInfo), -m_PlayStats(playStats) { } +data::userSaveInfo::userSaveInfo(uint64_t titleID, const FsSaveDataInfo &saveInfo, const PdmPlayStatistics &playStats) : m_TitleID(titleID), + m_SaveDataInfo(saveInfo), + m_PlayStats(playStats) {} uint64_t data::userSaveInfo::getTitleID(void) const { diff --git a/src/filesystem/directoryListing.cpp b/src/filesystem/directoryListing.cpp index 073de77..c2feae4 100755 --- a/src/filesystem/directoryListing.cpp +++ b/src/filesystem/directoryListing.cpp @@ -5,8 +5,7 @@ #include "stringUtil.hpp" #include "log.hpp" -fs::directoryListing::directoryListing(const std::string &directoryPath) : -m_DirectoryPath(directoryPath) +fs::directoryListing::directoryListing(const std::string &directoryPath) : m_DirectoryPath(directoryPath) { loadListing(); } @@ -19,7 +18,7 @@ void fs::directoryListing::loadListing(void) // Error code std::error_code errorCode; - for(const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(m_DirectoryPath, errorCode)) + for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(m_DirectoryPath, errorCode)) { m_DirectoryList.push_back(entry); } diff --git a/src/filesystem/filesystem.cpp b/src/filesystem/filesystem.cpp index fc6e0ff..c98bb48 100755 --- a/src/filesystem/filesystem.cpp +++ b/src/filesystem/filesystem.cpp @@ -142,8 +142,8 @@ bool fs::createSaveDataFileSystem(FsSaveDataType saveType, uint64_t titleID, Acc FsSaveDataMetaInfo saveMetaInfo = { - .size = saveType == FsSaveDataType_Bcat ? 0 : 0x40060, - .type = saveType == FsSaveDataType_Bcat ? 0 : FsSaveDataMetaType_Thumbnail + .size = saveType == FsSaveDataType_Bcat ? static_cast(0) : static_cast(0x40060), + .type = saveType == FsSaveDataType_Bcat ? static_cast(0) : static_cast(FsSaveDataMetaType_Thumbnail) }; Result createSaveResult = fsCreateSaveDataFileSystem(&saveDataAttributes, &saveCreationInfo, &saveMetaInfo); diff --git a/src/graphics/systemFont.cpp b/src/graphics/systemFont.cpp index 71b2934..29d465c 100755 --- a/src/graphics/systemFont.cpp +++ b/src/graphics/systemFont.cpp @@ -31,15 +31,12 @@ namespace FT_Face s_FTFaces[6]; //Number of fonts loaded int s_TotalFonts; + // Color used for rendering. Added to prevent duplicating code. + uint32_t s_RenderingColor; // This is the glyph texture cache map std::map, glyphData> s_GlyphMap; // How large the word buffer is for line wrapping. const int WORD_WRAP_BUFFER_LENGTH = 0x1000; - // Masks for converting glyphs to sdl surface - const uint32_t s_RedMask = 0xFF000000; - const uint32_t s_GreenMask = 0x00FF0000; - const uint32_t s_BlueMask = 0x0000FF00; - const uint32_t s_AlphaMask = 0x000000FF; // Codepoints to break lines at const std::array s_BreakPoints = {L' ', L' ', L'/', L'_', L'-', L'。', L'、'}; } @@ -99,7 +96,7 @@ static glyphData *getGlyph(uint32_t codepoint, int fontSize) } // Create Temporary SDL_Surface to convert to texture - SDL_Surface *tempGlyphSurface = SDL_CreateRGBSurfaceFrom(glyphPixelData.data(), bitmap.width, bitmap.rows, 32, sizeof(uint32_t) * bitmap.width, s_RedMask, s_GreenMask, s_BlueMask, s_AlphaMask); + SDL_Surface *tempGlyphSurface = SDL_CreateRGBSurfaceFrom(glyphPixelData.data(), bitmap.width, bitmap.rows, 32, sizeof(uint32_t) * bitmap.width, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); // Texture manager needs name for texture. std::string glyphName = std::to_string(codepoint) + "_" + std::to_string(fontSize); @@ -153,32 +150,33 @@ static size_t findNextBreakPoint(const char *str) } //Processes characters set to change text colors. Returns true if character is special -static bool processSpecialCharacters(uint32_t codepoint, uint32_t originalColor, uint32_t &color) +static bool processSpecialCharacters(uint32_t codepoint, uint32_t originalColor) { + // This is set to true and on default, set to false. bool isSpecial = true; switch (codepoint) { case L'#': { - color = color == COLOR_BLUE ? originalColor : COLOR_BLUE; + s_RenderingColor = s_RenderingColor == originalColor ? COLOR_BLUE : originalColor; } break; case L'*': { - color = color == COLOR_RED ? originalColor : COLOR_RED; + s_RenderingColor = s_RenderingColor == originalColor ? COLOR_RED : originalColor; } break; case L'<': { - color = color == COLOR_YELLOW ? originalColor : COLOR_YELLOW; + s_RenderingColor = s_RenderingColor == originalColor ? COLOR_YELLOW : originalColor; } break; case L'>': { - color = color == COLOR_GREEN ? originalColor : COLOR_GREEN; + s_RenderingColor = s_RenderingColor == originalColor ? COLOR_GREEN : originalColor; } break; @@ -188,6 +186,7 @@ static bool processSpecialCharacters(uint32_t codepoint, uint32_t originalColor, } break; } + return isSpecial; } @@ -249,7 +248,7 @@ void graphics::systemFont::renderText(const std::string &text, SDL_Texture *targ int workingY = y; //Color we're working with - uint32_t workingColor = color; + s_RenderingColor = color; //Current character/codepoint uint32_t codepoint = 0; @@ -272,7 +271,7 @@ void graphics::systemFont::renderText(const std::string &text, SDL_Texture *targ } i += unitCount; - if(processSpecialCharacters(codepoint, color, workingColor)) + if(processSpecialCharacters(codepoint, color)) { continue; } @@ -288,7 +287,7 @@ void graphics::systemFont::renderText(const std::string &text, SDL_Texture *targ if(glyph) { // Set color just to be sure - SDL_SetTextureColorMod(glyph->glyph.get(), getRed(workingColor), getGreen(workingColor), getBlue(workingColor)); + SDL_SetTextureColorMod(glyph->glyph.get(), getRed(s_RenderingColor), getGreen(s_RenderingColor), getBlue(s_RenderingColor)); // Render glyph texture graphics::textureRender(glyph->glyph.get(), target, workingX + glyph->left, workingY + (fontSize - glyph->top)); // X update @@ -303,6 +302,7 @@ void graphics::systemFont::renderTextWrap(const std::string &text, SDL_Texture * int workingX = x; int workingY = y; int stringLength = text.length(); + // This buffer is used to calculate if the next word should create a line break std::array wordBuffer = { 0 }; @@ -338,7 +338,6 @@ int graphics::systemFont::getTextWidth(const std::string &text, int fontSize) { int textWidth = 0; uint32_t codepoint = 0; - uint32_t colorMod = 0; // This is just needed so we can properly count and skip special chars ssize_t unitCount = 0; resizeFont(fontSize); @@ -352,7 +351,7 @@ int graphics::systemFont::getTextWidth(const std::string &text, int fontSize) } i += unitCount; - if(processSpecialCharacters(codepoint, COLOR_WHITE, colorMod)) + if(processSpecialCharacters(codepoint, COLOR_WHITE)) { continue; } diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp index 1b73fd0..2ee6084 100755 --- a/src/ui/menu.cpp +++ b/src/ui/menu.cpp @@ -11,22 +11,27 @@ namespace { + int menuID = 0; // This is how much extra vertical space is needed for bounding/selection box const int BOUNDING_EXTRA_HEIGHT = 32; } -ui::menu::menu(int x, int y, int rectWidth, int fontSize, int maxScroll) : -m_X(x), -m_Y(y), -m_OriginalY(y), -m_FontSize(fontSize), -m_RectWidth(rectWidth), -m_RectHeight(m_FontSize + BOUNDING_EXTRA_HEIGHT), -m_Selected(0), -m_MaxScroll(maxScroll) { } +ui::menu::menu(int x, int y, int rectWidth, int fontSize, int maxScroll) : m_X(x), + m_Y(y), + m_OriginalY(y), + m_FontSize(fontSize), + m_RectWidth(rectWidth), + m_RectHeight(m_FontSize + BOUNDING_EXTRA_HEIGHT), + m_Selected(0), + m_MaxScroll(maxScroll) +{ + // String for rendertarget + std::string menuTargetName = "menuTarget_" + std::to_string(menuID++); + // This is for rendering the options to. So text can't be rendered outside bounding box. + m_OptionRenderTarget = graphics::textureManager::createTexture(menuTargetName, m_RectWidth, m_RectHeight, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); +} -ui::menu::menu(int x, int y, int rectWidth, int fontSize, int maxScroll, const std::string *menuOptions, int menuOptCount) : -menu(x, y, rectWidth, fontSize, maxScroll) +ui::menu::menu(int x, int y, int rectWidth, int fontSize, int maxScroll, const std::string *menuOptions, int menuOptCount) : menu(x, y, rectWidth, fontSize, maxScroll) { for (int i = 0; i < menuOptCount; i++) { @@ -53,6 +58,14 @@ void ui::menu::update(void) { m_Selected = 0; } + else if (sys::input::buttonDown(HidNpadButton_AnyLeft) && (m_Selected -= m_MaxScroll) < 0) + { + m_Selected = 0; + } + else if (sys::input::buttonDown(HidNpadButton_AnyRight) && (m_Selected += m_MaxScroll) > menuSize) + { + m_Selected = menuSize; + } // Calculate if scrolling needs to happen if (m_Selected <= m_MaxScroll) @@ -73,7 +86,7 @@ void ui::menu::update(void) { double addToY = static_cast(static_cast(m_TargetY) - static_cast(m_Y)) / config::getAnimationScaling(); m_Y += std::ceil(addToY); - } + } } void ui::menu::render(SDL_Texture *target) @@ -89,11 +102,17 @@ void ui::menu::render(SDL_Texture *target) SDL_QueryTexture(target, NULL, NULL, NULL, &targetHeight); for (int i = 0; i < (int)m_MenuOptions.size(); i++) { + // Clear option target + graphics::textureClear(m_OptionRenderTarget.get(), COLOR_TRANSPARENT); + // Render option to it. + graphics::systemFont::renderText(m_MenuOptions.at(i), m_OptionRenderTarget.get(), 16, (m_RectHeight / 2) - (m_FontSize /2), m_FontSize, COLOR_WHITE); + // Render option target to target + graphics::textureRender(m_OptionRenderTarget.get(), target, m_X, m_Y + (i * m_RectHeight)); + // If it's the selected option, render the selection box over top. if (m_Selected == i) { - ui::renderSelectionBox(target, m_X - 4, (m_Y + (i * m_RectHeight)) - 4, m_RectWidth, m_RectHeight, m_ColorMod); + ui::renderSelectionBox(target, m_X, (m_Y + (i * m_RectHeight)), m_RectWidth, m_RectHeight, m_ColorMod); } - graphics::systemFont::renderText(m_MenuOptions.at(i), target, m_X + 8, m_Y + (i * m_RectHeight) + (m_RectHeight / 2 - m_FontSize / 2), m_FontSize, COLOR_WHITE); } } @@ -104,7 +123,7 @@ void ui::menu::addOption(const std::string &newOption) void ui::menu::updateColorPulse(void) { - if (m_ColorShift && (m_ColorMod += 6) >= 0x72) + if (m_ColorShift && (m_ColorMod += 6) >= 0x72) { m_ColorShift = false; }