Finalize text menu logic. Build with -Werror for better standards.

This commit is contained in:
J-D-K
2024-12-09 11:20:17 -05:00
parent a62665313f
commit da2d004ba6
30 changed files with 364 additions and 134 deletions

View File

@@ -0,0 +1,20 @@
#pragma once
#include "AppStates/AppState.hpp"
#include "SDL.hpp"
#include "UI/Menu.hpp"
class ExtrasMenuState : public AppState
{
public:
ExtrasMenuState(void);
~ExtrasMenuState() {};
void Update(void);
void Render(void);
private:
// Actual menu
UI::Menu m_ExtrasMenu;
// Render target
SDL::SharedTexture m_RenderTarget;
};

View File

@@ -17,4 +17,6 @@ class SettingsState : public AppState
UI::Menu m_SettingsMenu;
// Render target.
SDL::SharedTexture m_RenderTarget = nullptr;
// Control guide X coordinate.
int m_ControlGuideX = 0;
};

View File

@@ -0,0 +1,25 @@
#pragma once
#include "AppStates/TitleSelectCommon.hpp"
#include "Data/Data.hpp"
#include "SDL.hpp"
#include "UI/Menu.hpp"
class TextTitleSelectState : public TitleSelectCommon
{
public:
TextTitleSelectState(Data::User *User);
~TextTitleSelectState() {};
void Update(void);
void Render(void);
void Refresh(void);
private:
// Pointer to user to save.
Data::User *m_User;
// Title select menu
UI::Menu m_TitleSelectMenu;
// Render target
SDL::SharedTexture m_RenderTarget;
};

View File

@@ -0,0 +1,20 @@
#pragma once
#include "AppStates/AppState.hpp"
class TitleSelectCommon : public AppState
{
public:
TitleSelectCommon(void);
virtual ~TitleSelectCommon() {};
virtual void Update(void) = 0;
virtual void Render(void) = 0;
virtual void Refresh(void) = 0;
void RenderControlGuide(void);
protected:
// X coordinate for control guide. Shared between all instances. Only should be calculated once.
static inline int m_TitleControlsX = 0;
};

View File

@@ -1,10 +1,10 @@
#pragma once
#include "AppStates/AppState.hpp"
#include "AppStates/TitleSelectCommon.hpp"
#include "Data/Data.hpp"
#include "SDL.hpp"
#include "UI/TitleView.hpp"
class TitleSelectState : public AppState
class TitleSelectState : public TitleSelectCommon
{
public:
TitleSelectState(Data::User *User);
@@ -13,6 +13,8 @@ class TitleSelectState : public AppState
void Update(void);
void Render(void);
void Refresh(void);
private:
// Save pointer to user
Data::User *m_User = nullptr;
@@ -20,6 +22,4 @@ class TitleSelectState : public AppState
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;
};

View File

@@ -12,6 +12,8 @@ namespace Config
void Save(void);
// Retrieves a value with its key.
uint8_t GetByKey(std::string_view Key);
// Retrieves value by index.
uint8_t GetByIndex(int Index);
// Gets the working directory.
FsLib::Path GetWorkingDirectory(void);
// Gets the UI's transition scaling
@@ -33,6 +35,8 @@ namespace Config
static constexpr std::string_view WorkingDirectory = "WorkingDirectory";
static constexpr std::string_view IncludeDeviceSaves = "IncludeDeviceSaves";
static constexpr std::string_view AutoBackupOnRestore = "AutoBackupOnRestore";
static constexpr std::string_view AutoNameBackups = "AutoNameBackups";
static constexpr std::string_view AutoUpload = "AutoUploadToRemote";
static constexpr std::string_view HoldForDeletion = "HoldForDeletion";
static constexpr std::string_view HoldForRestoration = "HoldForRestoration";
static constexpr std::string_view HoldForOverwrite = "HoldForOverWrite";
@@ -40,13 +44,12 @@ namespace Config
static constexpr std::string_view ListAccountSystemSaves = "ListAccountSystemSaves";
static constexpr std::string_view AllowSystemSaveWriting = "AllowSystemSaveWriting";
static constexpr std::string_view ExportToZip = "ExportToZip";
static constexpr std::string_view TitleSortType = "TitleSortType";
static constexpr std::string_view JKSMTextMode = "JKSMTextMode";
static constexpr std::string_view ForceEnglish = "ForceEnglish";
static constexpr std::string_view EnableTrashBin = "EnableTrash";
static constexpr std::string_view AutoNameBackups = "AutoNameBackups";
static constexpr std::string_view TitleSortType = "TitleSortType";
static constexpr std::string_view UIAnimationScaling = "UIAnimationScaling";
static constexpr std::string_view Favorites = "Favorites";
static constexpr std::string_view BlackList = "BlackList";
static constexpr std::string_view AutoUpload = "AutoUploadToRemote";
static constexpr std::string_view UIAnimationScaling = "UIAnimationScaling";
} // namespace Keys
} // namespace Config

