forked from 1b-agent/opencadstudio-upstream
feat(display): add model lineweight scale
This commit is contained in:
1 parent
edbc4d8ff8
commit
76bdab1e5b
11 files changed
+66
-19
No files matched your search
@@ -492,6 +492,8 @@ pub(super) struct OpenCADStudio {
|
|||||||
crosshair_color: Option<[u8; 3]>,
|
crosshair_color: Option<[u8; 3]>,
|
||||||
/// Editable Options buffer for the crosshair colour.
|
/// Editable Options buffer for the crosshair colour.
|
||||||
crosshair_color_input: String,
|
crosshair_color_input: String,
|
||||||
|
/// Model-space lineweight preview scale, in percent (25..=200).
|
||||||
|
lineweight_display_scale: i32,
|
||||||
/// Isometric drafting state and active axis pair.
|
/// Isometric drafting state and active axis pair.
|
||||||
isometric_drafting: bool,
|
isometric_drafting: bool,
|
||||||
iso_plane: settings::IsoPlane,
|
iso_plane: settings::IsoPlane,
|
||||||
@@ -1910,6 +1912,8 @@ pub enum Message {
|
|||||||
PickBoxChanged(i32),
|
PickBoxChanged(i32),
|
||||||
/// Set CURSORTYPE from Options.
|
/// Set CURSORTYPE from Options.
|
||||||
CursorTypeChanged(settings::CursorType),
|
CursorTypeChanged(settings::CursorType),
|
||||||
|
/// Set the model-space lineweight preview scale from Options.
|
||||||
|
LineweightDisplayScaleChanged(i32),
|
||||||
/// Edit the optional crosshair RGB value; blank restores automatic contrast.
|
/// Edit the optional crosshair RGB value; blank restores automatic contrast.
|
||||||
CrosshairColorChanged(String),
|
CrosshairColorChanged(String),
|
||||||
/// Set the default type/version used when first saving a new drawing.
|
/// Set the default type/version used when first saving a new drawing.
|
||||||
@@ -3280,6 +3284,7 @@ impl OpenCADStudio {
|
|||||||
cursor_type: settings::CursorType::Crosshair,
|
cursor_type: settings::CursorType::Crosshair,
|
||||||
crosshair_color: None,
|
crosshair_color: None,
|
||||||
crosshair_color_input: String::new(),
|
crosshair_color_input: String::new(),
|
||||||
|
lineweight_display_scale: 100,
|
||||||
isometric_drafting: false,
|
isometric_drafting: false,
|
||||||
iso_plane: settings::IsoPlane::Left,
|
iso_plane: settings::IsoPlane::Left,
|
||||||
snap_angle_deg: 0.0,
|
snap_angle_deg: 0.0,
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ pub struct UserSettings {
|
|||||||
pub cursor_type: CursorType,
|
pub cursor_type: CursorType,
|
||||||
/// Explicit crosshair RGB. `None` keeps automatic background contrast.
|
/// Explicit crosshair RGB. `None` keeps automatic background contrast.
|
||||||
pub crosshair_color: Option<[u8; 3]>,
|
pub crosshair_color: Option<[u8; 3]>,
|
||||||
|
/// Model-space lineweight preview scale as a percentage.
|
||||||
|
pub lineweight_display_scale: i32,
|
||||||
/// Isometric drafting changes the grid and crosshair to the active axis pair.
|
/// Isometric drafting changes the grid and crosshair to the active axis pair.
|
||||||
pub isometric_drafting: bool,
|
pub isometric_drafting: bool,
|
||||||
pub iso_plane: IsoPlane,
|
pub iso_plane: IsoPlane,
|
||||||
@@ -282,6 +284,7 @@ impl Default for UserSettings {
|
|||||||
pick_box: 3,
|
pick_box: 3,
|
||||||
cursor_type: CursorType::Crosshair,
|
cursor_type: CursorType::Crosshair,
|
||||||
crosshair_color: None,
|
crosshair_color: None,
|
||||||
|
lineweight_display_scale: 100,
|
||||||
isometric_drafting: false,
|
isometric_drafting: false,
|
||||||
iso_plane: IsoPlane::Left,
|
iso_plane: IsoPlane::Left,
|
||||||
snap_angle_deg: 0.0,
|
snap_angle_deg: 0.0,
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
|||||||
self.tab_counter += 1;
|
self.tab_counter += 1;
|
||||||
self.tabs[0] = crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
self.tabs[0] = crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
||||||
self.active_tab = 0;
|
self.active_tab = 0;
|
||||||
self.apply_bg_default(0);
|
self.apply_display_defaults(0);
|
||||||
} else {
|
} else {
|
||||||
self.tabs.remove(idx);
|
self.tabs.remove(idx);
|
||||||
if self.active_tab >= self.tabs.len() {
|
if self.active_tab >= self.tabs.len() {
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
|||||||
self.tabs[0] =
|
self.tabs[0] =
|
||||||
crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
||||||
self.active_tab = 0;
|
self.active_tab = 0;
|
||||||
self.apply_bg_default(0);
|
self.apply_display_defaults(0);
|
||||||
} else {
|
} else {
|
||||||
self.tabs.remove(idx);
|
self.tabs.remove(idx);
|
||||||
if self.active_tab >= self.tabs.len() {
|
if self.active_tab >= self.tabs.len() {
|
||||||
|
|||||||
+13
-13
@@ -364,6 +364,7 @@ impl OpenCADStudio {
|
|||||||
pick_box: self.pick_box,
|
pick_box: self.pick_box,
|
||||||
cursor_type: self.cursor_type,
|
cursor_type: self.cursor_type,
|
||||||
crosshair_color: self.crosshair_color,
|
crosshair_color: self.crosshair_color,
|
||||||
|
lineweight_display_scale: self.lineweight_display_scale,
|
||||||
isometric_drafting: self.isometric_drafting,
|
isometric_drafting: self.isometric_drafting,
|
||||||
iso_plane: self.iso_plane,
|
iso_plane: self.iso_plane,
|
||||||
snap_angle_deg: self.snap_angle_deg,
|
snap_angle_deg: self.snap_angle_deg,
|
||||||
@@ -416,6 +417,7 @@ impl OpenCADStudio {
|
|||||||
.crosshair_color
|
.crosshair_color
|
||||||
.map(crate::app::config::rgb_to_hex)
|
.map(crate::app::config::rgb_to_hex)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
self.lineweight_display_scale = s.lineweight_display_scale.clamp(25, 200);
|
||||||
self.isometric_drafting = s.isometric_drafting;
|
self.isometric_drafting = s.isometric_drafting;
|
||||||
self.iso_plane = s.iso_plane;
|
self.iso_plane = s.iso_plane;
|
||||||
self.snap_angle_deg = if s.snap_angle_deg.is_finite() {
|
self.snap_angle_deg = if s.snap_angle_deg.is_finite() {
|
||||||
@@ -469,11 +471,10 @@ impl OpenCADStudio {
|
|||||||
.take(200)
|
.take(200)
|
||||||
.map(|(k, v)| (k.clone(), *v))
|
.map(|(k, v)| (k.clone(), *v))
|
||||||
.collect();
|
.collect();
|
||||||
// Push the restored background onto every drawing tab that exists now
|
// Push restored display defaults onto every drawing tab that exists now.
|
||||||
// (the start tab and any initial drawing). Tabs created later pick it
|
// Tabs created later pick them up at their construction site.
|
||||||
// up via `apply_bg_default` at their construction site.
|
|
||||||
for idx in 0..self.tabs.len() {
|
for idx in 0..self.tabs.len() {
|
||||||
self.apply_bg_default(idx);
|
self.apply_display_defaults(idx);
|
||||||
}
|
}
|
||||||
self.rebuild_ribbon_modules();
|
self.rebuild_ribbon_modules();
|
||||||
}
|
}
|
||||||
@@ -596,19 +597,18 @@ impl OpenCADStudio {
|
|||||||
h.object_snap_mode = osmode;
|
h.object_snap_mode = osmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the persisted default background(s) to tab `idx`. No-op for the
|
/// Apply persisted viewport display defaults to tab `idx`.
|
||||||
/// start tab or when no default is set. Refreshes the tab's cached wires
|
pub(in crate::app) fn apply_display_defaults(&mut self, idx: usize) {
|
||||||
/// and meshes so background-adaptive colours pick up the change.
|
|
||||||
pub(in crate::app) fn apply_bg_default(&mut self, idx: usize) {
|
|
||||||
let bg = self.default_bg_color;
|
let bg = self.default_bg_color;
|
||||||
let paper_bg = self.default_paper_bg_color;
|
let paper_bg = self.default_paper_bg_color;
|
||||||
if bg.is_none() && paper_bg.is_none() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let tab = &mut self.tabs[idx];
|
let tab = &mut self.tabs[idx];
|
||||||
if tab.is_start {
|
if tab.is_start {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
tab.scene.model_lineweight_scale = self.lineweight_display_scale as f32 / 100.0;
|
||||||
|
if bg.is_none() && paper_bg.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if let Some(c) = bg {
|
if let Some(c) = bg {
|
||||||
tab.bg_color = Some(c);
|
tab.bg_color = Some(c);
|
||||||
tab.scene.bg_color = c;
|
tab.scene.bg_color = c;
|
||||||
@@ -1286,7 +1286,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
|
|||||||
self.tabs.push(new_tab);
|
self.tabs.push(new_tab);
|
||||||
let idx = self.tabs.len() - 1;
|
let idx = self.tabs.len() - 1;
|
||||||
self.active_tab = idx;
|
self.active_tab = idx;
|
||||||
self.apply_bg_default(idx);
|
self.apply_display_defaults(idx);
|
||||||
idx
|
idx
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2381,7 +2381,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
|
|||||||
self.tab_counter += 1;
|
self.tab_counter += 1;
|
||||||
self.tabs[i] = crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
self.tabs[i] = crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
||||||
self.active_tab = i;
|
self.active_tab = i;
|
||||||
self.apply_bg_default(i);
|
self.apply_display_defaults(i);
|
||||||
self.update(Message::OpenPathPicked(Some((
|
self.update(Message::OpenPathPicked(Some((
|
||||||
conflict.path,
|
conflict.path,
|
||||||
metadata.len(),
|
metadata.len(),
|
||||||
|
|||||||
+11
-1
@@ -1271,7 +1271,7 @@ impl OpenCADStudio {
|
|||||||
// creating one doesn't silently reset them (its header default is
|
// creating one doesn't silently reset them (its header default is
|
||||||
// 0 = no snaps); saving then persists them into the file.
|
// 0 = no snaps); saving then persists them into the file.
|
||||||
self.stamp_header_sysvars(idx);
|
self.stamp_header_sysvars(idx);
|
||||||
self.apply_bg_default(idx);
|
self.apply_display_defaults(idx);
|
||||||
self.sync_ribbon_layers();
|
self.sync_ribbon_layers();
|
||||||
self.sync_ribbon_styles();
|
self.sync_ribbon_styles();
|
||||||
// #21: reset ribbon Color / Linetype / Lineweight to the
|
// #21: reset ribbon Color / Linetype / Lineweight to the
|
||||||
@@ -5787,6 +5787,16 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::LineweightDisplayScaleChanged(value) => {
|
||||||
|
self.lineweight_display_scale = value.clamp(25, 200);
|
||||||
|
let scale = self.lineweight_display_scale as f32 / 100.0;
|
||||||
|
for tab in &mut self.tabs {
|
||||||
|
tab.scene.model_lineweight_scale = scale;
|
||||||
|
}
|
||||||
|
self.persist_settings_if_changed();
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
|
||||||
Message::CrosshairColorChanged(value) => {
|
Message::CrosshairColorChanged(value) => {
|
||||||
self.crosshair_color_input = value.clone();
|
self.crosshair_color_input = value.clone();
|
||||||
if value.trim().is_empty() {
|
if value.trim().is_empty() {
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ impl OpenCADStudio {
|
|||||||
self.cursor_type,
|
self.cursor_type,
|
||||||
self.crosshair_color,
|
self.crosshair_color,
|
||||||
&self.crosshair_color_input,
|
&self.crosshair_color_input,
|
||||||
|
self.lineweight_display_scale,
|
||||||
flow,
|
flow,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1469,6 +1469,8 @@ pub struct Scene {
|
|||||||
/// Whether entity transparency is honoured on screen. When false the
|
/// Whether entity transparency is honoured on screen. When false the
|
||||||
/// wire shader forces every line opaque (a uniform toggle, no retessellate).
|
/// wire shader forces every line opaque (a uniform toggle, no retessellate).
|
||||||
pub transparency_display: bool,
|
pub transparency_display: bool,
|
||||||
|
/// User-adjustable model-space lineweight preview multiplier.
|
||||||
|
pub model_lineweight_scale: f32,
|
||||||
/// Selection filter: entity-type names excluded from interactive picking.
|
/// Selection filter: entity-type names excluded from interactive picking.
|
||||||
/// Empty = every type is selectable.
|
/// Empty = every type is selectable.
|
||||||
pub selection_filter: HashSet<String>,
|
pub selection_filter: HashSet<String>,
|
||||||
@@ -1878,6 +1880,7 @@ impl Scene {
|
|||||||
refedit_keep: None,
|
refedit_keep: None,
|
||||||
hover_highlight: None,
|
hover_highlight: None,
|
||||||
transparency_display: true,
|
transparency_display: true,
|
||||||
|
model_lineweight_scale: 1.0,
|
||||||
selection_filter: HashSet::default(),
|
selection_filter: HashSet::default(),
|
||||||
preview_wires: vec![],
|
preview_wires: vec![],
|
||||||
preview_hatches: Arc::new(Vec::new()),
|
preview_hatches: Arc::new(Vec::new()),
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ pub struct Uniforms {
|
|||||||
/// zooming inside MSPACE changes one scalar instead of re-tessellating and
|
/// zooming inside MSPACE changes one scalar instead of re-tessellating and
|
||||||
/// re-uploading every dashed wire.
|
/// re-uploading every dashed wire.
|
||||||
pub linetype_scale: f32,
|
pub linetype_scale: f32,
|
||||||
/// Multiplier for screen-space lineweights. Model space keeps `1.0`;
|
/// Multiplier for screen-space lineweights. Model space uses the user's
|
||||||
/// paper layouts derive it from the current paper zoom.
|
/// preview scale; paper layouts derive it from the current paper zoom.
|
||||||
pub lineweight_scale: f32,
|
pub lineweight_scale: f32,
|
||||||
|
|
||||||
// ── Relative-to-eye (double-single) additions ───────────────────────────
|
// ── Relative-to-eye (double-single) additions ───────────────────────────
|
||||||
|
|||||||
@@ -3847,7 +3847,9 @@ impl Scene {
|
|||||||
full_bounds,
|
full_bounds,
|
||||||
self.document.header.lineweight_display || display_plot_lineweights,
|
self.document.header.lineweight_display || display_plot_lineweights,
|
||||||
);
|
);
|
||||||
if self.current_layout != "Model" {
|
if self.current_layout == "Model" {
|
||||||
|
uniforms.lineweight_scale = self.model_lineweight_scale;
|
||||||
|
} else {
|
||||||
let paper_per_pixel = 2.0 * self.camera.borrow().ortho_size() / canvas.1.max(1.0);
|
let paper_per_pixel = 2.0 * self.camera.borrow().ortho_size() / canvas.1.max(1.0);
|
||||||
let paper_units_per_mm = self.paper_space_unit_factor() as f32;
|
let paper_units_per_mm = self.paper_space_unit_factor() as f32;
|
||||||
uniforms.lineweight_scale = paper_units_per_mm / paper_per_pixel / MM_TO_PX;
|
uniforms.lineweight_scale = paper_units_per_mm / paper_per_pixel / MM_TO_PX;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ pub fn view_window<'a>(
|
|||||||
cursor_type: CursorType,
|
cursor_type: CursorType,
|
||||||
crosshair_color: Option<[u8; 3]>,
|
crosshair_color: Option<[u8; 3]>,
|
||||||
crosshair_color_input: &'a str,
|
crosshair_color_input: &'a str,
|
||||||
|
lineweight_display_scale: i32,
|
||||||
sizing: crate::ui::modal::ModalSizing,
|
sizing: crate::ui::modal::ModalSizing,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
let selected_format = crate::io::SAVE_FORMAT_OPTIONS
|
let selected_format = crate::io::SAVE_FORMAT_OPTIONS
|
||||||
@@ -265,6 +266,28 @@ pub fn view_window<'a>(
|
|||||||
text(crate::t!("Leave the color blank to keep automatic viewport contrast."))
|
text(crate::t!("Leave the color blank to keep automatic viewport contrast."))
|
||||||
.size(11)
|
.size(11)
|
||||||
.width(sizing.width),
|
.width(sizing.width),
|
||||||
|
Space::new().height(24),
|
||||||
|
text(crate::t!("Lineweight")).size(15),
|
||||||
|
Space::new().height(10),
|
||||||
|
row![
|
||||||
|
text(crate::t!("Model display scale")).size(12).width(140),
|
||||||
|
slider(
|
||||||
|
25..=200,
|
||||||
|
lineweight_display_scale.clamp(25, 200),
|
||||||
|
Message::LineweightDisplayScaleChanged,
|
||||||
|
)
|
||||||
|
.step(1)
|
||||||
|
.width(Fill),
|
||||||
|
text(format!("{}%", lineweight_display_scale.clamp(25, 200)))
|
||||||
|
.size(11)
|
||||||
|
.width(44),
|
||||||
|
]
|
||||||
|
.spacing(10)
|
||||||
|
.align_y(iced::Center),
|
||||||
|
Space::new().height(6),
|
||||||
|
text(crate::t!("Changes the on-screen width in Model without affecting plotted output."))
|
||||||
|
.size(11)
|
||||||
|
.width(sizing.width),
|
||||||
]
|
]
|
||||||
.spacing(0)
|
.spacing(0)
|
||||||
.width(sizing.width);
|
.width(sizing.width);
|
||||||
|
|||||||
Reference in new issue
Block a user