fix(blend): add symmetric spine anchor conversion command (#2544)

This commit is contained in:
makesomethingshit
2026-10-18 01:11:38 +07:00
committed by bflatastic
parent 949473f1e3
commit f92c622e97
+41 -1
View File
@@ -14,7 +14,7 @@ use vectorcraft_doc::live::{
PreserveShape, Spine,
};
use vectorcraft_doc::{Appearance, Document, Node, NodeId, NodeKind, Selection};
use vectorcraft_geom::{Affine, PathData, Point, Vec2};
use vectorcraft_geom::{Affine, Anchor, PathData, Point, Vec2};
use super::edit::selected_roots;
use super::expand::gradient_sampler;
@@ -96,6 +96,15 @@ pub fn specs() -> Vec<CommandSpec> {
has_doc,
spine_move_anchor
),
cmd!(
"object.blend.spine.convertAnchor",
"Convert Spine Point",
[],
None,
"{id? (default: the selected blend), anchor: index, to: smooth|corner, x?, y?} convert a blend spine point: dragging a corner creates symmetric smooth handles, clicking a point with handles retracts both. Without x/y, smooth uses the neighbouring spine points",
has_doc,
spine_convert_anchor
),
cmd!(
"object.blend.spine.reshapeSegment",
"Reshape Spine Segment",
@@ -653,6 +662,37 @@ fn spine_move_anchor(s: &mut Session, p: &Value) -> Result<Value> {
ok()
}
fn spine_convert_anchor(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "object.blend.spine.convertAnchor";
let index = index_param(p, "anchor", C)?;
let smooth = match str_param(p, "to") {
Some("smooth") => true,
Some("corner") => false,
_ => return Err(bad(C, "to must be smooth or corner")),
};
let target = match (p.get("x"), p.get("y")) {
(None, None) => None,
(Some(_), Some(_)) => Some(finite_point(p, C)?),
_ => return Err(bad(C, "x and y must be given together")),
};
edit_spine(s, p, C, "Convert Spine Point", |sp, _, _| {
if smooth && target.is_none() {
if index >= sp.anchors.len() {
return Err(bad(C, "no such spine point"));
}
vectorcraft_tools::draw2::curvature_smooth(sp, index);
return Ok(());
}
let a = sp.anchors.get_mut(index).ok_or_else(|| bad(C, "no such spine point"))?;
match target {
Some(q) if smooth && q.distance(a.p) > 1e-9 => *a = Anchor::smooth(a.p, q),
_ => a.retract(),
}
Ok(())
})?;
ok()
}
fn spine_reshape_segment(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "object.blend.spine.reshapeSegment";
let seg = index_param(p, "segment", C)?;