Add per-constraint delete; fix named-parameter reference bugs

Constraint delete: a Properties-panel row delete button, viewport
click-to-select on a constraint glyph pill with Delete-key support, and a
right-click "Delete Constraint" menu item — all routed through one
undoable Scene::selected_constraint-aware path.

Fixes two named-parameter bugs found while testing that feature:
- DIMCONSTRAINT: a parameter named like a mode-switch keyword ("r", "d",
  "a", "x", "y") could never be referenced, since the keyword check ran
  before the parameter-name check.
- PARAMETERS modal Apply rebuilt Scene::named_parameters but never
  refreshed the Properties panel, leaving renamed/deleted rows stale
  until an unrelated refresh (e.g. a selection change) happened to occur.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Felix RiestraandClaude Sonnet 5 committed 2026-09-15 01:08:34 +02:00
1 parent 753df67ee4
commit 59ae38ae1a
14 files changed
+370 -77

No files matched your search

+11
View File
@@ -4287,6 +4287,13 @@ impl OpenCADStudio {
}
let i = self.active_tab;
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
// A selected constraint-glyph pill takes Delete before entity
// erase — the two selections are mutually exclusive (see
// `Scene::selected_constraint`).
if let Some(id) = self.tabs[i].scene.selected_constraint {
self.delete_sketch_constraint(id);
return Task::none();
}
let handles: Vec<_> = self.tabs[i].scene.selected.iter().cloned().collect();
if !handles.is_empty() {
// Erase is delta-safe unless a target is in a group (group
@@ -6218,6 +6225,10 @@ impl OpenCADStudio {
self.refresh_properties();
Task::none()
}
Message::PropConstraintDelete(id) => {
self.delete_sketch_constraint(id);
Task::none()
}
// ── Options / About windows ───────────────────────────────────
Message::OptionsOpen => {
+26
View File
@@ -4451,6 +4451,31 @@ properties={:.1}ms picked={}",
sel.box_current = None;
} else {
if box_anchor.is_none() {
// A sketch-constraint glyph pill draws on top of the
// geometry it touches and takes priority over it when
// clicked (design mirrors `has_selection` gating the
// viewport right-click menu, and `DeleteSelected`
// preferring a selected pill over entity erase).
let glyph_hit = (self.tabs[i].scene.current_layout == "Model")
.then(|| {
let scope = self.tabs[i].current_sketch_scope();
self.tabs[i].scene.constraint_glyph_hit(
scope,
canvas_sz,
self.show_constraint_values,
p_full,
)
})
.flatten();
if let Some(id) = glyph_hit {
if !selection_pick_add && !self.shift_down {
self.tabs[i].scene.deselect_all();
}
self.tabs[i].scene.selected_constraint = Some(id);
self.refresh_properties();
selection_just_completed = true;
}
if glyph_hit.is_none() {
let (view_rot, eye, all_wires) = self.pick_view(i, &edit_cam, bounds);
let click_world = self.cursor_model_point(i, &edit_cam, p, bounds);
let t_arm = crate::perf::enabled().then(Instant::now);
@@ -4611,6 +4636,7 @@ was_selected={}",
}
}
}
}
} else {
let a = box_anchor.unwrap();
let box_points = [