forked from 1b-agent/opencadstudio-upstream
feat: render active MSPACE viewport as a true 3D widget in paper space
When a paper-space viewport is activated (double-click / MSPACE command), it is now rendered through its own dedicated PaperViewportPipeline rather than the CPU-projection approach used for inactive viewports. Architecture: - PaperSheet widget (full-canvas): renders paper entities + CPU-projected content of all viewports *except* the active one. - PaperViewportPane widget (Fixed w×h, positioned at viewport screen rect): renders the active viewport with a true 3D camera derived from the viewport's view_direction/view_target/view_height. PaperViewportPipeline is a newtype of Pipeline. Having a distinct type gives it its own Iced storage entry (keyed by TypeId), preventing the shared prepare() overwrite that broke the earlier per-viewport approach. Changes: - render.rs: PaperViewportPipeline, PaperViewportPrimitive newtypes; build_active_viewport_primitive(); build_paper_sheet_primitive() now excludes active_viewport from CPU projection. - viewport_pane.rs: PaperViewportPane<'a> with shader::Program impl. - mod.rs: viewport_content_wires() gains exclude_vp parameter; viewport_screen_rect() is no longer dead code. - view.rs: paper_canvas_view() overlays PaperViewportPane when MSPACE is active. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
d1d4bb3d02
commit
97dbd80c93
4 files changed
+171
-21
No files matched your search
+43
-13
@@ -4,7 +4,7 @@ use super::history::history_dropdown_labels;
|
||||
use super::helpers::grid_plane_from_camera;
|
||||
use crate::scene::{VIEWCUBE_DRAW_PX, VIEWCUBE_PAD};
|
||||
use crate::scene::grip::grips_to_screen;
|
||||
use crate::scene::viewport_pane::ViewportPane;
|
||||
use crate::scene::viewport_pane::{PaperViewportPane, ViewportPane};
|
||||
use crate::ui::overlay;
|
||||
use iced::widget::{button, column, container, mouse_area, row, shader, stack, text, Row, Space};
|
||||
use iced::window;
|
||||
@@ -457,22 +457,52 @@ impl H7CAD {
|
||||
|
||||
// ── Paper canvas ──────────────────────────────────────────────────────────
|
||||
//
|
||||
// Renders the full paper canvas as a single full-size shader widget using the
|
||||
// PaperSheet mode, which includes both paper-space entities (title blocks,
|
||||
// frames, borders) and model-space content projected through each viewport's
|
||||
// view matrix into paper-space coordinates.
|
||||
// PSPACE: single full-canvas PaperSheet widget — renders paper entities plus
|
||||
// model content of all viewports via CPU projection.
|
||||
//
|
||||
// Note: A per-viewport widget approach (ViewportPane::Paper) was attempted but
|
||||
// does not work correctly because Iced 0.14 batches all shader prepare() calls
|
||||
// before any render() calls, causing widgets that share the same Pipeline type
|
||||
// to overwrite each other's GPU buffers. The CPU-projection approach used here
|
||||
// is the correct solution within Iced's shader framework.
|
||||
// MSPACE (active viewport): PaperSheet widget (excludes the active viewport
|
||||
// from its CPU projection) + a PaperViewportPane widget overlaid at the
|
||||
// active viewport's screen-space position. PaperViewportPane uses a
|
||||
// distinct pipeline type (PaperViewportPipeline) so Iced's per-type storage
|
||||
// keeps the two prepare() calls from overwriting each other.
|
||||
|
||||
fn paper_canvas_view<'a>(tab: &'a super::document::DocumentTab) -> Element<'a, Message> {
|
||||
shader(ViewportPane::paper_sheet(&tab.scene))
|
||||
let scene = &tab.scene;
|
||||
|
||||
let paper_sheet = shader(ViewportPane::paper_sheet(scene))
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.into()
|
||||
.height(Fill);
|
||||
|
||||
if let Some(vp_handle) = scene.active_viewport {
|
||||
let (canvas_w, canvas_h) = scene.selection.borrow().vp_size;
|
||||
if let Some(rect) = scene.viewport_screen_rect(vp_handle, (canvas_w, canvas_h)) {
|
||||
let w = rect.width.max(1.0);
|
||||
let h = rect.height.max(1.0);
|
||||
let x = rect.x.max(0.0);
|
||||
let y = rect.y.max(0.0);
|
||||
|
||||
let vp_widget = shader(PaperViewportPane::new(scene, vp_handle))
|
||||
.width(iced::Length::Fixed(w))
|
||||
.height(iced::Length::Fixed(h));
|
||||
|
||||
let positioned = column![
|
||||
Space::new().height(iced::Length::Fixed(y)),
|
||||
row![
|
||||
Space::new().width(iced::Length::Fixed(x)),
|
||||
vp_widget,
|
||||
],
|
||||
]
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
|
||||
return stack![paper_sheet, positioned]
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
paper_sheet.into()
|
||||
}
|
||||
|
||||
// ── Document tab bar ───────────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user