From 0438937c5c79bc3f0ed232893880df59b21d97cf Mon Sep 17 00:00:00 2001 From: J-D-K Date: Tue, 9 Sep 2025 20:47:48 -0400 Subject: [PATCH] Tinkering with transitions more. --- Makefile | 2 +- include/appstates/FileModeState.hpp | 10 +-- include/appstates/MainMenuState.hpp | 11 ++-- include/appstates/SettingsState.hpp | 11 ++-- include/appstates/TitleSelectCommon.hpp | 16 ++--- include/ui/ControlGuide.hpp | 51 +++++++++++++++ include/ui/Transition.hpp | 72 ++++++++++++++++++++++ include/ui/ui.hpp | 3 +- romfs/Textures/GuideCap.png | Bin 0 -> 481 bytes source/StateManager.cpp | 2 +- source/appstates/FileModeState.cpp | 19 ++---- source/appstates/FileOptionState.cpp | 3 - source/appstates/MainMenuState.cpp | 11 ++-- source/appstates/SettingsState.cpp | 13 ++-- source/appstates/TextTitleSelectState.cpp | 8 ++- source/appstates/TitleSelectCommon.cpp | 23 +++---- source/appstates/TitleSelectState.cpp | 3 +- source/main.cpp | 2 +- source/ui/ControlGuide.cpp | 50 +++++++++++++++ source/ui/Transition.cpp | 61 ++++++++++++++++++ 20 files changed, 297 insertions(+), 74 deletions(-) create mode 100644 include/ui/ControlGuide.hpp create mode 100644 include/ui/Transition.hpp create mode 100644 romfs/Textures/GuideCap.png create mode 100644 source/ui/ControlGuide.cpp create mode 100644 source/ui/Transition.cpp diff --git a/Makefile b/Makefile index b2b4b55..1e621f5 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE # NOTE: For some reason, devkitpro no longer has freetype-config included? Also, using pkg-config causes conflicts with # my local pkg-config and I don't feel like dealing with CMake for all of this right now. CFLAGS := $(INCLUDE) -D__SWITCH__ `sdl2-config --cflags` `curl-config --cflags`\ - -g -Wall -O3 -ffunction-sections -ffast-math -fmax-errors=1 \ + -g -Wall -O3 -Os -ffunction-sections -ffast-math -fmax-errors=1 \ $(ARCH) $(DEFINES) CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=c++23 diff --git a/include/appstates/FileModeState.hpp b/include/appstates/FileModeState.hpp index 8dc51dd..3f86367 100644 --- a/include/appstates/FileModeState.hpp +++ b/include/appstates/FileModeState.hpp @@ -87,11 +87,8 @@ class FileModeState final : public BaseState /// @brief This is the render target the browsers are rendered to. static inline sdl::SharedTexture sm_renderTarget{}; - /// @brief Stores a pointer to the guide in the bottom-right corner. - static inline const char *sm_controlGuide{}; - - /// @brief Calculated X coordinate of the control guide text. - static inline int sm_controlGuideX{}; + /// @brief Control guide shared by all instances. + static inline std::shared_ptr sm_controlGuide{}; /// @brief Initializes the members shared by all instances of FileModeState. void initialize_static_members(); @@ -136,9 +133,6 @@ class FileModeState final : public BaseState ui::Menu &menu, const fslib::DirectoryEntry &entry); - /// @brief Renders the control guide string on the bottom of the screen. - void render_control_guide(); - /// @brief Returns a reference to the currently active menu. ui::Menu &get_source_menu() noexcept; diff --git a/include/appstates/MainMenuState.hpp b/include/appstates/MainMenuState.hpp index afb5153..b1b82b7 100644 --- a/include/appstates/MainMenuState.hpp +++ b/include/appstates/MainMenuState.hpp @@ -3,6 +3,7 @@ #include "appstates/BaseState.hpp" #include "data/data.hpp" #include "sdl.hpp" +#include "ui/ControlGuide.hpp" #include "ui/IconMenu.hpp" #include @@ -28,6 +29,9 @@ class MainMenuState final : public BaseState /// @brief Runs update routine. void update() override; + /// @brief Runs the sub-update routine. + void sub_update() override; + /// @brief Renders menu to screen. void render() override; @@ -62,11 +66,8 @@ class MainMenuState final : public BaseState /// @brief Special menu type that uses icons. std::shared_ptr m_mainMenu{}; - /// @brief Pointer to control guide string so I don't need to call string::getByName every loop. - const char *m_controlGuide{}; - - /// @brief X coordinate of the control guide in the bottom right corner. - int m_controlGuideX{}; + /// @brief Control guide in the bottom right. + std::shared_ptr m_controlGuide{}; /// @brief This is the data struct passed to tasks. MainMenuState::TaskData m_dataStruct{}; diff --git a/include/appstates/SettingsState.hpp b/include/appstates/SettingsState.hpp index 0918797..b633f75 100644 --- a/include/appstates/SettingsState.hpp +++ b/include/appstates/SettingsState.hpp @@ -1,6 +1,7 @@ #pragma once #include "appstates/BaseState.hpp" #include "sdl.hpp" +#include "ui/ControlGuide.hpp" #include "ui/Menu.hpp" /// @brief The state for settings. @@ -16,6 +17,9 @@ class SettingsState final : public BaseState /// @brief Runs the update routine. void update() override; + /// @brief Sub update routine. + void sub_update() override; + /// @brief Runs the render routine. void render() override; @@ -23,15 +27,12 @@ class SettingsState final : public BaseState /// @brief Menu for selecting and toggling settings. std::shared_ptr m_settingsMenu{}; - /// @brief Pointer to the control guide string. - const char *m_controlGuide{}; - // These are pointers to strings this state uses constantly. const char *m_onOff[2]{}; const char *m_sortTypes[3]{}; - /// @brief X coordinate of the control guide in the bottom right corner. - int m_controlGuideX{}; + /// @brief Control guide. + std::shared_ptr m_controlGuide{}; /// @brief Render target to render to. sdl::SharedTexture m_renderTarget{}; diff --git a/include/appstates/TitleSelectCommon.hpp b/include/appstates/TitleSelectCommon.hpp index 0164ab8..a152665 100644 --- a/include/appstates/TitleSelectCommon.hpp +++ b/include/appstates/TitleSelectCommon.hpp @@ -1,5 +1,6 @@ #pragma once #include "appstates/BaseState.hpp" +#include "ui/ControlGuide.hpp" /// @brief Class that both view types are derived from. class TitleSelectCommon : public BaseState @@ -15,19 +16,20 @@ class TitleSelectCommon : public BaseState /// @brief Required, inherited. virtual void update() = 0; + /// @brief Sub-update routine. Normally in a file, but I didn't feel like it really needed one. + void sub_update() override; + /// @brief Required, inherited. virtual void render() = 0; /// @brief Both derived classes need this function. virtual void refresh() = 0; - /// @brief Renders the control guide string to the bottom right corner. - void render_control_guide(); + protected: + /// @brief This is the control guide shared by all title selects. + static inline std::shared_ptr sm_controlGuide{}; private: - /// @brief Pointer to the control guide string. - static inline const char *sm_controlGuide{}; - - /// @brief X coordinate the control guide is rendered at. - static inline int sm_controlGuideX{}; + /// @brief Initializes the control guide if it hasn't been already. + void initialize_control_guide(); }; diff --git a/include/ui/ControlGuide.hpp b/include/ui/ControlGuide.hpp new file mode 100644 index 0000000..ff65223 --- /dev/null +++ b/include/ui/ControlGuide.hpp @@ -0,0 +1,51 @@ +#pragma once +#include "sdl.hpp" +#include "ui/Element.hpp" +#include "ui/Transition.hpp" + +namespace ui +{ + class ControlGuide final : public ui::Element + { + public: + /// @brief Creates a new control guide. + /// @param string Pointer to the control guide string to render. + ControlGuide(const char *guide); + + static inline std::shared_ptr create(const char *guide) + { + return std::make_shared(guide); + } + + /// @brief Update routine. Opens the guide. + void update(bool hasFocus) override; + + /// @brief Sub update routine. Handles hiding the control guide. + void sub_update(); + + /// @brief Renders the control guide. Both arguments are ignored in this case. + void render(sdl::SharedTexture &target, bool hasFocus) override; + + private: + /// @brief Stores the pointer to the guide string. + const char *m_guide{}; + + /// @brief Width of the control guide text. + int m_textWidth{}; + + /// @brief This stores the target X coordinate of the guide. + int m_targetX{}; + + /// @brief Width of the guide. + int m_guideWidth{}; + + /// @brief Transition for the guide string. + ui::Transition m_transition{}; + + /// @brief This is shared by all instances. + static inline sdl::SharedTexture sm_controlCap{}; + + /// @brief Ensures the control guide cap is loaded for all instances. + void initialize_static_members(); + }; +} \ No newline at end of file diff --git a/include/ui/Transition.hpp b/include/ui/Transition.hpp new file mode 100644 index 0000000..f880d93 --- /dev/null +++ b/include/ui/Transition.hpp @@ -0,0 +1,72 @@ +#pragma once + +namespace ui +{ + class Transition final + { + public: + /// @brief Default. + Transition() = default; + + /// @brief Constructs a new transition. + /// @param x Beginning X coord. + /// @param y Beginning Y coord. + /// @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; + + /// @brief Updates the transition. + void update() noexcept; + + /// @brief Returns whether or not the transition has been met. + bool in_place() const noexcept; + + /// @brief Returns the X coordinate. + int get_x() const noexcept; + + /// @brief Returns the Y coordinate. + int get_y() 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 Sets the X coordinate. + void set_x(int x) noexcept; + + /// @brief Sets the Y coordinate. + void set_y(int y) 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; + + private: + /// @brief Current X. + double m_x{}; + + /// @brief Current Y. + double m_y{}; + + /// @brief Target X. + double m_targetX{}; + + /// @brief Target Y. + double m_targetY{}; + + /// @brief Pixel gap threshold. + double m_threshold{}; + + /// @brief Scaling from config. + double m_scaling{}; + + void update_x_coord() noexcept; + + void update_y_coord() noexcept; + }; +} \ No newline at end of file diff --git a/include/ui/ui.hpp b/include/ui/ui.hpp index 7427b18..43b0984 100644 --- a/include/ui/ui.hpp +++ b/include/ui/ui.hpp @@ -1,6 +1,7 @@ #pragma once #include "ui/BoundingBox.hpp" #include "ui/ColorMod.hpp" +#include "ui/ControlGuide.hpp" #include "ui/DialogBox.hpp" #include "ui/Element.hpp" #include "ui/Frame.hpp" @@ -10,4 +11,4 @@ #include "ui/SlideOutPanel.hpp" #include "ui/TextScroll.hpp" #include "ui/TitleTile.hpp" -#include "ui/TitleView.hpp" +#include "ui/TitleView.hpp" \ No newline at end of file diff --git a/romfs/Textures/GuideCap.png b/romfs/Textures/GuideCap.png new file mode 100644 index 0000000000000000000000000000000000000000..f005b8c7adb64f5a388bf2a6e8319859f5675c60 GIT binary patch literal 481 zcmV<70UrK|P)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vG?BLDy{BLR4&KXw2B0ZK_kK~zY`rPVP@12Gf;;Lq#g z;7}Y?Q0XG-prRns!O2CZ&f+8v`VSqQ1a}8PQ9%W%gP4M1yo-u{>TtKRem8uCX1Ag$9X3@+6;1!=(OCi+; z-~r!Q9fdT;%nq2N#QKi1^SEayjOJp X@53wqt(|Gc00000NkvXXu0mjfu=&BV literal 0 HcmV?d00001 diff --git a/source/StateManager.cpp b/source/StateManager.cpp index 911b2bf..7911015 100644 --- a/source/StateManager.cpp +++ b/source/StateManager.cpp @@ -25,7 +25,7 @@ void StateManager::update() if (stateVector.empty()) { return; } // Run sub update routines. - for (auto &state : stateVector) { state->sub_update(); } + for (auto iter = stateVector.begin(); iter < stateVector.end() - 1; iter++) { (*iter)->sub_update(); } std::shared_ptr &back = stateVector.back(); if (!back->has_focus()) { back->give_focus(); } diff --git a/source/appstates/FileModeState.cpp b/source/appstates/FileModeState.cpp index 57acda7..4d021c2 100644 --- a/source/appstates/FileModeState.cpp +++ b/source/appstates/FileModeState.cpp @@ -51,6 +51,7 @@ void FileModeState::update() else if (FileModeState::is_hidden()) { FileModeState::deactivate_state(); } menu.update(hasFocus); + sm_controlGuide->update(hasFocus); } void FileModeState::render() @@ -60,7 +61,7 @@ void FileModeState::render() sm_renderTarget->clear(colors::TRANSPARENT); // This is here so it's rendered underneath the pop-up frame. - if (hasFocus) { FileModeState::render_control_guide(); } + sm_controlGuide->render(sdl::Texture::Null, hasFocus); sdl::render_line(sm_renderTarget, 617, 0, 617, 538, colors::WHITE); sdl::render_line(sm_renderTarget, 618, 0, 618, 538, colors::DIALOG_DARK); @@ -76,14 +77,11 @@ void FileModeState::initialize_static_members() { static constexpr std::string_view RENDER_TARGET_NAME = "FMRenderTarget"; - static constexpr int CONTROL_GUIDE_START_X = 1220; + if (sm_frame && sm_renderTarget && sm_controlGuide) { return; } - if (sm_frame && sm_renderTarget) { return; } - - sm_frame = ui::Frame::create(15, 720, 1250, 555); - sm_renderTarget = sdl::TextureManager::load(RENDER_TARGET_NAME, 1234, 538, SDL_TEXTUREACCESS_TARGET); - sm_controlGuide = strings::get_by_name(strings::names::CONTROL_GUIDES, 4); - sm_controlGuideX = CONTROL_GUIDE_START_X - sdl::text::get_width(22, sm_controlGuide); + sm_frame = ui::Frame::create(15, 720, 1250, 555); + sm_renderTarget = sdl::TextureManager::load(RENDER_TARGET_NAME, 1234, 538, SDL_TEXTUREACCESS_TARGET); + sm_controlGuide = ui::ControlGuide::create(strings::get_by_name(strings::names::CONTROL_GUIDES, 4)); } void FileModeState::initialize_paths() @@ -204,11 +202,6 @@ void FileModeState::enter_directory(fslib::Path &path, FileModeState::initialize_directory_menu(path, directory, menu); } -void FileModeState::render_control_guide() -{ - sdl::text::render(sdl::Texture::Null, sm_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, sm_controlGuide); -} - ui::Menu &FileModeState::get_source_menu() noexcept { return m_target ? *m_dirMenuB.get() : *m_dirMenuA.get(); } ui::Menu &FileModeState::get_destination_menu() noexcept { return m_target ? *m_dirMenuA.get() : *m_dirMenuB.get(); } diff --git a/source/appstates/FileOptionState.cpp b/source/appstates/FileOptionState.cpp index c10c37e..1ae50f0 100644 --- a/source/appstates/FileOptionState.cpp +++ b/source/appstates/FileOptionState.cpp @@ -93,9 +93,6 @@ void FileOptionState::render() sm_dialog->render(sdl::Texture::Null, hasFocus); sm_copyMenu->render(sdl::Texture::Null, hasFocus); - - // I just didn't like this disappearing. - m_spawningState->render_control_guide(); } void FileOptionState::update_source() { m_updateSource = true; } diff --git a/source/appstates/MainMenuState.cpp b/source/appstates/MainMenuState.cpp index 230702f..b8dbb8d 100644 --- a/source/appstates/MainMenuState.cpp +++ b/source/appstates/MainMenuState.cpp @@ -30,8 +30,7 @@ MainMenuState::MainMenuState() , m_settingsIcon(sdl::TextureManager::load("settingsIcon", "romfs:/Textures/SettingsIcon.png")) , m_extrasIcon(sdl::TextureManager::load("extrasIcon", "romfs:/Textures/ExtrasIcon.png")) , m_mainMenu(ui::IconMenu::create(50, 15, 555)) - , m_controlGuide(strings::get_by_name(strings::names::CONTROL_GUIDES, 0)) - , m_controlGuideX(1220 - sdl::text::get_width(22, m_controlGuide)) + , m_controlGuide(ui::ControlGuide::create(strings::get_by_name(strings::names::CONTROL_GUIDES, 0))) , m_dataStruct(std::make_shared()) { MainMenuState::initialize_settings_extras(); @@ -55,8 +54,13 @@ void MainMenuState::update() else if (yPressed) { MainMenuState::backup_all_for_all(); } m_mainMenu->update(hasFocus); + m_controlGuide->update(hasFocus); + + for (auto &state : sm_states) { state->sub_update(); } } +void MainMenuState::sub_update() { m_controlGuide->sub_update(); } + void MainMenuState::render() { const bool hasFocus = BaseState::has_focus(); @@ -65,13 +69,12 @@ void MainMenuState::render() m_background->render(m_renderTarget, 0, 0); m_mainMenu->render(m_renderTarget, hasFocus); m_renderTarget->render(sdl::Texture::Null, 0, 91); + m_controlGuide->render(sdl::Texture::Null, hasFocus); if (hasFocus) { BaseState *target = sm_states[selected].get(); - target->render(); - sdl::text::render(sdl::Texture::Null, m_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, m_controlGuide); } } diff --git a/source/appstates/SettingsState.cpp b/source/appstates/SettingsState.cpp index b8b9d86..f1b0b8b 100644 --- a/source/appstates/SettingsState.cpp +++ b/source/appstates/SettingsState.cpp @@ -63,8 +63,7 @@ namespace SettingsState::SettingsState() : m_settingsMenu(ui::Menu::create(32, 8, 1000, 24, 555)) - , m_controlGuide(strings::get_by_name(strings::names::CONTROL_GUIDES, 3)) - , m_controlGuideX(1220 - sdl::text::get_width(22, m_controlGuide)) + , m_controlGuide(ui::ControlGuide::create(strings::get_by_name(strings::names::CONTROL_GUIDES, 3))) , m_renderTarget(sdl::TextureManager::load(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_TARGET)) { SettingsState::load_settings_menu(); @@ -83,8 +82,12 @@ void SettingsState::update() if (aPressed) { SettingsState::toggle_options(); } else if (minusPressed) { SettingsState::create_push_description_message(); } else if (bPressed) { BaseState::deactivate(); } + + m_controlGuide->update(hasFocus); } +void SettingsState::sub_update() { m_controlGuide->sub_update(); } + void SettingsState::render() { const bool hasFocus = BaseState::has_focus(); @@ -92,11 +95,7 @@ void SettingsState::render() m_renderTarget->clear(colors::TRANSPARENT); m_settingsMenu->render(m_renderTarget, hasFocus); m_renderTarget->render(sdl::Texture::Null, 201, 91); - - if (hasFocus) - { - sdl::text::render(sdl::Texture::Null, m_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, m_controlGuide); - } + m_controlGuide->render(sdl::Texture::Null, hasFocus); } void SettingsState::load_settings_menu() diff --git a/source/appstates/TextTitleSelectState.cpp b/source/appstates/TextTitleSelectState.cpp index 9346444..7e79066 100644 --- a/source/appstates/TextTitleSelectState.cpp +++ b/source/appstates/TextTitleSelectState.cpp @@ -43,13 +43,17 @@ void TextTitleSelectState::update() else if (xPressed) { TextTitleSelectState::create_title_option_menu(); } else if (yPressed) { TextTitleSelectState::add_remove_favorite(); } else if (bPressed) { BaseState::deactivate(); } + + sm_controlGuide->update(hasFocus); } void TextTitleSelectState::render() { + const bool hasFocus = BaseState::has_focus(); + m_renderTarget->clear(colors::TRANSPARENT); - m_titleSelectMenu->render(m_renderTarget, BaseState::has_focus()); - TitleSelectCommon::render_control_guide(); + m_titleSelectMenu->render(m_renderTarget, hasFocus); + sm_controlGuide->render(sdl::Texture::Null, hasFocus); m_renderTarget->render(sdl::Texture::Null, 201, 91); } diff --git a/source/appstates/TitleSelectCommon.cpp b/source/appstates/TitleSelectCommon.cpp index 9fdd60d..2c3f752 100644 --- a/source/appstates/TitleSelectCommon.cpp +++ b/source/appstates/TitleSelectCommon.cpp @@ -4,20 +4,13 @@ #include "sdl.hpp" #include "strings/strings.hpp" -TitleSelectCommon::TitleSelectCommon() +TitleSelectCommon::TitleSelectCommon() { TitleSelectCommon::initialize_control_guide(); } + +void TitleSelectCommon::sub_update() { sm_controlGuide->sub_update(); } + +void TitleSelectCommon::initialize_control_guide() { - if (sm_controlGuide && sm_controlGuideX != 0) { return; } + if (sm_controlGuide) { return; } - sm_controlGuide = strings::get_by_name(strings::names::CONTROL_GUIDES, 1); - sm_controlGuideX = 1220 - sdl::text::get_width(22, sm_controlGuide); -} - -void TitleSelectCommon::render_control_guide() -{ - const bool hasFocus = BaseState::has_focus(); - - if (hasFocus) - { - sdl::text::render(sdl::Texture::Null, sm_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, sm_controlGuide); - } -} + sm_controlGuide = ui::ControlGuide::create(strings::get_by_name(strings::names::CONTROL_GUIDES, 1)); +} \ No newline at end of file diff --git a/source/appstates/TitleSelectState.cpp b/source/appstates/TitleSelectState.cpp index d3c0851..4ce241b 100644 --- a/source/appstates/TitleSelectState.cpp +++ b/source/appstates/TitleSelectState.cpp @@ -45,6 +45,7 @@ void TitleSelectState::update() } m_titleView->update(hasFocus); + sm_controlGuide->update(hasFocus); } void TitleSelectState::render() @@ -53,7 +54,7 @@ void TitleSelectState::render() m_renderTarget->clear(colors::TRANSPARENT); m_titleView->render(m_renderTarget, hasFocus); - TitleSelectCommon::render_control_guide(); + sm_controlGuide->render(sdl::Texture::Null, hasFocus); m_renderTarget->render(sdl::Texture::Null, 201, 91); } diff --git a/source/main.cpp b/source/main.cpp index 4642d45..03fedbd 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,7 +2,7 @@ #include -int main() +int main(int argc, const char *argv[]) { JKSV jksv{}; while (appletMainLoop() && jksv.is_running()) diff --git a/source/ui/ControlGuide.cpp b/source/ui/ControlGuide.cpp new file mode 100644 index 0000000..8884968 --- /dev/null +++ b/source/ui/ControlGuide.cpp @@ -0,0 +1,50 @@ +#include "ui/ControlGuide.hpp" + +#include "graphics/colors.hpp" +#include "logging/logger.hpp" + +ui::ControlGuide::ControlGuide(const char *guide) + : m_guide(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) +{ + ui::ControlGuide::initialize_static_members(); +} + +void ui::ControlGuide::update(bool hasFocus) +{ + m_transition.update(); + if (!m_transition.in_place()) { return; } + + const int targetX = m_transition.get_target_x(); + if (hasFocus && targetX != m_targetX) { m_transition.set_target_x(m_targetX); } +} + +void ui::ControlGuide::sub_update() +{ + const int targetX = m_transition.get_target_x(); + if (targetX != 1280) { m_transition.set_target_x(1280); } + + m_transition.update(); +} + +void ui::ControlGuide::render(sdl::SharedTexture &target, bool hasFocus) +{ + const int guideX = m_transition.get_x(); + const int guideY = m_transition.get_y(); + + sm_controlCap->render(sdl::Texture::Null, guideX, guideY); + sdl::render_rect_fill(sdl::Texture::Null, guideX + 16, guideY, m_guideWidth - 16, 48, colors::SLIDE_PANEL_CLEAR); + sdl::text::render(sdl::Texture::Null, guideX + 24, guideY + 10, 23, sdl::text::NO_WRAP, colors::WHITE, m_guide); +} + +void ui::ControlGuide::initialize_static_members() +{ + static constexpr std::string_view NAME_CAP = "ControlGuideCap"; + + if (sm_controlCap) { return; } + + sm_controlCap = sdl::TextureManager::load(NAME_CAP, "romfs:/Textures/GuideCap.png"); +} \ No newline at end of file diff --git a/source/ui/Transition.cpp b/source/ui/Transition.cpp new file mode 100644 index 0000000..ef8aaf4 --- /dev/null +++ b/source/ui/Transition.cpp @@ -0,0 +1,61 @@ +#include "ui/Transition.hpp" + +#include "config/config.hpp" +#include "logging/logger.hpp" +#include "mathutil.hpp" + +#include + +ui::Transition::Transition(int x, int y, int targetX, int targetY, int threshold) noexcept + : m_x(x) + , m_y(y) + , m_targetX(targetX) + , m_targetY(targetY) + , m_threshold(threshold) + , m_scaling(config::get_animation_scaling()) {}; + +void ui::Transition::update() noexcept +{ + ui::Transition::update_x_coord(); + ui::Transition::update_y_coord(); +} + +bool ui::Transition::in_place() const noexcept { return m_x == m_targetX && m_y == m_targetY; } + +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_target_x() const noexcept { return static_cast(m_targetX); } + +int ui::Transition::get_target_y() const noexcept { return static_cast(m_targetY); } + +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_target_x(int targetX) noexcept { m_targetX = targetX; } + +void ui::Transition::set_target_y(int targetY) noexcept { m_targetY = targetY; } + +void ui::Transition::update_x_coord() noexcept +{ + if (m_x == m_targetX) { return; } + + const double add = (m_targetX - m_x) / m_scaling; + m_x += std::round(add); + + const double distance = math::Util::absolute_distance(m_x, m_targetX); + if (distance <= m_threshold) { m_x = m_targetX; } +} + +void ui::Transition::update_y_coord() noexcept +{ + if (m_y == m_targetY) { return; } + + const double add = (m_targetY - m_y) / m_scaling; + m_y += std::round(add); + + 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