## Why Multi-viewport support is a standard feature in DCC tools (Maya, Houdini, Blender) that lets users view the same scene from different camera angles simultaneously. Currently the app has a single `ViewportPanel` — users cannot compare views (e.g., free camera + a USD camera prim, or top/orthographic + perspective) without switching back and forth. This limits scene inspection, layout work, and side-by-side comparison during shading and lighting iteration. ## What Changes - Introduce a **viewport layout system** that manages 1–4 viewport tiles within a single ImGui window area - Each tile has its own `ViewportCamera`, `UsdSceneRenderer`, selection highlight set, and per-viewport settings (grid, AA, background color, bounding box mode) - Selection is **shared** across all viewports (pick in any viewport, all viewports highlight) - The main `ViewportPanel` becomes a **container** that holds N child viewports (N=1 default, up to 4) - **Layout presets**: single, 2-split horizontal/vertical, 4-quadrant - Per-viewport camera toolbar remains (camera selector, render delegate, view options) but is **compact** (icon-only) to conserve space - The manipulator gizmo is only active in the **focused** viewport (the one that last received a click) - **Space-key maximize**: pressing Space while hovering over a tile temporarily maximizes that tile to fill the entire viewport area, hiding dividers and other tiles. Pressing Space again restores the previous multi-tile layout (identical to Maya's viewport maximize behavior) - **BREAKING**: `Application`'s `m_viewportPanel` member type changes (it remains `ViewportPanel` but `ViewportPanel` switches from a single renderer to a container) ## Capabilities ### New Capabilities - `viewport-layout`: Layout management — splitting, merging, preset switching, drag-resize dividers, Space-key maximize/restore, persistence of layout choice - `per-viewport-camera`: Each tile has an independent `ViewportCamera`, camera selector dropdown, and free/USD camera switching - `per-viewport-settings`: Per-tile grid toggle, AA, background color, bounding box mode, render delegate selection (independent per viewport) - `shared-selection`: Single selection model across all viewports — picking in any tile updates all others and propagates to SceneHierarchyPanel / PropertyPanel - `focused-viewport-manipulator`: Transform gizmo only renders and accepts input in the most recently clicked viewport tile ### Modified Capabilities - *(None — `imgui-docking` is purely an ImGui infrastructure change; the new viewport system builds on top of it and does not alter its spec)* ## Impact - **`src/ui/ViewportPanel.h/.cpp`**: Rewritten from a single-viewport class to a container that owns N `ViewportTile` instances. Public API surface changes — `SetSelectedPrimPath`, `SetStage`, `GetCamera`, `GetRenderer` remain but are forwarded to the active/focused tile or broadcast to all tiles. - **`src/core/UsdSceneRenderer.h/.cpp`**: No changes needed (each tile owns its own `UsdSceneRenderer` already). - **`src/core/ViewportCamera.h/.cpp`**: No changes needed (each tile owns its own `ViewportCamera` already). - **`src/ui/Application.h/.cpp`**: Wire up `OnPrimPicked` / `OnPrimsPickedRect` as before on the container; the container relays selection to the `SceneHierarchyPanel` / `PropertyPanel`. - **New files**: `src/ui/ViewportTile.h/.cpp` — the per-tile rendering logic extracted from `ViewportPanel::Render()`. - **New files**: `src/ui/ViewportLayout.h/.cpp` — layout splitting/merge logic, divider drag, layout persistence. - Memory: N `UsdSceneRenderer` instances means N FBO draw targets. For N≤4 and typical 1080p viewports this is ~200 MB worst-case — acceptable for a DCC tool.