diff --git a/src/app/automation.rs b/src/app/automation.rs index 6ea9c4f3d..eee846b2b 100644 --- a/src/app/automation.rs +++ b/src/app/automation.rs @@ -565,6 +565,27 @@ mod tests { assert_eq!(app.automation_op(r#"{"op":"run"}"#)["ok"], false); } + #[test] + fn ucs_interactive_inline_args() { + // `UCS Z 90` must drive the interactive UCS command step-by-step (option + // "Z" then value "90") and rotate the active UCS 90° about Z. (#169) + let mut app = OpenCADStudio::new_for_test(); + app.automation_op(r#"{"op":"new"}"#); + app.automation_op(r#"{"op":"run","cmd":"UCS Z 90"}"#); + let i = app.active_tab; + let ucs = app.tabs[i] + .active_ucs + .as_ref() + .expect("UCS Z 90 should set an active UCS"); + // 90° about Z sends the X axis (1,0,0) → (0,1,0). + assert!( + ucs.x_axis.x.abs() < 1e-6 && (ucs.x_axis.y - 1.0).abs() < 1e-6, + "x_axis after UCS Z 90 = ({}, {})", + ucs.x_axis.x, + ucs.x_axis.y + ); + } + #[test] fn save_then_open_round_trips() { let mut app = OpenCADStudio::new_for_test(); diff --git a/src/app/cmd_result.rs b/src/app/cmd_result.rs index 39cba5ede..2315f2107 100644 --- a/src/app/cmd_result.rs +++ b/src/app/cmd_result.rs @@ -567,6 +567,15 @@ impl OpenCADStudio { self.restore_pre_cmd_tangent(); let _ = self.dispatch_command(&cmd); } + CmdResult::Dispatch(cmd) => { + // End this interactive front-end, then run the assembled command + // through the normal dispatcher. Selection is left untouched. + self.tabs[i].active_cmd = None; + self.tabs[i].snap_result = None; + self.tabs[i].scene.clear_preview_wire(); + self.restore_pre_cmd_tangent(); + let _ = self.dispatch_command(&cmd); + } CmdResult::MatchEntityLayer { dest, src } => { self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; diff --git a/src/app/commands.rs b/src/app/commands.rs index ed9ae96c5..1a0ac49c0 100644 --- a/src/app/commands.rs +++ b/src/app/commands.rs @@ -3618,8 +3618,18 @@ impl OpenCADStudio { } } - // ── UCS management ─────────────────────────────────────────── - cmd if cmd == "UCS" || cmd.starts_with("UCS ") => { + // Bare UCS → interactive front-end (option then value as steps), so + // `UCS Z 90` is typable in the command line and works headlessly. + // The front-end delegates back to the inline handler below. (#169) + "UCS" => { + use crate::modules::view::ucs_cmd::UcsCommand; + let cmd_obj = UcsCommand::new(); + self.command_line.push_info(&cmd_obj.prompt()); + self.tabs[i].active_cmd = Some(Box::new(cmd_obj)); + } + + // ── UCS management (inline `UCS