feat(statusbar): transparency-display toggle (TPY pill)
Add a transparency_enable uniform read by the wire shader: when the new TPY pill is off, every line is forced opaque; when on, baked entity transparency shows through. Toggling is a uniform write, no retessellate (same mechanism as the lineweight-display toggle). Pill is toggleable from the status-bar customization menu. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
28ec360255
commit
66f7d24bc9
9 changed files with 48 additions and 3 deletions
|
|
@ -750,6 +750,8 @@ pub enum Message {
|
||||||
ToggleStatusPill(crate::ui::statusbar_config::StatusPill),
|
ToggleStatusPill(crate::ui::statusbar_config::StatusPill),
|
||||||
/// Toggle clean-screen mode (hide ribbon + side panels).
|
/// Toggle clean-screen mode (hide ribbon + side panels).
|
||||||
ToggleCleanScreen,
|
ToggleCleanScreen,
|
||||||
|
/// Toggle whether entity transparency is shown on screen.
|
||||||
|
ToggleTransparencyDisplay,
|
||||||
/// Toggle the drawing-units picker open/closed.
|
/// Toggle the drawing-units picker open/closed.
|
||||||
ToggleUnitsPopup,
|
ToggleUnitsPopup,
|
||||||
/// Close the drawing-units picker.
|
/// Close the drawing-units picker.
|
||||||
|
|
|
||||||
|
|
@ -3582,6 +3582,14 @@ impl OpenCADStudio {
|
||||||
self.clean_screen ^= true;
|
self.clean_screen ^= true;
|
||||||
Task::none()
|
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 => {
|
Message::ToggleUnitsPopup => {
|
||||||
self.units_popup_open ^= true;
|
self.units_popup_open ^= true;
|
||||||
Task::none()
|
Task::none()
|
||||||
|
|
|
||||||
|
|
@ -1162,6 +1162,7 @@ impl OpenCADStudio {
|
||||||
tab.scene.document.header.insertion_units,
|
tab.scene.document.header.insertion_units,
|
||||||
self.units_popup_open,
|
self.units_popup_open,
|
||||||
tab.scene.is_isolation_active(),
|
tab.scene.is_isolation_active(),
|
||||||
|
tab.scene.transparency_display,
|
||||||
&self.statusbar_config,
|
&self.statusbar_config,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -553,6 +553,9 @@ pub struct Scene {
|
||||||
/// `tessellate_block`'s visibility test skips these, so they neither
|
/// `tessellate_block`'s visibility test skips these, so they neither
|
||||||
/// render nor hit-test until isolation ends.
|
/// render nor hit-test until isolation ends.
|
||||||
pub hidden: HashSet<Handle>,
|
pub hidden: HashSet<Handle>,
|
||||||
|
/// 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).
|
/// In-progress preview wires while a command is active (rubber-band + object ghosts).
|
||||||
pub preview_wires: Vec<WireModel>,
|
pub preview_wires: Vec<WireModel>,
|
||||||
/// Committed-segment wire drawn during multi-point commands (normal colour).
|
/// Committed-segment wire drawn during multi-point commands (normal colour).
|
||||||
|
|
@ -698,6 +701,7 @@ impl Scene {
|
||||||
document: CadDocument::new(),
|
document: CadDocument::new(),
|
||||||
selected: HashSet::new(),
|
selected: HashSet::new(),
|
||||||
hidden: HashSet::new(),
|
hidden: HashSet::new(),
|
||||||
|
transparency_display: true,
|
||||||
preview_wires: vec![],
|
preview_wires: vec![],
|
||||||
interim_wire: None,
|
interim_wire: None,
|
||||||
camera_generation: 0,
|
camera_generation: 0,
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,13 @@ pub struct Uniforms {
|
||||||
/// triangle gets a uniform shade (FlatShaded mode); 0.0 → keeps the
|
/// triangle gets a uniform shade (FlatShaded mode); 0.0 → keeps the
|
||||||
/// per-vertex normal interpolation (GouraudShaded-style).
|
/// per-vertex normal interpolation (GouraudShaded-style).
|
||||||
pub flat_shade: f32,
|
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
|
/// Pads the struct to 112 B (next multiple of 16) so wgpu's uniform
|
||||||
/// alignment rules are satisfied.
|
/// alignment rules are satisfied.
|
||||||
pub _pad: [f32; 3],
|
pub _pad: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Uniforms {
|
impl Uniforms {
|
||||||
|
|
@ -39,7 +43,8 @@ impl Uniforms {
|
||||||
world_per_pixel,
|
world_per_pixel,
|
||||||
lwdisplay_enable: if lwdisplay_enable { 1.0 } else { 0.0 },
|
lwdisplay_enable: if lwdisplay_enable { 1.0 } else { 0.0 },
|
||||||
flat_shade: 0.0,
|
flat_shade: 0.0,
|
||||||
_pad: [0.0; 3],
|
transparency_enable: 1.0,
|
||||||
|
_pad: [0.0; 2],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -636,6 +636,7 @@ impl Scene {
|
||||||
uniforms.view_proj = crop_view_proj(uniforms.view_proj, uo, vo, us, vs);
|
uniforms.view_proj = crop_view_proj(uniforms.view_proj, uo, vo, us, vs);
|
||||||
uniforms.viewport_size = [visible_w, visible_h];
|
uniforms.viewport_size = [visible_w, visible_h];
|
||||||
uniforms.flat_shade = if flags.flat_shade { 1.0 } else { 0.0 };
|
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
|
// `screen_rect` carries the *visible* sub-rectangle in normalized
|
||||||
// canvas coords — that's what `Pipeline::prepare` uses to size
|
// canvas coords — that's what `Pipeline::prepare` uses to size
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ struct Uniforms {
|
||||||
// per-instance baked half_width. Lets the LWT button switch without
|
// per-instance baked half_width. Lets the LWT button switch without
|
||||||
// retessellating.
|
// retessellating.
|
||||||
lwdisplay_enable: f32,
|
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<uniform> u: Uniforms;
|
@group(0) @binding(0) var<uniform> u: Uniforms;
|
||||||
|
|
||||||
|
|
@ -156,5 +162,7 @@ fn in_dash(dist: f32, pat_len: f32, p0: vec4<f32>, p1: vec4<f32>) -> 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<f32>(in.color.rgb, alpha);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ impl StatusBar {
|
||||||
units_popup_open: bool,
|
units_popup_open: bool,
|
||||||
// True when objects are hidden by Isolate / Hide.
|
// True when objects are hidden by Isolate / Hide.
|
||||||
isolation_active: bool,
|
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.
|
// Which pills the user has chosen to show on the bar.
|
||||||
config: &'a StatusBarConfig,
|
config: &'a StatusBarConfig,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
|
|
@ -175,6 +177,16 @@ impl StatusBar {
|
||||||
"Drawing Units (INSUNITS)\nClick to change",
|
"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) {
|
if vis(StatusPill::Isolate) {
|
||||||
right_status = right_status.push(tip(
|
right_status = right_status.push(tip(
|
||||||
toggle_pill("ISO", isolation_active, Message::ToggleIsolatePopup),
|
toggle_pill("ISO", isolation_active, Message::ToggleIsolatePopup),
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ pub enum StatusPill {
|
||||||
Space,
|
Space,
|
||||||
Scale,
|
Scale,
|
||||||
Units,
|
Units,
|
||||||
|
Transparency,
|
||||||
Isolate,
|
Isolate,
|
||||||
Vp,
|
Vp,
|
||||||
CleanScreen,
|
CleanScreen,
|
||||||
|
|
@ -44,6 +45,7 @@ impl StatusPill {
|
||||||
StatusPill::Space,
|
StatusPill::Space,
|
||||||
StatusPill::Scale,
|
StatusPill::Scale,
|
||||||
StatusPill::Units,
|
StatusPill::Units,
|
||||||
|
StatusPill::Transparency,
|
||||||
StatusPill::Isolate,
|
StatusPill::Isolate,
|
||||||
StatusPill::Vp,
|
StatusPill::Vp,
|
||||||
StatusPill::CleanScreen,
|
StatusPill::CleanScreen,
|
||||||
|
|
@ -64,6 +66,7 @@ impl StatusPill {
|
||||||
StatusPill::Space => "space",
|
StatusPill::Space => "space",
|
||||||
StatusPill::Scale => "scale",
|
StatusPill::Scale => "scale",
|
||||||
StatusPill::Units => "units",
|
StatusPill::Units => "units",
|
||||||
|
StatusPill::Transparency => "transparency",
|
||||||
StatusPill::Isolate => "isolate",
|
StatusPill::Isolate => "isolate",
|
||||||
StatusPill::Vp => "vp",
|
StatusPill::Vp => "vp",
|
||||||
StatusPill::CleanScreen => "cleanscreen",
|
StatusPill::CleanScreen => "cleanscreen",
|
||||||
|
|
@ -85,6 +88,7 @@ impl StatusPill {
|
||||||
StatusPill::Space => "Model/Paper Space",
|
StatusPill::Space => "Model/Paper Space",
|
||||||
StatusPill::Scale => "Annotation Scale",
|
StatusPill::Scale => "Annotation Scale",
|
||||||
StatusPill::Units => "Drawing Units",
|
StatusPill::Units => "Drawing Units",
|
||||||
|
StatusPill::Transparency => "Show Transparency",
|
||||||
StatusPill::Isolate => "Isolate Objects",
|
StatusPill::Isolate => "Isolate Objects",
|
||||||
StatusPill::Vp => "Viewport Count",
|
StatusPill::Vp => "Viewport Count",
|
||||||
StatusPill::CleanScreen => "Clean Screen",
|
StatusPill::CleanScreen => "Clean Screen",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue