diff --git a/res/rml/overlay.rcss b/res/rml/overlay.rcss index a8323bb7b2..f2e2ba5c3b 100644 --- a/res/rml/overlay.rcss +++ b/res/rml/overlay.rcss @@ -144,4 +144,6 @@ footer-button.reset { background-color: transparent; opacity: 1; cursor: pointer; + font-family: "Material Symbols Rounded"; + font-weight: normal; } diff --git a/res/rml/window.rcss b/res/rml/window.rcss index 17e4dec6f3..5cc5a2ca57 100644 --- a/res/rml/window.rcss +++ b/res/rml/window.rcss @@ -225,11 +225,12 @@ select-button key { font-weight: bold; font-size: 18dp; text-transform: uppercase; - flex: 1 0 auto; + flex: 0 1 auto; } select-button value { - margin-left: auto; + flex: 1 1 auto; + text-align: right; font-size: 20dp; } @@ -241,3 +242,17 @@ select-button input { text-align: right; font-size: 20dp; } + +icon { + font-family: "Material Symbols Rounded"; + font-weight: normal; + display: inline-block; + vertical-align: middle; +} + +icon.warning { + width: 1em; + height: 1em; + decorator: text("" center center); + color: #ffcc00; +} diff --git a/src/dusk/ui/bool_button.cpp b/src/dusk/ui/bool_button.cpp index 873274758e..49cee53fdb 100644 --- a/src/dusk/ui/bool_button.cpp +++ b/src/dusk/ui/bool_button.cpp @@ -3,7 +3,11 @@ namespace dusk::ui { BoolButton::BoolButton(Rml::Element* parent, Props props) - : BaseControlledSelectButton(parent, {std::move(props.key)}), + : BaseControlledSelectButton(parent, + { + .key = std::move(props.key), + .icon = std::move(props.icon), + }), mGetValue(std::move(props.getValue)), mSetValue(std::move(props.setValue)), mIsDisabled(std::move(props.isDisabled)), mIsModified(std::move(props.isModified)) {} diff --git a/src/dusk/ui/bool_button.hpp b/src/dusk/ui/bool_button.hpp index 8573efbc23..a6bd133c44 100644 --- a/src/dusk/ui/bool_button.hpp +++ b/src/dusk/ui/bool_button.hpp @@ -7,6 +7,7 @@ class BoolButton : public BaseControlledSelectButton { public: struct Props { Rml::String key; + Rml::String icon; std::function getValue; std::function setValue; std::function isDisabled; diff --git a/src/dusk/ui/overlay.cpp b/src/dusk/ui/overlay.cpp index e97af576b5..2d572227c0 100644 --- a/src/dusk/ui/overlay.cpp +++ b/src/dusk/ui/overlay.cpp @@ -84,7 +84,7 @@ Rml::Element* create_stepped_carousel_arrow( auto button = doc->CreateElement("button"); button->SetClass("stepped-carousel-arrow", true); button->SetClass(className, true); - button->SetInnerRML(escape(label)); + button->SetInnerRML(label); return parent->AppendChild(std::move(button)); } @@ -92,10 +92,10 @@ Rml::Element* create_stepped_carousel_arrow( SteppedCarousel::SteppedCarousel(Rml::Element* parent, Props props) : Component(create_stepped_carousel_root(parent)), mProps(std::move(props)) { - Rml::Element* prevElem = create_stepped_carousel_arrow(mRoot, "prev", "<"); + Rml::Element* prevElem = create_stepped_carousel_arrow(mRoot, "prev", ""); mValueElem = append(mRoot, "div"); mValueElem->SetClass("stepped-carousel-value", true); - Rml::Element* nextElem = create_stepped_carousel_arrow(mRoot, "next", ">"); + Rml::Element* nextElem = create_stepped_carousel_arrow(mRoot, "next", ""); listen(prevElem, Rml::EventId::Click, [this](Rml::Event&) { handle_nav_command(NavCommand::Left); }); diff --git a/src/dusk/ui/select_button.cpp b/src/dusk/ui/select_button.cpp index bb19329125..f53c444011 100644 --- a/src/dusk/ui/select_button.cpp +++ b/src/dusk/ui/select_button.cpp @@ -19,6 +19,7 @@ Rml::Element* createRoot(Rml::Element* parent) { SelectButton::SelectButton(Rml::Element* parent, Props props) : FluentComponent(createRoot(parent)) { mKeyElem = append(mRoot, "key"); + mIconElem = append(mRoot, "icon"); mValueElem = append(mRoot, "value"); update_props(std::move(props)); on_nav_command([this](Rml::Event&, NavCommand cmd) { return handle_nav_command(cmd); }); @@ -32,7 +33,7 @@ void SelectButton::set_modified(bool value) { if (mProps.modified != value) { mValueElem->SetClass("modified", value); if (value) { - mValueElem->SetInnerRML(fmt::format("• {}", escape(mProps.value))); + mValueElem->SetInnerRML(fmt::format("• {}", escape(mProps.value))); } else { mValueElem->SetInnerRML(escape(mProps.value)); } @@ -43,7 +44,7 @@ void SelectButton::set_modified(bool value) { void SelectButton::set_value_label(const Rml::String& value) { if (mProps.value != value) { if (mProps.modified) { - mValueElem->SetInnerRML(fmt::format("• {}", escape(value))); + mValueElem->SetInnerRML(fmt::format("• {}", escape(value))); } else { mValueElem->SetInnerRML(escape(value)); } @@ -67,6 +68,16 @@ void SelectButton::update_props(Props props) { if (mProps.key != props.key) { mKeyElem->SetInnerRML(escape(props.key)); } + if (mProps.icon != props.icon) { + Rml::StringList iconClasses; + Rml::StringUtilities::ExpandString(iconClasses, mIconElem->GetClassNames(), ' ', true); + for (const auto& className : iconClasses) { + mIconElem->SetClass(className, false); + } + if (!props.icon.empty()) { + mIconElem->SetClass(props.icon, true); + } + } set_value_label(props.value); set_modified(props.modified); mProps = std::move(props); diff --git a/src/dusk/ui/select_button.hpp b/src/dusk/ui/select_button.hpp index f050943673..08dd638ff4 100644 --- a/src/dusk/ui/select_button.hpp +++ b/src/dusk/ui/select_button.hpp @@ -15,6 +15,7 @@ public: struct Props { Rml::String key; Rml::String value; + Rml::String icon; bool modified = false; }; @@ -31,6 +32,7 @@ protected: Props mProps; Rml::Element* mKeyElem = nullptr; + Rml::Element* mIconElem = nullptr; Rml::Element* mValueElem = nullptr; }; diff --git a/src/dusk/ui/settings.cpp b/src/dusk/ui/settings.cpp index 173b4d72e1..554671cc17 100644 --- a/src/dusk/ui/settings.cpp +++ b/src/dusk/ui/settings.cpp @@ -56,6 +56,10 @@ const Rml::String kBloomHelpText = "a higher-quality bloom pass."; const Rml::String kBloomBrightnessHelpText = "Configure bloom intensity. Higher values make bright areas glow more strongly."; +const Rml::String kUnlockFramerateHelpText = + "Uses inter-frame interpolation to enable higher frame rates.

Experimental feature: Visual artifacts, animation glitches, or " + "instability may occur."; int bloom_multiplier_percent() { return std::clamp( @@ -72,6 +76,7 @@ bool gyro_enabled() { struct ConfigBoolProps { Rml::String key; + Rml::String icon; Rml::String helpText; std::function onChange; std::function isDisabled; @@ -80,7 +85,9 @@ struct ConfigBoolProps { SelectButton& config_bool_select( Pane& leftPane, Pane& rightPane, ConfigVar& var, ConfigBoolProps props) { return leftPane - .add_child(BoolButton::Props{.key = std::move(props.key), + .add_child(BoolButton::Props{ + .key = std::move(props.key), + .icon = std::move(props.icon), .getValue = [&var] { return var.getValue(); }, .setValue = [&var, callback = std::move(props.onChange)](bool value) { @@ -94,7 +101,8 @@ SelectButton& config_bool_select( } }, .isDisabled = std::move(props.isDisabled), - .isModified = [&var] { return var.getValue() != var.getDefaultValue(); }}) + .isModified = [&var] { return var.getValue() != var.getDefaultValue(); }, + }) .on_focus([&rightPane, helpText = std::move(props.helpText)](Rml::Event&) { rightPane.clear(); rightPane.add_rml(helpText); @@ -303,9 +311,15 @@ SettingsWindow::SettingsWindow() { "Quicker climbing on ladders and vines like the HD version."); addOption("Faster Tears of Light", getSettings().game.fastTears, "Tears of Light dropped by Shadow Insects pop out faster like the HD version."); - addOption("Autosave", getSettings().game.autoSave, - "Autosaves the game when going to a new area, opening a dungeon door, or getting " - "a new item.

This feature is currently experimental, use at your own risk."); + config_bool_select(leftPane, rightPane, getSettings().game.autoSave, + { + .key = "Autosave", + .icon = "warning", + .helpText = + "Autosaves the game when going to a new area, opening a dungeon door, " + "or getting a new item.

Experimental " + "feature: Use at your own risk.", + }); addOption("Instant Saves", getSettings().game.instantSaves, "Skips the delay when writing to the Memory Card."); addOption("Hold B for Instant Text", getSettings().game.instantText, @@ -601,9 +615,8 @@ SettingsWindow::SettingsWindow() { config_bool_select(leftPane, rightPane, getSettings().game.enableFrameInterpolation, { .key = "Unlock Framerate", - .helpText = - "Uses inter-frame interpolation to enable higher frame rates.

Visual " - "artifacts, animation glitches, or instability may occur.", + .icon = "warning", + .helpText = kUnlockFramerateHelpText, }); config_bool_select(leftPane, rightPane, getSettings().game.enableDepthOfField, {