Minor code revisions.

This commit is contained in:
J-D-K
2025-09-07 12:31:24 -04:00
parent 700790dba1
commit 1095971895
21 changed files with 139 additions and 98 deletions

View File

@@ -15,15 +15,11 @@ class BaseTask : public BaseState
/// @brief Runs the update routine for rendering the loading glyph animation.
/// @param
void update() override;
virtual void update() = 0;
/// @brief Virtual render function.
virtual void render() = 0;
/// @brief This function renders the loading glyph in the bottom left corner.
/// @note This is mostly just so users don't think JKSV has frozen when operations take a long time.
void render_loading_glyph();
protected:
/// @brief Underlying system task. This needs to be allocated by the derived classes.
std::unique_ptr<sys::Task> m_task{};
@@ -31,6 +27,13 @@ class BaseTask : public BaseState
/// @brief Updates the loading glyph animation.
void update_loading_glyph();
/// @brief Displays the "can't quit JKSV" when plus is pressed.
void pop_on_plus();
/// @brief This function renders the loading glyph in the bottom left corner.
/// @note This is mostly just so users don't think JKSV has frozen when operations take a long time.
void render_loading_glyph();
/// @brief This is the font size used for displaying text during tasks.
static inline constexpr int FONT_SIZE = 20;

View File

@@ -3,6 +3,7 @@
#include "appstates/BaseTask.hpp"
#include "data/DataContext.hpp"
#include "sdl.hpp"
#include "sys/OpTimer.hpp"
#include <functional>
#include <vector>

View File

@@ -18,7 +18,7 @@ namespace fs
~MiniUnzip();
/// @brief Returns whether or not the unzFile was successfully opened.
bool is_open() const;
bool is_open() const noexcept;
/// @brief Attempts to open the path passed as a ZIP file.
bool open(const fslib::Path &path);
@@ -42,13 +42,13 @@ namespace fs
ssize_t read(void *buffer, size_t bufferSize);
/// @brief Returns the name of the current file.
const char *get_filename();
const char *get_filename() const noexcept;
/// @brief Returns the compressed size of the currently open file.
uint64_t get_compressed_size() const;
uint64_t get_compressed_size() const noexcept;
/// @brief Returns the uncompressed size of the the currently open file.
uint64_t get_uncompressed_size() const;
uint64_t get_uncompressed_size() const noexcept;
private:
/// @brief Underlying unzFile.

View File

@@ -20,7 +20,7 @@ namespace fs
/// @brief Returns whether or not the zip file was successfully opened.
/// @return
bool is_open() const;
bool is_open() const noexcept;
/// @brief Opens a Zip file at path
bool open(const fslib::Path &path);

26
include/sys/OpTimer.hpp Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <chrono>
#include <source_location>
namespace sys
{
class OpTimer final
{
public:
/// @brief Starts the operation timer.
OpTimer(const std::source_location &location = std::source_location::current()) noexcept;
/// @brief Ends the timer and
~OpTimer() noexcept;
private:
// Stores a reference to the location passed.
const std::source_location m_location;
/// @brief Stores the time the timer was started.
std::chrono::high_resolution_clock::time_point m_begin{};
/// @brief Returns a string_view containing just the function name. No return type.
std::string_view get_function_name() const noexcept;
};
}

View File

@@ -99,6 +99,9 @@ namespace ui
/// @brief The target Y coordinate the menu should be rendered at.
double m_targetY{};
/// @brief Maximum number of display options render target can show.
int m_maxDisplayOptions{};
/// @brief How many options before scrolling happens.
int m_scrollLength{};
@@ -114,15 +117,15 @@ namespace ui
/// @brief Vertical size of the destination render target in pixels.
int m_renderTargetHeight{};
/// @brief Maximum number of display options render target can show.
int m_maxDisplayOptions{};
/// @brief Vector of options.
std::vector<std::string> m_options{};
/// @brief Text scroll for when the current option is too long to on screen.
std::shared_ptr<ui::TextScroll> m_optionScroll{};
/// @brief Keeps track of the current menu ID for render target.
static inline int sm_menuID{};
/// @brief Updates the text scroll for the currently highlighted option.
void update_scroll_text();

View File

@@ -108,6 +108,9 @@ namespace ui
/// @brief Vector of elements.
std::vector<std::shared_ptr<ui::Element>> m_elements{};
/// @brief Tracks the internal ID of render targets for panels.
static inline int sm_targetID{};
/// @brief Handles sliding out logic.
void slide_out() noexcept;

View File

@@ -16,6 +16,7 @@
#include "sdl.hpp"
#include "strings/strings.hpp"
#include "stringutil.hpp"
#include "sys/OpTimer.hpp"
#include "ui/PopMessageManager.hpp"
#include <chrono>