View File

@@ -6,7 +6,7 @@ static inline bool operator==(AccountUid AccountID1, AccountUid AccountID2)
return (AccountID1.uid[0] == AccountID2.uid[0]) && (AccountID1.uid[1] == AccountID2.uid[1]);
}
static inline u128 AccountUIDToU128(AccountUid AccountID)
static inline bool operator==(AccountUid AccountID, u128 u128ID)
{
return (static_cast<u128>(AccountID.uid[0]) << 64 | AccountID.uid[1]);
return AccountID.uid[0] == (u128ID >> 64 & 0xFFFFFFFFFFFFFFFF) && AccountID.uid[1] == (u128ID & 0xFFFFFFFFFFFFFFFF);
}

View File

@@ -15,6 +15,7 @@ namespace Strings
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 ExtrasMenu = "ExtrasMenu";
static constexpr std::string_view OnOff = "OnOff";
} // namespace Names
} // namespace Strings

View File

@@ -7,7 +7,7 @@ namespace UI
class IconMenu : public UI::Menu
{
public:
IconMenu(int X, int Y, int ScrollLength, int RenderTargetHeight);
IconMenu(int X, int Y, int RenderTargetHeight);
~IconMenu() {};
void Update(bool HasFocus);

View File

@@ -10,51 +10,44 @@ namespace UI
class Menu : public UI::Element
{
public:
// Coordinates to render to and dimensions of menu.
Menu(int X, int Y, int Width, int FontSize, int ScrollLength, int RenderTargetHeight);
Menu(int X, int Y, int Width, int FontSize, int RenderTargetHeight);
~Menu() {};
// Required functions from Element.
void Update(bool HasFocus);
void Render(SDL_Texture *Target, bool HasFocus);
// Adds an option to the menu.
void AddOption(std::string_view NewOption);
// Returns the index of the selected item.
int GetSelected(void) const;
// Sets the selected option
void SetSelected(int Selected);
// Resets the menu.
void Reset(void);
protected:
// X and Y coordinates.
double m_X, m_Y;
// Font size
int m_FontSize;
// Selected option.
int m_Selected = 0;
// Color mod for rendering bounding box.
// Color pulse
UI::ColorMod m_ColorMod;
// Actual length of the menu.
int m_OptionsLength = -1;
// Height of options.
// Calculated height of the options.
int m_OptionHeight;
// Total height of menu in pixels.
int m_MenuHeight = 0;
// A small target to render the option to so it can't draw text outside of the bounding area.
// Render target for options so they can't render outside the bounding area.
SDL::SharedTexture m_OptionTarget = nullptr;
private:
// These are used for the scrolling effect.
double m_OriginalY, m_TargetY;
// How many options before scrolling starts happening.
int m_ScrollLength, m_MenuRenderLength;
// The height of the render target for scrolling calculations.
int m_RenderTargetHeight = 0;
// Width.
// Need to preserve the original Y.
double m_OriginalY;
// This is the TargetY the menu catches up to so-to-speak.
double m_TargetY;
// This is calculated according to the render target's length.
int m_ScrollLength;
// Maximum display length of options.
int m_Width;
// Font size.
int m_FontSize;
// Vertical size of the destination render target in pixels.
int m_RenderTargetHeight;
// Maximum number of display options render target can show.
int m_MaxDisplayOptions;
// Vector of options.
std::vector<std::string> m_Options;
};

View File

@@ -23,11 +23,11 @@ namespace UI
// Saves pointer to the user passed.
Data::User *m_User = nullptr;
// Y coordinate.
double m_Y = 38;
double m_Y = 28.0f;
// 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.
double m_SelectedX, m_SelectedY = 38.0f;
double m_SelectedX, m_SelectedY = 28.0f;
// Color mod for pulse.
UI::ColorMod m_ColorMod;
// Vector of tiles.

BIN
JKSV.7z Normal file

Binary file not shown.

View File

@@ -47,9 +47,9 @@ ICON := icon.jpg
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
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)
CFLAGS := $(INCLUDE) -D__SWITCH__ `sdl2-config --cflags` `freetype-config --cflags` \
`curl-config --cflags` -g -Wall -Werror -O2 -ffunction-sections -ffast-math \
$(ARCH) $(DEFINES)
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=c++23

