diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index eff62faab..d681ba1d1 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -400,10 +400,18 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print const PrintInstance *print_instance; BoundingBox bounding_box; Polygon hull_polygon; - int index; + int object_index; double arrange_score; double height; }; + auto find_object_index = [](const Model& model, const ModelObject* obj) { + for (int index = 0; index < model.objects.size(); index++) + { + if (model.objects[index] == obj) + return index; + } + return -1; + }; std::vector print_instance_with_bounding_box; { // sequential_print_horizontal_clearance_valid @@ -481,6 +489,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print } struct print_instance_info print_info {&instance, convex_hull.bounding_box(), convex_hull}; print_info.height = instance.print_object->height(); + print_info.object_index = find_object_index(print.model(), print_object->model_object()); print_instance_with_bounding_box.push_back(std::move(print_info)); convex_hulls_other.emplace_back(std::move(convex_hull)); } @@ -500,6 +509,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print double hc2 = scale_(print.config().extruder_clearance_height_to_rod); // height to rod double printable_height = scale_(print.config().printable_height); +#if 0 //do not sort anymore, use the order in object list auto bed_points = get_bed_shape(print_config); float bed_width = bed_points[1].x() - bed_points[0].x(); // 如果扩大以后的多边形的距离小于这个值,就需要严格保证从左到右的打印顺序,否则会撞工具头右侧 @@ -591,7 +601,16 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print for (auto &inst : print_instance_with_bounding_box) BOOST_LOG_TRIVIAL(debug) << "after sorting print_instance " << inst.print_instance->model_instance->get_object()->name << ", score: " << inst.arrange_score << ", height:"<< inst.height; +#else + // sort the print instance + std::sort(print_instance_with_bounding_box.begin(), print_instance_with_bounding_box.end(), + [](print_instance_info& l, print_instance_info& r) {return l.object_index < r.object_index;}); + for (auto &inst : print_instance_with_bounding_box) + BOOST_LOG_TRIVIAL(debug) << "after sorting print_instance " << inst.print_instance->model_instance->get_object()->name << ", object_index: " << inst.object_index + << ", height:"<< inst.height; + +#endif // sequential_print_vertical_clearance_valid { // Ignore the last instance printed. @@ -621,7 +640,6 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print break; }*/ - // if objects are not overlapped on y-axis, they will not collide even if they are taller than extruder_clearance_height_to_rod int print_instance_count = print_instance_with_bounding_box.size(); std::map> too_tall_instances; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f08bb740b..3074fea77 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -810,13 +810,8 @@ void GLCanvas3D::Labels::render(const std::vector& sorted_ } // force re-render while the windows gets to its final size (it takes several frames) -#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT if (ImGui::GetWindowContentRegionWidth() + 2.0f * ImGui::GetStyle().WindowPadding.x != ImGui::CalcWindowNextAutoFitSize(ImGui::GetCurrentWindow()).x) imgui.set_requires_extra_frame(); -#else - if (ImGui::GetWindowContentRegionWidth() + 2.0f * ImGui::GetStyle().WindowPadding.x != ImGui::CalcWindowNextAutoFitSize(ImGui::GetCurrentWindow()).x) - m_canvas.request_extra_frame(); -#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT imgui.end(); ImGui::PopStyleColor(); @@ -3027,8 +3022,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'C': case 'c': { m_gcode_viewer.toggle_gcode_window_visibility(); m_dirty = true; request_extra_frame(); break; } #endif - //case 'E': - //case 'e': { m_labels.show(!m_labels.is_shown()); m_dirty = true; break; } + case 'E': + case 'e': { m_labels.show(!m_labels.is_shown()); m_dirty = true; break; } //case 'G': //case 'g': { // if ((evt.GetModifiers() & shiftMask) != 0) { diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 673b40bf3..4e7dc99a0 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -234,9 +234,9 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &ObjectList::OnContextMenu, this); // BBS - //Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, &ObjectList::OnBeginDrag, this); - //Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this); - //Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this); + Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, &ObjectList::OnBeginDrag, this); + Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this); + Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this); Bind(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, &ObjectList::OnEditingStarted, this); Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &ObjectList::OnEditingDone, this); @@ -1388,17 +1388,28 @@ void ObjectList::key_event(wxKeyEvent& event) void ObjectList::OnBeginDrag(wxDataViewEvent &event) { + bool sequential_print = (wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_enum("print_sequence") == PrintSequence::ByObject); + if (!sequential_print) { + //drag forbidden under bylayer mode + event.Veto(); + return; + } const wxDataViewItem item(event.GetItem()); const bool mult_sel = multiple_selection(); - + const ItemType& type = m_objects_model->GetItemType(item); + if (mult_sel || (type != itObject)) { + //drag only allowed for single object + event.Veto(); + return; + } +#if 0 if ((mult_sel && !selected_instances_of_same_object()) || (!mult_sel && (GetSelection() != item)) ) { event.Veto(); return; } - const ItemType& type = m_objects_model->GetItemType(item); if (!(type & (itVolume | itObject | itInstance))) { event.Veto(); return; @@ -1420,7 +1431,9 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) type&itVolume ? m_objects_model->GetVolumeIdByItem(item) : m_objects_model->GetInstanceIdByItem(item), type); - +#else + m_dragged_data.init(m_objects_model->GetIdByItem(item), type); +#endif /* Under MSW or OSX, DnD moves an item to the place of another selected item * But under GTK, DnD moves an item between another two items. * And as a result - call EVT_CHANGE_SELECTION to unselect all items. @@ -1438,8 +1451,28 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move; } -bool ObjectList::can_drop(const wxDataViewItem& item) const +bool ObjectList::can_drop(const wxDataViewItem& item, int& src_obj_id, int& src_plate, int& dest_obj_id, int& dest_plate) const { +#if 1 + if (!item.IsOk() || (m_objects_model->GetItemType(item) != m_dragged_data.type())) + return false; + + int from_obj_id = m_dragged_data.obj_idx(); + int to_obj_id = m_objects_model->GetIdByItem(item); + PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list(); + + int from_plate = partplate_list.find_instance(from_obj_id, 0); + if (from_plate == -1) + return false; + int to_plate = partplate_list.find_instance(to_obj_id, 0); + if ((to_plate == -1) || (from_plate != to_plate)) + return false; + + src_obj_id = from_obj_id; + dest_obj_id = to_obj_id; + src_plate = from_plate; + dest_plate = to_plate; +#else // move instance(s) or object on "empty place" of ObjectList if ( (m_dragged_data.type() & (itInstance | itObject)) && !item.IsOk() ) return true; @@ -1488,7 +1521,7 @@ bool ObjectList::can_drop(const wxDataViewItem& item) const return false; } - +#endif return true; } @@ -1496,7 +1529,8 @@ void ObjectList::OnDropPossible(wxDataViewEvent &event) { const wxDataViewItem& item = event.GetItem(); - if (!can_drop(item)) { + int src_obj_id, src_plate, dest_obj_id, dest_plate; + if (!can_drop(item, src_obj_id, src_plate, dest_obj_id, dest_plate)) { event.Veto(); m_prevent_list_events = false; } @@ -1506,13 +1540,45 @@ void ObjectList::OnDrop(wxDataViewEvent &event) { const wxDataViewItem& item = event.GetItem(); - if (!can_drop(item)) + int src_obj_id, src_plate, dest_obj_id, dest_plate; + if (!can_drop(item, src_obj_id, src_plate, dest_obj_id, dest_plate)) { event.Veto(); m_dragged_data.clear(); return; } +#if 1 + take_snapshot("Object order changed"); + + int delta = dest_obj_id < src_obj_id ? -1 : 1; + PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list(); + /*int cnt = 0, cur_id = src_obj_id, next_id, total = abs(src_obj_id - dest_obj_id); + //for (cur_id = src_obj_id; cnt < total; id += delta, cnt++) + next_id = src_obj_id + delta; + while (cnt < total) + { + int cur_plate = partplate_list.find_instance(next_id, 0); + if (cur_plate != src_plate) { + cnt ++; + next_id += delta; + continue; + } + std::swap((*m_objects)[cur_id], (*m_objects)[next_id]); + cur_id = next_id; + cnt ++; + next_id += delta; + }*/ + + int cnt = 0; + for (int id = src_obj_id; cnt < abs(src_obj_id - dest_obj_id); id += delta, cnt++) + std::swap((*m_objects)[id], (*m_objects)[id + delta]); + + select_item(m_objects_model->ReorganizeObjects(src_obj_id, dest_obj_id)); + + partplate_list.reload_all_objects(false, src_plate); + changed_object(src_obj_id); +#else if (m_dragged_data.type() == itInstance) { // BBS: remove snapshot name "Instances to Separated Objects" @@ -1553,6 +1619,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event) } changed_object(m_dragged_data.obj_idx()); +#endif m_dragged_data.clear(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index e7e3e25de..8ce1b81e7 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -446,7 +446,7 @@ private: void OnBeginDrag(wxDataViewEvent &event); void OnDropPossible(wxDataViewEvent &event); void OnDrop(wxDataViewEvent &event); - bool can_drop(const wxDataViewItem& item) const ; + bool can_drop(const wxDataViewItem& item, int& src_obj_id, int& src_plate, int& dest_obj_id, int& dest_plate) const ; void ItemValueChanged(wxDataViewEvent &event); // Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected. diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 612657cca..d0ea1a4ea 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -2223,7 +2223,7 @@ void MainFrame::init_menubar_as_editor() viewMenu->Check(wxID_CAMERA_ORTHOGONAL + camera_id_base, true); viewMenu->AppendSeparator(); - append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels"), _L("Show object labels in 3D scene"), + append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\tE", _L("Show object labels in 3D scene"), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 0debef4b6..0ee35959a 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -1721,15 +1721,16 @@ wxDataViewItem ObjectDataViewModel::ReorganizeObjects( const int current_id, co ObjectDataViewModelNode* deleted_node = m_objects[current_id]; m_objects.erase(m_objects.begin() + current_id); - ItemDeleted(wxDataViewItem(nullptr), wxDataViewItem(deleted_node)); + ItemDeleted(wxDataViewItem(deleted_node->m_parent), wxDataViewItem(deleted_node)); m_objects.emplace(m_objects.begin() + new_id, deleted_node); - ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(deleted_node)); + ItemAdded(wxDataViewItem(deleted_node->m_parent), wxDataViewItem(deleted_node)); + + //ItemChanged(wxDataViewItem(nullptr)); // If some item has a children, just to add a deleted item is not enough on Linux // We should to add all its children separately AddAllChildren(wxDataViewItem(deleted_node)); - return wxDataViewItem(deleted_node); } @@ -1832,14 +1833,12 @@ unsigned int ObjectDataViewModel::GetChildren(const wxDataViewItem &parent, wxDa return 0; } - unsigned int count = node->GetChildren().GetCount(); - for (unsigned int pos = 0; pos < count; pos++) - { - ObjectDataViewModelNode *child = node->GetChildren().Item(pos); - array.Add(wxDataViewItem((void*)child)); - } + for (auto object : m_objects) + { + array.Add(wxDataViewItem((void*)object)); + } - return count; + return array.size(); } void ObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index d363d9062..a01f2acb9 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -4132,7 +4132,7 @@ int PartPlateList::rebuild_plates_after_arrangement(bool recycle_plates, bool ex BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":before rebuild, plates count %1%, recycle_plates %2%") % m_plate_list.size() % recycle_plates; // sort by arrange_order - //std::sort(m_model->objects.begin(), m_model->objects.end(), [](auto a, auto b) {return a->instances[0]->arrange_order < b->instances[0]->arrange_order; }); + std::sort(m_model->objects.begin(), m_model->objects.end(), [](auto a, auto b) {return a->instances[0]->arrange_order < b->instances[0]->arrange_order; }); //for (auto object : m_model->objects) // std::sort(object->instances.begin(), object->instances.end(), [](auto a, auto b) {return a->arrange_order < b->arrange_order; }); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b22d5d46c..f9339f370 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -9823,7 +9823,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config) { bool update_scheduled = false; bool bed_shape_changed = false; - bool print_sequence_changed = false; + //bool print_sequence_changed = false; t_config_option_keys diff_keys = p->config->diff(config); for (auto opt_key : diff_keys) { if (opt_key == "filament_colour") { @@ -9878,7 +9878,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config) } else if (opt_key == "print_sequence") { update_scheduled = true; - print_sequence_changed = true; + //print_sequence_changed = true; } else if (opt_key == "printer_model") { p->reset_gcode_toolpaths(); @@ -9904,8 +9904,8 @@ void Plater::on_config_change(const DynamicPrintConfig &config) std::string info_text = _u8L("Print By Object: \nSuggest to use auto-arrange to avoid collisions when printing."); notify_manager->bbl_show_seqprintinfo_notification(info_text); //always show label when switch to sequence print - if (print_sequence_changed) - this->show_view3D_labels(true); + //if (print_sequence_changed) + // this->show_view3D_labels(true); } else notify_manager->bbl_close_seqprintinfo_notification();