From a62665313fe8be87f2f9c733afd9a05b3cb33819 Mon Sep 17 00:00:00 2001 From: J-D-K Date: Sun, 8 Dec 2024 18:26:14 -0500 Subject: [PATCH] Progress for today --- Include/AppStates/MainMenuState.hpp | 2 + Include/AppStates/SettingsState.hpp | 20 +++++ Include/AppStates/TitleSelectState.hpp | 25 ++++++ Include/Colors.hpp | 1 + Include/Strings.hpp | 2 + Include/UI/Element.hpp | 2 +- Include/UI/IconMenu.hpp | 2 +- Include/UI/Menu.hpp | 2 +- Include/UI/TitleTile.hpp | 6 ++ Include/UI/TitleView.hpp | 12 ++- Makefile | 2 +- RomFS/Text/ENUS.json | 23 +++++- RomFS/Textures/BCAT.png | Bin 10002 -> 6390 bytes RomFS/Textures/Cache.png | Bin 7243 -> 5299 bytes RomFS/Textures/Icon.alpha | Bin 0 -> 65536 bytes RomFS/Textures/SettingsIcon.png | Bin 9542 -> 6728 bytes RomFS/Textures/SystemSaves.png | Bin 4903 -> 3737 bytes Source/AppStates/MainMenuState.cpp | 28 ++++++- Source/AppStates/SettingsState.cpp | 40 +++++++++ Source/AppStates/TitleSelectState.cpp | 59 ++++++++++++++ Source/Config.cpp | 8 +- Source/Data/TitleInfo.cpp | 5 +- Source/JKSV.cpp | 1 + Source/Main.cpp | 5 +- Source/UI/IconMenu.cpp | 20 +++-- Source/UI/Menu.cpp | 21 +++-- Source/UI/TitleTile.cpp | 18 ++++- Source/UI/TitleView.cpp | 108 +++++++++++++++++++++++++ 28 files changed, 374 insertions(+), 38 deletions(-) create mode 100644 Include/AppStates/SettingsState.hpp create mode 100644 Include/AppStates/TitleSelectState.hpp create mode 100644 RomFS/Textures/Icon.alpha create mode 100644 Source/AppStates/SettingsState.cpp create mode 100644 Source/AppStates/TitleSelectState.cpp diff --git a/Include/AppStates/MainMenuState.hpp b/Include/AppStates/MainMenuState.hpp index 4b78069..c16b8d6 100644 --- a/Include/AppStates/MainMenuState.hpp +++ b/Include/AppStates/MainMenuState.hpp @@ -25,6 +25,8 @@ class MainMenuState : public AppState UI::IconMenu m_MainMenu; // Vector of pointers to users. std::vector m_Users; + // Vector of view states for each user, settings, and extras + std::vector> m_States; // Pointer to control guide string so I don't need to call and fetch it every loop. const char *m_ControlGuide = nullptr; // X coordinate to render controls at. diff --git a/Include/AppStates/SettingsState.hpp b/Include/AppStates/SettingsState.hpp new file mode 100644 index 0000000..8acc0c8 --- /dev/null +++ b/Include/AppStates/SettingsState.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "AppStates/AppState.hpp" +#include "SDL.hpp" +#include "UI/Menu.hpp" + +class SettingsState : public AppState +{ + public: + SettingsState(void); + ~SettingsState() {}; + + void Update(void); + void Render(void); + + private: + // Menu containing options. + UI::Menu m_SettingsMenu; + // Render target. + SDL::SharedTexture m_RenderTarget = nullptr; +}; diff --git a/Include/AppStates/TitleSelectState.hpp b/Include/AppStates/TitleSelectState.hpp new file mode 100644 index 0000000..e2648de --- /dev/null +++ b/Include/AppStates/TitleSelectState.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "AppStates/AppState.hpp" +#include "Data/Data.hpp" +#include "SDL.hpp" +#include "UI/TitleView.hpp" + +class TitleSelectState : public AppState +{ + public: + TitleSelectState(Data::User *User); + ~TitleSelectState() {}; + + void Update(void); + void Render(void); + + private: + // Save pointer to user + Data::User *m_User = nullptr; + // Render target. + SDL::SharedTexture m_RenderTarget = nullptr; + // Title select view + UI::TitleView m_TitleView; + // X coordinate for control guide. Shared between all instances. Only should be calculated once. + static inline int m_TitleControlsX = 0; +}; diff --git a/Include/Colors.hpp b/Include/Colors.hpp index 9227edd..82949f2 100644 --- a/Include/Colors.hpp +++ b/Include/Colors.hpp @@ -10,6 +10,7 @@ namespace Colors static constexpr SDL::Color Blue = {0x0099EEFF}; static constexpr SDL::Color Yellow = {0xF8FC00FF}; static constexpr SDL::Color Pink = {0xFF4444FF}; + static constexpr SDL::Color BlueGreen = {0x00FFC5FF}; static constexpr SDL::Color ClearColor = {0x2D2D2DFF}; static constexpr SDL::Color DialogBox = {0x505050FF}; static constexpr SDL::Color BackgroundDim = {0x00000088}; diff --git a/Include/Strings.hpp b/Include/Strings.hpp index 68997e5..ffdd91b 100644 --- a/Include/Strings.hpp +++ b/Include/Strings.hpp @@ -14,5 +14,7 @@ namespace Strings static constexpr std::string_view ControlGuides = "ControlGuides"; static constexpr std::string_view SaveDataTypes = "SaveDataTypes"; static constexpr std::string_view MainMenuNames = "MainMenuNames"; + static constexpr std::string_view SettingsMenu = "SettingsMenu"; + static constexpr std::string_view OnOff = "OnOff"; } // namespace Names } // namespace Strings diff --git a/Include/UI/Element.hpp b/Include/UI/Element.hpp index 48b1b7b..0bdc53e 100644 --- a/Include/UI/Element.hpp +++ b/Include/UI/Element.hpp @@ -9,7 +9,7 @@ namespace UI Element(void) = default; virtual ~Element() {}; - virtual void Update(void) = 0; + virtual void Update(bool HasFocus) = 0; virtual void Render(SDL_Texture *Target, bool HasFocus) = 0; }; } // namespace UI diff --git a/Include/UI/IconMenu.hpp b/Include/UI/IconMenu.hpp index 46717f9..a0ba86c 100644 --- a/Include/UI/IconMenu.hpp +++ b/Include/UI/IconMenu.hpp @@ -10,7 +10,7 @@ namespace UI IconMenu(int X, int Y, int ScrollLength, int RenderTargetHeight); ~IconMenu() {}; - void Update(void); + void Update(bool HasFocus); void Render(SDL_Texture *Target, bool HasFocus); // Adds icon to menu. diff --git a/Include/UI/Menu.hpp b/Include/UI/Menu.hpp index 906211d..b20256f 100644 --- a/Include/UI/Menu.hpp +++ b/Include/UI/Menu.hpp @@ -15,7 +15,7 @@ namespace UI ~Menu() {}; // Required functions from Element. - void Update(void); + void Update(bool HasFocus); void Render(SDL_Texture *Target, bool HasFocus); // Adds an option to the menu. diff --git a/Include/UI/TitleTile.hpp b/Include/UI/TitleTile.hpp index 4d14ef4..5804124 100644 --- a/Include/UI/TitleTile.hpp +++ b/Include/UI/TitleTile.hpp @@ -11,6 +11,12 @@ namespace UI void Update(bool IsSelected); void Render(SDL_Texture *Target, int X, int Y); + // Resets width and height. + void Reset(void); + // Returns RenderWidth and RenderHeight + int GetWidth(void) const; + int GetHeight(void) const; + private: // Width and height so icon can "expand" when highlighted. int m_RenderWidth = 128, m_RenderHeight = 128; diff --git a/Include/UI/TitleView.hpp b/Include/UI/TitleView.hpp index 4771c0a..9d6314b 100644 --- a/Include/UI/TitleView.hpp +++ b/Include/UI/TitleView.hpp @@ -12,24 +12,22 @@ namespace UI { public: TitleView(Data::User *User); - + void Update(bool HasFocus); + void Render(SDL_Texture *Target, bool HasFocus); // Returns index of selected title. int GetSelected(void) const; - - void Update(void); - void Render(SDL_Texture *Target); + // Resets all tiles to 128x128 + void Reset(void); private: // Saves pointer to the user passed. Data::User *m_User = nullptr; // Y coordinate. double m_Y = 38; - // Target Y for scrolling effect. - double m_TargetY = 38; // Currently highlighted/selected title. int m_Selected = 0; // This is to save the X and Y coordinates so the selected icon can be drawn last. - int m_SelectedX, m_SelectedY; + double m_SelectedX, m_SelectedY = 38.0f; // Color mod for pulse. UI::ColorMod m_ColorMod; // Vector of tiles. diff --git a/Makefile b/Makefile index b1a6c5f..728d358 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ override CFLAGS += $(INCLUDE) -D__SWITCH__ override CFLAGS += `sdl2-config --cflags` `freetype-config --cflags` `curl-config --cflags` override CFLAGS += -g -Wall -O2 -ffunction-sections -ffast-math $(ARCH) $(DEFINES) -CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23 +CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=c++23 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) diff --git a/RomFS/Text/ENUS.json b/RomFS/Text/ENUS.json index baf978b..3799800 100644 --- a/RomFS/Text/ENUS.json +++ b/RomFS/Text/ENUS.json @@ -5,7 +5,7 @@ ], "ControlGuides" : [ "[A] Select [Y] Dump All Saves [X] User Options", - "[A] Select [L][R] Jump [Y] Favorite [X] Title Options [B] Back", + "[A] Select [L] [R] Jump [Y] Favorite [X] Title Options [B] Back", "[A] Select [Y] Restore [X] Delete [ZR] Upload [B] Close", "[A] Toggle [X] Defaults [B] Back" ], @@ -17,5 +17,26 @@ "Temporary", "Cache", "System BCAT" + ], + "SettingsMenu" : [ + "Set JKSV output folder.", + "Edit Blacklist", + "Include Device Saves with users: %s", + "Auto-backup on restore: %s", + "Auto-name backups: %s", + "Hold to delete backups: %s", + "Hold to restore backups: %s", + "Hold to overwrite backups: %s", + "Only list mountable titles: %s", + "Show account system saves: %s", + "Enable writing to system saves and NAND: %s", + "Export saves to ZIP: %s", + "Force English: %s", + "Enable trash bin: %s", + "Animation scaling: %s" + ], + "OnOff" : [ + "Off", + ">On>" ] } diff --git a/RomFS/Textures/BCAT.png b/RomFS/Textures/BCAT.png index da6c45ce4a03cc2184e5f1b5c0b3041127a9edcc..0444086ed6e9a57dacff1e47b1d37eec3b4295c7 100644 GIT binary patch literal 6390 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 literal 10002 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 diff --git a/RomFS/Textures/Cache.png b/RomFS/Textures/Cache.png index 5cacbe47e418299edbb650f79ff81d1293ea123c..f7075a348dffb9bd7da9680d11d40cd7ec25076f 100644 GIT binary patch literal 5299 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 BsmTBU literal 7243 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 E7hZl>yZ`_I diff --git a/RomFS/Textures/Icon.alpha b/RomFS/Textures/Icon.alpha new file mode 100644 index 0000000000000000000000000000000000000000..9735322592c2bded416189f03972f9bac0a38312 GIT binary patch literal 65536 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 Y*mWN+@p$QZ-XQ`Iw~cfvv`|t12c!VwUjP6A literal 9542 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 diff --git a/RomFS/Textures/SystemSaves.png b/RomFS/Textures/SystemSaves.png index 35edc5f0dc86fa81cdf99c6467a5b5453ec66bc2..53daa8d980c46cad4099215b6a77ef1d14f7eead 100644 GIT binary patch literal 3737 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 ZOqp-sU*nXwvA!5FxD|rawkiaL}(dgjWEeJ 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 + m_States.push_back(std::make_shared(m_Users.at(i))); } + m_States.push_back(std::make_shared()); // Create icons for the other two. m_SettingsIcon = SDL::TextureManager::CreateLoadTexture("SettingsIcon", "romfs:/Textures/SettingsIcon.png"); + m_ExtrasIcon = SDL::TextureManager::CreateLoadTexture("ExtrasIcon", 256, 256, 0); // Finally add them to the end. m_MainMenu.AddOption(m_SettingsIcon); @@ -36,7 +43,19 @@ MainMenuState::MainMenuState(void) void MainMenuState::Update(void) { - m_MainMenu.Update(); + m_MainMenu.Update(AppState::HasFocus()); + + if (Input::ButtonPressed(HidNpadButton_A) && m_MainMenu.GetSelected() < m_Users.size() && + m_Users.at(m_MainMenu.GetSelected())->GetTotalDataEntries() > 0) + { + m_States.at(m_MainMenu.GetSelected())->Reactivate(); + JKSV::PushState(m_States.at(m_MainMenu.GetSelected())); + } + else if (Input::ButtonPressed(HidNpadButton_A) && m_MainMenu.GetSelected() >= m_Users.size()) + { + m_States.at(m_MainMenu.GetSelected())->Reactivate(); + JKSV::PushState(m_States.at(m_MainMenu.GetSelected())); + } } void MainMenuState::Render(void) @@ -48,9 +67,10 @@ void MainMenuState::Render(void) // Render target to screen. m_RenderTarget->Render(NULL, 0, 91); - // Control Guide. + // Render next state for current user and control guide if this state has focus. if (AppState::HasFocus()) { - SDL::Text::Render(NULL, m_ControlGuideX, 673, 20, SDL::Text::NO_TEXT_WRAP, Colors::White, m_ControlGuide); + m_States.at(m_MainMenu.GetSelected())->Render(); + SDL::Text::Render(NULL, m_ControlGuideX, 673, 22, SDL::Text::NO_TEXT_WRAP, Colors::White, m_ControlGuide); } } diff --git a/Source/AppStates/SettingsState.cpp b/Source/AppStates/SettingsState.cpp new file mode 100644 index 0000000..7dc87f0 --- /dev/null +++ b/Source/AppStates/SettingsState.cpp @@ -0,0 +1,40 @@ +#include "AppStates/SettingsState.hpp" +#include "Colors.hpp" +#include "Input.hpp" +#include "Strings.hpp" + +namespace +{ + // All of these states share the same render target. + constexpr std::string_view SECONDARY_TARGET = "SecondaryTarget"; +} // namespace + +SettingsState::SettingsState(void) + : m_SettingsMenu(32, 18, 1002, 32, 4, 555), + m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET)) +{ + // Loop through strings and add them until nullptr. + int CurrentString = 0; + const char *SettingsString = nullptr; + while ((SettingsString = Strings::GetByName(Strings::Names::SettingsMenu, CurrentString++)) != nullptr) + { + m_SettingsMenu.AddOption(SettingsString); + } +} + +void SettingsState::Update(void) +{ + m_SettingsMenu.Update(AppState::HasFocus()); + + if (Input::ButtonPressed(HidNpadButton_B)) + { + AppState::Deactivate(); + } +} + +void SettingsState::Render(void) +{ + m_RenderTarget->Clear(Colors::Transparent); + m_SettingsMenu.Render(m_RenderTarget->Get(), AppState::HasFocus()); + m_RenderTarget->Render(NULL, 201, 91); +} diff --git a/Source/AppStates/TitleSelectState.cpp b/Source/AppStates/TitleSelectState.cpp new file mode 100644 index 0000000..5b880e1 --- /dev/null +++ b/Source/AppStates/TitleSelectState.cpp @@ -0,0 +1,59 @@ +#include "AppStates/TitleSelectState.hpp" +#include "Colors.hpp" +#include "Config.hpp" +#include "Input.hpp" +#include "SDL.hpp" +#include "Strings.hpp" +#include + +namespace +{ + // All of these states share the same render target. + constexpr std::string_view SECONDARY_TARGET = "SecondaryTarget"; +} // namespace + +TitleSelectState::TitleSelectState(Data::User *User) + : m_User(User), + m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET)), + m_TitleView(m_User) +{ + if (m_TitleControlsX == 0) + { + m_TitleControlsX = 1220 - SDL::Text::GetWidth(22, Strings::GetByName(Strings::Names::ControlGuides, 1)); + } +} + +void TitleSelectState::Update(void) +{ + m_TitleView.Update(AppState::HasFocus()); + + if (Input::ButtonPressed(HidNpadButton_B)) + { + // This will reset all the tiles so they're 128x128. + m_TitleView.Reset(); + AppState::Deactivate(); + } + else if (Input::ButtonPressed(HidNpadButton_Y)) + { + uint64_t ApplicationID = m_User->GetApplicationIDAt(m_TitleView.GetSelected()); + Config::AddRemoveFavorite(ApplicationID); + } +} + +void TitleSelectState::Render(void) +{ + m_RenderTarget->Clear(Colors::Transparent); + m_TitleView.Render(m_RenderTarget->Get(), AppState::HasFocus()); + + if (AppState::HasFocus()) + { + SDL::Text::Render(NULL, + m_TitleControlsX, + 673, + 22, + SDL::Text::NO_TEXT_WRAP, + Colors::White, + Strings::GetByName(Strings::Names::ControlGuides, 1)); + } + m_RenderTarget->Render(NULL, 201, 91); +} diff --git a/Source/Config.cpp b/Source/Config.cpp index b73bb55..baea6de 100644 --- a/Source/Config.cpp +++ b/Source/Config.cpp @@ -1,6 +1,7 @@ #include "Config.hpp" #include "JSON.hpp" #include "Logger.hpp" +#include "StringUtil.hpp" #include #include #include @@ -38,7 +39,7 @@ static void ReadArrayToVector(std::vector &Vector, json_object *Array) { continue; } - Vector.push_back(json_object_get_uint64(ArrayEntry)); + Vector.push_back(std::strtoull(json_object_get_string(ArrayEntry), NULL, 16)); } } @@ -134,7 +135,8 @@ void Config::Save(void) json_object *FavoritesArray = json_object_new_array(); for (uint64_t &TitleID : s_Favorites) { - json_object *NewFavorite = json_object_new_uint64(TitleID); + // Need to do it like this or json-c does decimal instead of hex. + json_object *NewFavorite = json_object_new_string(StringUtil::GetFormattedString("%016llX", TitleID).c_str()); json_object_array_add(FavoritesArray, NewFavorite); } json_object_object_add(ConfigJSON.get(), Config::Keys::Favorites.data(), FavoritesArray); @@ -143,7 +145,7 @@ void Config::Save(void) json_object *BlacklistArray = json_object_new_array(); for (uint64_t &TitleID : s_Blacklist) { - json_object *NewBlacklist = json_object_new_uint64(TitleID); + json_object *NewBlacklist = json_object_new_string(StringUtil::GetFormattedString("%016llX", TitleID).c_str()); json_object_array_add(BlacklistArray, NewBlacklist); } json_object_object_add(ConfigJSON.get(), Config::Keys::BlackList.data(), BlacklistArray); diff --git a/Source/Data/TitleInfo.cpp b/Source/Data/TitleInfo.cpp index 539ff43..d65275b 100644 --- a/Source/Data/TitleInfo.cpp +++ b/Source/Data/TitleInfo.cpp @@ -30,9 +30,10 @@ Data::TitleInfo::TitleInfo(uint64_t ApplicationID) sprintf(m_PathSafeTitle, "%016llX", ApplicationID); // Create a place holder icon. - int TextX = 128 - (SDL::Text::GetWidth(32, ApplicationIDHex.c_str()) / 2); + int TextX = 128 - (SDL::Text::GetWidth(48, ApplicationIDHex.c_str()) / 2); m_Icon = SDL::TextureManager::CreateLoadTexture(ApplicationIDHex, 256, 256, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); - SDL::Text::Render(m_Icon->Get(), TextX, 112, 32, SDL::Text::NO_TEXT_WRAP, Colors::White, ApplicationIDHex.c_str()); + m_Icon->Clear(Colors::DialogBox); + SDL::Text::Render(m_Icon->Get(), TextX, 104, 48, SDL::Text::NO_TEXT_WRAP, Colors::White, ApplicationIDHex.c_str()); } else if (R_SUCCEEDED(NsError) && R_SUCCEEDED(nacpGetLanguageEntry(&NsControlData.nacp, &LanguageEntry))) { diff --git a/Source/JKSV.cpp b/Source/JKSV.cpp index 51f9f41..863acb3 100644 --- a/Source/JKSV.cpp +++ b/Source/JKSV.cpp @@ -126,6 +126,7 @@ void JKSV::Update(void) { while (!m_StateVector.back()->IsActive()) { + m_StateVector.back()->TakeFocus(); m_StateVector.pop_back(); m_StateVector.back()->GiveFocus(); } diff --git a/Source/Main.cpp b/Source/Main.cpp index 895a046..3e9e57f 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -1,12 +1,15 @@ +#include "Config.hpp" #include "JKSV.hpp" +#include int main(void) { JKSV Jksv; - while (Jksv.IsRunning()) + while (appletMainLoop() && Jksv.IsRunning()) { Jksv.Update(); Jksv.Render(); } + Config::Save(); return 0; } diff --git a/Source/UI/IconMenu.cpp b/Source/UI/IconMenu.cpp index 999efe9..5a8a9f3 100644 --- a/Source/UI/IconMenu.cpp +++ b/Source/UI/IconMenu.cpp @@ -2,25 +2,31 @@ #include "Colors.hpp" #include "UI/RenderFunctions.hpp" -UI::IconMenu::IconMenu(int X, int Y, int ScrollLength, int RenderTargetHeight) : Menu(X, Y, 152, 132, ScrollLength, RenderTargetHeight) {}; +UI::IconMenu::IconMenu(int X, int Y, int ScrollLength, int RenderTargetHeight) : Menu(X, Y, 152, 88, ScrollLength, RenderTargetHeight) {}; -void UI::IconMenu::Update(void) +void UI::IconMenu::Update(bool HasFocus) { - Menu::Update(); + Menu::Update(HasFocus); } void UI::IconMenu::Render(SDL_Texture *Target, bool HasFocus) { - m_ColorMod.Update(); + if (HasFocus) + { + m_ColorMod.Update(); + } - for (int i = 0, TempY = m_Y; i < m_OptionsLength; i++, TempY += m_OptionHeight) + for (int i = 0, TempY = m_Y; i <= m_OptionsLength; i++, TempY += m_OptionHeight) { // Clear target. m_OptionTarget->Clear(Colors::Transparent); if (i == m_Selected) { - UI::RenderBoundingBox(Target, m_X - 8, TempY - 8, 152, 146, m_ColorMod); - SDL::RenderRectFill(m_OptionTarget->Get(), 0, 0, 4, 130, {0x00FFC5FF}); + if (HasFocus) + { + UI::RenderBoundingBox(Target, m_X - 8, TempY - 8, 152, 146, m_ColorMod); + } + SDL::RenderRectFill(m_OptionTarget->Get(), 0, 0, 6, 130, {0x00FFC5FF}); } //m_Options.at(i)->Render(m_OptionTarget->Get(), 0, 0); m_Options.at(i)->RenderStretched(m_OptionTarget->Get(), 8, 1, 128, 128); diff --git a/Source/UI/Menu.cpp b/Source/UI/Menu.cpp index 888c174..727a37b 100644 --- a/Source/UI/Menu.cpp +++ b/Source/UI/Menu.cpp @@ -3,10 +3,11 @@ #include "Config.hpp" #include "Input.hpp" #include "UI/RenderFunctions.hpp" +#include UI::Menu::Menu(int X, int Y, int Width, int FontSize, int ScrollLength, int RenderTargetHeight) : m_X(X), m_Y(Y), m_OriginalY(Y), m_FontSize(FontSize), m_ScrollLength(ScrollLength), m_MenuRenderLength(ScrollLength * 2), m_Width(Width), - m_OptionHeight(FontSize + 16), m_TargetY(Y), m_RenderTargetHeight(RenderTargetHeight) + m_OptionHeight(std::ceil(static_cast(FontSize) * 1.8f)), m_TargetY(Y), m_RenderTargetHeight(RenderTargetHeight) { static int MenuID = 0; // Create target for menu option @@ -15,7 +16,7 @@ UI::Menu::Menu(int X, int Y, int Width, int FontSize, int ScrollLength, int Rend SDL::TextureManager::CreateLoadTexture(MenuTargetName, m_Width, m_OptionHeight, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); } -void UI::Menu::Update(void) +void UI::Menu::Update(bool HasFocus) { // Bail if there's nothing to update. if (m_Options.empty()) @@ -46,7 +47,8 @@ void UI::Menu::Update(void) { m_TargetY = m_OriginalY; } - else if (PreviousSelected != m_Selected && m_Selected >= m_ScrollLength && (m_Selected > PreviousSelected || m_Selected < PreviousSelected)) + else if (PreviousSelected != m_Selected && m_Selected >= m_ScrollLength && + (m_Selected > PreviousSelected || m_Selected < PreviousSelected) && m_Selected < (m_OptionsLength - m_ScrollLength)) { m_TargetY = m_OriginalY - ((m_Selected - m_ScrollLength) * m_OptionHeight); } @@ -81,18 +83,21 @@ void UI::Menu::Render(SDL_Texture *Target, bool HasFocus) if (i == m_Selected) { - // Render the bounding box - UI::RenderBoundingBox(Target, m_X - 4, m_Y - 4, m_Width + 8, m_OptionHeight + 8, m_ColorMod); + if (HasFocus) + { + // Render the bounding box + UI::RenderBoundingBox(Target, m_X - 4, TempY - 4, m_Width + 8, m_OptionHeight + 8, m_ColorMod); + } // Render the little rectangle. - SDL::RenderRectFill(m_OptionTarget->Get(), 8, 2, 4, m_OptionHeight - 4, {0x00FFC5FF}); + SDL::RenderRectFill(m_OptionTarget->Get(), 8, 8, 6, m_OptionHeight - 16, Colors::BlueGreen); } // Render text to target. SDL::Text::Render(m_OptionTarget->Get(), - 14, + 20, (m_OptionHeight / 2) - (m_FontSize / 2), m_FontSize, SDL::Text::NO_TEXT_WRAP, - i == m_Selected ? Colors::Blue : Colors::White, + i == m_Selected ? Colors::BlueGreen : Colors::White, m_Options.at(i).c_str()); // Render target to target m_OptionTarget->Render(Target, m_X, TempY); diff --git a/Source/UI/TitleTile.cpp b/Source/UI/TitleTile.cpp index a845f01..b298b3b 100644 --- a/Source/UI/TitleTile.cpp +++ b/Source/UI/TitleTile.cpp @@ -26,6 +26,22 @@ void UI::TitleTile::Render(SDL_Texture *Target, int X, int Y) m_Icon->RenderStretched(Target, RenderX, RenderY, m_RenderWidth, m_RenderHeight); if (m_IsFavorite) { - SDL::Text::Render(Target, RenderX + 8, RenderY + 8, 20, SDL::Text::NO_TEXT_WRAP, Colors::Pink, "\uE017"); + SDL::Text::Render(Target, RenderX + 4, RenderY + 2, 28, SDL::Text::NO_TEXT_WRAP, Colors::Pink, "\uE017"); } } + +void UI::TitleTile::Reset(void) +{ + m_RenderWidth = 128; + m_RenderHeight = 128; +} + +int UI::TitleTile::GetWidth(void) const +{ + return m_RenderWidth; +} + +int UI::TitleTile::GetHeight(void) const +{ + return m_RenderHeight; +} diff --git a/Source/UI/TitleView.cpp b/Source/UI/TitleView.cpp index c00f1f8..8173c59 100644 --- a/Source/UI/TitleView.cpp +++ b/Source/UI/TitleView.cpp @@ -1,5 +1,15 @@ #include "UI/TitleView.hpp" +#include "Colors.hpp" #include "Config.hpp" +#include "Input.hpp" +#include "Logger.hpp" +#include "UI/RenderFunctions.hpp" +#include + +namespace +{ + constexpr int ICON_ROW_SIZE = 7; +} UI::TitleView::TitleView(Data::User *User) : m_User(User) { @@ -11,3 +21,101 @@ UI::TitleView::TitleView(Data::User *User) : m_User(User) m_TitleTiles.emplace_back(Config::IsFavorite(m_User->GetApplicationIDAt(i)), CurrentTitleInfo->GetIcon()); } } + +void UI::TitleView::Update(bool HasFocus) +{ + if (m_TitleTiles.empty()) + { + return; + } + + // Update pulse + if (HasFocus) + { + m_ColorMod.Update(); + } + + // Input. + int TotalTiles = m_TitleTiles.size() - 1; + if (Input::ButtonPressed(HidNpadButton_AnyUp) && (m_Selected -= ICON_ROW_SIZE) < 0) + { + m_Selected = 0; + } + else if (Input::ButtonPressed(HidNpadButton_AnyDown) && (m_Selected += ICON_ROW_SIZE) > TotalTiles) + { + m_Selected = TotalTiles; + } + else if (Input::ButtonPressed(HidNpadButton_AnyLeft) && m_Selected > 0) + { + --m_Selected; + } + else if (Input::ButtonPressed(HidNpadButton_AnyRight) && m_Selected < TotalTiles) + { + ++m_Selected; + } + + double Scaling = Config::GetAnimationScaling(); + if (m_SelectedY > 280.0f) + { + m_Y += std::ceil((280.0f - m_SelectedY) / Scaling); + } + else if (m_SelectedY < 38.0f) + { + m_Y += std::ceil((38.0f - m_SelectedY) / Scaling); + } + + for (size_t i = 0; i < m_TitleTiles.size(); i++) + { + m_TitleTiles.at(i).Update(m_Selected == i ? true : false); + } +} + +void UI::TitleView::Render(SDL_Texture *Target, bool HasFocus) +{ + if (m_TitleTiles.empty()) + { + return; + } + + for (int i = 0, TempY = m_Y; i < static_cast(m_TitleTiles.size()); TempY += 144) + { + int EndRow = i + 7; + for (int j = i, TempX = 32; j < EndRow; j++, i++, TempX += 144) + { + if (i >= static_cast(m_TitleTiles.size())) + { + break; + } + + // Save the X and Y to render the selected tile over the rest. + if (i == m_Selected) + { + m_SelectedX = TempX; + m_SelectedY = TempY; + continue; + } + // Just render + m_TitleTiles.at(i).Render(Target, TempX, TempY); + } + } + // Now render the selected title. + if (HasFocus) + { + SDL::RenderRectFill(Target, m_SelectedX - 23, m_SelectedY - 23, 174, 174, Colors::ClearColor); + UI::RenderBoundingBox(Target, m_SelectedX - 24, m_SelectedY - 24, 176, 176, m_ColorMod); + } + m_TitleTiles.at(m_Selected).Render(Target, m_SelectedX, m_SelectedY); +} + +int UI::TitleView::GetSelected(void) const +{ + return m_Selected; +} + +void UI::TitleView::Reset(void) +{ + for (UI::TitleTile &CurrentTile : m_TitleTiles) + { + CurrentTile.Reset(); + } +}