View File

@@ -24,6 +24,7 @@
"Include Device Saves with users: %s",
"Auto-backup on restore: %s",
"Auto-name backups: %s",
"Auto-upload backups to remote storage: %s",
"Hold to delete backups: %s",
"Hold to restore backups: %s",
"Hold to overwrite backups: %s",
@@ -31,9 +32,21 @@
"Show account system saves: %s",
"Enable writing to system saves and NAND: %s",
"Export saves to ZIP: %s",
"Title sort type: %s",
"Text menu (JKSM) mode: %s",
"Force English: %s",
"Enable trash bin: %s",
"Animation scaling: %s"
"Animation scaling: %.02f"
],
"ExtrasMenu" : [
"Reload Titles",
"SD to SD Browser",
"BIS: ProfInfoF",
"BIS: Safe",
"BIS: System",
"BIS: User",
"Terminate Process",
"Mount System Save"
],
"OnOff" : [
"Off",

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,39 @@
#include "AppStates/ExtrasMenuState.hpp"
#include "Colors.hpp"
#include "Input.hpp"
#include "Strings.hpp"
#include <string_view>
namespace
{
constexpr std::string_view SECONDARY_TARGET = "SecondaryTarget";
}
ExtrasMenuState::ExtrasMenuState(void)
: m_ExtrasMenu(32, 8, 1000, 32, 555),
m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET))
{
const char *ExtrasString = nullptr;
int CurrentString = 0;
while ((ExtrasString = Strings::GetByName(Strings::Names::ExtrasMenu, CurrentString++)) != nullptr)
{
m_ExtrasMenu.AddOption(ExtrasString);
}
}
void ExtrasMenuState::Update(void)
{
m_ExtrasMenu.Update(AppState::HasFocus());
if (Input::ButtonPressed(HidNpadButton_B))
{
AppState::Deactivate();
}
}
void ExtrasMenuState::Render(void)
{
m_RenderTarget->Clear(Colors::Transparent);
m_ExtrasMenu.Render(m_RenderTarget->Get(), AppState::HasFocus());
m_RenderTarget->Render(NULL, 201, 91);
}

View File

