Tonight's progress

This commit is contained in:
J-D-K 2024-12-09 21:17:47 -05:00
parent da2d004ba6
commit 0b503b6324
21 changed files with 331 additions and 21 deletions

View File

@ -0,0 +1,39 @@
#pragma once
#include "AppStates/AppState.hpp"
#include "Data/Data.hpp"
#include "FsLib.hpp"
#include "UI/Menu.hpp"
#include "UI/RenderTarget.hpp"
#include "UI/SlideOutPanel.hpp"
class BackupMenuState : public AppState
{
public:
BackupMenuState(Data::User *User, Data::TitleInfo *TitleInfo);
~BackupMenuState() {};
void Update(void);
void Render(void);
// Refreshes/Updates menu and listing.
void RefreshListing(void);
private:
// Pointer to user.
Data::User *m_User;
// Pointer to title info.
Data::TitleInfo *m_TitleInfo;
// Backup folder path
FsLib::Path m_DirectoryPath;
// Directory listing of that folder.
FsLib::Directory m_DirectoryListing;
// Menu
UI::Menu m_BackupMenu;
// Render target for menu.
UI::RenderTarget m_MenuTarget;
// Slide panel.
UI::SlideOutPanel m_SlidePanel;
// Width of panel.
static inline int m_PanelWidth = 0;
// X coordinate of text above menu.
static inline int m_CurrentBackupsCoordinate = 0;
};

View File

@ -13,6 +13,9 @@ class MainMenuState : public AppState
void Update(void);
void Render(void);
// This allows other parts of the program to signal to this one to refresh the view states on the next Update() call.
static void RefreshViewStates(void);
private:
// The render target.
SDL::SharedTexture m_RenderTarget = nullptr;
@ -24,11 +27,13 @@ class MainMenuState : public AppState
// Icon menu for users
UI::IconMenu m_MainMenu;
// Vector of pointers to users.
std::vector<Data::User *> m_Users;
static inline std::vector<Data::User *> m_Users;
// Vector of view states for each user, settings, and extras
std::vector<std::shared_ptr<AppState>> m_States;
static inline 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.
int m_ControlGuideX;
// Variable that holds refresh signal.
static inline bool m_RefreshNeeded = false;
};

View File

@ -17,5 +17,6 @@ namespace Strings
static constexpr std::string_view SettingsMenu = "SettingsMenu";
static constexpr std::string_view ExtrasMenu = "ExtrasMenu";
static constexpr std::string_view OnOff = "OnOff";
static constexpr std::string_view BackupMenu = "BackupMenu";
} // namespace Names
} // namespace Strings

View File

@ -0,0 +1,25 @@
#pragma once
#include "SDL.hpp"
#include "UI/Element.hpp"
// This class serves no purpose other than to wrap a sub-render target in an element for slide out panels.
namespace UI
{
class RenderTarget : UI::Element
{
public:
RenderTarget(int X, int Y, int Width, int Height);
~RenderTarget() {};
void Update(bool HasFocus) {};
void Render(SDL_Texture *Target, bool HasFocus);
SDL_Texture *Get(void);
private:
// Coordinates
int m_X, m_Y;
// Underlying SDL::SharedTexture
SDL::SharedTexture m_RenderTarget;
};
} // namespace UI

View File

@ -0,0 +1,45 @@
#pragma once
#include "SDL.hpp"
#include "UI/Element.hpp"
#include <vector>
namespace UI
{
class SlideOutPanel : public UI::Element
{
public:
// Which side the panel the slides out from.
enum class Side
{
Left,
Right
};
// Width of panel, which side it "spawns" from.
SlideOutPanel(int Width, SlideOutPanel::Side Side);
~SlideOutPanel() {};
void Update(bool HasFocus);
void Render(SDL_Texture *Target, bool HasFocus);
// Closes panel.
void Close(void);
// Returns whether or not panel is fully open.
bool IsOpen(void) const;
// Adds new element to vector.
void PushNewElement(std::shared_ptr<UI::Element> NewElement);
// Returns pointer to render target to allow rendering besides elements pushed.
SDL_Texture *Get(void);
private:
// X coordinate
double m_X;
// Side the panel spawned from.
SlideOutPanel::Side m_Side;
// Vector of elements.
std::vector<std::shared_ptr<UI::Element>> m_Elements;
// Bool for whether panel is open or not.
bool m_IsOpen = false;
// Render target
SDL::SharedTexture m_RenderTarget;
};
} // namespace UI

View File

