From 2afdc66dfb84f512a3f72b0a18ceb51873d779c5 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 6 Oct 2021 15:29:39 +0200 Subject: [PATCH 01/22] #7068 - Automatic update of legend when switching on/off travel visibility in preview --- src/slic3r/GUI/GUI_Preview.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index a676945418..0cd0ac9eb0 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -496,13 +496,20 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt) void Preview::on_combochecklist_options(wxCommandEvent& evt) { - unsigned int curr_flags = m_canvas->get_gcode_options_visibility_flags(); - unsigned int new_flags = Slic3r::GUI::combochecklist_get_flags(m_combochecklist_options); + const unsigned int curr_flags = m_canvas->get_gcode_options_visibility_flags(); + const unsigned int new_flags = Slic3r::GUI::combochecklist_get_flags(m_combochecklist_options); if (curr_flags == new_flags) return; m_canvas->set_gcode_options_visibility_from_flags(new_flags); - m_canvas->refresh_gcode_preview_render_paths(); + if (m_canvas->get_gcode_view_type() == GCodeViewer::EViewType::Feedrate) { + const unsigned int diff_flags = curr_flags ^ new_flags; + if ((diff_flags & (1 << static_cast(Preview::OptionType::Travel))) != 0) + refresh_print(); + } + else + m_canvas->refresh_gcode_preview_render_paths(); + update_moves_slider(); } From dbad87fb42343a8c9eaf51897bfe316a82c344d7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 6 Oct 2021 15:46:01 +0200 Subject: [PATCH 02/22] Follow-up of 2afdc66dfb84f512a3f72b0a18ceb51873d779c5 - Added missing use case --- src/slic3r/GUI/GUI_Preview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 0cd0ac9eb0..57840dda28 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -506,6 +506,8 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt) const unsigned int diff_flags = curr_flags ^ new_flags; if ((diff_flags & (1 << static_cast(Preview::OptionType::Travel))) != 0) refresh_print(); + else + m_canvas->refresh_gcode_preview_render_paths(); } else m_canvas->refresh_gcode_preview_render_paths(); From 7340488aaf075a9abde9a1c2ae877a02e0b12533 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 6 Oct 2021 17:24:22 +0200 Subject: [PATCH 03/22] ObjectList: Fixes * Fixed update of a warning icon for multi-part object, when some part with errors was deleted * Fixed a crash when selecting non-Object and non-Volume item (in get_mesh_errors_info() was missed check of the obj_idx) + Follow-up https://github.com/prusa3d/PrusaSlicer/commit/1cc7b4ba971e8d04558b8a49869d9ce1647b8f77 - some code refactoring: * fixed RepairedMeshErrors.merge() * get_mesh_errors_count() renamed to get_repaired_errors_count() --- src/libslic3r/Model.cpp | 6 +- src/libslic3r/Model.hpp | 4 +- src/libslic3r/TriangleMesh.cpp | 3 +- src/libslic3r/TriangleMesh.hpp | 14 ++-- src/slic3r/GUI/GUI_ObjectList.cpp | 80 ++++++++++++----------- src/slic3r/GUI/GUI_ObjectList.hpp | 12 +++- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 9 ++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 3 +- src/slic3r/GUI/ObjectDataViewModel.cpp | 8 +++ src/slic3r/GUI/ObjectDataViewModel.hpp | 1 + src/slic3r/GUI/Plater.cpp | 10 +-- 11 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index b681cbdf44..8659e69612 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1629,10 +1629,10 @@ TriangleMeshStats ModelObject::get_object_stl_stats() const return full_stats; } -int ModelObject::get_mesh_errors_count(const int vol_idx /*= -1*/) const +int ModelObject::get_repaired_errors_count(const int vol_idx /*= -1*/) const { if (vol_idx >= 0) - return this->volumes[vol_idx]->get_mesh_errors_count(); + return this->volumes[vol_idx]->get_repaired_errors_count(); const RepairedMeshErrors& stats = get_object_stl_stats().repaired_errors; @@ -1704,7 +1704,7 @@ void ModelVolume::calculate_convex_hull() assert(m_convex_hull.get()); } -int ModelVolume::get_mesh_errors_count() const +int ModelVolume::get_repaired_errors_count() const { const RepairedMeshErrors &stats = this->mesh().stats().repaired_errors; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ea1d0ed175..6e0063f1bc 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -377,7 +377,7 @@ public: // Get full stl statistics for all object's meshes TriangleMeshStats get_object_stl_stats() const; // Get count of errors in the mesh( or all object's meshes, if volume index isn't defined) - int get_mesh_errors_count(const int vol_idx = -1) const; + int get_repaired_errors_count(const int vol_idx = -1) const; private: friend class Model; @@ -682,7 +682,7 @@ public: const TriangleMesh& get_convex_hull() const; std::shared_ptr get_convex_hull_shared_ptr() const { return m_convex_hull; } // Get count of errors in the mesh - int get_mesh_errors_count() const; + int get_repaired_errors_count() const; // Helpers for loading / storing into AMF / 3MF files. static ModelVolumeType type_from_string(const std::string &s); diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index e98dcf554e..bb3c9fc5c2 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -68,8 +68,7 @@ TriangleMesh::TriangleMesh(const indexed_triangle_set &its) : its(its) TriangleMesh::TriangleMesh(indexed_triangle_set &&its, const RepairedMeshErrors& errors/* = RepairedMeshErrors()*/) : its(std::move(its)) { - if (errors.repaired()) - m_stats.repaired_errors = errors; + m_stats.repaired_errors = errors; fill_initial_stats(this->its, m_stats); } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index b223b4346f..5223631c0b 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -33,14 +33,12 @@ struct RepairedMeshErrors { void clear() { *this = RepairedMeshErrors(); } - RepairedMeshErrors merge(const RepairedMeshErrors& rhs) const { - RepairedMeshErrors out; - out.edges_fixed = this->edges_fixed + rhs.edges_fixed; - out.degenerate_facets = this->degenerate_facets + rhs.degenerate_facets; - out.facets_removed = this->facets_removed + rhs.facets_removed; - out.facets_reversed = this->facets_reversed + rhs.facets_reversed; - out.backwards_edges = this->backwards_edges + rhs.backwards_edges; - return out; + void merge(const RepairedMeshErrors& rhs) { + this->edges_fixed += rhs.edges_fixed; + this->degenerate_facets += rhs.degenerate_facets; + this->facets_removed += rhs.facets_removed; + this->facets_reversed += rhs.facets_reversed; + this->backwards_edges += rhs.backwards_edges; } bool repaired() const { return degenerate_facets > 0 || edges_fixed > 0 || facets_removed > 0 || facets_reversed > 0 || backwards_edges > 0; } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 6c416c475e..d2a6b6e9aa 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -375,9 +375,9 @@ void ObjectList::get_selection_indexes(std::vector& obj_idxs, std::vector= 0 ? (*m_objects)[obj_idx]->get_mesh_errors_count(vol_idx) : 0; + return obj_idx >= 0 ? (*m_objects)[obj_idx]->get_repaired_errors_count(vol_idx) : 0; } static std::string get_warning_icon_name(const TriangleMeshStats& stats) @@ -385,8 +385,11 @@ static std::string get_warning_icon_name(const TriangleMeshStats& stats) return stats.manifold() ? (stats.repaired() ? "exclamation_manifold" : "") : "exclamation"; } -std::pair ObjectList::get_mesh_errors(const int obj_idx, const int vol_idx /*= -1*/, wxString* sidebar_info /*= nullptr*/) const +MeshErrorsInfo ObjectList::get_mesh_errors_info(const int obj_idx, const int vol_idx /*= -1*/, wxString* sidebar_info /*= nullptr*/) const { + if (obj_idx < 0) + return { {}, {} }; // hide tooltip + const TriangleMeshStats& stats = vol_idx == -1 ? (*m_objects)[obj_idx]->get_object_stl_stats() : (*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats(); @@ -401,7 +404,7 @@ std::pair ObjectList::get_mesh_errors(const int obj_idx, // Create tooltip string, if there are errors if (stats.repaired()) { - const int errors = get_mesh_errors_count(obj_idx, vol_idx); + const int errors = get_repaired_errors_count(obj_idx, vol_idx); auto_repaired_info = format_wxstr(_L_PLURAL("Auto-repaired %1$d error", "Auto-repaired %1$d errors", errors), errors); tooltip += auto_repaired_info +":\n"; @@ -434,15 +437,24 @@ std::pair ObjectList::get_mesh_errors(const int obj_idx, return { tooltip, get_warning_icon_name(stats) }; } -std::pair ObjectList::get_mesh_errors(wxString* sidebar_info /*= nullptr*/) +MeshErrorsInfo ObjectList::get_mesh_errors_info(wxString* sidebar_info /*= nullptr*/) { - if (!GetSelection()) + wxDataViewItem item = GetSelection(); + if (!item) return { "", "" }; int obj_idx, vol_idx; get_selected_item_indexes(obj_idx, vol_idx); - return get_mesh_errors(obj_idx, vol_idx, sidebar_info); + if (obj_idx < 0) { // child of ObjectItem is selected + if (sidebar_info) + obj_idx = m_objects_model->GetObjectIdByItem(item); + else + return { "", "" }; + } + assert(obj_idx >= 0); + + return get_mesh_errors_info(obj_idx, vol_idx, sidebar_info); } void ObjectList::set_tooltip_for_item(const wxPoint& pt) @@ -478,9 +490,12 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) #endif //__WXMSW__ else if (col->GetTitle() == _("Name") && (pt.x >= 2 * wxGetApp().em_unit() && pt.x <= 4 * wxGetApp().em_unit())) { - int obj_idx, vol_idx; - get_selected_item_indexes(obj_idx, vol_idx, item); - tooltip = get_mesh_errors(obj_idx, vol_idx).first; + if (const ItemType type = m_objects_model->GetItemType(item); + type & (itObject | itVolume)) { + int obj_idx = m_objects_model->GetObjectIdByItem(item); + int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1; + tooltip = get_mesh_errors_info(obj_idx, vol_idx).tooltip; + } } GetMainWindow()->SetToolTip(tooltip); @@ -1797,10 +1812,8 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) // If last volume item with warning was deleted, unmark object item if (type & itVolume) { - if (auto obj = object(obj_idx); obj->get_mesh_errors_count() == 0) - m_objects_model->DeleteWarningIcon(parent); - else - m_objects_model->AddWarningIcon(parent, get_warning_icon_name(obj->mesh().stats())); + const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats()); + m_objects_model->UpdateWarningIcon(parent, icon_name); } m_objects_model->Delete(item); @@ -2509,7 +2522,7 @@ void ObjectList::part_selection_changed() if (item) { // wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item)); wxGetApp().obj_manipul()->update_item_name(m_objects_model->GetName(item)); - wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors(obj_idx, volume_id)); + wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_info(obj_idx, volume_id)); } } @@ -2769,10 +2782,7 @@ void ObjectList::delete_from_model_and_list(const std::vector& it m_objects_model->SetExtruder(extruder, parent); } // If last volume item with warning was deleted, unmark object item - if (obj->get_mesh_errors_count() == 0) - m_objects_model->DeleteWarningIcon(parent); - else - m_objects_model->AddWarningIcon(parent, get_warning_icon_name(obj->mesh().stats())); + m_objects_model->UpdateWarningIcon(parent, get_warning_icon_name(obj->get_object_stl_stats())); } wxGetApp().plater()->canvas3D()->ensure_on_bed(item->obj_idx, printer_technology() != ptSLA); } @@ -4055,7 +4065,7 @@ void ObjectList::fix_through_netfabb() if (vol_idxs.empty()) { #if !FIX_THROUGH_NETFABB_ALWAYS for (int i = int(obj_idxs.size())-1; i >= 0; --i) - if (object(obj_idxs[i])->get_mesh_errors_count() == 0) + if (object(obj_idxs[i])->get_repaired_errors_count() == 0) obj_idxs.erase(obj_idxs.begin()+i); #endif // FIX_THROUGH_NETFABB_ALWAYS for (int obj_idx : obj_idxs) @@ -4065,7 +4075,7 @@ void ObjectList::fix_through_netfabb() ModelObject* obj = object(obj_idxs.front()); #if !FIX_THROUGH_NETFABB_ALWAYS for (int i = int(vol_idxs.size()) - 1; i >= 0; --i) - if (obj->get_mesh_errors_count(vol_idxs[i]) == 0) + if (obj->get_repaired_errors_count(vol_idxs[i]) == 0) vol_idxs.erase(vol_idxs.begin() + i); #endif // FIX_THROUGH_NETFABB_ALWAYS for (int vol_idx : vol_idxs) @@ -4121,7 +4131,7 @@ void ObjectList::fix_through_netfabb() int vol_idx{ -1 }; for (int obj_idx : obj_idxs) { #if !FIX_THROUGH_NETFABB_ALWAYS - if (object(obj_idx)->get_mesh_errors_count(vol_idx) == 0) + if (object(obj_idx)->get_repaired_errors_count(vol_idx) == 0) continue; #endif // FIX_THROUGH_NETFABB_ALWAYS if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg, succes_models, failed_models)) @@ -4178,24 +4188,18 @@ void ObjectList::simplify() void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) const { - const wxDataViewItem item = vol_idx <0 ? m_objects_model->GetItemById(obj_idx) : - m_objects_model->GetItemByVolumeId(obj_idx, vol_idx); - if (!item) + auto obj = object(obj_idx); + if (wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx)) { + const std::string& icon_name = get_warning_icon_name(obj->get_object_stl_stats()); + m_objects_model->UpdateWarningIcon(obj_item, icon_name); + } + + if (vol_idx < 0) return; - if (get_mesh_errors_count(obj_idx, vol_idx) == 0) - { - // if whole object has no errors more, - if (get_mesh_errors_count(obj_idx) == 0) - // unmark all items in the object - m_objects_model->DeleteWarningIcon(vol_idx >= 0 ? m_objects_model->GetParent(item) : item, true); - else - // unmark fixed item only - m_objects_model->DeleteWarningIcon(item); - } - else { - auto obj = object(obj_idx); - m_objects_model->AddWarningIcon(item, get_warning_icon_name(vol_idx < 0 ? obj->mesh().stats() : obj->volumes[vol_idx]->mesh().stats())); + if (wxDataViewItem vol_item = m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)) { + const std::string& icon_name = get_warning_icon_name(obj->volumes[vol_idx]->mesh().stats()); + m_objects_model->UpdateWarningIcon(vol_item, icon_name); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 54e3f5d45e..cc619fc456 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -67,6 +67,12 @@ struct ItemForDelete } }; +struct MeshErrorsInfo +{ + wxString tooltip; + std::string warning_icon_name; +}; + class ObjectList : public wxDataViewCtrl { public: @@ -212,13 +218,13 @@ public: void get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& item = wxDataViewItem(0)); void get_selection_indexes(std::vector& obj_idxs, std::vector& vol_idxs); // Get count of errors in the mesh - int get_mesh_errors_count(const int obj_idx, const int vol_idx = -1) const; + int get_repaired_errors_count(const int obj_idx, const int vol_idx = -1) const; // Get list of errors in the mesh and name of the warning icon // Return value is a pair , used for the tooltip and related warning icon // Function without parameters is for a call from Manipulation panel, // when we don't know parameters of selected item - std::pair get_mesh_errors(const int obj_idx, const int vol_idx = -1, wxString* sidebar_info = nullptr) const; - std::pair get_mesh_errors(wxString* sidebar_info = nullptr); + MeshErrorsInfo get_mesh_errors_info(const int obj_idx, const int vol_idx = -1, wxString* sidebar_info = nullptr) const; + MeshErrorsInfo get_mesh_errors_info(wxString* sidebar_info = nullptr); void set_tooltip_for_item(const wxPoint& pt); void selection_changed(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 7d5f80a300..b8c053f888 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -1,5 +1,4 @@ #include "GUI_ObjectManipulation.hpp" -#include "GUI_ObjectList.hpp" #include "I18N.hpp" #include "BitmapComboBox.hpp" @@ -132,7 +131,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : return; wxGetApp().obj_list()->fix_through_netfabb(); - update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors()); + update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_info()); }); sizer->Add(m_fix_throught_netfab_bitmap); @@ -781,12 +780,12 @@ void ObjectManipulation::update_item_name(const wxString& item_name) m_item_name->SetLabel(item_name); } -void ObjectManipulation::update_warning_icon_state(const std::pair& warning) +void ObjectManipulation::update_warning_icon_state(const MeshErrorsInfo& warning) { - if (const std::string& warning_icon_name = warning.second; + if (const std::string& warning_icon_name = warning.warning_icon_name; !warning_icon_name.empty()) m_manifold_warning_bmp = ScalableBitmap(m_parent, warning_icon_name); - const wxString& tooltip = warning.first; + const wxString& tooltip = warning.tooltip; m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0,0) : m_manifold_warning_bmp.bmp().GetSize()); m_fix_throught_netfab_bitmap->SetToolTip(tooltip); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 9b77591be6..a15c72fb8e 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -4,6 +4,7 @@ #include #include "GUI_ObjectSettings.hpp" +#include "GUI_ObjectList.hpp" #include "libslic3r/Point.hpp" #include @@ -194,7 +195,7 @@ public: #endif // __APPLE__ void update_item_name(const wxString &item_name); - void update_warning_icon_state(const std::pair& warning); + void update_warning_icon_state(const MeshErrorsInfo& warning); void msw_rescale(); void sys_color_changed(); void on_change(const std::string& opt_key, int axis, double new_value); diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 78735b9258..ed4b477b81 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -1786,6 +1786,14 @@ bool ObjectDataViewModel::HasWarningIcon(const wxDataViewItem& item) const return node->has_warning_icon(); } +void ObjectDataViewModel::UpdateWarningIcon(const wxDataViewItem& item, const std::string& warning_icon_name) +{ + if (warning_icon_name.empty()) + DeleteWarningIcon(item, true); + else + AddWarningIcon(item, warning_icon_name); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index ca7a0cde03..f8885b2060 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -389,6 +389,7 @@ public: const std::string& warning_icon_name = std::string()); void AddWarningIcon(const wxDataViewItem& item, const std::string& warning_name); void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false); + void UpdateWarningIcon(const wxDataViewItem& item, const std::string& warning_name); bool HasWarningIcon(const wxDataViewItem& item) const; t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f00c6df3e1..68c20d497b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1204,9 +1204,9 @@ void Sidebar::show_info_sizer() static_cast(model_object->facets_count()), stats.number_of_parts)); wxString info_manifold_label; - auto mesh_errors = obj_list()->get_mesh_errors(&info_manifold_label); - wxString tooltip = mesh_errors.first; - p->object_info->update_warning_icon(mesh_errors.second); + auto mesh_errors = obj_list()->get_mesh_errors_info(&info_manifold_label); + wxString tooltip = mesh_errors.tooltip; + p->object_info->update_warning_icon(mesh_errors.warning_icon_name); p->object_info->info_manifold->SetLabel(info_manifold_label); p->object_info->info_manifold->SetToolTip(tooltip); p->object_info->manifold_warning_icon->SetToolTip(tooltip); @@ -4593,14 +4593,14 @@ bool Plater::priv::can_fix_through_netfabb() const // Fixing only if the model is not manifold. if (vol_idxs.empty()) { for (auto obj_idx : obj_idxs) - if (model.objects[obj_idx]->get_mesh_errors_count() > 0) + if (model.objects[obj_idx]->get_repaired_errors_count() > 0) return true; return false; } int obj_idx = obj_idxs.front(); for (auto vol_idx : vol_idxs) - if (model.objects[obj_idx]->get_mesh_errors_count(vol_idx) > 0) + if (model.objects[obj_idx]->get_repaired_errors_count(vol_idx) > 0) return true; return false; #endif // FIX_THROUGH_NETFABB_ALWAYS From c15be26bff17ed0354323f047ba56cb317d6c63b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 09:12:31 +0200 Subject: [PATCH 04/22] Check if object's size appears to be zero, when loading the model file. --- src/libslic3r/Model.cpp | 16 ++++++++++++++++ src/libslic3r/Model.hpp | 1 + src/slic3r/GUI/Plater.cpp | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8659e69612..1ade36e36d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -513,6 +513,22 @@ void Model::convert_from_meters(bool only_small_volumes) } } +static constexpr const double zero_volume = 0.0000000001; + +int Model::removed_objects_with_zero_volume() +{ + if (objects.size() == 0) + return 0; + + int removed = 0; + for (int i = int(objects.size()) - 1; i >= 0; i--) + if (objects[i]->get_object_stl_stats().volume < zero_volume) { + delete_object(size_t(i)); + removed++; + } + return removed; +} + void Model::adjust_min_z() { if (objects.empty()) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 6e0063f1bc..11cbdc0cf1 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1124,6 +1124,7 @@ public: void convert_from_imperial_units(bool only_small_volumes); bool looks_like_saved_in_meters() const; void convert_from_meters(bool only_small_volumes); + int removed_objects_with_zero_volume(); // Ensures that the min z of the model is not negative void adjust_min_z(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 68c20d497b..0710c0916c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2438,6 +2438,14 @@ std::vector Plater::priv::load_files(const std::vector& input_ }; if (!is_project_file) { + if (int deleted_objects = model.removed_objects_with_zero_volume(); deleted_objects > 0) { + MessageDialog(q, format_wxstr(_L_PLURAL( + "Object size from file %s appears to be zero.\n" + "This object has been removed from the model", + "Objects size from file %s appear to be zero.\n" + "These objects have been removed from the model", deleted_objects), from_path(filename)) + "\n", + _L("Object size is zero"), wxICON_INFORMATION | wxOK).ShowModal(); + } if (imperial_units) // Convert even if the object is big. convert_from_imperial_units(model, false); From 1b828ca7f5a70b81a6c35c6d5755879a01f09128 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 10:14:55 +0200 Subject: [PATCH 05/22] Deleted unused PNG-files. Added mirroring_transparent.svg (thanks for @AkiraNorthstar) --- resources/icons/colorchange_add_off.png | Bin 600 -> 0 bytes resources/icons/colorchange_add_on.png | Bin 695 -> 0 bytes resources/icons/colorchange_delete_off.png | Bin 589 -> 0 bytes resources/icons/colorchange_delete_on.png | Bin 628 -> 0 bytes resources/icons/down_half_circle.png | Bin 631 -> 0 bytes resources/icons/left_half_circle.png | Bin 651 -> 0 bytes resources/icons/mirroring_transparent.png | Bin 93 -> 0 bytes resources/icons/mirroring_transparent.svg | 4 ++++ resources/icons/mode_advanced_.png | Bin 1466 -> 0 bytes resources/icons/mode_advanced_sq.png | Bin 158 -> 0 bytes resources/icons/mode_expert_.png | Bin 1379 -> 0 bytes resources/icons/mode_expert_sq.png | Bin 164 -> 0 bytes resources/icons/mode_simple_.png | Bin 1164 -> 0 bytes resources/icons/mode_simple_sq.png | Bin 158 -> 0 bytes resources/icons/one_layer_lock_off.png | Bin 1001 -> 0 bytes resources/icons/one_layer_lock_on.png | Bin 1106 -> 0 bytes resources/icons/one_layer_unlock_off.png | Bin 997 -> 0 bytes resources/icons/one_layer_unlock_on.png | Bin 1129 -> 0 bytes resources/icons/pause_add.png | Bin 5883 -> 0 bytes resources/icons/right_half_circle.png | Bin 654 -> 0 bytes resources/icons/row.png | Bin 1923 -> 0 bytes resources/icons/shape_ungroup.png | Bin 803 -> 0 bytes resources/icons/table.png | Bin 465 -> 0 bytes resources/icons/up_half_circle.png | Bin 650 -> 0 bytes resources/icons/variable_layer_height_reset.png | Bin 1050 -> 0 bytes .../icons/variable_layer_height_tooltip.png | Bin 10017 -> 0 bytes 26 files changed, 4 insertions(+) delete mode 100644 resources/icons/colorchange_add_off.png delete mode 100644 resources/icons/colorchange_add_on.png delete mode 100644 resources/icons/colorchange_delete_off.png delete mode 100644 resources/icons/colorchange_delete_on.png delete mode 100644 resources/icons/down_half_circle.png delete mode 100644 resources/icons/left_half_circle.png delete mode 100644 resources/icons/mirroring_transparent.png create mode 100644 resources/icons/mirroring_transparent.svg delete mode 100644 resources/icons/mode_advanced_.png delete mode 100644 resources/icons/mode_advanced_sq.png delete mode 100644 resources/icons/mode_expert_.png delete mode 100644 resources/icons/mode_expert_sq.png delete mode 100644 resources/icons/mode_simple_.png delete mode 100644 resources/icons/mode_simple_sq.png delete mode 100644 resources/icons/one_layer_lock_off.png delete mode 100644 resources/icons/one_layer_lock_on.png delete mode 100644 resources/icons/one_layer_unlock_off.png delete mode 100644 resources/icons/one_layer_unlock_on.png delete mode 100644 resources/icons/pause_add.png delete mode 100644 resources/icons/right_half_circle.png delete mode 100644 resources/icons/row.png delete mode 100644 resources/icons/shape_ungroup.png delete mode 100644 resources/icons/table.png delete mode 100644 resources/icons/up_half_circle.png delete mode 100644 resources/icons/variable_layer_height_reset.png delete mode 100644 resources/icons/variable_layer_height_tooltip.png diff --git a/resources/icons/colorchange_add_off.png b/resources/icons/colorchange_add_off.png deleted file mode 100644 index 6ddeccbe0a2a82019c5c2efd1773c20c0833c4d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 600 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBC{YpM6XNqfL!5oT`ng2Uv7KO- z`>oK>c;wi#w-Y8-9OfwbtPfPmnB?v5!uX#__a2bLS>O>_%)p?h48n{ROYO^mg6t)p zzOL*KxFrR+#s37PM*)TAdb&7gOf=4WlTK;F^nd^Dc_ijpxxR1T zX#3n&TDl=r(%}>cpt3=meXk`S|u=mmKH$V*x Mp00i_>zopr04OBpdH?_b diff --git a/resources/icons/colorchange_add_on.png b/resources/icons/colorchange_add_on.png deleted file mode 100644 index cc800b81e8a6355877fa8cf58fee3731540f5dbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD6u8LC&cwX?ZDQK|Lu1F z3#9(1u>Ehd{lBC4e=5iS1cv`9?Ekm-{NK>{f7gWnt9$>~IQ`$*4|2u&`v2?e{dfTo%*MD>FcgxMz#tc&>wjKYvlkv2}>W3ZX<P)+_zJD`=!SuPm-m%Y^cA85^??v;%fYzs559euLSj6?CPDVv# z8OPo07q)BrukMjxdUaSr{b2Kv9pC;|`Sb4o|Mpw@uyeDVx zW$1|Bsj=8bi@Q>L-?mjR+Ky$nt-EqlSb4pc^PF5&HlSxzOI#yLQW8s2t&)pUffR$0 zfuWhMp`oskX^5ejm7%GXsj;?!p_PHb`H8EHQ8eV{r(~v8qH8d;GO~ndkeu{n5l{nz Mr>mdKI;Vst0C-YMUjP6A diff --git a/resources/icons/colorchange_delete_off.png b/resources/icons/colorchange_delete_off.png deleted file mode 100644 index c16655271a7e10d9d83047189086d4d6b509abc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S0wixl{&NRXEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZEE?e4>iGH4#PT$HOWYUVmw=D)W4<$2R?NV2M}KA?FdtNTmJp~!15S*|LT8;MoC zXsZ3%W24$-moh2c@9l*fmo+q>Gq62KSXA699k*xgMiDE{G|yhA4QhurtG<}@uu!C_ z<$>}m-=I62B~!k9UHS2l6URxP__|{b{!P~`Som^z%$(k+UE0pWDc5vL>wMPBh1~ac zOgPu;&>~>6W*@_Frwy&D=l0S8q@B+Qm*U`007}-kq7#>;Nm&p5M&yqHoBEQzy zY0CSzuP^(vnT8meSs9vI xnHp;w7+M(^oS(SL7)3*FeoAIqCAtPfD`O*whU@kljsZ0=c)I$ztaD0e0ssxu+3)}W diff --git a/resources/icons/colorchange_delete_on.png b/resources/icons/colorchange_delete_on.png deleted file mode 100644 index 8f27ce9fe684cca59295bd787f0c564f14a56a25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 628 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S0wixl{&NRXEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZEE?e4yA$Thpan!eyJ5ZE|lwT7;ffcnvE zS;w+UCtS;Nk}WE(*0icP_POSv<^KD{Mb$yQ(FI4REZ!IK`2_R)UyEa!cz3P+`04`t z{hZU%K_&mTt8UMEpM2aV&hod9dl<8x*4CJ9HxKi5&!3)Df4S#W*Q&b>yI22j=vX^V zN2n)Lr+H5h+lo`osZwf9*@ahFFK4ad3^C7@C^3O zPrjD~3a37HGZKiN!`D`B)H&;x+upMdZvr^>@ujWVCAfaBxAC{SdtoWHFMjlkyh{DG za*j&_)BC37>U<7=kI(V^<2moiw_|H`-C}#RDkiV9dRkkwNm};kgU!{O7tC!`5!kGA z^GE;ee@5|{S6i4p0)jJVZr^=>`yT6c`+I)XS|^=q?fadV_WRo97S>|Fv|GC`%Kv5L zl`d>pzF+$gFcwrxTq8h@qL4p{bRrv9^Jsm4U(e niK~oJH00)|WTsW3YcRAjHic*qn$hP0)WG2B>gTe~DWM4f)HnL< diff --git a/resources/icons/down_half_circle.png b/resources/icons/down_half_circle.png deleted file mode 100644 index f86a2932c1da84cc5e4b9214b26e04a49542af73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631 zcmV--0*L*IP)5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5=j6wYYx57>K1)u*YSQLCnrxtjJS&=pv;pY$dTN+FA5|tC)r3t?7 z#8at`%Ao_oMjA?6ya>;Tn{PLl>!_?;FXgL84|*7&kEh?!9t+H*c~lM;a|SCBFkA-% R>c#*7002ovPDHLkV1nhP51#-4 diff --git a/resources/icons/left_half_circle.png b/resources/icons/left_half_circle.png deleted file mode 100644 index 3bdc4c3eefbecd5a7625dbb118f1ef39e879fbd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 651 zcmV;60(AX}P)5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5~(?C#d28Jphg%k%)>W?G;E`!6C3*rXk@BgrEk| zC2Z1#9sA$R&xCq%AyoPp2~$ikEFqVA3Iky-%!J3wVwnq}G*I{y-teF?rAoiv{1-y6 z?wqxSe;`boooyE;x55h;-UlJOF8p?ZZ5LQe$J-$7u)?Vo#Frz!r40^k6@(o=q#tR| l^|NT|eD|dAf>(_3d + + + \ No newline at end of file diff --git a/resources/icons/mode_advanced_.png b/resources/icons/mode_advanced_.png deleted file mode 100644 index d98d8f7091d0fcebd33a354a11feb8cd0a08f5bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1466 zcmV;r1x5OaP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Yww&N%a{MRaG2}VK)mc#R$-oY$?3hX>@uG@Wk zLSl>p0;-C#ssHa2<3@L;SAD?{UjGMUapS^aQU)Sf@Y`?_G`Qr~pNKnh( z4E^Yz5!c56JNmow8Yinqo_Hj>&3q)3IWyzt=ogPf!h8I-5K70m?4Oo?{8C$s-`vsZ zz3mNPG(|pP;x0}$T*I72umXvaXAD;s=IyxmVz`Q=&)Crp^H=chcW>Bj`H0Ia6tvwE zg*S|jxYN(rErecJd(8auhm1SXU$7ga#WDK6yX*sy3UqAhwv}~fg_d* z)&ya`uf?r-)0(fkh?$#1Pj*P=CY$etJ_UbL?uo{j(sgc&J5G=V*2PoPSjJ>-UeODL zxN%^r3*S}fNjKXQu>uBl!5p!{yp=sgQTNc6ES?4Zbn~=}esk821b_&0D;DDf3~a%P zy5KfrHs^q21V0%oXYpLXfK%n>Xn-4$0CFPFxiQAv>dVS|7}f$JR00l31Vb5Qd9Toq z`3MbV74@X5K~1A3%|U_>8bYuzJt~`+H??49(URpT(MOFTT8uHpoHz+AOjAfkDW;Ti z#-tgkGe&3h$hmNl;)|A0ti+N^u8>dlRcokLV@)+TZqji4TWCftw$yTW9a8GPYY*Le z?5XDgtqmD|=m^6`9BJe`YwkFDcrOZot%L&_705O zWB`KZ$=Md2_dJ=KoNbA5D3rmP(@9QqlQA&pyJH>h&fSB#Q{G7ZAMwWDF-McS|ART2 z)E&%y|2|92MxiqfcDo$R*o=rzD-bN`nu72!II@%VS z7Ce(Ica}{V~e6CF`7Y8>3M!AS8cF)pzi=nD7d8XGaqct#|Z3gbmQbTUTfl$U-0iGN) z7dT{`H!;u0|50P4?y2maYNE9_8z-v)iWv|?u?2O9vK#08L;|+FVfPX{#JQ(iXluNa z;ETi429JoqSwU`YZh*Ch(jPhe|!uz=l0Yb{k1S9s9avCh@sS%o^q#;djGB5ZxlQPPv0p1j|EQ;#V>`w9f9kD zr*9PhS?+IQe^P&;k9z-J?r&nhtH04lz5h<`AH+@{)czx})2rI=>h{m_zan<}p!RXI zmfy+!Zp#SJ;{ZJA{j%I24o?q@f71I8rZtv&rPS@@I+}-KAy`RgSuG{;$-08Z#p9`LT@;>v)-RZC2XAZg3b$dUT zJ6*T;bGg%Xdp{RD{q$Yt-Q8*Y&AZH#yVG@hKX-Tfq<0y3!%vX?fA%);>rHq<8UO$Q z24YJ`L;(K){{a7>y{D4^000SaNLh0L01|Wn01|Wo-ewjA5L~c#`DCC7XMsm# zF$0582?#UZOOvkv3bL1Y`ns||X5`|qG~f2QI22@nr;B5V#`)v~iHZY1{!3i0XG^qZ wWAm$JYkMy)DREEEDe!>HiI#^86ATy_JUQ8}xt6zj0JSlAy85}Sb4q9e0I>ZleE zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3vrlIti8h5u_6vjhYPiRJLDnjOsY=is;#C!O&f zciL3^P%udPbTBmj`Fqk|IJ~G)#3|*J9FCY{_60ZQZpZD)E^gfxc$m2MlXwkDI-p?E?jWvwt~4d4I3OgX{Y*_sx07 zd#Bgus7OW^j2Arl5jZ%U)0!o~gJ7X78_qs>@Amr`63$`udzU-9rTKgE?sqS_b7i-O z=TwmU8YsQwXt%Sx&)t@xCu)zGpZ=Kj4*FZ}=Il1-xJ6fDLZ%Y!L4Ad?-JxSeD#P|# zLR0(%_qw%=W(cu?SO?9D)`&BEWOH)l&V?tB?b^7(#ps7uT)l5TY&Hw(vu_)exEfEd zA%{+2STKyEQu0jXQu1AShd!4FMKcZ$nh!M{R|Tb3i|Fk#0rrSo=NzQiQn$ z&Ts$$mpBL~cIv${Baa3?1)lp5eFXs)@ttXc4eB0n%&)oej`G&mi@%w%v;c%aA__D) z6u^p6P(KBoRrXVv?n#kYbXQlBTsr6%86yG^wg-)?&e;i6v7r%T}__0ZW+V zl$EmOoJ+x^1w$9SUC^VH>T9U6N=;R()m%$M`Lx)irKZhVZl(JkI^^F|SL)VtFM|h4 zX~ZET4IMV}C=<0d!;DjAnmTRfS?<($m+ccZej#^GjdyB`Sls&QgBr}LUqkR(PGm6y zF&`PkbrC>8`^C%|$LJTi#mr?7QHTdMmIbHtA_jtSu$Reqb`Nr=+(_ajZvMZ>(L(nd zwbj`a6EwIUYTce^(%HhyJtYXSH{oujE6-7# zc29+ojS*%~4o*N)C29(7mOk+@E#3;e%q9^ZDOYS1tfWpP##YK`fE|T_59`s$6Vk^} zu_Ot@&)Rfku~t*SqKisE2|Pkr5mY~JQGUf}#?&VYSUL(F9t-{FIKVa!WeV2;w z1|mWQve~?mqE}QYEK)H&fqIAOg%T~tH&D-*{sie8Bl;nvZ;a>)q(>TFoamG7-jNag(jFqvC)>RvC;DW&cceuB3lrw)**W?b z+PYSP@1brk00006VoOIv0RI600RN!9r;`8x010qNS#tmY5_A9n5_AFHW*>L}000Mc zNliru;tCcBE-rCcRgeGx05C~JK~yNuW8BWh_Fw1MF9t3d6^0K_?l7EXfB+^228K^O lJPb?>1i+|*Q3cdh002W22;H2eLIwZ;002ovPDHLkV1id3f^Pr- diff --git a/resources/icons/mode_expert_sq.png b/resources/icons/mode_expert_sq.png deleted file mode 100644 index 742ffc08891d60c465c4cba7bf33cbf207579870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^96&6jA5L~c#`DCC7XMsm# zF$0582?#UZOOvkv3bL1Y`ns||X5`{9kU8CJ7y}eC^mK6y(Kw%+AW?B($K2kx`_HY9 z=ZP`W;*p!0fTkU4d1!`vSboFyt=akR{ E05GC4r2qf` diff --git a/resources/icons/mode_simple_.png b/resources/icons/mode_simple_.png deleted file mode 100644 index aac2b61b042094981b9e8f37da32662fb48b8c5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1164 zcmV;71atd|P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3vrlEfwqg#YUlIRX+0!EwMqRc?^ur?Hv0vx#Rj z)Y^=UCAq&gv(*3kbI>37h~q#(EyWz8!zbjBrC^fW@j1@y!hU>?&F?R9;;=3tt@Akh z<7@0|eL-9wH`rRw^)*hmtvqQZx>a5Y{j4mQtaWK6@^Zv)jZj|qmGIR1`pa!^-tk)W z{yiAPXo`GZNV;e5aE!BxM+ZLnGGjQ37jbJIyzTLLt{ojRe~NdXy=mvliu+e7$lVgf zH;q=D^<2AMp%-e8$}bnTbT9Ft-54#6(T}GqAwsE0>!EIsvd^%vLQ22i7BLKein;A0 zVNzJ?)!P;4J`)gVmOOz;`dncCRw%}N|=L(n9sfu7>VCN z%_A)LUU;vY_j(&ARBnuw!brxG=KG+t;5Xx*XpCuHW|t0~U<>pm)6-~UlAA}Y0uUZc zQ{DC52R-@5J%RNgsJqMw4_I71QdH%KxBSl8W1YG{hv^+#TL~Z$YAc#y4+1W-SB~sV z#F(LD0-u7;#RsV%z^c-i2H1EX0Vm0-B zUIVFWRMVtcOY|{BjWJrBdsH!R!PKIeCCgTlPa$cF$x=!=l`Pp~3)394QBFDMQc$!Y zb-~>QD@v(SeGOG>tX5OawQR7@7B=1DW?S0wR+=>5@cOsdj9O~BmChYj>Y;0o-FoV| zmjSO0Kf=%vhmADyD0gbSUfUOH{6_9)YP_gTVqsrr4{8XT-BR$}PINK@F$oOfHVMGc zGMTx=A;=^*nYk=@DO5m>b;4;piGg6~EIRnk?m_NHZlvK7H~A-WG|~MZRWtds8cwV;;SRF>2M3%U0w3fzW{81y@op*u0!Z zpoyd634F=KwfBr`$w_W);Jq%5@A=GTKAZWpS4$mRT9E`5us+S1TW546KlbCLC0DbG z>uHLZ@mtH9;DOZv_Uzde;ToE-m(s}m)?4cyJLOS(uHR=*=gM>|4%e<6kM07r`4?&K z%FvSLJ7J!5p-*A<-u|mJcV*~9nk&LQL7`vB@?seJl`v1b&~?Y08-}hs=G-v!wKQ*r zpx?|1_L)RU1ZW#Jnm^Z`Fcd~pMhORs2+%Ry9}$3|)83 zxnbzKW6ljj*Bx_i7`pD5bHmVe$DA96t~=)3Fm&B9=Z2x{jyX3BU3bijVLblP$@DkZ z+afZyIfuyr000JJOGiWi{{a60|De66lK=n!32;bRa{vGmbN~PnbOGLGA9w%&00(qQ zO+^Rd3Kj@25=Sf;RsaA1DoI2^R4C75oO43_zpx}T0~;$d!>`|e8Qwns%YY1+7zlt- e1)~b6s{jD4<_My71_K=c0000jA5L~c#`DCC7XMsm# zF$0582?#UZOOvkv3bL1Y`ns||X5`|qGM=^hNk7N{PZ!4!jq}L~5)}t5p11s{PxMS< wGYd;=i{Jm>Xix1waaTrRMd7ygrh^O&r^`9I`v3VK2Wn&RboFyt=akR{00Jy79RL6T diff --git a/resources/icons/one_layer_lock_off.png b/resources/icons/one_layer_lock_off.png deleted file mode 100644 index f6e61d058cd6b9d384d80e95b5689b4a8658b1ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1001 zcmV5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5ue@z1?;r=>zE+9su?6S43Tu_%p%zkrHJM37X(%2tFBm55l0#9uH8 zk&slPTRRD1!J@H|CQ>ieqOa;@w9{UTJ7(rih~MU%Joov1&v~A6?g`W=?$w5aIDj4V zVO?`}ac&r|Fo1y|?^CrWs4{190+-QI3$M~pDd%307ndO=z(w?_YoPlWdry(cGX0Td zO=OqyqMt{%D9jdd9yf!$#i&F-iA$h4$G+2y4=0AP*EF`$b%fk*p5CS~8{ry0;9eB> zT8-<-fcj;`F+)#y`;xgI%zk0XavD}vcc30O;$DwKY(-PK;^|SojWhW^0sPVAduB$H z@+xY>p$MB(ZEM>?7$s$Oc2S&DF0-+fj-9-DUhU|K(2|1m^s%~~ruFPPN|>SeD;XPB zC6H@-svX-S)TJPuUCG$k%Gb|KjU><&rM1>>Or;lts3pYDR5Xq&^JjOtbB3pPDzU5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU54V+L&fRh&|M+UcJ7qZ*PhJ7U$-tVgrXW%>3tn&I~gHn?zEwB(J2m zlE!4@m!xJ%rII|GW2|+-k-&MNinjW6x|?9I8$t`PBOa17A-5QcO8bB+pwY4{t&xNY zDrtXIP5WcmeGm#SgDVn(BM{?;$Y|(%0sWnD<@E}14Y+Gr*6Kf!GT;Ff9v875xbzSv z`l0ncjP^oYBIKWev}}0lHRN^QL%;>gvKsAhjR18Sa*8u~cU~U|SzCh0_ zm>4jh5Bz}JN27o{l9FuT2rakV40fC11pP2S0aHHsz35bL$_F!klO90tduXdq22R*O z9-mtraPlFrBOqZfWaL9yjyW0mCav^52ix@$pdvH`*rgc&j}6Qd<6hrwj{fl( zG{>0$V@ytO|y3!ujay2w86I4sN26ZXP^B1p+} zY_`kMbBh6*kmQjxsj3|5BGT%r)+F##>g$lEe2y)&U~sjCk~AbKDO?7XNm`NDZ35>f zrJ!G$8I@)OMi2U>xp8Uan{+i@l9nW$1&9cL>AFhlPnk~rpX@7ulQjT0fakDr zilZ=7e4W;N>2x=nc3+%-Ncrq&Jevx7sIv Y0T%OASmVe+!2kdN07*qoM6N<$g0ThsfdBvi diff --git a/resources/icons/one_layer_unlock_off.png b/resources/icons/one_layer_unlock_off.png deleted file mode 100644 index 46fabfb0501592fb64bb87d32eaa658fc455941a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 997 zcmV5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5?kFhlSJFEMxp0StFCt(VK?^-86Z<~th; zh-YSIOixd%)oOwuFfcG+YirBK#)dRavqX73$9F6SNs^4>3x?+B=k4t5SYKZk1cBMv zS;ND_*4Eb4>-E27wU1kQ%wY)5&(9qk9Dp=U?d|Ppx7%8+)@7xQ;eH-dUC;6Hu{2GE zVW_XKPZUK8g@P!GgkdNM0_}ENqtVC`-Ob~A*IHd&Rj=2TN+ol1bBe{H{{DWGlao$P zPNZq7*=$-`TFR14QHb#_Kqa+hnAmi;kW=z-`>{TTgyq6CbeDt0%tzFTJ+D THHORC00000NkvXXu0mjfwn)tq diff --git a/resources/icons/one_layer_unlock_on.png b/resources/icons/one_layer_unlock_on.png deleted file mode 100644 index 265b926101933cce7995dccd8e0220bd8a862eea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1129 zcmV-v1eW`WP)5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5&TVWK2pYO(ypL_8q%8fK)8q|Ow1xeaP3gYBe=pIUk7HWmAg_izoo$S`h zp<^x7pr47`OZ1K?}1Aak%)*q6_M{E zV#}F+ipVz+c_bp?%Qfmku@^`Iuk!hP)UqsW+osWI5DW$}O_Q;)F(xM`E#MWfq?D32 zzaYioFTm{cm&0-gi!l~SiJvTd8w(^E>NlDi{{#UiCriB_w1WvpVcNIsvB0QWWEj%8T@RI61) z1dqpquIm_vf!FKBFbsmhAiA#O_xszRot+(kdtJcIa=8pZHk+kZs}YOENG6l`d_Htt zXJTT4sWBT zUIz$kKs68ubj<5Q0k*cbNT<`-w%s1tmCxq`ur**W6bfBgoGXvVgV*bI3p!+)Ccuv_ zAU8TX%I@xN`%$U3k%>m5^!D~*7zO~ErnTSV@i@R&4aiPSP5lms|3<=b92$)V)oK;P zFo;AVIF7^7(GitO1vv9bGMU^1zH~TtVPU~@a&q#|(OmWP^e{g^?*I>#QlH%3J_7G% zW@Z>19Q-d}XlRJ(>1lvBz-Q=8v5&J9zs%)wQOmL@m&-VgLm&{qG)?01IEh5U0^V|# v;;U9Zhebr>nTTXA+>>7-k`|FC*WHsp>Q69+U?zjU00000NkvXXu0mjf%y$mq diff --git a/resources/icons/pause_add.png b/resources/icons/pause_add.png deleted file mode 100644 index afe881de8bbea4b942cc0e9ae35bfba53c9dc057..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5883 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 S?=bzFkEE)orBEYh5&nO)^r2<| diff --git a/resources/icons/right_half_circle.png b/resources/icons/right_half_circle.png deleted file mode 100644 index ecc8980b3286942886d30c3a170691e848adc9df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 654 zcmV;90&)F`P)5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5-#MTcL~B zeAB7|aE})aPj!IsfKELi@O%kC`x>bH;07*qoM6N<$g1VU`!2kdN diff --git a/resources/icons/row.png b/resources/icons/row.png deleted file mode 100644 index 18a6034fd597baffa886ed65145183a5627310d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1923 zcmV-}2YmR6P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SONCmh2`B{bv2UMA8^>9>^_xpz(Zwiv zHGSLq3H|aI5Zvz1_kI(~wxin+U54kwW9Cucdb$m`J;B*OTejJ4{I%@@ zf>8zb*c#iI_`uhXSr{I0`E;)}#d9y*CP-YE^8KLAk%;OFC3F=|K z5w8Mb0b>(YG>U3={5Vr{c}XN_K%`<^x0tPRH8)C&*R&>g~Qf<`)#!5J8{j=*>r z3}8Xq!P%kYoE^*!&W>oYDa3*`l0i~Wj#K!Y^M|GRS;c!vrK}pckmGR4kTeUIs5#m$l@Jfwcz(V#zdB%*-p;@{ z&0L$;Nq;}I3(mEZ$j$}FlujvxM;AT$`>r%UQuwY!nm(5in*!(hIsNi&ud3RXZ)pp$ zSG2QV!WNGn>(dHd>xiq}wqoX{+DVpvQ7++aLD#g6OX>b-w4wFj`cYopZmnHz27ov& z5EDbYVJOR^3q<=2g57eW1;#aGgHH#V8;toH4K8`Jl}d&3@=}pfYw|Zxy9G?+ zsK^?gJuWRdZ^M>r;TGyMwx;$WbzHnR+oX2uy5DFDarF!UONb2Jf_vlM#f{w;Bs8QE z+5XuPwKw%8geQmw^0j~X#Wyz1pz{?)dT67m@{lr6*c*tjg=V1mlmY3}l6LO{%-17B z-RS~5Z{`bWI1M~?$8|MV7PDs-OD04cvU^A~ZUHMPBAWzlulxR?oMS80WF^jEN+huL zrk<8h(j|rBsl?qxB1`(FEp_E1tdZCxcFuPg?hb=b7$G7r2DyY7ZOt=`a3**ihxJbI z9tZqVy5MX8VWE+}=pQ=-$N7Y_OZi@ z=tF5w2o#apMis&FL3ii|c!_OOF@z@JT9LNYQDc2QFIw3yVCUxp#&_7Q3pMKNafE2* zJDmIk=j||hL$Obh31bl6A21yL`M$%Dhfx36arDtpD7D^Vd@h<53F|1d^8f$=eMv+?R5;6}lfP>eaS+8nyPOg{@Cs48h+uV9gzJ*R ze?TEk3T?&Uk3t2p5eq?xjgf;uuCc!qDe^a@NFkU)61#ALG>U?O&gG~L@2O~EF6Js96?B2zL=jM9-h43{auge5rD+;k#$uJ=f*m}I4TM;NkL?DUCb0n2FpujP_3yERzEr4X!YfPEZ{sG~-EP|Z%oVWl0002ov JPDHLkV1lKIrrrPm diff --git a/resources/icons/shape_ungroup.png b/resources/icons/shape_ungroup.png deleted file mode 100644 index 97aaceb23d4f899af7d44f31934bfd3418e0b04d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 803 zcmV+;1Kj+HP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0004x zP)t-s|NsAqiHV1Yhj@5+adB~mhK65XUqV7cI5;>bCns=la9>|vRaI3pGcyMV2O}dR zA0HnY8X5!y1ONa4h=_=Db90G_iPO{5goK2y%k`|t^{dGBsm1lD#r1D*Z^_BYXJ==F zgM*BbnZVWezSZ}=)Azg5_qx&deS?i-V`Hqz^}p5kzSQ@;)Azd4_qfsbx6t>s&i9+X z^@E3vadB~Vd48|P>$J}Iv(5LJyYoFgJz`>FgsIntujPfT72UgnYiagOH?c@ENg3Pc6)<}ujQh^>!7~sp1kOr zy6Bj<=9RSNlCk7$mfFU~#$8=qn!NL$zUrO3=$g3bm$v4Vv*nSo`&BV;i&CJcs;?~Xn$GgOfc=y%-0004EOGiWihy@);0002NNkllm#LnCN3cC$9hzU{zF7R#8<`*U)5x>e15H(bdy8Ff@W0BCTp{Vrph? zVadR5#Q_qKQInImwz0LdcW`ua1_`+6ySll1czSvJ`1)}I`CR@1=7B-MA)#U65s@GT z3Q^H9cCm5s35iL`DIfvvR33&jZ=dvx%&hDjm_@lj<$3u9g+)+4Z*fUda%ow4MI|3Z zpsKp2wl1frzM-)RBET;o2&RRag)u!30LOeLiBJkwz5oCK8FWQhbW?9;ba!ELWdK2B hZ(?O2No`?gWm08fWO;GPWjp`?002ovPDHLkV1nO6dG!DQ diff --git a/resources/icons/table.png b/resources/icons/table.png deleted file mode 100644 index 3bc0bd32fceb21d70368f7842a00a53d6369ba48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmV;?0WSWDP)zJNu3H-P zO&@UpeyZQXi7jKe-Hk?r-sue;aDce_XqkvXP+W#F_*ot`jB?BS93Uw71|U^ZjLH`yP%FO7U<6!nLCG} z$SDlW5rH9Dk4UMwL=F#Vj*HNvx$E|B9UM+u!@1iBF%Gd+oU3TUe39n_r2$wci*{SUruWo zvta--*}M@BO?a0hE8eCToOFu!(G}H9eSCg?mb&)!fK9FUeX3Xeynn4_J#K1Xa|(}X zx{(*25}w=2>x%bVl8E4 zgolNFne?VsJ&*bmS3JA4pmgyLOu~eiz{@m~1PL(6sKkIw$4|e!QK#NtuAd_(wVFho zZ45R@k|Iy9sGHI~E^9*cxIAge5L0*XceZ9?$Y1$_YX%x$E$g!fnvS5fXIbATmQ^|h zhs@=sSgX$!VdP!(LQV4>gL@Y)uWMTD46X{${;WrhXjyWI+Y<@+IEU5z>% diff --git a/resources/icons/variable_layer_height_reset.png b/resources/icons/variable_layer_height_reset.png deleted file mode 100644 index 6e051fe95104027f06f524c7e60e090dcdc05bce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1050 zcmV+#1m*jQP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1FuO$K~z{r?U>7J z6Hye#zf5A2rb(MV6k01dMRcY*JQ}3Bi`bxVCE#POqs!t-;76OIta?#Gyc|1#~*RY&!*OSs9OVC$B&p8 z9K_8JeTcG5ZvZy9LJW*zNqf=3qkmF1R|w3zxL?W%W}1K)uDdb&?Hi&aBM=JpQ0esu z9y*Mt`S}^wNL0$o`*$%Djq)sI>b~s*ELN(exYDaCwW6ezPsBoSB@(mc z#peA^Ghp{fu~0HeR^k%NTBlaC@#7~MyLg$g);7kDwK8`80vp-0muUqdV@|4VjBb+A zjirpK#1q$acvHs&LQG)vD2%AE5c4v6;6yy`oO$u_ytop}R!m$qblRu|YN}L0n4JY^ zn~7Fy)Tp7}qf}<6pRcMPjXkuj_I1YsHW#|=VYsjGF)7e_6+Uw#jwBY@j^^~8rzmgn zQUqp0NeP}dHbG521`&c%RYk6pz-TEJ*t!k13gIMrjKfEeE~PbJGo1eUTf##qxB{K9 z)VpEv#A2yiB1hgYN*0U+WnU9C1VwDLQ`AqsK7WScU=S01AD}BMg|@U5Pd08st$3^} zRreLR!*+C~JfIH_-k6iNpfkY3A{=SXfe=+*vTw`e{ep6Wk)YV)P>L`$Fo21nAyhwl zfK`Df80+uHkKT9CSCpfW-eVrETaR_i3V61h0_eOtuWACf(6azkHoeB1F#oDFFQv)L zD<_!c1qEQyIch~wf-;2hPXy)hL+SJpUGqGM?*si9d)o^^5TGJgkQJ-@Hm!BMZxAR; zJ$f4BJ%~Hxiak(=ciy}o&X5DK_9T-hUU91jVY3r{n*VL5()O})Hr8~I4e!{Q@$}KE zRIG2UnSI&3h1s;a1@R^9jFTyDFqv{5$s(M83<}HtgO^2%XbAt8@?f$k4<@64pX?TS U6@jyFr~m)}07*qoM6N<$f;Z&d_5c6? diff --git a/resources/icons/variable_layer_height_tooltip.png b/resources/icons/variable_layer_height_tooltip.png deleted file mode 100644 index 18200529278f5b24de50c01de9121a884db25052..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10017 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 From 34f5dde024839adecb919e07aef5edfb5dd63a07 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 7 Oct 2021 10:37:49 +0200 Subject: [PATCH 06/22] #6380 - Fixed non-uniform scaling of a volume using the sidebar fields --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index b8c053f888..d5a1a5659f 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -547,8 +547,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) } else { m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); - m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); - m_new_scale = volume->get_instance_scaling_factor() * 100.; + m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); + m_new_scale = volume->get_instance_scaling_factor() * 100.; } m_new_enabled = true; @@ -569,7 +569,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = volume->get_volume_offset(); m_new_rotation = volume->get_volume_rotation() * (180. / M_PI); m_new_scale = volume->get_volume_scaling_factor() * 100.; - m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box().size())); + m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size())); m_new_enabled = true; } else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) { @@ -861,7 +861,7 @@ void ObjectManipulation::change_scale_value(int axis, double value) Vec3d scale = m_cache.scale; scale(axis) = value; - this->do_scale(axis, scale); + this->do_scale(axis, 0.01 * scale); m_cache.scale = scale; m_cache.scale_rounded(axis) = DBL_MAX; @@ -880,14 +880,21 @@ void ObjectManipulation::change_size_value(int axis, double value) const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d ref_size = m_cache.size; - if (selection.is_single_volume() || selection.is_single_modifier()) - ref_size = selection.get_volume(*selection.get_volume_idxs().begin())->bounding_box().size(); + if (selection.is_single_volume() || selection.is_single_modifier()) { + const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); + const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor()); + const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor()); + const Vec3d local_change = local_size.cwiseQuotient(local_ref_size); + + size = local_change.cwiseProduct(v->get_volume_scaling_factor()); + ref_size = Vec3d::Ones(); + } else if (selection.is_single_full_instance()) ref_size = m_world_coordinates ? selection.get_unscaled_instance_bounding_box().size() : wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size(); - this->do_scale(axis, 100. * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); + this->do_scale(axis, size.cwiseQuotient(ref_size)); m_cache.size = size; m_cache.size_rounded(axis) = DBL_MAX; @@ -910,7 +917,7 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const scaling_factor = scale(axis) * Vec3d::Ones(); selection.start_dragging(); - selection.scale(scaling_factor * 0.01, transformation_type); + selection.scale(scaling_factor, transformation_type); wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale")); } From 68fd37b300e18052a5b445080dac721f26da05ee Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 11:49:34 +0200 Subject: [PATCH 07/22] Added SVG-file for G-CodeViewer logo --- resources/icons/PrusaSlicer-gcodeviewer.svg | 73 +++++++++++++++++++ ...{prusa_slicer_logo.svg => PrusaSlicer.svg} | 0 src/slic3r/GUI/AboutDialog.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 4 +- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/KBShortcutsDialog.cpp | 2 +- src/slic3r/GUI/SysInfoDialog.cpp | 2 +- 7 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 resources/icons/PrusaSlicer-gcodeviewer.svg rename resources/icons/{prusa_slicer_logo.svg => PrusaSlicer.svg} (100%) diff --git a/resources/icons/PrusaSlicer-gcodeviewer.svg b/resources/icons/PrusaSlicer-gcodeviewer.svg new file mode 100644 index 0000000000..6312beee32 --- /dev/null +++ b/resources/icons/PrusaSlicer-gcodeviewer.svg @@ -0,0 +1,73 @@ + + + + + + + diff --git a/resources/icons/prusa_slicer_logo.svg b/resources/icons/PrusaSlicer.svg similarity index 100% rename from resources/icons/prusa_slicer_logo.svg rename to resources/icons/PrusaSlicer.svg diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index a6b99a08ba..05f301186a 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -220,7 +220,7 @@ AboutDialog::AboutDialog() main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20); // logo - m_logo_bitmap = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192); + m_logo_bitmap = ScalableBitmap(this, wxGetApp().logo_name(), 192); m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp()); hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e1fcc029a6..e2a9df25d5 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -193,7 +193,7 @@ public: // load bitmap for logo BitmapCache bmp_cache; int logo_size = lround(width * 0.25); - wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().is_editor() ? "prusa_slicer_logo" : "add_gcode", logo_size, logo_size); + wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().logo_name(), logo_size, logo_size); wxCoord margin = int(m_scale * 20); @@ -883,7 +883,7 @@ bool GUI_App::on_init_inner() } // create splash screen with updated bmp - scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("prusa_slicer_logo", nullptr, 400), + scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("PrusaSlicer", nullptr, 400), wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, splashscreen_pos); #ifndef __linux__ wxYield(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index a581cf8b30..3061bbe132 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -166,6 +166,7 @@ public: bool is_editor() const { return m_app_mode == EAppMode::Editor; } bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; } bool is_recreating_gui() const { return m_is_recreating_gui; } + std::string logo_name() const { return is_editor() ? "PrusaSlicer" : "PrusaSlicer-gcodeviewer"; } // To be called after the GUI is fully built up. // Process command line parameters cached in this->init_params, diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 0bed7eb74f..d16161f890 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -270,7 +270,7 @@ wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_f sizer->AddStretchSpacer(); // logo - m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_32px.png" : "PrusaSlicer-gcodeviewer_32px.png", 32); + m_logo_bmp = ScalableBitmap(this, wxGetApp().logo_name(), 32); m_header_bitmap = new wxStaticBitmap(panel, wxID_ANY, m_logo_bmp.bmp()); sizer->Add(m_header_bitmap, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index 6f8eeedccd..5475a36eaa 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -94,7 +94,7 @@ SysInfoDialog::SysInfoDialog() main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10); // logo - m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192); + m_logo_bmp = ScalableBitmap(this, wxGetApp().logo_name(), 192); m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bmp.bmp()); hsizer->Add(m_logo, 0, wxALIGN_CENTER_VERTICAL); From a2b99db0df1be25d1e21c052f2fc33ca45a199d3 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 11:51:12 +0200 Subject: [PATCH 08/22] MSW specific:Added dark mode for G-CodeViewer --- src/libslic3r/AppConfig.cpp | 6 +++--- src/slic3r/GUI/Preferences.cpp | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 26c5b470e3..fd2c4f8651 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -85,9 +85,6 @@ void AppConfig::set_defaults() if (get("associate_stl").empty()) set("associate_stl", "0"); - if (get("dark_color_mode").empty()) - set("dark_color_mode", "0"); - if (get("tabs_as_menu").empty()) set("tabs_as_menu", "0"); #endif // _WIN32 @@ -179,6 +176,9 @@ void AppConfig::set_defaults() #ifdef _WIN32 if (get("use_legacy_3DConnexion").empty()) set("use_legacy_3DConnexion", "0"); + + if (get("dark_color_mode").empty()) + set("dark_color_mode", "0"); #endif // _WIN32 // Remove legacy window positions/sizes diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 880723693c..9d12369227 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -343,6 +343,7 @@ void PreferencesDialog::build(size_t selected_tab) m_optgroup_gui->append_single_option_line(option); #ifdef _MSW_DARK_MODE + } def.label = L("Use Dark color mode (experimental)"); def.type = coBool; def.tooltip = L("If enabled, UI will use Dark mode colors. " @@ -351,6 +352,7 @@ void PreferencesDialog::build(size_t selected_tab) option = Option(def, "dark_color_mode"); m_optgroup_gui->append_single_option_line(option); + if (is_editor) { def.label = L("Set settings tabs as menu items (experimental)"); def.type = coBool; def.tooltip = L("If enabled, Settings Tabs will be placed as menu items. " From fb3ed367ad71b589b328f02b5532b76ef399080f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 11:53:04 +0200 Subject: [PATCH 09/22] Try to fix a focus for Application after closing of the "fix thought NetFab" ProgressBarDialog --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d2a6b6e9aa..e6e7336f7e 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -4123,8 +4123,7 @@ void ObjectList::fix_through_netfabb() Plater::TakeSnapshot snapshot(plater, _L("Fix through NetFabb")); // Open a progress dialog. - wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100, - nullptr, // ! parent of the wxProgressDialog should be nullptr to avoid flickering during the model fixing + wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100, plater, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); int model_idx{ 0 }; if (vol_idxs.empty()) { From 992a279bef876b8ad9622a1f8f512136b7c408a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 11:25:17 +0200 Subject: [PATCH 10/22] Removed the vertical space in the below information about how to use gizmo for all painting gizmos. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 1 - src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 5 +---- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 437106fedd..6f11329415 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -129,7 +129,6 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l for (const auto &t : std::array{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); - m_imgui->text(""); ImGui::Separator(); ImGui::AlignTextToFramePadding(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index d7824357f7..7bd4449524 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -42,7 +42,6 @@ void GLGizmoMmuSegmentation::on_shutdown() std::string GLGizmoMmuSegmentation::on_get_name() const { - // FIXME Lukas H.: Discuss and change shortcut return _u8L("Multimaterial painting"); } @@ -107,7 +106,6 @@ void GLGizmoMmuSegmentation::init_extruders_data() bool GLGizmoMmuSegmentation::on_init() { - // FIXME Lukas H.: Discuss and change shortcut m_shortcut_key = WXK_CONTROL_N; m_desc["reset_direction"] = _L("Reset direction"); @@ -289,7 +287,6 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott for (const auto &t : std::array{"first_color", "second_color", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); - m_imgui->text(""); ImGui::Separator(); ImGui::AlignTextToFramePadding(); @@ -400,7 +397,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(cursor_type_offset +cursor_type_radio_sphere + m_imgui->scaled(0.f)); + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + m_imgui->scaled(0.f)); ImGui::PushItemWidth(cursor_type_radio_circle); if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE)) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index b235287725..286d322563 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -119,7 +119,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) for (const auto &t : std::array{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); - m_imgui->text(""); + ImGui::Separator(); if (m_imgui->button(m_desc.at("remove_all"))) { Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), From 6012bf1e038fca849e39e902513fa453fada74d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 6 Oct 2021 15:34:28 +0200 Subject: [PATCH 11/22] Removed unintended space after ImGui::SliderFloat in all painting gizmos. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 6 +++--- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 6f11329415..9a9739b906 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -139,7 +139,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l "placed after the number with no whitespace in between."); ImGui::SameLine(autoset_slider_left); ImGui::PushItemWidth(window_width - autoset_slider_left); - if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) { + if (m_imgui->slider_float("##angle_threshold_deg", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) { m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg); if (! m_parent.is_using_slope()) { m_parent.use_slope(true); @@ -188,7 +188,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l m_imgui->text(m_desc.at("cursor_size")); ImGui::SameLine(cursor_slider_left); ImGui::PushItemWidth(window_width - cursor_slider_left); - m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); + m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); @@ -252,7 +252,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); auto clp_dist = float(m_c->object_clipper()->get_position()); - if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) + if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); if (ImGui::IsItemHovered()) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 7bd4449524..16310cbc54 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -431,7 +431,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->text(m_desc.at("cursor_size")); ImGui::SameLine(sliders_width); ImGui::PushItemWidth(window_width - sliders_width); - m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); + m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); @@ -489,7 +489,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::SameLine(sliders_width); ImGui::PushItemWidth(window_width - sliders_width); auto clp_dist = float(m_c->object_clipper()->get_position()); - if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) + if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 286d322563..3d897b0ded 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -144,7 +144,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) m_imgui->text(m_desc.at("cursor_size")); ImGui::SameLine(cursor_size_slider_left); ImGui::PushItemWidth(window_width - cursor_size_slider_left); - m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); + m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); @@ -206,7 +206,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); auto clp_dist = float(m_c->object_clipper()->get_position()); - if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) + if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); if (ImGui::IsItemHovered()) { From 925d3fad1f20fbb5edfdbee0be9407acf8e20350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 6 Oct 2021 21:54:40 +0200 Subject: [PATCH 12/22] Fixed the wrong calculation of caption text size in all painting gizmos, which could lead to showing unintended space after ImGui::SliderFloat. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 11 ++++++----- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 10 +++++----- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 11 ++++++----- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 9a9739b906..6a892e9c13 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -108,13 +108,14 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l float caption_max = 0.f; float total_text_max = 0.f; for (const auto &t : std::array{"enforce", "block", "remove"}) { - caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); - total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x); + total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x); } - caption_max += m_imgui->scaled(1.f); - total_text_max += m_imgui->scaled(1.f); + total_text_max += caption_max + m_imgui->scaled(1.f); + caption_max += m_imgui->scaled(1.f); - float window_width = minimal_slider_width + std::max(autoset_slider_left, std::max(cursor_slider_left, clipping_slider_left)); + float sliders_width = std::max(autoset_slider_left, std::max(cursor_slider_left, clipping_slider_left)); + float window_width = minimal_slider_width + sliders_width; window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 16310cbc54..c9edb6c932 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -262,13 +262,13 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f); float caption_max = 0.f; - float total_text_max = 0.; + float total_text_max = 0.f; for (const auto &t : std::array{"first_color", "second_color", "remove"}) { - caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); - total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x); + total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x); } - caption_max += m_imgui->scaled(1.f); - total_text_max += m_imgui->scaled(1.f); + total_text_max += caption_max + m_imgui->scaled(1.f); + caption_max += m_imgui->scaled(1.f); float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left)); float window_width = minimal_slider_width + sliders_width; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 3d897b0ded..fea506eaa8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -98,13 +98,14 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) float caption_max = 0.f; float total_text_max = 0.f; for (const auto &t : std::array{"enforce", "block", "remove"}) { - caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); - total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x); + total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x); } - caption_max += m_imgui->scaled(1.f); - total_text_max += m_imgui->scaled(1.f); + total_text_max += caption_max + m_imgui->scaled(1.f); + caption_max += m_imgui->scaled(1.f); - float window_width = minimal_slider_width + std::max(cursor_size_slider_left, clipping_slider_left); + float sliders_width = std::max(cursor_size_slider_left, clipping_slider_left); + float window_width = minimal_slider_width + sliders_width; window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); From dfb4ccdb13fa514c718b8f451fb71e7e3764ce58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 11:51:38 +0200 Subject: [PATCH 13/22] Reworked seam painting gizmo to the same layout as multi-material painting gizmo. --- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 78 ++++++++++++--------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index fea506eaa8..6723818351 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -87,11 +87,11 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); const float cursor_size_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x - + m_imgui->scaled(2.5f); - const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x - + m_imgui->scaled(2.5f); + + const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc["cursor_type"]).x + m_imgui->scaled(1.f); + const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); + const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f); + const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float minimal_slider_width = m_imgui->scaled(4.f); @@ -108,7 +108,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) float window_width = minimal_slider_width + sliders_width; window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); - window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); + window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_sphere + cursor_type_radio_circle); auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f); @@ -122,29 +122,12 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::Separator(); - if (m_imgui->button(m_desc.at("remove_all"))) { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), - UndoRedo::SnapshotType::GizmoAction); - ModelObject* mo = m_c->selection_info()->model_object(); - int idx = -1; - for (ModelVolume* mv : mo->volumes) { - if (mv->is_model_part()) { - ++idx; - m_triangle_selectors[idx]->reset(); - m_triangle_selectors[idx]->request_update_render_data(); - } - } - - update_model_object(); - m_parent.set_as_dirty(); - } - const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("cursor_size")); - ImGui::SameLine(cursor_size_slider_left); - ImGui::PushItemWidth(window_width - cursor_size_slider_left); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -156,12 +139,12 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("cursor_type")); - ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width1); - bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; - if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) - sphere_sel = true; + float cursor_type_offset = cursor_type_radio_left + (window_width - cursor_type_radio_left - cursor_type_radio_sphere - cursor_type_radio_circle + m_imgui->scaled(0.5f)) / 2.f; + ImGui::SameLine(cursor_type_offset); + ImGui::PushItemWidth(cursor_type_radio_sphere); + if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE)) + m_cursor_type = TriangleSelector::CursorType::SPHERE; if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -171,11 +154,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::EndTooltip(); } - ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width2); - - if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) - sphere_sel = false; + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere); + ImGui::PushItemWidth(cursor_type_radio_circle); + if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE)) + m_cursor_type = TriangleSelector::CursorType::CIRCLE; if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -185,12 +167,6 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::EndTooltip(); } - m_cursor_type = sphere_sel - ? TriangleSelector::CursorType::SPHERE - : TriangleSelector::CursorType::CIRCLE; - - - ImGui::Separator(); if (m_c->object_clipper()->get_position() == 0.f) { ImGui::AlignTextToFramePadding(); @@ -204,8 +180,8 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) } } - ImGui::SameLine(clipping_slider_left); - ImGui::PushItemWidth(window_width - clipping_slider_left); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); auto clp_dist = float(m_c->object_clipper()->get_position()); if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); @@ -218,6 +194,22 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::EndTooltip(); } + ImGui::Separator(); + if (m_imgui->button(m_desc.at("remove_all"))) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), UndoRedo::SnapshotType::GizmoAction); + ModelObject *mo = m_c->selection_info()->model_object(); + int idx = -1; + for (ModelVolume *mv : mo->volumes) + if (mv->is_model_part()) { + ++idx; + m_triangle_selectors[idx]->reset(); + m_triangle_selectors[idx]->request_update_render_data(); + } + + update_model_object(); + m_parent.set_as_dirty(); + } + m_imgui->end(); } From 99edfd22ce17895051a6a2e9325806aff174ae29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 11:59:37 +0200 Subject: [PATCH 14/22] Improved the alignment of tool type and brush type in the multi-material gizmo. --- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index c9edb6c932..e2088d4acb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -318,15 +318,13 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::Separator(); m_imgui->text(m_desc.at("tool_type")); - - float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(2.f)) / 2.f; - ImGui::NewLine(); - ImGui::SameLine(tool_type_offset + m_imgui->scaled(0.f)); + float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(1.5f)) / 2.f; + ImGui::SameLine(tool_type_offset); ImGui::PushItemWidth(tool_type_radio_brush); - if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BRUSH)) { - m_tool_type = GLGizmoMmuSegmentation::ToolType::BRUSH; + if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == ToolType::BRUSH)) { + m_tool_type = ToolType::BRUSH; for (auto &triangle_selector : m_triangle_selectors) { triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->request_update_render_data(); @@ -341,10 +339,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(tool_type_offset + tool_type_radio_brush + m_imgui->scaled(0.f)); + ImGui::SameLine(tool_type_offset + tool_type_radio_brush); ImGui::PushItemWidth(tool_type_radio_smart_fill); - if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::SMART_FILL)) { - m_tool_type = GLGizmoMmuSegmentation::ToolType::SMART_FILL; + if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == ToolType::SMART_FILL)) { + m_tool_type = ToolType::SMART_FILL; for (auto &triangle_selector : m_triangle_selectors) { triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->request_update_render_data(); @@ -359,10 +357,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_smart_fill + m_imgui->scaled(0.f)); + ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_smart_fill); ImGui::PushItemWidth(tool_type_radio_bucket_fill); - if (m_imgui->radio_button(m_desc["tool_bucket_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BUCKET_FILL)) { - m_tool_type = GLGizmoMmuSegmentation::ToolType::BUCKET_FILL; + if (m_imgui->radio_button(m_desc["tool_bucket_fill"], m_tool_type == ToolType::BUCKET_FILL)) { + m_tool_type = ToolType::BUCKET_FILL; for (auto &triangle_selector : m_triangle_selectors) { triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->request_update_render_data(); @@ -383,8 +381,8 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->text(m_desc.at("cursor_type")); ImGui::NewLine(); - float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(2.f)) / 2.f; - ImGui::SameLine(cursor_type_offset + m_imgui->scaled(0.f)); + float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(1.5f)) / 2.f; + ImGui::SameLine(cursor_type_offset); ImGui::PushItemWidth(cursor_type_radio_sphere); if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE)) m_cursor_type = TriangleSelector::CursorType::SPHERE; @@ -397,7 +395,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + m_imgui->scaled(0.f)); + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere); ImGui::PushItemWidth(cursor_type_radio_circle); if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE)) @@ -411,7 +409,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle + m_imgui->scaled(0.f)); + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle); ImGui::PushItemWidth(cursor_type_radio_pointer); if (m_imgui->radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER)) @@ -491,6 +489,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott auto clp_dist = float(m_c->object_clipper()->get_position()); if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); From 8c9c8a9cc4590e99c2032d9897654d921627bdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 12:11:26 +0200 Subject: [PATCH 15/22] Prepared the FDM support gizmo for smart fill. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 218 +++++++++++++------ 1 file changed, 152 insertions(+), 66 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 6a892e9c13..307f0d0282 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -51,10 +51,17 @@ bool GLGizmoFdmSupports::on_init() m_desc["remove_all"] = _L("Remove all selection"); m_desc["circle"] = _L("Circle"); m_desc["sphere"] = _L("Sphere"); + m_desc["pointer"] = _L("Pointer"); m_desc["highlight_by_angle"] = _L("Highlight by angle"); m_desc["enforce_button"] = _L("Enforce"); m_desc["cancel"] = _L("Cancel"); + m_desc["tool_type"] = _L("Tool type") + ": "; + m_desc["tool_brush"] = _L("Brush"); + m_desc["tool_smart_fill"] = _L("Smart fill"); + + m_desc["smart_fill_angle"] = _L("Smart fill angle"); + return true; } @@ -89,22 +96,26 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: - const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, - m_imgui->calc_text_size(m_desc.at("reset_direction")).x) - + m_imgui->scaled(1.5f); - const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); - const float autoset_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x - + m_imgui->scaled(2.5f); - const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x - + m_imgui->scaled(2.5f); + const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, + m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); + const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); + const float autoset_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).x + m_imgui->scaled(1.f); + const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.f); + + const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f); + const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); + const float cursor_type_radio_pointer = m_imgui->calc_text_size(m_desc["pointer"]).x + m_imgui->scaled(2.5f); + const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float button_enforce_width = m_imgui->calc_text_size(m_desc.at("enforce_button")).x; const float button_cancel_width = m_imgui->calc_text_size(m_desc.at("cancel")).x; const float buttons_width = std::max(button_enforce_width, button_cancel_width) + m_imgui->scaled(0.5f); const float minimal_slider_width = m_imgui->scaled(4.f); + const float tool_type_radio_left = m_imgui->calc_text_size(m_desc["tool_type"]).x + m_imgui->scaled(1.f); + const float tool_type_radio_brush = m_imgui->calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f); + const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f); + float caption_max = 0.f; float total_text_max = 0.f; for (const auto &t : std::array{"enforce", "block", "remove"}) { @@ -114,11 +125,12 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l total_text_max += caption_max + m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f); - float sliders_width = std::max(autoset_slider_left, std::max(cursor_slider_left, clipping_slider_left)); + float sliders_width = std::max(std::max(autoset_slider_left, smart_fill_slider_left), std::max(cursor_slider_left, clipping_slider_left)); float window_width = minimal_slider_width + sliders_width; window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); - window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); + window_width = std::max(window_width, cursor_type_radio_circle + cursor_type_radio_sphere + cursor_type_radio_pointer); + window_width = std::max(window_width, tool_type_radio_left + tool_type_radio_brush + tool_type_radio_smart_fill); window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f)); auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { @@ -138,8 +150,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in FDM supports gizmo," "placed after the number with no whitespace in between."); - ImGui::SameLine(autoset_slider_left); - ImGui::PushItemWidth(window_width - autoset_slider_left); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); if (m_imgui->slider_float("##angle_threshold_deg", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) { m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg); if (! m_parent.is_using_slope()) { @@ -163,79 +175,136 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l } m_imgui->disabled_end(); - ImGui::Separator(); - - if (m_imgui->button(m_desc.at("remove_all"))) { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), - UndoRedo::SnapshotType::GizmoAction); - ModelObject* mo = m_c->selection_info()->model_object(); - int idx = -1; - for (ModelVolume* mv : mo->volumes) { - if (mv->is_model_part()) { - ++idx; - m_triangle_selectors[idx]->reset(); - m_triangle_selectors[idx]->request_update_render_data(); - } - } - - update_model_object(); - m_parent.set_as_dirty(); - } - - const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; - ImGui::AlignTextToFramePadding(); - m_imgui->text(m_desc.at("cursor_size")); - ImGui::SameLine(cursor_slider_left); - ImGui::PushItemWidth(window_width - cursor_slider_left); - m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - + ImGui::Separator(); ImGui::AlignTextToFramePadding(); - m_imgui->text(m_desc.at("cursor_type")); - ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width1); + m_imgui->text(m_desc["tool_type"]); - bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; - if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) - sphere_sel = true; + float tool_type_offset = tool_type_radio_left + (window_width - tool_type_radio_left - tool_type_radio_brush - tool_type_radio_smart_fill + m_imgui->scaled(0.5f)) / 2.f; + ImGui::SameLine(tool_type_offset); + ImGui::PushItemWidth(tool_type_radio_brush); + if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == ToolType::BRUSH)) + m_tool_type = ToolType::BRUSH; if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); + ImGui::TextUnformatted(_L("Paints facets according to the chosen painting brush.").ToUTF8().data()); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } - ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width2); - - if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) - sphere_sel = false; + ImGui::SameLine(tool_type_offset + tool_type_radio_brush); + ImGui::PushItemWidth(tool_type_radio_smart_fill); + if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == ToolType::SMART_FILL)) + m_tool_type = ToolType::SMART_FILL; if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::TextUnformatted(_L("Paints neighboring facets whose relative angle is less or equal to set angle.").ToUTF8().data()); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } - m_cursor_type = sphere_sel - ? TriangleSelector::CursorType::SPHERE - : TriangleSelector::CursorType::CIRCLE; + ImGui::Separator(); + if (m_tool_type == ToolType::BRUSH) { + m_imgui->text(m_desc.at("cursor_type")); + ImGui::NewLine(); + float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(1.5f)) / 2.f; + ImGui::SameLine(cursor_type_offset); + ImGui::PushItemWidth(cursor_type_radio_sphere); + if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE)) + m_cursor_type = TriangleSelector::CursorType::SPHERE; + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere); + ImGui::PushItemWidth(cursor_type_radio_circle); + + if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE)) + m_cursor_type = TriangleSelector::CursorType::CIRCLE; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle); + ImGui::PushItemWidth(cursor_type_radio_pointer); + + if (m_imgui->radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER)) + m_cursor_type = TriangleSelector::CursorType::POINTER; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Paints only one facet.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_imgui->disabled_begin(m_cursor_type != TriangleSelector::CursorType::SPHERE && m_cursor_type != TriangleSelector::CursorType::CIRCLE); + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("cursor_size")); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); + m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_imgui->checkbox(_L("Split triangles"), m_triangle_splitting_enabled); + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Split bigger facets into smaller ones while the object is painted.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_imgui->disabled_end(); + } else { + assert(m_tool_type == ToolType::SMART_FILL); + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc["smart_fill_angle"] + ":"); + std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo," + "placed after the number with no whitespace in between."); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); + if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data())) + for (auto &triangle_selector : m_triangle_selectors) { + triangle_selector->seed_fill_unselect_all_triangles(); + triangle_selector->request_update_render_data(); + } + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + } ImGui::Separator(); if (m_c->object_clipper()->get_position() == 0.f) { @@ -250,8 +319,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l } } - ImGui::SameLine(clipping_slider_left); - ImGui::PushItemWidth(window_width - clipping_slider_left); + ImGui::SameLine(sliders_width); + ImGui::PushItemWidth(window_width - sliders_width); auto clp_dist = float(m_c->object_clipper()->get_position()); if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) m_c->object_clipper()->set_position(clp_dist, true); @@ -263,6 +332,23 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } + + ImGui::Separator(); + if (m_imgui->button(m_desc.at("remove_all"))) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), UndoRedo::SnapshotType::GizmoAction); + ModelObject *mo = m_c->selection_info()->model_object(); + int idx = -1; + for (ModelVolume *mv : mo->volumes) + if (mv->is_model_part()) { + ++idx; + m_triangle_selectors[idx]->reset(); + m_triangle_selectors[idx]->request_update_render_data(); + } + + update_model_object(); + m_parent.set_as_dirty(); + } + m_imgui->end(); } @@ -291,7 +377,7 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) // Now calculate dot product of vert_direction and facets' normals. int idx = 0; const indexed_triangle_set &its = mv->mesh().its; - for (stl_triangle_vertex_indices face : its.indices) { + for (const stl_triangle_vertex_indices &face : its.indices) { if (its_face_normal(its, face).dot(down) > dot_limit) { m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER); m_triangle_selectors.back()->request_update_render_data(); From 2b59a16dc7d3206a52eee5201df1bf21eb21e06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 12:45:53 +0200 Subject: [PATCH 16/22] Refactored rendering of the contour around areas selected by smart fill to prepare it for the FDM supports painting gizmo. --- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 87 ++++--------------- .../GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 18 ---- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 63 +++++++++++++- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 41 +++++++++ 4 files changed, 116 insertions(+), 93 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index e2088d4acb..3153b880b9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -592,11 +592,6 @@ std::array GLGizmoMmuSegmentation::get_cursor_sphere_right_button_colo return {color[0], color[1], color[2], 0.25f}; } -static std::array get_seed_fill_color(const std::array &base_color) -{ - return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f}; -} - void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) { if (m_update_render_data) @@ -612,14 +607,14 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) if (m_gizmo_scene.has_VBOs(color_idx)) { if (color_idx > m_colors.size()) // Seed fill VBO - shader->set_uniform("uniform_color", get_seed_fill_color(color_idx == (m_colors.size() + 1) ? m_default_volume_color : m_colors[color_idx - (m_colors.size() + 1) - 1])); + shader->set_uniform("uniform_color", TriangleSelectorGUI::get_seed_fill_color(color_idx == (m_colors.size() + 1) ? m_default_volume_color : m_colors[color_idx - (m_colors.size() + 1) - 1])); else // Normal VBO shader->set_uniform("uniform_color", color_idx == 0 ? m_default_volume_color : m_colors[color_idx - 1]); m_gizmo_scene.render(color_idx); } - if (m_gizmo_scene.has_contour_VBO()) { + if (m_paint_contour.has_VBO()) { ScopeGuard guard_gouraud([shader]() { shader->start_using(); }); shader->stop_using(); @@ -627,7 +622,7 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) contour_shader->start_using(); glsafe(::glDepthFunc(GL_LEQUAL)); - m_gizmo_scene.render_contour(); + m_paint_contour.render(); glsafe(::glDepthFunc(GL_LESS)); contour_shader->stop_using(); @@ -666,23 +661,24 @@ void TriangleSelectorMmGui::update_render_data() m_gizmo_scene.finalize_triangle_indices(); + m_paint_contour.release_geometry(); std::vector contour_edges = this->get_seed_fill_contour(); - m_gizmo_scene.contour_vertices.reserve(contour_edges.size() * 6); + m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); for (const Vec2i &edge : contour_edges) { - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); - m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); } - m_gizmo_scene.contour_indices.assign(m_gizmo_scene.contour_vertices.size() / 3, 0); - std::iota(m_gizmo_scene.contour_indices.begin(), m_gizmo_scene.contour_indices.end(), 0); - m_gizmo_scene.contour_indices_size = m_gizmo_scene.contour_indices.size(); + m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0); + std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0); + m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); - m_gizmo_scene.finalize_contour(); + m_paint_contour.finalize_geometry(); } wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const @@ -706,14 +702,6 @@ void GLMmSegmentationGizmo3DScene::release_geometry() { glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); triangle_indices_VBO_id = 0; } - if (this->contour_vertices_VBO_id) { - glsafe(::glDeleteBuffers(1, &this->contour_vertices_VBO_id)); - this->contour_vertices_VBO_id = 0; - } - if (this->contour_indices_VBO_id) { - glsafe(::glDeleteBuffers(1, &this->contour_indices_VBO_id)); - this->contour_indices_VBO_id = 0; - } this->clear(); } @@ -741,29 +729,6 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -void GLMmSegmentationGizmo3DScene::render_contour() const -{ - assert(this->contour_vertices_VBO_id != 0); - assert(this->contour_indices_VBO_id != 0); - - glsafe(::glLineWidth(4.0f)); - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_vertices_VBO_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); - - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - - if (this->contour_indices_size > 0) { - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->contour_indices_VBO_id)); - glsafe(::glDrawElements(GL_LINES, GLsizei(this->contour_indices_size), GL_UNSIGNED_INT, nullptr)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - } - - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); -} - void GLMmSegmentationGizmo3DScene::finalize_vertices() { assert(this->vertices_VBO_id == 0); @@ -791,26 +756,4 @@ void GLMmSegmentationGizmo3DScene::finalize_triangle_indices() } } -void GLMmSegmentationGizmo3DScene::finalize_contour() -{ - assert(this->contour_vertices_VBO_id == 0); - assert(this->contour_indices_VBO_id == 0); - - if (!this->contour_vertices.empty()) { - glsafe(::glGenBuffers(1, &this->contour_vertices_VBO_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_vertices_VBO_id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_vertices.size() * sizeof(float), this->contour_vertices.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - this->contour_vertices.clear(); - } - - if (!this->contour_indices.empty()) { - glsafe(::glGenBuffers(1, &this->contour_indices_VBO_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_indices_VBO_id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_indices.size() * sizeof(unsigned int), this->contour_indices.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - this->contour_indices.clear(); - } -} - } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 851a5ac4ff..604edf64da 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -25,8 +25,6 @@ public: return this->triangle_indices_VBO_ids[triangle_indices_idx] != 0; } - [[nodiscard]] inline bool has_contour_VBO() const { return this->contour_indices_VBO_id != 0; } - // Release the geometry data, release OpenGL VBOs. void release_geometry(); // Finalize the initialization of the geometry, upload the geometry to OpenGL VBO objects @@ -35,9 +33,6 @@ public: // Finalize the initialization of the indices, upload the indices to OpenGL VBO objects // and possibly releasing it if it has been loaded into the VBOs. void finalize_triangle_indices(); - // Finalize the initialization of the contour geometry and the indices, upload both to OpenGL VBO objects - // and possibly releasing it if it has been loaded into the VBOs. - void finalize_contour(); void clear() { @@ -47,34 +42,21 @@ public: for (size_t &triangle_indices_size : this->triangle_indices_sizes) triangle_indices_size = 0; - - this->contour_vertices.clear(); - this->contour_indices.clear(); - this->contour_indices_size = 0; } void render(size_t triangle_indices_idx) const; - void render_contour() const; - std::vector vertices; std::vector> triangle_indices; - std::vector contour_vertices; - std::vector contour_indices; - // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects, // the above mentioned std::vectors are cleared and the following variables keep their original length. std::vector triangle_indices_sizes; - size_t contour_indices_size{0}; // IDs of the Vertex Array Objects, into which the geometry has been loaded. // Zero if the VBOs are not sent to GPU yet. unsigned int vertices_VBO_id{0}; std::vector triangle_indices_VBO_ids; - - unsigned int contour_vertices_VBO_id{0}; - unsigned int contour_indices_VBO_id{0}; }; class TriangleSelectorMmGui : public TriangleSelectorGUI { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 42bdd0843e..56073b5b7e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -541,7 +541,10 @@ void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive&) m_schedule_update = true; } - +std::array TriangleSelectorGUI::get_seed_fill_color(const std::array &base_color) +{ + return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f}; +} void TriangleSelectorGUI::render(ImGuiWrapper* imgui) { @@ -575,8 +578,6 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) #endif } - - void TriangleSelectorGUI::update_render_data() { int enf_cnt = 0; @@ -608,7 +609,63 @@ void TriangleSelectorGUI::update_render_data() iva->finalize_geometry(true); } +void GLPaintContour::render() const +{ + assert(this->m_contour_VBO_id != 0); + assert(this->m_contour_EBO_id != 0); + glsafe(::glLineWidth(4.0f)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id)); + glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); + + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + + if (this->contour_indices_size > 0) { + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_contour_EBO_id)); + glsafe(::glDrawElements(GL_LINES, GLsizei(this->contour_indices_size), GL_UNSIGNED_INT, nullptr)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } + + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); +} + +void GLPaintContour::finalize_geometry() +{ + assert(this->m_contour_VBO_id == 0); + assert(this->m_contour_EBO_id == 0); + + if (!this->contour_vertices.empty()) { + glsafe(::glGenBuffers(1, &this->m_contour_VBO_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_vertices.size() * sizeof(float), this->contour_vertices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + this->contour_vertices.clear(); + } + + if (!this->contour_indices.empty()) { + glsafe(::glGenBuffers(1, &this->m_contour_EBO_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_EBO_id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_indices.size() * sizeof(unsigned int), this->contour_indices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + this->contour_indices.clear(); + } +} + +void GLPaintContour::release_geometry() +{ + if (this->m_contour_VBO_id) { + glsafe(::glDeleteBuffers(1, &this->m_contour_VBO_id)); + this->m_contour_VBO_id = 0; + } + if (this->m_contour_EBO_id) { + glsafe(::glDeleteBuffers(1, &this->m_contour_EBO_id)); + this->m_contour_EBO_id = 0; + } + this->clear(); +} #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 8d37f24048..172e876d3a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -10,6 +10,7 @@ #include "libslic3r/Model.hpp" #include +#include @@ -26,6 +27,41 @@ enum class PainterGizmoType { MMU_SEGMENTATION }; +class GLPaintContour +{ +public: + GLPaintContour() = default; + + void render() const; + + inline bool has_VBO() const { return this->m_contour_EBO_id != 0; } + + // Release the geometry data, release OpenGL VBOs. + void release_geometry(); + + // Finalize the initialization of the contour geometry and the indices, upload both to OpenGL VBO objects + // and possibly releasing it if it has been loaded into the VBOs. + void finalize_geometry(); + + void clear() + { + this->contour_vertices.clear(); + this->contour_indices.clear(); + this->contour_indices_size = 0; + } + + std::vector contour_vertices; + std::vector contour_indices; + + // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects, + // the above mentioned std::vectors are cleared and the following variables keep their original length. + size_t contour_indices_size{0}; + + // IDs of the Vertex Array Objects, into which the geometry has been loaded. + // Zero if the VBOs are not sent to GPU yet. + GLuint m_contour_VBO_id{0}; + GLuint m_contour_EBO_id{0}; +}; class TriangleSelectorGUI : public TriangleSelector { public: @@ -49,12 +85,17 @@ public: protected: bool m_update_render_data = false; + static std::array get_seed_fill_color(const std::array &base_color); + private: void update_render_data(); GLIndexedVertexArray m_iva_enforcers; GLIndexedVertexArray m_iva_blockers; std::array m_varrays; + +protected: + GLPaintContour m_paint_contour; }; class GLGizmoTransparentRender From 542ba1bb9ad4bf66b27800afe6964de9797446ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 13:04:22 +0200 Subject: [PATCH 17/22] Added rendering of smart fill and contour around selected areas for the FDM supports painting gizmo. --- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 66 ++++++++++++++++++-- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 2 +- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 56073b5b7e..fdb05ae22b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -569,6 +569,29 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) } } + for (auto &iva : m_iva_seed_fills) + if (iva.has_VBOs()) { + size_t color_idx = &iva - &m_iva_seed_fills.front(); + const std::array &color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : + color_idx == 2 ? blockers_color : + GLVolume::NEUTRAL_COLOR); + shader->set_uniform("uniform_color", color); + iva.render(); + } + + if (m_paint_contour.has_VBO()) { + ScopeGuard guard_gouraud([shader]() { shader->start_using(); }); + shader->stop_using(); + + auto *contour_shader = wxGetApp().get_shader("mm_contour"); + contour_shader->start_using(); + + glsafe(::glDepthFunc(GL_GEQUAL)); + m_paint_contour.render(); + glsafe(::glDepthFunc(GL_LESS)); + + contour_shader->stop_using(); + } #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG if (imgui) @@ -580,22 +603,31 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) void TriangleSelectorGUI::update_render_data() { - int enf_cnt = 0; - int blc_cnt = 0; + int enf_cnt = 0; + int blc_cnt = 0; + std::vector seed_fill_cnt(m_iva_seed_fills.size(), 0); for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) iva->release_geometry(); + for (auto &iva : m_iva_seed_fills) + iva.release_geometry(); + for (const Triangle &tr : m_triangles) { - if (!tr.valid() || tr.is_split() || tr.get_state() == EnforcerBlockerType::NONE) + if (!tr.valid() || tr.is_split() || (tr.get_state() == EnforcerBlockerType::NONE && !tr.is_selected_by_seed_fill())) continue; - GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; - int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; + int tr_state = int(tr.get_state()); + GLIndexedVertexArray &iva = tr.is_selected_by_seed_fill() ? m_iva_seed_fills[tr_state] : + tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : + m_iva_blockers; + int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] : + tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : + blc_cnt; const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v; const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v; const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v; - //FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort + //FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort // or the current implementation may be more cache friendly. const Vec3f n = (v1 - v0).cross(v2 - v1).normalized(); iva.push_geometry(v0, n); @@ -607,6 +639,28 @@ void TriangleSelectorGUI::update_render_data() for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) iva->finalize_geometry(true); + + for (auto &iva : m_iva_seed_fills) + iva.finalize_geometry(true); + + m_paint_contour.release_geometry(); + std::vector contour_edges = this->get_seed_fill_contour(); + m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); + for (const Vec2i &edge : contour_edges) { + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); + + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); + m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); + } + + m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0); + std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0); + m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); + + m_paint_contour.finalize_geometry(); } void GLPaintContour::render() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 172e876d3a..cc15af41fe 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -92,6 +92,7 @@ private: GLIndexedVertexArray m_iva_enforcers; GLIndexedVertexArray m_iva_blockers; + std::array m_iva_seed_fills; std::array m_varrays; protected: diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 764c42c730..08a94a97d7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -548,7 +548,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) // mouse anywhere if (evt.Moving()) { m_tooltip = update_hover_state(mouse_pos); - if (m_current == MmuSegmentation) + if (m_current == MmuSegmentation || m_current == FdmSupports) gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown()); } else if (evt.LeftUp()) { if (m_mouse_capture.left) { From ebdc69bdc92edc28ef14376f811a95ee57f550bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 13:06:58 +0200 Subject: [PATCH 18/22] Fixed the positioning of the painting gizmos. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 307f0d0282..286e60213c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -89,7 +89,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l if (! m_c->selection_info()->model_object()) return; - const float approx_height = m_imgui->scaled(17.0f); + const float approx_height = m_imgui->scaled(20.5f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 3153b880b9..11a5b21bb1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -234,7 +234,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott if (!m_c->selection_info()->model_object()) return; - const float approx_height = m_imgui->scaled(25.0f); + const float approx_height = m_imgui->scaled(22.0f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 6723818351..2f9d16f904 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -77,7 +77,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) if (! m_c->selection_info()->model_object()) return; - const float approx_height = m_imgui->scaled(14.0f); + const float approx_height = m_imgui->scaled(12.5f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); From d6d575f607742fdb22d94af36ecf56f7489f5ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 13:10:48 +0200 Subject: [PATCH 19/22] Renamed the brush "Pointer" to "Triangles" in the multi-material painting gizmo, and in the FDM supports painting gizmo. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 286e60213c..12b827e64e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -51,7 +51,7 @@ bool GLGizmoFdmSupports::on_init() m_desc["remove_all"] = _L("Remove all selection"); m_desc["circle"] = _L("Circle"); m_desc["sphere"] = _L("Sphere"); - m_desc["pointer"] = _L("Pointer"); + m_desc["pointer"] = _L("Triangles"); m_desc["highlight_by_angle"] = _L("Highlight by angle"); m_desc["enforce_button"] = _L("Enforce"); m_desc["cancel"] = _L("Cancel"); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 11a5b21bb1..b472fbc1b5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -121,7 +121,7 @@ bool GLGizmoMmuSegmentation::on_init() m_desc["remove_all"] = _L("Remove all painted areas"); m_desc["circle"] = _L("Circle"); m_desc["sphere"] = _L("Sphere"); - m_desc["pointer"] = _L("Pointer"); + m_desc["pointer"] = _L("Triangles"); m_desc["tool_type"] = _L("Tool type"); m_desc["tool_brush"] = _L("Brush"); From 82bf9c158a3c286ed043e27360421c5bccfa18b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 4 Oct 2021 12:52:52 +0200 Subject: [PATCH 20/22] Optimized multi-material segmentation to construct Voronoi diagrams only for layers that have more than one color. If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram. --- src/libslic3r/MultiMaterialSegmentation.cpp | 59 ++++++++++++++------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 9456f50775..9cbfaae4a0 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1214,7 +1214,7 @@ static void cut_segmented_layers(const std::vector const std::function &throw_on_cancel_callback) { BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()),[&](const tbb::blocked_range& range) { + tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &throw_on_cancel_callback](const tbb::blocked_range& range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); std::vector> segmented_regions_cuts; @@ -1366,7 +1366,8 @@ static inline std::vector> mmu_segmentation_top_and_bott return out; }; - tbb::parallel_for(tbb::blocked_range(0, num_layers, granularity), [&](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, num_layers, granularity), [&granularity, &num_layers, &num_extruders, &layer_color_stat, &top_raw, &triangles_by_color_top, + &throw_on_cancel_callback, &input_expolygons, &bottom_raw, &triangles_by_color_bottom](const tbb::blocked_range &range) { size_t group_idx = range.begin() / granularity; size_t layer_idx_offset = (group_idx & 1) * num_layers; for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { @@ -1417,7 +1418,7 @@ static inline std::vector> mmu_segmentation_top_and_bott std::vector> triangles_by_color_merged(num_extruders); triangles_by_color_merged.assign(num_extruders, std::vector(num_layers)); - tbb::parallel_for(tbb::blocked_range(0, num_layers), [&](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, num_layers), [&triangles_by_color_merged, &triangles_by_color_bottom, &triangles_by_color_top, &num_layers, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { throw_on_cancel_callback(); for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) { @@ -1446,7 +1447,7 @@ static std::vector>> merge_segmented_la std::vector>> segmented_regions_merged(segmented_regions.size()); BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()), [&](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (const std::pair &colored_expoly : segmented_regions[layer_idx]) { throw_on_cancel_callback(); @@ -1526,6 +1527,20 @@ void export_processed_input_expolygons_to_svg(const std::string &path, const Lay } #endif // MMU_SEGMENTATION_DEBUG_INPUT +// Check if all ColoredLine representing a single layer uses the same color. +static bool has_layer_only_one_color(const std::vector> &colored_polygons) +{ + assert(!colored_polygons.empty()); + assert(!colored_polygons.front().empty()); + int first_line_color = colored_polygons.front().front().color; + for (const std::vector &colored_polygon : colored_polygons) + for (const ColoredLine &colored_line : colored_polygon) + if (first_line_color != colored_line.color) + return false; + + return true; +} + std::vector>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { std::vector>> segmented_regions(print_object.layers().size()); @@ -1539,7 +1554,7 @@ std::vector>> multi_material_segmentati // Merge all regions and remove small holes BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, layers.size()), [&](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, layers.size()), [&layers, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); ExPolygons ex_polygons; @@ -1649,16 +1664,16 @@ std::vector>> multi_material_segmentati edge_grids[layer_idx].visit_cells_intersecting_line(line_start, line_end, visitor); } } - }); + }); // end of parallel_for } - }); + }); // end of parallel_for } BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - end"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - painted layers count: " << std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector &pl) { return !pl.empty(); }); BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&print_object, &edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { @@ -1677,20 +1692,28 @@ std::vector>> multi_material_segmentati if (!painted_lines_single.empty()) { std::vector> color_poly = colorize_polygons(edge_grids[layer_idx].contours(), painted_lines_single); - MMU_Graph graph = build_graph(layer_idx, color_poly); - remove_multiple_edges_in_vertices(graph, color_poly); - graph.remove_nodes_with_one_arc(); + assert(!color_poly.empty()); + assert(!color_poly.front().empty()); + if (has_layer_only_one_color(color_poly)) { + // If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram for the segmentation of this layer. + for (const ExPolygon &ex_polygon : input_expolygons[layer_idx]) + segmented_regions[layer_idx].emplace_back(ex_polygon, size_t(color_poly.front().front().color)); + } else { + MMU_Graph graph = build_graph(layer_idx, color_poly); + remove_multiple_edges_in_vertices(graph, color_poly); + graph.remove_nodes_with_one_arc(); #ifdef MMU_SEGMENTATION_DEBUG_GRAPH - { - static int iRun = 0; - export_graph_to_svg(debug_out_path("mm-graph-final-%d-%d.svg", layer_idx, iRun++), graph, input_expolygons[layer_idx]); - } + { + static int iRun = 0; + export_graph_to_svg(debug_out_path("mm-graph-final-%d-%d.svg", layer_idx, iRun++), graph, input_expolygons[layer_idx]); + } #endif // MMU_SEGMENTATION_DEBUG_GRAPH - std::vector> segmentation = extract_colored_segments(graph); - for (std::pair ®ion : segmentation) - segmented_regions[layer_idx].emplace_back(std::move(region)); + std::vector> segmentation = extract_colored_segments(graph); + for (std::pair ®ion : segmentation) + segmented_regions[layer_idx].emplace_back(std::move(region)); + } #ifdef MMU_SEGMENTATION_DEBUG_REGIONS { From b99be85187745f98c83d8457cb3076053ff675c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 7 Oct 2021 13:36:06 +0200 Subject: [PATCH 21/22] Fixed a warning. --- src/libslic3r/MultiMaterialSegmentation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 9cbfaae4a0..b48c718286 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1673,7 +1673,7 @@ std::vector>> multi_material_segmentati << std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector &pl) { return !pl.empty(); }); BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&print_object, &edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { From c0f3077ce928ccd02ee1e4df927a56141c1ee0a8 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 7 Oct 2021 14:03:50 +0200 Subject: [PATCH 22/22] Follow-up fb3ed367ad71b589b328f02b5532b76ef399080f : Fixed flickering of the wxProgressDialog during the model fixing --- src/slic3r/Utils/FixModelByWin10.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp index 30c81f6f75..6f6b21f686 100644 --- a/src/slic3r/Utils/FixModelByWin10.cpp +++ b/src/slic3r/Utils/FixModelByWin10.cpp @@ -421,7 +421,7 @@ bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxPro } }); while (! finished) { - condition.wait_for(lock, std::chrono::milliseconds(500), [&progress]{ return progress.updated; }); + condition.wait_for(lock, std::chrono::milliseconds(250), [&progress]{ return progress.updated; }); // decrease progress.percent value to avoid closing of the progress dialog if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message))) canceled = true;