Command ids are SolveCraft's own: 173 ids that were another product's internal command ids become dotted, lower-case ids (<area>.<thing>[.<variant>]: solid.extrude, sketch.rectangle.two_point, sheet.flange, joint.drive, ...), in the registry, toolbar, dialogs, shortcuts, palette, control channel, MCP, examples, scenarios and docs
The old ids live only in crates/engine/src/legacy_ids.rs (the legacy migration table): find_command maps them, so old scripts, recipes and control calls keep working, and saved shortcuts, recent and pinned commands are migrated on load (designs store no command ids). Parity maps the observed catalog ids to ours through xtask/data/fusion-ids.tsv. The agent rule now reads: our own dotted id, never another product's. Cargo.toml's repository points at github.com/bherbruck/solvecraft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
740360d7c3
commit
d10312b7fd
158 files changed
+3611
-3205
No files matched your search
@@ -16,7 +16,7 @@ fn ids(v: &Value) -> Vec<String> {
|
||||
|
||||
fn new_sketch() -> Session {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "SketchCreate", json!({"plane": "XY"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY"}));
|
||||
s
|
||||
}
|
||||
|
||||
@@ -27,21 +27,21 @@ fn sketch(s: &Session) -> solvecraft_sketch::Sketch {
|
||||
#[test]
|
||||
fn redundant_constraints_and_dimensions_are_refused_driven_ones_measure() {
|
||||
let mut s = new_sketch();
|
||||
let l = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [10, 0]], "infer": true}))["curves"])[0].clone();
|
||||
let l = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 0], [10, 0]], "infer": true}))["curves"])[0].clone();
|
||||
// Already horizontal (inferred).
|
||||
let e = s.execute("ConstraintHorizontalVertical", &json!({"line": l})).unwrap_err().to_string();
|
||||
let e = s.execute("sketch.constraint.horizontal_vertical", &json!({"line": l})).unwrap_err().to_string();
|
||||
assert!(e.contains("over-constrain"), "{e}");
|
||||
run(&mut s, "ConstraintCoincident", json!({"a": format!("{l}.start"), "b": "origin"}));
|
||||
run(&mut s, "SketchDimension", json!({"entities": [l], "value": 10}));
|
||||
run(&mut s, "sketch.constraint.coincident", json!({"a": format!("{l}.start"), "b": "origin"}));
|
||||
run(&mut s, "sketch.dimension", json!({"entities": [l], "value": 10}));
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
assert_eq!(si["dof"], 0, "{si}");
|
||||
// A second length on it over-constrains: refused, unless driven.
|
||||
assert!(s.execute("SketchDimension", &json!({"entities": [format!("{l}.start"), format!("{l}.end")]})).is_err());
|
||||
let d = run(&mut s, "SketchDimension", json!({"entities": [format!("{l}.start"), format!("{l}.end")], "driven": true}));
|
||||
assert!(s.execute("sketch.dimension", &json!({"entities": [format!("{l}.start"), format!("{l}.end")]})).is_err());
|
||||
let d = run(&mut s, "sketch.dimension", json!({"entities": [format!("{l}.start"), format!("{l}.end")], "driven": true}));
|
||||
assert_eq!(d["driven"], true);
|
||||
// The driven dimension follows the driving one.
|
||||
let pname = si["constraints"].as_array().unwrap().iter().find_map(|c| c["param"].as_str().map(str::to_string)).unwrap();
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": pname, "expression": "25 mm"}));
|
||||
run(&mut s, "parameters.change", json!({"name": pname, "expression": "25 mm"}));
|
||||
let g = run(&mut s, "sketch.glyphs", json!({}));
|
||||
let driven = g["glyphs"].as_array().unwrap().iter().find(|x| x["driven"] == true).unwrap().clone();
|
||||
assert!((driven["value"].as_f64().unwrap() - 25.0).abs() < 1e-7, "{driven}");
|
||||
@@ -53,9 +53,10 @@ fn curvature_polygon_arc_length_linear_diameter() {
|
||||
let mut s = new_sketch();
|
||||
// A horizontal line ending where a control-point spline starts: G2 keeps the spline's
|
||||
// start straight (zero curvature) and tangent.
|
||||
let l = ids(&run(&mut s, "DrawPolyline", json!({"points": [[-10, 0], [0, 0]], "infer": true}))["curves"])[0].clone();
|
||||
let sp = ids(&run(&mut s, "DrawCVMSpline3D", json!({"points": [format!("{l}.end"), [5, 2], [10, 6], [15, 15]]}))["curves"])[0].clone();
|
||||
run(&mut s, "ConstraintSmooth", json!({"a": l, "b": sp}));
|
||||
let l = ids(&run(&mut s, "sketch.line", json!({"points": [[-10, 0], [0, 0]], "infer": true}))["curves"])[0].clone();
|
||||
let sp =
|
||||
ids(&run(&mut s, "sketch.spline.control_point", json!({"points": [format!("{l}.end"), [5, 2], [10, 6], [15, 15]]}))["curves"])[0].clone();
|
||||
run(&mut s, "sketch.constraint.curvature", json!({"a": l, "b": sp}));
|
||||
let sk = sketch(&s);
|
||||
let pts: Vec<Vec2> = sk.curves[sk.curve_index(&sp).unwrap()].kind.point_ids().iter().map(|i| sk.point(*i).unwrap()).collect();
|
||||
// Tangent: first leg along +x; zero curvature: the second leg too (collinear first three).
|
||||
@@ -63,16 +64,16 @@ fn curvature_polygon_arc_length_linear_diameter() {
|
||||
assert!((pts[2] - pts[1]).cross(pts[1] - pts[0]).abs() < 1e-3, "{pts:?}");
|
||||
|
||||
// Polygon constraint on a rough quadrilateral: becomes a square-ish regular polygon.
|
||||
let q = run(&mut s, "DrawPolyline", json!({"points": [[100, 0], [111, 1], [110, 9], [99, 10]], "closed": true}));
|
||||
let q = run(&mut s, "sketch.line", json!({"points": [[100, 0], [111, 1], [110, 9], [99, 10]], "closed": true}));
|
||||
let ql = ids(&q["curves"]);
|
||||
run(&mut s, "SketchPolygonConstraintCmd", json!({"lines": ql}));
|
||||
run(&mut s, "sketch.constraint.polygon", json!({"lines": ql}));
|
||||
let sk = sketch(&s);
|
||||
let lens: Vec<f64> = ql.iter().map(|i| sk.polyline(sk.curve_index(i).unwrap())).map(|p| p[0].dist(p[p.len() - 1])).collect();
|
||||
assert!(lens.iter().all(|x| (x - lens[0]).abs() < 1e-6), "{lens:?}");
|
||||
|
||||
// Arc length.
|
||||
let a = ids(&run(&mut s, "ArcCenterTwoPoint", json!({"center": [0, 50], "start": [10, 50], "end": [0, 60]}))["curves"])[0].clone();
|
||||
run(&mut s, "SketchDimension", json!({"entities": [a], "type": "arc_length", "value": 20}));
|
||||
let a = ids(&run(&mut s, "sketch.arc.center_point", json!({"center": [0, 50], "start": [10, 50], "end": [0, 60]}))["curves"])[0].clone();
|
||||
run(&mut s, "sketch.dimension", json!({"entities": [a], "type": "arc_length", "value": 20}));
|
||||
let sk = sketch(&s);
|
||||
let ai = sk.curve_index(&a).unwrap();
|
||||
let len = match sk.segs(ai)[0] {
|
||||
@@ -82,10 +83,10 @@ fn curvature_polygon_arc_length_linear_diameter() {
|
||||
assert!((len - 20.0).abs() < 1e-6, "{len}");
|
||||
|
||||
// Linear diameter about a centerline.
|
||||
let cl = ids(&run(&mut s, "DrawPolyline", json!({"points": [[200, 0], [200, 50]]}))["curves"])[0].clone();
|
||||
let cl = ids(&run(&mut s, "sketch.line", json!({"points": [[200, 0], [200, 50]]}))["curves"])[0].clone();
|
||||
run(&mut s, "sketch.centerline", json!({"curves": [cl]}));
|
||||
run(&mut s, "DrawPoint", json!({"point": [207, 10], "id": "rim"}));
|
||||
let d = run(&mut s, "SketchDimension", json!({"entities": ["rim", cl], "value": 30}));
|
||||
run(&mut s, "sketch.point", json!({"point": [207, 10], "id": "rim"}));
|
||||
let d = run(&mut s, "sketch.dimension", json!({"entities": ["rim", cl], "value": 30}));
|
||||
assert_eq!(d["type"], "LinearDiameterDimension", "{d}");
|
||||
let sk = sketch(&s);
|
||||
let rim = sk.point(sk.point_index("rim").unwrap()).unwrap();
|
||||
@@ -98,7 +99,7 @@ fn curvature_polygon_arc_length_linear_diameter() {
|
||||
#[test]
|
||||
fn glyphs_and_snaps() {
|
||||
let mut s = new_sketch();
|
||||
let r = run(&mut s, "ShapeRectangleTwoPoint", json!({"p0": [0, 0], "p1": [20, 10]}));
|
||||
let r = run(&mut s, "sketch.rectangle.two_point", json!({"p0": [0, 0], "p1": [20, 10]}));
|
||||
let l = ids(&r["curves"]);
|
||||
let g = run(&mut s, "sketch.glyphs", json!({}));
|
||||
assert_eq!(g["glyphs"].as_array().unwrap().len(), 4);
|
||||
@@ -116,9 +117,9 @@ fn glyphs_and_snaps() {
|
||||
fn auto_constrain_fully_constrains_a_rough_sketch() {
|
||||
let mut s = new_sketch();
|
||||
// A slightly crooked closed rectangle and a circle inside.
|
||||
run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [40, 0.004], [40.003, 30], [0, 30.002]], "closed": true}));
|
||||
run(&mut s, "CircleCenterRadius", json!({"center": [20, 15], "radius": 5}));
|
||||
let r = run(&mut s, "SketchAutoConstraintAndDimCmd", json!({}));
|
||||
run(&mut s, "sketch.line", json!({"points": [[0, 0], [40, 0.004], [40.003, 30], [0, 30.002]], "closed": true}));
|
||||
run(&mut s, "sketch.circle.center", json!({"center": [20, 15], "radius": 5}));
|
||||
let r = run(&mut s, "sketch.auto_constrain", json!({}));
|
||||
assert_eq!(r["dof"], 0, "{r}");
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
assert_eq!(si["fully_constrained"], true, "{si}");
|
||||
@@ -127,9 +128,9 @@ fn auto_constrain_fully_constrains_a_rough_sketch() {
|
||||
assert!(names.iter().any(|n| n == "DiameterDimension"), "{names:?}");
|
||||
// From a datum, and finishing.
|
||||
let mut s = new_sketch();
|
||||
run(&mut s, "DrawPoint", json!({"point": [5, 5], "id": "d"}));
|
||||
run(&mut s, "DrawPolyline", json!({"points": [[10, 10], [20, 10]]}));
|
||||
let r = run(&mut s, "SketchAutoConstrainAndFinish", json!({"datum": "d"}));
|
||||
run(&mut s, "sketch.point", json!({"point": [5, 5], "id": "d"}));
|
||||
run(&mut s, "sketch.line", json!({"points": [[10, 10], [20, 10]]}));
|
||||
let r = run(&mut s, "sketch.finish_auto_constrain", json!({"datum": "d"}));
|
||||
assert!(s.active_sketch.is_none());
|
||||
assert!(r["added"].as_array().unwrap().len() >= 3, "{r}");
|
||||
}
|
||||
@@ -137,11 +138,11 @@ fn auto_constrain_fully_constrains_a_rough_sketch() {
|
||||
#[test]
|
||||
fn drawing_infers_tangent_and_perpendicular() {
|
||||
let mut s = new_sketch();
|
||||
let l1 = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [10, 10]], "infer": true}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("{l1}.end"), [20, 0]], "infer": true}));
|
||||
let l1 = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 0], [10, 10]], "infer": true}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.line", json!({"points": [format!("{l1}.end"), [20, 0]], "infer": true}));
|
||||
assert_eq!(r["constraints"].as_array().unwrap().len(), 1, "{r}");
|
||||
let a = ids(&run(&mut s, "ArcCenterTwoPoint", json!({"center": [50, 0], "start": [60, 0], "end": [50, 10]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("{a}.end"), [30, 10]], "infer": true}));
|
||||
let a = ids(&run(&mut s, "sketch.arc.center_point", json!({"center": [50, 0], "start": [60, 0], "end": [50, 10]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.line", json!({"points": [format!("{a}.end"), [30, 10]], "infer": true}));
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
let names: Vec<&str> = si["constraints"].as_array().unwrap().iter().map(|c| c["name"].as_str().unwrap()).collect();
|
||||
assert!(names.contains(&"Perpendicular") && names.contains(&"Tangent"), "{names:?} {r}");
|
||||
@@ -150,18 +151,18 @@ fn drawing_infers_tangent_and_perpendicular() {
|
||||
#[test]
|
||||
fn smart_constrain_and_driven_toggle() {
|
||||
let mut s = new_sketch();
|
||||
let a = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [10, 0.5]]}))["curves"])[0].clone();
|
||||
let b = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 5], [10, 6]]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "SketchConstrainer", json!({"entities": [a]}));
|
||||
let a = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 0], [10, 0.5]]}))["curves"])[0].clone();
|
||||
let b = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 5], [10, 6]]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.constrainer", json!({"entities": [a]}));
|
||||
assert_eq!(r["type"], "Horizontal");
|
||||
let r = run(&mut s, "SketchConstrainer", json!({"entities": [a, b]}));
|
||||
let r = run(&mut s, "sketch.constrainer", json!({"entities": [a, b]}));
|
||||
assert_eq!(r["type"], "Parallel");
|
||||
let c1 = ids(&run(&mut s, "CircleCenterRadius", json!({"center": [50, 0], "radius": 5}))["curves"])[0].clone();
|
||||
let c2 = ids(&run(&mut s, "CircleCenterRadius", json!({"center": [50.3, 0.2], "radius": 3}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "SketchConstrainer", json!({"entities": [c1, c2]}));
|
||||
let c1 = ids(&run(&mut s, "sketch.circle.center", json!({"center": [50, 0], "radius": 5}))["curves"])[0].clone();
|
||||
let c2 = ids(&run(&mut s, "sketch.circle.center", json!({"center": [50.3, 0.2], "radius": 3}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.constrainer", json!({"entities": [c1, c2]}));
|
||||
assert_eq!(r["type"], "Concentric");
|
||||
// Driven toggle.
|
||||
let d = run(&mut s, "SketchDimension", json!({"entities": [c1], "value": 10}));
|
||||
let d = run(&mut s, "sketch.dimension", json!({"entities": [c1], "value": 10}));
|
||||
let g = run(&mut s, "sketch.glyphs", json!({}));
|
||||
let did = g["glyphs"].as_array().unwrap().iter().find(|x| x["param"] == d["param"]).unwrap()["id"].as_str().unwrap().to_string();
|
||||
let r = run(&mut s, "sketch.toggle_driven", json!({"constraint": did}));
|
||||
@@ -174,8 +175,8 @@ fn smart_constrain_and_driven_toggle() {
|
||||
#[test]
|
||||
fn drawing_from_a_line_midpoint_keeps_it_there() {
|
||||
let mut s = new_sketch();
|
||||
let l = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [20, 0]]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("mid:{l}"), [10, 15]]}));
|
||||
let l = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 0], [20, 0]]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.line", json!({"points": [format!("mid:{l}"), [10, 15]]}));
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
assert!(si["constraints"].as_array().unwrap().iter().any(|c| c["name"] == "MidPoint"), "{si}");
|
||||
// Lengthen the first line: the second one's start follows the middle.
|
||||
@@ -191,10 +192,10 @@ fn drawing_from_a_line_midpoint_keeps_it_there() {
|
||||
#[test]
|
||||
fn drawing_onto_a_curve_keeps_the_point_on_it() {
|
||||
let mut s = new_sketch();
|
||||
let c = ids(&run(&mut s, "CircleCenterRadius", json!({"center": [0, 0], "radius": 10}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("on:{c}:7.2,7.1"), [30, 30]]}));
|
||||
let c = ids(&run(&mut s, "sketch.circle.center", json!({"center": [0, 0], "radius": 10}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "sketch.line", json!({"points": [format!("on:{c}:7.2,7.1"), [30, 30]]}));
|
||||
let n = ids(&r["curves"])[0].clone();
|
||||
run(&mut s, "SketchDimension", json!({"entities": [c], "value": 16}));
|
||||
run(&mut s, "sketch.dimension", json!({"entities": [c], "value": 16}));
|
||||
let sk = sketch(&s);
|
||||
let st = sk.resolve_point(&format!("{n}.start")).and_then(|i| sk.point(i)).unwrap();
|
||||
let cc = sk.center(sk.curve_index(&c).unwrap()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user