@ -16,6 +16,8 @@ namespace UI
void Render(SDL_Texture *Target, bool HasFocus);
// Returns index of selected title.
int GetSelected(void) const;
// Refreshes the view using m_User
void Refresh(void);
// Resets all tiles to 128x128
void Reset(void);

BIN
JKSV.7z

Binary file not shown.

@ -1 +1 @@
Subproject commit 3ffe1c9038227f6aa7cecb8e38be8a62ea263254
Subproject commit eba5d13d1c20c96d4e848f0ae1153e2740099213

View File

@ -51,5 +51,9 @@
"OnOff" : [
"Off",
">On>"
],
"BackupMenu" : [
"Current Backups:",
"New Backup"
]
}

View File

@ -0,0 +1,40 @@
#include "AppStates/BackupMenuState.hpp"
#include "Config.hpp"
#include "SDL.hpp"
#include "Strings.hpp"
BackupMenuState::BackupMenuState(Data::User *User, Data::TitleInfo *TitleInfo)
: m_User(User), m_TitleInfo(TitleInfo), m_DirectoryPath(Config::GetWorkingDirectory() / m_TitleInfo->GetPathSafeTitle())
{
// Calculate these if they weren't already by a previous instance.
if (m_PanelWidth == 0 || m_CurrentBackupsCoordinate == 0)
{
m_PanelWidth = SDL::Text::GetWidth(22, Strings::GetByName(Strings::Names::ControlGuides, 2)) + 64;
m_CurrentBackupsCoordinate = (m_PanelWidth / 2) - (SDL::Text::GetWidth(28, Strings::GetByName(Strings::Names::BackupMenu, 0)) / 2);
}
BackupMenuState::RefreshListing();
}
void BackupMenuState::Update(void)
{
}
void BackupMenuState::Render(void)
{
}
void BackupMenuState::RefreshListing(void)
{
m_DirectoryListing.Open(m_DirectoryPath);
if (!m_DirectoryListing.IsOpen())
{
return false;
}
m_BackupMenu.Reset();
for (int64_t i = 0; i < m_DirectoryListing.GetEntryCount(); i++)
{
m_BackupMenu.AddOption(m_DirectoryListing[i]);
}
}

View File

@ -10,7 +10,7 @@ namespace
}
ExtrasMenuState::ExtrasMenuState(void)
: m_ExtrasMenu(32, 8, 1000, 32, 555),
: m_ExtrasMenu(32, 8, 1000, 24, 555),
m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET))
{
const char *ExtrasString = nullptr;

View File

@ -1,6 +1,8 @@
#include "AppStates/MainMenuState.hpp"
#include "AppStates/ExtrasMenuState.hpp"
#include "AppStates/SettingsState.hpp"
#include "AppStates/TextTitleSelectState.hpp"
#include "AppStates/TitleSelectCommon.hpp"
#include "AppStates/TitleSelectState.hpp"
#include "Colors.hpp"
#include "Config.hpp"
@ -22,7 +24,15 @@ 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)));
if (Config::GetByKey(Config::Keys::JKSMTextMode))
{
m_States.push_back(std::make_shared<TextTitleSelectState>(m_Users.at(i)));
}
else
{
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>());
@ -70,3 +80,12 @@ void MainMenuState::Render(void)
SDL::Text::Render(NULL, m_ControlGuideX, 673, 22, SDL::Text::NO_TEXT_WRAP, Colors::White, m_ControlGuide);
}
}
void MainMenuState::RefreshViewStates(void)
{
for (size_t i = 0; i < m_Users.size(); i++)
{
m_Users.at(i)->SortData();
std::static_pointer_cast<TitleSelectCommon>(m_States.at(i))->Refresh();
}
}

View File

@ -17,7 +17,7 @@ static inline const char *GetValueText(uint8_t Value)
}
SettingsState::SettingsState(void)
: m_SettingsMenu(32, 8, 1000, 32, 555),
: m_SettingsMenu(32, 8, 1000, 24, 555),
m_RenderTarget(SDL::TextureManager::CreateLoadTexture(SECONDARY_TARGET, 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET))
{
// Add the first two, because they don't have values to display.

View File

@ -1,5 +1,8 @@
#include "AppStates/TextTitleSelectState.hpp"
#include "AppStates/MainMenuState.hpp"
#include "Colors.hpp"
#include "Config.hpp"
#include "Input.hpp"
#include "SDL.hpp"
#include <string_view>
@ -18,6 +21,16 @@ TextTitleSelectState::TextTitleSelectState(Data::User *User)
void TextTitleSelectState::Update(void)
{
m_TitleSelectMenu.Update(AppState::HasFocus());
if (Input::ButtonPressed(HidNpadButton_Y))
{
Config::AddRemoveFavorite(m_User->GetApplicationIDAt(m_TitleSelectMenu.GetSelected()));
MainMenuState::RefreshViewStates();
}
else if (Input::ButtonPressed(HidNpadButton_B))
{
AppState::Deactivate();
}
}
void TextTitleSelectState::Render(void)
@ -33,6 +46,17 @@ 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());
std::string Option;
uint64_t ApplicationID = m_User->GetApplicationIDAt(i);
const char *Title = Data::GetTitleInfoByID(ApplicationID)->GetTitle();
if (Config::IsFavorite(ApplicationID))
{
Option = std::string("^\uE017^ ") + Title;
}
else
{
Option = Title;
}
m_TitleSelectMenu.AddOption(Option.c_str());
}
}

