Fix system save check.

This commit is contained in:
J-D-K 2025-06-09 18:05:15 -04:00
parent 5d14f26495
commit 95ecbec3e4
12 changed files with 95 additions and 92 deletions

View File

@ -3,7 +3,9 @@
#include "data/data.hpp"
#include "system/Timer.hpp"
#include "ui/SlideOutPanel.hpp"
#include "ui/TextScroll.hpp"
#include <memory>
#include <string>
class TitleInfoState : public AppState
{
@ -14,7 +16,7 @@ class TitleInfoState : public AppState
TitleInfoState(data::User *user, data::TitleInfo *titleInfo);
/// @brief Required destructor.
~TitleInfoState() {};
~TitleInfoState();
/// @brief Runs update routine.
void update(void) override;
@ -29,24 +31,15 @@ class TitleInfoState : public AppState
/// @brief Pointer to title info.
data::TitleInfo *m_titleInfo;
/// @brief Width of titles in pixels.
int m_titleWidth = 0;
/// @brief X coordinate of title text.
int m_titleX = 0;
/// @brief Whether or not the title is too long to fit in the panel and needs to be scrolled.
bool m_titleScrolling = false;
/// @brief Whether or not a scroll has been triggered.
bool m_titleScrollTriggered = false;
/// @brief Timer to scroll title if needed.
sys::Timer m_titleScrollTimer;
/// @brief This is a pointer to the title's icon.
sdl::SharedTexture m_icon;
/// @brief Bool to tell whether or not static members are initialized.
static inline bool sm_initialized = false;
/// @brief This is the render target for the title text just in case it needs scrolling.
static inline sdl::SharedTexture sm_titleTarget = nullptr;
/// @brief Slide panel.
static inline std::unique_ptr<ui::SlideOutPanel> sm_slidePanel = nullptr;
};

View File

@ -24,7 +24,7 @@ class TitleOptionState : public AppState
private:
/// @brief This is just in case the option should only apply to the current user.
data::User *m_targetUser = nullptr;
data::User *m_user = nullptr;
/// @brief This is the target title.
data::TitleInfo *m_titleInfo = nullptr;

View File

@ -23,6 +23,7 @@ namespace strings
static constexpr std::string_view BACKUP_MENU = "BackupMenu";
static constexpr std::string_view COPYING_FILES = "CopyingFiles";
static constexpr std::string_view BACKUPMENU_CONFIRMATIONS = "BackupMenuConfirmations";
static constexpr std::string_view BACKUPMENU_POPS = "BackupMenuPops";
static constexpr std::string_view DELETING_FILES = "DeletingFiles";
static constexpr std::string_view KEYBOARD_STRINGS = "KeyboardStrings";
static constexpr std::string_view USER_OPTIONS = "UserOptions";

View File

@ -58,23 +58,30 @@ namespace ui
/// @brief Returns a pointer to the render target of the panel.
/// @return Raw SDL_Texture pointer to target.
SDL_Texture *get(void);
SDL_Texture *get_target(void);
private:
/// @brief Bool for whether panel is fully open or not.
bool m_isOpen = false;
/// @brief Whether or not to close panel.
bool m_closePanel = false;
/// @brief Current X coordinate to render to. Panels are always 720 pixels in height so no Y is required.
double m_x;
/// @brief Width of the panel in pixels.
int m_width;
/// @brief Target X position of panel.
double m_targetX;
/// @brief Which side the panel is on.
SlideOutPanel::Side m_side;
/// @brief Render target if panel.
sdl::SharedTexture m_renderTarget;
/// @brief Vector of elements.
std::vector<std::shared_ptr<ui::Element>> m_elements;
};

View File

@ -37,20 +37,28 @@ namespace ui
private:
/// @brief Text to display.
std::string m_text;
/// @brief X coordinate to render text at.
int m_x;
/// @brief Y coordinate to render text at.
int m_y;
/// @brief Font size used to calculate and render text.
int m_fontSize = 0;
/// @brief Color used to render the text.
sdl::Color m_textColor;
/// @brief Width of text in pixels.
int m_textWidth = 0;
/// @brief Whether or not text is too wide to fit into the availableWidth passed to the constructor.
bool m_textScrolling = false;
/// @brief Whether or not a scroll was triggered.
bool m_textScrollTriggered = false;
/// @brief Timer for scrolling text.
sys::Timer m_scrollTimer;
};

