From 2ddf2a31da046ede0959bc471579fc59f1abe78f Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 13 Oct 2026 15:32:55 +0300 Subject: [PATCH] feat(hatch): HPASSOC sets whether new hatches are associative HPASSOC (0 or 1, default 1) is the starting state of the hatch command's associative option. It is an application setting: typed directly or through SETVAR, it persists across sessions and does not mark the drawing modified. Co-Authored-By: Claude Opus 5.5 --- src/app/commands/draw.rs | 3 ++- src/app/commands/styleprops.rs | 13 +++++++++++++ src/app/mod.rs | 3 +++ src/app/settings.rs | 3 +++ src/app/update/file.rs | 2 ++ src/modules/draw/draw/hatch.rs | 6 ++++++ 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/app/commands/draw.rs b/src/app/commands/draw.rs index 004ccf0ff..a59efadb8 100644 --- a/src/app/commands/draw.rs +++ b/src/app/commands/draw.rs @@ -764,7 +764,8 @@ impl OpenCADStudio { }); let new_cmd = HatchCommand::new(outlines, boundary_sources, selected, inherited, plane) - .with_origin(self.tabs[i].scene.document.hatch_origin()); + .with_origin(self.tabs[i].scene.document.hatch_origin()) + .with_associative(self.hatch_associative); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); self.refresh_area_preview(i); diff --git a/src/app/commands/styleprops.rs b/src/app/commands/styleprops.rs index c556efa81..849244d4e 100644 --- a/src/app/commands/styleprops.rs +++ b/src/app/commands/styleprops.rs @@ -1148,6 +1148,7 @@ impl OpenCADStudio { | "SHORTCUTMENUDURATION" | "CURSORSIZE" | "PICKBOX" + | "HPASSOC" | "CURSORTYPE" | "SNAPANG" | "TEXTFILL" @@ -2188,6 +2189,17 @@ impl OpenCADStudio { }, None => Ok((format!("PICKBOX = {}", self.pick_box), false)), }, + "HPASSOC" => match value.as_deref() { + Some(v @ ("0" | "1")) => { + self.hatch_associative = v == "1"; + Ok((format!("HPASSOC = {v}"), true)) + } + Some(_) => Err("SETVAR: 0 or 1 required.".into()), + None => Ok(( + format!("HPASSOC = {}", u8::from(self.hatch_associative)), + false, + )), + }, "CURSORTYPE" => match &value { Some(v) => match v.as_str() { "0" => { @@ -3134,6 +3146,7 @@ impl OpenCADStudio { | "SHORTCUTMENUDURATION" | "CURSORSIZE" | "PICKBOX" + | "HPASSOC" | "CURSORTYPE" | "SNAPANG" | "CLIPROMPTLINES" diff --git a/src/app/mod.rs b/src/app/mod.rs index df546b25a..a22158dc1 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -640,6 +640,8 @@ pub(super) struct OpenCADStudio { cursor_size: i32, /// Selection-box size setting (PICKBOX, 0..=50). pick_box: i32, + /// HPASSOC: new hatches follow their boundary objects. + hatch_associative: bool, /// Use REFEDIT rather than BEDIT when double-clicking an attribute-free block. double_click_block_refedit: bool, /// Open ATTEDIT when double-clicking a block with attributes. @@ -4534,6 +4536,7 @@ impl OpenCADStudio { zoom_factor_input: 60.to_string(), cursor_size: 5, pick_box: 3, + hatch_associative: true, double_click_block_refedit: false, double_click_block_attedit: true, right_click_mode: settings::RightClickMode::ShortcutMenu, diff --git a/src/app/settings.rs b/src/app/settings.rs index 960a2a54c..d1cb7be40 100644 --- a/src/app/settings.rs +++ b/src/app/settings.rs @@ -398,6 +398,8 @@ pub struct UserSettings { pub cursor_size: i32, /// PICKBOX: normalized visible-box and click-aperture size. pub pick_box: i32, + /// HPASSOC: new hatches follow their boundary objects. + pub hatch_associative: bool, /// When true, double-clicking a block reference starts REFEDIT instead of BEDIT. pub double_click_block_refedit: bool, /// When true, double-clicking a block with attributes opens ATTEDIT. @@ -829,6 +831,7 @@ impl Default for UserSettings { zoom_factor: 60, cursor_size: 5, pick_box: 3, + hatch_associative: true, options_tab: crate::ui::window::options::OptionsTab::General, show_viewcube: true, show_ucs_icon: true, diff --git a/src/app/update/file.rs b/src/app/update/file.rs index 9d78560ef..d0db21054 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -780,6 +780,7 @@ impl OpenCADStudio { zoom_factor: self.zoom_factor, cursor_size: self.cursor_size, pick_box: self.pick_box, + hatch_associative: self.hatch_associative, options_tab: self.options_tab, show_viewcube: self.show_viewcube, show_ucs_icon: self.show_ucs_icon, @@ -891,6 +892,7 @@ impl OpenCADStudio { self.zoom_factor_input = self.zoom_factor.to_string(); self.cursor_size = s.cursor_size.clamp(1, 100); self.pick_box = s.pick_box.clamp(0, 50); + self.hatch_associative = s.hatch_associative; self.options_tab = s.options_tab; self.spacemouse_preferences = s.spacemouse; // These four drive real features with commands and status-bar pills, diff --git a/src/modules/draw/draw/hatch.rs b/src/modules/draw/draw/hatch.rs index 587073aba..1811c5e60 100644 --- a/src/modules/draw/draw/hatch.rs +++ b/src/modules/draw/draw/hatch.rs @@ -248,6 +248,12 @@ impl HatchCommand { command } + /// HPASSOC: whether the hatch starts out associative. + pub fn with_associative(mut self, associative: bool) -> Self { + self.associative = associative; + self + } + pub fn with_origin(mut self, origin: [f64; 2]) -> Self { self.default_origin = origin; self