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

overlays: get localized values in home menu settings

This commit is contained in:
Megamouse 2024-11-14 23:48:51 +01:00
parent 1211acd59c
commit 070add461f
12 changed files with 139 additions and 13 deletions

View File

@ -15,8 +15,10 @@ void fmt_class_string<cfg::node>::format(std::string& out, u64 arg)
namespace cfg namespace cfg
{ {
u32 _base::id_counter = 0;
_base::_base(type _type) _base::_base(type _type)
: m_type(_type) : m_type(_type), m_id(id_counter++)
{ {
if (_type != type::node) if (_type != type::node)
{ {
@ -25,7 +27,7 @@ namespace cfg
} }
_base::_base(type _type, node* owner, std::string name, bool dynamic) _base::_base(type _type, node* owner, std::string name, bool dynamic)
: m_type(_type), m_dynamic(dynamic), m_name(std::move(name)) : m_type(_type), m_parent(owner), m_dynamic(dynamic), m_name(std::move(name)), m_id(id_counter++)
{ {
for (const auto& node : owner->m_nodes) for (const auto& node : owner->m_nodes)
{ {

View File

@ -51,9 +51,13 @@ namespace cfg
const type m_type{}; const type m_type{};
protected: protected:
_base* m_parent = nullptr;
bool m_dynamic = true; bool m_dynamic = true;
const std::string m_name{}; const std::string m_name{};
static u32 id_counter;
u32 m_id = 0;
// Ownerless entry constructor // Ownerless entry constructor
_base(type _type); _base(type _type);
@ -67,9 +71,16 @@ namespace cfg
virtual ~_base() = default; virtual ~_base() = default;
// Get unique ID
u32 get_id() const { return m_id; }
// Get parent
_base* get_parent() const { return m_parent; }
// Get type // Get type
type get_type() const { return m_type; } type get_type() const { return m_type; }
// Get name
const std::string& get_name() const { return m_name; } const std::string& get_name() const { return m_name; }
// Get dynamic property for reloading configs during games // Get dynamic property for reloading configs during games

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Emu/RSX/Overlays/overlays.h" #include "Emu/RSX/Overlays/overlays.h"
#include "Emu/System.h"
#include "Utilities/Config.h" #include "Utilities/Config.h"
namespace rsx namespace rsx
@ -102,7 +103,8 @@ namespace rsx
if (!this->is_compiled) if (!this->is_compiled)
{ {
m_dropdown.set_text(fmt::format("%s", this->m_last_value)); const std::string value_text = Emu.GetCallbacks().get_localized_setting(home_menu_setting<T, cfg::_enum<T>>::m_setting, static_cast<u32>(this->m_last_value));
m_dropdown.set_text(value_text);
m_dropdown.set_pos(m_dropdown.x, this->y + (this->h - m_dropdown.h) / 2); m_dropdown.set_pos(m_dropdown.x, this->y + (this->h - m_dropdown.h) / 2);
this->compiled_resources = horizontal_layout::get_compiled(); this->compiled_resources = horizontal_layout::get_compiled();

View File

@ -3,8 +3,6 @@
#include "overlay_home_menu_components.h" #include "overlay_home_menu_components.h"
#include "Emu/system_config.h" #include "Emu/system_config.h"
// TODO: Localization of the dropdown values
namespace rsx namespace rsx
{ {
namespace overlays namespace overlays

View File

@ -61,7 +61,7 @@ namespace rsx
if (setting) if (setting)
{ {
usz new_index = 0; usz new_index = 0;
T value = setting->get(); const T value = setting->get();
const std::string val = fmt::format("%s", value); const std::string val = fmt::format("%s", value);
const std::vector<std::string> list = setting->to_list(); const std::vector<std::string> list = setting->to_list();

View File

@ -24,6 +24,11 @@ class spu_thread;
template <typename T> template <typename T>
class named_thread; class named_thread;
namespace cfg
{
class _base;
}
enum class system_state : u32 enum class system_state : u32
{ {
stopped, stopped,
@ -93,6 +98,7 @@ struct EmuCallbacks
std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog; std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
std::function<std::string(localized_string_id, const char*)> get_localized_string; std::function<std::string(localized_string_id, const char*)> get_localized_string;
std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string; std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string;
std::function<std::string(const cfg::_base*, u32)> get_localized_setting;
std::function<void(const std::string&)> play_sound; std::function<void(const std::string&)> play_sound;
std::function<bool(const std::string&, std::string&, s32&, s32&, s32&)> get_image_info; // (filename, sub_type, width, height, CellSearchOrientation) std::function<bool(const std::string&, std::string&, s32&, s32&, s32&)> get_image_info; // (filename, sub_type, width, height, CellSearchOrientation)
std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit) std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit)

View File

@ -161,6 +161,7 @@ void headless_application::InitializeCallbacks()
callbacks.get_localized_string = [](localized_string_id, const char*) -> std::string { return {}; }; callbacks.get_localized_string = [](localized_string_id, const char*) -> std::string { return {}; };
callbacks.get_localized_u32string = [](localized_string_id, const char*) -> std::u32string { return {}; }; callbacks.get_localized_u32string = [](localized_string_id, const char*) -> std::u32string { return {}; };
callbacks.get_localized_setting = [](const cfg::_base*, u32) -> std::string { return {}; };
callbacks.play_sound = [](const std::string&){}; callbacks.play_sound = [](const std::string&){};
callbacks.add_breakpoint = [](u32 /*addr*/){}; callbacks.add_breakpoint = [](u32 /*addr*/){};

View File

@ -189,7 +189,7 @@ bool emu_settings::ValidateSettings(bool cleanup)
for (const auto& yml_entry : yml_node) for (const auto& yml_entry : yml_node)
{ {
const std::string key = yml_entry.first.Scalar(); const std::string& key = yml_entry.first.Scalar();
cfg::_base* cfg_node = nullptr; cfg::_base* cfg_node = nullptr;
keys.resize(next_level); keys.resize(next_level);
@ -253,13 +253,13 @@ bool emu_settings::ValidateSettings(bool cleanup)
} }
}; };
cfg_root root; std::unique_ptr<cfg_root> root = std::make_unique<cfg_root>();
std::vector<std::string> keys; std::vector<std::string> keys;
do do
{ {
is_clean = true; is_clean = true;
search_level(0, m_current_settings, keys, &root); search_level(0, m_current_settings, keys, root.get());
} }
while (cleanup && !is_clean); while (cleanup && !is_clean);
@ -885,6 +885,64 @@ void emu_settings::SetSetting(emu_settings_type type, const std::string& val) co
cfg_adapter::get_node(m_current_settings, ::at32(settings_location, type)) = val; cfg_adapter::get_node(m_current_settings, ::at32(settings_location, type)) = val;
} }
emu_settings_type emu_settings::FindSettingsType(const cfg::_base* node) const
{
// Add key and value to static map on first use
static std::map<u32, emu_settings_type> id_to_type;
static std::mutex mtx;
std::lock_guard lock(mtx);
if (!node) [[unlikely]]
{
// Provoke error. Don't use ensure or we will get a nullptr deref warning in VS
return ::at32(id_to_type, umax);
}
std::vector<std::string> node_location;
if (!id_to_type.contains(node->get_id()))
{
for (const cfg::_base* n = node; n; n = n->get_parent())
{
if (!n->get_name().empty())
{
node_location.push_back(n->get_name());
}
}
std::reverse(node_location.begin(), node_location.end());
for (const auto& [type, loc]: settings_location)
{
if (node_location.size() != loc.size())
{
continue;
}
bool is_match = true;
for (usz i = 0; i < node_location.size(); i++)
{
if (node_location[i] != loc[i])
{
is_match = false;
break;
}
}
if (is_match && !id_to_type.try_emplace(node->get_id(), type).second)
{
cfg_log.error("'%s' already exists", loc.back());
}
}
}
if (!id_to_type.contains(node->get_id()))
{
fmt::throw_exception("Node '%s' not represented in emu_settings_type", node->get_name());
}
return ::at32(id_to_type, node->get_id());
}
void emu_settings::OpenCorrectionDialog(QWidget* parent) void emu_settings::OpenCorrectionDialog(QWidget* parent)
{ {
if (!m_broken_types.empty() && QMessageBox::question(parent, tr("Fix invalid settings?"), if (!m_broken_types.empty() && QMessageBox::question(parent, tr("Fix invalid settings?"),
@ -1166,6 +1224,16 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case detail_level::high: return tr("High", "Detail Level"); case detail_level::high: return tr("High", "Detail Level");
} }
break; break;
case emu_settings_type::PerfOverlayFramerateDetailLevel:
case emu_settings_type::PerfOverlayFrametimeDetailLevel:
switch (static_cast<perf_graph_detail_level>(index))
{
case perf_graph_detail_level::minimal: return tr("Minimal", "Perf Graph Detail Level");
case perf_graph_detail_level::show_min_max: return tr("Show Min And Max", "Perf Graph Detail Level");
case perf_graph_detail_level::show_one_percent_avg: return tr("Show 1% Low And Average", "Perf Graph Detail Level");
case perf_graph_detail_level::show_all: return tr("Show All", "Perf Graph Detail Level");
}
break;
case emu_settings_type::PerfOverlayPosition: case emu_settings_type::PerfOverlayPosition:
switch (static_cast<screen_quadrant>(index)) switch (static_cast<screen_quadrant>(index))
{ {
@ -1386,3 +1454,15 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
return original; return original;
} }
std::string emu_settings::GetLocalizedSetting(const std::string& original, emu_settings_type type, int index, bool strict) const
{
return GetLocalizedSetting(QString::fromStdString(original), type, index, strict).toStdString();
}
std::string emu_settings::GetLocalizedSetting(const cfg::_base* node, u32 index) const
{
const emu_settings_type type = FindSettingsType(node);
const std::vector<std::string> settings = GetSettingOptions(type);
return GetLocalizedSetting(::at32(settings, index), type, index, true);
}

View File

@ -18,6 +18,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace cfg
{
class _base;
}
constexpr auto qstr = QString::fromStdString;
class emu_settings : public QObject class emu_settings : public QObject
{ {
/** A settings class for Emulator specific settings. This class is a refactored version of the wx version. It is much nicer /** A settings class for Emulator specific settings. This class is a refactored version of the wx version. It is much nicer
@ -76,6 +83,9 @@ public:
/** Sets the setting type to a given value.*/ /** Sets the setting type to a given value.*/
void SetSetting(emu_settings_type type, const std::string& val) const; void SetSetting(emu_settings_type type, const std::string& val) const;
/** Try to find the settings type for a given string.*/
emu_settings_type FindSettingsType(const cfg::_base* node) const;
/** Gets all the renderer info for gpu settings.*/ /** Gets all the renderer info for gpu settings.*/
render_creator* m_render_creator = nullptr; render_creator* m_render_creator = nullptr;
@ -94,6 +104,12 @@ public:
/** Get a localized and therefore freely adjustable version of the string used in config.yml.*/ /** Get a localized and therefore freely adjustable version of the string used in config.yml.*/
QString GetLocalizedSetting(const QString& original, emu_settings_type type, int index, bool strict) const; QString GetLocalizedSetting(const QString& original, emu_settings_type type, int index, bool strict) const;
/** Get a localized and therefore freely adjustable version of the string used in config.yml.*/
std::string GetLocalizedSetting(const std::string& original, emu_settings_type type, int index, bool strict) const;
/** Get a localized and therefore freely adjustable version of the string used in config.yml.*/
std::string GetLocalizedSetting(const cfg::_base* node, u32 index) const;
/** Validates the settings and logs unused entries or cleans up the yaml*/ /** Validates the settings and logs unused entries or cleans up the yaml*/
bool ValidateSettings(bool cleanup); bool ValidateSettings(bool cleanup);

View File

@ -111,6 +111,8 @@ enum class emu_settings_type
PerfOverlayFramerateDatapoints, PerfOverlayFramerateDatapoints,
PerfOverlayFrametimeDatapoints, PerfOverlayFrametimeDatapoints,
PerfOverlayDetailLevel, PerfOverlayDetailLevel,
PerfOverlayFramerateDetailLevel,
PerfOverlayFrametimeDetailLevel,
PerfOverlayPosition, PerfOverlayPosition,
PerfOverlayUpdateInterval, PerfOverlayUpdateInterval,
PerfOverlayFontSize, PerfOverlayFontSize,
@ -306,6 +308,8 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
{ emu_settings_type::PerfOverlayFramerateDatapoints, { "Video", "Performance Overlay", "Framerate datapoints" } }, { emu_settings_type::PerfOverlayFramerateDatapoints, { "Video", "Performance Overlay", "Framerate datapoints" } },
{ emu_settings_type::PerfOverlayFrametimeDatapoints, { "Video", "Performance Overlay", "Frametime datapoints" } }, { emu_settings_type::PerfOverlayFrametimeDatapoints, { "Video", "Performance Overlay", "Frametime datapoints" } },
{ emu_settings_type::PerfOverlayDetailLevel, { "Video", "Performance Overlay", "Detail level" } }, { emu_settings_type::PerfOverlayDetailLevel, { "Video", "Performance Overlay", "Detail level" } },
{ emu_settings_type::PerfOverlayFramerateDetailLevel, { "Video", "Performance Overlay", "Framerate graph detail level" } },
{ emu_settings_type::PerfOverlayFrametimeDetailLevel, { "Video", "Performance Overlay", "Frametime graph detail level" } },
{ emu_settings_type::PerfOverlayPosition, { "Video", "Performance Overlay", "Position" } }, { emu_settings_type::PerfOverlayPosition, { "Video", "Performance Overlay", "Position" } },
{ emu_settings_type::PerfOverlayUpdateInterval, { "Video", "Performance Overlay", "Metrics update interval (ms)" } }, { emu_settings_type::PerfOverlayUpdateInterval, { "Video", "Performance Overlay", "Metrics update interval (ms)" } },
{ emu_settings_type::PerfOverlayFontSize, { "Video", "Performance Overlay", "Font size (px)" } }, { emu_settings_type::PerfOverlayFontSize, { "Video", "Performance Overlay", "Font size (px)" } },

View File

@ -606,6 +606,12 @@ void gui_application::InitializeCallbacks()
return localized_emu::get_u32string(id, args); return localized_emu::get_u32string(id, args);
}; };
callbacks.get_localized_setting = [this](const cfg::_base* node, u32 enum_index) -> std::string
{
ensure(!!m_emu_settings);
return m_emu_settings->GetLocalizedSetting(node, enum_index);
};
callbacks.play_sound = [this](const std::string& path) callbacks.play_sound = [this](const std::string& path)
{ {
Emu.CallFromMainThread([this, path]() Emu.CallFromMainThread([this, path]()

View File

@ -448,9 +448,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
r_creator->update_names( r_creator->update_names(
{ {
m_emu_settings->GetLocalizedSetting("Vulkan", emu_settings_type::Renderer, static_cast<int>(video_renderer::vulkan), true), m_emu_settings->GetLocalizedSetting(QString("Vulkan"), emu_settings_type::Renderer, static_cast<int>(video_renderer::vulkan), true),
m_emu_settings->GetLocalizedSetting("OpenGl", emu_settings_type::Renderer, static_cast<int>(video_renderer::opengl), true), m_emu_settings->GetLocalizedSetting(QString("OpenGl"), emu_settings_type::Renderer, static_cast<int>(video_renderer::opengl), true),
m_emu_settings->GetLocalizedSetting("Null", emu_settings_type::Renderer, static_cast<int>(video_renderer::null), true) m_emu_settings->GetLocalizedSetting(QString("Null"), emu_settings_type::Renderer, static_cast<int>(video_renderer::null), true)
}); });
// Comboboxes // Comboboxes
@ -1098,7 +1098,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
}; };
for (const audio_format_flag& audio_fmt : audio_formats) for (const audio_format_flag& audio_fmt : audio_formats)
{ {
const QString audio_format_name = m_emu_settings->GetLocalizedSetting("", emu_settings_type::AudioFormats, static_cast<int>(audio_fmt), true); const QString audio_format_name = m_emu_settings->GetLocalizedSetting(QString(), emu_settings_type::AudioFormats, static_cast<int>(audio_fmt), true);
QListWidgetItem* item = new QListWidgetItem(audio_format_name, ui->list_audio_formats); QListWidgetItem* item = new QListWidgetItem(audio_format_name, ui->list_audio_formats);
item->setData(Qt::UserRole, static_cast<u32>(audio_fmt)); item->setData(Qt::UserRole, static_cast<u32>(audio_fmt));
if (audio_fmt == audio_format_flag::lpcm_2_48khz) if (audio_fmt == audio_format_flag::lpcm_2_48khz)