refactor(viewport): migrate model-space tiling to iced pane_grid

Replace the custom model_tiles tiling with iced 0.14 pane_grid as the layout
source of truth, while paper-space floating viewports are left untouched (they
overlap/free-place, which pane_grid cannot model).

Each Model pane is its own shader widget rendering its camera into the pane
bounds; the renderer Primitive carries a base_slot so several shader widgets
share the type-keyed MultiPipeline storage on disjoint slots. A second pane_grid
of transparent mouse_areas (plus on_resize) layers above the crosshair overlay
to receive input — the overlay's Hidden cursor interaction otherwise levitates
the cursor and starves any layer beneath it. The active pane follows the cursor
(hover-activate), and grid / crosshair / UCS icon render per pane while the
ViewCube and render-mode picker stay on the active pane only.

Split / close / VPORTS presets and the VPort table round-trip now drive
pane_grid (guillotine reconstruction on load). Adds drag-to-swap via a controls
bar handle with a ghost-card preview, visible pane dividers from the pane_grid
split regions, a default model background of RGB(33,40,48), and removes all the
superseded custom-tile code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-27 11:50:11 +03:00
commit 495b13ec4f
18 changed files with 1004 additions and 733 deletions

View file

@ -2165,8 +2165,11 @@ pub struct MultiPipeline {
}
impl MultiPipeline {
/// Ensure exactly `n` (≥1) inner pipelines exist, creating any missing
/// ones. Extra pipelines beyond `n` are dropped.
/// Ensure at least `n` (≥1) inner pipelines exist, creating any missing
/// ones. Grow-only: extra pipelines are NOT dropped, because per-pane Model
/// shader widgets share this storage and each only touches its own slot —
/// truncating mid-frame would destroy another pane's slot. Stale inners (a
/// closed pane, or fewer paper viewports) are harmless idle GPU resources.
pub(crate) fn ensure_len(
&mut self,
device: &wgpu::Device,
@ -2177,7 +2180,6 @@ impl MultiPipeline {
while self.inners.len() < n {
self.inners.push(Pipeline::new(device, queue, self.format));
}
self.inners.truncate(n);
}
}