aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-21 20:55:02 +0200
committerhachem <im@hachem.wtf>2026-09-21 20:55:02 +0200
commit270eda6f558c972ec86ad0580f1d3d18afc83a94 (patch)
tree5944a95bf052ed264372b2eb29c76d2be97e395f /docs
parent908db452c4268f367e49b027b7e91fc60f5e0a86 (diff)
feat: update ui
Diffstat (limited to 'docs')
-rw-r--r--docs/README.md2
-rw-r--r--docs/architecture.md63
2 files changed, 40 insertions, 25 deletions
diff --git a/docs/README.md b/docs/README.md
index 3ab9570..a10d307 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -16,7 +16,7 @@ go into how it actually works.
layering (application / scene / renderpath / uilayer), the portable rhi that lets
the same rendering run on opengl and vulkan, the frame loop, the unified
scene-and-simulation world, the rendering pipeline (progressive resolution,
- supersampling, environment lighting, tone-mapping), the docking ui, the export
+ supersampling, environment lighting, tone-mapping), the workspace tabs and docking ui, the export
pipeline, and the build system.
for each pixel, donut casts a ray from the camera and follows it backward through
diff --git a/docs/architecture.md b/docs/architecture.md
index 0868775..98f2b6f 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -48,7 +48,7 @@ flowchart TD
| --- | --- | --- |
| `Application` | [`src/core/application.cpp`](../src/core/application.cpp) | owns everything; runs the main loop; handles input, resize, vsync, fullscreen; exposes actions to the ui |
| `Scene` | [`src/scene/scene.h`](../src/scene/scene.h) | the world as plain data — placed objects, black-hole/disk parameters, the editor and simulation cameras, the hdri path |
-| `UILayer` | [`src/ui/ui_layer.cpp`](../src/ui/ui_layer.cpp) | the docking shell: menu bar, dockable panels, default layouts; returns which view is live and drives the scene through `AppActions` |
+| `UILayer` | [`src/ui/ui_layer.cpp`](../src/ui/ui_layer.cpp) | the docking shell: menu bar, workspace tabs, dockable panels with a layout per workspace; returns which view is live and drives the scene through `AppActions` |
| `RenderPath` | [`src/rendering/render_path.cpp`](../src/rendering/render_path.cpp) | turns the scene into pixels on whatever device is active; owns the two renderers and the environment cubemap |
| `RHI::Device` | [`src/rendering/rhi.h`](../src/rendering/rhi.h) | the portable gpu interface every backend implements |
@@ -219,14 +219,30 @@ fragment shader averages four sub-pixel samples in a rotated-grid ("4-rook") pat
before tone-mapping, which cleans up the near-horizontal lensed edges and the thin
photon ring.
-## the workspace: docking and panels
+## workspaces: tabs, docking and panels
-the interface is a docking shell. a main menu bar sits above a full-viewport dock
-space with a pass-through centre, so the live 3d render shows through the middle
-while dockable tool panels attach to the edges — drag, tab, hide, or restore them
-like a normal desktop app. the layout persists in `imgui.ini` between runs.
+the interface is a docking shell with three workspaces along the top —
+**simulation**, **scene editor** and **export** — each a tab with its own
+independent layout, the way blender's workspace tabs work. a main menu bar sits
+above the tab strip; below it is a full-viewport dock space with a pass-through
+centre, so the live 3d render shows through the middle while the workspace's tool
+panels attach to the edges — drag, tab, hide, or restore them like a normal
+desktop app. rearranging one workspace never touches the others, and all three
+layouts, the open workspace and each one's panel set persist in `imgui.ini`
+between runs.
-the panels are separate windows, each toggled from the **window** menu:
+each workspace fixes what the centre viewport shows — the `View` that
+`UILayer::draw` returns to the `RenderPath` — and has its own set of panels. the
+sphere panels are available in the black-hole workspaces too, since the lensed
+render draws the spheres, though the gizmo itself only works in the scene editor:
+
+| workspace | view | panels (open by default in bold) |
+| --- | --- | --- |
+| simulation | `BlackHole` — the lensed black hole | **black hole**, **diagnostics**, settings, outliner, properties |
+| scene editor | `Scene` — the world editor | **outliner**, **properties**, **diagnostics**, settings |
+| export | `BlackHole` | **export**, **black hole**, **diagnostics**, settings, outliner, properties |
+
+the panels themselves:
| panel | for |
| --- | --- |
@@ -235,26 +251,25 @@ the panels are separate windows, each toggled from the **window** menu:
| black hole | camera mode/fov, the accretion disk, and integration quality |
| settings | display & renderer: vsync, frame cap, resolution, fullscreen, ui scale, api, overlay, hdri |
| export | choose which observable channels, at what resolution and format, then render to disk |
-| stats | device, backend, fps and frame time |
+| diagnostics | device, backend, fps and a frame-time graph |
-two menus drive the rest. **view** picks what the centre viewport shows — `Scene`
-(the world editor) or `Simulation` (the lensed black hole) — which is the `View`
-`UILayer::draw` returns to the `RenderPath`. **layout** applies one of the default
-arrangements, each built programmatically with imgui's `DockBuilder` api and paired
-with a sensible view and panel set:
-
-| layout | view | panels shown |
-| --- | --- | --- |
-| simulation (default) | `Simulation` | black hole, stats |
-| scene editing | `Scene` | outliner, properties, stats |
-| export | `Simulation` | export, black hole, stats |
+the **workspace** menu (or cmd/ctrl + 1/2/3) switches tabs, the **window** menu
+toggles the open workspace's panels, and **layout → reset** rebuilds the open
+workspace's default arrangement, or all three.
-on first launch (no saved `imgui.ini`) the simulation layout is built by
-`DockBuilder`; after that the user's arrangement is restored, and *layout → reset*
-rebuilds the current preset. only panels are docked windows — the centre stays a
+underneath, each workspace is its own imgui dock space with a fixed id. only the
+open one is submitted for real each frame; the other two get a keep-alive ping,
+which freezes their trees in place instead of tearing them down — nothing is laid
+out or undocked while a workspace is off screen. an imgui window can only live in
+one dock tree, so every panel is instanced once per workspace under a stable
+`###workspace.panel` id (the same code draws all of them), which is also what lets
+imgui save and restore each tree on its own. a workspace with no saved tree is
+seeded on the first frame with the `DockBuilder` api. imgui doesn't remember which
+workspace was open or which panels were showing, so a small `[Donut][Workspaces]`
+section in `imgui.ini` does. only panels are docked windows — the centre stays a
pass-through hole onto the full-frame 3d render, so `Application::update_input`
-drives the camera whenever the cursor is over that centre (imgui reports it doesn't
-want the mouse) and yields to the panels otherwise.
+drives the camera whenever the cursor is over that centre (imgui reports it
+doesn't want the mouse) and yields to the panels otherwise.
## the export pipeline