Merge remote-tracking branch 'origin/main' into feat/sketch-tools-return-ids

# Conflicts:
#	crates/engine/src/cmd/mod.rs
#	crates/engine/src/cmd/sketch.rs
#	crates/engine/src/cmd/sketch_create.rs
#	crates/engine/src/cmd/sketch_modify.rs
#	crates/engine/src/lib.rs
#	docs/book/src/guide/sketching.md
This commit is contained in:
CypherNaugh_0x committed 2026-10-11 13:07:50 +02:00
commit b93d4905ac
181 files changed
+29350 -1572

No files matched your search

+21 -7
View File
@@ -53,7 +53,7 @@ pub static COMMANDS: &[CommandSpec] = &[
.at("SKETCH", "CREATE")
.icon("spline")
.enabled(in_sketch)
.params(concat!("points: [[x,y] or point refs…] (2…500): the spline passes through them", created_doc!())),
.params(concat!("points: [[x,y] or point refs…] (2…500): the spline passes through them, periodic?: boolean (default false); periodic cubic fit closes smoothly through at least 3 distinct samples", created_doc!())),
CommandSpec::new("sketch.spline.control_point", "Control Point Spline", spline_cv3)
.at("SKETCH", "CREATE")
.icon("spline_cv")
@@ -165,7 +165,7 @@ fn blend(s: &mut Session, p: &Value) -> Result<Value> {
let first_new = sk.points.len();
let c1 = sk.add_point(qa + ta * (l / 3.0), None)?;
let c2 = sk.add_point(qb + tb * (l / 3.0), None)?;
let sp = sk.add_curve(CurveKind::Spline { pts: vec![pa, c1, c2, pb], control: true, degree: 3 }, None)?;
let sp = sk.add_curve(CurveKind::Spline { pts: vec![pa, c1, c2, pb], control: true, degree: 3, periodic: false }, None)?;
let cons = vec![add_c(sk, ConstraintKind::Tangent { a: ca, b: sp })?, add_c(sk, ConstraintKind::Tangent { a: cb, b: sp })?];
solve_new_only(sk, first_new);
Ok((ids_of(sk, &[sp]), cons))
@@ -250,10 +250,24 @@ fn point_list(sk: &mut Sketch, p: &Value, cmd: &str) -> Result<Vec<usize>> {
}
fn spline(s: &mut Session, p: &Value, cmd: &str, control: bool, degree: u8) -> Result<Value> {
let periodic = match p.get("periodic") {
None => false,
Some(Value::Bool(v)) => *v,
_ => return Err(bad(cmd, "periodic must be boolean")),
};
if periodic && (control || degree != 3) {
return Err(bad(cmd, "periodic mode requires a cubic fit spline"));
}
let p = &super::sketch_project::snap_points(s, p, cmd)?;
let (out, info) = edit(s, p, cmd, false, |sk, _| {
let pts = point_list(sk, p, cmd)?;
let c = sk.add_curve(CurveKind::Spline { pts, control, degree }, None)?;
let mut pts = point_list(sk, p, cmd)?;
if periodic
&& sk.point(*pts.first().ok_or_else(|| bad(cmd, "missing first point"))?)
!= sk.point(*pts.last().ok_or_else(|| bad(cmd, "missing last point"))?)
{
pts.push(*pts.first().ok_or_else(|| bad(cmd, "missing first point"))?);
}
let c = sk.add_curve(CurveKind::Spline { pts, control, degree, periodic }, None)?;
mark_construction(sk, &[c], p);
Ok((ids_of(sk, &[c]), Vec::new()))
})?;
@@ -342,12 +356,12 @@ fn leaving_dir(sk: &Sketch, ci: usize, pi: usize) -> Option<Vec2> {
None
}
}
CurveKind::Spline { ref pts, control, .. } => {
CurveKind::Spline { ref pts, control, periodic, .. } => {
let q: Vec<Vec2> = pts.iter().filter_map(|i| sk.point(*i)).collect();
if pts.last() == Some(&pi) {
solvecraft_sketch::spline_end_tangent(&q, control, true)
solvecraft_sketch::spline_end_tangent_mode(&q, control, periodic, true)
} else if pts.first() == Some(&pi) {
solvecraft_sketch::spline_end_tangent(&q, control, false).map(|t| -t)
solvecraft_sketch::spline_end_tangent_mode(&q, control, periodic, false).map(|t| -t)
} else {
None
}