Support nested splits in the default dock layout #6

Open
opened 2026-09-19 19:37:08 -07:00 by burkkyy · 0 comments
Owner

Summary

DockLayout (engine/include/sophia/ui/dock_layout.hpp) can only describe four fixed regions (left, right, bottom, center), and each region is a single tab group. There is no way to say "split the bottom region into Asset Browser and Console side by side", or to nest further splits inside any region.

Users can already drag panels onto each other at runtime to tab or split them, and imgui.ini persists the result. This issue is only about expressing nested splits in the default layout.

Background

  • ImGuiRenderer::applyLayoutIfNeeded (engine/src/imgui_renderer.cpp) hard-codes three DockBuilderSplitNode calls (left, right, bottom) and docks each region's window list into the resulting node.
  • The default layout is set via panels().setDefaultLayout(...) in the application's onCreate().

Proposal

Replace the four fixed fields with a recursive tree, so a node is either a split or a tab group:

  • Split node: direction (Left/Right/Up/Down), a ratio for the first child, and two children.
  • Tab group (leaf): a list of window names.

Example: bottom = split Right at 0.5 of {Asset Browser} and {Console}.

applyLayoutIfNeeded then walks the tree, calling DockBuilderSplitNode at each split and DockBuilderDockWindow at each leaf.

Acceptance criteria

  • The editor's default layout can put Asset Browser and Console side by side in the bottom region.
  • A layout can nest splits to arbitrary depth.
  • Existing behaviour is unchanged: applied only when no saved layout exists, and restored by reset_layout.
  • The current editor layout is ported to the new API, and the old fixed-region DockLayout fields are removed.

Open questions

  • API shape: designated-initializer structs, or small builder helpers such as split(Dir::Right, 0.5f, a, b) and tabs({...})? Deep trees are awkward to write as nested braces.
  • Ratios: should ratios always refer to the first child of the split, or to whichever side is named?
  • Out of scope: a panel hosting its own embedded dockspace (for example a Viewport containing sub-panels). That needs ImGui::DockSpace() inside a window and separate node ids, so it should be a separate issue if we want it.
  • New panels: panels added to the default layout after a layout is already saved don't dock themselves. That is existing behaviour and unchanged here.
## Summary `DockLayout` (`engine/include/sophia/ui/dock_layout.hpp`) can only describe four fixed regions (left, right, bottom, center), and each region is a single tab group. There is no way to say "split the bottom region into Asset Browser and Console side by side", or to nest further splits inside any region. Users can already drag panels onto each other at runtime to tab or split them, and `imgui.ini` persists the result. This issue is only about expressing nested splits in the *default* layout. ## Background - `ImGuiRenderer::applyLayoutIfNeeded` (`engine/src/imgui_renderer.cpp`) hard-codes three `DockBuilderSplitNode` calls (left, right, bottom) and docks each region's window list into the resulting node. - The default layout is set via `panels().setDefaultLayout(...)` in the application's `onCreate()`. ## Proposal Replace the four fixed fields with a recursive tree, so a node is either a split or a tab group: - **Split node:** direction (`Left`/`Right`/`Up`/`Down`), a ratio for the first child, and two children. - **Tab group (leaf):** a list of window names. Example: bottom = split `Right` at 0.5 of `{Asset Browser}` and `{Console}`. `applyLayoutIfNeeded` then walks the tree, calling `DockBuilderSplitNode` at each split and `DockBuilderDockWindow` at each leaf. ## Acceptance criteria - The editor's default layout can put Asset Browser and Console side by side in the bottom region. - A layout can nest splits to arbitrary depth. - Existing behaviour is unchanged: applied only when no saved layout exists, and restored by `reset_layout`. - The current editor layout is ported to the new API, and the old fixed-region `DockLayout` fields are removed. ## Open questions - **API shape:** designated-initializer structs, or small builder helpers such as `split(Dir::Right, 0.5f, a, b)` and `tabs({...})`? Deep trees are awkward to write as nested braces. - **Ratios:** should ratios always refer to the first child of the split, or to whichever side is named? - **Out of scope:** a panel hosting its own embedded dockspace (for example a Viewport containing sub-panels). That needs `ImGui::DockSpace()` inside a window and separate node ids, so it should be a separate issue if we want it. - **New panels:** panels added to the default layout after a layout is already saved don't dock themselves. That is existing behaviour and unchanged here.
burkkyy added this to the sophia project 2026-09-19 19:39:58 -07:00
burkkyy moved this to Blocked in sophia on 2026-09-25 20:43:20 -07:00
Sign in to join this conversation.