Mesh: a color at a mesh envelope's point records no undo step

A mesh envelope's points carry no color, so object.mesh.addLine with
a color at a point the envelope already has changes nothing. It now
compares only the envelope's points and handles and records no undo
step. The command text and docs/mcp.md say so.
This commit is contained in:
dotCooCoo
2026-11-12 18:23:31 -08:00
parent fe1d56f339
commit 7380b2475d
4 changed files with 13 additions and 5 deletions
+1 -1
View File
@@ -290,7 +290,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Add Mesh Line",
[],
None,
"{id, x, y, color? (#rrggbbaa and #rgba are refused), keepModel?: bool (as paint.setFill), tolerance?: pt (0)} add a row and a column through (x, y), inside or on the edge, to a gradient mesh (new point in `color`) or a mesh envelope; a point outside within `tolerance` of the edge adds them through the nearest point of the edge; at a point that is already a mesh point it adds no line, and records no undo step unless `color` changes it → {index}",
"{id, x, y, color? (#rrggbbaa and #rgba are refused), keepModel?: bool (as paint.setFill), tolerance?: pt (0)} add a row and a column through (x, y), inside or on the edge, to a gradient mesh (new point in `color`) or a mesh envelope; a point outside within `tolerance` of the edge adds them through the nearest point of the edge; at a point that is already a mesh point it adds no line, and records no undo step unless `color` changes a gradient mesh's point (a mesh envelope's points have no color) → {index}",
has_doc,
mesh_add_line
),
+5 -2
View File
@@ -298,13 +298,16 @@ pub(super) fn mesh_add_line(s: &mut Session, p: &Value) -> Result<Value> {
}
// The lines are added to a copy of the object. A point that is already a mesh point adds none:
// when its color stays too, nothing changes and no undo step is recorded. The grid is compared,
// not the node: a mesh envelope stored without handles takes them in any edit.
// not the node: a mesh envelope stored without handles takes them in any edit, and keeps no
// colors, so only its points and handles count.
let orig = s.doc()?.doc.node(id).ok_or(EngineError::NoNode(id))?.kind.clone();
let colored = matches!(orig, NodeKind::Mesh(_));
let mut kind = orig.clone();
let (i, same) = edit_kind(&mut kind, C, true, |m| {
let before = m.clone();
let i = add(m)?;
Ok((i, *m == before))
let shape = |g: &GradientMesh| (g.rows, g.cols, g.points.iter().map(|q| (q.p, q.handles)).collect::<Vec<_>>());
Ok((i, if colored { *m == before } else { shape(m) == shape(&before) }))
})?;
if same {
return Ok(json!({ "index": i }));
+5 -1
View File
@@ -124,7 +124,8 @@ fn reset_with_warp_and_mesh_switch_the_kind_and_keep_the_content() {
}
/// `object.mesh.addLine` at a point a mesh envelope already has (one stored without handles) adds
/// no line and records no undo step; a point between its lines adds them as one step.
/// no line and records no undo step, with or without a `color`; a point between its lines adds
/// them as one step.
#[test]
fn mesh_envelope_add_line_at_a_mesh_point_records_no_undo_step() {
let mut s = session();
@@ -137,6 +138,9 @@ fn mesh_envelope_add_line_at_a_mesh_point_records_no_undo_step() {
s.execute("object.mesh.addLine", &json!({"id": e.0, "x": x, "y": y})).unwrap();
assert_eq!((kind(&s, e), undo_len(&s)), (before.clone(), n), "({x}, {y}): nothing changed");
}
// An envelope's points carry no color, so a color there changes nothing either.
s.execute("object.mesh.addLine", &json!({"id": e.0, "x": 200, "y": 150, "color": "#00ff00"})).unwrap();
assert_eq!((kind(&s, e), undo_len(&s)), (before.clone(), n), "a color changes nothing");
s.execute("object.mesh.addLine", &json!({"id": e.0, "x": 150, "y": 125})).unwrap();
assert!(matches!(kind(&s, e), EnvelopeKind::Mesh { rows: 3, cols: 3, .. }), "{:?}", kind(&s, e));
assert_eq!(undo_len(&s), n + 1);
+2 -1
View File
@@ -9628,7 +9628,8 @@ right/left/down/up; none stored means the smooth mesh through the points, as old
shows its mesh; the Mesh tool and Direct Selection drag its points and the clicked point's handles, and the Mesh tool
adds a row and a column where it clicks inside. `object.mesh.addLine`, and `object.mesh.create` with `at`, take a point exactly on
the mesh's outline (within a millionth of a point) on any side without `tolerance`; a point outside needs `tolerance`. `object.mesh.addLine` at a point that is already a mesh
point adds no line and records no undo step unless its `color` changes the point. `press_key` Escape during a drag of a point or handle of a mesh
point adds no line and records no undo step unless its `color` changes a gradient mesh's point (a mesh envelope's points
have no color). `press_key` Escape during a drag of a point or handle of a mesh
envelope or a gradient mesh cancels it: the point goes back and no undo step is added. The Control bar shows Edit Envelope / Edit Contents, the warp's
style, orientation, bend and distortions (or the mesh's rows and columns), Reset (an unbent warp, a flat mesh) and
Envelope Options.