diff --git a/src/app/mod.rs b/src/app/mod.rs index da282cadf..5ad05e5fa 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -750,6 +750,8 @@ pub enum Message { ToggleStatusPill(crate::ui::statusbar_config::StatusPill), /// Toggle clean-screen mode (hide ribbon + side panels). ToggleCleanScreen, + /// Toggle whether entity transparency is shown on screen. + ToggleTransparencyDisplay, /// Toggle the drawing-units picker open/closed. ToggleUnitsPopup, /// Close the drawing-units picker. diff --git a/src/app/update.rs b/src/app/update.rs index ec040d416..2ca28a942 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -3582,6 +3582,14 @@ impl OpenCADStudio { self.clean_screen ^= true; Task::none() } + Message::ToggleTransparencyDisplay => { + let i = self.active_tab; + if i < self.tabs.len() { + // No retessellate — the wire shader reads the flag from uniforms. + self.tabs[i].scene.transparency_display ^= true; + } + Task::none() + } Message::ToggleUnitsPopup => { self.units_popup_open ^= true; Task::none() diff --git a/src/app/view.rs b/src/app/view.rs index f5d7c372c..6e75b9e71 100644 --- a/src/app/view.rs +++ b/src/app/view.rs @@ -1162,6 +1162,7 @@ impl OpenCADStudio { tab.scene.document.header.insertion_units, self.units_popup_open, tab.scene.is_isolation_active(), + tab.scene.transparency_display, &self.statusbar_config, ) }) diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 2eda19745..0060082bd 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -553,6 +553,9 @@ pub struct Scene { /// `tessellate_block`'s visibility test skips these, so they neither /// render nor hit-test until isolation ends. pub hidden: HashSet, + /// Whether entity transparency is honoured on screen. When false the + /// wire shader forces every line opaque (a uniform toggle, no retessellate). + pub transparency_display: bool, /// In-progress preview wires while a command is active (rubber-band + object ghosts). pub preview_wires: Vec, /// Committed-segment wire drawn during multi-point commands (normal colour). @@ -698,6 +701,7 @@ impl Scene { document: CadDocument::new(), selected: HashSet::new(), hidden: HashSet::new(), + transparency_display: true, preview_wires: vec![], interim_wire: None, camera_generation: 0, diff --git a/src/scene/pipeline/uniforms.rs b/src/scene/pipeline/uniforms.rs index fa19c67d0..248c09cde 100644 --- a/src/scene/pipeline/uniforms.rs +++ b/src/scene/pipeline/uniforms.rs @@ -19,9 +19,13 @@ pub struct Uniforms { /// triangle gets a uniform shade (FlatShaded mode); 0.0 → keeps the /// per-vertex normal interpolation (GouraudShaded-style). pub flat_shade: f32, + /// Transparency-display toggle (1.0 = honour entity transparency, + /// 0.0 = force opaque). Read by the wire shader so the toggle does not + /// require a retessellate. + pub transparency_enable: f32, /// Pads the struct to 112 B (next multiple of 16) so wgpu's uniform /// alignment rules are satisfied. - pub _pad: [f32; 3], + pub _pad: [f32; 2], } impl Uniforms { @@ -39,7 +43,8 @@ impl Uniforms { world_per_pixel, lwdisplay_enable: if lwdisplay_enable { 1.0 } else { 0.0 }, flat_shade: 0.0, - _pad: [0.0; 3], + transparency_enable: 1.0, + _pad: [0.0; 2], } } } diff --git a/src/scene/render.rs b/src/scene/render.rs index e31bcd3c9..ce2f99003 100644 --- a/src/scene/render.rs +++ b/src/scene/render.rs @@ -636,6 +636,7 @@ impl Scene { uniforms.view_proj = crop_view_proj(uniforms.view_proj, uo, vo, us, vs); uniforms.viewport_size = [visible_w, visible_h]; uniforms.flat_shade = if flags.flat_shade { 1.0 } else { 0.0 }; + uniforms.transparency_enable = if self.transparency_display { 1.0 } else { 0.0 }; // `screen_rect` carries the *visible* sub-rectangle in normalized // canvas coords — that's what `Pipeline::prepare` uses to size diff --git a/src/shaders/wire.wgsl b/src/shaders/wire.wgsl index 112292b9e..50273a455 100644 --- a/src/shaders/wire.wgsl +++ b/src/shaders/wire.wgsl @@ -22,6 +22,12 @@ struct Uniforms { // per-instance baked half_width. Lets the LWT button switch without // retessellating. lwdisplay_enable: f32, + // Mesh flat-shade flag (unused here; kept so the field offsets match + // the shared Uniforms buffer layout). + flat_shade: f32, + // Transparency-display toggle: 1.0 = honour baked alpha, 0.0 = force + // every line opaque. + transparency_enable: f32, } @group(0) @binding(0) var u: Uniforms; @@ -156,5 +162,7 @@ fn in_dash(dist: f32, pat_len: f32, p0: vec4, p1: vec4) -> bool { } } } - return in.color; + // Transparency display off → force the line opaque. + let alpha = select(1.0, in.color.a, u.transparency_enable > 0.5); + return vec4(in.color.rgb, alpha); } diff --git a/src/ui/statusbar.rs b/src/ui/statusbar.rs index 6051f52ba..ff848fecf 100644 --- a/src/ui/statusbar.rs +++ b/src/ui/statusbar.rs @@ -61,6 +61,8 @@ impl StatusBar { units_popup_open: bool, // True when objects are hidden by Isolate / Hide. isolation_active: bool, + // Whether entity transparency is shown (Transparency pill state). + transparency_display: bool, // Which pills the user has chosen to show on the bar. config: &'a StatusBarConfig, ) -> Element<'a, Message> { @@ -175,6 +177,16 @@ impl StatusBar { "Drawing Units (INSUNITS)\nClick to change", )); } + if vis(StatusPill::Transparency) { + right_status = right_status.push(tip( + toggle_pill( + "TPY", + transparency_display, + Message::ToggleTransparencyDisplay, + ), + "Show Transparency\nForce opaque when off", + )); + } if vis(StatusPill::Isolate) { right_status = right_status.push(tip( toggle_pill("ISO", isolation_active, Message::ToggleIsolatePopup), diff --git a/src/ui/statusbar_config.rs b/src/ui/statusbar_config.rs index f6ba3edc4..d4b97a132 100644 --- a/src/ui/statusbar_config.rs +++ b/src/ui/statusbar_config.rs @@ -23,6 +23,7 @@ pub enum StatusPill { Space, Scale, Units, + Transparency, Isolate, Vp, CleanScreen, @@ -44,6 +45,7 @@ impl StatusPill { StatusPill::Space, StatusPill::Scale, StatusPill::Units, + StatusPill::Transparency, StatusPill::Isolate, StatusPill::Vp, StatusPill::CleanScreen, @@ -64,6 +66,7 @@ impl StatusPill { StatusPill::Space => "space", StatusPill::Scale => "scale", StatusPill::Units => "units", + StatusPill::Transparency => "transparency", StatusPill::Isolate => "isolate", StatusPill::Vp => "vp", StatusPill::CleanScreen => "cleanscreen", @@ -85,6 +88,7 @@ impl StatusPill { StatusPill::Space => "Model/Paper Space", StatusPill::Scale => "Annotation Scale", StatusPill::Units => "Drawing Units", + StatusPill::Transparency => "Show Transparency", StatusPill::Isolate => "Isolate Objects", StatusPill::Vp => "Viewport Count", StatusPill::CleanScreen => "Clean Screen",