Merge pull request #1171 from storytold/fix/1111-mesh-selection-grid

#1111: a selected gradient mesh shows its mesh lines and points
This commit is contained in:
BFlat 2026-10-11 17:36:34 +07:00 committed by GitHub
commit 1637165600
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 3 deletions

File diff suppressed because one or more lines are too long

View File

@ -1238,6 +1238,8 @@ fn node_outline(n: &Node) -> BezPath {
[b, c, d].into_iter().for_each(|q| bp.line_to(q));
bp.close_path();
}
// A gradient mesh shows its mesh lines (#1111).
NodeKind::Mesh(m) => bp.extend(m.lines().to_bezpath()),
// An envelope shows its mesh (or top object), not its content.
NodeKind::Envelope { .. } => {
if let Some((lines, _)) = vectorcraft_doc::live::envelope_overlay(c) {
@ -1632,9 +1634,15 @@ fn selection_overlay(app: &mut VectorcraftApp, p: &egui::Painter, xf: &Xf) {
let partial = st.selection.partial(*id);
// Path outlines.
stroke_path(p, &node_outline(n), xf, Stroke::new(1.0, color));
// Anchors (and handles for selected anchors in direct mode); a mesh envelope's points.
// Anchors (and handles for selected anchors in direct mode); a gradient mesh's or a mesh
// envelope's points.
walk_drawn(n, &mut |c| {
if let Some((_, Some(grid))) = vectorcraft_doc::live::envelope_overlay(c) {
let envelope = vectorcraft_doc::live::envelope_overlay(c).and_then(|(_, grid)| grid);
let grid = match &c.kind {
NodeKind::Mesh(m) => Some(m),
_ => envelope.as_ref(),
};
if let Some(grid) = grid {
for q in &grid.points {
anchor_square(p, xf.to_screen(q.p), color, false, anchor(direct));
}
@ -2548,6 +2556,34 @@ mod tests {
assert!(points > 200 && squares > 200, "{points} outline points, {squares} squares");
}
/// #1111: a selected gradient mesh shows its mesh lines and points to the selection tools, not
/// only to the Mesh tool.
#[test]
fn a_selected_gradient_mesh_shows_its_lines_and_points() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
app.session.execute("shape.rectangle", &json!({"x": 20, "y": 20, "width": 200, "height": 100})).unwrap();
app.session.execute("object.mesh.create", &json!({"rows": 2, "cols": 2})).unwrap();
let ctx = egui::Context::default();
let drawn = |app: &mut VectorcraftApp| {
frame(app, &ctx, vec![]);
let shapes = shapes(app, &ctx);
let lines = shapes.iter().filter(|s| matches!(s, Shape::Path(ps) if ps.points.len() > 1)).count();
(lines, shapes.iter().filter(|s| matches!(s, Shape::Rect(_))).count())
};
let (none_lines, none_points) = {
app.session.execute("select.none", &json!({})).unwrap();
drawn(&mut app)
};
for tool in ["selection", "directSelection"] {
app.select_tool(tool);
app.session.execute("select.all", &json!({})).unwrap();
let (lines, points) = drawn(&mut app);
// The outline, two inner lines each way; the 3 × 3 points.
assert!(lines >= none_lines + 3 && points >= none_points + 9, "{tool}: {lines} lines, {points} points");
}
}
/// #541: the key object's outline is drawn thicker than the rest of the selection's.
#[test]
fn the_key_object_has_a_thicker_outline() {