Rebalance overlay layout and fix the layout-on-launch overlap

Feedback from real use: the center column was far too wide and Injection/Log too
narrow; Audio was too tall while Controllers/Video were too short; and the layout
overlapped on launch until "Reset layout" was pressed.

- Columns are now proportional: Injection (left) and Log (right) take 36% each of the
  usable width, the center control column 28% -- so the wide panels are wide and the
  control panels narrow.
- The center stack heights are evened out (Controllers 30% / Video 38% / Audio 32% of
  the column), so Audio no longer hogs it.
- The default layout is now forced (ImGuiCond_Always) for the first few frames after
  launch, because the viewport WorkSize isn't trustworthy on frame 0 -- FirstUseEver
  was locking in those wrong (overlapping) positions until a manual Reset layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 10:41:58 +02:00
parent 784c31a9b5
commit 1493ce08e5

View File

@@ -13,6 +13,10 @@ namespace
// Set by "View -> Reset layout"; true for the one frame in which panels re-apply // Set by "View -> Reset layout"; true for the one frame in which panels re-apply
// their default position/size, then cleared by apply_layout_end_frame(). // their default position/size, then cleared by apply_layout_end_frame().
bool g_layout_reset = false; bool g_layout_reset = false;
// Force the computed layout for the first few frames after launch: the viewport
// WorkSize isn't trustworthy on frame 0, and FirstUseEver would otherwise lock in
// those wrong positions (overlapping) until the user pressed Reset layout.
int g_startup_force = 4;
} // namespace } // namespace
void request_layout_reset() void request_layout_reset()
@@ -23,6 +27,10 @@ void request_layout_reset()
void apply_layout_end_frame() void apply_layout_end_frame()
{ {
g_layout_reset = false; g_layout_reset = false;
if (g_startup_force > 0)
{
--g_startup_force;
}
} }
void apply_panel_layout(Panel panel) void apply_panel_layout(Panel panel)
@@ -33,43 +41,52 @@ void apply_panel_layout(Panel panel)
const float m = 12.0f; // outer margin const float m = 12.0f; // outer margin
const float gap = 10.0f; // between panels const float gap = 10.0f; // between panels
const float left_w = 440.0f; // Injection (window list + hook diagnostics) // Three columns: Injection (left) and Log (right) are the wide ones (window list
const float right_w = 380.0f; // Log // titles / log lines); the center control-panel column is the narrow one.
const float center_x = o.x + m + left_w + gap; const float usable_w = std::max(600.0f, s.x - 2.0f * m - 2.0f * gap);
const float right_x = o.x + s.x - right_w - m; const float left_w = usable_w * 0.36f;
const float center_w = std::max(360.0f, right_x - gap - center_x); const float center_w = usable_w * 0.28f;
const float right_w = usable_w * 0.36f;
const float left_x = o.x + m;
const float center_x = left_x + left_w + gap;
const float right_x = center_x + center_w + gap;
const float top = o.y + m;
const float full_h = std::max(200.0f, s.y - 2.0f * m); const float full_h = std::max(200.0f, s.y - 2.0f * m);
const float ctrl_h = 210.0f; // Controllers
const float vid_h = 250.0f; // Video mirror // Center column stacks Controllers / Video / Audio at roughly even heights (Video
const float audio_y = o.y + m + ctrl_h + gap + vid_h + gap; // a touch taller for its graphs), so Audio no longer hogs the column.
const float bottom = o.y + m + full_h; const float stack_avail = std::max(150.0f, full_h - 2.0f * gap);
const float ctrl_h = stack_avail * 0.30f;
const float vid_h = stack_avail * 0.38f;
const float audio_h = stack_avail * 0.32f;
ImVec2 pos, size; ImVec2 pos, size;
switch (panel) switch (panel)
{ {
case Panel::Injection: case Panel::Injection:
pos = ImVec2(o.x + m, o.y + m); pos = ImVec2(left_x, top);
size = ImVec2(left_w, full_h); size = ImVec2(left_w, full_h);
break; break;
case Panel::Controllers: case Panel::Controllers:
pos = ImVec2(center_x, o.y + m); pos = ImVec2(center_x, top);
size = ImVec2(center_w, ctrl_h); size = ImVec2(center_w, ctrl_h);
break; break;
case Panel::Video: case Panel::Video:
pos = ImVec2(center_x, o.y + m + ctrl_h + gap); pos = ImVec2(center_x, top + ctrl_h + gap);
size = ImVec2(center_w, vid_h); size = ImVec2(center_w, vid_h);
break; break;
case Panel::Audio: case Panel::Audio:
pos = ImVec2(center_x, audio_y); pos = ImVec2(center_x, top + ctrl_h + gap + vid_h + gap);
size = ImVec2(center_w, std::max(180.0f, bottom - audio_y)); size = ImVec2(center_w, audio_h);
break; break;
case Panel::Log: case Panel::Log:
pos = ImVec2(right_x, o.y + m); pos = ImVec2(right_x, top);
size = ImVec2(right_w, full_h); size = ImVec2(right_w, full_h);
break; break;
} }
const ImGuiCond cond = g_layout_reset ? ImGuiCond_Always : ImGuiCond_FirstUseEver; const ImGuiCond cond = (g_layout_reset || g_startup_force > 0) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
ImGui::SetNextWindowPos(pos, cond); ImGui::SetNextWindowPos(pos, cond);
ImGui::SetNextWindowSize(size, cond); ImGui::SetNextWindowSize(size, cond);
} }