@@ -1,4 +1,5 @@
#include "AppStates/MainMenuState.hpp"
#include "AppStates/ExtrasMenuState.hpp"
#include "AppStates/SettingsState.hpp"
#include "AppStates/TitleSelectState.hpp"
#include "Colors.hpp"
@@ -9,32 +10,27 @@
#include "SDL.hpp"
#include "Strings.hpp"
namespace
{
// Size of the font to use to make tweaking this easier.
static int ICON_FONT_SIZE = 50;
} // namespace
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(22, m_ControlGuide))
m_Background(SDL::TextureManager::CreateLoadTexture("MainMenuBackground", "romfs:/Textures/MenuBackground.png")), m_MainMenu(50, 15, 555),
m_ControlGuide(Strings::GetByName(Strings::Names::ControlGuides, 0)), m_ControlGuideX(1220 - SDL::Text::GetWidth(22, m_ControlGuide))
{
// Fetch user list.
Data::GetUsers(m_Users);
// Loop through and add icons to menu
// Loop through add user's icon to menu and create states.
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)));
}
// Add the settings and extras.
m_States.push_back(std::make_shared<SettingsState>());
m_States.push_back(std::make_shared<ExtrasMenuState>());
// 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);
m_ExtrasIcon = SDL::TextureManager::CreateLoadTexture("ExtrasIcon", "romfs:/Textures/ExtrasIcon.png");
// Finally add them to the end.
m_MainMenu.AddOption(m_SettingsIcon);
@@ -45,13 +41,13 @@ void MainMenuState::Update(void)
{
m_MainMenu.Update(AppState::HasFocus());
if (Input::ButtonPressed(HidNpadButton_A) && m_MainMenu.GetSelected() < m_Users.size() &&
if (Input::ButtonPressed(HidNpadButton_A) && m_MainMenu.GetSelected() < static_cast<int>(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())
else if (Input::ButtonPressed(HidNpadButton_A) && m_MainMenu.GetSelected() >= static_cast<int>(m_Users.size()))
{
m_States.at(m_MainMenu.GetSelected())->Reactivate();
JKSV::PushState(m_States.at(m_MainMenu.GetSelected()));

View File

@@ -1,6 +1,8 @@
#include "AppStates/SettingsState.hpp"
#include "Colors.hpp"
#include "Config.hpp"
#include "Input.hpp"
#include "StringUtil.hpp"
#include "Strings.hpp"
namespace
@@ -9,17 +11,28 @@ namespace
constexpr std::string_view SECONDARY_TARGET = "SecondaryTarget";
} // namespace
static inline const char *GetValueText(uint8_t Value)
{
return Value == 1 ? Strings::GetByName(Strings::Names::OnOff, 0) : Strings::GetByName(Strings::Names::OnOff, 1);
}
SettingsState::SettingsState(void)
: m_SettingsMenu(32, 18, 1002, 32, 4, 555),
: m_SettingsMenu(32, 8, 1000, 32, 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;
// Add the first two, because they don't have values to display.
m_SettingsMenu.AddOption(Strings::GetByName(Strings::Names::SettingsMenu, 0));
m_SettingsMenu.AddOption(Strings::GetByName(Strings::Names::SettingsMenu, 1));
int CurrentString = 2;
const char *SettingsString = nullptr;
while ((SettingsString = Strings::GetByName(Strings::Names::SettingsMenu, CurrentString++)) != nullptr)
while (CurrentString < 16 && (SettingsString = Strings::GetByName(Strings::Names::SettingsMenu, CurrentString++)) != nullptr)
{
m_SettingsMenu.AddOption(SettingsString);
m_SettingsMenu.AddOption(StringUtil::GetFormattedString(SettingsString, GetValueText(Config::GetByIndex(CurrentString - 1))));
}
// Add the scaling
m_SettingsMenu.AddOption(
StringUtil::GetFormattedString(Strings::GetByName(Strings::Names::SettingsMenu, 17), Config::GetAnimationScaling()));
}
void SettingsState::Update(void)

View File

@@ -0,0 +1,38 @@
#include "AppStates/TextTitleSelectState.hpp"
#include "Colors.hpp"
#include "SDL.hpp"
#include <string_view>
namespace
{
constexpr std::string_view SECONDARY_TARGET = "SecondaryTarget";
}
TextTitleSelectState::TextTitleSelectState(Data::User *User)
: TitleSelectCommon(), m_User(User), m_TitleSelectMenu(32, 8, 1000, 20, 555),
m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET))
{
TextTitleSelectState::Refresh();
}
void TextTitleSelectState::Update(void)
{
m_TitleSelectMenu.Update(AppState::HasFocus());
}
void TextTitleSelectState::Render(void)
{
m_RenderTarget->Clear(Colors::Transparent);
m_TitleSelectMenu.Render(m_RenderTarget->Get(), AppState::HasFocus());
TitleSelectCommon::RenderControlGuide();
m_RenderTarget->Render(NULL, 201, 91);
}
void TextTitleSelectState::Refresh(void)
{
m_TitleSelectMenu.Reset();
for (size_t i = 0; i < m_User->GetTotalDataEntries(); i++)
{
m_TitleSelectMenu.AddOption(Data::GetTitleInfoByID(m_User->GetApplicationIDAt(i))->GetTitle());
}
}

View File

@@ -0,0 +1,26 @@
#include "AppStates/TitleSelectCommon.hpp"
#include "Colors.hpp"
#include "SDL.hpp"
#include "Strings.hpp"
TitleSelectCommon::TitleSelectCommon(void)
{
if (m_TitleControlsX == 0)
{
m_TitleControlsX = 1220 - SDL::Text::GetWidth(22, Strings::GetByName(Strings::Names::ControlGuides, 1));
}
}
void TitleSelectCommon::RenderControlGuide(void)
{
if (AppState::HasFocus())
{
SDL::Text::Render(NULL,
m_TitleControlsX,
673,
22,
SDL::Text::NO_TEXT_WRAP,
Colors::White,
Strings::GetByName(Strings::Names::ControlGuides, 1));
}
}

View File

@@ -13,15 +13,9 @@ namespace
} // namespace
TitleSelectState::TitleSelectState(Data::User *User)
: m_User(User),
: TitleSelectCommon(), 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));
}
}
m_TitleView(m_User) {};
void TitleSelectState::Update(void)
{
@@ -44,16 +38,10 @@ 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));
}
TitleSelectCommon::RenderControlGuide();
m_RenderTarget->Render(NULL, 201, 91);
}
void TitleSelectState::Refresh(void)
{
}

