Fix/Unfix on every sketch entity: points (Fix constraint) and lines, arcs, circles, ellipses, splines and conics (fixed curves hold their points and radius); ConstraintFix takes entities (fixes them all unless all are fixed); the toolbar button and the context menu act on the whole selection; fixed points never move when dragged or solved; projected geometry counts as fixed; fixed geometry is drawn green; sketch.inspect reports fixed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 05:12:13 +00:00
1 parent b457b6b7b6
commit 5b8816aa7d
11 files changed
+252 -35

No files matched your search

+2 -5
View File
@@ -586,11 +586,8 @@ pub fn run_item(app: &mut SolveApp, item: &Item, at: Pos2) {
"ui.unsection" => drop(app.run("FusionHalfSectionViewCommand", json!({"clear": true}))),
"ui.fit" => app.animate_view("fit"),
"ui.home" => app.animate_view("home"),
"ui.fix" => {
for e in strs(&p, "entities") {
let _ = app.run("ConstraintFix", json!({ "entity": e }));
}
}
// One command for the whole selection: all fixed unless all already are.
"ui.fix" => drop(app.run("ConstraintFix", json!({ "entities": strs(&p, "entities") }))),
"ui.editSketch" => {
if let Some(id) = id_of(&p, "sketch") {
app.edit_sketch(id);
+16
View File
@@ -295,6 +295,22 @@ impl SolveApp {
let edges = self.session.selection.iter().any(|s| matches!(s, solvecraft_engine::Sel::Edge { .. }));
return self.start(if edges { "FusionFilletEdgesCommand" } else { "Extrude" });
}
// Fix/Unfix: the selected sketch points and curves change at once, otherwise pick them.
if id == "ConstraintFix" {
let ents: Vec<String> = self
.session
.selection
.iter()
.filter_map(|s| match s {
solvecraft_engine::Sel::SketchCurve { id } | solvecraft_engine::Sel::SketchPoint { id } => Some(id.clone()),
_ => None,
})
.collect();
if !ents.is_empty() {
let _ = self.run(id, json!({ "entities": ents }));
return;
}
}
// Construction toggle: selected sketch curves switch at once, otherwise pick them.
if id == "sketch.construction" {
let curves: Vec<String> = self
+10 -1
View File
@@ -178,6 +178,8 @@ fn sketch_color(t: &Tokens, c: Rgb) -> [u8; 4] {
c4(t.sketch)
} else if c == colors::SKETCH_DONE || c == colors::SKETCH_FIXED {
c4(t.sketch_fixed)
} else if c == colors::SKETCH_LOCKED {
c4(t.sketch_locked)
} else {
rgba(c)
}
@@ -1265,13 +1267,20 @@ fn overlays(app: &SolveApp, painter: &egui::Painter, proj: &Proj) {
let Some(sid) = app.session.active_sketch else { return };
let Some(ss) = st.sketch(sid) else { return };
let sk = &ss.sketch;
let locked = sk.locked_points();
for (i, p) in sk.points.iter().enumerate() {
if !solvecraft_engine::view::sketch_point_visible(sk, i) {
continue;
}
let Some(sp) = proj.to_screen(ss.plane.to_world(p.pos)) else { continue };
let det = ss.report.point_determined.get(i).copied().unwrap_or(false);
let c = if det { t.sketch_point } else { t.sketch_point_free };
let c = if p.link.is_none() && locked.get(i).copied().unwrap_or(false) {
t.sketch_locked
} else if det {
t.sketch_point
} else {
t.sketch_point_free
};
if i == 0 {
painter.circle(sp, 3.5, Color32::from_rgb(240, 200, 60), Stroke::new(1.0, t.body_edge));
} else {