From e670cd849489311fd32e1b72849d3eaced66e2df Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Tue, 25 Feb 2025 10:41:14 +0800 Subject: [PATCH] NEW:add "Sub merge" function jira: github 5855 Change-Id: I7f21a0340245aec4d47f56b2f0584a5cf08d81f7 --- src/slic3r/GUI/GUI_Factories.cpp | 40 ++++++++++++++++- src/slic3r/GUI/GUI_Factories.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 74 +++++++++++++++++++++++++++++++ src/slic3r/GUI/GUI_ObjectList.hpp | 1 + 4 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 6395895e5..126e00434 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -1600,12 +1600,26 @@ wxMenu* MenuFactory::multi_selection_menu() wxDataViewItemArray sels; obj_list()->GetSelections(sels); bool multi_volume = true; - + int count = 0; + int obj_idx = -1; for (const wxDataViewItem& item : sels) { multi_volume = list_model()->GetItemType(item) & itVolume; if (!(list_model()->GetItemType(item) & (itVolume | itObject | itInstance))) // show this menu only for Objects(Instances mixed with Objects)/Volumes selection return nullptr; + if (multi_volume) { + auto temp_obj_idx = obj_list()->GetModel()->GetObjectIdByItem(item); + if (temp_obj_idx >= 0 && temp_obj_idx != obj_idx) { + if (obj_idx == -1) { + obj_idx = temp_obj_idx; + } + else { + multi_volume = false; + break; + } + } + } + count++; } wxMenu* menu = new MenuWithSeparators(); @@ -1632,6 +1646,10 @@ wxMenu* MenuFactory::multi_selection_menu() } else { append_menu_item_center(menu); + auto mo = (*obj_list()->objects())[obj_idx]; + if (count < mo->volumes.size()) { + append_menu_item_sub_merge(menu); + } append_menu_item_fix_through_netfabb(menu); //append_menu_item_simplify(menu); append_menu_item_delete(menu); @@ -1787,6 +1805,26 @@ void MenuFactory::append_menu_item_center(wxMenu* menu) }, m_parent); } +void MenuFactory::append_menu_item_sub_merge(wxMenu *menu) +{ + append_menu_item( + menu, wxID_ANY, _L("Sub merge"), "", + [this](wxCommandEvent &) { + obj_list()->add_new_model_object_from_old_object(); + }, + "", nullptr, + []() { + if (plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasView3D) + return false; + else { + if (obj_list()->has_selected_cut_object()) + return false; + return true; + } + }, + m_parent); +} + void MenuFactory::append_menu_item_per_object_process(wxMenu* menu) { const std::vector names = { _L("Edit Process Settings"), _L("Edit Process Settings") }; diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index f2b1510fe..35ed8df99 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -171,6 +171,7 @@ private: void append_menu_item_clone(wxMenu* menu); void append_menu_item_simplify(wxMenu* menu); void append_menu_item_center(wxMenu* menu); + void append_menu_item_sub_merge(wxMenu *menu); void append_menu_item_per_object_process(wxMenu* menu); void append_menu_item_per_object_settings(wxMenu* menu); void append_menu_item_change_filament(wxMenu* menu); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index ee1127db5..886042992 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2362,6 +2362,80 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode } } +void GUI::ObjectList::add_new_model_object_from_old_object() { + const Selection &selection = scene_selection(); + int instance_idx = *selection.get_instance_idxs().begin(); + assert(instance_idx != -1); + if (instance_idx == -1) + return; + wxDataViewItemArray sels; + GetSelections(sels); + if (sels.IsEmpty()) return; + int obj_idx = -1; + std::vector vol_idxs; + for (wxDataViewItem item : sels) { + const int temp_obj_idx = m_objects_model->GetObjectIdByItem(item); + if (temp_obj_idx < 0) //&& object(obj_idx)->is_cut() + return; + obj_idx = temp_obj_idx; + const int vol_idx = m_objects_model->GetVolumeIdByItem(item); + vol_idxs.emplace_back(vol_idx); + } + if (vol_idxs.empty()) { + return; + } + take_snapshot("Add new model object"); + wxBusyCursor cursor; + std::sort(vol_idxs.begin(), vol_idxs.end()); + ModelVolumePtrs sel_volumes; + auto mo = (*m_objects)[obj_idx]; + for (int i = vol_idxs.size() - 1; i >= 0; i--) { + if (vol_idxs[i] > mo->volumes.size()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "check error:array bound"; + continue; + } + auto vol_idx = vol_idxs[i]; + auto mv = mo->volumes[vol_idx]; + sel_volumes.emplace_back(mv); + mo->volumes.erase(mo->volumes.begin() + vol_idx); + } + for (int i = vol_idxs.size() - 1; i >= 0; i--) { + auto vol_idx = vol_idxs[i]; + delete_volume_from_list(obj_idx, vol_idx); + } + // Add mesh to model as a new object + Model &model = wxGetApp().plater()->model(); + + std::vector object_idxs; + ModelObject * new_object = model.add_object(); + new_object->name = into_u8("Sub merge"); + new_object->add_instance(); // each object should have at least one instance + int min_extruder = (int) EnforcerBlockerType::ExtruderMax - 1; + for (auto mv : sel_volumes) { + new_object->add_volume(*mv, mv->type()); + auto option = mv->config.option("extruder"); + if (option) { + auto volume_extruder_id = (dynamic_cast(option))->getInt(); + if (min_extruder > volume_extruder_id) { + min_extruder = volume_extruder_id; + } + } + } + new_object->sort_volumes(true); + // set a default extruder value, since user can't add it manually + new_object->config.set_key_value("extruder", new ConfigOptionInt(min_extruder)); + new_object->invalidate_bounding_box(); + new_object->instances[0]->set_transformation(mo->instances[0]->get_transformation()); + // BBS: backup + Slic3r::save_object_mesh(*new_object); + new_object->ensure_on_bed(); + // BBS init assmeble transformation + new_object->get_model()->set_assembly_pos(new_object); + object_idxs.push_back(model.objects.size() - 1); + paste_objects_into_list(object_idxs); + wxGetApp().mainframe->update_title(); +} + void ObjectList::switch_to_object_process() { wxGetApp().params_panel()->switch_to_object(true); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 8f5c2d833..e78820974 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -288,6 +288,7 @@ public: //void load_part(ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); + void add_new_model_object_from_old_object(); void load_shape_object(const std::string &type_name); void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true); // BBS