From 492e6b8e518f0c306dd7a27a4d2eea5ad4ff1617 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 a676945418b..0cd0ac9eb0b 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 a1b312eb833624adff0e165123c3e45fdda6ca76 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 0cd0ac9eb0b..57840dda28e 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 d83b2e0d3d04ea6081cb9c25eed91d3f84ea2495 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 b681cbdf442..8659e696124 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 ea1d0ed1751..6e0063f1bcb 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 e98dcf554e5..bb3c9fc5c21 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 b223b4346fa..5223631c0be 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 6c416c475e3..d2a6b6e9aae 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 54e3f5d45ea..cc619fc456e 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 7d5f80a3008..b8c053f8888 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 9b77591be60..a15c72fb8ed 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 78735b92589..ed4b477b814 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 ca7a0cde03d..f8885b20605 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 f00c6df3e1b..68c20d497b2 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 2a367f6774890e6bef8409f01877680ca4655bdb 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 8659e696124..1ade36e36d4 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 6e0063f1bcb..11cbdc0cf1a 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 68c20d497b2..0710c0916c1 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 06576082ce47e543d16767e1badc58a668a6d253 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 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 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 5ccf850859311f9d9697b7e6aee56a6d779bb720 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 b8c053f8888..d5a1a5659f2 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 45406faf1ca2f18f7979e2423523c146a3bdcfa7 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 00000000000..6312beee323 --- /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 a6b99a08baf..05f301186af 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 e1fcc029a6d..e2a9df25d57 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 a581cf8b305..3061bbe1329 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 0bed7eb74f2..d16161f8903 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 6f8eeedccd3..5475a36eaa2 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 6e976817e687d612f4ae7d90492f329389188618 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 26c5b470e33..fd2c4f8651c 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 880723693c3..9d12369227b 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 cf624b081db6f56ef49ead7eee60a759ec13f438 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 d2a6b6e9aae..e6e7336f7e4 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 4fb49fb39c97ce953bfc6387251f152222da1954 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 437106feddb..6f113294152 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 d7824357f7c..7bd4449524c 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 b235287725c..286d3225630 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 9a4759322ebc212016711366406304dd745a993d 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 6f113294152..9a9739b9062 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 7bd4449524c..16310cbc541 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 286d3225630..3d897b0dedc 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 163d171541d9f06a98be3bee22eb98f491ae7e76 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 9a9739b9062..6a892e9c138 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 16310cbc541..c9edb6c9320 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 3d897b0dedc..fea506eaa86 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 53772a19f6f600bf55404ad756ae0de6a72580c8 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 fea506eaa86..67238183513 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 4cf5c919b36daf7ae290201e50d0963f037bb7c8 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 c9edb6c9320..e2088d4acbb 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 379dbdf83f3dc785ff652c0d529288e1f7a6b43b 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 6a892e9c138..307f0d0282a 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 c25357969f2048caef0840a9d8868b8ce8556e52 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 e2088d4acbb..3153b880b94 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 851a5ac4fff..604edf64da3 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 42bdd0843e3..56073b5b7ef 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 8d37f240480..172e876d3a9 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 6d88f891925b7fea76ad2dafd045836f9613af9c 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 56073b5b7ef..fdb05ae22be 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 172e876d3a9..cc15af41fee 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 764c42c7306..08a94a97d70 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 cb66737396675ad7b64d2347cc05a5c6414b54d2 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 307f0d0282a..286e60213c9 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 3153b880b94..11a5b21bb11 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 67238183513..2f9d16f904b 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 d2acd0c0a3556b82ba734341029b954518f9d5ce 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 286e60213c9..12b827e64e9 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 11a5b21bb11..b472fbc1b53 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 20ce0abd009cf4fafd6b2ea6a4d2b456cf14af1d 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 9456f507751..9cbfaae4a01 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 11247aa6aca96c5b5cf80c7edeb627de7fc8a1ef 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 9cbfaae4a01..b48c718286e 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 fc26a256b04666495477c9a9af18aa2606332134 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 30c81f6f752..6f6b21f6868 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;