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 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-10-21 08:53:59 +02:00
commit ad6a7c072b
2 changed files with 17 additions and 1 deletions

View file

@ -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. // Like the picked: faces that face the same way, edges as long, points with as many edges.
auto App::selectSimilar() -> void { auto App::selectSimilar() -> void {
Object* o = editing(); Object* o = editing();
if (!o && mode_ == Mode::Object) { // whole objects: the others of the same shape (copies of one part: every bolt)
std::vector<const Object*> 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; if (!o) return;
const Mesh& m = o->mesh; const Mesh& m = o->mesh;
if (elem_ == Elem::Face) { if (elem_ == Elem::Face) {
@ -1668,6 +1683,7 @@ auto App::shortcuts(ImGuiIO& io) -> void {
if (key(ImGuiKey_Q)) setTool(Tool::Select); if (key(ImGuiKey_Q)) setTool(Tool::Select);
if (key(ImGuiKey_W)) setTool(Tool::Move); if (key(ImGuiKey_W)) setTool(Tool::Move);
if (key(ImGuiKey_E) && shift && mode_ == Mode::Edit) return creaseSelected(); 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_E)) setTool(Tool::Rotate);
if (key(ImGuiKey_R)) setTool(Tool::Scale); if (key(ImGuiKey_R)) setTool(Tool::Scale);
if (key(ImGuiKey_D)) setTool(Tool::Draw); if (key(ImGuiKey_D)) setTool(Tool::Draw);

View file

@ -441,7 +441,7 @@ auto App::buildCommands() -> void {
add("select.grow", "Select more (grow)", "Select", "Ctrl +", [this] { growSelection(); }, editing); add("select.grow", "Select more (grow)", "Select", "Ctrl +", [this] { growSelection(); }, editing);
add("select.shrink", "Select less (shrink)", "Select", "Ctrl -", [this] { shrinkSelection(); }, 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.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.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"); add("select.ring", "Select rings (across the picked edges)", "Select", "", [this] { loopsOfSelected(true); }, editing, "edge ring");
for (const auto& [t, n] : std::initializer_list<std::pair<SelShape, const char*>>{{SelShape::Box, "box"}, {SelShape::Brush, "brush"}, {SelShape::Lasso, "lasso"}}) for (const auto& [t, n] : std::initializer_list<std::pair<SelShape, const char*>>{{SelShape::Box, "box"}, {SelShape::Brush, "brush"}, {SelShape::Lasso, "lasso"}})