Merge PR #1598 from yztink/feat/dynmode-sysvar: DYNMODE system variable and command for Dynamic Input

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-03 15:00:30 +03:00
commit 92c00ecbe2
6 files changed
+83 -1

No files matched your search

+66 -1
View File
@@ -1086,6 +1086,7 @@ impl OpenCADStudio {
| "CONSTRAINTNAMEFORMAT"
| "DYNCONSTRAINTDISPLAY"
| "CCONSTRAINTFORM"
| "DYNMODE"
) =>
{
return self.dispatch_styleprops(&format!("SETVAR {cmd}"), i);
@@ -1110,7 +1111,7 @@ impl OpenCADStudio {
self.command_line.push_info(&super::plotvars::setvar_listing());
self.command_line.push_info(&super::blockvars::setvar_listing());
self.command_line.push_info(
crate::t!("SETVAR: CETRANSPARENCY LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR SHORTCUTMENU SHORTCUTMENUDURATION CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE CONSTRAINTSOLVEMODE CONSTRAINTINFER CONSTRAINTBARDISPLAY CONSTRAINTBARMODE CONSTRAINTNAMEFORMAT DYNCONSTRAINTDISPLAY ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER GRIPOBJLIMIT | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
crate::t!("SETVAR: CETRANSPARENCY LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR SHORTCUTMENU SHORTCUTMENUDURATION CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE CONSTRAINTSOLVEMODE CONSTRAINTINFER CONSTRAINTBARDISPLAY CONSTRAINTBARMODE CONSTRAINTNAMEFORMAT DYNCONSTRAINTDISPLAY DYNMODE ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER GRIPOBJLIMIT | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
);
} else {
// Point cloud settings, kept with the drawing.
@@ -1703,6 +1704,24 @@ impl OpenCADStudio {
.ok_or_else(|| "SETVAR: 0 or 1 required.".into()),
None => Ok((format!("MIRRTEXT = {}", h.mirror_text as i32), false)),
},
"DYNMODE" => match &value {
Some(v) => match v.parse::<i16>() {
Ok(mode) if (-3..=3).contains(&mode) => {
self.dyn_mode = mode;
self.dyn_input = mode > 0;
Ok((format!("DYNMODE = {mode}"), true))
}
_ => Err("SETVAR: integer from -3 to 3 required.".into()),
},
None => {
let mode = if self.dyn_input {
if self.dyn_mode > 0 { self.dyn_mode } else { 3 }
} else {
if self.dyn_mode <= 0 { self.dyn_mode } else { 0 }
};
Ok((format!("DYNMODE = {mode}"), false))
}
},
"ZOOMWHEEL" => match &value {
Some(v) => match parse_bool(v) {
Some(reversed) => {
@@ -2685,6 +2704,7 @@ impl OpenCADStudio {
// Without this it marked the drawing
// modified instead of persisting.
| "TEXTFILL"
| "DYNMODE"
) {
self.persist_settings_if_changed();
} else {
@@ -3782,6 +3802,51 @@ mod tests {
let _ = app.run_command_line("SETVAR DELOBJ 4");
assert_eq!(app.delete_objects, 3);
}
#[test]
fn dynmode_direct_and_setvar_toggles_dynamic_input() {
let mut app = fresh_app();
assert!(app.dyn_input);
assert_eq!(app.dyn_mode, 3);
// Turn off via direct command: DYNMODE 0
let _ = app.run_command_line("DYNMODE 0");
assert!(!app.dyn_input);
assert_eq!(app.dyn_mode, 0);
// Turn on via direct command: DYNMODE 3
let _ = app.run_command_line("DYNMODE 3");
assert!(app.dyn_input);
assert_eq!(app.dyn_mode, 3);
// Turn off via SETVAR: SETVAR DYNMODE 0
let _ = app.run_command_line("SETVAR DYNMODE 0");
assert!(!app.dyn_input);
assert_eq!(app.dyn_mode, 0);
// Turn on via SETVAR: SETVAR DYNMODE 1 (pointer input only)
let _ = app.run_command_line("SETVAR DYNMODE 1");
assert!(app.dyn_input);
assert_eq!(app.dyn_mode, 1);
// Out of range rejected
let _ = app.run_command_line("DYNMODE 5");
assert_eq!(app.dyn_mode, 1);
assert!(app.dyn_input);
let _ = app.run_command_line("DYNMODE -5");
assert_eq!(app.dyn_mode, 1);
assert!(app.dyn_input);
// F12 / Message::ToggleDynInput synchronization
let _ = app.update(crate::app::Message::ToggleDynInput);
assert!(!app.dyn_input);
assert_eq!(app.dyn_mode, 0);
let _ = app.update(crate::app::Message::ToggleDynInput);
assert!(app.dyn_input);
assert_eq!(app.dyn_mode, 3);
}
}
#[cfg(test)]
+5
View File
@@ -101,6 +101,11 @@ impl OpenCADStudio {
self.snapper.snap3d_enabled = state.osnap3d_on;
self.snapper.enabled3d = state.snap3d_modes.clone();
self.dyn_input = state.dyn_input_on;
if self.dyn_input && self.dyn_mode <= 0 {
self.dyn_mode = 3;
} else if !self.dyn_input && self.dyn_mode > 0 {
self.dyn_mode = 0;
}
self.quick_properties = state.quick_props_on;
self.selection_cycling = state.selection_cycling_on;
self.sync_vport_display(self.active_tab);
+3
View File
@@ -615,6 +615,8 @@ pub(super) struct OpenCADStudio {
pub grid_beyond_limits: bool,
/// Dynamic input overlay (F12): show coordinate tooltip near cursor.
dyn_input: bool,
/// Dynamic input mode (DYNMODE): 0=off, 1=pointer, 2=dimensional, 3=both.
dyn_mode: i16,
/// Currently visible page in the application Options dialog.
options_tab: crate::ui::window::options::OptionsTab,
/// The Options window's commit point (see `options_session`).
@@ -4136,6 +4138,7 @@ impl OpenCADStudio {
grid_adaptive: true,
grid_beyond_limits: true,
dyn_input: true,
dyn_mode: 3,
options_tab: crate::ui::window::options::OptionsTab::General,
options_saved: None,
options_close_confirm: false,
+2
View File
@@ -383,6 +383,7 @@ pub const MAX_SELECTED_GRIPS: usize = 4096;
pub struct UserSettings {
pub spacemouse: crate::input::spacemouse::Preferences,
pub dyn_input: bool,
pub dyn_mode: i16,
pub polar: bool,
pub polar_increment_deg: f32,
pub zoom_wheel_reversed: bool,
@@ -771,6 +772,7 @@ impl Default for UserSettings {
Self {
spacemouse: crate::input::spacemouse::Preferences::default(),
dyn_input: true,
dyn_mode: 3,
polar: false,
polar_increment_deg: 45.0,
zoom_wheel_reversed: false,
+2
View File
@@ -659,6 +659,7 @@ impl OpenCADStudio {
crate::app::settings::UserSettings {
spacemouse: self.spacemouse_preferences,
dyn_input: self.dyn_input,
dyn_mode: self.dyn_mode,
polar: self.polar_mode,
polar_increment_deg: self.polar_increment_deg,
zoom_wheel_reversed: self.zoom_wheel_reversed,
@@ -750,6 +751,7 @@ impl OpenCADStudio {
/// Apply restored preferences to live state.
pub(in crate::app) fn apply_settings(&mut self, s: &crate::app::settings::UserSettings) {
self.dyn_input = s.dyn_input;
self.dyn_mode = if s.dyn_mode != 0 { s.dyn_mode } else if s.dyn_input { 3 } else { 0 };
self.polar_mode = s.polar;
self.polar_increment_deg = s.polar_increment_deg;
self.zoom_wheel_reversed = s.zoom_wheel_reversed;
+5
View File
@@ -4197,6 +4197,11 @@ impl OpenCADStudio {
}
Message::ToggleDynInput => {
self.dyn_input ^= true;
if self.dyn_input && self.dyn_mode <= 0 {
self.dyn_mode = 3;
} else if !self.dyn_input && self.dyn_mode > 0 {
self.dyn_mode = 0;
}
Task::none()
}
Message::ToggleViewCube => {