diff --git a/Makefile b/Makefile index 8e44937..bc76fd8 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ INCLUDES := include ./Libraries/FsLib/Switch/FsLib/include ./Libraries/SDLLib/SD EXEFS_SRC := exefs_src APP_TITLE := JKSV APP_AUTHOR := JK -APP_VERSION := 09.26.2025 +APP_VERSION := 09.29.2025 ROMFS := romfs ICON := icon.jpg diff --git a/Text/compress_text.py b/Text/compress_text.py index 93789a6..a9a2a2b 100644 --- a/Text/compress_text.py +++ b/Text/compress_text.py @@ -7,34 +7,35 @@ import sys import shutil def main(): - # This is run from the makefile. All paths must be relative to it. - inputDir = "./Text/Files" - outputDir = "./romfs/Text" + # This is run from the makefile. All paths must be relative to it, not the script. + inputDir: str = "./Text/Files" + outputDir: str = "./romfs/Text" - if(os.path.exists(outputDir)): + if os.path.exists(outputDir): shutil.rmtree(outputDir) os.mkdir(outputDir) + for entry in os.listdir(inputDir): - inputPath = f"{inputDir}/{entry}"; - inputSize = os.path.getsize(inputPath) - inputFile = open(file=inputPath, mode="rb") + inputPath: str = f"{inputDir}/{entry}"; + inputSize: int = os.path.getsize(inputPath) + inputFile: object = open(file=inputPath, mode="rb") if inputFile.closed: print(f"Error opening {inputPath} for reading!") continue - inputBuffer = inputFile.read(inputSize) - outputBuffer = zlib.compress(inputBuffer, 9) + inputBuffer: bytes = inputFile.read(inputSize) + outputBuffer: bytes = zlib.compress(inputBuffer, 9) - outputPath = f"{outputDir}/{entry}.z" - outputFile = open(file=outputPath, mode="wb") + outputPath: str = f"{outputDir}/{entry}.z" + outputFile: object = open(file=outputPath, mode="wb") if outputFile.closed: print("Error opening {outputPath} for writing!") continue - inputSizeBytes = inputSize.to_bytes(4, byteorder="little") - outputSizeBytes = len(outputBuffer).to_bytes(4, byteorder="little") + inputSizeBytes: bytes = inputSize.to_bytes(4, byteorder="little") + outputSizeBytes: bytes = len(outputBuffer).to_bytes(4, byteorder="little") outputFile.write(inputSizeBytes) outputFile.write(outputSizeBytes) outputFile.write(outputBuffer) diff --git a/include/appstates/ConfirmState.hpp b/include/appstates/ConfirmState.hpp index 9694f47..12ca17c 100644 --- a/include/appstates/ConfirmState.hpp +++ b/include/appstates/ConfirmState.hpp @@ -46,7 +46,7 @@ class ConfirmState final : public BaseState , m_yesText(strings::get_by_name(strings::names::YES_NO_OK, 0)) , m_noText(strings::get_by_name(strings::names::YES_NO_OK, 1)) , m_holdRequired(holdRequired) - , m_transition(280, 720, 280, 229, 4) + , m_transition(280, 229, 32, 32, 280, 229, 720, 256, 4) , m_function(function) , m_taskData(taskData) { @@ -92,6 +92,7 @@ class ConfirmState final : public BaseState void update() override { m_transition.update(); + sm_dialog->set_from_transition(m_transition, true); if (!m_transition.in_place()) { return; } const bool aPressed = input::button_pressed(HidNpadButton_A); @@ -109,7 +110,7 @@ class ConfirmState final : public BaseState else if (holdSustained) { ConfirmState::hold_sustained(); } else if (aReleased) { ConfirmState::hold_released(); } else if (bPressed) { ConfirmState::close_dialog(); } - else if (m_close && m_transition.in_place()) { ConfirmState::deactivate_cancelled(); } + else if (m_close && m_transition.in_place()) { ConfirmState::deactivate_state(); } } /// @brief Renders the state to screen. @@ -117,11 +118,11 @@ class ConfirmState final : public BaseState { const bool hasFocus = BaseState::has_focus(); const int y = m_transition.get_y(); - sm_dialog->set_y(y); sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::DIM_BACKGROUND); - sm_dialog->render(sdl::Texture::Null, hasFocus); + if (!m_transition.in_place() || m_close) { return; } + sdl::text::render(sdl::Texture::Null, 312, y + 24, 20, 656, colors::WHITE, m_query); sdl::render_line(sdl::Texture::Null, 280, y + 192, 999, y + 192, colors::DIV_COLOR); @@ -144,6 +145,9 @@ class ConfirmState final : public BaseState /// @brief This is to prevent the dialog from triggering immediately. bool m_triggerGuard{}; + /// @brief Whether or not the action was confirmed + bool m_confirmed{}; + /// @brief Whether or not holding [A] to confirm is required. const bool m_holdRequired{}; @@ -174,8 +178,8 @@ class ConfirmState final : public BaseState { if (sm_dialog) { return; } - // sm_dialog = ui::DialogBox::create(280, 262, 720, 256); - sm_dialog = ui::DialogBox::create(280, 720, 720, 256); + sm_dialog = ui::DialogBox::create(0, 0, 0, 0); + sm_dialog->set_from_transition(m_transition, true); } // This just centers the Yes or holding text. @@ -201,8 +205,8 @@ class ConfirmState final : public BaseState void confirmed() { - auto newState = StateType::create_and_push(m_function, m_taskData); - BaseState::deactivate(); + m_confirmed = true; + ConfirmState::close_dialog(); } void hold_triggered() @@ -229,9 +233,12 @@ class ConfirmState final : public BaseState ConfirmState::center_yes(); } - void deactivate_cancelled() + void deactivate_state() { - FadeState::create_and_push(colors::DIM_BACKGROUND, colors::ALPHA_FADE_END, colors::ALPHA_FADE_BEGIN, nullptr); + if (m_confirmed) { StateType::create_and_push(m_function, m_taskData); } + else { + FadeState::create_and_push(colors::DIM_BACKGROUND, colors::ALPHA_FADE_END, colors::ALPHA_FADE_BEGIN, nullptr); + } BaseState::deactivate(); } @@ -244,7 +251,8 @@ class ConfirmState final : public BaseState void close_dialog() { m_close = true; - m_transition.set_target_y(720); + m_transition.set_target_width(32); + m_transition.set_target_height(32); } }; diff --git a/include/appstates/MessageState.hpp b/include/appstates/MessageState.hpp index 6ba02ed..d9a91ba 100644 --- a/include/appstates/MessageState.hpp +++ b/include/appstates/MessageState.hpp @@ -70,6 +70,9 @@ class MessageState final : public BaseState /// @brief Allocates and ensures ^ void initialize_static_members(); + /// @brief Updates the dialog according to the transition. + void update_dialog(); + /// @brief Closes and "hides" the dialog. void close_dialog(); diff --git a/include/appstates/ProgressState.hpp b/include/appstates/ProgressState.hpp index efe5e17..e2300db 100644 --- a/include/appstates/ProgressState.hpp +++ b/include/appstates/ProgressState.hpp @@ -60,6 +60,12 @@ class ProgressState final : public BaseTask /// @brief Percentage as a string for printing to screen. std::string m_percentageString{}; + /// @brief Transition. + ui::Transition m_transition{}; + + /// @brief Controls the closing transition. + bool m_close{}; + /// @brief This is the dialog box everything is rendered to. static inline std::shared_ptr sm_dialog{}; @@ -69,6 +75,9 @@ class ProgressState final : public BaseTask /// @brief Initializes the shared dialog box. void initialize_static_members(); + /// @brief Closes the dialog. + void close_dialog(); + /// @brief Performs some cleanup and marks the state for purging. void deactivate_state(); }; diff --git a/include/builddate.hpp b/include/builddate.hpp index 28316c4..94b94c2 100644 --- a/include/builddate.hpp +++ b/include/builddate.hpp @@ -3,6 +3,6 @@ namespace builddate { inline constexpr int MONTH = 9; - inline constexpr int DAY = 26; + inline constexpr int DAY = 29; inline constexpr int YEAR = 2025; } diff --git a/include/remote/Storage.hpp b/include/remote/Storage.hpp index 0923058..719fd6e 100644 --- a/include/remote/Storage.hpp +++ b/include/remote/Storage.hpp @@ -64,6 +64,14 @@ namespace remote /// @param name Name of the file. bool file_exists(std::string_view name) const noexcept; + /// @brief Searches the list for a file matching name and the current parent. + /// @param name Name of the file to search for. + /// @return Pointer to the item if located. nullptr if not. + remote::Item *get_file_by_name(std::string_view name) noexcept; + + /// @brief Searches for and returns the item with id. Returns nullptr on failure. + remote::Item *get_item_by_id(std::string_view id) noexcept; + /// @brief Uploads a file from the SD card to the remote. /// @param source Path to the file to upload. virtual bool upload_file(const fslib::Path &source, std::string_view name, sys::ProgressTask *task = nullptr) = 0; @@ -80,11 +88,6 @@ namespace remote const fslib::Path &destination, sys::ProgressTask *task = nullptr) = 0; - /// @brief Searches the list for a file matching name and the current parent. - /// @param name Name of the file to search for. - /// @return Pointer to the item if located. nullptr if not. - remote::Item *get_file_by_name(std::string_view name) noexcept; - // General functions that apply to both. /// @brief Deletes a file or folder from the remote. /// @param item Item to delete. diff --git a/include/ui/DialogBox.hpp b/include/ui/DialogBox.hpp index e7cfc50..e0dfbb8 100644 --- a/include/ui/DialogBox.hpp +++ b/include/ui/DialogBox.hpp @@ -1,6 +1,7 @@ #pragma once #include "sdl.hpp" #include "ui/Element.hpp" +#include "ui/Transition.hpp" #include @@ -52,6 +53,11 @@ namespace ui /// @brief Sets the height. void set_height(int height) noexcept; + /// @brief Uses the transition passed to position the dialog. + /// @param transition Transition to use. + /// @param centered Whether or not the center the dialog. + void set_from_transition(ui::Transition &transition, bool centered = false); + private: /// @brief X render coord. int m_x{}; diff --git a/include/ui/Transition.hpp b/include/ui/Transition.hpp index f880d93..55f034a 100644 --- a/include/ui/Transition.hpp +++ b/include/ui/Transition.hpp @@ -14,7 +14,15 @@ namespace ui /// @param targetX Target X coord. /// @param targetY Target Y coord. /// @param threshold Gap, in pixels, before the x and/or y clamp into position. - Transition(int x, int y, int targetX, int targetY, int threshold) noexcept; + Transition(int x, + int y, + int width, + int height, + int targetX, + int targetY, + int targetWidth, + int targetHeight, + int threshold) noexcept; /// @brief Updates the transition. void update() noexcept; @@ -28,24 +36,54 @@ namespace ui /// @brief Returns the Y coordinate. int get_y() const noexcept; + /// @brief Returns the current width. + int get_width() const noexcept; + + /// @brief Returns the current height. + int get_height() const noexcept; + /// @brief Returns the target X. int get_target_x() const noexcept; /// @brief Returns the target Y. int get_target_y() const noexcept; + /// @brief Returns the target width. + int get_target_width() const noexcept; + + /// @brief Returns the target height. + int get_target_height() const noexcept; + + /// @brief Returns a screen centered coordinate according to the current x. + int get_centered_x() const noexcept; + + /// @brief Returns a screen centered coordinate according to the current y. + int get_centered_y() const noexcept; + /// @brief Sets the X coordinate. void set_x(int x) noexcept; /// @brief Sets the Y coordinate. void set_y(int y) noexcept; + /// @brief Sets the current width. + void set_width(int width) noexcept; + + /// @brief Sets the current height. + void set_height(int height) noexcept; + /// @brief Sets the target X coord. void set_target_x(int targetX) noexcept; /// @brief Sets the target Y coord. void set_target_y(int targetY) noexcept; + /// @brief Sets the target width of the transition. + void set_target_width(int targetWidth) noexcept; + + /// @brief Sets the target height of the transition. + void set_target_height(int targetHeight) noexcept; + private: /// @brief Current X. double m_x{}; @@ -53,12 +91,24 @@ namespace ui /// @brief Current Y. double m_y{}; + /// @brief Current width. + double m_width{}; + + /// @brief Current height. + double m_height{}; + /// @brief Target X. double m_targetX{}; /// @brief Target Y. double m_targetY{}; + /// @brief Target/end width. + double m_targetWidth{}; + + /// @brief Target/end height. + double m_targetHeight{}; + /// @brief Pixel gap threshold. double m_threshold{}; @@ -68,5 +118,9 @@ namespace ui void update_x_coord() noexcept; void update_y_coord() noexcept; + + void update_width() noexcept; + + void update_height() noexcept; }; -} \ No newline at end of file +} diff --git a/source/appstates/FileModeState.cpp b/source/appstates/FileModeState.cpp index bad1bdc..dc50819 100644 --- a/source/appstates/FileModeState.cpp +++ b/source/appstates/FileModeState.cpp @@ -15,7 +15,7 @@ FileModeState::FileModeState(std::string_view mountA, std::string_view mountB, i : m_mountA(mountA) , m_mountB(mountB) , m_journalSize(journalSize) - , m_transition(15, 720, 15, 85, 4) + , m_transition(15, 720, 0, 0, 15, 85, 0, 0, 4) , m_isSystem(isSystem) , m_allowSystem(config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM)) { @@ -29,9 +29,7 @@ void FileModeState::update() m_transition.update(); if (!m_transition.in_place()) { - const int x = m_transition.get_x(); const int y = m_transition.get_y(); - sm_frame->set_x(x); sm_frame->set_y(y); return; } @@ -125,7 +123,9 @@ void FileModeState::initialize_directory_menu(const fslib::Path &path, fslib::Di { std::string option{}; if (entry.is_directory()) { option = DIR_PREFIX; } - else { option = FILE_PREFIX; } + else { + option = FILE_PREFIX; + } option += entry.get_filename(); menu.add_option(option); @@ -211,4 +211,4 @@ void FileModeState::deactivate_state() noexcept fslib::close_file_system(m_mountA); fslib::close_file_system(m_mountB); BaseState::deactivate(); -} \ No newline at end of file +} diff --git a/source/appstates/FileOptionState.cpp b/source/appstates/FileOptionState.cpp index 842e56a..c57f4a4 100644 --- a/source/appstates/FileOptionState.cpp +++ b/source/appstates/FileOptionState.cpp @@ -38,7 +38,7 @@ static std::string get_size_string(int64_t totalSize); FileOptionState::FileOptionState(FileModeState *spawningState) : m_spawningState(spawningState) , m_target(spawningState->m_target) - , m_transition(m_target ? 1280 : -240, 218, m_target ? 840 : 200, 218, 4) + , m_transition(m_target ? 1280 : -240, 218, 0, 0, m_target ? 840 : 200, 218, 0, 0, 4) , m_dataStruct(std::make_shared()) { FileOptionState::initialize_static_members(); @@ -331,7 +331,9 @@ void FileOptionState::get_show_target_properties() const bool isDir = fslib::directory_exists(targetPath); if (isDir) { FileOptionState::get_show_directory_properties(targetPath); } - else { FileOptionState::get_show_file_properties(targetPath); } + else { + FileOptionState::get_show_file_properties(targetPath); + } } void FileOptionState::get_show_directory_properties(const fslib::Path &path) @@ -432,11 +434,10 @@ static std::string get_size_string(int64_t totalSize) const double kilobytes = static_cast(totalSize) / static_cast(THRESHOLD_BYTES); sizeString = stringutil::get_formatted_string("%.02f KB", kilobytes); } - else - { + else { const double megabytes = static_cast(totalSize) / static_cast(THRESHOLD_KB); sizeString = stringutil::get_formatted_string("%.02f MB", megabytes); } return sizeString; -} \ No newline at end of file +} diff --git a/source/appstates/MessageState.cpp b/source/appstates/MessageState.cpp index c60656e..7cab05e 100644 --- a/source/appstates/MessageState.cpp +++ b/source/appstates/MessageState.cpp @@ -8,7 +8,7 @@ MessageState::MessageState(std::string_view message) : m_message(message) - , m_transition(280, 720, 280, 229, 4) + , m_transition(0, 0, 32, 32, 0, 0, 720, 256, 4) { MessageState::initialize_static_members(); } @@ -16,6 +16,7 @@ MessageState::MessageState(std::string_view message) void MessageState::update() { m_transition.update(); + sm_dialog->set_from_transition(m_transition, true); if (!m_transition.in_place()) { return; } // To do: I only use this in one place right now. I'm not sure this guards correctly here? @@ -29,12 +30,13 @@ void MessageState::update() void MessageState::render() { - const bool hasFocus = BaseState::has_focus(); - const int y = m_transition.get_y(); - sm_dialog->set_y(y); + static constexpr int y = 229; + const bool hasFocus = BaseState::has_focus(); sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::DIM_BACKGROUND); sm_dialog->render(sdl::Texture::Null, hasFocus); + if (!m_transition.in_place()) { return; } + sdl::text::render(sdl::Texture::Null, 312, y + 24, 20, 656, colors::WHITE, m_message); sdl::render_line(sdl::Texture::Null, 280, y + 192, 999, y + 192, colors::DIV_COLOR); sdl::text::render(sdl::Texture::Null, sm_okX, y + 214, 22, sdl::text::NO_WRAP, colors::WHITE, sm_okText); @@ -47,13 +49,15 @@ void MessageState::initialize_static_members() sm_okText = strings::get_by_name(strings::names::YES_NO_OK, 2); sm_okX = HALF_WIDTH - (sdl::text::get_width(22, sm_okText) / 2); - sm_dialog = ui::DialogBox::create(280, 262, 720, 256); + sm_dialog = ui::DialogBox::create(0, 0, 0, 0); + sm_dialog->set_from_transition(m_transition, true); } void MessageState::close_dialog() { m_close = true; - m_transition.set_target_y(720); + m_transition.set_target_width(32); + m_transition.set_target_height(32); } void MessageState::deactivate_state() diff --git a/source/appstates/ProgressState.cpp b/source/appstates/ProgressState.cpp index 4c9b620..4a8e054 100644 --- a/source/appstates/ProgressState.cpp +++ b/source/appstates/ProgressState.cpp @@ -22,6 +22,7 @@ namespace } ProgressState::ProgressState(sys::threadpool::JobFunction function, sys::Task::TaskData taskData) + : m_transition(0, 0, 32, 32, 0, 0, 720, 256, 4) { initialize_static_members(); m_task = std::make_unique(function, taskData); @@ -29,13 +30,18 @@ ProgressState::ProgressState(sys::threadpool::JobFunction function, sys::Task::T void ProgressState::update() { + BaseTask::update_loading_glyph(); + BaseTask::pop_on_plus(); + m_transition.update(); + sm_dialog->set_from_transition(m_transition, true); + if (!m_transition.in_place()) { return; } + sys::ProgressTask *task = static_cast(m_task.get()); const double current = task->get_progress(); - BaseTask::update_loading_glyph(); - BaseTask::pop_on_plus(); - - if (!m_task->is_running()) { ProgressState::deactivate_state(); } + const bool isRunning = m_task->is_running(); + if (!isRunning && !m_close) { ProgressState::close_dialog(); } + else if (m_close && m_transition.in_place()) { ProgressState::deactivate_state(); } m_progressBarWidth = std::round(SIZE_BAR_WIDTH * current); m_progress = std::round(current * 100); @@ -47,13 +53,15 @@ void ProgressState::update() void ProgressState::render() { static constexpr int RIGHT_EDGE_X = (COORD_BAR_X + SIZE_BAR_WIDTH) - 16; - - const bool hasFocus = BaseState::has_focus(); - const int barWidth = static_cast(SIZE_BAR_WIDTH); - const std::string status = m_task->get_status(); + const bool hasFocus = BaseState::has_focus(); sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::DIM_BACKGROUND); sm_dialog->render(sdl::Texture::Null, hasFocus); + BaseTask::render_loading_glyph(); + if (!m_transition.in_place()) { return; } + + const int barWidth = static_cast(SIZE_BAR_WIDTH); + const std::string status = m_task->get_status(); sdl::text::render(sdl::Texture::Null, 312, 255, BaseTask::FONT_SIZE, 656, colors::WHITE, status); sdl::render_line(sdl::Texture::Null, 280, 421, 999, 421, colors::DIV_COLOR); @@ -70,8 +78,6 @@ void ProgressState::render() sdl::text::NO_WRAP, colors::WHITE, m_percentageString); - - BaseTask::render_loading_glyph(); } void ProgressState::initialize_static_members() @@ -80,8 +86,17 @@ void ProgressState::initialize_static_members() if (sm_dialog && sm_barEdges) { return; } - sm_dialog = ui::DialogBox::create(280, 229, 720, 256); + sm_dialog = ui::DialogBox::create(0, 0, 0, 0); sm_barEdges = sdl::TextureManager::load(BAR_EDGE_NAME, "romfs:/Textures/BarEdges.png"); + + sm_dialog->set_from_transition(m_transition, true); +} + +void ProgressState::close_dialog() +{ + m_transition.set_target_width(32); + m_transition.set_target_height(32); + m_close = true; } void ProgressState::deactivate_state() diff --git a/source/remote/Storage.cpp b/source/remote/Storage.cpp index 7152da9..3c32107 100644 --- a/source/remote/Storage.cpp +++ b/source/remote/Storage.cpp @@ -68,6 +68,16 @@ remote::Item *remote::Storage::get_file_by_name(std::string_view name) noexcept return &(*findFile); } +remote::Item *remote::Storage::get_item_by_id(std::string_view id) noexcept +{ + auto is_match = [&](const remote::Item &item) { return item.get_id() == id; }; + + auto findMatch = std::find_if(m_list.begin(), m_list.end(), is_match); + if (findMatch == m_list.end()) { return nullptr; } + + return &(*findMatch); +} + bool remote::Storage::supports_utf8() const noexcept { return m_utf8Paths; } std::string_view remote::Storage::get_prefix() const noexcept { return m_prefix; } diff --git a/source/tasks/titleoptions.cpp b/source/tasks/titleoptions.cpp index b678e64..38c1ec3 100644 --- a/source/tasks/titleoptions.cpp +++ b/source/tasks/titleoptions.cpp @@ -70,8 +70,7 @@ void tasks::titleoptions::delete_all_local_backups_for_title(sys::threadpool::Jo const bool dirExists = fslib::directory_exists(targetPath); const bool deleteFailed = dirExists && error::fslib(fslib::delete_directory_recursively(targetPath)); if (deleteFailed) { ui::PopMessageManager::push_message(popTicks, popFailure); } - else - { + else { const char *title = titleInfo->get_title(); std::string popMessage = stringutil::get_formatted_string(popSuccess, title); ui::PopMessageManager::push_message(popTicks, popMessage); @@ -97,11 +96,16 @@ void tasks::titleoptions::delete_all_remote_backups_for_title(sys::threadpool::J if (!exists) { TASK_FINISH_RETURN(task); } remote::Item *workDir = remote->get_directory_by_name(remoteTitle); + if (!workDir) { TASK_FINISH_RETURN(task); } remote->change_directory(workDir); remote::Storage::DirectoryListing remoteListing{}; remote->get_directory_listing(remoteListing); + // This is needed because deleting one throws the vector out of whack. + std::vector ids{}; + for (remote::Item *item : remoteListing) { ids.emplace_back(item->get_id()); } + { const char *statusFormat = strings::get_by_name(strings::names::TITLEOPTION_STATUS, 0); std::string status = stringutil::get_formatted_string(statusFormat, title); @@ -111,10 +115,18 @@ void tasks::titleoptions::delete_all_remote_backups_for_title(sys::threadpool::J const int popTicks = ui::PopMessageManager::DEFAULT_TICKS; const char *popSuccess = strings::get_by_name(strings::names::TITLEOPTION_POPS, 0); const char *popFailure = strings::get_by_name(strings::names::TITLEOPTION_POPS, 1); - for (remote::Item *item : remoteListing) + for (const std::string &id : ids) { + remote::Item *item = remote->get_item_by_id(id); + if (!item) { continue; } + const bool deleted = remote->delete_item(item); - if (!deleted) { ui::PopMessageManager::push_message(popTicks, popFailure); } + if (!deleted) + { + ui::PopMessageManager::push_message(popTicks, popFailure); + remote->return_to_root(); + TASK_FINISH_RETURN(task); + } } remote->return_to_root(); @@ -154,7 +166,9 @@ void tasks::titleoptions::reset_save_data(sys::threadpool::JobData taskData) const bool resetFailed = error::fslib(fslib::delete_directory_recursively(fs::DEFAULT_SAVE_ROOT)); const bool commitFailed = error::fslib(fslib::commit_data_to_file_system(fs::DEFAULT_SAVE_MOUNT)); if (resetFailed || commitFailed) { ui::PopMessageManager::push_message(popTicks, popFailed); } - else { ui::PopMessageManager::push_message(popTicks, popSuccess); } + else { + ui::PopMessageManager::push_message(popTicks, popSuccess); + } } task->complete(); @@ -248,8 +262,7 @@ void tasks::titleoptions::extend_save_data(sys::threadpool::JobData taskData) const char *popSuccess = strings::get_by_name(strings::names::TITLEOPTION_POPS, 10); ui::PopMessageManager::push_message(popTicks, popSuccess); } - else - { + else { const char *popFailed = strings::get_by_name(strings::names::TITLEOPTION_POPS, 11); ui::PopMessageManager::push_message(popTicks, popFailed); } diff --git a/source/ui/ControlGuide.cpp b/source/ui/ControlGuide.cpp index 447a587..cd190af 100644 --- a/source/ui/ControlGuide.cpp +++ b/source/ui/ControlGuide.cpp @@ -8,7 +8,7 @@ ui::ControlGuide::ControlGuide(const char *guide) , m_textWidth(sdl::text::get_width(23, m_guide)) , m_targetX(1220 - (m_textWidth + 24)) , m_guideWidth(1280 - m_targetX) - , m_transition(1280, 662, m_targetX, 662, 4) + , m_transition(1280, 662, 0, 0, m_targetX, 662, 0, 0, 4) { ui::ControlGuide::initialize_static_members(); } @@ -53,4 +53,4 @@ void ui::ControlGuide::reset() noexcept { m_transition.set_target_x(1280); m_transition.set_x(1280); -} \ No newline at end of file +} diff --git a/source/ui/DialogBox.cpp b/source/ui/DialogBox.cpp index 9614ab6..541eed2 100644 --- a/source/ui/DialogBox.cpp +++ b/source/ui/DialogBox.cpp @@ -57,6 +57,19 @@ void ui::DialogBox::set_width(int width) noexcept { m_width = width; } void ui::DialogBox::set_height(int height) noexcept { m_height = height; } +void ui::DialogBox::set_from_transition(ui::Transition &transition, bool centered) +{ + const int x = centered ? transition.get_centered_x() : transition.get_x(); + const int y = centered ? transition.get_centered_y() : transition.get_y(); + const int width = transition.get_width(); + const int height = transition.get_height(); + + m_x = x; + m_y = y; + m_width = width; + m_height = height; +} + void ui::DialogBox::initialize_static_members() { if (sm_darkCorners && sm_lightCorners) { return; } diff --git a/source/ui/SlideOutPanel.cpp b/source/ui/SlideOutPanel.cpp index b6b99a9..9af7760 100644 --- a/source/ui/SlideOutPanel.cpp +++ b/source/ui/SlideOutPanel.cpp @@ -16,7 +16,7 @@ ui::SlideOutPanel::SlideOutPanel(int width, Side side) : m_width(width) , m_targetX(side == Side::Left ? 0.0f : static_cast(SCREEN_WIDTH) - m_width) , m_side(side) - , m_transition(m_side == Side::Left ? -m_width : SCREEN_WIDTH, 0, m_targetX, 0, 4) + , m_transition(m_side == Side::Left ? -m_width : SCREEN_WIDTH, 0, 0, 0, m_targetX, 0, 0, 0, 4) , m_renderTarget( sdl::TextureManager::load("PANEL_" + std::to_string(sm_targetID++), m_width, 720, SDL_TEXTUREACCESS_TARGET)) {}; diff --git a/source/ui/Transition.cpp b/source/ui/Transition.cpp index ef8aaf4..ed8b7d1 100644 --- a/source/ui/Transition.cpp +++ b/source/ui/Transition.cpp @@ -6,11 +6,23 @@ #include -ui::Transition::Transition(int x, int y, int targetX, int targetY, int threshold) noexcept +ui::Transition::Transition(int x, + int y, + int width, + int height, + int targetX, + int targetY, + int targetWidth, + int targetHeight, + int threshold) noexcept : m_x(x) , m_y(y) + , m_width(width) + , m_height(height) , m_targetX(targetX) , m_targetY(targetY) + , m_targetWidth(targetWidth) + , m_targetHeight(targetHeight) , m_threshold(threshold) , m_scaling(config::get_animation_scaling()) {}; @@ -18,26 +30,51 @@ void ui::Transition::update() noexcept { ui::Transition::update_x_coord(); ui::Transition::update_y_coord(); + ui::Transition::update_width(); + ui::Transition::update_height(); } -bool ui::Transition::in_place() const noexcept { return m_x == m_targetX && m_y == m_targetY; } +bool ui::Transition::in_place() const noexcept +{ + return m_x == m_targetX && m_y == m_targetY && m_width == m_targetWidth && m_height == m_targetHeight; +} int ui::Transition::get_x() const noexcept { return static_cast(m_x); } int ui::Transition::get_y() const noexcept { return static_cast(m_y); } +int ui::Transition::get_width() const noexcept { return static_cast(m_width); } + +int ui::Transition::get_height() const noexcept { return static_cast(m_height); } + int ui::Transition::get_target_x() const noexcept { return static_cast(m_targetX); } int ui::Transition::get_target_y() const noexcept { return static_cast(m_targetY); } +int ui::Transition::get_target_width() const noexcept { return static_cast(m_targetWidth); } + +int ui::Transition::get_target_height() const noexcept { return static_cast(m_targetHeight); } + +int ui::Transition::get_centered_x() const noexcept { return 640 - (static_cast(m_width) / 2); } + +int ui::Transition::get_centered_y() const noexcept { return 360 - (static_cast(m_height) / 2); } + void ui::Transition::set_x(int x) noexcept { m_x = x; } void ui::Transition::set_y(int y) noexcept { m_y = y; } +void ui::Transition::set_width(int width) noexcept { m_width = static_cast(width); } + +void ui::Transition::set_height(int height) noexcept { m_height = static_cast(height); } + void ui::Transition::set_target_x(int targetX) noexcept { m_targetX = targetX; } void ui::Transition::set_target_y(int targetY) noexcept { m_targetY = targetY; } +void ui::Transition::set_target_width(int targetWidth) noexcept { m_targetWidth = targetWidth; } + +void ui::Transition::set_target_height(int targetHeight) noexcept { m_targetHeight = targetHeight; } + void ui::Transition::update_x_coord() noexcept { if (m_x == m_targetX) { return; } @@ -58,4 +95,26 @@ void ui::Transition::update_y_coord() noexcept const double distance = math::Util::absolute_distance(m_y, m_targetY); if (distance <= m_threshold) { m_y = m_targetY; } -} \ No newline at end of file +} + +void ui::Transition::update_width() noexcept +{ + if (m_width == m_targetWidth) { return; } + + const double add = (m_targetWidth - m_width) / m_scaling; + m_width += std::round(add); + + const double distance = math::Util::absolute_distance(m_width, m_targetWidth); + if (distance <= m_threshold) { m_width = m_targetWidth; } +} + +void ui::Transition::update_height() noexcept +{ + if (m_height == m_targetHeight) { return; } + + const double add = (m_targetHeight - m_height) / m_scaling; + m_height += add; + + const double distance = math::Util::absolute_distance(m_height, m_targetHeight); + if (distance <= m_threshold) { m_height = m_targetHeight; } +}