View File

@ -1,4 +1,5 @@
#include "AppStates/TitleSelectState.hpp"
#include "AppStates/MainMenuState.hpp"
#include "Colors.hpp"
#include "Config.hpp"
#include "Input.hpp"
@ -29,8 +30,9 @@ void TitleSelectState::Update(void)
}
else if (Input::ButtonPressed(HidNpadButton_Y))
{
uint64_t ApplicationID = m_User->GetApplicationIDAt(m_TitleView.GetSelected());
Config::AddRemoveFavorite(ApplicationID);
Config::AddRemoveFavorite(m_User->GetApplicationIDAt(m_TitleView.GetSelected()));
// MainMenuState has all the Users and views, so have it refresh.
MainMenuState::RefreshViewStates();
}
}
@ -44,4 +46,5 @@ void TitleSelectState::Render(void)
void TitleSelectState::Refresh(void)
{
m_TitleView.Refresh();
}

View File

@ -80,6 +80,7 @@ JKSV::JKSV(void)
SDL::Text::AddColorCharacter(L'*', Colors::Red);
SDL::Text::AddColorCharacter(L'<', Colors::Yellow);
SDL::Text::AddColorCharacter(L'>', Colors::Green);
SDL::Text::AddColorCharacter(L'^', Colors::Pink);
// This is to check whether the author wanted credit for their work.
m_ShowTranslationInfo = std::char_traits<char>::compare(Strings::GetByName(Strings::Names::TranslationInfo, 1), "NULL", 4) != 0;

View File

@ -26,7 +26,7 @@ void UI::IconMenu::Render(SDL_Texture *Target, bool HasFocus)
{
UI::RenderBoundingBox(Target, m_X - 8, TempY - 8, 152, 146, m_ColorMod);
}
SDL::RenderRectFill(m_OptionTarget->Get(), 0, 0, 6, 130, {0x00FFC5FF});
SDL::RenderRectFill(m_OptionTarget->Get(), 0, 0, 4, 130, {0x00FFC5FF});
}
//m_Options.at(i)->Render(m_OptionTarget->Get(), 0, 0);
m_Options.at(i)->RenderStretched(m_OptionTarget->Get(), 8, 1, 128, 128);

View File

