From 6c59898ac09c6bb9d630dcc83cd3aafda5754129 Mon Sep 17 00:00:00 2001 From: Tommaso Bianchi Date: Sun, 2 Aug 2026 09:57:53 +0200 Subject: [PATCH] Design: pointing at part of a body is pointing at the body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tommaso: "i deleted a body using rubber band selection, but this is not intuitive as all the ux revolves around clicking". Correct on both counts, and a correction to what I said last round: the rubber band IS implemented and shipping (pick_bodies_in_rectangle, m_rubber, the drag branch in on_mouse). What is unbound is whole-body picking via CLICK; I read the comment about the click path and wrongly generalised it to the gesture as a whole. The handlers were never the problem either. Move, Mirror, Cut, Mass and Colour all resolve their target through selected_body_default() / m_sel_solid_body, and that is already set when you click a FACE — level >= 1 records the body. They would have worked from a click all along. The only thing keeping them out was the atlas gate: accepts listed body_solid and no face kind, so offer_selection_kind() returning FacePlanar filtered the rows away. This is therefore an atlas-only change, no handler edits. Cut, Split, Mirror, Transform, Mass and Colour now accept face/edge/vertex as well, matching what Delete Body already did. Edges and vertices are included deliberately, not just faces: a click resolves to a vertex, an edge or a face depending on where inside the pixel it lands, so accepting only faces would make Move vanish whenever you clicked near a corner — a flicker that reads as a bug and gets reported as "sometimes it works". NOT widened: Extrude on a face means push/pull THAT face, and Thicken consumes the face you point at. Both have genuine face-specific meaning, so widening them would change what they do rather than where they can be reached from. The rubber band keeps its job — it is still the only way to take a body without also naming one of its faces. It just stops being the only door. Verified on both rigs from a plain face click: Transform > Move opens with Body = Extrude2 (resolved from the face pick), Modify > Edit / Delete Face / Colour / Delete Body, and Reference > Mass. --- docs/ux/tool_atlas.json | 48 +++++++++++++++++++++++++++++----- src/slic3r/GUI/DesignOffer.hpp | 12 ++++----- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/docs/ux/tool_atlas.json b/docs/ux/tool_atlas.json index ec6ce04986..fb3399b14b 100644 --- a/docs/ux/tool_atlas.json +++ b/docs/ux/tool_atlas.json @@ -558,7 +558,13 @@ "mcp": null, "accepts": [ "body_solid", - "datum_plane" + "datum_plane", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 @@ -577,7 +583,13 @@ "feature": "Cut", "mcp": "split", "accepts": [ - "body_solid" + "body_solid", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 @@ -725,7 +737,13 @@ "mcp": "mirror", "accepts": [ "body_solid", - "datum_plane" + "datum_plane", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 @@ -766,7 +784,13 @@ "accepts": [ "body_solid", "body_sheet", - "art" + "art", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 @@ -954,7 +978,13 @@ "feature": null, "mcp": "mass_properties", "accepts": [ - "body_solid" + "body_solid", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 @@ -1040,7 +1070,13 @@ "mcp": null, "accepts": [ "body_solid", - "body_sheet" + "body_sheet", + "face_planar", + "face_cyl", + "face_other", + "edge_str", + "edge_circ", + "vertex" ], "needs": { "bodies": 1 diff --git a/src/slic3r/GUI/DesignOffer.hpp b/src/slic3r/GUI/DesignOffer.hpp index 1a00098c25..9213dfef0b 100644 --- a/src/slic3r/GUI/DesignOffer.hpp +++ b/src/slic3r/GUI/DesignOffer.hpp @@ -99,17 +99,17 @@ static const OfferVerb kOfferVerbs[] = { {"hole", "Hole", 2, "Shift+H", "key:S+H", "Pick a face or a plane to drill into", 0x00000402u, 1, 0, false, false, nullptr, "design_hole", "Drill a hole, centred on a picked face or placed on a plane"}, {"thread", "Thread", 2, "Shift+T", "key:S+T", "Pick a cylindrical surface (bore / outer) or a circular edge for a thread", 0x00000024u, 1, 0, false, false, nullptr, "design_thread", "Thread a cylindrical surface (inner bore / outer) or a circular edge"}, {"shell", "Shell", 2, "Shift+K", "key:S+K", "Shell needs a solid body", 0x00000082u, 1, 0, false, false, nullptr, "design_shell", "Hollow the body to a wall thickness, opening a picked face"}, - {"cut", "Cut", 2, "Shift+X", "key:S+X", "Create a solid body to cut first", 0x00000480u, 1, 0, false, false, nullptr, "design_cut", "Trim the body with a plane — drag the offset arrow; keep one half or both"}, - {"split", "Split", 2, nullptr, nullptr, "Split needs a solid body", 0x00000080u, 1, 0, false, false, nullptr, nullptr, "Split the body along a picked face into two solids"}, + {"cut", "Cut", 2, "Shift+X", "key:S+X", "Create a solid body to cut first", 0x000004feu, 1, 0, false, false, nullptr, "design_cut", "Trim the body with a plane — drag the offset arrow; keep one half or both"}, + {"split", "Split", 2, nullptr, nullptr, "Split needs a solid body", 0x000000feu, 1, 0, false, false, nullptr, nullptr, "Split the body along a picked face into two solids"}, {"fillet", "Fillet", 3, "Shift+F", "btn:dress#0", "Pick an edge to round", 0x000000b2u, 1, 0, false, false, nullptr, "design_filletedge", "Pick an edge, then drag the radius arrow or type it"}, {"chamfer", "Chamfer", 3, nullptr, "btn:dress#1", "Pick an edge to bevel", 0x000000b2u, 1, 0, false, false, nullptr, "design_chamfer", "Pick an edge, then drag the distance arrow or type it"}, {"draft", "Draft", 3, "Shift+D", "key:S+D", "Pick a face to taper", 0x0000000au, 1, 0, false, false, nullptr, "design_draft", "Tilt a picked face by a draft angle"}, {"surf_offset", "Surface Offset", 3, nullptr, "fly:surface#4", "target is not a sheet body", 0x00000100u, 0, 0, true, false, nullptr, "design_offset", "Offset a sheet body's shell by a signed distance"}, {"pattern", "Linear pattern", 4, "Shift+N", "btn:pat#0", "Create a solid body to pattern first", 0x00006082u, 1, 0, false, false, nullptr, "design_array", "Repeat the body along a direction — drag the spacing, set the count"}, {"pattern_circular", "Circular pattern", 4, nullptr, "btn:pat#1", "Create a solid body to pattern first", 0x00006082u, 1, 0, false, false, nullptr, "design_polararray", "Repeat the body around an axis — set the count and sweep"}, - {"mirror", "Mirror", 4, "Shift+Z", "key:S+Z", "Mirror needs a body — add or import one first", 0x00000480u, 1, 0, false, false, nullptr, "design_mirror", "Reflect a body about a plane"}, + {"mirror", "Mirror", 4, "Shift+Z", "key:S+Z", "Mirror needs a body — add or import one first", 0x000004feu, 1, 0, false, false, nullptr, "design_mirror", "Reflect a body about a plane"}, {"pat_curve", "Pattern on Curve", 4, nullptr, nullptr, "Pattern on curve needs a body and a curve", 0x00000090u, 1, 0, false, false, nullptr, nullptr, "Repeat the body along a picked curve"}, - {"transform", "Move", 5, "Shift+Y", "key:S+Y", "Transform needs a body — add or import one first", 0x00002180u, 1, 0, false, false, nullptr, "design_move", "Move and/or rotate an existing body"}, + {"transform", "Move", 5, "Shift+Y", "key:S+Y", "Transform needs a body — add or import one first", 0x000021feu, 1, 0, false, false, nullptr, "design_move", "Move and/or rotate an existing body"}, {"mate", "Mate", 5, nullptr, "fly:placement#2", "A mate needs two coordinate systems", 0x00001202u, 2, 0, false, false, nullptr, "design_c_coincident", "Assembly: align two CoordSys features (fastened, planar, revolute, slider, cylindrical)"}, {"align", "Align to", 5, nullptr, nullptr, "Align needs a body", 0x00000002u, 1, 0, false, false, nullptr, nullptr, "Align the body to a picked face or plane"}, {"plane", "Plane", 6, "Shift+P", "key:S+P", nullptr, 0x00000453u, 0, 0, false, false, nullptr, "design_plane", "Reference plane (offset / tilt / midplane / tangent / two edges / coincident)"}, @@ -118,11 +118,11 @@ static const OfferVerb kOfferVerbs[] = { {"helix", "Helix", 6, nullptr, "fly:plane#3", nullptr, 0x00000405u, 0, 0, false, false, nullptr, "design_thread", "Helical curve (spring path) — use as a sweep path for coils / springs / augers"}, {"project", "Project", 6, nullptr, "fly:plane#4", "Project needs a body — add or import one first", 0x00000482u, 1, 0, false, false, nullptr, "design_sketch", "Project body edges onto a plane as sketch entities"}, {"measure", "Measure", 6, nullptr, nullptr, nullptr, 0x000b03feu, 0, 0, false, false, nullptr, nullptr, "Measure between the picked points, edges or faces"}, - {"mass_props", "Mass", 6, nullptr, "btn:mass", nullptr, 0x00000080u, 1, 0, false, false, nullptr, "info", "Report the volume and surface area of the selected body"}, + {"mass_props", "Mass", 6, nullptr, "btn:mass", nullptr, 0x000000feu, 1, 0, false, false, nullptr, "info", "Report the volume and surface area of the selected body"}, {"interference", "Interference", 6, nullptr, nullptr, nullptr, 0x00000200u, 2, 0, false, false, nullptr, nullptr, "Check whether two bodies overlap — reports, changes nothing"}, {"edit_feature", "Edit", 7, nullptr, "btn:edit", nullptr, 0x00007d8eu, 0, 0, false, false, nullptr, "design_edit", "Reopen the selected feature to change what it was made from"}, {"delete_face", "Delete Face", 7, nullptr, "fly:dressup#3", "Delete Face needs a body — add or import one first", 0x0000000eu, 1, 0, false, false, nullptr, "design_delete", "Remove faces from a body and heal the solid"}, - {"colour", "Colour", 7, nullptr, "btn:colour", nullptr, 0x00000180u, 1, 0, false, false, nullptr, "color_palette", "Set the selected body's display colour"}, + {"colour", "Colour", 7, nullptr, "btn:colour", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "color_palette", "Set the selected body's display colour"}, {"delete", "Delete", 7, "Del", "btn:delete", nullptr, 0x000f7c00u, 0, 0, false, false, nullptr, "design_delete", "Delete what is selected"}, {"delete_body", "Delete Body", 7, nullptr, "btn:delete_body", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "design_delete", "Delete this whole body — removes the feature it was made from"}, {"sk_line_t", "Line", 0, "L", "key:L", nullptr, 0x000f8000u, 0, 0, false, true, "Line", "design_line", "Line — click start, then end"},