From e62f3bd4a83270bdebf9301b650af2d497b56c5f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 6 Apr 2025 20:31:40 +1000 Subject: [PATCH] PostProcessing: Show Reshade ui_text style help text --- src/core/fullscreen_ui.cpp | 18 +++++++++++++++++- .../postprocessingsettingswidget.cpp | 14 +++++++++++++- src/util/postprocessing.cpp | 7 +++++++ src/util/postprocessing.h | 13 ++++++++----- src/util/postprocessing_shader_fx.cpp | 1 + 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index d0d296a83..07aa0d7a1 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -5854,7 +5854,23 @@ void FullscreenUI::DrawPostProcessingSettingsPage() for (PostProcessing::ShaderOption& opt : si.options) { - if (opt.ui_name.empty()) + if (!opt.help_text.empty()) + { + const float width = ImGui::GetCurrentWindow()->WorkRect.GetWidth(); + const ImVec2 text_size = + UIStyle.MediumFont->CalcTextSizeA(UIStyle.MediumFont->FontSize, FLT_MAX, width, opt.help_text.c_str(), + opt.help_text.c_str() + opt.help_text.length()); + ImVec2 pos, size; + ImGuiFullscreen::GetMenuButtonFrameBounds(LayoutUnscale(text_size.y), &pos, &size); + const ImVec2& frame_padding = ImGui::GetStyle().FramePadding; + const ImRect rect = ImRect(pos + frame_padding, pos + size - frame_padding); + ImGui::ItemSize(size); + RenderShadowedTextClipped(UIStyle.MediumFont, rect.Min, rect.Max, ImGui::GetColorU32(ImGuiCol_TextDisabled), + opt.help_text.c_str(), opt.help_text.c_str() + opt.help_text.length(), &text_size, + ImVec2(0.0f, 0.0f), width, &rect); + } + + if (opt.ShouldHide()) continue; switch (opt.type) diff --git a/src/duckstation-qt/postprocessingsettingswidget.cpp b/src/duckstation-qt/postprocessingsettingswidget.cpp index 26ea4f253..a6b686fe6 100644 --- a/src/duckstation-qt/postprocessingsettingswidget.cpp +++ b/src/duckstation-qt/postprocessingsettingswidget.cpp @@ -337,7 +337,8 @@ void PostProcessingShaderConfigWidget::createUi() for (PostProcessing::ShaderOption& option : m_options) { - if (option.ui_name.empty()) + const bool should_hide = option.ShouldHide(); + if (should_hide && option.help_text.empty()) continue; if (!last_category || option.category != *last_category) @@ -368,6 +369,17 @@ void PostProcessingShaderConfigWidget::createUi() const QString tooltip = QString::fromStdString(option.tooltip); + if (!option.help_text.empty()) + { + QLabel* label = new QLabel(QString::fromStdString(option.help_text), this); + label->setWordWrap(true); + m_layout->addWidget(label, row++, 0, 1, 3); + m_widgets.push_back(label); + } + + if (should_hide) + continue; + if (option.type == PostProcessing::ShaderOption::Type::Bool) { QCheckBox* checkbox = new QCheckBox(QString::fromStdString(option.ui_name), this); diff --git a/src/util/postprocessing.cpp b/src/util/postprocessing.cpp index aed3cf471..80b4190c8 100644 --- a/src/util/postprocessing.cpp +++ b/src/util/postprocessing.cpp @@ -90,6 +90,13 @@ u32 PostProcessing::ShaderOption::ParseFloatVector(std::string_view line, ValueV return ParseVector(line, values); } +bool PostProcessing::ShaderOption::ShouldHide() const +{ + // Typical for reshade shaders to have help text in ui_text, and a radio button with no valid range. + return (ui_name.empty() || (StringUtil::StripWhitespace(ui_name).empty() && + std::memcmp(min_value.data(), max_value.data(), sizeof(min_value)) == 0)); +} + u32 PostProcessing::ShaderOption::ParseIntVector(std::string_view line, ValueVector* values) { return ParseVector(line, values); diff --git a/src/util/postprocessing.h b/src/util/postprocessing.h index 4364b8b42..cc20c91a6 100644 --- a/src/util/postprocessing.h +++ b/src/util/postprocessing.h @@ -49,11 +49,6 @@ struct ShaderOption using ValueVector = std::array; static_assert(sizeof(ValueVector) == sizeof(u32) * MAX_VECTOR_COMPONENTS); - std::string name; - std::string ui_name; - std::string dependent_option; - std::string category; - std::string tooltip; Type type; u32 vector_size; u32 buffer_size; @@ -63,8 +58,16 @@ struct ShaderOption ValueVector max_value; ValueVector step_value; ValueVector value; + std::string name; + std::string ui_name; + std::string dependent_option; + std::string category; + std::string tooltip; + std::string help_text; std::vector choice_options; + bool ShouldHide() const; + static u32 ParseIntVector(std::string_view line, ValueVector* values); static u32 ParseFloatVector(std::string_view line, ValueVector* values); diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index 98e929d91..9b03b1925 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -638,6 +638,7 @@ bool PostProcessing::ReShadeFXShader::CreateOptions(const reshadefx::effect_modu opt.name = ui.name; opt.category = GetStringAnnotationValue(ui.annotations, "ui_category", std::string_view()); opt.tooltip = GetStringAnnotationValue(ui.annotations, "ui_tooltip", std::string_view()); + opt.help_text = GetStringAnnotationValue(ui.annotations, "ui_text", std::string_view()); if (!GetBooleanAnnotationValue(ui.annotations, "hidden", false)) {