@ -33,7 +33,7 @@ void UI::Menu::Update(bool HasFocus)
{
m_Selected = OptionsSize - 1;
}
else if (Input::ButtonPressed(HidNpadButton_AnyDown) && ++m_Selected >= static_cast<int>(m_Options.size()))
else if (Input::ButtonPressed(HidNpadButton_AnyDown) && ++m_Selected >= OptionsSize)
{
m_Selected = 0;
}
@ -41,7 +41,15 @@ void UI::Menu::Update(bool HasFocus)
{
m_Selected = 0;
}
else if (Input::ButtonPressed(HidNpadButton_AnyRight) && (m_Selected += m_ScrollLength) >= static_cast<int>(m_Options.size()))
else if (Input::ButtonPressed(HidNpadButton_AnyRight) && (m_Selected += m_ScrollLength) >= OptionsSize)
{
m_Selected = OptionsSize - 1;
}
else if (Input::ButtonPressed(HidNpadButton_L) && (m_Selected -= m_ScrollLength * 3) < 0)
{
m_Selected = 0;
}
else if (Input::ButtonPressed(HidNpadButton_R) && (m_Selected += m_ScrollLength * 3) >= OptionsSize)
{
m_Selected = OptionsSize - 1;
}
@ -101,11 +109,11 @@ void UI::Menu::Render(SDL_Texture *Target, bool HasFocus)
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, 8, 6, m_OptionHeight - 16, Colors::BlueGreen);
SDL::RenderRectFill(m_OptionTarget->Get(), 8, 8, 4, m_OptionHeight - 16, Colors::BlueGreen);
}
// Render text to target.
SDL::Text::Render(m_OptionTarget->Get(),
28,
24,
(m_OptionHeight / 2) - (m_FontSize / 2),
m_FontSize,
SDL::Text::NO_TEXT_WRAP,

View File

@ -0,0 +1,18 @@
#include "UI/RenderTarget.hpp"
UI::RenderTarget::RenderTarget(int X, int Y, int Width, int Height) : m_X(X), m_Y(Y)
{
static int RenderTargetID = 0;
std::string TargetName = "RenderTarget_" + std::to_string(RenderTargetID++);
m_RenderTarget = SDL::TextureManager::CreateLoadTexture(TargetName, Width, Height, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
}
void UI::RenderTarget::Render(SDL_Texture *Target, bool HasFocus)
{
m_RenderTarget->Render(Target, m_X, m_Y);
}
SDL_Texture *UI::RenderTarget::Get(void)
{
return m_RenderTarget->Get();
}

View File

@ -0,0 +1,62 @@
#include "UI/SlideOutPanel.hpp"
#include "Config.hpp"
UI::SlideOutPanel::SlideOutPanel(int Width, SlideOutPanel::Side Side) : m_X(Side == Side::Left ? -Width : 1280), m_Side(Side)
{
static int SlidePanelTargetID = 0;
std::string PanelTargetName = "PanelTarget_" + std::to_string(SlidePanelTargetID++);
m_RenderTarget = SDL::TextureManager::CreateLoadTexture(PanelTargetName, Width, 720, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
}
void UI::SlideOutPanel::Update(bool HasFocus)
{
double Scaling = Config::GetAnimationScaling();
if (m_Side == Side::Left && m_X < 0)
{
m_X += m_X / Scaling;
}
else if (m_Side == Side::Right && m_X > 1280)
{
m_X -= m_X / Scaling;
}
else
{
m_IsOpen = true;
}
if (HasFocus && m_IsOpen)
{
for (auto &CurrentElement : m_Elements)
{
CurrentElement->Update(HasFocus);
}
}
}
void UI::SlideOutPanel::Render(SDL_Texture *Target, bool HasFocus)
{
for (auto &CurrentElement : m_Elements)
{
CurrentElement->Render(m_RenderTarget->Get(), HasFocus);
}
m_RenderTarget->Render(NULL, m_X, 0);
}
void UI::SlideOutPanel::Close(void)
{
}
bool UI::SlideOutPanel::IsOpen(void) const
{
return m_IsOpen;
}
void UI::SlideOutPanel::PushNewElement(std::shared_ptr<UI::Element> NewElement)
{
m_Elements.push_back(NewElement);
}
SDL_Texture *UI::SlideOutPanel::Get(void)
{
return m_RenderTarget->Get();
}

View File

@ -13,13 +13,7 @@ namespace
UI::TitleView::TitleView(Data::User *User) : m_User(User)
{
for (size_t i = 0; i < m_User->GetTotalDataEntries(); i++)
{
// Get pointer to data from user save index I.
Data::TitleInfo *CurrentTitleInfo = Data::GetTitleInfoByID(m_User->GetApplicationIDAt(i));
// Emplace is faster than push
m_TitleTiles.emplace_back(Config::IsFavorite(m_User->GetApplicationIDAt(i)), CurrentTitleInfo->GetIcon());
}
TitleView::Refresh();
}
void UI::TitleView::Update(bool HasFocus)
@ -53,6 +47,14 @@ void UI::TitleView::Update(bool HasFocus)
{
++m_Selected;
}
else if (Input::ButtonPressed(HidNpadButton_L) && (m_Selected -= 21) < 0)
{
m_Selected = 0;
}
else if (Input::ButtonPressed(HidNpadButton_R) && (m_Selected += 21) > TotalTiles)
{
m_Selected = TotalTiles;
}
double Scaling = Config::GetAnimationScaling();
if (m_SelectedY > 388.0f)
@ -112,6 +114,18 @@ int UI::TitleView::GetSelected(void) const
return m_Selected;
}
void UI::TitleView::Refresh(void)
{
m_TitleTiles.clear();
for (size_t i = 0; i < m_User->GetTotalDataEntries(); i++)
{
// Get pointer to data from user save index I.
Data::TitleInfo *CurrentTitleInfo = Data::GetTitleInfoByID(m_User->GetApplicationIDAt(i));
// Emplace is faster than push
m_TitleTiles.emplace_back(Config::IsFavorite(m_User->GetApplicationIDAt(i)), CurrentTitleInfo->GetIcon());
}
}
void UI::TitleView::Reset(void)
{
for (UI::TitleTile &CurrentTile : m_TitleTiles)