Browse Source

fix(activity-host): improve floating tool windows

- add title bars and standard close controls
- sync window visibility with Activity Host checkboxes
- remove redundant card wrappers from tool windows
- improve resize visibility and window framing
- center World and Packets with viewport-relative first-use sizes
- preserve existing Activity Host behavior
saulo benigno 1 week ago
parent
commit
6d04769909

+ 10 - 54
Sunrise/src/server/ui/activity_host/activity_host_event_view.cpp

@@ -8,7 +8,6 @@
 #include <imgui.h>
 #include <string_view>
 
-#include "../../../core/ui/components/card/ui_card_component.h"
 #include "../../../core/ui/components/section/ui_section_component.h"
 #include "../../../middleware/bap/activity_message/wire_schema/activity_wire_schema.h"
 #include "../../activity/host_runtime.h"
@@ -20,7 +19,6 @@ namespace sunrise::server::ui::activity_host::event_view {
 namespace {
 
 namespace host = server::activity::host;
-namespace card = core::ui::components::card;
 namespace section = core::ui::components::section;
 namespace wire_schema = middleware::bap::activity_message::wire_schema;
 namespace sense_update = middleware::bap::activity_message::sense_update;
@@ -499,39 +497,6 @@ void draw_client_messages(const state::activity::SessionBinding* selected,
     }
 }
 
-/** Counts ingress rows after the current generation, type, and epoch filters. */
-[[nodiscard]] std::size_t
-visible_client_message_count(const state::activity::SessionBinding* selected,
-                             const host::DiagnosticsSnapshot& snapshot) noexcept {
-    std::size_t count = 0;
-    bool hasPatchEpoch = false;
-    for (std::size_t index = 0; index < snapshot.clientMessageCount; ++index) {
-        const host::ClientMessageRecord& record = snapshot.clientMessages[index];
-        if (!client_message_visible(record, selected)) {
-            continue;
-        }
-        if (g_coalescePatchEpoch && record.messageType == 52) {
-            hasPatchEpoch = true;
-        } else {
-            ++count;
-        }
-    }
-    return count + (hasPatchEpoch ? 1U : 0U);
-}
-
-/** Counts host transitions for the selected exact generation. */
-[[nodiscard]] std::size_t visible_event_count(const state::activity::SessionBinding* selected,
-                                              const host::DiagnosticsSnapshot& snapshot) noexcept {
-    if (selected == nullptr) {
-        return 0;
-    }
-    std::size_t count = 0;
-    for (std::size_t index = 0; index < snapshot.eventCount; ++index) {
-        count += same_binding(snapshot.events[index].binding, *selected) ? 1U : 0U;
-    }
-    return count;
-}
-
 /** Draws recent events for the selected exact activity generation. */
 void draw_events(const state::activity::SessionBinding& selected,
                  const host::DiagnosticsSnapshot& snapshot) noexcept {
@@ -595,26 +560,17 @@ void draw(bool& open,
     }
     const state::activity::SessionBinding* const selected =
         instance != nullptr ? &instance->binding : nullptr;
-    const std::size_t clientRows = visible_client_message_count(selected, snapshot);
-    const std::size_t eventRows = visible_event_count(selected, snapshot);
-    const float rows = table_layout::authored_rows_height(clientRows, 16)
-                       + table_layout::authored_rows_height(eventRows, 16);
-    const float baseHeight = selected != nullptr ? 250.0F : 190.0F;
-    const ImVec2 windowSize{820.0F, (std::clamp)(baseHeight + rows, 240.0F, 680.0F)};
-    const bool visible = tool_window::begin(
-        "Activity Host - Packets###activity_host_events", open, {320.0F, 320.0F}, windowSize);
+    const bool visible =
+        tool_window::begin("Packets - Activity Host###activity_host_events", open, {0.72F, 0.46F});
     if (visible) {
-        const card::Scope surface("##activity_host_events_card");
-        if (surface.visible()) {
-            draw_client_messages(selected, snapshot);
-            if (instance != nullptr) {
-                ImGui::Spacing();
-                draw_events(instance->binding, snapshot);
-                ImGui::Spacing();
-                incident_editor::draw(instance->binding, *instance, snapshot);
-            } else {
-                ImGui::TextDisabled("No activity selected. Showing every packet.");
-            }
+        draw_client_messages(selected, snapshot);
+        if (instance != nullptr) {
+            ImGui::Spacing();
+            draw_events(instance->binding, snapshot);
+            ImGui::Spacing();
+            incident_editor::draw(instance->binding, *instance, snapshot);
+        } else {
+            ImGui::TextDisabled("No activity selected. Showing every packet.");
         }
     }
     ImGui::End();

+ 3 - 8
Sunrise/src/server/ui/activity_host/activity_host_sdk_view.cpp

@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "../../../client/ui/activity/authored_placement_marker.h"
-#include "../../../core/ui/components/card/ui_card_component.h"
 #include "../../../core/ui/scaling/dpi/ui_dpi_scaling.h"
 #include "../../../state/activity_sdk/generation/runtime.h"
 #include "../../../state/activity_sdk/runtime.h"
@@ -25,7 +24,6 @@
 namespace sunrise::server::ui::activity_host::sdk_view {
 namespace {
 
-namespace card = core::ui::components::card;
 namespace format = state::activity_sdk::format;
 namespace generation = state::activity_sdk::generation;
 namespace host = server::activity::host;
@@ -386,13 +384,10 @@ void draw(bool& open, const host::InstanceSnapshot* instance) noexcept {
         marker::set_world_page(marker::WorldPage::none);
         return;
     }
-    const bool visible = tool_window::begin(
-        "Activity Host - World###activity_host_sdk", open, {32.0F, 40.0F}, {940.0F, 680.0F});
+    const bool visible =
+        tool_window::begin("World - Activity Host###activity_host_sdk", open, {0.72F, 0.68F});
     if (visible) {
-        const card::Scope surface("##activity_host_sdk_card");
-        if (surface.visible()) {
-            draw_content(instance);
-        }
+        draw_content(instance);
     }
     ImGui::End();
     if (!open) {

+ 21 - 26
Sunrise/src/server/ui/activity_host/activity_host_tool_window.h

@@ -7,51 +7,46 @@
 
 namespace sunrise::server::ui::activity_host::tool_window {
 
-/** The transparent parent moves and resizes while the card owns content scrolling. */
+/** A titled window that moves, resizes and scrolls its own content. */
 constexpr ImGuiWindowFlags kWindowFlags =
-    ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings
-    | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
+    ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings;
 
-/** Applies a bounded content size and a first-use position. */
-inline void set_next(const ImVec2& authoredPosition, const ImVec2& authoredSize) noexcept {
+/** Applies bounded size constraints and a centered first-use size given as work-area fractions. */
+inline void set_next(const ImVec2& workFraction) noexcept {
     namespace scaling = core::ui::scaling::dpi;
-    ImVec2 size = scaling::pixels(authoredSize);
     const ImGuiViewport* viewport = ImGui::GetMainViewport();
     if (viewport == nullptr) {
-        ImGui::SetNextWindowSize(size, ImGuiCond_FirstUseEver);
         return;
     }
     const float margin = scaling::pixels(16.0F);
     const ImVec2 maximum{(std::max)(viewport->WorkSize.x - (margin * 2.0F), 1.0F),
                          (std::max)(viewport->WorkSize.y - (margin * 2.0F), 1.0F)};
-    size.x = (std::min)(size.x, maximum.x);
-    size.y = (std::min)(size.y, maximum.y);
     const ImVec2 requestedMinimum = scaling::pixels({320.0F, 120.0F});
     const ImVec2 minimum{(std::min)(requestedMinimum.x, maximum.x),
                          (std::min)(requestedMinimum.y, maximum.y)};
+    const ImVec2 size{std::clamp(viewport->WorkSize.x * workFraction.x, minimum.x, maximum.x),
+                      std::clamp(viewport->WorkSize.y * workFraction.y, minimum.y, maximum.y)};
     ImGui::SetNextWindowSizeConstraints(minimum, maximum);
     ImGui::SetNextWindowSize(size, ImGuiCond_FirstUseEver);
-
-    const ImVec2 requested = scaling::pixels(authoredPosition);
-    const ImVec2 available{(std::max)(viewport->WorkSize.x - size.x, 0.0F),
-                           (std::max)(viewport->WorkSize.y - size.y, 0.0F)};
-    const ImVec2 position{viewport->WorkPos.x + std::clamp(requested.x, 0.0F, available.x),
-                          viewport->WorkPos.y + std::clamp(requested.y, 0.0F, available.y)};
-    ImGui::SetNextWindowPos(position, ImGuiCond_FirstUseEver);
+    ImGui::SetNextWindowPos(viewport->GetWorkCenter(), ImGuiCond_FirstUseEver, {0.5F, 0.5F});
 }
 
-/** Begins a transparent movable parent whose entire visible surface is the child card. */
-[[nodiscard]] inline bool begin(const char* id,
-                                bool& open,
-                                const ImVec2& authoredPosition,
-                                const ImVec2& authoredSize) noexcept {
-    set_next(authoredPosition, authoredSize);
-    ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4{});
-    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0F);
-    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{});
+/** Begins a movable, resizable window whose title bar reads as a raised Sunrise panel. */
+[[nodiscard]] inline bool begin(const char* id, bool& open, const ImVec2& workFraction) noexcept {
+    namespace scaling = core::ui::scaling::dpi;
+    set_next(workFraction);
+    // Dear ImGui reads these only while Begin draws the frame, so the body keeps the theme.
+    // The same colour whether focused or not, so focus never lights the bar up.
+    const ImGuiStyle& style = ImGui::GetStyle();
+    const ImVec4 titleBackground = style.Colors[ImGuiCol_ChildBg];
+    ImGui::PushStyleColor(ImGuiCol_TitleBg, titleBackground);
+    ImGui::PushStyleColor(ImGuiCol_TitleBgActive, titleBackground);
+    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
+                        ImVec2{style.FramePadding.x, scaling::pixels(8.0F)});
+    ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, style.WindowBorderSize);
     const bool visible = ImGui::Begin(id, &open, kWindowFlags);
     ImGui::PopStyleVar(2);
-    ImGui::PopStyleColor();
+    ImGui::PopStyleColor(2);
     return visible;
 }