View File

@@ -8,13 +8,13 @@ BaseState::BaseState(bool isClosable)
: m_isClosable(isClosable)
{
if (m_isClosable) { return; }
error::libnx(appletBeginBlockingHomeButton(0));
error::libnx(appletBeginBlockingHomeButtonShortAndLongPressed(0));
}
BaseState::~BaseState()
{
if (m_isClosable) { return; }
error::libnx(appletEndBlockingHomeButton());
error::libnx(appletEndBlockingHomeButtonShortAndLongPressed());
}
void BaseState::deactivate() { m_isActive = false; }

View File

@@ -13,29 +13,8 @@ namespace
BaseTask::BaseTask()
: BaseState(false)
, m_popUnableExit(strings::get_by_name(strings::names::GENERAL_POPS, 0))
{
m_frameTimer.start(TICKS_GLYPH_TRIGGER);
}
void BaseTask::update()
{
const bool plusPressed = input::button_pressed(HidNpadButton_Plus);
if (!m_task->is_running())
{
BaseState::deactivate();
return;
}
else if (plusPressed) { ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_TICKS, m_popUnableExit); }
BaseTask::update_loading_glyph();
}
void BaseTask::render_loading_glyph()
{
sdl::text::render(sdl::Texture::Null, 56, 673, 32, sdl::text::NO_WRAP, m_colorMod, sm_glyphArray[m_currentFrame]);
}
, m_frameTimer(TICKS_GLYPH_TRIGGER)
, m_popUnableExit(strings::get_by_name(strings::names::GENERAL_POPS, 0)) {};
void BaseTask::update_loading_glyph()
{
@@ -44,3 +23,15 @@ void BaseTask::update_loading_glyph()
if (!m_frameTimer.is_triggered()) { return; }
if (++m_currentFrame % 8 == 0) { m_currentFrame = 0; }
}
void BaseTask::pop_on_plus()
{
const bool plusPressed = input::button_pressed(HidNpadButton_Plus);
if (plusPressed) { ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_TICKS, m_popUnableExit); }
}
void BaseTask::render_loading_glyph()
{
sdl::text::render(sdl::Texture::Null, 56, 673, 32, sdl::text::NO_WRAP, m_colorMod, sm_glyphArray[m_currentFrame]);
}

View File

@@ -14,10 +14,9 @@ FadeState::FadeState(sdl::Color baseColor, uint8_t startAlpha, uint8_t endAlpha,
: m_baseColor(baseColor)
, m_alpha(startAlpha)
, m_endAlpha(endAlpha)
, m_direction(m_endAlpha < m_alpha ? FadeState::Direction::In : FadeState::Direction::Out)
, m_nextState(nextState)
{
m_direction = m_endAlpha < m_alpha ? FadeState::Direction::In : FadeState::Direction::Out;
FadeState::find_divisor();
m_fadeTimer.start(TICKS_TIMER_TRIGGER);
}

View File

@@ -27,6 +27,8 @@ void ProgressState::update()
const double current = task->get_progress();
BaseTask::update_loading_glyph();
BaseTask::pop_on_plus();
if (!m_task->is_running()) { ProgressState::deactivate_state(); }
m_progressBarWidth = std::round(SIZE_BAR_WIDTH * current);

View File

@@ -10,6 +10,7 @@
void TaskState::update()
{
BaseTask::update_loading_glyph();
BaseTask::pop_on_plus();
if (!m_task->is_running()) { TaskState::deactivate_state(); }
}

View File

@@ -41,10 +41,9 @@ data::TitleInfo::TitleInfo(uint64_t applicationID) noexcept
// To do: Make this safer...
data::TitleInfo::TitleInfo(uint64_t applicationID, NsApplicationControlData &controlData) noexcept
: m_applicationID(applicationID)
, m_data(controlData)
, m_hasData(true)
{
m_hasData = true;
m_data = controlData;
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data.nacp, &m_entry));
if (entryError)
{

View File

@@ -33,8 +33,8 @@ namespace
static bool sort_user_data(const data::UserDataEntry &entryA, const data::UserDataEntry &entryB);
data::User::User(AccountUid accountID, FsSaveDataType saveType) noexcept
: m_accountID{accountID}
, m_saveType{saveType}
: m_accountID(accountID)
, m_saveType(saveType)
{
AccountProfile profile{};
AccountProfileBase profileBase{};
@@ -50,11 +50,11 @@ data::User::User(AccountUid accountID,
std::string_view nickname,
std::string_view pathSafeNickname,
FsSaveDataType saveType) noexcept
: m_accountID{accountID}
, m_saveType{saveType}
: m_accountID(accountID)
, m_saveType(saveType)
{
std::memcpy(m_nickname, nickname.data(), nickname.length());
std::memcpy(m_pathSafeNickname, pathSafeNickname.data(), pathSafeNickname.length());
std::strncpy(m_nickname, nickname.data(), nickname.length());
std::strncpy(m_pathSafeNickname, pathSafeNickname.data(), pathSafeNickname.length());
}
data::User::User(data::User &&user) noexcept { *this = std::move(user); }
@@ -72,9 +72,7 @@ data::User &data::User::operator=(data::User &&user) noexcept
user.m_accountID = {0};
user.m_saveType = static_cast<FsSaveDataType>(0);
std::memset(user.m_nickname, 0x00, SIZE_NICKNAME);
std::memset(user.m_pathSafeNickname, 0x00, SIZE_NICKNAME);
user.m_icon = nullptr;
user.m_icon = nullptr;
return *this;
}

View File

@@ -7,7 +7,7 @@ fs::MiniUnzip::MiniUnzip(const fslib::Path &path) { MiniUnzip::open(path); }
fs::MiniUnzip::~MiniUnzip() { MiniUnzip::close(); }
bool fs::MiniUnzip::is_open() const { return m_isOpen; }
bool fs::MiniUnzip::is_open() const noexcept { return m_isOpen; }
bool fs::MiniUnzip::open(const fslib::Path &path)
{
@@ -59,8 +59,8 @@ bool fs::MiniUnzip::reset()
ssize_t fs::MiniUnzip::read(void *buffer, size_t bufferSize) { return unzReadCurrentFile(m_unz, buffer, bufferSize); }
const char *fs::MiniUnzip::get_filename() { return m_filename; }
const char *fs::MiniUnzip::get_filename() const noexcept { return m_filename; }
uint64_t fs::MiniUnzip::get_compressed_size() const { return m_fileInfo.compressed_size; }
uint64_t fs::MiniUnzip::get_compressed_size() const noexcept { return m_fileInfo.compressed_size; }
uint64_t fs::MiniUnzip::get_uncompressed_size() const { return m_fileInfo.uncompressed_size; }
uint64_t fs::MiniUnzip::get_uncompressed_size() const noexcept { return m_fileInfo.uncompressed_size; }

View File

@@ -17,7 +17,7 @@ fs::MiniZip::MiniZip(const fslib::Path &path)
fs::MiniZip::~MiniZip() { MiniZip::close(); }
bool fs::MiniZip::is_open() const { return m_isOpen; }
bool fs::MiniZip::is_open() const noexcept { return m_isOpen; }
bool fs::MiniZip::open(const fslib::Path &path)
{

View File

@@ -7,6 +7,7 @@
#include "logging/logger.hpp"
#include "stringutil.hpp"
#include <array>
#include <map>
#include <string>
#include <unordered_map>
@@ -16,25 +17,24 @@ namespace
// This is the actual map where the strings are.
std::map<std::pair<std::string, int>, std::string> s_stringMap;
// This map is for matching files to the language value
std::unordered_map<SetLanguage, std::string_view> s_fileMap = {{SetLanguage_JA, "JA.json"},
{SetLanguage_ENUS, "ENUS.json"},
{SetLanguage_FR, "FR.json"},
{SetLanguage_DE, "DE.json"},
{SetLanguage_IT, "IT.json"},
{SetLanguage_ES, "ES.json"},
{SetLanguage_ZHCN, "ZHCN.json"},
{SetLanguage_KO, "KO.json"},
{SetLanguage_NL, "NL.json"},
{SetLanguage_PT, "PT.json"},
{SetLanguage_RU, "RU.json"},
{SetLanguage_ZHTW, "ZHTW.json"},
{SetLanguage_ENGB, "ENGB.json"},
{SetLanguage_FRCA, "FRCA.json"},
{SetLanguage_ES419, "ES419.json"},
{SetLanguage_ZHHANS, "ZHCN.json"},
{SetLanguage_ZHHANT, "ZHTW.json"},
{SetLanguage_PTBR, "PTBR.json"}};
const std::array<std::string_view, SetLanguage_Total> PATH_ARRAY = {"JA.json",
"ENUS.json",
"FR.json",
"DE.json",
"IT.json",
"ES.json",
"ZHCN.json",
"KO.json",
"NL.json",
"PT.json",
"RU.json",
"ZHTW.json",
"ENGB.json",
"FRCA.json",
"ES419.json",
"ZHCN.json",
"ZHTW.json",
"PTBR.json"};
} // namespace
// Definitions at bottom.
@@ -84,7 +84,7 @@ const char *strings::get_by_name(std::string_view name, int index) noexcept
const auto findPair = s_stringMap.find(mapPair);
if (findPair == s_stringMap.end()) { return nullptr; }
return s_stringMap.at(mapPair).c_str();
return findPair->second.c_str();
}
static fslib::Path get_file_path()
@@ -98,8 +98,8 @@ static fslib::Path get_file_path()
const bool forceEnglish = config::get_by_key(config::keys::FORCE_ENGLISH);
const bool codeError = error::libnx(setGetLanguageCode(&languageCode));
const bool langError = !codeError && error::libnx(setMakeLanguage(languageCode, &language));
if (forceEnglish || codeError || langError) { returnPath /= s_fileMap[SetLanguage_ENUS]; }
else { returnPath /= s_fileMap[language]; }
if (forceEnglish || codeError || langError) { returnPath /= PATH_ARRAY[SetLanguage_ENUS]; }
else { returnPath /= PATH_ARRAY[language]; }
return returnPath;
}

