aliases: import AutoCAD PGP files and support UCS-follow workflows

This commit is contained in:
Pictus08 committed 2026-10-14 20:46:35 -03:00
1 parent 2414721c14
commit d19c797685
39 files changed
+818 -30

No files matched your search

+73 -4
View File
@@ -55,7 +55,7 @@ impl CadCommand for UcsCommand {
fn prompt(&self) -> String {
match self.option.as_deref() {
None => {
t!("UCS option [Face/OBject/World/View/3Point/Z/X/Y/Origin/Save/Delete] or name:")
t!("UCS specify new origin or [Face/OBject/World/View/3Point/Z/X/Y/Origin/Save/Delete] or name:")
.into_owned()
}
Some("Z") => t!("UCS rotation angle about Z (degrees):").into_owned(),
@@ -81,7 +81,10 @@ impl CadCommand for UcsCommand {
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
let t = text.trim();
if matches!(self.option.as_deref(), Some("3POINT") | Some("3P"))
// Coordinate input is handled by the point-input pipeline, just like a
// click. With no option selected, it starts the default three-point UCS.
if (self.option.is_none()
|| matches!(self.option.as_deref(), Some("3POINT") | Some("3P")))
&& crate::app::helpers::parse_coord(t).is_some()
{
return None;
@@ -94,6 +97,20 @@ impl CadCommand for UcsCommand {
return Some(CmdResult::Dispatch("UCS LIST".into()));
}
let up = t.to_uppercase();
// Accept the Spanish labels shown by the localized prompt as
// well as international option keywords. Only normalize the
// option token, never the value/name supplied in the next step.
let up = match up.trim_start_matches('_') {
"UNIVERSAL" | "U" => "WORLD",
"VISTA" => "VIEW",
"CARA" => "FACE",
"OBJETO" => "OBJECT",
"ORIGEN" => "ORIGIN",
"GUARDAR" | "G" => "SAVE",
"ELIMINAR" | "E" => "DELETE",
"3" | "3PUNTOS" | "3 PUNTOS" => "3POINT",
value => value,
}.to_owned();
if Self::is_zero_arg(&up) {
Some(CmdResult::Dispatch(format!("UCS {up}")))
} else if Self::takes_value(&up) || Self::takes_point(&up) {
@@ -111,6 +128,11 @@ impl CadCommand for UcsCommand {
}
fn on_point(&mut self, pt: DVec3) -> CmdResult {
// AutoCAD accepts the new origin immediately after UCS/SCP. Do not
// silently ignore that first click while waiting for an option keyword.
if self.option.is_none() {
self.option = Some("3POINT".into());
}
if matches!(self.option.as_deref(), Some("3POINT") | Some("3P")) {
self.points.push(pt);
if self.points.len() < 3 {
@@ -131,8 +153,7 @@ impl CadCommand for UcsCommand {
points[2].z,
));
}
// A clicked point only makes sense for the Origin option; otherwise a
// stray click is ignored (keep waiting for the typed keyword / value).
// Other point-taking options retain their explicit behavior.
if matches!(self.option.as_deref(), Some(o) if Self::takes_point(o)) {
self.option.take();
return CmdResult::Dispatch(format!("UCS ORIGINW {},{},{}", pt.x, pt.y, pt.z));
@@ -149,3 +170,51 @@ impl CadCommand for UcsCommand {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bare_ucs_accepts_origin_then_x_then_xy_without_option() {
let mut cmd = UcsCommand::new();
assert!(matches!(cmd.on_point(DVec3::new(10.0, 20.0, 0.0)), CmdResult::NeedPoint));
assert_eq!(cmd.points.len(), 1);
assert!(matches!(cmd.on_point(DVec3::new(11.0, 20.0, 0.0)), CmdResult::NeedPoint));
match cmd.on_point(DVec3::new(10.0, 21.0, 0.0)) {
CmdResult::Dispatch(command) => assert_eq!(
command, "UCS 3POINTW 10,20,0|11,20,0|10,21,0"
),
_ => panic!("three clicks must dispatch the new UCS"),
}
}
#[test]
fn initial_coordinate_is_delegated_to_point_pipeline() {
let mut cmd = UcsCommand::new();
assert!(cmd.on_text_input("10,20,0").is_none());
assert!(matches!(cmd.on_point(DVec3::new(10.0, 20.0, 0.0)), CmdResult::NeedPoint));
assert_eq!(cmd.points.len(), 1);
}
#[test]
fn explicit_origin_still_changes_only_origin() {
let mut cmd = UcsCommand::new();
assert!(matches!(cmd.on_text_input("O"), Some(CmdResult::NeedPoint)));
match cmd.on_point(DVec3::new(10.0, 20.0, 0.0)) {
CmdResult::Dispatch(command) => assert_eq!(command, "UCS ORIGINW 10,20,0"),
_ => panic!("explicit Origin must dispatch after one point"),
}
}
#[test]
fn spanish_and_international_options_work() {
for option in ["Universal", "U", "_World"] {
let mut cmd = UcsCommand::new();
assert!(matches!(cmd.on_text_input(option), Some(CmdResult::Dispatch(s)) if s == "UCS WORLD"));
}
let mut cmd = UcsCommand::new();
assert!(matches!(cmd.on_text_input("Guardar"), Some(CmdResult::NeedPoint)));
assert!(matches!(cmd.on_text_input("MiPlano"), Some(CmdResult::Dispatch(s)) if s == "UCS SAVE MiPlano"));
}
}