feat(statusbar): honor $COORDS in the coordinate readout, click to cycle
The Coords pill always showed live absolute X,Y,Z, ignoring the drawing's
$COORDS (coords_mode) sysvar. Drive the readout from it:
- 0 static — the last picked point; the readout freezes between picks.
- 1 live — continuous absolute X,Y,Z (previous behavior, default).
- 2 polar — distance<angle relative to the last point while a command is
prompting for a point; absolute otherwise.
The cursor and last point are reported in the active UCS, matching the rest of
the readout. Clicking the pill cycles the mode 0→1→2→0 (CycleCoordsMode), marks
the tab dirty and echoes it; SETVAR COORDS still works. $COORDS round-trips per
drawing via acadrust's coords_mode.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6bbd88153b
commit
71db52a0a4
4 changed files with 66 additions and 8 deletions
|
|
@ -1458,6 +1458,8 @@ pub enum Message {
|
||||||
ToggleLayoutList,
|
ToggleLayoutList,
|
||||||
/// Close the Model/layout list dropdown.
|
/// Close the Model/layout list dropdown.
|
||||||
CloseLayoutList,
|
CloseLayoutList,
|
||||||
|
/// Cycle the coordinate readout mode ($COORDS): static → live → polar.
|
||||||
|
CycleCoordsMode,
|
||||||
/// Toggle the status-bar customization menu open/closed.
|
/// Toggle the status-bar customization menu open/closed.
|
||||||
ToggleStatusBarMenu,
|
ToggleStatusBarMenu,
|
||||||
/// Close the status-bar customization menu.
|
/// Close the status-bar customization menu.
|
||||||
|
|
|
||||||
|
|
@ -1541,6 +1541,26 @@ impl OpenCADStudio {
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
Message::CycleCoordsMode => {
|
||||||
|
// $COORDS 0 (static) → 1 (live absolute) → 2 (polar) → 0.
|
||||||
|
let i = self.active_tab;
|
||||||
|
if i < self.tabs.len() {
|
||||||
|
let mode = {
|
||||||
|
let h = &mut self.tabs[i].scene.document.header;
|
||||||
|
h.coords_mode = (h.coords_mode + 1).rem_euclid(3);
|
||||||
|
h.coords_mode
|
||||||
|
};
|
||||||
|
self.tabs[i].dirty = true;
|
||||||
|
let label = match mode {
|
||||||
|
0 => "static",
|
||||||
|
2 => "polar",
|
||||||
|
_ => "live",
|
||||||
|
};
|
||||||
|
self.command_line
|
||||||
|
.push_output(&format!("COORDS = {mode} ({label})"));
|
||||||
|
}
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
Message::TogglePolar => {
|
Message::TogglePolar => {
|
||||||
self.polar_mode ^= true;
|
self.polar_mode ^= true;
|
||||||
if self.polar_mode {
|
if self.polar_mode {
|
||||||
|
|
|
||||||
|
|
@ -1303,16 +1303,21 @@ impl OpenCADStudio {
|
||||||
// drawing coordinates (paper space carries no offset), then
|
// drawing coordinates (paper space carries no offset), then
|
||||||
// report it in the active UCS — the readout follows the
|
// report it in the active UCS — the readout follows the
|
||||||
// user's coordinate system, not raw WCS (no-op without UCS).
|
// user's coordinate system, not raw WCS (no-op without UCS).
|
||||||
let cursor_coord = {
|
let to_readout = |p: glam::Vec3| {
|
||||||
let lc = tab.last_cursor_world;
|
|
||||||
// The readout follows the active pane's UCS — model space
|
// The readout follows the active pane's UCS — model space
|
||||||
// or inside a floating viewport (no-op without a UCS).
|
// or inside a floating viewport (no-op without a UCS).
|
||||||
if tab.editing_model_space() {
|
if tab.editing_model_space() {
|
||||||
tab.ucs_xform().to_ucs(lc)
|
tab.ucs_xform().to_ucs(p)
|
||||||
} else {
|
} else {
|
||||||
lc
|
p
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let cursor_coord = to_readout(tab.last_cursor_world);
|
||||||
|
// The last picked point (same UCS as the cursor) drives the
|
||||||
|
// static ($COORDS 0) and polar ($COORDS 2) readouts.
|
||||||
|
let last_coord = self.last_point.map(to_readout);
|
||||||
|
let coords_mode = tab.scene.document.header.coords_mode;
|
||||||
|
let picking = tab.active_cmd.is_some();
|
||||||
self.status_bar.view(
|
self.status_bar.view(
|
||||||
&self.snapper,
|
&self.snapper,
|
||||||
self.snap_popup_open,
|
self.snap_popup_open,
|
||||||
|
|
@ -1334,6 +1339,9 @@ impl OpenCADStudio {
|
||||||
scale_pill_enabled,
|
scale_pill_enabled,
|
||||||
tab.scene.document.header.lineweight_display,
|
tab.scene.document.header.lineweight_display,
|
||||||
cursor_coord,
|
cursor_coord,
|
||||||
|
coords_mode,
|
||||||
|
last_coord,
|
||||||
|
picking,
|
||||||
self.clean_screen,
|
self.clean_screen,
|
||||||
tab.scene.document.header.insertion_units,
|
tab.scene.document.header.insertion_units,
|
||||||
self.units_popup_open,
|
self.units_popup_open,
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,13 @@ impl StatusBar {
|
||||||
lineweight_display: bool,
|
lineweight_display: bool,
|
||||||
// Live cursor position in model coordinates, for the coordinate readout.
|
// Live cursor position in model coordinates, for the coordinate readout.
|
||||||
cursor_world: glam::Vec3,
|
cursor_world: glam::Vec3,
|
||||||
|
// $COORDS readout mode: 0 = static (updates only on a pick), 1 = live
|
||||||
|
// absolute, 2 = polar (distance<angle from the last point while picking).
|
||||||
|
coords_mode: i16,
|
||||||
|
// The last committed point, for the static (0) and polar (2) readouts.
|
||||||
|
last_point: Option<glam::Vec3>,
|
||||||
|
// True while a command is prompting for a point (enables the polar readout).
|
||||||
|
picking: bool,
|
||||||
// True while clean-screen mode hides the ribbon and side panels.
|
// True while clean-screen mode hides the ribbon and side panels.
|
||||||
clean_screen: bool,
|
clean_screen: bool,
|
||||||
// Drawing units (INSUNITS) for the units pill.
|
// Drawing units (INSUNITS) for the units pill.
|
||||||
|
|
@ -153,10 +160,11 @@ impl StatusBar {
|
||||||
let vis = |p: StatusPill| config.is_visible(p);
|
let vis = |p: StatusPill| config.is_visible(p);
|
||||||
let mut pills: Vec<Element<'_, Message>> = Vec::new();
|
let mut pills: Vec<Element<'_, Message>> = Vec::new();
|
||||||
if vis(StatusPill::Coords) {
|
if vis(StatusPill::Coords) {
|
||||||
|
let coords_label = format_coords(cursor_world, last_point, coords_mode, picking);
|
||||||
pills.push(
|
pills.push(
|
||||||
tip(
|
tip(
|
||||||
status_pill(format_coords(cursor_world)).into(),
|
popup_pill(&coords_label, false, Message::CycleCoordsMode),
|
||||||
"Cursor coordinates (X, Y, Z)",
|
"Cursor coordinates ($COORDS)\nClick to cycle: static / live / polar",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
@ -377,8 +385,28 @@ impl StatusBar {
|
||||||
|
|
||||||
// ── Coordinate readout ────────────────────────────────────────────────────
|
// ── Coordinate readout ────────────────────────────────────────────────────
|
||||||
|
|
||||||
fn format_coords(p: glam::Vec3) -> String {
|
fn format_coords(cursor: glam::Vec3, last: Option<glam::Vec3>, mode: i16, picking: bool) -> String {
|
||||||
format!("{:.4}, {:.4}, {:.4}", p.x, p.y, p.z)
|
let abs = |p: glam::Vec3| format!("{:.4}, {:.4}, {:.4}", p.x, p.y, p.z);
|
||||||
|
match mode {
|
||||||
|
// Static: show the last picked point; the readout freezes between picks.
|
||||||
|
0 => abs(last.unwrap_or(cursor)),
|
||||||
|
// Polar: distance < angle relative to the last point while a command is
|
||||||
|
// prompting for a point; absolute otherwise.
|
||||||
|
2 => match (picking, last) {
|
||||||
|
(true, Some(l)) => {
|
||||||
|
let d = cursor - l;
|
||||||
|
let dist = (d.x * d.x + d.y * d.y).sqrt();
|
||||||
|
let mut ang = d.y.atan2(d.x).to_degrees();
|
||||||
|
if ang < 0.0 {
|
||||||
|
ang += 360.0;
|
||||||
|
}
|
||||||
|
format!("{dist:.4} < {ang:.2}\u{b0}")
|
||||||
|
}
|
||||||
|
_ => abs(cursor),
|
||||||
|
},
|
||||||
|
// 1 (default) and anything else: live absolute.
|
||||||
|
_ => abs(cursor),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Customization handle ──────────────────────────────────────────────────
|
// ── Customization handle ──────────────────────────────────────────────────
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue