mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-09-12 20:45:11 -05:00
Minor code revisions.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "appstates/BaseTask.hpp"
|
||||
#include "data/DataContext.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "sys/OpTimer.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
26
include/sys/OpTimer.hpp
Normal 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;
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "sdl.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "sys/OpTimer.hpp"
|
||||
#include "ui/PopMessageManager.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
void TaskState::update()
|
||||
{
|
||||
BaseTask::update_loading_glyph();
|
||||
BaseTask::pop_on_plus();
|
||||
if (!m_task->is_running()) { TaskState::deactivate_state(); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
25
source/sys/OpTimer.cpp
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user