From ad6a7c072b4b6604c65cfdd2a6cb19b112786aa3 Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Wed, 21 Oct 2026 08:53:59 +0200 Subject: [PATCH] Select similar on whole objects too (the others of the same shape: every bolt); Shift+G was only shown, now it's a key Co-Authored-By: Claude Opus 5.5 --- src/app.cpp | 16 ++++++++++++++++ src/app_panels.cpp | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/app.cpp b/src/app.cpp index c5c2986..6ac1b9f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1255,6 +1255,21 @@ auto App::shrinkSelection() -> void { // Like the picked: faces that face the same way, edges as long, points with as many edges. auto App::selectSimilar() -> void { Object* o = editing(); + if (!o && mode_ == Mode::Object) { // whole objects: the others of the same shape (copies of one part: every bolt) + std::vector like; + for (const Object& p : scene_.objects) + if (selected_.count(p.id)) like.push_back(&p); + if (like.empty()) return say("Pick an object first"); + auto same = [](const Object& a, const Object& b) { + if (!a.recipe.empty() || !b.recipe.empty()) return a.recipe == b.recipe && a.settings == b.settings; + return a.mesh.verts.size() == b.mesh.verts.size() && a.mesh.faces.size() == b.mesh.faces.size(); + }; + const size_t before = selected_.size(); + for (const Object& p : scene_.objects) + if (p.visible && !p.locked && std::any_of(like.begin(), like.end(), [&](const Object* l) { return same(*l, p); })) selected_.insert(p.id); + const size_t more = selected_.size() - before; + return say(more ? std::format("{} more of the same shape picked", more) : "No others of the same shape"); + } if (!o) return; const Mesh& m = o->mesh; if (elem_ == Elem::Face) { @@ -1668,6 +1683,7 @@ auto App::shortcuts(ImGuiIO& io) -> void { if (key(ImGuiKey_Q)) setTool(Tool::Select); if (key(ImGuiKey_W)) setTool(Tool::Move); if (key(ImGuiKey_E) && shift && mode_ == Mode::Edit) return creaseSelected(); + if (key(ImGuiKey_G) && shift) return selectSimilar(); if (key(ImGuiKey_E)) setTool(Tool::Rotate); if (key(ImGuiKey_R)) setTool(Tool::Scale); if (key(ImGuiKey_D)) setTool(Tool::Draw); diff --git a/src/app_panels.cpp b/src/app_panels.cpp index c36d4ad..b0f4332 100644 --- a/src/app_panels.cpp +++ b/src/app_panels.cpp @@ -441,7 +441,7 @@ auto App::buildCommands() -> void { add("select.grow", "Select more (grow)", "Select", "Ctrl +", [this] { growSelection(); }, editing); add("select.shrink", "Select less (shrink)", "Select", "Ctrl -", [this] { shrinkSelection(); }, editing); add("select.linked", "Select everything joined to it", "Select", "L", [this] { selectLinked(); }, editing, "linked connected"); - add("select.similar", "Select similar faces (facing the same way)", "Select", "Shift+G", [this] { selectSimilar(); }, editing, "same normal size"); + add("select.similar", "Select similar (faces the same way; objects of the same shape)", "Select", "Shift+G", [this] { selectSimilar(); }, [=] { return editing() || picked(); }, "same normal size copies"); add("select.loop", "Select whole loops (of the picked edges)", "Select", "", [this] { loopsOfSelected(false); }, editing, "edge loop"); add("select.ring", "Select rings (across the picked edges)", "Select", "", [this] { loopsOfSelected(true); }, editing, "edge ring"); for (const auto& [t, n] : std::initializer_list>{{SelShape::Box, "box"}, {SelShape::Brush, "brush"}, {SelShape::Lasso, "lasso"}})