X and the toolbar's Construction no longer start a pick tool (Fusion has none): with a selection they convert it, with nothing selected they switch construction mode, outside a sketch they say so. Center Rectangle draws both diagonals as construction, the centre at their crossing, with only the first carrying the midpoint constraint (the second is implied), so a fresh one stays at 4 DOF. Scenarios s30 (pattern a hole) and s32 (cut in the active component) enabled now that b36b332 is on main
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
90873e51bb
commit
1e8fc25976
6 files changed
+33
-11
No files matched your search
@@ -552,10 +552,16 @@ fn rect_center(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let (out, info) = edit(s, p, cmd, false, |sk, _| {
|
||||
let (l, pts) = polygon_lines(sk, &[c - h, Vec2::new(c.x + h.x, c.y - h.y), c + h, Vec2::new(c.x - h.x, c.y + h.y)])?;
|
||||
let mut cons = rect_constraints(sk, &l)?;
|
||||
if let (Some(p0), Some(p2)) = (pts.first(), pts.get(2)) {
|
||||
// Both diagonals (construction), the centre at their crossing. Only the first carries
|
||||
// the midpoint constraint: diagonals of a parallelogram bisect each other, so a second
|
||||
// one would be redundant (over-constrained).
|
||||
if let (Some(p0), Some(p1), Some(p2), Some(p3)) = (pts.first(), pts.get(1), pts.get(2), pts.get(3)) {
|
||||
let diag = sk.add_line_pts(*p0, *p2, None)?;
|
||||
if let Some(cu) = sk.curves.get_mut(diag) {
|
||||
cu.construction = true;
|
||||
let diag2 = sk.add_line_pts(*p1, *p3, None)?;
|
||||
for d in [diag, diag2] {
|
||||
if let Some(cu) = sk.curves.get_mut(d) {
|
||||
cu.construction = true;
|
||||
}
|
||||
}
|
||||
let cp = sk.add_point(c, None)?;
|
||||
cons.push(add_c(sk, ConstraintKind::Midpoint { p: cp, l: diag })?);
|
||||
|
||||
@@ -101,3 +101,19 @@ fn dragging_corners_never_collapses_a_side() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn center_rectangle_draws_both_diagonals_like_fusion() {
|
||||
let (mut s, _) = rect("center");
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
let curves = si["curves"].as_array().cloned().unwrap_or_default();
|
||||
// Four sides plus two construction diagonals; the other rectangles have no diagonals.
|
||||
assert_eq!(curves.len(), 6, "{si}");
|
||||
assert_eq!(curves.iter().filter(|c| c["construction"] == true).count(), 2, "{si}");
|
||||
assert_eq!(healthy(&mut s, "center diagonals"), 4);
|
||||
for k in ["two", "three"] {
|
||||
let (mut s, _) = rect(k);
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
assert_eq!(si["curves"].as_array().map(Vec::len), Some(4), "{k}: {si}");
|
||||
}
|
||||
}
|
||||
@@ -420,8 +420,8 @@ impl SolveApp {
|
||||
}
|
||||
}
|
||||
// Construction toggle: selected sketch curves switch at once, otherwise pick them.
|
||||
// Construction (X): convert the selection, or switch construction mode.
|
||||
if id == "sketch.construction" && self.session.active_sketch.is_some() {
|
||||
// Construction (X): convert the selection, or switch construction mode; no pick tool.
|
||||
if id == "sketch.construction" {
|
||||
sketch_palette::toggle_construction(self);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,9 @@ pub fn set_mode(app: &mut SolveApp, m: u8) {
|
||||
/// switch construction mode on or off.
|
||||
pub fn toggle_construction(app: &mut SolveApp) {
|
||||
let curves = selected_curves(app);
|
||||
if curves.is_empty() {
|
||||
if curves.is_empty() && app.session.active_sketch.is_none() {
|
||||
app.set_status("Construction mode is for drawing in a sketch: edit a sketch first", false);
|
||||
} else if curves.is_empty() {
|
||||
let m = if mode(app) == 1 { 0 } else { 1 };
|
||||
set_mode(app, m);
|
||||
} else {
|
||||
|
||||
@@ -65,7 +65,6 @@ impl Tool {
|
||||
"ConstraintCollinear" => ("ConstraintCollinear", Kind::Pick(2)),
|
||||
"ConstraintMidPoint" => ("ConstraintMidPoint", Kind::Pick(2)),
|
||||
"ConstraintSymmetry" => ("ConstraintSymmetry", Kind::Pick(3)),
|
||||
"sketch.construction" => ("sketch.construction", Kind::Pick(1)),
|
||||
_ => return crate::sketch_tools::tool_for(id),
|
||||
};
|
||||
Some(Tool { cmd, kind, pts: Vec::new(), hover: None, picks: Vec::new(), dims: Vec::new(), dims_stage: usize::MAX, dims_focus: false })
|
||||
@@ -280,7 +279,6 @@ fn run_pick(app: &mut SolveApp, t: &Tool) {
|
||||
let params = match t.cmd {
|
||||
"ConstraintHorizontalVertical" => json!({"line": k[0]}),
|
||||
"ConstraintFix" => json!({"entity": k[0]}),
|
||||
"sketch.construction" => json!({"curves": [k[0]]}),
|
||||
"ConstraintCoincident" => json!({"a": k[0], "b": k[1]}),
|
||||
"ConstraintMidPoint" => json!({"point": k[0], "line": k[1]}),
|
||||
"ConstraintSymmetry" => json!({"a": k[0], "b": k[1], "line": k[2]}),
|
||||
|
||||
@@ -53,7 +53,9 @@ scenarios!(
|
||||
s33_move_x_arrow,
|
||||
s34_component_move_carries_sketches,
|
||||
s35_construction_mode,
|
||||
s36_sketch_palette_visible
|
||||
s36_sketch_palette_visible,
|
||||
s32_cut_in_active_component,
|
||||
s30_pattern_a_hole
|
||||
);
|
||||
|
||||
/// Scenarios written ahead of their fixes or features (the user's open bugs): run with
|
||||
@@ -70,6 +72,4 @@ macro_rules! pending {
|
||||
|
||||
pending!(
|
||||
s31_sketch_on_face_projects: "user bug: a sketch on a face projects its loops as reference (solvecraft-sketch)",
|
||||
s32_cut_in_active_component: "user bug: a cut in the active component leaves others alone (solvecraft-params)",
|
||||
s30_pattern_a_hole: "the dialog sends the hole as a feature; the engine's pattern of a blind hole cuts too little (one hole short)",
|
||||
);
|
||||
Reference in new issue
Block a user