25
source/sys/OpTimer.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include "sys/OpTimer.hpp"
#include "logging/logger.hpp"
sys::OpTimer::OpTimer(const std::source_location &location) noexcept
: m_location(location)
, m_begin(std::chrono::high_resolution_clock::now()) {};
sys::OpTimer::~OpTimer() noexcept
{
const auto end = std::chrono::high_resolution_clock::now();
const auto diff = std::chrono::duration_cast<std::chrono::microseconds>(end - m_begin);
std::string_view functionName = OpTimer::get_function_name();
logger::log("%s took %lli microseconds.", functionName.data(), diff.count());
}
std::string_view sys::OpTimer::get_function_name() const noexcept
{
std::string_view function = m_location.function_name();
const size_t nameBegin = function.find_first_of(' ');
if (nameBegin != function.npos) { function = function.substr(nameBegin + 1); }
return function;
}

View File

@@ -12,27 +12,19 @@ ui::Menu::Menu(int x, int y, int width, int fontSize, int renderTargetHeight)
: m_x(x)
, m_y(y)
, m_optionHeight(std::round(static_cast<double>(fontSize) * 1.8f))
, m_optionTarget(
sdl::TextureManager::load("MENU_" + std::to_string(sm_menuID++), width, m_optionHeight, SDL_TEXTUREACCESS_TARGET))
, m_boundingBox(ui::BoundingBox::create(0, 0, width + 12, m_optionHeight + 12))
, m_originalY(y)
, m_targetY(y)
, m_maxDisplayOptions((renderTargetHeight - m_originalY) / m_optionHeight)
, m_scrollLength(std::floor(static_cast<double>(m_maxDisplayOptions) / 2))
, m_width(width)
, m_fontSize(fontSize)
, m_textY((m_optionHeight / 2) - (m_fontSize / 2)) // This seems to be the best alignment.
, m_renderTargetHeight(renderTargetHeight)
, m_optionScroll(
ui::TextScroll::create("", 16, 0, m_width, m_optionHeight, m_fontSize, colors::BLUE_GREEN, colors::TRANSPARENT))
{
// Create render target for options
static int MENU_ID = 0;
const std::string menuTargetName = "MENU_" + std::to_string(MENU_ID++);
m_optionTarget = sdl::TextureManager::load(menuTargetName, m_width, m_optionHeight, SDL_TEXTUREACCESS_TARGET);
// Outside the initializer list because I'm tired and don't wanna deal with the headache.
m_boundingBox = ui::BoundingBox::create(0, 0, m_width + 12, m_optionHeight + 12);
// 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);
}
ui::TextScroll::create({}, 16, 0, m_width, m_optionHeight, m_fontSize, colors::BLUE_GREEN, colors::TRANSPARENT)) {};
void ui::Menu::update(bool hasFocus)
{

View File

@@ -17,11 +17,8 @@ ui::SlideOutPanel::SlideOutPanel(int width, Side side)
, m_width(width)
, m_targetX(side == Side::Left ? 0.0f : static_cast<double>(SCREEN_WIDTH) - m_width)
, m_side(side)
{
static int targetID = 0;
std::string targetName = "panelTarget_" + std::to_string(targetID++);
m_renderTarget = sdl::TextureManager::load(targetName, width, 720, SDL_TEXTUREACCESS_TARGET);
}
, m_renderTarget(
sdl::TextureManager::load("PANEL_" + std::to_string(sm_targetID++), m_width, 720, SDL_TEXTUREACCESS_TARGET)) {};
void ui::SlideOutPanel::update(bool hasFocus)
{