diff --git a/src/dusk/ui/overlay.cpp b/src/dusk/ui/overlay.cpp index 340f856d2b..811e909ab2 100644 --- a/src/dusk/ui/overlay.cpp +++ b/src/dusk/ui/overlay.cpp @@ -7,6 +7,7 @@ #include "dusk/config.hpp" #include "dusk/settings.h" +#include #include namespace dusk::ui { @@ -39,6 +40,12 @@ int get_value(GraphicsOption option) { return getSettings().game.internalResolutionScale.getValue(); case GraphicsOption::ShadowResolution: return getSettings().game.shadowResolutionMultiplier.getValue(); + case GraphicsOption::BloomMode: + return static_cast(getSettings().game.bloomMode.getValue()); + case GraphicsOption::BloomMultiplier: + return std::clamp( + static_cast(getSettings().game.bloomMultiplier.getValue() * 100.0f + 0.5f), 0, + 100); } return 0; } @@ -52,6 +59,14 @@ void set_value(GraphicsOption option, int value) { case GraphicsOption::ShadowResolution: getSettings().game.shadowResolutionMultiplier.setValue(value); break; + case GraphicsOption::BloomMode: + getSettings().game.bloomMode.setValue( + static_cast(std::clamp(value, static_cast(BloomMode::Off), + static_cast(BloomMode::Dusk)))); + break; + case GraphicsOption::BloomMultiplier: + getSettings().game.bloomMultiplier.setValue(std::clamp(value, 0, 100) / 100.0f); + break; } config::Save(); } @@ -150,13 +165,25 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) { } case GraphicsOption::ShadowResolution: return fmt::format("{}x", value); + case GraphicsOption::BloomMode: + switch (static_cast(value)) { + case BloomMode::Off: + return "Off"; + case BloomMode::Classic: + return "Classic"; + case BloomMode::Dusk: + return "Dusk"; + } + break; + case GraphicsOption::BloomMultiplier: + return fmt::format("{}%", value); } return ""; } Overlay::Overlay(OverlayProps props) : Document(kDocumentSource), mOption(props.option), mValueMin(props.valueMin), - mValueMax(props.valueMax) { + mValueMax(props.valueMax), mDefaultValue(props.defaultValue) { if (mDocument == nullptr) { return; } @@ -236,7 +263,7 @@ bool Overlay::handle_nav_command(Rml::Event& event, NavCommand cmd) { } void Overlay::reset_default() { - set_value(mOption, mValueMin); + set_value(mOption, mDefaultValue); } } // namespace dusk::ui diff --git a/src/dusk/ui/overlay.hpp b/src/dusk/ui/overlay.hpp index 1ad2d8a161..7e6e180fb5 100644 --- a/src/dusk/ui/overlay.hpp +++ b/src/dusk/ui/overlay.hpp @@ -40,6 +40,8 @@ private: enum class GraphicsOption { InternalResolution, ShadowResolution, + BloomMode, + BloomMultiplier, }; Rml::String format_graphics_setting_value(GraphicsOption option, int value); @@ -50,6 +52,7 @@ struct OverlayProps { Rml::String helpText; int valueMin = 0; int valueMax = 0; + int defaultValue = 0; }; class Overlay : public Document { @@ -78,6 +81,7 @@ private: GraphicsOption mOption; int mValueMin = 0; int mValueMax = 0; + int mDefaultValue = 0; std::vector > mComponents; Rml::Element* mRoot; bool mDismissed = false; diff --git a/src/dusk/ui/settings.cpp b/src/dusk/ui/settings.cpp index fc3935aa74..a4be7b6e3e 100644 --- a/src/dusk/ui/settings.cpp +++ b/src/dusk/ui/settings.cpp @@ -13,6 +13,8 @@ #include "pane.hpp" #include "ui.hpp" +#include + namespace dusk::ui { namespace { @@ -48,6 +50,16 @@ const Rml::String kInternalResolutionHelpText = const Rml::String kShadowResolutionHelpText = "Configure the shadow-map resolution. Higher values improve shadow quality but increase GPU " "and memory usage."; +const Rml::String kBloomHelpText = + "Configure the post-processing bloom effect. Classic uses the original bloom pass; Dusk uses " + "a higher-quality bloom pass."; +const Rml::String kBloomBrightnessHelpText = + "Configure bloom intensity. Higher values make bright areas glow more strongly."; + +int bloom_multiplier_percent() { + return std::clamp( + static_cast(getSettings().game.bloomMultiplier.getValue() * 100.0f + 0.5f), 0, 100); +} struct ConfigBoolProps { Rml::String key; @@ -335,6 +347,7 @@ SettingsWindow::SettingsWindow() { .helpText = kInternalResolutionHelpText, .valueMin = 0, .valueMax = 12, + .defaultValue = 0, })); return true; } @@ -360,8 +373,9 @@ SettingsWindow::SettingsWindow() { .option = GraphicsOption::ShadowResolution, .title = "Shadow Resolution", .helpText = kShadowResolutionHelpText, - .valueMin = 0, + .valueMin = 1, .valueMax = 8, + .defaultValue = 1, })); return true; } @@ -373,8 +387,65 @@ SettingsWindow::SettingsWindow() { }); leftPane.add_section("Post-Processing"); - // TODO: Bloom - // TODO: Bloom Brightness + leftPane + .add_select_button({ + .key = "Bloom", + .getValue = + [] { + return format_graphics_setting_value(GraphicsOption::BloomMode, + static_cast(getSettings().game.bloomMode.getValue())); + }, + }) + .on_nav_command([](Rml::Event&, NavCommand cmd) { + if (cmd == NavCommand::Confirm || cmd == NavCommand::Left || + cmd == NavCommand::Right) { + push_document(std::make_unique(OverlayProps{ + .option = GraphicsOption::BloomMode, + .title = "Bloom", + .helpText = kBloomHelpText, + .valueMin = static_cast(BloomMode::Off), + .valueMax = static_cast(BloomMode::Dusk), + .defaultValue = static_cast(BloomMode::Classic), + })); + return true; + } + return false; + }) + .on_focus([&rightPane](Rml::Event&) { + rightPane.clear(); + rightPane.add_text(kBloomHelpText); + }); + leftPane + .add_select_button({ + .key = "Bloom Brightness", + .getValue = + [] { + return format_graphics_setting_value( + GraphicsOption::BloomMultiplier, bloom_multiplier_percent()); + }, + .isDisabled = [] { + return getSettings().game.bloomMode.getValue() == BloomMode::Off; + }, + }) + .on_nav_command([](Rml::Event&, NavCommand cmd) { + if (cmd == NavCommand::Confirm || cmd == NavCommand::Left || + cmd == NavCommand::Right) { + push_document(std::make_unique(OverlayProps{ + .option = GraphicsOption::BloomMultiplier, + .title = "Bloom Brightness", + .helpText = kBloomBrightnessHelpText, + .valueMin = 0, + .valueMax = 100, + .defaultValue = 100, + })); + return true; + } + return false; + }) + .on_focus([&rightPane](Rml::Event&) { + rightPane.clear(); + rightPane.add_text(kBloomBrightnessHelpText); + }); leftPane.add_section("Rendering"); config_bool_select(leftPane, rightPane, getSettings().game.enableFrameInterpolation,