diff --git a/.gitignore b/.gitignore index 8ba5bbc4f..3f66a360f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ src/OrcaSlicer-doc/ /deps/DL_CACHE **/.flatpak-builder/ resources/profiles/user/default -OrcaSlicer.code-workspace +*.code-workspace diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 38c9deb29..26a96ec9b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -2433,6 +2433,12 @@ void MainFrame::init_menubar_as_editor() }, "menu_remove", nullptr, [this](){return can_clone(); }, this); editMenu->AppendSeparator(); + append_menu_item(editMenu, wxID_ANY, _L("Duplicate Current Plate"), + _L("Duplicate the current plate"),[this](wxCommandEvent&) { + m_plater->duplicate_plate(); + }, + "menu_remove", nullptr, [this](){return true;}, this); + editMenu->AppendSeparator(); #else // BBS undo append_menu_item(editMenu, wxID_ANY, _L("Undo") + "\t" + ctrl + "Z", @@ -2530,6 +2536,13 @@ void MainFrame::init_menubar_as_editor() }, "", nullptr, [this](){return can_clone(); }, this); editMenu->AppendSeparator(); + append_menu_item(editMenu, wxID_ANY, _L("Duplicate Current Plate"), + _L("Duplicate the current plate"),[this, handle_key_event](wxCommandEvent&) { + m_plater->duplicate_plate(); + }, + "", nullptr, [this](){return true;}, this); + editMenu->AppendSeparator(); + #endif // BBS Select All diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index f99db5445..c8c4d0b6c 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2716,7 +2716,7 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve calc_vertex_for_number(0, false, m_plate_idx_icon); if (m_plater) { // calc vertex for plate name - generate_plate_name_texture(); + generate_plate_name_texture(); } } @@ -3654,6 +3654,38 @@ int PartPlateList::create_plate(bool adjust_position) return new_index; } + +int PartPlateList::duplicate_plate(int index) +{ + // create a new plate + int new_plate_index = create_plate(true); + PartPlate* old_plate = NULL; + PartPlate* new_plate = NULL; + old_plate = get_plate(index); + new_plate = get_plate(new_plate_index); + + // get the offset between plate centers + Vec3d plate_to_plate_offset = new_plate->m_origin - old_plate->m_origin; + + // iterate over all the objects in this plate + ModelObjectPtrs obj_ptrs = old_plate->get_objects_on_this_plate(); + for (ModelObject* object : obj_ptrs){ + // copy and move the object to the same relative position in the new plate + ModelObject* object_copy = m_model->add_object(*object); + int new_obj_id = new_plate->m_model->objects.size() - 1; + // go over the instances and pair with the object + for (size_t new_instance_id = 0; new_instance_id < object_copy->instances.size(); new_instance_id++){ + new_plate->obj_to_instance_set.emplace(std::pair(new_obj_id, new_instance_id)); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicate object into plate: index_pair [%1%,%2%], obj_id %3%") % new_obj_id % new_instance_id % object_copy->id().id; + } + } + new_plate->translate_all_instance(plate_to_plate_offset); + // update the plates + wxGetApp().obj_list()->reload_all_plates(); + return new_plate_index; +} + + //destroy print's objects and results int PartPlateList::destroy_print(int print_index) { @@ -4781,7 +4813,7 @@ void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& pr if (m_is_dark != last_dark_mode_status) { last_dark_mode_status = m_is_dark; generate_icon_textures(); - }else if(m_del_texture.get_id() == 0) + } else if(m_del_texture.get_id() == 0) generate_icon_textures(); for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) { int current_index = (*it)->get_index(); diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index e0b0e90ac..0f2a5f241 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -660,6 +660,9 @@ public: //create an empty plate and return its index int create_plate(bool adjust_position = true); + // duplicate plate + int duplicate_plate(int index); + //destroy print which has the index of print_index int destroy_print(int print_index); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 352dfe95a..203ba175a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2951,19 +2951,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D_canvas->Bind(EVT_GLCANVAS_PLATE_RIGHT_CLICK, &priv::on_plate_right_click, this); view3D_canvas->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); }); view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent& evt) { - //BBS arrage from EVT set default state. + //BBS arrange from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT); this->q->arrange(); }); view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_PARTPLATE, [this](SimpleEvent& evt) { - //BBS arrage from EVT set default state. + //BBS arrange from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_MENU); this->q->arrange(); }); view3D_canvas->Bind(EVT_GLCANVAS_ORIENT, [this](SimpleEvent& evt) { - //BBS oriant from EVT set default state. + //BBS orient from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT); this->q->orient(); }); view3D_canvas->Bind(EVT_GLCANVAS_ORIENT_PARTPLATE, [this](SimpleEvent& evt) { - //BBS oriant from EVT set default state. + //BBS orient from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_MENU); this->q->orient(); }); //BBS @@ -3002,11 +3002,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D_canvas->Bind(EVT_GLTOOLBAR_ADD_PLATE, &priv::on_action_add_plate, this); view3D_canvas->Bind(EVT_GLTOOLBAR_DEL_PLATE, &priv::on_action_del_plate, this); view3D_canvas->Bind(EVT_GLTOOLBAR_ORIENT, [this](SimpleEvent&) { - //BBS arrage from EVT set default state. + //BBS arrange from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT); this->q->orient(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { - //BBS arrage from EVT set default state. + //BBS arrange from EVT set default state. this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT); this->q->arrange(); }); @@ -13997,6 +13997,19 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi return ret; } +int Plater::duplicate_plate(int plate_index) +{ + int index = plate_index, ret; + if (plate_index == -1) + index = p->partplate_list.get_curr_plate_index(); + + ret = p->partplate_list.duplicate_plate(index); + + //need to call update + update(); + return ret; +} + //BBS: delete the plate, index= -1 means the current plate int Plater::delete_plate(int plate_index) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 109e7845d..0b25c4245 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -599,6 +599,7 @@ public: int select_plate_by_hover_id(int hover_id, bool right_click = false, bool isModidyPlateName = false); //BBS: delete the plate, index= -1 means the current plate int delete_plate(int plate_index = -1); + int duplicate_plate(int plate_index = -1); //BBS: select the sliced plate by index int select_sliced_plate(int plate_index); //BBS: set bed positions