forked from 1b-agent/opencadstudio-upstream
refactor(paper): drop sheet viewport border + clean stale PaperCanvas docs
The overall "sheet" viewport now IS the paper view, so its own border rectangle must not be drawn as an entity — filter it out of paper_sheet_wires_arc (content viewport borders are kept). Also update the doc comments that still referenced the removed PaperCanvas widget / paper_canvas_wires to describe the GPU sheet path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
206ad1a4aa
commit
ac4126072c
3 files changed
+38
-36
No files matched your search
+6
-7
@@ -248,15 +248,14 @@ impl OpenCADStudio {
|
||||
let i = self.active_tab;
|
||||
let tab = &self.tabs[i];
|
||||
let is_paper = tab.scene.current_layout != "Model";
|
||||
// Start tab: render welcome page in place of the model/paper canvas.
|
||||
// Start tab: render welcome page in place of the viewport.
|
||||
// Surrounding chrome (tab bar, status bar) stays; the welcome widget
|
||||
// returned here also flags the rest of `view` to skip drawing-only
|
||||
// overlays via `tab.is_start`.
|
||||
// Unified GPU widget for both layouts. In a paper layout the
|
||||
// PaperCanvas (2-D sheet + paper entities + viewport borders) is
|
||||
// layered underneath this shader so the area outside floating
|
||||
// viewports shows the sheet; the shader only blits inside each
|
||||
// content viewport's scissor rect.
|
||||
// Unified GPU widget for both layouts. A paper layout renders through
|
||||
// the same shader as model space: a full-canvas top-locked "sheet"
|
||||
// viewport draws the layout's own geometry (white sheet + entities +
|
||||
// borders) and the floating content viewports blit on top.
|
||||
let viewport_3d: Element<'_, Message> = if tab.is_start {
|
||||
start_page_view()
|
||||
} else {
|
||||
@@ -576,7 +575,7 @@ impl OpenCADStudio {
|
||||
// Active paper-space viewport overlays: a render-mode picker in
|
||||
// its top-left corner and a ViewCube hit area in its top-right,
|
||||
// both layered ABOVE the viewport mouse_area so they receive
|
||||
// clicks (the paper canvas itself sits below it). Positioned with
|
||||
// clicks (the shader viewport sits below it). Positioned with
|
||||
// leading Spaces sized to the viewport's screen rectangle.
|
||||
let active_vp_rect: Option<iced::Rectangle> = if is_paper && !tab.is_start {
|
||||
tab.scene.active_viewport.and_then(|h| {
|
||||
|
||||
+28
-22
@@ -600,11 +600,11 @@ pub struct Scene {
|
||||
/// Maps vp_handle → (geometry_epoch, Arc<Vec<WireModel>>).
|
||||
viewport_wire_cache: RefCell<HashMap<Handle, ((u64, u32), Arc<Vec<WireModel>>)>>,
|
||||
/// Cached tessellation of paper-space layout block entities (title block, annotations, etc.).
|
||||
/// Separate from `wire_cache` so paper_canvas_wires() doesn't re-tessellate on every frame.
|
||||
/// Separate from `wire_cache` so the GPU sheet viewport doesn't re-tessellate every frame.
|
||||
/// Keyed by `(geometry_epoch, camera_generation)` — paper view changes
|
||||
/// on zoom too, so culled wire output depends on camera.
|
||||
paper_sheet_cache: RefCell<Option<((u64, u64), Arc<Vec<WireModel>>)>>,
|
||||
/// Per-viewport projected wire cache for the paper canvas (2-D Iced widget).
|
||||
/// Per-viewport projected wire cache for paper-space content viewports.
|
||||
/// Stores projected + clipped wires in paper-space coordinates.
|
||||
/// Maps vp_handle → (geometry_epoch, Vec<WireModel>).
|
||||
paper_projected_cache: RefCell<HashMap<Handle, (u64, Vec<WireModel>)>>,
|
||||
@@ -732,7 +732,7 @@ impl Scene {
|
||||
pub(super) fn view_world_aabb(&self) -> Option<[f32; 4]> {
|
||||
if self.current_layout != "Model" {
|
||||
// Paper-space viewport composition handles its own culling; the
|
||||
// top-level paper canvas is small enough not to need it.
|
||||
// top-level paper view is small enough not to need it.
|
||||
return None;
|
||||
}
|
||||
// Until the first explicit camera move (typically `fit_all()` after
|
||||
@@ -771,12 +771,10 @@ impl Scene {
|
||||
/// World units per screen pixel at the current viewport size. Returns
|
||||
/// `None` until the first render captures real bounds.
|
||||
///
|
||||
/// Also returns `None` in paper space: `set_render_pixel_scale` is only
|
||||
/// fed by the shader pipeline (`build_primitive`), and the paper layout
|
||||
/// renders through `PaperCanvas` (an Iced 2-D canvas) which never touches
|
||||
/// it. Whatever value is cached would be a stale model-world wpp and,
|
||||
/// applied to mm-sheet entity AABBs, would cull every paper-space
|
||||
/// annotation. Matches the same skip already in `view_world_aabb`.
|
||||
/// Also returns `None` in paper space: `last_world_per_pixel` tracks the
|
||||
/// model camera, so a cached value applied to mm-sheet entity AABBs would
|
||||
/// be a stale model-world wpp and cull every paper-space annotation.
|
||||
/// Matches the same skip already in `view_world_aabb`.
|
||||
pub(super) fn world_per_pixel(&self) -> Option<f32> {
|
||||
if self.current_layout != "Model" {
|
||||
return None;
|
||||
@@ -1438,9 +1436,8 @@ impl Scene {
|
||||
arc
|
||||
}
|
||||
|
||||
/// Cached tessellation of the current layout block's paper-space entities.
|
||||
/// Shared by both `entity_wires_arc()` and `paper_canvas_wires()` so a single
|
||||
/// cache miss triggers only one tessellation pass, not two.
|
||||
/// Cached tessellation of the current layout block's paper-space entities,
|
||||
/// shared by `entity_wires_arc()` and the GPU sheet viewport.
|
||||
fn paper_sheet_wires_arc(&self) -> Arc<Vec<WireModel>> {
|
||||
let key = (self.geometry_epoch, self.camera_generation);
|
||||
{
|
||||
@@ -1452,7 +1449,15 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let arc = Arc::new(self.wires_for_block(layout_block));
|
||||
let mut wires = self.wires_for_block(layout_block);
|
||||
// The overall "sheet" viewport now IS the paper view itself, so its own
|
||||
// border rectangle must not be drawn as an entity on the sheet.
|
||||
let sheet = self.current_layout_sheet_viewport_handle();
|
||||
if sheet.is_valid() {
|
||||
let sheet_name = sheet.value().to_string();
|
||||
wires.retain(|w| w.name != sheet_name);
|
||||
}
|
||||
let arc = Arc::new(wires);
|
||||
*self.paper_sheet_cache.borrow_mut() = Some((key, Arc::clone(&arc)));
|
||||
arc
|
||||
}
|
||||
@@ -5784,11 +5789,11 @@ impl Scene {
|
||||
}
|
||||
|
||||
/// Convert a paper-space Viewport entity's position/size into a pixel
|
||||
/// `Rectangle` relative to the top-left of the paper canvas.
|
||||
/// `Rectangle` relative to the top-left of the canvas.
|
||||
///
|
||||
/// Uses the same camera-based ortho transform as `PaperCanvas::draw()` so
|
||||
/// that the overlay lands exactly over the drawn viewport border regardless
|
||||
/// of zoom or pan level.
|
||||
/// Uses the same top-down ortho transform as the GPU sheet viewport so the
|
||||
/// overlay lands exactly over the drawn viewport border regardless of zoom
|
||||
/// or pan level.
|
||||
pub fn viewport_screen_rect(
|
||||
&self,
|
||||
vp_handle: Handle,
|
||||
@@ -5812,7 +5817,7 @@ impl Scene {
|
||||
let ty = cam.target.y;
|
||||
drop(cam);
|
||||
|
||||
// Mirror the to_px closure in PaperCanvas::draw().
|
||||
// Top-down ortho mapping matching the GPU sheet viewport's camera.
|
||||
let to_px = |wx: f32, wy: f32| -> (f32, f32) {
|
||||
let x = (wx - tx + half_w) / (2.0 * half_w) * canvas_w;
|
||||
let y = (ty + half_h - wy) / (2.0 * half_h) * canvas_h;
|
||||
@@ -5840,7 +5845,8 @@ impl Scene {
|
||||
|
||||
// ── Paper-space helpers ───────────────────────────────────────────────
|
||||
|
||||
/// Hatch fills for the paper-space 2-D canvas. The GPU-rendered
|
||||
/// Paper-layout hatch fills, restricted to the active layout block (used by
|
||||
/// paper-space hatch hit-testing / export). The GPU-rendered
|
||||
/// content viewports already draw model-block hatches inside their
|
||||
/// own scissor; including those here would also draw them on the
|
||||
/// paper sheet through the paper camera (huge / off-position), so
|
||||
@@ -5886,7 +5892,7 @@ impl Scene {
|
||||
Arc::new(models)
|
||||
}
|
||||
|
||||
/// Wipeout fills for the paper-space 2-D canvas. Same rationale as
|
||||
/// Paper-layout wipeout fills (paper hit-testing / export). Same rationale as
|
||||
/// `paper_canvas_hatches` — only include wipeouts owned by the
|
||||
/// active paper layout block, so model wipeouts (drawn through their
|
||||
/// content viewport's GPU pipeline) don't get a second mis-projected
|
||||
@@ -5940,8 +5946,8 @@ impl Scene {
|
||||
}
|
||||
|
||||
/// Build a Camera oriented and scaled to match a paper-space Viewport entity.
|
||||
/// Used by `ViewportPane::Paper` to render model-space content through the
|
||||
/// viewport's own view direction and scale.
|
||||
/// Used by `active_viewports` to render model-space content through each
|
||||
/// content viewport's own view direction and scale.
|
||||
fn camera_for_viewport(&self, vp_handle: Handle) -> Option<camera::Camera> {
|
||||
let vp = match self.document.get_entity(vp_handle) {
|
||||
Some(EntityType::Viewport(vp)) => vp,
|
||||
|
||||
+4
-7
@@ -535,18 +535,15 @@ impl Scene {
|
||||
let canvas = (bounds.width.max(1.0), bounds.height.max(1.0));
|
||||
let instances = self.active_viewports(canvas.0, canvas.1, model_render_mode);
|
||||
// Transparent clear — outside drawn geometry the resolve texture
|
||||
// stays at alpha=0, so the alpha-blended blit reveals whatever the
|
||||
// underlying widget painted (model layout: container bg; paper
|
||||
// layout: PaperCanvas sheet — including inside content viewport
|
||||
// rectangles).
|
||||
// stays at alpha=0, so the alpha-blended blit reveals the container
|
||||
// background (model bg, or the desk colour in a paper layout).
|
||||
let bg_color = [0.0, 0.0, 0.0, 0.0];
|
||||
let viewports: Vec<ViewportData> = instances
|
||||
.iter()
|
||||
.filter_map(|inst| self.viewport_data_for(inst, canvas, hover_region))
|
||||
.collect();
|
||||
// Empty viewports → blit nothing. The widget container's
|
||||
// background (model bg or the PaperCanvas widget below) stays
|
||||
// visible. This happens in paper layouts without content viewports.
|
||||
// Empty viewports → blit nothing; the container background (model bg
|
||||
// or the paper desk colour) stays visible.
|
||||
Primitive { viewports, bg_color }
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user