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:
parent
206ad1a4aa
commit
ac4126072c
3 changed files with 38 additions and 36 deletions
|
|
@ -248,15 +248,14 @@ impl OpenCADStudio {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
let tab = &self.tabs[i];
|
let tab = &self.tabs[i];
|
||||||
let is_paper = tab.scene.current_layout != "Model";
|
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
|
// Surrounding chrome (tab bar, status bar) stays; the welcome widget
|
||||||
// returned here also flags the rest of `view` to skip drawing-only
|
// returned here also flags the rest of `view` to skip drawing-only
|
||||||
// overlays via `tab.is_start`.
|
// overlays via `tab.is_start`.
|
||||||
// Unified GPU widget for both layouts. In a paper layout the
|
// Unified GPU widget for both layouts. A paper layout renders through
|
||||||
// PaperCanvas (2-D sheet + paper entities + viewport borders) is
|
// the same shader as model space: a full-canvas top-locked "sheet"
|
||||||
// layered underneath this shader so the area outside floating
|
// viewport draws the layout's own geometry (white sheet + entities +
|
||||||
// viewports shows the sheet; the shader only blits inside each
|
// borders) and the floating content viewports blit on top.
|
||||||
// content viewport's scissor rect.
|
|
||||||
let viewport_3d: Element<'_, Message> = if tab.is_start {
|
let viewport_3d: Element<'_, Message> = if tab.is_start {
|
||||||
start_page_view()
|
start_page_view()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -576,7 +575,7 @@ impl OpenCADStudio {
|
||||||
// Active paper-space viewport overlays: a render-mode picker in
|
// Active paper-space viewport overlays: a render-mode picker in
|
||||||
// its top-left corner and a ViewCube hit area in its top-right,
|
// its top-left corner and a ViewCube hit area in its top-right,
|
||||||
// both layered ABOVE the viewport mouse_area so they receive
|
// 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.
|
// leading Spaces sized to the viewport's screen rectangle.
|
||||||
let active_vp_rect: Option<iced::Rectangle> = if is_paper && !tab.is_start {
|
let active_vp_rect: Option<iced::Rectangle> = if is_paper && !tab.is_start {
|
||||||
tab.scene.active_viewport.and_then(|h| {
|
tab.scene.active_viewport.and_then(|h| {
|
||||||
|
|
|
||||||
|
|
@ -600,11 +600,11 @@ pub struct Scene {
|
||||||
/// Maps vp_handle → (geometry_epoch, Arc<Vec<WireModel>>).
|
/// Maps vp_handle → (geometry_epoch, Arc<Vec<WireModel>>).
|
||||||
viewport_wire_cache: RefCell<HashMap<Handle, ((u64, u32), 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.).
|
/// 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
|
/// Keyed by `(geometry_epoch, camera_generation)` — paper view changes
|
||||||
/// on zoom too, so culled wire output depends on camera.
|
/// on zoom too, so culled wire output depends on camera.
|
||||||
paper_sheet_cache: RefCell<Option<((u64, u64), Arc<Vec<WireModel>>)>>,
|
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.
|
/// Stores projected + clipped wires in paper-space coordinates.
|
||||||
/// Maps vp_handle → (geometry_epoch, Vec<WireModel>).
|
/// Maps vp_handle → (geometry_epoch, Vec<WireModel>).
|
||||||
paper_projected_cache: RefCell<HashMap<Handle, (u64, 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]> {
|
pub(super) fn view_world_aabb(&self) -> Option<[f32; 4]> {
|
||||||
if self.current_layout != "Model" {
|
if self.current_layout != "Model" {
|
||||||
// Paper-space viewport composition handles its own culling; the
|
// 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;
|
return None;
|
||||||
}
|
}
|
||||||
// Until the first explicit camera move (typically `fit_all()` after
|
// 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
|
/// World units per screen pixel at the current viewport size. Returns
|
||||||
/// `None` until the first render captures real bounds.
|
/// `None` until the first render captures real bounds.
|
||||||
///
|
///
|
||||||
/// Also returns `None` in paper space: `set_render_pixel_scale` is only
|
/// Also returns `None` in paper space: `last_world_per_pixel` tracks the
|
||||||
/// fed by the shader pipeline (`build_primitive`), and the paper layout
|
/// model camera, so a cached value applied to mm-sheet entity AABBs would
|
||||||
/// renders through `PaperCanvas` (an Iced 2-D canvas) which never touches
|
/// be a stale model-world wpp and cull every paper-space annotation.
|
||||||
/// it. Whatever value is cached would be a stale model-world wpp and,
|
/// Matches the same skip already in `view_world_aabb`.
|
||||||
/// applied to mm-sheet entity AABBs, would cull every paper-space
|
|
||||||
/// annotation. Matches the same skip already in `view_world_aabb`.
|
|
||||||
pub(super) fn world_per_pixel(&self) -> Option<f32> {
|
pub(super) fn world_per_pixel(&self) -> Option<f32> {
|
||||||
if self.current_layout != "Model" {
|
if self.current_layout != "Model" {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -1438,9 +1436,8 @@ impl Scene {
|
||||||
arc
|
arc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cached tessellation of the current layout block's paper-space entities.
|
/// Cached tessellation of the current layout block's paper-space entities,
|
||||||
/// Shared by both `entity_wires_arc()` and `paper_canvas_wires()` so a single
|
/// shared by `entity_wires_arc()` and the GPU sheet viewport.
|
||||||
/// cache miss triggers only one tessellation pass, not two.
|
|
||||||
fn paper_sheet_wires_arc(&self) -> Arc<Vec<WireModel>> {
|
fn paper_sheet_wires_arc(&self) -> Arc<Vec<WireModel>> {
|
||||||
let key = (self.geometry_epoch, self.camera_generation);
|
let key = (self.geometry_epoch, self.camera_generation);
|
||||||
{
|
{
|
||||||
|
|
@ -1452,7 +1449,15 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let layout_block = self.current_layout_block_handle();
|
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)));
|
*self.paper_sheet_cache.borrow_mut() = Some((key, Arc::clone(&arc)));
|
||||||
arc
|
arc
|
||||||
}
|
}
|
||||||
|
|
@ -5784,11 +5789,11 @@ impl Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a paper-space Viewport entity's position/size into a pixel
|
/// 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
|
/// Uses the same top-down ortho transform as the GPU sheet viewport so the
|
||||||
/// that the overlay lands exactly over the drawn viewport border regardless
|
/// overlay lands exactly over the drawn viewport border regardless of zoom
|
||||||
/// of zoom or pan level.
|
/// or pan level.
|
||||||
pub fn viewport_screen_rect(
|
pub fn viewport_screen_rect(
|
||||||
&self,
|
&self,
|
||||||
vp_handle: Handle,
|
vp_handle: Handle,
|
||||||
|
|
@ -5812,7 +5817,7 @@ impl Scene {
|
||||||
let ty = cam.target.y;
|
let ty = cam.target.y;
|
||||||
drop(cam);
|
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 to_px = |wx: f32, wy: f32| -> (f32, f32) {
|
||||||
let x = (wx - tx + half_w) / (2.0 * half_w) * canvas_w;
|
let x = (wx - tx + half_w) / (2.0 * half_w) * canvas_w;
|
||||||
let y = (ty + half_h - wy) / (2.0 * half_h) * canvas_h;
|
let y = (ty + half_h - wy) / (2.0 * half_h) * canvas_h;
|
||||||
|
|
@ -5840,7 +5845,8 @@ impl Scene {
|
||||||
|
|
||||||
// ── Paper-space helpers ───────────────────────────────────────────────
|
// ── 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
|
/// content viewports already draw model-block hatches inside their
|
||||||
/// own scissor; including those here would also draw them on the
|
/// own scissor; including those here would also draw them on the
|
||||||
/// paper sheet through the paper camera (huge / off-position), so
|
/// paper sheet through the paper camera (huge / off-position), so
|
||||||
|
|
@ -5886,7 +5892,7 @@ impl Scene {
|
||||||
Arc::new(models)
|
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
|
/// `paper_canvas_hatches` — only include wipeouts owned by the
|
||||||
/// active paper layout block, so model wipeouts (drawn through their
|
/// active paper layout block, so model wipeouts (drawn through their
|
||||||
/// content viewport's GPU pipeline) don't get a second mis-projected
|
/// 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.
|
/// Build a Camera oriented and scaled to match a paper-space Viewport entity.
|
||||||
/// Used by `ViewportPane::Paper` to render model-space content through the
|
/// Used by `active_viewports` to render model-space content through each
|
||||||
/// viewport's own view direction and scale.
|
/// content viewport's own view direction and scale.
|
||||||
fn camera_for_viewport(&self, vp_handle: Handle) -> Option<camera::Camera> {
|
fn camera_for_viewport(&self, vp_handle: Handle) -> Option<camera::Camera> {
|
||||||
let vp = match self.document.get_entity(vp_handle) {
|
let vp = match self.document.get_entity(vp_handle) {
|
||||||
Some(EntityType::Viewport(vp)) => vp,
|
Some(EntityType::Viewport(vp)) => vp,
|
||||||
|
|
|
||||||
|
|
@ -535,18 +535,15 @@ impl Scene {
|
||||||
let canvas = (bounds.width.max(1.0), bounds.height.max(1.0));
|
let canvas = (bounds.width.max(1.0), bounds.height.max(1.0));
|
||||||
let instances = self.active_viewports(canvas.0, canvas.1, model_render_mode);
|
let instances = self.active_viewports(canvas.0, canvas.1, model_render_mode);
|
||||||
// Transparent clear — outside drawn geometry the resolve texture
|
// Transparent clear — outside drawn geometry the resolve texture
|
||||||
// stays at alpha=0, so the alpha-blended blit reveals whatever the
|
// stays at alpha=0, so the alpha-blended blit reveals the container
|
||||||
// underlying widget painted (model layout: container bg; paper
|
// background (model bg, or the desk colour in a paper layout).
|
||||||
// layout: PaperCanvas sheet — including inside content viewport
|
|
||||||
// rectangles).
|
|
||||||
let bg_color = [0.0, 0.0, 0.0, 0.0];
|
let bg_color = [0.0, 0.0, 0.0, 0.0];
|
||||||
let viewports: Vec<ViewportData> = instances
|
let viewports: Vec<ViewportData> = instances
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|inst| self.viewport_data_for(inst, canvas, hover_region))
|
.filter_map(|inst| self.viewport_data_for(inst, canvas, hover_region))
|
||||||
.collect();
|
.collect();
|
||||||
// Empty viewports → blit nothing. The widget container's
|
// Empty viewports → blit nothing; the container background (model bg
|
||||||
// background (model bg or the PaperCanvas widget below) stays
|
// or the paper desk colour) stays visible.
|
||||||
// visible. This happens in paper layouts without content viewports.
|
|
||||||
Primitive { viewports, bg_color }
|
Primitive { viewports, bg_color }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue