Progress for today
@@ -25,6 +25,8 @@ class MainMenuState : public AppState
|
||||
UI::IconMenu m_MainMenu;
|
||||
// Vector of pointers to users.
|
||||
std::vector<Data::User *> m_Users;
|
||||
// Vector of view states for each user, settings, and extras
|
||||
std::vector<std::shared_ptr<AppState>> 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.
|
||||
|
||||
20
Include/AppStates/SettingsState.hpp
Normal file
@@ -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;
|
||||
};
|
||||
25
Include/AppStates/TitleSelectState.hpp
Normal file
@@ -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;
|
||||
};
|
||||
@@ -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};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
2
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)
|
||||
|
||||
@@ -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>"
|
||||
]
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 5.2 KiB |
BIN
RomFS/Textures/Icon.alpha
Normal file
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -1,6 +1,10 @@
|
||||
#include "AppStates/MainMenuState.hpp"
|
||||
#include "AppStates/SettingsState.hpp"
|
||||
#include "AppStates/TitleSelectState.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Input.hpp"
|
||||
#include "JKSV.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "SDL.hpp"
|
||||
#include "Strings.hpp"
|
||||
@@ -15,7 +19,7 @@ MainMenuState::MainMenuState(void)
|
||||
: m_RenderTarget(SDL::TextureManager::CreateLoadTexture("MainMenuTarget", 200, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET)),
|
||||
m_Background(SDL::TextureManager::CreateLoadTexture("MainMenuBackground", "romfs:/Textures/MenuBackground.png")),
|
||||
m_MainMenu(50, 15, 1, 555), m_ControlGuide(Strings::GetByName(Strings::Names::ControlGuides, 0)),
|
||||
m_ControlGuideX(1220 - SDL::Text::GetWidth(20, m_ControlGuide))
|
||||
m_ControlGuideX(1220 - SDL::Text::GetWidth(22, m_ControlGuide))
|
||||
{
|
||||
// Fetch user list.
|
||||
Data::GetUsers(m_Users);
|
||||
@@ -24,10 +28,13 @@ MainMenuState::MainMenuState(void)
|
||||
for (size_t i = 0; i < m_Users.size(); i++)
|
||||
{
|
||||
m_MainMenu.AddOption(m_Users.at(i)->GetSharedIcon());
|
||||
m_States.push_back(std::make_shared<TitleSelectState>(m_Users.at(i)));
|
||||
}
|
||||
m_States.push_back(std::make_shared<SettingsState>());
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
40
Source/AppStates/SettingsState.cpp
Normal file
@@ -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);
|
||||
}
|
||||
59
Source/AppStates/TitleSelectState.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "AppStates/TitleSelectState.hpp"
|
||||
#include "Colors.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Input.hpp"
|
||||
#include "SDL.hpp"
|
||||
#include "Strings.hpp"
|
||||
#include <string_view>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Config.hpp"
|
||||
#include "JSON.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "StringUtil.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@@ -38,7 +39,7 @@ static void ReadArrayToVector(std::vector<uint64_t> &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);
|
||||
|
||||
@@ -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)))
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include "Config.hpp"
|
||||
#include "JKSV.hpp"
|
||||
#include <switch.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
JKSV Jksv;
|
||||
while (Jksv.IsRunning())
|
||||
while (appletMainLoop() && Jksv.IsRunning())
|
||||
{
|
||||
Jksv.Update();
|
||||
Jksv.Render();
|
||||
}
|
||||
Config::Save();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
#include "Config.hpp"
|
||||
#include "Input.hpp"
|
||||
#include "UI/RenderFunctions.hpp"
|
||||
#include <cmath>
|
||||
|
||||
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<double>(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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 <cmath>
|
||||
|
||||
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<int>(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<int>(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();
|
||||
}
|
||||
}
|
||||
|
||||