From ac131c7835728354f36955ae07d8549c207893ad Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sat, 30 Dec 2023 19:03:57 -0500 Subject: [PATCH] More work on graphics config menu, improved focus handling in UI, fixed scissor bug in UI rendering --- assets/config_menu.rml | 91 +++++++++++++++++++++++++++++++----------- assets/recomp.rcss | 60 +++++++++++++++++++--------- src/ui/ui_renderer.cpp | 64 ++++++++++++++++++++++++++++- 3 files changed, 171 insertions(+), 44 deletions(-) diff --git a/assets/config_menu.rml b/assets/config_menu.rml index 5f88a39..bfb9ead 100644 --- a/assets/config_menu.rml +++ b/assets/config_menu.rml @@ -23,7 +23,7 @@ text-align: center; } #tab_graphics:selected { - nav-down:#ar_original; + nav-down:#res_auto; } @@ -35,29 +35,74 @@ Graphics
-
-
-
-
- - - - +
+
+
+
+
+
+ + + + + + +
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ + + + + + + + +
+
+
+ +
+
+
+
+
+ + + + + + +
+ +
+
-
- -
-
-

- - - - - - -
- -

diff --git a/assets/recomp.rcss b/assets/recomp.rcss index 05e5bfe..2d90194 100644 --- a/assets/recomp.rcss +++ b/assets/recomp.rcss @@ -22,6 +22,39 @@ body { tab-index:none; } */ +div.option_container { + display:flex; + flex-direction: column; + width:850dp; + border-radius:0dp; + height:auto; + padding:16dp; + text-align:left; + margin-left:auto; + margin-right:auto; + font-effect: outline(2dp black); + font-size:24dp; + background:rgba(50,50,50,200); +} + +div.option_row { + display:flex; + flex-direction: row; +} + +div.option { + flex:1; + padding:4dp; + text-align:center; +} + +div.option_list { + padding:2dp; + text-align:center; + display:flex; + justify-content:center; +} + div#title_bar { z-index: 1; position: absolute; @@ -71,7 +104,7 @@ div#content { p { text-align: left; - margin-bottom: 4dp; + /* margin-bottom: 4dp; */ } h1 { @@ -255,17 +288,18 @@ select selectbox option:hover { input.radio, input.checkbox { /* width: 30dp; */ - height: 30dp; + /* height: 30dp; */ /* vertical-align: -11dp; */ - margin-top: 4dp; - margin-bottom: 4dp; - flex: 1; + /* margin-top: 4dp; */ + /* margin-bottom: 4dp; */ + flex: 0; tab-index:auto; focus:auto; nav-up:auto; nav-down:auto; nav-right:auto; nav-left:auto; + width:0dp; } input.radio + label { @@ -276,6 +310,8 @@ input.radio + label { text-align:center; tab-index:none; focus:auto; + margin-left:10dp; + margin-right:10dp; /* display:none; */ /* decorator: image(radio) */ } @@ -295,21 +331,11 @@ input.radio:checked + label { /* decorator: image(radio-checked) */ } -input.radio:hover + label { - color:#329696; - /* background: rgb(150,150,150); */ -} - input.radio:focus + label { color:#329696; /* background: rgb(150,150,150); */ } -input.radio:checked:hover + label { - border-bottom:1dp; - /* background: rgb(150,150,150); */ -} - tabset { font:bold; margin:1dp; @@ -332,10 +358,6 @@ tab { nav-left:auto; } -tab:hover { - color:#329696; -} - tab:selected { border-top: 2dp; border-color: white; diff --git a/src/ui/ui_renderer.cpp b/src/ui/ui_renderer.cpp index c7a6bf0..e0cc38a 100644 --- a/src/ui/ui_renderer.cpp +++ b/src/ui/ui_renderer.cpp @@ -339,7 +339,7 @@ public: list_->setViewports(RT64::RenderViewport{ 0, 0, float(window_width_), float(window_height_) }); if (scissor_enabled_) { - list_->setScissors(RT64::RenderRect{ scissor_x_, scissor_y_, scissor_width_, scissor_height_ }); + list_->setScissors(RT64::RenderRect{ scissor_x_, scissor_y_, scissor_width_ + scissor_x_, scissor_height_ + scissor_y_ }); } else { list_->setScissors(RT64::RenderRect{ 0, 0, window_width_, window_height_ }); @@ -564,11 +564,34 @@ public: } }; +bool can_focus(Rml::Element* element) { + return element->GetProperty(Rml::PropertyId::TabIndex)->Get() != Rml::Property(Rml::Style::TabIndex::None); +} + +Rml::Element* get_target(Rml::ElementDocument* document, Rml::Element* element) { + // Labels can have targets, so check if this element is a label. + if (element->GetTagName() == "label") { + // Check if the label has a "for" property. + Rml::String for_value = element->GetAttribute("for", ""); + + // If there is a value for the "for" property, find that element and return it if it exists. + if (!for_value.empty()) { + Rml::Element* target_element = document->GetElementById(for_value); + if (target_element) { + return target_element; + } + } + } + // Return the element directly if no target exists. + return element; +} + struct { struct UIRenderContext render; class { std::unordered_map documents; Rml::ElementDocument* current_document; + Rml::Element* prev_focused; public: SystemInterface_SDL system_interface; std::unique_ptr render_interface; @@ -619,6 +642,30 @@ struct { documents.emplace(recomp::Menu::Launcher, context->LoadDocument("assets/launcher.rml")); documents.emplace(recomp::Menu::Config, context->LoadDocument("assets/config_menu.rml")); } + + void update_focus(bool mouse_moved) { + Rml::Element* focused = current_document->GetFocusLeafNode(); + + // If there was mouse motion, get the current hovered element (or its target if it points to one) and focus that if applicable. + if (mouse_moved) { + Rml::Element* hovered = context->GetHoverElement(); + if (hovered) { + Rml::Element* hover_target = get_target(current_document, hovered); + if (hover_target && can_focus(hover_target)) { + hover_target->Focus(); + } + } + } + + // Revert focus to the previous element if focused on anything without a tab index. + // This should prevent the user from losing focus on something that has no navigation. + if (focused && !can_focus(focused)) { + prev_focused->Focus(); + } + else { + prev_focused = current_document->GetFocusLeafNode(); + } + } } rml; } UIContext; @@ -693,7 +740,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_ bool is_reload_held = key_state[SDL_SCANCODE_F11] != 0; bool reload_sheets = is_reload_held && !was_reload_held; was_reload_held = is_reload_held; - + static recomp::Menu prev_menu = recomp::Menu::None; recomp::Menu cur_menu = open_menu.load(); @@ -710,10 +757,23 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_ SDL_Event cur_event{}; + bool mouse_moved = false; + while (recomp::try_deque_event(cur_event)) { RmlSDL::InputEventHandler(UIContext.rml.context, cur_event); + + // If a menu is open then implement some additional behavior for specific events on top of what RmlUi normally does with them. + if (cur_menu != recomp::Menu::None) { + switch (cur_event.type) { + case SDL_EventType::SDL_MOUSEMOTION: + mouse_moved = true; + break; + } + } } + UIContext.rml.update_focus(mouse_moved); + if (cur_menu != recomp::Menu::None) { int width, height; SDL_GetWindowSizeInPixels(window, &width, &height);