forked from 1b-agent/opencadstudio-upstream
feat(view): -VIEW orthographic UCS, sEttings and Window like the reference
An orthographic preset sets its orthographic UCS while UCSORTHO is on (*FRONT*, *RIGHT*, …; TOP returns to the world UCS); presets no longer flip to the opposite view when repeated. -VIEW runs as its own command: Window asks for the name and corners, sEttings loops over Background, Categorize, Layer snapshot, live Section, Ucs and Visual style with the reference prompts and messages, Save keeps the UCS with the view while UCSVIEW is on and Restore brings it back. UCSORTHO and UCSVIEW are profile variables. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
62ff1daade
commit
cfe64ae6a4
10 files changed
+945
-127
No files matched your search
+16
-109
@@ -760,83 +760,21 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// -VIEW: the command-line form. Its presets set the standard
|
||||
// orthographic and isometric views; the rest are VIEW's verbs.
|
||||
// -VIEW: the command-line form of VIEW (modules/view/view_cmd.rs).
|
||||
// The command gathers the input; `-VIEW >…` carries out what it
|
||||
// gathered. A whole line (`-VIEW _O _FRONT`) feeds its words to
|
||||
// the command one by one, as typed.
|
||||
"-VIEW" => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"-VIEW",
|
||||
"Enter an option [?/Delete/Orthographic/Restore/Save/sEttings/Window]:",
|
||||
vec![
|
||||
("?", "?", None),
|
||||
("Delete", "DELETE", Some("Enter view name(s) to delete:")),
|
||||
("Orthographic", "ORTHOGRAPHIC", None),
|
||||
("Restore", "RESTORE", Some("Enter view name to restore:")),
|
||||
("Save", "SAVE", Some("Enter view name to save:")),
|
||||
],
|
||||
)
|
||||
.with_hidden(&["TOP", "BOTTOM", "FRONT", "BACK", "LEFT", "RIGHT", "SWISO", "SEISO", "NEISO", "NWISO"]);
|
||||
use crate::command::CadCommand;
|
||||
let c = crate::modules::view::view_cmd::DashViewCommand::new(self.dash_view_names(i));
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
}
|
||||
cmd if cmd.starts_with("-VIEW >") => {
|
||||
return Some(self.run_dash_view(&cmd["-VIEW >".len()..], i));
|
||||
}
|
||||
cmd if cmd.starts_with("-VIEW ") => {
|
||||
let words: Vec<String> = cmd["-VIEW ".len()..]
|
||||
.split_whitespace()
|
||||
.map(|word| word.trim_start_matches('_').to_ascii_uppercase())
|
||||
.collect();
|
||||
let first = words.first().map(String::as_str).unwrap_or("");
|
||||
let preset = |word: &str| -> Option<&'static str> {
|
||||
["TOP", "BOTTOM", "FRONT", "BACK", "LEFT", "RIGHT", "SWISO", "SEISO", "NEISO", "NWISO"]
|
||||
.into_iter()
|
||||
.find(|name| name.eq_ignore_ascii_case(word))
|
||||
};
|
||||
// The Orthographic face: Top/Bottom/Front/BAck/Left/Right.
|
||||
let face = |word: &str| -> Option<&'static str> {
|
||||
match word {
|
||||
"BA" | "BAC" | "BACK" => Some("BACK"),
|
||||
_ => ["TOP", "BOTTOM", "FRONT", "LEFT", "RIGHT"]
|
||||
.into_iter()
|
||||
.find(|name| !word.is_empty() && name.starts_with(word)),
|
||||
}
|
||||
};
|
||||
let orthographic = !first.is_empty() && "ORTHOGRAPHIC".starts_with(first);
|
||||
let view = if orthographic {
|
||||
match words.get(1) {
|
||||
Some(word) => face(word),
|
||||
None => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"-VIEW ORTHOGRAPHIC",
|
||||
"Enter an option [Top/Bottom/Front/BAck/Left/Right]<Top>:",
|
||||
vec![
|
||||
("Top", "TOP", None),
|
||||
("Bottom", "BOTTOM", None),
|
||||
("Front", "FRONT", None),
|
||||
("BAck", "BACK", None),
|
||||
("Left", "LEFT", None),
|
||||
("Right", "RIGHT", None),
|
||||
],
|
||||
)
|
||||
.with_default("TOP");
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
return Some(self.finish_dispatch(cmd));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
preset(first)
|
||||
};
|
||||
if let Some(view) = view {
|
||||
self.command_line.push_output(crate::t!("Regenerating model.").as_ref());
|
||||
return self.dispatch_layerprops(&format!("VIEW {view}"), i);
|
||||
}
|
||||
if orthographic {
|
||||
self.command_line.push_error(crate::t!("Invalid option keyword.").as_ref());
|
||||
return Some(self.finish_dispatch(cmd));
|
||||
}
|
||||
// View names keep their case.
|
||||
let rest = cmd["-VIEW ".len()..].split_whitespace().skip(1).collect::<Vec<_>>().join(" ");
|
||||
return self.dispatch_layerprops(format!("VIEW {first} {rest}").trim_end(), i);
|
||||
return Some(self.run_command_line(cmd));
|
||||
}
|
||||
"VIEW" => {
|
||||
use crate::command::KeywordCommand;
|
||||
@@ -936,45 +874,14 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Standard orientation presets — snap the camera to a world
|
||||
// axis view (these names take precedence over a same-named
|
||||
// saved view, matching the standard orientation behaviour).
|
||||
"TOP" | "FRONT" | "BACK" | "LEFT" | "RIGHT" | "BOTTOM" => {
|
||||
use crate::scene::pipeline::viewcube::{
|
||||
FACE_BACK, FACE_BOTTOM, FACE_FRONT, FACE_LEFT, FACE_RIGHT, FACE_TOP,
|
||||
};
|
||||
let face = match sub.as_str() {
|
||||
"TOP" => FACE_TOP,
|
||||
"BOTTOM" => FACE_BOTTOM,
|
||||
"FRONT" => FACE_FRONT,
|
||||
"BACK" => FACE_BACK,
|
||||
"RIGHT" => FACE_RIGHT,
|
||||
_ => FACE_LEFT,
|
||||
};
|
||||
return Some(Task::done(Message::ViewCubeSnapWorld(
|
||||
crate::scene::CubeRegion::Face(face),
|
||||
)));
|
||||
// Standard orientation presets: the world views -VIEW sets,
|
||||
// with the orthographic UCS while UCSORTHO is on. These
|
||||
// names take precedence over a same-named saved view.
|
||||
"TOP" | "FRONT" | "BACK" | "LEFT" | "RIGHT" | "BOTTOM" | "SWISO" | "SEISO" | "NEISO" | "NWISO" => {
|
||||
return Some(self.apply_view_preset(&sub));
|
||||
}
|
||||
// Isometric presets snap to the matching ViewCube corner;
|
||||
// ISO alone is the south-west one.
|
||||
"ISO" | "ISOMETRIC" | "SWISO" | "SEISO" | "NEISO" | "NWISO" => {
|
||||
let (x, y) = match sub.as_str() {
|
||||
"SEISO" => (1.0, -1.0),
|
||||
"NEISO" => (1.0, 1.0),
|
||||
"NWISO" => (-1.0, 1.0),
|
||||
_ => (-1.0, -1.0),
|
||||
};
|
||||
let want = glam::Vec3::new(x, y, 1.0).normalize();
|
||||
let corner = (18..26)
|
||||
.map(crate::scene::CubeRegion::Corner)
|
||||
.max_by(|a, b| {
|
||||
a.snap_direction()
|
||||
.dot(want)
|
||||
.total_cmp(&b.snap_direction().dot(want))
|
||||
})
|
||||
.expect("the cube has corners");
|
||||
return Some(Task::done(Message::ViewCubeSnap(corner)));
|
||||
}
|
||||
"ISO" | "ISOMETRIC" => return Some(self.apply_view_preset("SWISO")),
|
||||
// VIEW <name> shortcut for restore
|
||||
_ => {
|
||||
let name = sub.clone();
|
||||
|
||||
Reference in new issue
Block a user