View File

@@ -6,7 +6,6 @@
#include <cstdint>
#include <cstring>
#include <string>
#include <unordered_map>
#include <vector>
namespace
@@ -14,8 +13,8 @@ namespace
// Config path(s)
const char *CONFIG_FOLDER = "sdmc:/config/JKSV";
const char *CONFIG_PATH = "sdmc:/config/JKSV/JKSV.json";
// Map of config values
std::unordered_map<std::string, uint8_t> s_ConfigMap;
// Vector to preserve order now.
std::vector<std::pair<std::string, uint8_t>> s_ConfigVector;
// Working directory
FsLib::Path s_WorkingDirectory;
// UI animation scaling.
@@ -86,7 +85,7 @@ void Config::Initialize(void)
}
else
{
s_ConfigMap[KeyName] = json_object_get_uint64(ConfigValue);
s_ConfigVector.push_back(std::make_pair(KeyName, json_object_get_uint64(ConfigValue)));
}
json_object_iter_next(&ConfigIterator);
}
@@ -95,20 +94,21 @@ void Config::Initialize(void)
void Config::ResetToDefault(void)
{
s_WorkingDirectory = "sdmc:/JKSV";
s_ConfigMap[Config::Keys::IncludeDeviceSaves.data()] = 1;
s_ConfigMap[Config::Keys::AutoBackupOnRestore.data()] = 1;
s_ConfigMap[Config::Keys::HoldForDeletion.data()] = 1;
s_ConfigMap[Config::Keys::HoldForRestoration.data()] = 1;
s_ConfigMap[Config::Keys::HoldForOverwrite.data()] = 1;
s_ConfigMap[Config::Keys::OnlyListMountable.data()] = 1;
s_ConfigMap[Config::Keys::ListAccountSystemSaves.data()] = 0;
s_ConfigMap[Config::Keys::AllowSystemSaveWriting.data()] = 0;
s_ConfigMap[Config::Keys::ExportToZip.data()] = 1;
s_ConfigMap[Config::Keys::ForceEnglish.data()] = 0;
s_ConfigMap[Config::Keys::EnableTrashBin.data()] = 1;
s_ConfigMap[Config::Keys::AutoNameBackups.data()] = 0;
s_ConfigMap[Config::Keys::TitleSortType.data()] = 0;
s_ConfigMap[Config::Keys::AutoUpload.data()] = 0;
s_ConfigVector.push_back(std::make_pair(Config::Keys::IncludeDeviceSaves.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::AutoBackupOnRestore.data(), 1));
s_ConfigVector.push_back(std::make_pair(Config::Keys::AutoNameBackups.data(), 1));
s_ConfigVector.push_back(std::make_pair(Config::Keys::AutoUpload.data(), 1));
s_ConfigVector.push_back(std::make_pair(Config::Keys::HoldForDeletion.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::HoldForRestoration.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::HoldForOverwrite.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::OnlyListMountable.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::ListAccountSystemSaves.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::AllowSystemSaveWriting.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::ExportToZip.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::TitleSortType.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::JKSMTextMode.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::ForceEnglish.data(), 0));
s_ConfigVector.push_back(std::make_pair(Config::Keys::EnableTrashBin.data(), 0));
s_UIAnimationScaling = 2.5f;
}
@@ -121,7 +121,7 @@ void Config::Save(void)
json_object_object_add(ConfigJSON.get(), Config::Keys::WorkingDirectory.data(), WorkingDirectory);
// Loop through map and add it.
for (auto &[Key, Value] : s_ConfigMap)
for (auto &[Key, Value] : s_ConfigVector)
{
json_object *JsonValue = json_object_new_uint64(Value);
json_object_object_add(ConfigJSON.get(), Key.c_str(), JsonValue);
@@ -157,11 +157,23 @@ void Config::Save(void)
uint8_t Config::GetByKey(std::string_view Key)
{
if (s_ConfigMap.find(Key.data()) == s_ConfigMap.end())
auto FindKey = std::find_if(s_ConfigVector.begin(), s_ConfigVector.end(), [Key](const std::pair<std::string, uint8_t> &ConfigPair) {
return Key == ConfigPair.first;
});
if (FindKey == s_ConfigVector.end())
{
return 0;
}
return s_ConfigMap.at(Key.data());
return FindKey->second;
}
uint8_t Config::GetByIndex(int Index)
{
if (Index < 0 || Index >= static_cast<int>(s_ConfigVector.size()))
{
return 0;
}
return s_ConfigVector.at(Index).second;
}
FsLib::Path Config::GetWorkingDirectory(void)

View File

@@ -80,6 +80,38 @@ bool Data::Initialize(void)
while (R_SUCCEEDED(fsSaveDataInfoReaderRead(&SaveInfoReader, &SaveInfo, 1, &TotalEntries)) && TotalEntries > 0)
{
// Skip this stuff
if (!Config::GetByKey(Config::Keys::ListAccountSystemSaves) && SaveInfo.save_data_type == FsSaveDataType_System &&
SaveInfo.uid != 0)
{
continue;
}
switch (SaveInfo.save_data_type)
{
case FsSaveDataType_Bcat:
{
SaveInfo.uid = {FsSaveDataType_Bcat};
}
break;
case FsSaveDataType_Device:
{
SaveInfo.uid = {FsSaveDataType_Device};
}
break;
case FsSaveDataType_Cache:
{
SaveInfo.uid = {FsSaveDataType_Cache};
}
break;
default:
break;
}
auto FindUser = std::find_if(s_UserVector.begin(), s_UserVector.end(), [&SaveInfo](UserIDPair &IDPair) {
return IDPair.first == SaveInfo.uid;
});

View File

@@ -26,8 +26,8 @@ Data::TitleInfo::TitleInfo(uint64_t ApplicationID)
std::memset(&m_NACP, 0x00, sizeof(NacpStruct));
// Sprintf title ids to language entries for safety.
sprintf(m_NACP.lang[SetLanguage_ENUS].name, "%016llX", ApplicationID);
sprintf(m_PathSafeTitle, "%016llX", ApplicationID);
sprintf(m_NACP.lang[SetLanguage_ENUS].name, "%016lX", ApplicationID);
sprintf(m_PathSafeTitle, "%016lX", ApplicationID);
// Create a place holder icon.
int TextX = 128 - (SDL::Text::GetWidth(48, ApplicationIDHex.c_str()) / 2);
@@ -42,7 +42,7 @@ Data::TitleInfo::TitleInfo(uint64_t ApplicationID)
// Get a path safe version of the title.
if (!StringUtil::SanitizeStringForPath(LanguageEntry->name, m_PathSafeTitle, 0x200))
{
std::sprintf(m_PathSafeTitle, "%016llX", ApplicationID);
std::sprintf(m_PathSafeTitle, "%016lX", ApplicationID);
}
// Load the icon.
m_Icon = SDL::TextureManager::CreateLoadTexture(LanguageEntry->name, NsControlData.icon, NsAppControlSize - sizeof(NacpStruct));

View File

@@ -19,7 +19,7 @@
namespace
{
constexpr uint8_t BUILD_MON = 12;
constexpr uint8_t BUILD_DAY = 5;
constexpr uint8_t BUILD_DAY = 9;
constexpr uint16_t BUILD_YEAR = 2024;
} // namespace

View File

@@ -2,7 +2,7 @@
#include "Colors.hpp"
#include "UI/RenderFunctions.hpp"
UI::IconMenu::IconMenu(int X, int Y, int ScrollLength, int RenderTargetHeight) : Menu(X, Y, 152, 88, ScrollLength, RenderTargetHeight) {};
UI::IconMenu::IconMenu(int X, int Y, int RenderTargetHeight) : Menu(X, Y, 152, 80, RenderTargetHeight) {};
void UI::IconMenu::Update(bool HasFocus)
{
@@ -16,7 +16,7 @@ void UI::IconMenu::Render(SDL_Texture *Target, bool 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 < static_cast<int>(m_Options.size()); i++, TempY += m_OptionHeight)
{
// Clear target.
m_OptionTarget->Clear(Colors::Transparent);

View File

@@ -5,15 +5,19 @@
#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(std::ceil(static_cast<double>(FontSize) * 1.8f)), m_TargetY(Y), m_RenderTargetHeight(RenderTargetHeight)
UI::Menu::Menu(int X, int Y, int Width, int FontSize, int RenderTargetHeight)
: m_X(X), m_Y(Y), m_OptionHeight(std::ceil(static_cast<double>(FontSize) * 1.8f)), m_OriginalY(Y), m_TargetY(Y), m_Width(Width),
m_FontSize(FontSize), m_RenderTargetHeight(RenderTargetHeight)
{
// Create render target for options
static int MenuID = 0;
// Create target for menu option
std::string MenuTargetName = "Menu_" + std::to_string(MenuID++);
m_OptionTarget =
SDL::TextureManager::CreateLoadTexture(MenuTargetName, m_Width, m_OptionHeight, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
// Calculate around how many options can be shown on the render target at once.
m_MaxDisplayOptions = (RenderTargetHeight - m_OriginalY) / m_OptionHeight;
m_ScrollLength = std::floor(static_cast<double>(m_MaxDisplayOptions) / 2.0f);
}
void UI::Menu::Update(bool HasFocus)
@@ -24,36 +28,43 @@ void UI::Menu::Update(bool HasFocus)
return;
}
int PreviousSelected = m_Selected;
int OptionsSize = m_Options.size();
if (Input::ButtonPressed(HidNpadButton_AnyUp) && --m_Selected < 0)
{
m_Selected = m_OptionsLength;
m_Selected = OptionsSize - 1;
}
else if (Input::ButtonPressed(HidNpadButton_AnyDown) && ++m_Selected > m_OptionsLength)
else if (Input::ButtonPressed(HidNpadButton_AnyDown) && ++m_Selected >= static_cast<int>(m_Options.size()))
{
m_Selected = 0;
}
else if (Input::ButtonPressed(HidNpadButton_Left) && (m_Selected -= m_ScrollLength) < 0)
else if (Input::ButtonPressed(HidNpadButton_AnyLeft) && (m_Selected -= m_ScrollLength) < 0)
{
m_Selected = 0;
}
else if (Input::ButtonPressed(HidNpadButton_AnyRight) && (m_Selected += m_ScrollLength) > m_OptionsLength)
else if (Input::ButtonPressed(HidNpadButton_AnyRight) && (m_Selected += m_ScrollLength) >= static_cast<int>(m_Options.size()))
{
m_Selected = m_OptionsLength;
m_Selected = OptionsSize - 1;
}
// To do: Refine this further. It's so close.
if (PreviousSelected != m_Selected && m_Selected < m_ScrollLength)
// Don't bother continuing further if there's no reason to scroll.
if (static_cast<int>(m_Options.size()) <= m_MaxDisplayOptions)
{
return;
}
if (m_Selected < m_ScrollLength)
{
m_TargetY = m_OriginalY;
}
else if (PreviousSelected != m_Selected && m_Selected >= m_ScrollLength &&
(m_Selected > PreviousSelected || m_Selected < PreviousSelected) && m_Selected < (m_OptionsLength - m_ScrollLength))
else if (m_Selected >= static_cast<int>(m_Options.size()) - (m_MaxDisplayOptions - m_ScrollLength))
{
m_TargetY = m_OriginalY - ((m_Options.size() - m_MaxDisplayOptions) * m_OptionHeight);
}
else if (m_Selected >= m_ScrollLength)
{
m_TargetY = m_OriginalY - ((m_Selected - m_ScrollLength) * m_OptionHeight);
}
if (m_Y != m_TargetY)
{
m_Y += std::ceil((m_TargetY - m_Y) / Config::GetAnimationScaling());
@@ -72,12 +83,13 @@ void UI::Menu::Render(SDL_Texture *Target, bool HasFocus)
// I hate doing this.
int TargetHeight = 0;
SDL_QueryTexture(Target, NULL, NULL, NULL, &TargetHeight);
for (int i = 0, TempY = m_Y; i <= m_OptionsLength; i++, TempY += m_OptionHeight)
for (int i = 0, TempY = m_Y; i < static_cast<int>(m_Options.size()); i++, TempY += m_OptionHeight)
{
if (TempY < 0 || TempY > TargetHeight)
if (TempY < -m_FontSize)
{
continue;
}
// Clear target texture.
m_OptionTarget->Clear(Colors::Transparent);
@@ -93,11 +105,11 @@ void UI::Menu::Render(SDL_Texture *Target, bool HasFocus)
}
// Render text to target.
SDL::Text::Render(m_OptionTarget->Get(),
20,
28,
(m_OptionHeight / 2) - (m_FontSize / 2),
m_FontSize,
SDL::Text::NO_TEXT_WRAP,
i == m_Selected ? Colors::BlueGreen : Colors::White,
i == m_Selected && HasFocus ? Colors::BlueGreen : Colors::White,
m_Options.at(i).c_str());
// Render target to target
m_OptionTarget->Render(Target, m_X, TempY);
@@ -107,8 +119,6 @@ void UI::Menu::Render(SDL_Texture *Target, bool HasFocus)
void UI::Menu::AddOption(std::string_view NewOption)
{
m_Options.push_back(NewOption.data());
++m_OptionsLength;
m_MenuHeight += m_OptionHeight;
}
int UI::Menu::GetSelected(void) const
@@ -123,6 +133,5 @@ void UI::Menu::SetSelected(int Selected)
void UI::Menu::Reset(void)
{
m_OptionsLength = -1;
m_Options.clear();
}

View File

@@ -34,7 +34,7 @@ void UI::RenderBoundingBox(SDL_Texture *Target, int X, int Y, int Width, int Hei
}
// Setup color.
SDL::Color RenderMod = {(0x88 + ColorMod) << 16 | (0xC5 + (ColorMod / 2)) << 8 | 0xFF};
SDL::Color RenderMod = {static_cast<uint32_t>((0x88 + ColorMod) << 16 | (0xC5 + (ColorMod / 2)) << 8 | 0xFF)};
// This shouldn't fail, but I don't really care if it does.
SDL_SetTextureColorMod(s_MenuBoundingCorners->Get(), RenderMod.RGBA[3], RenderMod.RGBA[2], RenderMod.RGBA[1]);

View File

@@ -55,18 +55,18 @@ void UI::TitleView::Update(bool HasFocus)
}
double Scaling = Config::GetAnimationScaling();
if (m_SelectedY > 280.0f)
if (m_SelectedY > 388.0f)
{
m_Y += std::ceil((280.0f - m_SelectedY) / Scaling);
m_Y += std::ceil((388.0f - m_SelectedY) / Scaling);
}
else if (m_SelectedY < 38.0f)
else if (m_SelectedY < 28.0f)
{
m_Y += std::ceil((38.0f - m_SelectedY) / Scaling);
m_Y += std::ceil((28.0f - m_SelectedY) / Scaling);
}
for (size_t i = 0; i < m_TitleTiles.size(); i++)
{
m_TitleTiles.at(i).Update(m_Selected == i ? true : false);
m_TitleTiles.at(i).Update(m_Selected == static_cast<int>(i) ? true : false);
}
}