View File

@ -95,6 +95,9 @@
"Are you sure you really want to restore #%s#?",
"Are you sure you really want to delete #%s#?"
],
"BackupMenuPops": [
"System save data cannot be restored to the system!"
],
"DeletingFiles": [
"Deleting #%s#..."
],

View File

@ -77,7 +77,6 @@ BackupMenuState::BackupMenuState(data::User *user, data::TitleInfo *titleInfo, F
// This needs sm_panelWidth or it'd be in the initializer list.
sm_slidePanel->push_new_element(std::make_shared<ui::TextScroll>(panelString, 22, sm_panelWidth, 8, colors::WHITE));
fslib::Directory saveCheck(fs::DEFAULT_SAVE_ROOT);
m_saveHasData = saveCheck.get_count() > 0;
@ -230,6 +229,7 @@ void BackupMenuState::update(void)
sm_slidePanel->reset();
AppState::deactivate();
}
// Update panel.
sm_slidePanel->update(AppState::has_focus());
// This state bypasses the Slideout panel's normal behavior because it kind of has to.
@ -242,7 +242,7 @@ void BackupMenuState::render(void)
sm_slidePanel->clear_target();
// Grab the render target.
SDL_Texture *slideTarget = sm_slidePanel->get();
SDL_Texture *slideTarget = sm_slidePanel->get_target();
sdl::render_line(slideTarget, 10, 42, sm_panelWidth - 10, 42, colors::WHITE);
sdl::render_line(slideTarget, 10, 648, sm_panelWidth - 10, 648, colors::WHITE);
@ -259,7 +259,7 @@ void BackupMenuState::render(void)
// render menu to it.
sm_backupMenu->render(sm_menuRenderTarget->get(), AppState::has_focus());
// render it to panel target.
sm_menuRenderTarget->render(sm_slidePanel->get(), 0, 43);
sm_menuRenderTarget->render(slideTarget, 0, 43);
sm_slidePanel->render(NULL, AppState::has_focus());
}

View File

@ -98,7 +98,7 @@ void SaveCreateState::render(void)
{
// Clear slide target, render menu, render slide to frame buffer.
sm_slidePanel->clear_target();
m_saveMenu.render(sm_slidePanel->get(), AppState::has_focus());
m_saveMenu.render(sm_slidePanel->get_target(), AppState::has_focus());
sm_slidePanel->render(NULL, AppState::has_focus());
}

View File

@ -3,29 +3,32 @@
#include "input.hpp"
#include "sdl.hpp"
TitleInfoState::TitleInfoState(data::User *user, data::TitleInfo *titleInfo)
: m_user(user), m_titleInfo(titleInfo), m_titleScrollTimer(3000)
namespace
{
/// @brief This is the width of the panel in pixels.
constexpr int SIZE_PANEL_WIDTH = 480;
} // namespace
TitleInfoState::TitleInfoState(data::User *user, data::TitleInfo *titleInfo)
: m_user(user), m_titleInfo(titleInfo), m_icon(m_titleInfo->get_icon())
{
// This needs to be checked. All title information panels share these members.
if (!sm_initialized)
{
// This is the slide panel everything is rendered to.
sm_slidePanel = std::make_unique<ui::SlideOutPanel>(480, ui::SlideOutPanel::Side::Right);
sm_slidePanel = std::make_unique<ui::SlideOutPanel>(SIZE_PANEL_WIDTH, ui::SlideOutPanel::Side::Right);
sm_titleTarget = sdl::TextureManager::create_load_texture("infoTitleTarget",
SIZE_PANEL_WIDTH - 32,
32,
SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
sm_initialized = true;
}
}
// Check if the title is too large to fit within the target.
m_titleWidth = sdl::text::get_width(32, m_titleInfo->get_title());
if (m_titleWidth > 480)
{
// Just set this to 8 and we'll scroll the title.
m_titleX = 8;
m_titleScrolling = true;
}
else
{
// Just center it.
m_titleX = 240 - (m_titleWidth / 2);
}
TitleInfoState::~TitleInfoState()
{
// Clear this so the next time it's called, the vector is cleared.
sm_slidePanel->clear_elements();
}
void TitleInfoState::update(void)
@ -40,21 +43,7 @@ void TitleInfoState::update(void)
else if (sm_slidePanel->is_closed())
{
sm_slidePanel->reset();
}
else if (m_titleScrolling && m_titleScrollTimer.is_triggered())
{
m_titleX -= 2;
m_titleScrollTriggered = true;
}
else if (m_titleScrollTriggered && m_titleX > 8 - m_titleWidth)
{
m_titleX -= 2;
}
else if (m_titleScrollTriggered && m_titleX <= 8 - m_titleWidth)
{
m_titleX = 8;
m_titleScrollTriggered = false;
m_titleScrollTimer.restart();
AppState::deactivate();
}
}
@ -62,10 +51,16 @@ void TitleInfoState::render(void)
{
// Grab the panel's target and clear it. To do: This how I originally intended to.
sm_slidePanel->clear_target();
// SDL_Texture *panelTarget = sm_slidePanel->get();
// If the title doesn't need to be scrolled, just render it.
// Grab the panel target for rendering to.
SDL_Texture *panelTarget = sm_slidePanel->get_target();
// Start by rendering the icon.
m_icon->render(panelTarget, 112, 24);
// Clear the title target and render the text scroll to it.
sm_titleTarget->clear(colors::DIALOG_BOX);
sdl::render_line(sm_slidePanel->get(), 10, 42, 460, 42, colors::WHITE);
sm_slidePanel->render(NULL, AppState::has_focus());
}

View File

@ -1,5 +1,6 @@
#include "appstates/TitleOptionState.hpp"
#include "appstates/ConfirmState.hpp"
#include "appstates/TitleInfoState.hpp"
#include "colors.hpp"
#include "config.hpp"
#include "fs/fs.hpp"
@ -36,7 +37,7 @@ namespace
// Struct to send data to functions that require confirmation.
typedef struct
{
data::User *m_targetUser;
data::User *m_user;
data::TitleInfo *m_targetTitle;
} TargetStruct;
@ -49,8 +50,7 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<Target
static void extend_save_data(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
static void export_svi_file(data::TitleInfo *titleInfo);
TitleOptionState::TitleOptionState(data::User *user, data::TitleInfo *titleInfo)
: m_targetUser(user), m_titleInfo(titleInfo)
TitleOptionState::TitleOptionState(data::User *user, data::TitleInfo *titleInfo) : m_user(user), m_titleInfo(titleInfo)
{
// Create panel if needed.
if (!sm_initialized)
@ -66,6 +66,7 @@ TitleOptionState::TitleOptionState(data::User *user, data::TitleInfo *titleInfo)
{
sm_titleOptionMenu->add_option(currentString);
}
// Only do this once.
sm_initialized = true;
}
@ -83,6 +84,8 @@ void TitleOptionState::update(void)
{
case INFORMATION:
{
// Just push the state.
JKSV::push_state(std::make_shared<TitleInfoState>(m_user, m_titleInfo));
}
break;
@ -145,8 +148,8 @@ void TitleOptionState::update(void)
case RESET_SAVE_DATA:
{
// Need to check this first. For safety.
FsSaveDataInfo *saveInfo = m_targetUser->get_save_info_by_id(m_titleInfo->get_application_id());
if (!config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM) || fs::is_system_save_data(saveInfo))
FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(m_titleInfo->get_application_id());
if (fs::is_system_save_data(saveInfo) && !config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM))
{
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 6));
@ -160,7 +163,7 @@ void TitleOptionState::update(void)
// Data
std::shared_ptr<TargetStruct> data = std::make_shared<TargetStruct>();
data->m_targetUser = m_targetUser;
data->m_user = m_user;
data->m_targetTitle = m_titleInfo;
std::shared_ptr<ConfirmState<sys::Task, TaskState, TargetStruct>> confirm =
@ -175,8 +178,8 @@ void TitleOptionState::update(void)
case DELETE_SAVE_FROM_SYSTEM:
{
FsSaveDataInfo *saveInfo = m_targetUser->get_save_info_by_id(m_titleInfo->get_application_id());
if (!config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM) || fs::is_system_save_data(saveInfo))
FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(m_titleInfo->get_application_id());
if (fs::is_system_save_data(saveInfo) && !config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM))
{
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 6));
@ -186,12 +189,12 @@ void TitleOptionState::update(void)
// String
std::string confirmString = stringutil::get_formatted_string(
strings::get_by_name(strings::names::TITLE_OPTION_CONFIRMATIONS, 3),
m_targetUser->get_nickname(),
m_user->get_nickname(),
m_titleInfo->get_title());
// Data
std::shared_ptr<TargetStruct> data = std::make_shared<TargetStruct>();
data->m_targetUser = m_targetUser;
data->m_user = m_user;
data->m_targetTitle = m_titleInfo;
// Confirmation.
@ -207,8 +210,8 @@ void TitleOptionState::update(void)
case EXTEND_CONTAINER:
{
FsSaveDataInfo *saveInfo = m_targetUser->get_save_info_by_id(m_titleInfo->get_application_id());
if (!config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM) || fs::is_system_save_data(saveInfo))
FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(m_titleInfo->get_application_id());
if (fs::is_system_save_data(saveInfo) && !config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM))
{
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 6));
@ -217,7 +220,7 @@ void TitleOptionState::update(void)
// Data
std::shared_ptr<TargetStruct> data = std::make_shared<TargetStruct>();
data->m_targetUser = m_targetUser;
data->m_user = m_user;
data->m_targetTitle = m_titleInfo;
// State.
@ -228,7 +231,7 @@ void TitleOptionState::update(void)
case EXPORT_SVI:
{
// This type of save data can't have this exported anyway.
FsSaveDataInfo *saveInfo = m_targetUser->get_save_info_by_id(m_titleInfo->get_application_id());
FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(m_titleInfo->get_application_id());
if (fs::is_system_save_data(saveInfo))
{
return;
@ -254,7 +257,7 @@ void TitleOptionState::update(void)
void TitleOptionState::render(void)
{
sm_slidePanel->clear_target();
sm_titleOptionMenu->render(sm_slidePanel->get(), AppState::has_focus());
sm_titleOptionMenu->render(sm_slidePanel->get_target(), AppState::has_focus());
sm_slidePanel->render(NULL, AppState::has_focus());
}
@ -339,7 +342,7 @@ static void reset_save_data(sys::Task *task, std::shared_ptr<TargetStruct> dataS
// Attempt to mount save.
if (!fslib::open_save_data_with_save_info(
fs::DEFAULT_SAVE_MOUNT,
*dataStruct->m_targetUser->get_save_info_by_id(dataStruct->m_targetTitle->get_application_id())))
*dataStruct->m_user->get_save_info_by_id(dataStruct->m_targetTitle->get_application_id())))
{
logger::log(ERROR_RESETTING_SAVE, fslib::get_error_string());
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
@ -381,12 +384,12 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<Target
{
// Set the status in case this takes a little while.
task->set_status(strings::get_by_name(strings::names::TITLE_OPTION_STATUS, 2),
dataStruct->m_targetUser->get_nickname(),
dataStruct->m_user->get_nickname(),
dataStruct->m_targetTitle->get_title());
// Grab the save data info pointer.
uint64_t applicationID = dataStruct->m_targetTitle->get_application_id();
FsSaveDataInfo *saveInfo = dataStruct->m_targetUser->get_save_info_by_id(applicationID);
FsSaveDataInfo *saveInfo = dataStruct->m_user->get_save_info_by_id(applicationID);
if (saveInfo == nullptr)
{
logger::log("Error deleting save data for user. Target save data null?");
@ -402,7 +405,7 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<Target
}
// Erase the info from the user since it should have been deleted.
dataStruct->m_targetUser->erase_save_info_by_id(applicationID);
dataStruct->m_user->erase_save_info_by_id(applicationID);
// Done?
task->finished();
@ -412,7 +415,7 @@ static void extend_save_data(sys::Task *task, std::shared_ptr<TargetStruct> data
{
// This is just to make stuff easier to read.
data::TitleInfo *titleInfo = dataStruct->m_targetTitle;
FsSaveDataInfo *saveInfo = dataStruct->m_targetUser->get_save_info_by_id(titleInfo->get_application_id());
FsSaveDataInfo *saveInfo = dataStruct->m_user->get_save_info_by_id(titleInfo->get_application_id());
if (!saveInfo)
{
logger::log("Error retrieving save data info to extend!");
@ -423,7 +426,7 @@ static void extend_save_data(sys::Task *task, std::shared_ptr<TargetStruct> data
// Set the status.
task->set_status(strings::get_by_name(strings::names::TITLE_OPTION_STATUS, 3),
dataStruct->m_targetUser->get_nickname(),
dataStruct->m_user->get_nickname(),
dataStruct->m_targetTitle->get_title());
// This is the header string.
@ -490,10 +493,3 @@ static void export_svi_file(data::TitleInfo *titleInfo)
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 4));
}
static bool is_system_save_data(const FsSaveDataInfo *saveInfo)
{
// The config setting will override this
return config::get_by_key(config::keys::ALLOW_WRITING_TO_SYSTEM) ||
saveInfo->save_data_type == FsSaveDataType_System || saveInfo->save_data_type == FsSaveDataType_SystemBcat;
}

View File

@ -30,7 +30,7 @@ namespace
// Struct to pass data to functions that require it.
typedef struct
{
data::User *m_targetUser;
data::User *m_user;
} UserStruct;
// Declarations here. Defintions after class.
@ -75,7 +75,7 @@ void UserOptionState::update(void)
// Data to send if confirmed.
std::shared_ptr<UserStruct> dataStruct(new UserStruct);
dataStruct->m_targetUser = m_user;
dataStruct->m_user = m_user;
// State to push
auto confirmBackupAll =
@ -102,7 +102,7 @@ void UserOptionState::update(void)
m_user->get_nickname());
std::shared_ptr<UserStruct> dataStruct(new UserStruct);
dataStruct->m_targetUser = m_user;
dataStruct->m_user = m_user;
auto confirmCreateAll =
std::make_shared<ConfirmState<sys::Task, TaskState, UserStruct>>(queryString,
@ -122,7 +122,7 @@ void UserOptionState::update(void)
m_user->get_nickname());
std::shared_ptr<UserStruct> dataStruct(new UserStruct);
dataStruct->m_targetUser = m_user;
dataStruct->m_user = m_user;
auto confirmDeleteAll =
std::make_shared<ConfirmState<sys::Task, TaskState, UserStruct>>(queryString,
@ -155,13 +155,13 @@ void UserOptionState::render(void)
// Render panel.
m_menuPanel->clear_target();
m_userOptionMenu.render(m_menuPanel->get(), AppState::has_focus());
m_userOptionMenu.render(m_menuPanel->get_target(), AppState::has_focus());
m_menuPanel->render(NULL, AppState::has_focus());
}
static void backup_all_for_user(sys::ProgressTask *task, std::shared_ptr<UserStruct> dataStruct)
{
data::User *targetUser = dataStruct->m_targetUser;
data::User *targetUser = dataStruct->m_user;
for (size_t i = 0; i < targetUser->get_total_data_entries(); i++)
{
@ -237,7 +237,7 @@ static void backup_all_for_user(sys::ProgressTask *task, std::shared_ptr<UserStr
static void create_all_save_data_for_user(sys::Task *task, std::shared_ptr<UserStruct> dataStruct)
{
data::User *targetUser = dataStruct->m_targetUser;
data::User *targetUser = dataStruct->m_user;
// Get title info map.
auto &titleInfoMap = data::get_title_info_map();
@ -265,7 +265,7 @@ static void create_all_save_data_for_user(sys::Task *task, std::shared_ptr<UserS
static void delete_all_save_data_for_user(sys::Task *task, std::shared_ptr<UserStruct> dataStruct)
{
data::User *targetUser = dataStruct->m_targetUser;
data::User *targetUser = dataStruct->m_user;
for (size_t i = 0; i < targetUser->get_total_data_entries(); i++)
{

View File

@ -96,7 +96,7 @@ void ui::SlideOutPanel::clear_elements(void)
m_elements.clear();
}
SDL_Texture *ui::SlideOutPanel::get(void)
SDL_Texture *ui::SlideOutPanel::get_target(void)
{
return m_renderTarget->get();
}