rpcsx/rpcs3/Emu/RSX/Overlays/overlay_save_dialog.cpp

335 lines
9 KiB
C++
Raw Normal View History

2020-12-05 13:08:24 +01:00
#include "stdafx.h"
2020-02-25 22:42:29 +01:00
#include "overlay_save_dialog.h"
2020-02-22 20:42:49 +01:00
#include "Utilities/date_time.h"
2021-10-31 00:48:41 +02:00
#include "Emu/System.h"
2022-02-05 21:15:45 +01:00
#include "Emu/RSX/RSXThread.h"
2019-05-16 22:48:05 +02:00
namespace rsx
{
namespace overlays
{
save_dialog::save_dialog_entry::save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf)
{
std::unique_ptr<overlay_element> image = std::make_unique<image_view>();
image->set_size(160, 110);
image->set_padding(36, 36, 11, 11); // Square image, 88x88
if (resource_id != image_resource_id::raw_image)
{
static_cast<image_view*>(image.get())->set_image_resource(resource_id);
}
else if (!icon_buf.empty())
2019-05-16 22:48:05 +02:00
{
image->set_padding(0, 0, 11, 11); // Half sized icon, 320x176->160x88
icon_data = std::make_unique<image_info>(icon_buf);
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
}
else
{
// Fallback
static_cast<image_view*>(image.get())->set_image_resource(resource_config::standard_image_resource::save);
}
std::unique_ptr<overlay_element> text_stack = std::make_unique<vertical_layout>();
std::unique_ptr<overlay_element> padding = std::make_unique<spacer>();
std::unique_ptr<overlay_element> header_text = std::make_unique<label>(text1);
std::unique_ptr<overlay_element> subtext = std::make_unique<label>(text2);
2019-05-16 22:48:05 +02:00
padding->set_size(1, 1);
header_text->set_size(800, 40);
header_text->set_font("Arial", 16);
header_text->set_wrap_text(true);
subtext->set_size(800, 0);
subtext->set_font("Arial", 14);
subtext->set_wrap_text(true);
static_cast<label*>(subtext.get())->auto_resize(true);
// Make back color transparent for text
header_text->back_color.a = 0.f;
subtext->back_color.a = 0.f;
static_cast<vertical_layout*>(text_stack.get())->pack_padding = 5;
static_cast<vertical_layout*>(text_stack.get())->add_element(padding);
static_cast<vertical_layout*>(text_stack.get())->add_element(header_text);
static_cast<vertical_layout*>(text_stack.get())->add_element(subtext);
if (!text3.empty())
{
// Detail info actually exists
std::unique_ptr<overlay_element> detail = std::make_unique<label>(text3);
2019-05-16 22:48:05 +02:00
detail->set_size(800, 0);
detail->set_font("Arial", 12);
detail->set_wrap_text(true);
detail->back_color.a = 0.f;
static_cast<label*>(detail.get())->auto_resize(true);
static_cast<vertical_layout*>(text_stack.get())->add_element(detail);
}
if (text_stack->h > image->h)
{
std::unique_ptr<overlay_element> padding2 = std::make_unique<spacer>();
padding2->set_size(1, 5);
static_cast<vertical_layout*>(text_stack.get())->add_element(padding2);
}
// Pack
this->pack_padding = 15;
add_element(image);
add_element(text_stack);
}
save_dialog::save_dialog()
{
m_dim_background = std::make_unique<overlay_element>();
m_dim_background->set_size(1280, 720);
m_list = std::make_unique<list_view>(1240, 540);
m_description = std::make_unique<label>();
m_time_thingy = std::make_unique<label>();
m_list->set_pos(20, 85);
m_description->set_font("Arial", 20);
m_description->set_pos(20, 37);
m_description->set_text(localized_string_id::RSX_OVERLAYS_SAVE_DIALOG_TITLE);
2019-05-16 22:48:05 +02:00
m_time_thingy->set_font("Arial", 14);
m_time_thingy->set_pos(1000, 30);
m_time_thingy->set_text(date_time::current_time());
2021-04-21 23:20:33 +02:00
m_description->auto_resize();
m_time_thingy->auto_resize();
2019-05-16 22:48:05 +02:00
2021-03-17 08:48:07 +01:00
m_dim_background->back_color.a = 0.5f;
2019-05-16 22:48:05 +02:00
m_description->back_color.a = 0.f;
m_time_thingy->back_color.a = 0.f;
2022-02-05 21:15:45 +01:00
fade_animation.duration = 0.15f;
2019-05-16 22:48:05 +02:00
return_code = selection_code::canceled;
}
void save_dialog::update()
{
m_time_thingy->set_text(date_time::current_time());
2021-04-21 23:20:33 +02:00
m_time_thingy->auto_resize();
2022-02-05 21:15:45 +01:00
if (fade_animation.active)
{
fade_animation.update(rsx::get_current_renderer()->vblank_count);
}
2019-05-16 22:48:05 +02:00
}
void save_dialog::on_button_pressed(pad_button button_press)
{
2022-02-05 21:15:45 +01:00
if (fade_animation.active) return;
bool close_dialog = false;
2019-05-16 22:48:05 +02:00
switch (button_press)
{
case pad_button::cross:
if (m_no_saves)
break;
return_code = m_list->get_selected_index();
2022-02-05 21:15:45 +01:00
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
close_dialog = true;
break;
2019-05-16 22:48:05 +02:00
case pad_button::circle:
2021-10-31 00:48:41 +02:00
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
2022-02-05 21:15:45 +01:00
close_dialog = true;
break;
2019-05-16 22:48:05 +02:00
case pad_button::dpad_up:
case pad_button::ls_up:
2019-05-16 22:48:05 +02:00
m_list->select_previous();
break;
case pad_button::dpad_down:
case pad_button::ls_down:
2019-05-16 22:48:05 +02:00
m_list->select_next();
break;
case pad_button::L1:
m_list->select_previous(10);
break;
case pad_button::R1:
m_list->select_next(10);
break;
2019-05-16 22:48:05 +02:00
default:
rsx_log.trace("[ui] Button %d pressed", static_cast<u8>(button_press));
2021-04-21 23:20:33 +02:00
break;
2019-05-16 22:48:05 +02:00
}
2021-10-31 00:48:41 +02:00
2022-02-05 21:15:45 +01:00
if (close_dialog)
{
fade_animation.current = color4f(1.f);
fade_animation.end = color4f(0.f);
fade_animation.active = true;
fade_animation.on_finish = [this]
{
close(true, true);
};
}
else
{
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
}
2019-05-16 22:48:05 +02:00
}
compiled_resource save_dialog::get_compiled()
{
if (!visible)
{
return {};
}
2019-05-16 22:48:05 +02:00
compiled_resource result;
result.add(m_dim_background->get_compiled());
result.add(m_list->get_compiled());
result.add(m_description->get_compiled());
result.add(m_time_thingy->get_compiled());
if (m_no_saves)
result.add(m_no_saves_text->get_compiled());
2022-02-05 21:15:45 +01:00
fade_animation.apply(result);
2019-05-16 22:48:05 +02:00
return result;
}
2021-03-17 08:48:07 +01:00
s32 save_dialog::show(std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
2019-05-16 22:48:05 +02:00
{
visible = false;
2021-03-17 08:48:07 +01:00
if (enable_overlay)
{
2021-04-21 23:20:33 +02:00
m_dim_background->back_color.a = 0.9f;
2021-03-17 08:48:07 +01:00
}
else
{
m_dim_background->back_color.a = 0.5f;
}
2019-05-16 22:48:05 +02:00
std::vector<std::unique_ptr<overlay_element>> entries;
for (auto& entry : save_entries)
{
2021-04-24 17:59:55 +02:00
const std::string date_and_size = fmt::format("%s %s", entry.date(), entry.data_size());
2019-05-16 22:48:05 +02:00
std::unique_ptr<overlay_element> e;
2021-04-24 17:59:55 +02:00
e = std::make_unique<save_dialog_entry>(entry.subtitle, date_and_size, entry.details, image_resource_id::raw_image, entry.iconBuf);
2019-05-16 22:48:05 +02:00
entries.emplace_back(std::move(e));
}
if (op >= 8)
{
m_description->set_text(localized_string_id::RSX_OVERLAYS_SAVE_DIALOG_DELETE);
2019-05-16 22:48:05 +02:00
}
else if (op & 1)
{
m_description->set_text(localized_string_id::RSX_OVERLAYS_SAVE_DIALOG_LOAD);
2019-05-16 22:48:05 +02:00
}
else
{
m_description->set_text(localized_string_id::RSX_OVERLAYS_SAVE_DIALOG_SAVE);
2019-05-16 22:48:05 +02:00
}
const bool newpos_head = listSet && listSet->newData && listSet->newData->iconPosition == CELL_SAVEDATA_ICONPOS_HEAD;
2019-05-16 22:48:05 +02:00
if (!newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (listSet && listSet->newData)
2019-05-16 22:48:05 +02:00
{
2021-04-24 16:00:24 +02:00
std::string title = get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_TITLE);
2019-05-16 22:48:05 +02:00
std::vector<u8> icon;
2019-05-16 22:48:05 +02:00
int id = resource_config::standard_image_resource::new_entry;
2021-04-09 21:12:47 +02:00
if (const auto picon = +listSet->newData->icon)
2019-05-16 22:48:05 +02:00
{
if (picon->title)
title = picon->title.get_ptr();
if (picon->iconBuf && picon->iconBufSize && picon->iconBufSize <= 225280)
{
const auto iconBuf = static_cast<u8*>(picon->iconBuf.get_ptr());
const auto iconEnd = iconBuf + picon->iconBufSize;
icon.assign(iconBuf, iconEnd);
}
}
if (!icon.empty())
{
id = image_resource_id::raw_image;
}
2021-04-24 16:00:24 +02:00
std::unique_ptr<overlay_element> new_stub = std::make_unique<save_dialog_entry>(title, get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_SUB_TITLE), "", id, icon);
2019-05-16 22:48:05 +02:00
m_list->add_entry(new_stub);
}
if (newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (m_list->m_items.empty())
2019-05-16 22:48:05 +02:00
{
2021-04-24 16:00:24 +02:00
m_no_saves_text = std::make_unique<label>(get_localized_string(localized_string_id::CELL_SAVEDATA_NO_DATA));
2019-05-16 22:48:05 +02:00
m_no_saves_text->set_font("Arial", 20);
m_no_saves_text->align_text(overlay_element::text_align::center);
m_no_saves_text->set_pos(m_list->x, m_list->y + m_list->h / 2);
m_no_saves_text->set_size(m_list->w, 30);
m_no_saves_text->back_color.a = 0;
m_no_saves = true;
m_list->set_cancel_only(true);
}
else
{
// Only select an entry if there are entries available
m_list->select_entry(focused);
}
2021-04-21 23:20:33 +02:00
m_description->auto_resize();
2022-02-05 21:15:45 +01:00
fade_animation.current = color4f(0.f);
fade_animation.end = color4f(1.f);
fade_animation.active = true;
visible = true;
2019-05-16 22:48:05 +02:00
if (const auto error = run_input_loop())
{
if (error != selection_code::canceled)
{
rsx_log.error("Save dialog input loop exited with error code=%d", error);
}
return error;
}
2019-05-16 22:48:05 +02:00
2021-03-17 08:48:07 +01:00
if (return_code >= 0)
{
if (newpos_head)
{
return return_code - 1;
}
2021-04-21 23:20:33 +02:00
if (static_cast<usz>(return_code) == entries.size())
2021-03-17 08:48:07 +01:00
{
return selection_code::new_save;
}
}
2019-05-16 22:48:05 +02:00
return return_code;
}
} // namespace overlays
} // namespace RSX