forked from 1b-agent/opencadstudio-upstream
fix(paper): give the sheet back its desk and its edge
A paper layout painted its whole canvas in the page colour, so the sheet had no visible edge — zooming out never reached one, because the surround was the same colour as the page. Floating viewports then painted themselves black over it. Both come from the same idea, that a viewport's canvas is a colour it can be handed. What lies behind a viewport depends on what the viewport is: - The full-canvas sheet shows the desk. `paper_bg_color` is the page, and the page is a bounded rectangle `paper_sheet_fill` already draws; using it for the canvas too erased the boundary between them. The desk is now its own colour, defined once in the scene and read by both the widget and the renderer, so the two cannot drift apart. - A floating viewport sits on that sheet and must paint no canvas at all. Handing it a transparent one does not work: the background shader returns an opaque colour whatever alpha it is given, so alpha zero came out black. Skipping the pass is the only way to ask for see-through, so `skip_background` now suppresses both the clear and the pass. It is part of the frame signature too — without that, a cached frame would keep showing the canvas the flag was just turned off for. Shading and fog still blend toward what is behind a floating viewport, which is the page, so the uniform keeps that colour even though nothing paints it. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
6cbec232bb
commit
62dfbfe2be
4 files changed
+45
-9
No files matched your search
+6
-4
@@ -34,11 +34,13 @@ use viewcube::{viewcube_nav_controls, viewcube_ucs_picker, UCS_PICKER_W};
|
||||
pub(in crate::app) use overlay::{MTEXT_TEXT_ID, TEXT_INLINE_ID};
|
||||
|
||||
const VIEWCUBE_HIT_SIZE: f32 = VIEWCUBE_REGION_PX;
|
||||
/// The desk shown around the sheet, as the widget wants it. One definition,
|
||||
/// shared with the renderer that clears the sheet viewport to the same thing.
|
||||
const PAPER_SPACE_BACKGROUND: Color = Color {
|
||||
r: 138.0 / 255.0,
|
||||
g: 138.0 / 255.0,
|
||||
b: 138.0 / 255.0,
|
||||
a: 1.0,
|
||||
r: crate::scene::PAPER_DESK_COLOR[0],
|
||||
g: crate::scene::PAPER_DESK_COLOR[1],
|
||||
b: crate::scene::PAPER_DESK_COLOR[2],
|
||||
a: crate::scene::PAPER_DESK_COLOR[3],
|
||||
};
|
||||
|
||||
/// Base surface directly under the crosshair. Paper content viewports render
|
||||
|
||||
@@ -285,6 +285,12 @@ struct GeometryDelta {
|
||||
full: bool,
|
||||
}
|
||||
|
||||
/// The desk a paper layout lays its sheet on — the surface visible around the
|
||||
/// page. Distinct from both the page (`paper_bg_color`) and the model canvas
|
||||
/// (`bg_color`); if the desk took either of those colours the page edge would
|
||||
/// vanish into its own surround.
|
||||
pub const PAPER_DESK_COLOR: [f32; 4] = [138.0 / 255.0, 138.0 / 255.0, 138.0 / 255.0, 1.0];
|
||||
|
||||
const CACHE_CATEGORY_ANNOTATIVE: u16 = 1 << 0;
|
||||
const CACHE_CATEGORY_HATCH: u16 = 1 << 1;
|
||||
const CACHE_CATEGORY_WIPEOUT: u16 = 1 << 2;
|
||||
|
||||
@@ -340,6 +340,9 @@ pub struct Pipeline {
|
||||
/// `render` skips the (per-pixel, GPU-dominating) hatch pass this frame. The
|
||||
/// scene-render cache holds the full-quality frame once the view settles.
|
||||
pub skip_hatch_frame: bool,
|
||||
/// Skip the canvas entirely — no clear colour, no background pass — so
|
||||
/// whatever was drawn underneath this viewport shows through it.
|
||||
pub skip_background: bool,
|
||||
/// Stable identity of the viewport that last used this (index-addressed)
|
||||
/// pipeline slot. The renderer's viewport list drops off-canvas viewports,
|
||||
/// so a slot can be reused by a *different* viewport across frames; when the
|
||||
@@ -2015,6 +2018,7 @@ impl Pipeline {
|
||||
render_sig: u64::MAX,
|
||||
skip_geometry: false,
|
||||
skip_hatch_frame: false,
|
||||
skip_background: false,
|
||||
slot_id: u64::MAX,
|
||||
}
|
||||
}
|
||||
@@ -3282,7 +3286,7 @@ impl Pipeline {
|
||||
};
|
||||
let msaa = &self.msaa_view;
|
||||
let [r, g, b, a] = bg_color;
|
||||
let clear_color = if self.clip_boundary.is_some() {
|
||||
let clear_color = if self.clip_boundary.is_some() || self.skip_background {
|
||||
wgpu::Color::TRANSPARENT
|
||||
} else {
|
||||
wgpu::Color {
|
||||
@@ -3393,10 +3397,15 @@ impl Pipeline {
|
||||
pass.set_vertex_buffer(0, vbuf.slice(..));
|
||||
pass.draw(0..*vcount, 0..1);
|
||||
}
|
||||
pass.set_pipeline(&self.background_pipeline);
|
||||
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||
pass.set_stencil_reference(stencil_ref);
|
||||
pass.draw(0..3, 0..1);
|
||||
// The background shader returns an opaque colour whatever alpha it
|
||||
// is handed, so a see-through viewport cannot be asked for as a
|
||||
// transparent background — the pass has to not run.
|
||||
if !self.skip_background {
|
||||
pass.set_pipeline(&self.background_pipeline);
|
||||
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||
pass.set_stencil_reference(stencil_ref);
|
||||
pass.draw(0..3, 0..1);
|
||||
}
|
||||
// The capability-selected façade dispatches storage or texture
|
||||
// draws before wires so outlines remain on top in either backend.
|
||||
// Skipped while navigating because per-pixel hatch work dominates
|
||||
|
||||
@@ -202,6 +202,10 @@ pub struct ViewportData {
|
||||
/// into the render signature so the settle frame re-renders hatches once and
|
||||
/// the scene-render cache holds it. See [`Scene::navigating_lod`].
|
||||
pub(in crate::scene) skip_hatch: bool,
|
||||
/// True when this viewport must not paint a canvas of its own. A floating
|
||||
/// viewport on a paper layout sits ON the sheet: anything it painted first
|
||||
/// would cover the page it is supposed to be a window in.
|
||||
pub(in crate::scene) skip_background: bool,
|
||||
pub(in crate::scene) geometry_epoch: u64,
|
||||
/// Camera generation captured when this Primitive was assembled. Paired
|
||||
/// with `geometry_epoch` so the per-frame scissor / LOD recompute runs.
|
||||
@@ -434,6 +438,7 @@ impl shader::Primitive for Primitive {
|
||||
inner.skip_geometry = skip;
|
||||
// Interaction LOD: skip the hatch draw this frame while navigating.
|
||||
inner.skip_hatch_frame = vp.skip_hatch;
|
||||
inner.skip_background = vp.skip_background;
|
||||
if skip {
|
||||
if vp.show_viewcube {
|
||||
inner.viewcube.upload(
|
||||
@@ -1250,6 +1255,7 @@ fn render_signature(vp: &ViewportData, clip_w: u32, clip_h: u32) -> u64 {
|
||||
// Interaction-LOD hatch suppression: differs the signature so the settle
|
||||
// frame (skip_hatch flips false) re-renders with hatches and re-caches.
|
||||
vp.skip_hatch.hash(&mut h);
|
||||
vp.skip_background.hash(&mut h);
|
||||
clip_w.hash(&mut h);
|
||||
clip_h.hash(&mut h);
|
||||
// Live overlay (command preview / interim / grip drag). Small — a handful
|
||||
@@ -1912,7 +1918,19 @@ impl Scene {
|
||||
&self,
|
||||
viewport: &ViewportInstance,
|
||||
) -> ViewportDisplaySettings {
|
||||
// What lies behind a viewport depends on what the viewport is. The
|
||||
// full-canvas paper sheet shows the desk, and the page is drawn on top
|
||||
// of it by `paper_sheet_fill` — give the desk the page's own colour and
|
||||
// the edge disappears into a same-coloured surround that no amount of
|
||||
// zooming out reveals. A floating viewport sits ON that sheet, so it
|
||||
// paints no canvas at all; anything else would erase the page beneath
|
||||
// it. Only model space clears to the editor background.
|
||||
let canvas_background = if viewport.paper_sheet {
|
||||
crate::scene::PAPER_DESK_COLOR
|
||||
} else if self.current_layout != "Model" {
|
||||
// This viewport paints no canvas of its own (`skip_background`),
|
||||
// but shading and fog still blend toward whatever is behind it —
|
||||
// and behind a floating viewport is the page.
|
||||
self.paper_bg_color
|
||||
} else {
|
||||
self.bg_color
|
||||
@@ -3594,6 +3612,7 @@ impl Scene {
|
||||
// (hatched) frame once it settles. Only applied to the on-screen
|
||||
// Model / paper content — the paper *sheet* keeps its fills.
|
||||
skip_hatch: self.hatch_lod_enabled() && !inst.paper_sheet && self.navigating_lod(),
|
||||
skip_background: !inst.paper_sheet && self.current_layout != "Model",
|
||||
geometry_epoch: self.geometry_epoch,
|
||||
camera_generation: self.camera_generation,
|
||||
wire_content_id,
|
||||
|
||||
Reference in new issue
Block a user