1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

overlays: move some code to cpp files

This commit is contained in:
Megamouse 2019-05-16 22:48:05 +02:00
parent 4037225e98
commit 32bdd8ef7b
12 changed files with 1492 additions and 1313 deletions

View File

@ -129,289 +129,15 @@ namespace rsx
std::vector<u8> glyph_data;
bool initialized = false;
font(const char *ttf_name, f32 size)
{
// Init glyph
std::vector<u8> bytes;
std::vector<std::string> font_dirs;
std::vector<std::string> fallback_fonts;
#ifdef _WIN32
font_dirs.push_back("C:/Windows/Fonts/");
fallback_fonts.push_back("C:/Windows/Fonts/Arial.ttf");
#else
char *home = getenv("HOME");
if (home == nullptr)
home = getpwuid(getuid())->pw_dir;
font(const char* ttf_name, f32 size);
font_dirs.push_back(home);
if (home[font_dirs[0].length() - 1] == '/')
font_dirs[0] += ".fonts/";
else
font_dirs[0] += "/.fonts/";
stbtt_aligned_quad get_char(char c, f32& x_advance, f32& y_advance);
fallback_fonts.push_back("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"); //ubuntu
fallback_fonts.push_back("/usr/share/fonts/TTF/DejaVuSans.ttf"); //arch
#endif
// Search dev_flash for the font too
font_dirs.push_back(g_cfg.vfs.get_dev_flash() + "data/font/");
font_dirs.push_back(g_cfg.vfs.get_dev_flash() + "data/font/SONY-CC/");
void render_text_ex(std::vector<vertex>& result, f32& x_advance, f32& y_advance, const char* text, u32 char_limit, u16 max_width, bool wrap);
// Attempt to load a font from dev_flash as a last resort
fallback_fonts.push_back(g_cfg.vfs.get_dev_flash() + "data/font/SCE-PS3-VR-R-LATIN.TTF");
std::vector<vertex> render_text(const char* text, u16 max_width = UINT16_MAX, bool wrap = false);
// Attemt to load requested font
std::string file_path;
bool font_found = false;
for (auto& font_dir : font_dirs)
{
std::string requested_file = font_dir + ttf_name;
// Append ".ttf" if not present
std::string font_lower(requested_file);
std::transform(requested_file.begin(), requested_file.end(), font_lower.begin(), ::tolower);
if (font_lower.substr(font_lower.size() - 4) != ".ttf")
requested_file += ".ttf";
file_path = requested_file;
if (fs::is_file(requested_file))
{
font_found = true;
break;
}
}
// Attemt to load a fallback if request font wasn't found
if (!font_found)
{
for (auto &fallback_font : fallback_fonts)
{
if (fs::is_file(fallback_font))
{
file_path = fallback_font;
font_found = true;
LOG_NOTICE(RSX, "Found font file '%s' as a replacement for '%s'", fallback_font.c_str(), ttf_name);
break;
}
}
}
// Read font
if (font_found)
{
fs::file f(file_path);
f.read(bytes, f.size());
}
else
{
LOG_ERROR(RSX, "Failed to initialize font '%s.ttf'", ttf_name);
return;
}
glyph_data.resize(width * height);
pack_info.resize(256);
stbtt_pack_context context;
if (!stbtt_PackBegin(&context, glyph_data.data(), width, height, 0, 1, nullptr))
{
LOG_ERROR(RSX, "Font packing failed");
return;
}
stbtt_PackSetOversampling(&context, oversample, oversample);
// Convert pt to px
size_px = ceilf((f32)size * 96.f / 72.f);
size_pt = size;
if (!stbtt_PackFontRange(&context, bytes.data(), 0, size_px, 0, 256, pack_info.data()))
{
LOG_ERROR(RSX, "Font packing failed");
stbtt_PackEnd(&context);
return;
}
stbtt_PackEnd(&context);
font_name = ttf_name;
initialized = true;
f32 unused;
get_char('m', em_size, unused);
}
stbtt_aligned_quad get_char(char c, f32 &x_advance, f32 &y_advance)
{
if (!initialized)
return{};
stbtt_aligned_quad quad;
stbtt_GetPackedQuad(pack_info.data(), width, height, u8(c), &x_advance, &y_advance, &quad, false);
return quad;
}
void render_text_ex(std::vector<vertex>& result, f32& x_advance, f32& y_advance, const char* text, u32 char_limit, u16 max_width, bool wrap)
{
x_advance = 0.f;
y_advance = 0.f;
result.clear();
if (!initialized)
{
return;
}
u32 i = 0u;
bool skip_whitespace = false;
while (true)
{
if (char c = text[i++]; c && (i <= char_limit))
{
if (u8(c) >= char_count)
{
// Unsupported glyph, render null for now
c = ' ';
c = ' ';
}
switch (c)
{
case '\n':
{
y_advance += size_px + 2.f;
x_advance = 0.f;
continue;
}
case '\r':
{
x_advance = 0.f;
continue;
}
default:
{
stbtt_aligned_quad quad;
if (skip_whitespace && text[i - 1] == ' ')
{
quad = {};
}
else
{
quad = get_char(c, x_advance, y_advance);
skip_whitespace = false;
}
if (quad.x1 > max_width)
{
bool wrapped = false;
bool non_whitespace_break = false;
if (wrap)
{
// scan previous chars
for (int j = i - 1, nb_chars = 0; j > 0; j--, nb_chars++)
{
if (text[j] == '\n')
break;
if (text[j] == ' ')
{
non_whitespace_break = true;
continue;
}
if (non_whitespace_break)
{
if (nb_chars > 1)
{
nb_chars--;
auto first_affected = result.size() - (nb_chars * 4);
f32 base_x = result[first_affected].values[0];
for (size_t n = first_affected; n < result.size(); ++n)
{
auto char_index = n / 4;
if (text[char_index] == ' ')
{
// Skip character
result[n++].vec2(0.f, 0.f);
result[n++].vec2(0.f, 0.f);
result[n++].vec2(0.f, 0.f);
result[n].vec2(0.f, 0.f);
continue;
}
result[n].values[0] -= base_x;
result[n].values[1] += size_px + 2.f;
}
x_advance = result.back().values[0];
}
else
{
x_advance = 0.f;
}
wrapped = true;
y_advance += size_px + 2.f;
if (text[i - 1] == ' ')
{
quad = {};
skip_whitespace = true;
}
else
{
quad = get_char(c, x_advance, y_advance);
}
break;
}
}
}
if (!wrapped)
{
// TODO: Ellipsize
break;
}
}
result.push_back({ quad.x0, quad.y0, quad.s0, quad.t0 });
result.push_back({ quad.x1, quad.y0, quad.s1, quad.t0 });
result.push_back({ quad.x0, quad.y1, quad.s0, quad.t1 });
result.push_back({ quad.x1, quad.y1, quad.s1, quad.t1 });
break;
}
} // switch
}
else
{
break;
}
}
}
std::vector<vertex> render_text(const char *text, u16 max_width = UINT16_MAX, bool wrap = false)
{
std::vector<vertex> result;
f32 unused_x, unused_y;
render_text_ex(result, unused_x, unused_y, text, UINT32_MAX, max_width, wrap);
return result;
}
std::pair<f32, f32> get_char_offset(const char *text, u16 max_length, u16 max_width = UINT16_MAX, bool wrap = false)
{
std::vector<vertex> unused;
f32 loc_x, loc_y;
render_text_ex(unused, loc_x, loc_y, text, max_length, max_width, wrap);
return { loc_x, loc_y };
}
std::pair<f32, f32> get_char_offset(const char* text, u16 max_length, u16 max_width = UINT16_MAX, bool wrap = false);
};
// TODO: Singletons are cancer
@ -1417,99 +1143,18 @@ namespace rsx
f32 m_value = 0.f;
public:
progress_bar()
{
text_view.back_color = { 0.f, 0.f, 0.f, 0.f };
}
progress_bar();
void inc(f32 value);
void dec(f32 value);
void set_limit(f32 limit);
void set_value(f32 value);
void set_pos(u16 _x, u16 _y) override;
void set_size(u16 _w, u16 _h) override;
void translate(s16 dx, s16 dy) override;
void set_text(const char* str) override;
void set_text(const std::string& str) override;
void inc(f32 value)
{
set_value(m_value + value);
}
void dec(f32 value)
{
set_value(m_value - value);
}
void set_limit(f32 limit)
{
m_limit = limit;
is_compiled = false;
}
void set_value(f32 value)
{
m_value = std::clamp(value, 0.f, m_limit);
f32 indicator_width = (w * m_value) / m_limit;
indicator.set_size((u16)indicator_width, h);
is_compiled = false;
}
void set_pos(u16 _x, u16 _y) override
{
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_h += 13;
overlay_element::set_pos(_x, _y + text_h);
indicator.set_pos(_x, _y + text_h);
text_view.set_pos(_x, _y);
}
void set_size(u16 _w, u16 _h) override
{
overlay_element::set_size(_w, _h);
text_view.set_size(_w, text_view.h);
set_value(m_value);
}
void translate(s16 dx, s16 dy) override
{
set_pos(x + dx, y + dy);
}
void set_text(const char* str) override
{
text_view.set_text(str);
text_view.align_text(text_align::center);
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_view.set_size(w, text_h);
set_pos(text_view.x, text_view.y);
is_compiled = false;
}
void set_text(const std::string& str) override
{
text_view.set_text(str);
text_view.align_text(text_align::center);
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_view.set_size(w, text_h);
set_pos(text_view.x, text_view.y);
is_compiled = false;
}
compiled_resource& get_compiled() override
{
if (!is_compiled)
{
auto& compiled = overlay_element::get_compiled();
compiled.add(text_view.get_compiled());
indicator.back_color = fore_color;
indicator.refresh();
compiled.add(indicator.get_compiled());
}
return compiled_resources;
}
compiled_resource& get_compiled() override;
};
struct list_view : public vertical_layout
@ -1528,181 +1173,23 @@ namespace rsx
bool m_cancel_only = false;
public:
list_view(u16 width, u16 height)
{
w = width;
h = height;
list_view(u16 width, u16 height);
m_scroll_indicator_top = std::make_unique<image_view>(width, 5);
m_scroll_indicator_bottom = std::make_unique<image_view>(width, 5);
m_accept_btn = std::make_unique<image_button>(120, 20);
m_cancel_btn = std::make_unique<image_button>(120, 20);
m_highlight_box = std::make_unique<overlay_element>(width, 0);
void update_selection();
m_scroll_indicator_top->set_size(width, 40);
m_scroll_indicator_bottom->set_size(width, 40);
m_accept_btn->set_size(120, 30);
m_cancel_btn->set_size(120, 30);
void select_next();
void select_previous();
m_scroll_indicator_top->set_image_resource(resource_config::standard_image_resource::fade_top);
m_scroll_indicator_bottom->set_image_resource(resource_config::standard_image_resource::fade_bottom);
void add_entry(std::unique_ptr<overlay_element>& entry);
if (g_cfg.sys.enter_button_assignment == enter_button_assign::circle)
{
m_accept_btn->set_image_resource(resource_config::standard_image_resource::circle);
m_cancel_btn->set_image_resource(resource_config::standard_image_resource::cross);
}
else
{
m_accept_btn->set_image_resource(resource_config::standard_image_resource::cross);
m_cancel_btn->set_image_resource(resource_config::standard_image_resource::circle);
}
int get_selected_index();
m_scroll_indicator_bottom->set_pos(0, height - 40);
m_accept_btn->set_pos(30, height + 20);
m_cancel_btn->set_pos(180, height + 20);
std::string get_selected_item();
m_accept_btn->set_text("Select");
m_cancel_btn->set_text("Cancel");
void set_cancel_only(bool cancel_only);
void translate(s16 _x, s16 _y) override;
m_accept_btn->set_font("Arial", 16);
m_cancel_btn->set_font("Arial", 16);
auto_resize = false;
back_color = { 0.15f, 0.15f, 0.15f, 0.8f };
m_highlight_box->back_color = { .5f, .5f, .8f, 0.2f };
m_highlight_box->pulse_effect_enabled = true;
m_scroll_indicator_top->fore_color.a = 0.f;
m_scroll_indicator_bottom->fore_color.a = 0.f;
}
void update_selection()
{
auto current_element = m_items[m_selected_entry * 2].get();
// Calculate bounds
auto min_y = current_element->y - y;
auto max_y = current_element->y + current_element->h + pack_padding + 2 - y;
if (min_y < scroll_offset_value)
{
scroll_offset_value = min_y;
}
else if (max_y > (h + scroll_offset_value))
{
scroll_offset_value = max_y - h - 2;
}
if ((scroll_offset_value + h + 2) >= m_elements_height)
m_scroll_indicator_bottom->fore_color.a = 0.f;
else
m_scroll_indicator_bottom->fore_color.a = 0.5f;
if (scroll_offset_value == 0)
m_scroll_indicator_top->fore_color.a = 0.f;
else
m_scroll_indicator_top->fore_color.a = 0.5f;
m_highlight_box->set_pos(current_element->x, current_element->y);
m_highlight_box->h = current_element->h + pack_padding;
m_highlight_box->y -= scroll_offset_value;
m_highlight_box->refresh();
m_scroll_indicator_top->refresh();
m_scroll_indicator_bottom->refresh();
refresh();
}
void select_next()
{
if (m_selected_entry < (m_elements_count - 1))
{
m_selected_entry++;
update_selection();
}
}
void select_previous()
{
if (m_selected_entry > 0)
{
m_selected_entry--;
update_selection();
}
}
void add_entry(std::unique_ptr<overlay_element>& entry)
{
// Add entry view
add_element(entry);
m_elements_count++;
// Add separator
auto separator = std::make_unique<overlay_element>();
separator->back_color = fore_color;
separator->w = w;
separator->h = 2;
add_element(separator);
if (m_selected_entry < 0)
m_selected_entry = 0;
m_elements_height = advance_pos;
update_selection();
}
int get_selected_index()
{
return m_selected_entry;
}
std::string get_selected_item()
{
if (m_selected_entry < 0)
return{};
return m_items[m_selected_entry]->text;
}
void set_cancel_only(bool cancel_only)
{
if (cancel_only)
m_cancel_btn->set_pos(x + 30, y + h + 20);
else
m_cancel_btn->set_pos(x + 180, y + h + 20);
m_cancel_only = cancel_only;
is_compiled = false;
}
void translate(s16 _x, s16 _y) override
{
layout_container::translate(_x, _y);
m_scroll_indicator_top->translate(_x, _y);
m_scroll_indicator_bottom->translate(_x, _y);
m_accept_btn->translate(_x, _y);
m_cancel_btn->translate(_x, _y);
}
compiled_resource& get_compiled() override
{
if (!is_compiled)
{
auto compiled = vertical_layout::get_compiled();
compiled.add(m_highlight_box->get_compiled());
compiled.add(m_scroll_indicator_top->get_compiled());
compiled.add(m_scroll_indicator_bottom->get_compiled());
compiled.add(m_cancel_btn->get_compiled());
if (!m_cancel_only)
compiled.add(m_accept_btn->get_compiled());
compiled_resources = compiled;
}
return compiled_resources;
}
compiled_resource& get_compiled() override;
};
struct edit_text : public label
@ -1720,112 +1207,11 @@ namespace rsx
using label::label;
void move_caret(direction dir)
{
switch (dir)
{
case left:
{
if (caret_position)
{
caret_position--;
refresh();
}
break;
}
case right:
{
if (caret_position < text.length())
{
caret_position++;
refresh();
}
break;
}
case up:
case down:
// TODO
break;
}
}
void move_caret(direction dir);
void insert_text(const std::string& str);
void erase();
void insert_text(const std::string& str)
{
if (caret_position == 0)
{
// Start
text = str + text;
}
else if (caret_position == text.length())
{
// End
text += str;
}
else
{
// Middle
text.insert(caret_position, str);
}
caret_position += ::narrow<u16>(str.length());
refresh();
}
void erase()
{
if (!caret_position)
{
return;
}
if (caret_position == 1)
{
text = text.length() > 1? text.substr(1) : "";
}
else if (caret_position == text.length())
{
text = text.substr(0, caret_position - 1);
}
else
{
text = text.substr(0, caret_position - 1) + text.substr(caret_position);
}
caret_position--;
refresh();
}
compiled_resource& get_compiled() override
{
if (!is_compiled)
{
auto& compiled = label::get_compiled();
overlay_element caret;
auto renderer = get_font();
const auto caret_loc = renderer->get_char_offset(text.c_str(), caret_position,
clip_text ? w : UINT16_MAX, wrap_text);
caret.set_pos(u16(caret_loc.first + padding_left + x), u16(caret_loc.second + padding_top + y));
caret.set_size(1, u16(renderer->size_px + 2));
caret.fore_color = fore_color;
caret.back_color = fore_color;
caret.pulse_effect_enabled = true;
compiled.add(caret.get_compiled());
for (auto &cmd : compiled.draw_commands)
{
// TODO: Scrolling by using scroll offset
cmd.config.clip_region = true;
cmd.config.clip_rect = { f32(x), f32(y), f32(x + w), f32(y + h) };
}
is_compiled = true;
}
return compiled_resources;
}
compiled_resource& get_compiled() override;
};
}
}

View File

@ -0,0 +1,114 @@
#include "stdafx.h"
#include "overlay_controls.h"
namespace rsx
{
namespace overlays
{
void edit_text::move_caret(direction dir)
{
switch (dir)
{
case left:
{
if (caret_position)
{
caret_position--;
refresh();
}
break;
}
case right:
{
if (caret_position < text.length())
{
caret_position++;
refresh();
}
break;
}
case up:
case down:
// TODO
break;
}
}
void edit_text::insert_text(const std::string& str)
{
if (caret_position == 0)
{
// Start
text = str + text;
}
else if (caret_position == text.length())
{
// End
text += str;
}
else
{
// Middle
text.insert(caret_position, str);
}
caret_position += ::narrow<u16>(str.length());
refresh();
}
void edit_text::erase()
{
if (!caret_position)
{
return;
}
if (caret_position == 1)
{
text = text.length() > 1 ? text.substr(1) : "";
}
else if (caret_position == text.length())
{
text = text.substr(0, caret_position - 1);
}
else
{
text = text.substr(0, caret_position - 1) + text.substr(caret_position);
}
caret_position--;
refresh();
}
compiled_resource& edit_text::get_compiled()
{
if (!is_compiled)
{
auto& compiled = label::get_compiled();
overlay_element caret;
auto renderer = get_font();
const auto caret_loc = renderer->get_char_offset(text.c_str(), caret_position, clip_text ? w : UINT16_MAX, wrap_text);
caret.set_pos(u16(caret_loc.first + padding_left + x), u16(caret_loc.second + padding_top + y));
caret.set_size(1, u16(renderer->size_px + 2));
caret.fore_color = fore_color;
caret.back_color = fore_color;
caret.pulse_effect_enabled = true;
compiled.add(caret.get_compiled());
for (auto& cmd : compiled.draw_commands)
{
// TODO: Scrolling by using scroll offset
cmd.config.clip_region = true;
cmd.config.clip_rect = {f32(x), f32(y), f32(x + w), f32(y + h)};
}
is_compiled = true;
}
return compiled_resources;
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,292 @@
#include "stdafx.h"
#include "overlay_controls.h"
namespace rsx
{
namespace overlays
{
font::font(const char* ttf_name, f32 size)
{
// Init glyph
std::vector<u8> bytes;
std::vector<std::string> font_dirs;
std::vector<std::string> fallback_fonts;
#ifdef _WIN32
font_dirs.push_back("C:/Windows/Fonts/");
fallback_fonts.push_back("C:/Windows/Fonts/Arial.ttf");
#else
char* home = getenv("HOME");
if (home == nullptr)
home = getpwuid(getuid())->pw_dir;
font_dirs.push_back(home);
if (home[font_dirs[0].length() - 1] == '/')
font_dirs[0] += ".fonts/";
else
font_dirs[0] += "/.fonts/";
fallback_fonts.push_back("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"); // ubuntu
fallback_fonts.push_back("/usr/share/fonts/TTF/DejaVuSans.ttf"); // arch
#endif
// Search dev_flash for the font too
font_dirs.push_back(g_cfg.vfs.get_dev_flash() + "data/font/");
font_dirs.push_back(g_cfg.vfs.get_dev_flash() + "data/font/SONY-CC/");
// Attempt to load a font from dev_flash as a last resort
fallback_fonts.push_back(g_cfg.vfs.get_dev_flash() + "data/font/SCE-PS3-VR-R-LATIN.TTF");
// Attemt to load requested font
std::string file_path;
bool font_found = false;
for (auto& font_dir : font_dirs)
{
std::string requested_file = font_dir + ttf_name;
// Append ".ttf" if not present
std::string font_lower(requested_file);
std::transform(requested_file.begin(), requested_file.end(), font_lower.begin(), ::tolower);
if (font_lower.substr(font_lower.size() - 4) != ".ttf")
requested_file += ".ttf";
file_path = requested_file;
if (fs::is_file(requested_file))
{
font_found = true;
break;
}
}
// Attemt to load a fallback if request font wasn't found
if (!font_found)
{
for (auto& fallback_font : fallback_fonts)
{
if (fs::is_file(fallback_font))
{
file_path = fallback_font;
font_found = true;
LOG_NOTICE(RSX, "Found font file '%s' as a replacement for '%s'", fallback_font.c_str(), ttf_name);
break;
}
}
}
// Read font
if (font_found)
{
fs::file f(file_path);
f.read(bytes, f.size());
}
else
{
LOG_ERROR(RSX, "Failed to initialize font '%s.ttf'", ttf_name);
return;
}
glyph_data.resize(width * height);
pack_info.resize(256);
stbtt_pack_context context;
if (!stbtt_PackBegin(&context, glyph_data.data(), width, height, 0, 1, nullptr))
{
LOG_ERROR(RSX, "Font packing failed");
return;
}
stbtt_PackSetOversampling(&context, oversample, oversample);
// Convert pt to px
size_px = ceilf((f32)size * 96.f / 72.f);
size_pt = size;
if (!stbtt_PackFontRange(&context, bytes.data(), 0, size_px, 0, 256, pack_info.data()))
{
LOG_ERROR(RSX, "Font packing failed");
stbtt_PackEnd(&context);
return;
}
stbtt_PackEnd(&context);
font_name = ttf_name;
initialized = true;
f32 unused;
get_char('m', em_size, unused);
}
stbtt_aligned_quad font::get_char(char c, f32& x_advance, f32& y_advance)
{
if (!initialized)
return {};
stbtt_aligned_quad quad;
stbtt_GetPackedQuad(pack_info.data(), width, height, u8(c), &x_advance, &y_advance, &quad, false);
return quad;
}
void font::render_text_ex(std::vector<vertex>& result, f32& x_advance, f32& y_advance, const char* text, u32 char_limit, u16 max_width, bool wrap)
{
x_advance = 0.f;
y_advance = 0.f;
result.clear();
if (!initialized)
{
return;
}
u32 i = 0u;
bool skip_whitespace = false;
while (true)
{
if (char c = text[i++]; c && (i <= char_limit))
{
if (u8(c) >= char_count)
{
// Unsupported glyph, render null for now
c = ' ';
c = ' ';
}
switch (c)
{
case '\n':
{
y_advance += size_px + 2.f;
x_advance = 0.f;
continue;
}
case '\r':
{
x_advance = 0.f;
continue;
}
default:
{
stbtt_aligned_quad quad;
if (skip_whitespace && text[i - 1] == ' ')
{
quad = {};
}
else
{
quad = get_char(c, x_advance, y_advance);
skip_whitespace = false;
}
if (quad.x1 > max_width)
{
bool wrapped = false;
bool non_whitespace_break = false;
if (wrap)
{
// scan previous chars
for (int j = i - 1, nb_chars = 0; j > 0; j--, nb_chars++)
{
if (text[j] == '\n')
break;
if (text[j] == ' ')
{
non_whitespace_break = true;
continue;
}
if (non_whitespace_break)
{
if (nb_chars > 1)
{
nb_chars--;
auto first_affected = result.size() - (nb_chars * 4);
f32 base_x = result[first_affected].values[0];
for (size_t n = first_affected; n < result.size(); ++n)
{
auto char_index = n / 4;
if (text[char_index] == ' ')
{
// Skip character
result[n++].vec2(0.f, 0.f);
result[n++].vec2(0.f, 0.f);
result[n++].vec2(0.f, 0.f);
result[n].vec2(0.f, 0.f);
continue;
}
result[n].values[0] -= base_x;
result[n].values[1] += size_px + 2.f;
}
x_advance = result.back().values[0];
}
else
{
x_advance = 0.f;
}
wrapped = true;
y_advance += size_px + 2.f;
if (text[i - 1] == ' ')
{
quad = {};
skip_whitespace = true;
}
else
{
quad = get_char(c, x_advance, y_advance);
}
break;
}
}
}
if (!wrapped)
{
// TODO: Ellipsize
break;
}
}
result.push_back({quad.x0, quad.y0, quad.s0, quad.t0});
result.push_back({quad.x1, quad.y0, quad.s1, quad.t0});
result.push_back({quad.x0, quad.y1, quad.s0, quad.t1});
result.push_back({quad.x1, quad.y1, quad.s1, quad.t1});
break;
}
} // switch
}
else
{
break;
}
}
}
std::vector<vertex> font::render_text(const char* text, u16 max_width, bool wrap)
{
std::vector<vertex> result;
f32 unused_x, unused_y;
render_text_ex(result, unused_x, unused_y, text, UINT32_MAX, max_width, wrap);
return result;
}
std::pair<f32, f32> font::get_char_offset(const char* text, u16 max_length, u16 max_width, bool wrap)
{
std::vector<vertex> unused;
f32 loc_x, loc_y;
render_text_ex(unused, loc_x, loc_y, text, max_length, max_width, wrap);
return {loc_x, loc_y};
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,184 @@
#include "stdafx.h"
#include "overlay_controls.h"
namespace rsx
{
namespace overlays
{
list_view::list_view(u16 width, u16 height)
{
w = width;
h = height;
m_scroll_indicator_top = std::make_unique<image_view>(width, 5);
m_scroll_indicator_bottom = std::make_unique<image_view>(width, 5);
m_accept_btn = std::make_unique<image_button>(120, 20);
m_cancel_btn = std::make_unique<image_button>(120, 20);
m_highlight_box = std::make_unique<overlay_element>(width, 0);
m_scroll_indicator_top->set_size(width, 40);
m_scroll_indicator_bottom->set_size(width, 40);
m_accept_btn->set_size(120, 30);
m_cancel_btn->set_size(120, 30);
m_scroll_indicator_top->set_image_resource(resource_config::standard_image_resource::fade_top);
m_scroll_indicator_bottom->set_image_resource(resource_config::standard_image_resource::fade_bottom);
if (g_cfg.sys.enter_button_assignment == enter_button_assign::circle)
{
m_accept_btn->set_image_resource(resource_config::standard_image_resource::circle);
m_cancel_btn->set_image_resource(resource_config::standard_image_resource::cross);
}
else
{
m_accept_btn->set_image_resource(resource_config::standard_image_resource::cross);
m_cancel_btn->set_image_resource(resource_config::standard_image_resource::circle);
}
m_scroll_indicator_bottom->set_pos(0, height - 40);
m_accept_btn->set_pos(30, height + 20);
m_cancel_btn->set_pos(180, height + 20);
m_accept_btn->set_text("Select");
m_cancel_btn->set_text("Cancel");
m_accept_btn->set_font("Arial", 16);
m_cancel_btn->set_font("Arial", 16);
auto_resize = false;
back_color = {0.15f, 0.15f, 0.15f, 0.8f};
m_highlight_box->back_color = {.5f, .5f, .8f, 0.2f};
m_highlight_box->pulse_effect_enabled = true;
m_scroll_indicator_top->fore_color.a = 0.f;
m_scroll_indicator_bottom->fore_color.a = 0.f;
}
void list_view::update_selection()
{
auto current_element = m_items[m_selected_entry * 2].get();
// Calculate bounds
auto min_y = current_element->y - y;
auto max_y = current_element->y + current_element->h + pack_padding + 2 - y;
if (min_y < scroll_offset_value)
{
scroll_offset_value = min_y;
}
else if (max_y > (h + scroll_offset_value))
{
scroll_offset_value = max_y - h - 2;
}
if ((scroll_offset_value + h + 2) >= m_elements_height)
m_scroll_indicator_bottom->fore_color.a = 0.f;
else
m_scroll_indicator_bottom->fore_color.a = 0.5f;
if (scroll_offset_value == 0)
m_scroll_indicator_top->fore_color.a = 0.f;
else
m_scroll_indicator_top->fore_color.a = 0.5f;
m_highlight_box->set_pos(current_element->x, current_element->y);
m_highlight_box->h = current_element->h + pack_padding;
m_highlight_box->y -= scroll_offset_value;
m_highlight_box->refresh();
m_scroll_indicator_top->refresh();
m_scroll_indicator_bottom->refresh();
refresh();
}
void list_view::select_next()
{
if (m_selected_entry < (m_elements_count - 1))
{
m_selected_entry++;
update_selection();
}
}
void list_view::select_previous()
{
if (m_selected_entry > 0)
{
m_selected_entry--;
update_selection();
}
}
void list_view::add_entry(std::unique_ptr<overlay_element>& entry)
{
// Add entry view
add_element(entry);
m_elements_count++;
// Add separator
auto separator = std::make_unique<overlay_element>();
separator->back_color = fore_color;
separator->w = w;
separator->h = 2;
add_element(separator);
if (m_selected_entry < 0)
m_selected_entry = 0;
m_elements_height = advance_pos;
update_selection();
}
int list_view::get_selected_index()
{
return m_selected_entry;
}
std::string list_view::get_selected_item()
{
if (m_selected_entry < 0)
return {};
return m_items[m_selected_entry]->text;
}
void list_view::set_cancel_only(bool cancel_only)
{
if (cancel_only)
m_cancel_btn->set_pos(x + 30, y + h + 20);
else
m_cancel_btn->set_pos(x + 180, y + h + 20);
m_cancel_only = cancel_only;
is_compiled = false;
}
void list_view::translate(s16 _x, s16 _y)
{
layout_container::translate(_x, _y);
m_scroll_indicator_top->translate(_x, _y);
m_scroll_indicator_bottom->translate(_x, _y);
m_accept_btn->translate(_x, _y);
m_cancel_btn->translate(_x, _y);
}
compiled_resource& list_view::get_compiled()
{
if (!is_compiled)
{
auto compiled = vertical_layout::get_compiled();
compiled.add(m_highlight_box->get_compiled());
compiled.add(m_scroll_indicator_top->get_compiled());
compiled.add(m_scroll_indicator_bottom->get_compiled());
compiled.add(m_cancel_btn->get_compiled());
if (!m_cancel_only)
compiled.add(m_accept_btn->get_compiled());
compiled_resources = compiled;
}
return compiled_resources;
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,299 @@
#include "stdafx.h"
#include "overlays.h"
namespace rsx
{
namespace overlays
{
message_dialog::message_dialog(bool use_custom_background)
{
background.set_size(1280, 720);
background.back_color.a = 0.85f;
text_display.set_size(1100, 40);
text_display.set_pos(90, 364);
text_display.set_font("Arial", 16);
text_display.align_text(overlay_element::text_align::center);
text_display.set_wrap_text(true);
text_display.back_color.a = 0.f;
bottom_bar.back_color = color4f(1.f, 1.f, 1.f, 1.f);
bottom_bar.set_size(1200, 2);
bottom_bar.set_pos(40, 400);
progress_1.set_size(800, 4);
progress_2.set_size(800, 4);
progress_1.back_color = color4f(0.25f, 0.f, 0.f, 0.85f);
progress_2.back_color = color4f(0.25f, 0.f, 0.f, 0.85f);
btn_ok.set_text("Yes");
btn_ok.set_size(140, 30);
btn_ok.set_pos(545, 420);
btn_ok.set_font("Arial", 16);
btn_cancel.set_text("No");
btn_cancel.set_size(140, 30);
btn_cancel.set_pos(685, 420);
btn_cancel.set_font("Arial", 16);
if (g_cfg.sys.enter_button_assignment == enter_button_assign::circle)
{
btn_ok.set_image_resource(resource_config::standard_image_resource::circle);
btn_cancel.set_image_resource(resource_config::standard_image_resource::cross);
}
else
{
btn_ok.set_image_resource(resource_config::standard_image_resource::cross);
btn_cancel.set_image_resource(resource_config::standard_image_resource::circle);
}
if (use_custom_background)
{
auto icon_path = Emu.GetSfoDir() + "/PIC1.PNG";
if (!fs::exists(icon_path))
{
// Fallback path
icon_path = Emu.GetSfoDir() + "/ICON0.PNG";
}
if (fs::exists(icon_path))
{
background_image = std::make_unique<image_info>(icon_path.c_str());
if (background_image->data)
{
f32 color = (100 - g_cfg.video.shader_preloading_dialog.darkening_strength) / 100.f;
background_poster.fore_color = color4f(color, color, color, 1.);
background.back_color.a = 0.f;
background_poster.set_size(1280, 720);
background_poster.set_raw_image(background_image.get());
background_poster.set_blur_strength((u8)g_cfg.video.shader_preloading_dialog.blur_strength);
}
}
}
return_code = CELL_MSGDIALOG_BUTTON_NONE;
}
compiled_resource message_dialog::get_compiled()
{
compiled_resource result;
if (background_image && background_image->data)
{
result.add(background_poster.get_compiled());
}
result.add(background.get_compiled());
result.add(text_display.get_compiled());
if (num_progress_bars > 0)
{
result.add(progress_1.get_compiled());
}
if (num_progress_bars > 1)
{
result.add(progress_2.get_compiled());
}
if (interactive)
{
if (!num_progress_bars)
result.add(bottom_bar.get_compiled());
if (!cancel_only)
result.add(btn_ok.get_compiled());
if (!ok_only)
result.add(btn_cancel.get_compiled());
}
return result;
}
void message_dialog::on_button_pressed(pad_button button_press)
{
switch (button_press)
{
case pad_button::cross:
{
if (ok_only)
{
return_code = CELL_MSGDIALOG_BUTTON_OK;
}
else if (cancel_only)
{
// Do not accept for cancel-only dialogs
return;
}
else
{
return_code = CELL_MSGDIALOG_BUTTON_YES;
}
break;
}
case pad_button::circle:
{
if (ok_only)
{
// Ignore cancel operation for Ok-only
return;
}
else if (cancel_only)
{
return_code = CELL_MSGDIALOG_BUTTON_ESCAPE;
}
else
{
return_code = CELL_MSGDIALOG_BUTTON_NO;
}
break;
}
default: return;
}
close();
}
error_code message_dialog::show(const std::string& text, const MsgDialogType& type, std::function<void(s32 status)> on_close)
{
num_progress_bars = type.progress_bar_count;
if (num_progress_bars)
{
u16 offset = 58;
progress_1.set_pos(240, 412);
if (num_progress_bars > 1)
{
progress_2.set_pos(240, 462);
offset = 98;
}
// Push the other stuff down
bottom_bar.translate(0, offset);
btn_ok.translate(0, offset);
btn_cancel.translate(0, offset);
}
text_display.set_text(utf8_to_ascii8(text));
u16 text_w, text_h;
text_display.measure_text(text_w, text_h);
text_display.translate(0, -(text_h - 16));
switch (type.button_type.unshifted())
{
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE:
interactive = !type.disable_cancel;
if (interactive)
{
btn_cancel.set_pos(585, btn_cancel.y);
btn_cancel.set_text("Cancel");
cancel_only = true;
}
break;
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
btn_ok.set_pos(600, btn_ok.y);
btn_ok.set_text("OK");
interactive = true;
ok_only = true;
break;
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO: interactive = true; break;
}
this->on_close = on_close;
if (interactive)
{
thread_ctrl::spawn("dialog input thread", [&] {
if (auto error = run_input_loop())
{
LOG_ERROR(RSX, "Dialog input loop exited with error code=%d", error);
}
});
}
return CELL_OK;
}
u32 message_dialog::progress_bar_count()
{
return num_progress_bars;
}
void message_dialog::progress_bar_set_taskbar_index(s32 index)
{
taskbar_index = index;
}
error_code message_dialog::progress_bar_set_message(u32 index, const std::string& msg)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_text(msg);
else
progress_2.set_text(msg);
return CELL_OK;
}
error_code message_dialog::progress_bar_increment(u32 index, f32 value)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.inc(value);
else
progress_2.inc(value);
if (index == taskbar_index || taskbar_index == -1)
Emu.GetCallbacks().handle_taskbar_progress(1, (s32)value);
return CELL_OK;
}
error_code message_dialog::progress_bar_reset(u32 index)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_value(0.f);
else
progress_2.set_value(0.f);
Emu.GetCallbacks().handle_taskbar_progress(0, 0);
return CELL_OK;
}
error_code message_dialog::progress_bar_set_limit(u32 index, u32 limit)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_limit((float)limit);
else
progress_2.set_limit((float)limit);
if (index == taskbar_index)
{
taskbar_limit = limit;
Emu.GetCallbacks().handle_taskbar_progress(2, taskbar_limit);
}
else if (taskbar_index == -1)
{
taskbar_limit += limit;
Emu.GetCallbacks().handle_taskbar_progress(2, taskbar_limit);
}
return CELL_OK;
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,102 @@
#include "stdafx.h"
#include "overlay_controls.h"
namespace rsx
{
namespace overlays
{
progress_bar::progress_bar()
{
text_view.back_color = {0.f, 0.f, 0.f, 0.f};
}
void progress_bar::inc(f32 value)
{
set_value(m_value + value);
}
void progress_bar::dec(f32 value)
{
set_value(m_value - value);
}
void progress_bar::set_limit(f32 limit)
{
m_limit = limit;
is_compiled = false;
}
void progress_bar::set_value(f32 value)
{
m_value = std::clamp(value, 0.f, m_limit);
f32 indicator_width = (w * m_value) / m_limit;
indicator.set_size((u16)indicator_width, h);
is_compiled = false;
}
void progress_bar::set_pos(u16 _x, u16 _y)
{
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_h += 13;
overlay_element::set_pos(_x, _y + text_h);
indicator.set_pos(_x, _y + text_h);
text_view.set_pos(_x, _y);
}
void progress_bar::set_size(u16 _w, u16 _h)
{
overlay_element::set_size(_w, _h);
text_view.set_size(_w, text_view.h);
set_value(m_value);
}
void progress_bar::translate(s16 dx, s16 dy)
{
set_pos(x + dx, y + dy);
}
void progress_bar::set_text(const char* str)
{
text_view.set_text(str);
text_view.align_text(text_align::center);
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_view.set_size(w, text_h);
set_pos(text_view.x, text_view.y);
is_compiled = false;
}
void progress_bar::set_text(const std::string& str)
{
text_view.set_text(str);
text_view.align_text(text_align::center);
u16 text_w, text_h;
text_view.measure_text(text_w, text_h);
text_view.set_size(w, text_h);
set_pos(text_view.x, text_view.y);
is_compiled = false;
}
compiled_resource& progress_bar::get_compiled()
{
if (!is_compiled)
{
auto& compiled = overlay_element::get_compiled();
compiled.add(text_view.get_compiled());
indicator.back_color = fore_color;
indicator.refresh();
compiled.add(indicator.get_compiled());
}
return compiled_resources;
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,251 @@
#include "stdafx.h"
#include "overlays.h"
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.size())
{
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>(utf8_to_ascii8(text1));
std::unique_ptr<overlay_element> subtext = std::make_unique<label>(utf8_to_ascii8(text2));
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>(utf8_to_ascii8(text3));
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("Save Dialog");
m_time_thingy->set_font("Arial", 14);
m_time_thingy->set_pos(1000, 30);
m_time_thingy->set_text(date_time::current_time());
static_cast<label*>(m_description.get())->auto_resize();
static_cast<label*>(m_time_thingy.get())->auto_resize();
m_dim_background->back_color.a = 0.8f;
m_description->back_color.a = 0.f;
m_time_thingy->back_color.a = 0.f;
return_code = selection_code::canceled;
}
void save_dialog::update()
{
m_time_thingy->set_text(date_time::current_time());
static_cast<label*>(m_time_thingy.get())->auto_resize();
}
void save_dialog::on_button_pressed(pad_button button_press)
{
switch (button_press)
{
case pad_button::cross:
if (m_no_saves)
break;
return_code = m_list->get_selected_index();
// Fall through
case pad_button::circle:
close();
break;
case pad_button::dpad_up:
m_list->select_previous();
break;
case pad_button::dpad_down:
m_list->select_next();
break;
default:
LOG_TRACE(RSX, "[ui] Button %d pressed", (u8)button_press);
}
}
compiled_resource save_dialog::get_compiled()
{
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());
return result;
}
s32 save_dialog::show(std::vector<SaveDataEntry>& save_entries, u32 op, vm::ptr<CellSaveDataListSet> listSet)
{
std::vector<u8> icon;
std::vector<std::unique_ptr<overlay_element>> entries;
for (auto& entry : save_entries)
{
std::unique_ptr<overlay_element> e;
e = std::make_unique<save_dialog_entry>(entry.title, entry.subtitle, entry.details, image_resource_id::raw_image, entry.iconBuf);
entries.emplace_back(std::move(e));
}
if (op >= 8)
{
m_description->set_text("Delete Save");
}
else if (op & 1)
{
m_description->set_text("Load Save");
}
else
{
m_description->set_text("Save");
}
const bool newpos_head = listSet->newData && listSet->newData->iconPosition == CELL_SAVEDATA_ICONPOS_HEAD;
if (!newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (listSet->newData)
{
std::unique_ptr<overlay_element> new_stub;
const char* title = "Create New";
int id = resource_config::standard_image_resource::new_entry;
if (auto picon = +listSet->newData->icon)
{
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;
}
new_stub = std::make_unique<save_dialog_entry>(title, "Select to create a new entry", "", id, icon);
m_list->add_entry(new_stub);
}
if (newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (!m_list->m_items.size())
{
m_no_saves_text = std::make_unique<label>("There is no saved data.");
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);
}
static_cast<label*>(m_description.get())->auto_resize();
if (auto err = run_input_loop())
return err;
if (return_code == entries.size() && !newpos_head)
return selection_code::new_save;
if (return_code >= 0 && newpos_head)
return return_code - 1;
return return_code;
}
} // namespace overlays
} // namespace RSX

View File

@ -0,0 +1,91 @@
#include "stdafx.h"
#include "overlays.h"
namespace rsx
{
namespace overlays
{
shader_compile_notification::shader_compile_notification()
{
const u16 pos_x = g_cfg.video.shader_compilation_hint.pos_x;
const u16 pos_y = g_cfg.video.shader_compilation_hint.pos_y;
m_text.set_font("Arial", 16);
m_text.set_text("Compiling shaders");
m_text.auto_resize();
m_text.set_pos(pos_x, pos_y);
m_text.back_color.a = 0.f;
for (int n = 0; n < 3; ++n)
{
dots[n].set_size(2, 2);
dots[n].back_color = color4f(1.f, 1.f, 1.f, 1.f);
dots[n].set_pos(m_text.w + pos_x + 5 + (6 * n), pos_y + 20);
}
creation_time = get_system_time();
expire_time = creation_time + 1000000;
// Disable forced refresh unless fps dips below 4
min_refresh_duration_us = 250000;
}
void shader_compile_notification::update_animation(u64 t)
{
// Update rate is twice per second
auto elapsed = t - creation_time;
elapsed /= 500000;
auto old_dot = current_dot;
current_dot = elapsed % 3;
if (old_dot != current_dot)
{
if (old_dot != 255)
{
dots[old_dot].set_size(2, 2);
dots[old_dot].translate(0, 1);
}
dots[current_dot].translate(0, -1);
dots[current_dot].set_size(3, 3);
}
}
// Extends visible time by half a second. Also updates the screen
void shader_compile_notification::touch()
{
if (urgency_ctr == 0 || urgency_ctr > 8)
{
refresh();
urgency_ctr = 0;
}
expire_time = get_system_time() + 500000;
urgency_ctr++;
}
void shader_compile_notification::update()
{
auto current_time = get_system_time();
if (current_time > expire_time)
close();
update_animation(current_time);
// Usually this method is called during a draw-to-screen operation. Reset urgency ctr
urgency_ctr = 1;
}
compiled_resource shader_compile_notification::get_compiled()
{
auto compiled = m_text.get_compiled();
compiled.add(dots[0].get_compiled());
compiled.add(dots[1].get_compiled());
compiled.add(dots[2].get_compiled());
return compiled;
}
} // namespace overlays
} // namespace rsx

View File

@ -0,0 +1,70 @@
#include "stdafx.h"
#include "overlays.h"
namespace rsx
{
namespace overlays
{
trophy_notification::trophy_notification()
{
frame.set_pos(0, 0);
frame.set_size(260, 80);
frame.back_color.a = 0.85f;
image.set_pos(8, 8);
image.set_size(64, 64);
image.back_color.a = 0.f;
text_view.set_pos(85, 0);
text_view.set_padding(0, 0, 24, 0);
text_view.set_font("Arial", 8);
text_view.align_text(overlay_element::text_align::center);
text_view.back_color.a = 0.f;
}
void trophy_notification::update()
{
u64 t = get_system_time();
if (((t - creation_time) / 1000) > 7500)
close();
}
compiled_resource trophy_notification::get_compiled()
{
auto result = frame.get_compiled();
result.add(image.get_compiled());
result.add(text_view.get_compiled());
return result;
}
s32 trophy_notification::show(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophy_icon_buffer)
{
if (trophy_icon_buffer.size())
{
icon_info = std::make_unique<image_info>(trophy_icon_buffer);
image.set_raw_image(icon_info.get());
}
std::string trophy_message;
switch (trophy.trophyGrade)
{
case SCE_NP_TROPHY_GRADE_BRONZE: trophy_message = "bronze"; break;
case SCE_NP_TROPHY_GRADE_SILVER: trophy_message = "silver"; break;
case SCE_NP_TROPHY_GRADE_GOLD: trophy_message = "gold"; break;
case SCE_NP_TROPHY_GRADE_PLATINUM: trophy_message = "platinum"; break;
default: break;
}
trophy_message = "You have earned the " + trophy_message + " trophy\n" + utf8_to_ascii8(trophy.name);
text_view.set_text(trophy_message);
text_view.auto_resize();
// Resize background to cover the text
u16 margin_sz = text_view.x - image.w - image.x;
frame.w = text_view.x + text_view.w + margin_sz;
creation_time = get_system_time();
return CELL_OK;
}
} // namespace overlays
} // namespace rsx

View File

@ -496,76 +496,7 @@ namespace rsx
std::unique_ptr<image_info> icon_data;
public:
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.size())
{
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>(utf8_to_ascii8(text1));
std::unique_ptr<overlay_element> subtext = std::make_unique<label>(utf8_to_ascii8(text2));
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>(utf8_to_ascii8(text3));
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_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> m_dim_background;
@ -577,177 +508,14 @@ namespace rsx
bool m_no_saves = false;
public:
save_dialog()
{
m_dim_background = std::make_unique<overlay_element>();
m_dim_background->set_size(1280, 720);
save_dialog();
m_list = std::make_unique<list_view>(1240, 540);
m_description = std::make_unique<label>();
m_time_thingy = std::make_unique<label>();
void update() override;
void on_button_pressed(pad_button button_press) override;
m_list->set_pos(20, 85);
compiled_resource get_compiled() override;
m_description->set_font("Arial", 20);
m_description->set_pos(20, 37);
m_description->set_text("Save Dialog");
m_time_thingy->set_font("Arial", 14);
m_time_thingy->set_pos(1000, 30);
m_time_thingy->set_text(date_time::current_time());
static_cast<label*>(m_description.get())->auto_resize();
static_cast<label*>(m_time_thingy.get())->auto_resize();
m_dim_background->back_color.a = 0.8f;
m_description->back_color.a = 0.f;
m_time_thingy->back_color.a = 0.f;
return_code = selection_code::canceled;
}
void on_button_pressed(pad_button button_press) override
{
switch (button_press)
{
case pad_button::cross:
if (m_no_saves)
break;
return_code = m_list->get_selected_index();
// Fall through
case pad_button::circle:
close();
break;
case pad_button::dpad_up:
m_list->select_previous();
break;
case pad_button::dpad_down:
m_list->select_next();
break;
default:
LOG_TRACE(RSX, "[ui] Button %d pressed", (u8)button_press);
}
}
compiled_resource get_compiled() override
{
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());
return result;
}
s32 show(std::vector<SaveDataEntry>& save_entries, u32 op, vm::ptr<CellSaveDataListSet> listSet)
{
std::vector<u8> icon;
std::vector<std::unique_ptr<overlay_element>> entries;
for (auto& entry : save_entries)
{
std::unique_ptr<overlay_element> e;
e = std::make_unique<save_dialog_entry>(entry.title, entry.subtitle, entry.details, image_resource_id::raw_image, entry.iconBuf);
entries.emplace_back(std::move(e));
}
if (op >= 8)
{
m_description->set_text("Delete Save");
}
else if (op & 1)
{
m_description->set_text("Load Save");
}
else
{
m_description->set_text("Save");
}
const bool newpos_head = listSet->newData && listSet->newData->iconPosition == CELL_SAVEDATA_ICONPOS_HEAD;
if (!newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (listSet->newData)
{
std::unique_ptr<overlay_element> new_stub;
const char* title = "Create New";
int id = resource_config::standard_image_resource::new_entry;
if (auto picon = +listSet->newData->icon)
{
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;
}
new_stub = std::make_unique<save_dialog_entry>(title, "Select to create a new entry", "", id, icon);
m_list->add_entry(new_stub);
}
if (newpos_head)
{
for (auto& entry : entries)
{
m_list->add_entry(entry);
}
}
if (!m_list->m_items.size())
{
m_no_saves_text = std::make_unique<label>("There is no saved data.");
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);
}
static_cast<label*>(m_description.get())->auto_resize();
if (auto err = run_input_loop())
return err;
if (return_code == entries.size() && !newpos_head)
return selection_code::new_save;
if (return_code >= 0 && newpos_head)
return return_code - 1;
return return_code;
}
void update() override
{
m_time_thingy->set_text(date_time::current_time());
static_cast<label*>(m_time_thingy.get())->auto_resize();
}
s32 show(std::vector<SaveDataEntry>& save_entries, u32 op, vm::ptr<CellSaveDataListSet> listSet);
};
struct message_dialog : public user_interface
@ -771,300 +539,20 @@ namespace rsx
std::unique_ptr<image_info> background_image;
public:
message_dialog(bool use_custom_background = false)
{
background.set_size(1280, 720);
background.back_color.a = 0.85f;
message_dialog(bool use_custom_background = false);
text_display.set_size(1100, 40);
text_display.set_pos(90, 364);
text_display.set_font("Arial", 16);
text_display.align_text(overlay_element::text_align::center);
text_display.set_wrap_text(true);
text_display.back_color.a = 0.f;
compiled_resource get_compiled() override;
bottom_bar.back_color = color4f(1.f, 1.f, 1.f, 1.f);
bottom_bar.set_size(1200, 2);
bottom_bar.set_pos(40, 400);
void on_button_pressed(pad_button button_press) override;
progress_1.set_size(800, 4);
progress_2.set_size(800, 4);
progress_1.back_color = color4f(0.25f, 0.f, 0.f, 0.85f);
progress_2.back_color = color4f(0.25f, 0.f, 0.f, 0.85f);
error_code show(const std::string& text, const MsgDialogType& type, std::function<void(s32 status)> on_close);
btn_ok.set_text("Yes");
btn_ok.set_size(140, 30);
btn_ok.set_pos(545, 420);
btn_ok.set_font("Arial", 16);
btn_cancel.set_text("No");
btn_cancel.set_size(140, 30);
btn_cancel.set_pos(685, 420);
btn_cancel.set_font("Arial", 16);
if (g_cfg.sys.enter_button_assignment == enter_button_assign::circle)
{
btn_ok.set_image_resource(resource_config::standard_image_resource::circle);
btn_cancel.set_image_resource(resource_config::standard_image_resource::cross);
}
else
{
btn_ok.set_image_resource(resource_config::standard_image_resource::cross);
btn_cancel.set_image_resource(resource_config::standard_image_resource::circle);
}
if (use_custom_background)
{
auto icon_path = Emu.GetSfoDir() + "/PIC1.PNG";
if (!fs::exists(icon_path))
{
// Fallback path
icon_path = Emu.GetSfoDir() + "/ICON0.PNG";
}
if (fs::exists(icon_path))
{
background_image = std::make_unique<image_info>(icon_path.c_str());
if (background_image->data)
{
f32 color = (100 - g_cfg.video.shader_preloading_dialog.darkening_strength) / 100.f;
background_poster.fore_color = color4f(color, color, color, 1.);
background.back_color.a = 0.f;
background_poster.set_size(1280, 720);
background_poster.set_raw_image(background_image.get());
background_poster.set_blur_strength((u8)g_cfg.video.shader_preloading_dialog.blur_strength);
}
}
}
return_code = CELL_MSGDIALOG_BUTTON_NONE;
}
compiled_resource get_compiled() override
{
compiled_resource result;
if (background_image && background_image->data)
{
result.add(background_poster.get_compiled());
}
result.add(background.get_compiled());
result.add(text_display.get_compiled());
if (num_progress_bars > 0)
{
result.add(progress_1.get_compiled());
}
if (num_progress_bars > 1)
{
result.add(progress_2.get_compiled());
}
if (interactive)
{
if (!num_progress_bars)
result.add(bottom_bar.get_compiled());
if (!cancel_only)
result.add(btn_ok.get_compiled());
if (!ok_only)
result.add(btn_cancel.get_compiled());
}
return result;
}
void on_button_pressed(pad_button button_press) override
{
switch (button_press)
{
case pad_button::cross:
{
if (ok_only)
{
return_code = CELL_MSGDIALOG_BUTTON_OK;
}
else if (cancel_only)
{
// Do not accept for cancel-only dialogs
return;
}
else
{
return_code = CELL_MSGDIALOG_BUTTON_YES;
}
break;
}
case pad_button::circle:
{
if (ok_only)
{
// Ignore cancel operation for Ok-only
return;
}
else if (cancel_only)
{
return_code = CELL_MSGDIALOG_BUTTON_ESCAPE;
}
else
{
return_code = CELL_MSGDIALOG_BUTTON_NO;
}
break;
}
default:
return;
}
close();
}
error_code show(const std::string& text, const MsgDialogType &type, std::function<void(s32 status)> on_close)
{
num_progress_bars = type.progress_bar_count;
if (num_progress_bars)
{
u16 offset = 58;
progress_1.set_pos(240, 412);
if (num_progress_bars > 1)
{
progress_2.set_pos(240, 462);
offset = 98;
}
// Push the other stuff down
bottom_bar.translate(0, offset);
btn_ok.translate(0, offset);
btn_cancel.translate(0, offset);
}
text_display.set_text(utf8_to_ascii8(text));
u16 text_w, text_h;
text_display.measure_text(text_w, text_h);
text_display.translate(0, -(text_h - 16));
switch (type.button_type.unshifted())
{
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE:
interactive = !type.disable_cancel;
if (interactive)
{
btn_cancel.set_pos(585, btn_cancel.y);
btn_cancel.set_text("Cancel");
cancel_only = true;
}
break;
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
btn_ok.set_pos(600, btn_ok.y);
btn_ok.set_text("OK");
interactive = true;
ok_only = true;
break;
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
interactive = true;
break;
}
this->on_close = on_close;
if (interactive)
{
thread_ctrl::spawn("dialog input thread", [&]
{
if (auto error = run_input_loop())
{
LOG_ERROR(RSX, "Dialog input loop exited with error code=%d", error);
}
});
}
return CELL_OK;
}
u32 progress_bar_count()
{
return num_progress_bars;
}
void progress_bar_set_taskbar_index(s32 index)
{
taskbar_index = index;
}
error_code progress_bar_set_message(u32 index, const std::string& msg)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_text(msg);
else
progress_2.set_text(msg);
return CELL_OK;
}
error_code progress_bar_increment(u32 index, f32 value)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.inc(value);
else
progress_2.inc(value);
if (index == taskbar_index || taskbar_index == -1)
Emu.GetCallbacks().handle_taskbar_progress(1, (s32)value);
return CELL_OK;
}
error_code progress_bar_reset(u32 index)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_value(0.f);
else
progress_2.set_value(0.f);
Emu.GetCallbacks().handle_taskbar_progress(0, 0);
return CELL_OK;
}
error_code progress_bar_set_limit(u32 index, u32 limit)
{
if (index >= num_progress_bars)
return CELL_MSGDIALOG_ERROR_PARAM;
if (index == 0)
progress_1.set_limit((float)limit);
else
progress_2.set_limit((float)limit);
if (index == taskbar_index)
{
taskbar_limit = limit;
Emu.GetCallbacks().handle_taskbar_progress(2, taskbar_limit);
}
else if (taskbar_index == -1)
{
taskbar_limit += limit;
Emu.GetCallbacks().handle_taskbar_progress(2, taskbar_limit);
}
return CELL_OK;
}
u32 progress_bar_count();
void progress_bar_set_taskbar_index(s32 index);
error_code progress_bar_set_message(u32 index, const std::string& msg);
error_code progress_bar_increment(u32 index, f32 value);
error_code progress_bar_reset(u32 index);
error_code progress_bar_set_limit(u32 index, u32 limit);
};
struct trophy_notification : public user_interface
@ -1078,68 +566,13 @@ namespace rsx
std::unique_ptr<image_info> icon_info;
public:
trophy_notification()
{
frame.set_pos(0, 0);
frame.set_size(260, 80);
frame.back_color.a = 0.85f;
trophy_notification();
image.set_pos(8, 8);
image.set_size(64, 64);
image.back_color.a = 0.f;
void update() override;
text_view.set_pos(85, 0);
text_view.set_padding(0, 0, 24, 0);
text_view.set_font("Arial", 8);
text_view.align_text(overlay_element::text_align::center);
text_view.back_color.a = 0.f;
}
compiled_resource get_compiled() override;
void update() override
{
u64 t = get_system_time();
if (((t - creation_time) / 1000) > 7500)
close();
}
compiled_resource get_compiled() override
{
auto result = frame.get_compiled();
result.add(image.get_compiled());
result.add(text_view.get_compiled());
return result;
}
s32 show(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophy_icon_buffer)
{
if (trophy_icon_buffer.size())
{
icon_info = std::make_unique<image_info>(trophy_icon_buffer);
image.set_raw_image(icon_info.get());
}
std::string trophy_message;
switch (trophy.trophyGrade)
{
case SCE_NP_TROPHY_GRADE_BRONZE: trophy_message = "bronze"; break;
case SCE_NP_TROPHY_GRADE_SILVER: trophy_message = "silver"; break;
case SCE_NP_TROPHY_GRADE_GOLD: trophy_message = "gold"; break;
case SCE_NP_TROPHY_GRADE_PLATINUM: trophy_message = "platinum"; break;
default: break;
}
trophy_message = "You have earned the " + trophy_message + " trophy\n" + utf8_to_ascii8(trophy.name);
text_view.set_text(trophy_message);
text_view.auto_resize();
//Resize background to cover the text
u16 margin_sz = text_view.x - image.w - image.x;
frame.w = text_view.x + text_view.w + margin_sz;
creation_time = get_system_time();
return CELL_OK;
}
s32 show(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophy_icon_buffer);
};
struct shader_compile_notification : user_interface
@ -1153,88 +586,13 @@ namespace rsx
u64 expire_time = 0; // Time to end the prompt
u64 urgency_ctr = 0; // How critical it is to show to the user
shader_compile_notification()
{
const u16 pos_x = g_cfg.video.shader_compilation_hint.pos_x;
const u16 pos_y = g_cfg.video.shader_compilation_hint.pos_y;
shader_compile_notification();
m_text.set_font("Arial", 16);
m_text.set_text("Compiling shaders");
m_text.auto_resize();
m_text.set_pos(pos_x, pos_y);
void update_animation(u64 t);
void touch();
void update() override;
m_text.back_color.a = 0.f;
for (int n = 0; n < 3; ++n)
{
dots[n].set_size(2, 2);
dots[n].back_color = color4f(1.f, 1.f, 1.f, 1.f);
dots[n].set_pos(m_text.w + pos_x + 5 + (6 * n), pos_y + 20);
}
creation_time = get_system_time();
expire_time = creation_time + 1000000;
// Disable forced refresh unless fps dips below 4
min_refresh_duration_us = 250000;
}
void update_animation(u64 t)
{
// Update rate is twice per second
auto elapsed = t - creation_time;
elapsed /= 500000;
auto old_dot = current_dot;
current_dot = elapsed % 3;
if (old_dot != current_dot)
{
if (old_dot != 255)
{
dots[old_dot].set_size(2, 2);
dots[old_dot].translate(0, 1);
}
dots[current_dot].translate(0, -1);
dots[current_dot].set_size(3, 3);
}
}
// Extends visible time by half a second. Also updates the screen
void touch()
{
if (urgency_ctr == 0 || urgency_ctr > 8)
{
refresh();
urgency_ctr = 0;
}
expire_time = get_system_time() + 500000;
urgency_ctr++;
}
void update() override
{
auto current_time = get_system_time();
if (current_time > expire_time)
close();
update_animation(current_time);
// Usually this method is called during a draw-to-screen operation. Reset urgency ctr
urgency_ctr = 1;
}
compiled_resource get_compiled() override
{
auto compiled = m_text.get_compiled();
compiled.add(dots[0].get_compiled());
compiled.add(dots[1].get_compiled());
compiled.add(dots[2].get_compiled());
return compiled;
}
compiled_resource get_compiled() override;
};
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug - LLVM|x64">
@ -304,8 +304,16 @@
</ClCompile>
<ClCompile Include="Emu\RSX\Null\NullGSRender.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlays.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_edit_text.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_font.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_list_view.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_message_dialog.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_osk.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_perf_metrics.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_progress_bar.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_save_dialog.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_shader_compile_notification.cpp" />
<ClCompile Include="Emu\RSX\Overlays\overlay_trophy_notification.cpp" />
<ClCompile Include="Emu\RSX\RSXFIFO.cpp" />
<ClCompile Include="Emu\RSX\rsx_methods.cpp" />
<ClCompile Include="Emu\RSX\rsx_utils.cpp" />

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
@ -782,6 +782,30 @@
<ClCompile Include="Emu\Cell\lv2\sys_overlay.cpp">
<Filter>Emu\Cell\lv2</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_save_dialog.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_message_dialog.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_shader_compile_notification.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_trophy_notification.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_font.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_list_view.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_edit_text.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_progress_bar.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">