From ff78bc8d6c240cd9e9fe0dadb18e01c25af7c531 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 28 Apr 2026 00:18:52 -0600 Subject: [PATCH] Start using Rml::PropertyId/Property instead of strings --- .clang-format | 2 +- src/dusk/ui/button.cpp | 72 +++--- src/dusk/ui/button.hpp | 2 +- src/dusk/ui/control_surface.cpp | 14 +- src/dusk/ui/control_surface.hpp | 3 +- src/dusk/ui/disc_state.cpp | 84 ++++--- src/dusk/ui/disc_state.hpp | 3 +- src/dusk/ui/element.cpp | 23 +- src/dusk/ui/element.hpp | 11 +- src/dusk/ui/focus_border.cpp | 47 ++-- src/dusk/ui/game_menu.cpp | 254 ++++++++++--------- src/dusk/ui/game_option.cpp | 159 ++++++------ src/dusk/ui/game_option.hpp | 3 +- src/dusk/ui/label.cpp | 40 +-- src/dusk/ui/prelaunch_layout.cpp | 147 ++++++----- src/dusk/ui/prelaunch_layout.hpp | 4 +- src/dusk/ui/prelaunch_screen.cpp | 49 ++-- src/dusk/ui/theme.cpp | 18 +- src/dusk/ui/theme.hpp | 36 ++- src/dusk/ui/ui.cpp | 4 +- src/dusk/ui/window.cpp | 407 +++++++++++++++++-------------- src/dusk/ui/window.hpp | 6 +- 22 files changed, 787 insertions(+), 601 deletions(-) diff --git a/.clang-format b/.clang-format index 1428d3c71e..8ffd4ebe96 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ Language: Cpp Standard: C++03 AccessModifierOffset: -4 -AlignAfterOpenBracket: Align +AlignAfterOpenBracket: DontAlign AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignOperands: true diff --git a/src/dusk/ui/button.cpp b/src/dusk/ui/button.cpp index da513129d7..b2c4eae6e8 100644 --- a/src/dusk/ui/button.cpp +++ b/src/dusk/ui/button.cpp @@ -28,43 +28,49 @@ ControlSurfaceTone control_surface_tone(ButtonVariant variant) { } // namespace Button::Button(Rml::Element* parent, std::string_view id, std::string_view text, - ButtonVariant variant, std::function pressedCallback) + ButtonVariant variant, std::function pressedCallback) : m_variant(variant), m_pressedCallback(std::move(pressedCallback)) { using namespace theme; - m_element = append(parent, "button", id); - set_props(m_element, { - {"display", "flex"}, - {"position", "relative"}, - {"flex-direction", "row"}, - {"align-items", "center"}, - {"justify-content", "center"}, - {"box-sizing", "border-box"}, - {"width", "100%"}, - {"height", "68dp"}, - {"min-height", "68dp"}, - {"max-height", "68dp"}, - {"padding-left", "22dp"}, - {"padding-right", "22dp"}, - {"border-width", dp(BorderWidth)}, - {"border-radius", dp(BorderRadiusMedium)}, - {"cursor", "pointer"}, - {"tab-index", "auto"}, - {"nav-up", "auto"}, - {"nav-down", "auto"}, - {"nav-left", "auto"}, - {"nav-right", "auto"}, - {"opacity", "1"}, - {"font-family", "Inter"}, - {"color", rgba(Text)}, - }); + m_element = append(parent, "button", id, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::Position, Rml::Style::Position::Relative}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::Height, rml_dp(68.0f)}, + {Rml::PropertyId::MinHeight, rml_dp(68.0f)}, + {Rml::PropertyId::MaxHeight, rml_dp(68.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(22.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(22.0f)}, + {Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::Cursor, rml_string("pointer")}, + {Rml::PropertyId::TabIndex, Rml::Style::TabIndex::Auto}, + {Rml::PropertyId::NavUp, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavDown, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavLeft, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavRight, Rml::Style::Nav::Auto}, + {Rml::PropertyId::Opacity, rml_number(1.0f)}, + {Rml::PropertyId::FontFamily, rml_string("Inter")}, + {Rml::PropertyId::Color, rml_color(Text)}, + }); add_focus_border(m_element, BorderRadiusMedium); m_label = append_text(m_element, "span", text); apply_label_style(m_label, LabelStyle::Medium); set_props(m_label, { - {"pointer-events", "none"}, - {"text-align", "center"}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Center}, }); m_element->AddEventListener(Rml::EventId::Click, this); @@ -136,10 +142,10 @@ void Button::apply_style() { } const bool active = m_hovered || m_focused; - apply_control_surface_style(m_element, control_surface_style(control_surface_tone(m_variant)), - active); - m_element->SetProperty("color", rgba(active ? TextActive : Text)); - m_label->SetProperty("color", rgba(active ? TextActive : Text)); + apply_control_surface_style( + m_element, control_surface_style(control_surface_tone(m_variant)), active); + m_element->SetProperty(Rml::PropertyId::Color, rml_color(active ? TextActive : Text)); + m_label->SetProperty(Rml::PropertyId::Color, rml_color(active ? TextActive : Text)); set_focus_border_visible(m_element, m_focused); } diff --git a/src/dusk/ui/button.hpp b/src/dusk/ui/button.hpp index c60e2a0c8d..7123914bbb 100644 --- a/src/dusk/ui/button.hpp +++ b/src/dusk/ui/button.hpp @@ -21,7 +21,7 @@ enum class ButtonVariant { class Button : public Rml::EventListener { public: Button(Rml::Element* parent, std::string_view id, std::string_view text, ButtonVariant variant, - std::function pressedCallback); + std::function pressedCallback); ~Button() override; Button(const Button&) = delete; diff --git a/src/dusk/ui/control_surface.cpp b/src/dusk/ui/control_surface.cpp index 8521002e13..8d78f9053b 100644 --- a/src/dusk/ui/control_surface.cpp +++ b/src/dusk/ui/control_surface.cpp @@ -41,12 +41,20 @@ ControlSurfaceStyle control_surface_style(ControlSurfaceTone tone) { } } -void apply_control_surface_style(Rml::Element* element, const ControlSurfaceStyle& style, bool active) { +void apply_control_surface_style( + Rml::Element* element, const ControlSurfaceStyle& style, bool active) { if (element == nullptr) { return; } - element->SetProperty("border-color", active ? theme::rgba(style.accent, style.activeBorderOpacity) : theme::rgba(theme::ElevatedBorder, style.inactiveBorderOpacity)); - element->SetProperty("background-color", theme::rgba(style.accent, active ? style.activeBackgroundOpacity : style.inactiveBackgroundOpacity)); + const auto borderColor = active ? rml_color(style.accent, style.activeBorderOpacity) : + rml_color(theme::ElevatedBorder, style.inactiveBorderOpacity); + element->SetProperty(Rml::PropertyId::BorderLeftColor, borderColor); + element->SetProperty(Rml::PropertyId::BorderRightColor, borderColor); + element->SetProperty(Rml::PropertyId::BorderTopColor, borderColor); + element->SetProperty(Rml::PropertyId::BorderBottomColor, borderColor); + element->SetProperty(Rml::PropertyId::BackgroundColor, + rml_color(style.accent, + active ? style.activeBackgroundOpacity : style.inactiveBackgroundOpacity)); } } // namespace dusk::ui diff --git a/src/dusk/ui/control_surface.hpp b/src/dusk/ui/control_surface.hpp index 04ef80c98b..2d68441c9f 100644 --- a/src/dusk/ui/control_surface.hpp +++ b/src/dusk/ui/control_surface.hpp @@ -23,5 +23,6 @@ struct ControlSurfaceStyle { }; ControlSurfaceStyle control_surface_style(ControlSurfaceTone tone); -void apply_control_surface_style(Rml::Element* element, const ControlSurfaceStyle& style, bool active); +void apply_control_surface_style( + Rml::Element* element, const ControlSurfaceStyle& style, bool active); } // namespace dusk::ui diff --git a/src/dusk/ui/disc_state.cpp b/src/dusk/ui/disc_state.cpp index 1f61f68f01..23c102f610 100644 --- a/src/dusk/ui/disc_state.cpp +++ b/src/dusk/ui/disc_state.cpp @@ -12,47 +12,57 @@ namespace dusk::ui { DiscState::DiscState(Rml::Element* parent, std::string_view id, std::string_view text, - std::string_view statusText, bool statusIsError, - std::function pressedCallback) + std::string_view statusText, bool statusIsError, std::function pressedCallback) : m_pressedCallback(std::move(pressedCallback)), m_statusIsError(statusIsError) { using namespace theme; - m_element = append(parent, "button", id); - set_props(m_element, { - {"display", "flex"}, - {"position", "relative"}, - {"flex-direction", "column"}, - {"align-items", "stretch"}, - {"gap", "6dp"}, - {"width", "100%"}, - {"box-sizing", "border-box"}, - {"padding", "14dp 16dp"}, - {"border-width", dp(BorderWidth)}, - {"border-radius", dp(BorderRadiusSmall)}, - {"cursor", "pointer"}, - {"tab-index", "auto"}, - {"nav-up", "auto"}, - {"nav-down", "auto"}, - {"nav-left", "auto"}, - {"nav-right", "auto"}, - {"font-family", "Inter"}, - }); + m_element = append(parent, "button", id, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::Position, Rml::Style::Position::Relative}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Stretch}, + {Rml::PropertyId::RowGap, rml_dp(6.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(6.0f)}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::PaddingTop, rml_dp(14.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(16.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(14.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(16.0f)}, + {Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::Cursor, rml_string("pointer")}, + {Rml::PropertyId::TabIndex, Rml::Style::TabIndex::Auto}, + {Rml::PropertyId::NavUp, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavDown, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavLeft, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavRight, Rml::Style::Nav::Auto}, + {Rml::PropertyId::FontFamily, rml_string("Inter")}, + }); add_focus_border(m_element, BorderRadiusSmall); m_value = add_label(m_element, text, LabelStyle::Body); set_props(m_value, { - {"overflow", "hidden"}, - {"text-overflow", "ellipsis"}, - {"white-space", "nowrap"}, - {"pointer-events", "none"}, + {Rml::PropertyId::OverflowX, Rml::Style::Overflow::Hidden}, + {Rml::PropertyId::OverflowY, Rml::Style::Overflow::Hidden}, + {Rml::PropertyId::TextOverflow, Rml::Style::TextOverflow::Ellipsis}, + {Rml::PropertyId::WhiteSpace, Rml::Style::WhiteSpace::Nowrap}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, }); if (!statusText.empty()) { m_status = add_label(m_element, statusText, LabelStyle::Annotation); set_props(m_status, { - {"pointer-events", "none"}, - {"white-space", "normal"}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, + {Rml::PropertyId::WhiteSpace, Rml::Style::WhiteSpace::Normal}, }); } @@ -123,15 +133,19 @@ void DiscState::apply_style() { const bool active = m_hovered || m_focused; const Color accent = m_statusIsError ? Danger : Primary; - m_element->SetProperty("background-color", - rgba(accent, active ? 52 : (m_statusIsError ? 32 : 20))); - m_element->SetProperty("border-color", - rgba(accent, active ? 220 : (m_statusIsError ? 190 : 120))); - m_element->SetProperty("color", rgba(active ? TextActive : Text)); + m_element->SetProperty(Rml::PropertyId::BackgroundColor, + rml_color(accent, active ? 52 : (m_statusIsError ? 32 : 20))); + const auto borderColor = rml_color(accent, active ? 220 : (m_statusIsError ? 190 : 120)); + m_element->SetProperty(Rml::PropertyId::BorderTopColor, borderColor); + m_element->SetProperty(Rml::PropertyId::BorderRightColor, borderColor); + m_element->SetProperty(Rml::PropertyId::BorderBottomColor, borderColor); + m_element->SetProperty(Rml::PropertyId::BorderLeftColor, borderColor); + m_element->SetProperty(Rml::PropertyId::Color, rml_color(active ? TextActive : Text)); - m_value->SetProperty("color", rgba(active ? TextActive : Text)); + m_value->SetProperty(Rml::PropertyId::Color, rml_color(active ? TextActive : Text)); if (m_status != nullptr) { - m_status->SetProperty("color", rgba(m_statusIsError ? Danger : TextDim)); + m_status->SetProperty( + Rml::PropertyId::Color, rml_color(m_statusIsError ? Danger : TextDim)); } set_focus_border_visible(m_element, m_focused); } diff --git a/src/dusk/ui/disc_state.hpp b/src/dusk/ui/disc_state.hpp index ec1247abd3..c0e00097a3 100644 --- a/src/dusk/ui/disc_state.hpp +++ b/src/dusk/ui/disc_state.hpp @@ -15,8 +15,7 @@ namespace dusk::ui { class DiscState : public Rml::EventListener { public: DiscState(Rml::Element* parent, std::string_view id, std::string_view text, - std::string_view statusText, bool statusIsError, - std::function pressedCallback); + std::string_view statusText, bool statusIsError, std::function pressedCallback); ~DiscState() override; DiscState(const DiscState&) = delete; diff --git a/src/dusk/ui/element.cpp b/src/dusk/ui/element.cpp index c74ad74755..87a113486c 100644 --- a/src/dusk/ui/element.cpp +++ b/src/dusk/ui/element.cpp @@ -34,7 +34,8 @@ std::string escape(std::string_view text) { return result; } -Rml::Element* append(Rml::Element* parent, std::string_view tag, std::string_view id) { +Rml::Element* append(Rml::Element* parent, std::string_view tag, std::string_view id, + std::initializer_list > properties) { if (parent == nullptr) { return nullptr; } @@ -52,11 +53,13 @@ Rml::Element* append(Rml::Element* parent, std::string_view tag, std::string_vie if (!id.empty()) { rawChild->SetId(std::string(id)); } - return parent->AppendChild(std::move(child)); + Rml::Element* appended = parent->AppendChild(std::move(child)); + set_props(appended, properties); + return appended; } -Rml::Element* append_text(Rml::Element* parent, std::string_view tag, std::string_view text, - std::string_view id) { +Rml::Element* append_text( + Rml::Element* parent, std::string_view tag, std::string_view text, std::string_view id) { Rml::Element* element = append(parent, tag, id); set_text(element, text); return element; @@ -69,7 +72,7 @@ void set_text(Rml::Element* element, std::string_view text) { } void set_props(Rml::Element* element, - std::initializer_list > properties) { + std::initializer_list > properties) { if (element == nullptr) { return; } @@ -78,4 +81,14 @@ void set_props(Rml::Element* element, } } +void set_props(Rml::Element* element, + std::initializer_list > properties) { + if (element == nullptr) { + return; + } + for (const auto& [name, value] : properties) { + element->SetProperty(name, value); + } +} + } // namespace dusk::ui diff --git a/src/dusk/ui/element.hpp b/src/dusk/ui/element.hpp index 9d28471bce..a5f7586b32 100644 --- a/src/dusk/ui/element.hpp +++ b/src/dusk/ui/element.hpp @@ -8,11 +8,14 @@ namespace dusk::ui { std::string escape(std::string_view text); -Rml::Element* append(Rml::Element* parent, std::string_view tag, std::string_view id = {}); -Rml::Element* append_text(Rml::Element* parent, std::string_view tag, std::string_view text, - std::string_view id = {}); +Rml::Element* append(Rml::Element* parent, std::string_view tag, std::string_view id = {}, + std::initializer_list > properties = {}); +Rml::Element* append_text( + Rml::Element* parent, std::string_view tag, std::string_view text, std::string_view id = {}); void set_text(Rml::Element* element, std::string_view text); void set_props(Rml::Element* element, - std::initializer_list > properties); + std::initializer_list > properties); +void set_props(Rml::Element* element, + std::initializer_list > properties); } // namespace dusk::ui diff --git a/src/dusk/ui/focus_border.cpp b/src/dusk/ui/focus_border.cpp index 8fc474f956..32f872f5d1 100644 --- a/src/dusk/ui/focus_border.cpp +++ b/src/dusk/ui/focus_border.cpp @@ -3,24 +3,35 @@ #include "element.hpp" #include "theme.hpp" +#include + namespace dusk::ui { Rml::Element* add_focus_border(Rml::Element* parent, float radius) { using namespace theme; - auto* border = append(parent, "div"); - set_props(border, { - {"position", "absolute"}, - {"pointer-events", "none"}, - {"left", dp(-(BorderWidth * 3.0f))}, - {"top", dp(-(BorderWidth * 3.0f))}, - {"right", dp(-(BorderWidth * 3.0f))}, - {"bottom", dp(-(BorderWidth * 3.0f))}, - {"border-width", dp(BorderWidth * 2.0f)}, - {"border-radius", dp(radius + BorderWidth * 4.0f)}, - {"border-color", rgba(PrimaryLight, 0)}, - }); - return border; + const auto borderColor = rml_color(PrimaryLight, 0); + return append(parent, "div", {}, + { + {Rml::PropertyId::Position, Rml::Style::Position::Absolute}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, + {Rml::PropertyId::Left, rml_dp(-(BorderWidth * 3.0f))}, + {Rml::PropertyId::Top, rml_dp(-(BorderWidth * 3.0f))}, + {Rml::PropertyId::Right, rml_dp(-(BorderWidth * 3.0f))}, + {Rml::PropertyId::Bottom, rml_dp(-(BorderWidth * 3.0f))}, + {Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth * 2.0f)}, + {Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth * 2.0f)}, + {Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth * 2.0f)}, + {Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth * 2.0f)}, + {Rml::PropertyId::BorderTopLeftRadius, rml_dp(radius + BorderWidth * 4.0f)}, + {Rml::PropertyId::BorderTopRightRadius, rml_dp(radius + BorderWidth * 4.0f)}, + {Rml::PropertyId::BorderBottomRightRadius, rml_dp(radius + BorderWidth * 4.0f)}, + {Rml::PropertyId::BorderBottomLeftRadius, rml_dp(radius + BorderWidth * 4.0f)}, + {Rml::PropertyId::BorderTopColor, borderColor}, + {Rml::PropertyId::BorderRightColor, borderColor}, + {Rml::PropertyId::BorderBottomColor, borderColor}, + {Rml::PropertyId::BorderLeftColor, borderColor}, + }); } void set_focus_border_visible(Rml::Element* parent, bool visible) { @@ -28,9 +39,13 @@ void set_focus_border_visible(Rml::Element* parent, bool visible) { return; } - parent->GetChild(0)->SetProperty("border-color", visible ? - theme::rgba(theme::PrimaryLight, 255) : - theme::rgba(theme::PrimaryLight, 0)); + const auto borderColor = rml_color(theme::PrimaryLight, visible ? 255 : 0); + set_props(parent->GetChild(0), { + {Rml::PropertyId::BorderTopColor, borderColor}, + {Rml::PropertyId::BorderRightColor, borderColor}, + {Rml::PropertyId::BorderBottomColor, borderColor}, + {Rml::PropertyId::BorderLeftColor, borderColor}, + }); } } // namespace dusk::ui diff --git a/src/dusk/ui/game_menu.cpp b/src/dusk/ui/game_menu.cpp index 084bbbcbdb..a05e20acb5 100644 --- a/src/dusk/ui/game_menu.cpp +++ b/src/dusk/ui/game_menu.cpp @@ -70,13 +70,15 @@ constexpr std::array kBloomModeNames{"Off", "Classic", "Dusk"}; // TODO: Needs more spacing for newlines static const char* get_description_for_item(std::string_view id) { if (id == "internal-resolution") { - return "Auto renders at the native window resolution.\nHigher values scale the internal framebuffer."; + return "Auto renders at the native window resolution.\nHigher values scale the internal " + "framebuffer."; } if (id == "shadow-resolution") { return "Improves the shadow resolution, making them higher quality."; } if (id == "frame-interp") { - return "Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur."; + return "Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, " + "animation glitches, or instability may occur."; } return "No description found."; @@ -257,66 +259,74 @@ private: void style_document(Rml::ElementDocument* document) { using namespace theme; set_props(document, { - {"width", "100%"}, - {"height", "100%"}, - {"margin", "0"}, - {"padding", "0"}, - {"font-family", "Inter"}, - {"color", rgba(Text)}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::Height, rml_percent(100.0f)}, + {Rml::PropertyId::MarginTop, rml_px(0.0f)}, + {Rml::PropertyId::MarginRight, rml_px(0.0f)}, + {Rml::PropertyId::MarginBottom, rml_px(0.0f)}, + {Rml::PropertyId::MarginLeft, rml_px(0.0f)}, + {Rml::PropertyId::PaddingTop, rml_px(0.0f)}, + {Rml::PropertyId::PaddingRight, rml_px(0.0f)}, + {Rml::PropertyId::PaddingBottom, rml_px(0.0f)}, + {Rml::PropertyId::PaddingLeft, rml_px(0.0f)}, + {Rml::PropertyId::FontFamily, rml_string("Inter")}, + {Rml::PropertyId::Color, rml_color(Text)}, }); } Rml::Element* add_screen() { using namespace theme; - auto* screen = append(m_document, "div", "game-menu-screen"); - set_props(screen, { - {"display", "flex"}, - {"position", "absolute"}, - {"left", "0"}, - {"top", "0"}, - {"right", "0"}, - {"bottom", "0"}, - {"flex-direction", "column"}, - {"align-items", "center"}, - {"justify-content", "center"}, - {"box-sizing", "border-box"}, - {"padding", "32dp"}, - }); - return screen; + return append(m_document, "div", "game-menu-screen", + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::Position, Rml::Style::Position::Absolute}, + {Rml::PropertyId::Left, rml_px(0.0f)}, + {Rml::PropertyId::Top, rml_px(0.0f)}, + {Rml::PropertyId::Right, rml_px(0.0f)}, + {Rml::PropertyId::Bottom, rml_px(0.0f)}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::PaddingTop, rml_dp(32.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(32.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(32.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(32.0f)}, + }); } Rml::Element* add_section_header(Rml::Element* parent, std::string_view title) { - auto* row = append(parent, "div"); - set_props(row, { - {"display", "flex"}, - {"flex-direction", "row"}, - {"align-items", "center"}, - {"width", "100%"}, - {"padding-top", "8dp"}, - {"padding-bottom", "4dp"}, - }); + auto* row = append(parent, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::PaddingTop, rml_dp(8.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(4.0f)}, + }); auto* label = add_label(row, title, LabelStyle::Annotation); set_props(label, { - {"font-size", "14dp"}, - {"letter-spacing", "3dp"}, - {"color", theme::rgba(theme::WindowAccentSoft)}, - {"flex-shrink", "0"}, + {Rml::PropertyId::FontSize, rml_dp(14.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(3.0f)}, + {Rml::PropertyId::Color, rml_color(theme::WindowAccentSoft)}, + {Rml::PropertyId::FlexShrink, rml_number(0.0f)}, }); return row; } Rml::Element* add_scroll_body(Rml::Element* parent) { - auto* scroll = append(parent, "div"); - set_props(scroll, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"width", "100%"}, - {"flex-grow", "1"}, - {"min-height", "0"}, - {"gap", "8dp"}, - {"overflow-y", "auto"}, - }); - return scroll; + return append(parent, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::FlexGrow, rml_number(1.0f)}, + {Rml::PropertyId::MinHeight, rml_px(0.0f)}, + {Rml::PropertyId::RowGap, rml_dp(8.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(8.0f)}, + {Rml::PropertyId::OverflowY, Rml::Style::Overflow::Auto}, + }); } std::function queue_activate(std::string id) { @@ -330,8 +340,8 @@ private: } void add_toggle(Rml::Element* parent, std::string id, std::string_view title, - config::ConfigVar& var, std::function sideEffect = {}, - std::string_view detail = {}) { + config::ConfigVar& var, std::function sideEffect = {}, + std::string_view detail = {}) { auto mutate = [this, &var, sideEffect = std::move(sideEffect)] { const bool next = !var.getValue(); var.setValue(next); @@ -342,27 +352,26 @@ private: m_needsRebuild = true; }; const std::string_view valueText = var.getValue() ? "On" : "Off"; - auto option = std::make_unique(parent, id, title, valueText, detail, - queue_activate(id)); + auto option = + std::make_unique(parent, id, title, valueText, detail, queue_activate(id)); register_row(Row{id, mutate, [mutate](int) { mutate(); }}, std::move(option)); } void add_action(Rml::Element* parent, std::string id, std::string_view title, - std::function action, std::string_view valueText = ">", - std::string_view detail = {}) { + std::function action, std::string_view valueText = ">", + std::string_view detail = {}) { auto mutate = [this, action = std::move(action)] { action(); m_needsRebuild = true; }; - auto option = std::make_unique(parent, id, title, valueText, detail, - queue_activate(id)); + auto option = + std::make_unique(parent, id, title, valueText, detail, queue_activate(id)); register_row(Row{id, mutate, {}}, std::move(option)); } template void add_cycle_row(Rml::Element* parent, std::string id, std::string_view title, - std::string_view valueText, std::string_view detail, - std::function cycle) { + std::string_view valueText, std::string_view detail, std::function cycle) { auto mutate = [this, cycle] { cycle(1); m_needsRebuild = true; @@ -371,15 +380,14 @@ private: cycle(direction); m_needsRebuild = true; }; - auto option = std::make_unique(parent, id, title, valueText, detail, - queue_activate(id)); + auto option = + std::make_unique(parent, id, title, valueText, detail, queue_activate(id)); register_row(Row{id, mutate, cycleWithRebuild}, std::move(option)); } void add_int_cycle(Rml::Element* parent, std::string id, std::string_view title, - config::ConfigVar& var, int minValue, int maxValue, - std::function formatter, - std::function sideEffect = {}) { + config::ConfigVar& var, int minValue, int maxValue, + std::function formatter, std::function sideEffect = {}) { const int current = std::clamp(var.getValue(), minValue, maxValue); const std::string valueText = formatter(current); auto cycle = [&var, minValue, maxValue, sideEffect = std::move(sideEffect)](int dir) { @@ -400,11 +408,11 @@ private: void add_bloom_mode_row(Rml::Element* parent) { auto& var = getSettings().game.bloomMode; - const int current = std::clamp(static_cast(var.getValue()), 0, - static_cast(kBloomModeNames.size() - 1)); + const int current = std::clamp( + static_cast(var.getValue()), 0, static_cast(kBloomModeNames.size() - 1)); const std::string_view valueText = kBloomModeNames[static_cast(current)]; auto cycle = [&var](int dir) { - const int count = static_cast(kBloomModeNames.size()); + const int count = kBloomModeNames.size(); int next = static_cast(var.getValue()) + dir; next = (next % count + count) % count; var.setValue(static_cast(next)); @@ -427,15 +435,15 @@ private: closest = i; } } - const int count = static_cast(kBloomMultiplierStops.size()); + const int count = kBloomMultiplierStops.size(); const int next = (closest + dir + count) % count; var.setValue(kBloomMultiplierStops[next]); Save(); }; const std::string_view detail = getSettings().game.bloomMode.getValue() == BloomMode::Off ? "Bloom is disabled" : ""; - add_cycle_row(parent, "bloom-brightness", "Bloom Brightness", valueText, detail, - std::move(cycle)); + add_cycle_row( + parent, "bloom-brightness", "Bloom Brightness", valueText, detail, std::move(cycle)); } void build_description_pane() { @@ -446,15 +454,17 @@ private: return; } m_descriptionElement = append_text(right, "p", " ", "option-description"); - set_props(m_descriptionElement, {{"color", theme::rgba(theme::TextActive)}, - {"font-size", "20dp"}, - {"line-height", "1.45em"}, - {"text-align", "left"}, - {"align-self", "stretch"}, - {"width", "100%"}, - {"box-sizing", "border-box"}, - {"white-space", "pre-line"}, - }); + set_props(m_descriptionElement, + { + {Rml::PropertyId::Color, rml_color(theme::TextActive)}, + {Rml::PropertyId::FontSize, rml_dp(20.0f)}, + {Rml::PropertyId::LineHeight, Rml::Property(1.45f, Rml::Unit::EM)}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Left}, + {Rml::PropertyId::AlignSelf, Rml::Style::AlignSelf::Stretch}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::WhiteSpace, Rml::Style::WhiteSpace::Preline}, + }); } void sync_description_pane() { @@ -486,20 +496,23 @@ private: add_section_header(scroll, "Display"); // TODO: Replace this with a Display Mode toggle. - add_toggle(scroll, "fullscreen", "Toggle Fullscreen", - getSettings().video.enableFullscreen, - [](bool enabled) { VISetWindowFullscreen(enabled); }); - + add_toggle(scroll, "fullscreen", "Toggle Fullscreen", getSettings().video.enableFullscreen, + [](bool enabled) { VISetWindowFullscreen(enabled); }); + u32 internalWidth = 0; u32 internalHeight = 0; AuroraGetRenderSize(&internalWidth, &internalHeight); const std::string detail = fmt::format("Current: {}x{}", internalWidth, internalHeight); - const int currentScale = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0, kInternalResolutionScaleMax); - const std::string scaleValue = currentScale == 0 ? std::string("Auto") : fmt::format("{}x", currentScale); + const int currentScale = std::clamp( + getSettings().game.internalResolutionScale.getValue(), 0, kInternalResolutionScaleMax); + const std::string scaleValue = + currentScale == 0 ? std::string("Auto") : fmt::format("{}x", currentScale); auto scaleCycle = [](int dir) { - int next = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0, kInternalResolutionScaleMax) + dir; + int next = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0, + kInternalResolutionScaleMax) + + dir; if (next < 0) { next = kInternalResolutionScaleMax; } else if (next > kInternalResolutionScaleMax) { @@ -511,22 +524,22 @@ private: }; add_cycle_row(scroll, "internal-resolution", "Internal Resolution", scaleValue, detail, - std::move(scaleCycle)); - + std::move(scaleCycle)); + add_int_cycle(scroll, "shadow-resolution", "Shadow Resolution", - getSettings().game.shadowResolutionMultiplier, 1, kShadowResolutionMax, - [](int v) { return fmt::format("x{}", v); }); - + getSettings().game.shadowResolutionMultiplier, 1, kShadowResolutionMax, + [](int v) { return fmt::format("x{}", v); }); + add_toggle(scroll, "lock-aspect", "Force 4:3 Aspect Ratio", - getSettings().video.lockAspectRatio, - [](bool enabled) { AuroraSetViewportPolicy(enabled ? AURORA_VIEWPORT_FIT : AURORA_VIEWPORT_STRETCH); }); - - add_toggle(scroll, "vsync", "VSync", - getSettings().video.enableVsync, - [](bool enabled) { aurora_enable_vsync(enabled); }); - + getSettings().video.lockAspectRatio, [](bool enabled) { + AuroraSetViewportPolicy(enabled ? AURORA_VIEWPORT_FIT : AURORA_VIEWPORT_STRETCH); + }); + + add_toggle(scroll, "vsync", "VSync", getSettings().video.enableVsync, + [](bool enabled) { aurora_enable_vsync(enabled); }); + add_toggle(scroll, "frame-interp", "Unlock Framerate", - getSettings().game.enableFrameInterpolation, {}, "Experimental"); + getSettings().game.enableFrameInterpolation, {}, "Experimental"); add_section_header(scroll, "Post-Processing"); @@ -535,8 +548,8 @@ private: add_bloom_brightness_row(scroll); } - add_toggle(scroll, "depth-of-field", "Depth of Field", - getSettings().game.enableDepthOfField); + add_toggle( + scroll, "depth-of-field", "Depth of Field", getSettings().game.enableDepthOfField); add_section_header(scroll, "Developer Options"); @@ -545,31 +558,34 @@ private: aurora::gx::enableLodBias = !aurora::gx::enableLodBias; m_needsRebuild = true; }; - auto lodOption = std::make_unique(scroll, "lod-bias", "LOD Bias", - lodValue, std::string_view{}, - queue_activate("lod-bias")); - register_row(Row{"lod-bias", lodMutate, [lodMutate](int) { lodMutate(); }}, - std::move(lodOption)); + auto lodOption = std::make_unique(scroll, "lod-bias", "LOD Bias", lodValue, + std::string_view{}, queue_activate("lod-bias")); + register_row( + Row{"lod-bias", lodMutate, [lodMutate](int) { lodMutate(); }}, std::move(lodOption)); - add_toggle(scroll, "minimap-shadows", "Mini-Map Shadows", - getSettings().game.enableMapBackground); + add_toggle( + scroll, "minimap-shadows", "Mini-Map Shadows", getSettings().game.enableMapBackground); } void build_placeholder_tab(Rml::Element* body, std::string_view tabLabel) { - auto* wrap = append(body, "div"); - set_props(wrap, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"align-items", "center"}, - {"justify-content", "center"}, - {"width", "100%"}, - {"flex-grow", "1"}, - {"gap", "12dp"}, - }); + auto* wrap = append(body, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::FlexGrow, rml_number(1.0f)}, + {Rml::PropertyId::RowGap, rml_dp(12.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(12.0f)}, + }); auto* heading = add_label(wrap, tabLabel, LabelStyle::Large); - set_props(heading, {{"text-align", "center"}}); + set_props(heading, {{Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Center}}); auto* sub = add_label(wrap, "Not yet ported.", LabelStyle::Body); - set_props(sub, {{"text-align", "center"}, {"color", theme::rgba(theme::TextDim)}}); + set_props(sub, { + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Center}, + {Rml::PropertyId::Color, rml_color(theme::TextDim)}, + }); } void build_body() { @@ -630,7 +646,7 @@ private: void request_close() { m_requestClose = true; } void switch_tab(int direction) { - const int count = static_cast(kTabs.size()); + const int count = kTabs.size(); const int next = (static_cast(m_tab) + direction + count) % count; m_pendingTabId = kTabs[static_cast(next)].id; } diff --git a/src/dusk/ui/game_option.cpp b/src/dusk/ui/game_option.cpp index 8962e47442..66540c967c 100644 --- a/src/dusk/ui/game_option.cpp +++ b/src/dusk/ui/game_option.cpp @@ -13,89 +13,104 @@ namespace dusk::ui { GameOption::GameOption(Rml::Element* parent, std::string_view id, std::string_view title, - std::string_view value, std::string_view detail, - std::function pressedCallback) + std::string_view value, std::string_view detail, std::function pressedCallback) : m_pressedCallback(std::move(pressedCallback)) { using namespace theme; - m_element = append(parent, "button", id); - set_props(m_element, { - {"display", "flex"}, - {"position", "relative"}, - {"flex-direction", "row"}, - {"align-items", "center"}, - {"justify-content", "space-between"}, - {"box-sizing", "border-box"}, - {"gap", "16dp"}, - {"width", "100%"}, - {"height", "auto"}, - {"padding", "16dp"}, - {"border-width", dp(BorderWidth)}, - {"border-radius", dp(BorderRadiusSmall)}, - {"background-color", rgba(Transparent)}, - {"border-color", rgba(ElevatedBorder, 0)}, - {"color", rgba(TextDim)}, - {"cursor", "pointer"}, - {"tab-index", "auto"}, - {"nav-up", "auto"}, - {"nav-down", "auto"}, - {"nav-left", "auto"}, - {"nav-right", "auto"}, - {"opacity", "1"}, - {"font-family", "Inter"}, - }); + m_element = append(parent, "button", id, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::Position, Rml::Style::Position::Relative}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::SpaceBetween}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::RowGap, rml_dp(16.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(16.0f)}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::PaddingTop, rml_dp(16.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(16.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(16.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(16.0f)}, + {Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusSmall)}, + {Rml::PropertyId::BackgroundColor, rml_color(Transparent)}, + {Rml::PropertyId::BorderTopColor, rml_color(ElevatedBorder, 0)}, + {Rml::PropertyId::BorderRightColor, rml_color(ElevatedBorder, 0)}, + {Rml::PropertyId::BorderBottomColor, rml_color(ElevatedBorder, 0)}, + {Rml::PropertyId::BorderLeftColor, rml_color(ElevatedBorder, 0)}, + {Rml::PropertyId::Color, rml_color(TextDim)}, + {Rml::PropertyId::Cursor, rml_string("pointer")}, + {Rml::PropertyId::TabIndex, Rml::Style::TabIndex::Auto}, + {Rml::PropertyId::NavUp, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavDown, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavLeft, Rml::Style::Nav::Auto}, + {Rml::PropertyId::NavRight, Rml::Style::Nav::Auto}, + {Rml::PropertyId::Opacity, rml_number(1.0f)}, + {Rml::PropertyId::FontFamily, rml_string("Inter")}, + }); add_focus_border(m_element, BorderRadiusSmall); - auto* left = append(m_element, "div"); - set_props(left, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"gap", "4dp"}, - {"min-width", "0"}, - {"width", "0"}, - {"flex-grow", "1"}, - {"flex-shrink", "1"}, - {"pointer-events", "none"}, - }); + auto* left = append(m_element, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::RowGap, rml_dp(4.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(4.0f)}, + {Rml::PropertyId::MinWidth, rml_px(0.0f)}, + {Rml::PropertyId::Width, rml_px(0.0f)}, + {Rml::PropertyId::FlexGrow, rml_number(1.0f)}, + {Rml::PropertyId::FlexShrink, rml_number(1.0f)}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, + }); m_title = add_label(left, title, LabelStyle::Large); set_props(m_title, { - {"color", rgba(TextDim)}, - {"font-size", "28dp"}, - {"letter-spacing", "1dp"}, + {Rml::PropertyId::Color, rml_color(TextDim)}, + {Rml::PropertyId::FontSize, rml_dp(28.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(1.0f)}, }); if (!value.empty() || !detail.empty()) { - auto* right = append(m_element, "div"); - set_props(right, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"align-items", "flex-end"}, - {"justify-content", "center"}, - {"gap", "4dp"}, - {"min-width", "170dp"}, - {"max-width", "48%"}, - {"flex-shrink", "0"}, - {"pointer-events", "none"}, - }); + auto* right = append(m_element, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::FlexEnd}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::RowGap, rml_dp(4.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(4.0f)}, + {Rml::PropertyId::MinWidth, rml_dp(170.0f)}, + {Rml::PropertyId::MaxWidth, rml_percent(48.0f)}, + {Rml::PropertyId::FlexShrink, rml_number(0.0f)}, + {Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None}, + }); if (!value.empty()) { m_value = add_label(right, value, LabelStyle::Body); - set_props(m_value, { - {"color", rgba(TextDim)}, - {"text-align", "right"}, - {"overflow", "hidden"}, - {"text-overflow", "ellipsis"}, - {"white-space", "nowrap"}, - }); + set_props( + m_value, { + {Rml::PropertyId::Color, rml_color(TextDim)}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Right}, + {Rml::PropertyId::OverflowX, Rml::Style::Overflow::Hidden}, + {Rml::PropertyId::OverflowY, Rml::Style::Overflow::Hidden}, + {Rml::PropertyId::TextOverflow, Rml::Style::TextOverflow::Ellipsis}, + {Rml::PropertyId::WhiteSpace, Rml::Style::WhiteSpace::Nowrap}, + }); } if (!detail.empty()) { m_detail = add_label(right, detail, LabelStyle::Annotation); set_props(m_detail, { - {"color", rgba(TextDim)}, - {"text-align", "right"}, + {Rml::PropertyId::Color, rml_color(TextDim)}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Right}, }); } } @@ -167,18 +182,18 @@ void GameOption::apply_style() { } const bool active = m_hovered || m_focused; - apply_control_surface_style(m_element, control_surface_style(ControlSurfaceTone::Quiet), - active); - m_element->SetProperty("color", - active ? theme::rgba(theme::TextActive) : theme::rgba(theme::TextDim)); - m_title->SetProperty("color", - active ? theme::rgba(theme::TextActive) : theme::rgba(theme::TextDim)); + apply_control_surface_style( + m_element, control_surface_style(ControlSurfaceTone::Quiet), active); + m_element->SetProperty( + Rml::PropertyId::Color, rml_color(active ? theme::TextActive : theme::TextDim)); + m_title->SetProperty( + Rml::PropertyId::Color, rml_color(active ? theme::TextActive : theme::TextDim)); if (m_value != nullptr) { - m_value->SetProperty("color", - active ? theme::rgba(theme::TextActive) : theme::rgba(theme::TextDim)); + m_value->SetProperty( + Rml::PropertyId::Color, rml_color(active ? theme::TextActive : theme::TextDim)); } if (m_detail != nullptr) { - m_detail->SetProperty("color", theme::rgba(theme::TextDim)); + m_detail->SetProperty(Rml::PropertyId::Color, rml_color(theme::TextDim)); } set_focus_border_visible(m_element, m_focused); } diff --git a/src/dusk/ui/game_option.hpp b/src/dusk/ui/game_option.hpp index a8ae5c20b8..c66e3ddd2a 100644 --- a/src/dusk/ui/game_option.hpp +++ b/src/dusk/ui/game_option.hpp @@ -15,8 +15,7 @@ namespace dusk::ui { class GameOption : public Rml::EventListener { public: GameOption(Rml::Element* parent, std::string_view id, std::string_view title, - std::string_view value, std::string_view detail, - std::function pressedCallback); + std::string_view value, std::string_view detail, std::function pressedCallback); ~GameOption() override; GameOption(const GameOption&) = delete; diff --git a/src/dusk/ui/label.cpp b/src/dusk/ui/label.cpp index ca8ce3d4af..1077a9fcba 100644 --- a/src/dusk/ui/label.cpp +++ b/src/dusk/ui/label.cpp @@ -10,28 +10,36 @@ void apply_label_style(Rml::Element* element, LabelStyle style) { switch (style) { case LabelStyle::Annotation: - set_props(element, {{"font-size", "18dp"}, - {"letter-spacing", "2dp"}, - {"font-weight", "400"}, - {"color", rgba(TextDim)}}); + set_props(element, { + {Rml::PropertyId::FontSize, rml_dp(18.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(2.0f)}, + {Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Normal}, + {Rml::PropertyId::Color, rml_color(TextDim)}, + }); break; case LabelStyle::Body: - set_props(element, {{"font-size", "20dp"}, - {"letter-spacing", "0"}, - {"font-weight", "400"}, - {"color", rgba(Text)}}); + set_props(element, { + {Rml::PropertyId::FontSize, rml_dp(20.0f)}, + {Rml::PropertyId::LetterSpacing, rml_px(0.0f)}, + {Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Normal}, + {Rml::PropertyId::Color, rml_color(Text)}, + }); break; case LabelStyle::Medium: - set_props(element, {{"font-size", "28dp"}, - {"letter-spacing", "3dp"}, - {"font-weight", "700"}, - {"color", rgba(Text)}}); + set_props(element, { + {Rml::PropertyId::FontSize, rml_dp(28.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(3.0f)}, + {Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Bold}, + {Rml::PropertyId::Color, rml_color(Text)}, + }); break; case LabelStyle::Large: - set_props(element, {{"font-size", "36dp"}, - {"letter-spacing", "4dp"}, - {"font-weight", "700"}, - {"color", rgba(Text)}}); + set_props(element, { + {Rml::PropertyId::FontSize, rml_dp(36.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(4.0f)}, + {Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Bold}, + {Rml::PropertyId::Color, rml_color(Text)}, + }); break; } } diff --git a/src/dusk/ui/prelaunch_layout.cpp b/src/dusk/ui/prelaunch_layout.cpp index c5c6ff9dc7..a1916cc89e 100644 --- a/src/dusk/ui/prelaunch_layout.cpp +++ b/src/dusk/ui/prelaunch_layout.cpp @@ -4,77 +4,90 @@ #include "label.hpp" #include "theme.hpp" +#include + namespace dusk::ui::prelaunch::layout { void style_document(Rml::ElementDocument* document) { using namespace theme; set_props(document, { - {"width", "100%"}, - {"height", "100%"}, - {"margin", "0"}, - {"padding", "0"}, - {"font-family", "Inter"}, - {"background-color", rgba(Background1)}, - {"color", rgba(Text)}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::Height, rml_percent(100.0f)}, + {Rml::PropertyId::MarginTop, rml_px(0.0f)}, + {Rml::PropertyId::MarginRight, rml_px(0.0f)}, + {Rml::PropertyId::MarginBottom, rml_px(0.0f)}, + {Rml::PropertyId::MarginLeft, rml_px(0.0f)}, + {Rml::PropertyId::PaddingTop, rml_px(0.0f)}, + {Rml::PropertyId::PaddingRight, rml_px(0.0f)}, + {Rml::PropertyId::PaddingBottom, rml_px(0.0f)}, + {Rml::PropertyId::PaddingLeft, rml_px(0.0f)}, + {Rml::PropertyId::FontFamily, rml_string("Inter")}, + {Rml::PropertyId::BackgroundColor, rml_color(Background1)}, + {Rml::PropertyId::Color, rml_color(Text)}, }); } Rml::Element* add_screen(Rml::ElementDocument* document, ScreenLayout layout) { using namespace theme; - auto* screen = append(document, "div", "prelaunch-screen"); - set_props(screen, - { - {"display", "flex"}, - {"position", "absolute"}, - {"left", "0"}, - {"top", "0"}, - {"right", "0"}, - {"bottom", "0"}, - {"flex-direction", layout == ScreenLayout::CompactSplit ? "row" : "column"}, - {"align-items", "center"}, - {"justify-content", "center"}, - {"gap", layout == ScreenLayout::CompactSplit ? "28dp" : "24dp"}, - {"box-sizing", "border-box"}, - {"padding", layout == ScreenLayout::CompactSplit ? "24dp" : "48dp 28dp"}, - {"background-color", rgba(Background1)}, - }); - return screen; + const bool compact = layout == ScreenLayout::CompactSplit; + return append(document, "div", "prelaunch-screen", + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::Position, Rml::Style::Position::Absolute}, + {Rml::PropertyId::Left, rml_px(0.0f)}, + {Rml::PropertyId::Top, rml_px(0.0f)}, + {Rml::PropertyId::Right, rml_px(0.0f)}, + {Rml::PropertyId::Bottom, rml_px(0.0f)}, + {Rml::PropertyId::FlexDirection, + compact ? Rml::Style::FlexDirection::Row : Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::RowGap, rml_dp(compact ? 28.0f : 24.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(compact ? 28.0f : 24.0f)}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::PaddingTop, rml_dp(compact ? 24.0f : 48.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(compact ? 24.0f : 28.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(compact ? 24.0f : 48.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(compact ? 24.0f : 28.0f)}, + {Rml::PropertyId::BackgroundColor, rml_color(Background1)}, + }); } Rml::Element* add_brand(Rml::Element* parent, std::string_view logoPath, bool compact) { - auto* brand = append(parent, "div"); - set_props(brand, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"align-items", "center"}, - {"justify-content", "center"}, - {"gap", compact ? "8dp" : "12dp"}, - {"width", compact ? "260dp" : "100%"}, - {"max-width", compact ? "32%" : "720dp"}, - {"flex-shrink", compact ? "0" : "1"}, - }); + auto* brand = append(parent, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center}, + {Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center}, + {Rml::PropertyId::RowGap, rml_dp(compact ? 8.0f : 12.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(compact ? 8.0f : 12.0f)}, + {Rml::PropertyId::Width, compact ? rml_dp(260.0f) : rml_percent(100.0f)}, + {Rml::PropertyId::MaxWidth, compact ? rml_percent(32.0f) : rml_dp(720.0f)}, + {Rml::PropertyId::FlexShrink, rml_number(compact ? 0.0f : 1.0f)}, + }); auto* subtitle = add_label(brand, "Twilit Realm presents", LabelStyle::Annotation); set_props(subtitle, { - {"text-align", "center"}, - {"font-size", compact ? "14dp" : "18dp"}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Center}, + {Rml::PropertyId::FontSize, rml_dp(compact ? 14.0f : 18.0f)}, }); if (!logoPath.empty()) { auto* logo = append(brand, "img"); logo->SetAttribute("src", std::string(logoPath)); set_props(logo, { - {"width", compact ? "220dp" : "360dp"}, - {"max-width", compact ? "100%" : "70%"}, - {"height", "auto"}, + {Rml::PropertyId::Width, rml_dp(compact ? 220.0f : 360.0f)}, + {Rml::PropertyId::MaxWidth, rml_percent(compact ? 100.0f : 70.0f)}, + {Rml::PropertyId::Height, Rml::Style::Height::Auto}, }); } else { auto* title = add_label(brand, "Dusk", LabelStyle::Large); set_props(title, { - {"font-size", compact ? "42dp" : "54dp"}, - {"letter-spacing", compact ? "3dp" : "4dp"}, + {Rml::PropertyId::FontSize, rml_dp(compact ? 42.0f : 54.0f)}, + {Rml::PropertyId::LetterSpacing, rml_dp(compact ? 3.0f : 4.0f)}, }); } return brand; @@ -83,9 +96,9 @@ Rml::Element* add_brand(Rml::Element* parent, std::string_view logoPath, bool co Rml::Element* add_heading(Rml::Element* parent, std::string_view title) { auto* heading = add_label(parent, title, LabelStyle::Large); set_props(heading, { - {"width", "100%"}, - {"max-width", "840dp"}, - {"text-align", "left"}, + {Rml::PropertyId::Width, rml_percent(100.0f)}, + {Rml::PropertyId::MaxWidth, rml_dp(840.0f)}, + {Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Left}, }); return heading; } @@ -93,21 +106,33 @@ Rml::Element* add_heading(Rml::Element* parent, std::string_view title) { Rml::Element* add_panel(Rml::Element* parent, bool wide, bool compact) { using namespace theme; - auto* panel = append(parent, "div"); - set_props(panel, { - {"display", "flex"}, - {"flex-direction", "column"}, - {"gap", "12dp"}, - {"width", wide ? "840dp" : "520dp"}, - {"max-width", compact ? "62%" : "100%"}, - {"box-sizing", "border-box"}, - {"padding", compact ? "16dp" : "20dp"}, - {"border-width", dp(BorderWidth)}, - {"border-radius", dp(BorderRadiusMedium)}, - {"border-color", rgba(ElevatedBorder, ElevatedBorder.a)}, - {"background-color", rgba(ElevatedSoft, ElevatedSoft.a)}, - }); - return panel; + return append(parent, "div", {}, + { + {Rml::PropertyId::Display, Rml::Style::Display::Flex}, + {Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column}, + {Rml::PropertyId::RowGap, rml_dp(12.0f)}, + {Rml::PropertyId::ColumnGap, rml_dp(12.0f)}, + {Rml::PropertyId::Width, rml_dp(wide ? 840.0f : 520.0f)}, + {Rml::PropertyId::MaxWidth, rml_percent(compact ? 62.0f : 100.0f)}, + {Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox}, + {Rml::PropertyId::PaddingTop, rml_dp(compact ? 16.0f : 20.0f)}, + {Rml::PropertyId::PaddingRight, rml_dp(compact ? 16.0f : 20.0f)}, + {Rml::PropertyId::PaddingBottom, rml_dp(compact ? 16.0f : 20.0f)}, + {Rml::PropertyId::PaddingLeft, rml_dp(compact ? 16.0f : 20.0f)}, + {Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth)}, + {Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusMedium)}, + {Rml::PropertyId::BorderTopColor, rml_color(ElevatedBorder)}, + {Rml::PropertyId::BorderRightColor, rml_color(ElevatedBorder)}, + {Rml::PropertyId::BorderBottomColor, rml_color(ElevatedBorder)}, + {Rml::PropertyId::BorderLeftColor, rml_color(ElevatedBorder)}, + {Rml::PropertyId::BackgroundColor, rml_color(ElevatedSoft)}, + }); } } // namespace dusk::ui::prelaunch::layout diff --git a/src/dusk/ui/prelaunch_layout.hpp b/src/dusk/ui/prelaunch_layout.hpp index c43136a787..11efea9b4f 100644 --- a/src/dusk/ui/prelaunch_layout.hpp +++ b/src/dusk/ui/prelaunch_layout.hpp @@ -13,8 +13,8 @@ enum class ScreenLayout { }; void style_document(Rml::ElementDocument* document); -Rml::Element* add_screen(Rml::ElementDocument* document, - ScreenLayout layout = ScreenLayout::Standard); +Rml::Element* add_screen( + Rml::ElementDocument* document, ScreenLayout layout = ScreenLayout::Standard); Rml::Element* add_brand(Rml::Element* parent, std::string_view logoPath, bool compact = false); Rml::Element* add_heading(Rml::Element* parent, std::string_view title); Rml::Element* add_panel(Rml::Element* parent, bool wide, bool compact = false); diff --git a/src/dusk/ui/prelaunch_screen.cpp b/src/dusk/ui/prelaunch_screen.cpp index 67792e09d5..45525c6af7 100644 --- a/src/dusk/ui/prelaunch_screen.cpp +++ b/src/dusk/ui/prelaunch_screen.cpp @@ -53,7 +53,11 @@ struct BackendChoice { }; constexpr std::array kLanguageNames = { - "English", "German", "French", "Spanish", "Italian", + "English", + "German", + "French", + "Spanish", + "Italian", }; constexpr std::array kGameDiscFileFilters{{ @@ -217,7 +221,7 @@ std::string display_path(std::string_view path) { std::vector backend_choices() { std::vector choices; choices.push_back({BACKEND_AUTO, std::string(backend_id(BACKEND_AUTO)), - std::string(backend_name(BACKEND_AUTO))}); + std::string(backend_name(BACKEND_AUTO))}); size_t backendCount = 0; const AuroraBackend* availableBackends = aurora_get_available_backends(&backendCount); @@ -458,8 +462,8 @@ private: m_requestedCycleDirection = direction; } - void add_button_control(Rml::Element* parent, std::string_view id, std::string_view text, - ButtonVariant variant) { + void add_button_control( + Rml::Element* parent, std::string_view id, std::string_view text, ButtonVariant variant) { const std::string idString(id); m_focusIds.push_back(idString); m_buttons.push_back(std::make_unique