From 203e9e848c1c11770efe642e660f5c3791685e38 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 24 Apr 2019 13:33:05 +0200 Subject: [PATCH 01/15] Changed Manipulation panel. (Simple mode)There is exclamation mark icon next for the object name, if it has errors. + some code refactoring --- src/slic3r/GUI/GUI_ObjectList.cpp | 185 +++++++++++++++------- src/slic3r/GUI/GUI_ObjectList.hpp | 12 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 46 +++++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 5 + 4 files changed, 183 insertions(+), 65 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f8ad8b7bb..b16198d19 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -193,6 +193,106 @@ void ObjectList::create_popup_menus() create_instance_popupmenu(&m_menu_instance); } +void ObjectList::get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& input_item/* = wxDataViewItem(0)*/) +{ + const wxDataViewItem item = input_item == wxDataViewItem(0) ? GetSelection() : input_item; + + if (!item) + { + obj_idx = vol_idx = -1; + return; + } + + const ItemType type = m_objects_model->GetItemType(item); + + obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) : + type & itVolume ? m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)) : -1; + + vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1; +} + +int ObjectList::get_mesh_errors_count(const int obj_idx, const int vol_idx /*= -1*/) const +{ + if (obj_idx < 0) + return 0; + + int errors = 0; + + std::vector volumes; + if (vol_idx == -1) + volumes = (*m_objects)[obj_idx]->volumes; + else + volumes.emplace_back((*m_objects)[obj_idx]->volumes[vol_idx]); + + for (ModelVolume* volume : volumes) + { + const stl_stats& stats = volume->mesh.stl.stats; + + errors += stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + + stats.facets_added + stats.facets_reversed + stats.backwards_edges; + } + + return errors; +} + +wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx /*= -1*/) const +{ + const int errors = get_mesh_errors_count(obj_idx, vol_idx); + + if (errors == 0) + return ""; // hide tooltip + + // Create tooltip string, if there are errors + wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); + + std::vector volumes; + if (vol_idx == -1) + volumes = (*m_objects)[obj_idx]->volumes; + else + volumes.emplace_back((*m_objects)[obj_idx]->volumes[vol_idx]); + + std::map error_msg = { + {L("degenerate facets") , 0}, + {L("edges fixed") , 0}, + {L("facets removed") , 0}, + {L("facets added") , 0}, + {L("facets reversed") , 0}, + {L("backwards edges") , 0} + }; + + for (ModelVolume* volume : volumes) + { + const stl_stats& stats = volume->mesh.stl.stats; + + error_msg[L("degenerate facets")] += stats.degenerate_facets; + error_msg[L("edges fixed")] += stats.edges_fixed; + error_msg[L("facets removed")] += stats.facets_removed; + error_msg[L("facets added")] += stats.facets_added; + error_msg[L("facets reversed")] += stats.facets_reversed; + error_msg[L("backwards edges")] += stats.backwards_edges; + } + + for (const auto& error : error_msg) + if (error.second > 0) + tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); + + if (is_windows10()) + tooltip += _(L("Right button click the icon to fix STL through Netfabb")); + + return tooltip; +} + +wxString ObjectList::get_mesh_errors_list() +{ + if (!GetSelection()) + return ""; + + int obj_idx, vol_idx; + get_selected_item_indexes(obj_idx, vol_idx); + + return get_mesh_errors_list(obj_idx, vol_idx); +} + void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -202,38 +302,11 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); - else if (col->GetTitle() == _("Name") && - m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { - int obj_idx = m_objects_model->GetIdByItem(item); - auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; - int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - - wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); - - std::map error_msg; - error_msg[L("degenerate facets")] = stats.degenerate_facets; - error_msg[L("edges fixed")] = stats.edges_fixed; - error_msg[L("facets removed")] = stats.facets_removed; - error_msg[L("facets added")] = stats.facets_added; - error_msg[L("facets reversed")] = stats.facets_reversed; - error_msg[L("backwards edges")] = stats.backwards_edges; - - for (auto error : error_msg) - { - if (error.second > 0) - tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); - } -// OR -// tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " -// "%d facets added, %d facets reversed, %d backwards edges")), -// stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, -// stats.facets_added, stats.facets_reversed, stats.backwards_edges); - - if (is_windows10()) - tooltip += _(L("Right button click the icon to fix STL through Netfabb")); - - GetMainWindow()->SetToolTip(tooltip); + else if (col->GetTitle() == _("Name") ) + { + int obj_idx, vol_idx; + get_selected_item_indexes(obj_idx, vol_idx, item); + GetMainWindow()->SetToolTip(get_mesh_errors_list(obj_idx, vol_idx)); } else GetMainWindow()->SetToolTip(""); // hide tooltip @@ -533,10 +606,12 @@ void ObjectList::OnContextMenu(wxDataViewEvent&) if (title == " ") show_context_menu(); - else if (title == _("Name") && pt.x >15 && - m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) + else if (title == _("Name") && pt.x > 1.6f*wxGetApp().em_unit() && pt.x < 3.2f*wxGetApp().em_unit()) { - if (is_windows10()) + int obj_idx, vol_idx; + get_selected_item_indexes(obj_idx, vol_idx, item); + + if (is_windows10() && get_mesh_errors_count(obj_idx, vol_idx) > 0) fix_through_netfabb(); } @@ -1729,6 +1804,7 @@ void ObjectList::parts_changed(int obj_idx) void ObjectList::part_selection_changed() { int obj_idx = -1; + int volume_id = -1; m_config = nullptr; wxString og_name = wxEmptyString; @@ -1775,7 +1851,7 @@ void ObjectList::part_selection_changed() } else if (m_objects_model->GetItemType(item) == itVolume) { og_name = _(L("Part manipulation")); - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + volume_id = m_objects_model->GetVolumeIdByItem(item); m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; update_and_show_manipulations = true; } @@ -1795,7 +1871,11 @@ void ObjectList::part_selection_changed() if (update_and_show_manipulations) { wxGetApp().obj_manipul()->get_og()->set_name(" " + og_name + " "); - wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(GetSelection())); + + if (item) { + wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item)); + wxGetApp().obj_manipul()->update_manifold_warning_icon_state(get_mesh_errors_list(obj_idx, volume_id)); + } } if (update_and_show_settings) @@ -1815,16 +1895,13 @@ void ObjectList::part_selection_changed() void ObjectList::add_object_to_list(size_t obj_idx) { auto model_object = (*m_objects)[obj_idx]; - wxString item_name = from_u8(model_object->name); + const wxString& item_name = from_u8(model_object->name); const auto item = m_objects_model->Add(item_name, !model_object->config.has("extruder") ? 0 : model_object->config.option("extruder")->value); // Add error icon if detected auto-repaire - auto stats = model_object->volumes[0]->mesh.stl.stats; - int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - if (errors > 0) { + if (get_mesh_errors_count(obj_idx) > 0) { wxVariant variant; variant << PrusaDataViewBitmapText(item_name, m_bmp_manifold_warning); m_objects_model->SetValue(variant, item, 0); @@ -2641,18 +2718,10 @@ void ObjectList::rename_item() update_name_in_model(item); } -void ObjectList::fix_through_netfabb() const +void ObjectList::fix_through_netfabb() { - const wxDataViewItem item = GetSelection(); - if (!item) - return; - - const ItemType type = m_objects_model->GetItemType(item); - - const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) : - type & itVolume ? m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)) : -1; - - const int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1; + int obj_idx, vol_idx; + get_selected_item_indexes(obj_idx, vol_idx); wxGetApp().plater()->fix_through_netfabb(obj_idx, vol_idx); @@ -2666,16 +2735,10 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co if (!item) return; - auto model_object = (*m_objects)[obj_idx]; - - const stl_stats& stats = model_object->volumes[vol_idx<0 ? 0 : vol_idx]->mesh.stl.stats; - const int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - - if (errors == 0) { + if (get_mesh_errors_count(obj_idx, vol_idx) == 0) { // delete Error_icon if all errors are fixed wxVariant variant; - variant << PrusaDataViewBitmapText(from_u8(model_object->name), wxNullBitmap); + variant << PrusaDataViewBitmapText(from_u8((*m_objects)[obj_idx]->name), wxNullBitmap); m_objects_model->SetValue(variant, item, 0); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index a0343100a..617b6da8a 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -177,6 +177,16 @@ public: void init_icons(); + // Get obj_idx and vol_idx values for the selected (by default) or an adjusted item + void get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& item = wxDataViewItem(0)); + // Get count of errors in the mesh + int get_mesh_errors_count(const int obj_idx, const int vol_idx = -1) const; + /* Get list of errors in the mesh. Return value is a string, used for the tooltip + * Function without parameters is for a call from Manipulation panel, + * when we don't know parameters of selected item + */ + wxString get_mesh_errors_list(const int obj_idx, const int vol_idx = -1) const; + wxString get_mesh_errors_list(); void set_tooltip_for_item(const wxPoint& pt); void selection_changed(); @@ -285,7 +295,7 @@ public: void instances_to_separated_objects(const int obj_idx); void split_instances(); void rename_item(); - void fix_through_netfabb() const; + void fix_through_netfabb(); void update_item_error_icon(const int obj_idx, int vol_idx) const ; void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index f9284a19b..e623114e9 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -10,6 +10,7 @@ #include "Selection.hpp" #include +#include "slic3r/Utils/FixModelByWin10.hpp" namespace Slic3r { @@ -20,6 +21,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) #ifndef __APPLE__ , m_focused_option("") + , m_manifold_warning_bmp(create_scaled_bitmap(parent, "exclamation")) #endif // __APPLE__ { m_og->set_name(_(L("Object Manipulation"))); @@ -42,17 +44,47 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : ConfigOptionDef def; // Objects(sub-objects) name - def.label = L("Name"); +// def.label = L("Name"); +// def.gui_type = "legend"; +// def.tooltip = L("Object name"); +// def.width = 21 * wxGetApp().em_unit(); +// def.default_value = new ConfigOptionString{ " " }; +// m_og->append_single_option_line(Option(def, "object_name")); + + Line line = Line{ "Name", "Object name" }; + + auto manifold_warning_icon = [this](wxWindow* parent) { + m_fix_throught_netfab_bitmap = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_fix_throught_netfab_bitmap); + + if (is_windows10()) + m_fix_throught_netfab_bitmap->Bind(wxEVT_CONTEXT_MENU, [this](wxCommandEvent &e) + { + // if object/sub-object has no errors + if (m_fix_throught_netfab_bitmap->GetBitmap().GetRefData() == wxNullBitmap.GetRefData()) + return; + + wxGetApp().obj_list()->fix_through_netfabb(); + update_manifold_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list()); + }); + + return sizer; + }; + + line.append_widget(manifold_warning_icon); + def.label = ""; def.gui_type = "legend"; def.tooltip = L("Object name"); def.width = 21 * wxGetApp().em_unit(); def.default_value = new ConfigOptionString{ " " }; - m_og->append_single_option_line(Option(def, "object_name")); + line.append_option(Option(def, "object_name")); + m_og->append_line(line); const int field_width = 5 * wxGetApp().em_unit()/*50*/; // Legend for object modification - auto line = Line{ "", "" }; + line = Line{ "", "" }; def.label = ""; def.type = coString; def.width = field_width/*50*/; @@ -334,6 +366,14 @@ void ObjectManipulation::emulate_kill_focus() else on_change(option, 0); } + +void ObjectManipulation::update_manifold_warning_icon_state(const wxString& tooltip) +{ + m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp); + + m_fix_throught_netfab_bitmap->SetToolTip(tooltip); +} + #endif // __APPLE__ void ObjectManipulation::reset_settings_value() diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index a5a180a56..071edbed8 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -78,6 +78,9 @@ class ObjectManipulation : public OG_Settings bool m_uniform_scale {true}; PrusaLockButton* m_lock_bnt{ nullptr }; + wxBitmap m_manifold_warning_bmp; + wxStaticBitmap* m_fix_throught_netfab_bitmap; + #ifndef __APPLE__ // Currently focused option name (empty if none) std::string m_focused_option; @@ -107,6 +110,8 @@ public: void emulate_kill_focus(); #endif // __APPLE__ + void update_manifold_warning_icon_state(const wxString& tooltip); + private: void reset_settings_value(); From b4d5287d0c9826bcd3c95b595443efd437cd3f85 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 24 Apr 2019 16:04:47 +0200 Subject: [PATCH 02/15] Refactoring: get_mesh_errors_count() moved to ModelObject + added get_object_stl_stats() to ModelObject --- src/libslic3r/Model.cpp | 42 ++++++++++++++++ src/libslic3r/Model.hpp | 5 ++ src/slic3r/GUI/GUI_ObjectList.cpp | 60 ++++++----------------- src/slic3r/GUI/GUI_ObjectList.hpp | 2 +- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 1 + src/slic3r/GUI/Plater.cpp | 15 +++++- 6 files changed, 78 insertions(+), 47 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 37e1f4a1b..d1f426c5b 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1451,6 +1451,48 @@ std::string ModelObject::get_export_filename() const return ret; } +stl_stats ModelObject::get_object_stl_stats() const +{ + if (this->volumes.size() == 1) + return this->volumes[0]->mesh.stl.stats; + + stl_stats full_stats; + + // initialise full_stats + full_stats.degenerate_facets= 0; + full_stats.edges_fixed = 0; + full_stats.facets_removed = 0; + full_stats.facets_added = 0; + full_stats.facets_reversed = 0; + full_stats.backwards_edges = 0; + full_stats.normals_fixed = 0; + + // fill full_stats from all objet's meshes + for (ModelVolume* volume : this->volumes) + { + const stl_stats& stats = volume->mesh.stl.stats; + + full_stats.degenerate_facets+= stats.degenerate_facets; + full_stats.edges_fixed += stats.edges_fixed; + full_stats.facets_removed += stats.facets_removed; + full_stats.facets_added += stats.facets_added; + full_stats.facets_reversed += stats.facets_reversed; + full_stats.backwards_edges += stats.backwards_edges; + } + + return full_stats; +} + +int ModelObject::get_mesh_errors_count(const int vol_idx /*= -1*/) const +{ + const stl_stats& stats = vol_idx == -1 ? + get_object_stl_stats() : + this->volumes[vol_idx]->mesh.stl.stats; + + return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + + stats.facets_added + stats.facets_reversed + stats.backwards_edges; +} + void ModelVolume::set_material_id(t_model_material_id material_id) { m_material_id = material_id; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 80187d259..0fc3fc168 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -277,6 +277,11 @@ public: std::string get_export_filename() const; + // Get full stl statistics for all object's meshes + stl_stats 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; + protected: friend class Print; friend class SLAPrint; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b16198d19..d65ad2acc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -216,23 +216,7 @@ int ObjectList::get_mesh_errors_count(const int obj_idx, const int vol_idx /*= - if (obj_idx < 0) return 0; - int errors = 0; - - std::vector volumes; - if (vol_idx == -1) - volumes = (*m_objects)[obj_idx]->volumes; - else - volumes.emplace_back((*m_objects)[obj_idx]->volumes[vol_idx]); - - for (ModelVolume* volume : volumes) - { - const stl_stats& stats = volume->mesh.stl.stats; - - errors += stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - } - - return errors; + return (*m_objects)[obj_idx]->get_mesh_errors_count(vol_idx); } wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx /*= -1*/) const @@ -245,33 +229,19 @@ wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx / // Create tooltip string, if there are errors wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); - std::vector volumes; - if (vol_idx == -1) - volumes = (*m_objects)[obj_idx]->volumes; - else - volumes.emplace_back((*m_objects)[obj_idx]->volumes[vol_idx]); + const stl_stats& stats = vol_idx == -1 ? + (*m_objects)[obj_idx]->get_object_stl_stats() : + (*m_objects)[obj_idx]->volumes[vol_idx]->mesh.stl.stats; std::map error_msg = { - {L("degenerate facets") , 0}, - {L("edges fixed") , 0}, - {L("facets removed") , 0}, - {L("facets added") , 0}, - {L("facets reversed") , 0}, - {L("backwards edges") , 0} + { L("degenerate facets"), stats.degenerate_facets }, + { L("edges fixed"), stats.edges_fixed }, + { L("facets removed"), stats.facets_removed }, + { L("facets added"), stats.facets_added }, + { L("facets reversed"), stats.facets_reversed }, + { L("backwards edges"), stats.backwards_edges } }; - for (ModelVolume* volume : volumes) - { - const stl_stats& stats = volume->mesh.stl.stats; - - error_msg[L("degenerate facets")] += stats.degenerate_facets; - error_msg[L("edges fixed")] += stats.edges_fixed; - error_msg[L("facets removed")] += stats.facets_removed; - error_msg[L("facets added")] += stats.facets_added; - error_msg[L("facets reversed")] += stats.facets_reversed; - error_msg[L("backwards edges")] += stats.backwards_edges; - } - for (const auto& error : error_msg) if (error.second > 0) tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); @@ -1170,13 +1140,15 @@ void ObjectList::append_menu_items_osx(wxMenu* menu) menu->AppendSeparator(); } -void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) +wxMenuItem* ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) { - if (!is_windows10()) - return; - append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", +// if (!is_windows10()) +// return; + wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu); menu->AppendSeparator(); + + return menu_item; } void ObjectList::append_menu_item_export_stl(wxMenu* menu) const diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 617b6da8a..0dfa1f41c 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -204,7 +204,7 @@ public: wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu); void append_menu_items_osx(wxMenu* menu); - void append_menu_item_fix_through_netfabb(wxMenu* menu); + wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu); void append_menu_item_export_stl(wxMenu* menu) const ; void append_menu_item_change_extruder(wxMenu* menu) const; void append_menu_item_delete(wxMenu* menu); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 071edbed8..d3d5f8444 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -8,6 +8,7 @@ class wxStaticText; class PrusaLockButton; +class wxStaticBitmap; namespace Slic3r { namespace GUI { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8eb68fc39..dfb8fb98a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -926,7 +926,7 @@ void Sidebar::show_info_sizer() p->object_info->info_size->SetLabel(wxString::Format("%.2f x %.2f x %.2f",size(0), size(1), size(2))); p->object_info->info_materials->SetLabel(wxString::Format("%d", static_cast(model_object->materials_count()))); - auto& stats = model_object->volumes.front()->mesh.stl.stats; + const auto& stats = model_object->get_object_stl_stats();//model_object->volumes.front()->mesh.stl.stats; p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume)); p->object_info->info_facets->SetLabel(wxString::Format(_(L("%d (%d shells)")), static_cast(model_object->facets_count()), stats.number_of_parts)); @@ -1284,6 +1284,7 @@ struct Plater::priv bool can_split_to_volumes() const; bool can_arrange() const; bool can_layers_editing() const; + bool can_fix_through_netfabb() const; private: bool init_object_menu(); @@ -2886,7 +2887,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ menu->AppendSeparator(); } - sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); + wxMenuItem* item_fix_through_netfabb = sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) @@ -2906,6 +2907,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ { q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_fix_through_netfabb()); }, item_fix_through_netfabb->GetId()); } return true; @@ -3075,6 +3077,15 @@ bool Plater::priv::can_delete_all() const return !model.objects.empty(); } +bool Plater::priv::can_fix_through_netfabb() const +{ + int obj_idx = get_selected_object_idx(); + if (obj_idx < 0) + return false; + + return model.objects[obj_idx]->get_mesh_errors_count() > 0; +} + bool Plater::priv::can_increase_instances() const { if (arranging || rotoptimizing) { From 3d48190616e756e9c754b70de9ba8304066288ef Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Apr 2019 16:19:50 +0200 Subject: [PATCH 03/15] After merge fixing --- src/slic3r/GUI/GUI_ObjectList.cpp | 15 ++++++++------- src/slic3r/GUI/Plater.cpp | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index ff9bd763e..054f74d70 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1182,8 +1182,8 @@ void ObjectList::append_menu_items_osx(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) { -// if (!is_windows10()) -// return; + if (!is_windows10()) + return nullptr; wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu); menu->AppendSeparator(); @@ -2735,19 +2735,20 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co if (get_mesh_errors_count(obj_idx, vol_idx) == 0) { // delete Error_icon if all errors are fixed wxVariant variant; - variant << PrusaDataViewBitmapText(from_u8((*m_objects)[obj_idx]->name), wxNullBitmap); + variant << DataViewBitmapText(from_u8((*m_objects)[obj_idx]->name), wxNullBitmap); m_objects_model->SetValue(variant, item, 0); } } void ObjectList::msw_rescale() { + const int em = wxGetApp().em_unit(); // update min size !!! A width of control shouldn't be a wxDefaultCoord - SetMinSize(wxSize(1, 15 * wxGetApp().em_unit())); + SetMinSize(wxSize(1, 15 * em)); - GetColumn(0)->SetWidth(19 * wxGetApp().em_unit()); - GetColumn(1)->SetWidth(8 * wxGetApp().em_unit()); - GetColumn(2)->SetWidth(int(2 * wxGetApp().em_unit())); + GetColumn(0)->SetWidth(19 * em); + GetColumn(1)->SetWidth( 8 * em); + GetColumn(2)->SetWidth( 2 * em); // rescale all icons, used by ObjectList rescale_icons(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 91ae153dd..c221b5066 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2951,7 +2951,8 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ { q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_fix_through_netfabb()); }, item_fix_through_netfabb->GetId()); + if (item_fix_through_netfabb) + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_fix_through_netfabb()); }, item_fix_through_netfabb->GetId()); } return true; From 2a47f0dc9249470815b4f4fe76dc39fc46fd29ba Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 29 Apr 2019 15:27:59 +0200 Subject: [PATCH 04/15] ObjectList improvements: Added warning icon for Parts with a repaired errors --- src/libslic3r/Model.cpp | 15 ++- src/libslic3r/Model.hpp | 2 + src/slic3r/GUI/GUI_ObjectList.cpp | 111 ++++++++++++---------- src/slic3r/GUI/GUI_ObjectList.hpp | 2 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 13 ++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 3 +- src/slic3r/GUI/Plater.cpp | 3 +- src/slic3r/GUI/wxExtensions.cpp | 85 ++++++++++++++--- src/slic3r/GUI/wxExtensions.hpp | 35 +++---- 9 files changed, 180 insertions(+), 89 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d1f426c5b..17769a8e7 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1485,9 +1485,10 @@ stl_stats ModelObject::get_object_stl_stats() const int ModelObject::get_mesh_errors_count(const int vol_idx /*= -1*/) const { - const stl_stats& stats = vol_idx == -1 ? - get_object_stl_stats() : - this->volumes[vol_idx]->mesh.stl.stats; + if (vol_idx >= 0) + return this->volumes[vol_idx]->get_mesh_errors_count(); + + const stl_stats& stats = get_object_stl_stats(); return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + stats.facets_added + stats.facets_reversed + stats.backwards_edges; @@ -1558,6 +1559,14 @@ void ModelVolume::calculate_convex_hull() m_convex_hull = mesh.convex_hull_3d(); } +int ModelVolume::get_mesh_errors_count() const +{ + const stl_stats& stats = this->mesh.stl.stats; + + return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + + stats.facets_added + stats.facets_reversed + stats.backwards_edges; +} + const TriangleMesh& ModelVolume::get_convex_hull() const { return m_convex_hull; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 0fc3fc168..4efc19f58 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -375,6 +375,8 @@ public: void calculate_convex_hull(); const TriangleMesh& get_convex_hull() const; + // Get count of errors in the mesh + int get_mesh_errors_count() const; // Helpers for loading / storing into AMF / 3MF files. static ModelVolumeType type_from_string(const std::string &s); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 054f74d70..1a4245965 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -438,8 +438,8 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const void ObjectList::init_icons() { - m_bmp_modifiermesh = ScalableBitmap(nullptr, "add_modifier"); // Add part - m_bmp_solidmesh = ScalableBitmap(nullptr, "add_part"); // Add modifier + m_bmp_solidmesh = ScalableBitmap(nullptr, "add_part"); // Add part + m_bmp_modifiermesh = ScalableBitmap(nullptr, "add_modifier"); // Add modifier m_bmp_support_enforcer = ScalableBitmap(nullptr, "support_enforcer");// Add support enforcer m_bmp_support_blocker = ScalableBitmap(nullptr, "support_blocker"); // Add support blocker @@ -455,6 +455,8 @@ void ObjectList::init_icons() // init icon for manifold warning m_bmp_manifold_warning = ScalableBitmap(nullptr, "exclamation"); + // Set warning bitmap for the model + m_objects_model->SetWarningBitmap(&m_bmp_manifold_warning.bmp()); // init bitmap for "Split to sub-objects" context menu m_bmp_split = ScalableBitmap(nullptr, "split_parts_SMALL"); @@ -468,8 +470,8 @@ void ObjectList::rescale_icons() m_bmp_vector.clear(); m_bmp_vector.reserve(4); // bitmaps for different types of parts for (ScalableBitmap* bitmap : std::vector { - &m_bmp_modifiermesh, // Add part - &m_bmp_solidmesh, // Add modifier + &m_bmp_solidmesh, // Add part + &m_bmp_modifiermesh, // Add modifier &m_bmp_support_enforcer, // Add support enforcer &m_bmp_support_blocker }) // Add support blocker { @@ -480,6 +482,9 @@ void ObjectList::rescale_icons() m_objects_model->SetVolumeBitmaps(m_bmp_vector); m_bmp_manifold_warning.msw_rescale(); + // Set warning bitmap for the model + m_objects_model->SetWarningBitmap(&m_bmp_manifold_warning.bmp()); + m_bmp_split.msw_rescale(); m_bmp_cog.msw_rescale(); @@ -541,7 +546,8 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol for (const ModelVolume* volume : volumes) { - auto vol_item = m_objects_model->AddVolumeChild(object_item, volume->name, volume->type(), + const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(object_item, volume->name, volume->type(), + volume->get_mesh_errors_count()>0 , volume->config.has("extruder") ? volume->config.option("extruder")->value : 0); auto opt_keys = volume->config.keys(); if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder"))) @@ -617,12 +623,13 @@ void ObjectList::OnContextMenu(wxDataViewEvent&) if (title == " ") show_context_menu(); - else if (title == _("Name") && pt.x > 1.6f*wxGetApp().em_unit() && pt.x < 3.2f*wxGetApp().em_unit()) + else if (title == _("Name")) { int obj_idx, vol_idx; get_selected_item_indexes(obj_idx, vol_idx, item); - - if (is_windows10() && get_mesh_errors_count(obj_idx, vol_idx) > 0) + + if (is_windows10() && get_mesh_errors_count(obj_idx, vol_idx) > 0 && + pt.x > 2*wxGetApp().em_unit() && pt.x < 4*wxGetApp().em_unit() ) fix_through_netfabb(); } @@ -1374,21 +1381,23 @@ void ObjectList::load_subobject(ModelVolumeType type) int obj_idx = m_objects_model->GetIdByItem(item); if (obj_idx < 0) return; - wxArrayString part_names; - load_part((*m_objects)[obj_idx], part_names, type); + + std::vector> volumes_info; + load_part((*m_objects)[obj_idx], volumes_info, type); + changed_object(obj_idx); - for (int i = 0; i < part_names.size(); ++i) { - const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), type); - - if (i == part_names.size() - 1) - select_item(sel_item); - } + wxDataViewItem sel_item; + for (const auto& volume : volumes_info ) + sel_item = m_objects_model->AddVolumeChild(item, volume.first, type, volume.second); + + if (sel_item) + select_item(sel_item); } void ObjectList::load_part( ModelObject* model_object, - wxArrayString& part_names, + std::vector> &volumes_info, ModelVolumeType type) { wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); @@ -1424,7 +1433,7 @@ void ObjectList::load_part( ModelObject* model_object, new_volume->set_type(type); new_volume->name = boost::filesystem::path(input_file).filename().string(); - part_names.Add(from_u8(new_volume->name)); + volumes_info.push_back(std::make_pair(from_u8(new_volume->name), new_volume->get_mesh_errors_count()>0)); // set a default extruder value, since user can't add it manually new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); @@ -1580,7 +1589,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode changed_object(obj_idx); const auto object_item = m_objects_model->GetTopParent(GetSelection()); - select_item(m_objects_model->AddVolumeChild(object_item, name, type)); + select_item(m_objects_model->AddVolumeChild(object_item, name, type, + new_volume->get_mesh_errors_count()>0)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME selection_changed(); #endif //no __WXOSX__ //__WXMSW__ @@ -1612,6 +1622,10 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) else if (!del_subobject_from_object(obj_idx, idx, type)) return; + // If last volume item with warning was deleted, unmark object item + if (type == itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0) + m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item)); + m_objects_model->Delete(item); } @@ -1718,18 +1732,18 @@ void ObjectList::split() else parent = item; - for (auto id = 0; id < model_object->volumes.size(); id++) { - const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name), - model_object->volumes[id]->is_modifier() ? - ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, - model_object->volumes[id]->config.has("extruder") ? - model_object->volumes[id]->config.option("extruder")->value : 0, + for (const ModelVolume* volume : model_object->volumes) { + const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(parent, from_u8(volume->name), + volume->is_modifier() ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, + volume->get_mesh_errors_count()>0, + volume->config.has("extruder") ? + volume->config.option("extruder")->value : 0, false); // add settings to the part, if it has those - auto opt_keys = model_object->volumes[id]->config.keys(); + auto opt_keys = volume->config.keys(); if ( !(opt_keys.size() == 1 && opt_keys[0] == "extruder") ) { select_item(m_objects_model->AddSettingsChild(vol_item)); - /*Collapse*/Expand(vol_item); + Expand(vol_item); } } @@ -1896,28 +1910,23 @@ void ObjectList::add_object_to_list(size_t obj_idx) const wxString& item_name = from_u8(model_object->name); const auto item = m_objects_model->Add(item_name, !model_object->config.has("extruder") ? 0 : - model_object->config.option("extruder")->value); - - // Add error icon if detected auto-repaire - if (get_mesh_errors_count(obj_idx) > 0) { - wxVariant variant; - variant << DataViewBitmapText(item_name, m_bmp_manifold_warning.bmp()); - m_objects_model->SetValue(variant, item, 0); - } + model_object->config.option("extruder")->value, + get_mesh_errors_count(obj_idx) > 0); // add volumes to the object if (model_object->volumes.size() > 1) { - for (auto id = 0; id < model_object->volumes.size(); id++) { - auto vol_item = m_objects_model->AddVolumeChild(item, - from_u8(model_object->volumes[id]->name), - model_object->volumes[id]->type(), - !model_object->volumes[id]->config.has("extruder") ? 0 : - model_object->volumes[id]->config.option("extruder")->value, + for (const ModelVolume* volume : model_object->volumes) { + const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item, + from_u8(volume->name), + volume->type(), + volume->get_mesh_errors_count()>0, + !volume->config.has("extruder") ? 0 : + volume->config.option("extruder")->value, false); - auto opt_keys = model_object->volumes[id]->config.keys(); + auto opt_keys = volume->config.keys(); if (!opt_keys.empty() && !(opt_keys.size() == 1 && opt_keys[0] == "extruder")) { select_item(m_objects_model->AddSettingsChild(vol_item)); - /*Collapse*/Expand(vol_item); + Expand(vol_item); } } Expand(item); @@ -1931,7 +1940,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) auto opt_keys = model_object->config.keys(); if (!opt_keys.empty() && !(opt_keys.size() == 1 && opt_keys[0] == "extruder")) { select_item(m_objects_model->AddSettingsChild(item)); - /*Collapse*/Expand(item); + Expand(item); } #ifndef __WXOSX__ @@ -2732,11 +2741,15 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co if (!item) return; - if (get_mesh_errors_count(obj_idx, vol_idx) == 0) { - // delete Error_icon if all errors are fixed - wxVariant variant; - variant << DataViewBitmapText(from_u8((*m_objects)[obj_idx]->name), wxNullBitmap); - m_objects_model->SetValue(variant, item, 0); + 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); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 53acaaf3c..1ca358cd9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -216,7 +216,7 @@ public: void update_opt_keys(t_config_option_keys& t_optopt_keys); void load_subobject(ModelVolumeType type); - void load_part(ModelObject* model_object, wxArrayString& part_names, ModelVolumeType type); + void load_part(ModelObject* model_object, std::vector> &volumes_info, ModelVolumeType type); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); void del_object(const int obj_idx); void del_subobject_item(wxDataViewItem& item); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 29e8c2558..eea53e828 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -21,7 +21,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) #ifndef __APPLE__ , m_focused_option("") - , m_manifold_warning_bmp(create_scaled_bitmap(parent, "exclamation")) + , m_manifold_warning_bmp(ScalableBitmap(parent, "exclamation")) #endif // __APPLE__ { m_og->set_name(_(L("Object Manipulation"))); @@ -367,8 +367,7 @@ void ObjectManipulation::emulate_kill_focus() void ObjectManipulation::update_manifold_warning_icon_state(const wxString& tooltip) { - m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp); - + m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetToolTip(tooltip); } @@ -559,5 +558,13 @@ void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) m_og->set_value(opt_key, double_to_string(value)); } +void ObjectManipulation::msw_rescale() +{ + m_manifold_warning_bmp.msw_rescale(); + m_fix_throught_netfab_bitmap->SetBitmap(m_manifold_warning_bmp.bmp()); + + get_og()->msw_rescale(); +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 9ced31a1f..f691dcc83 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -79,7 +79,7 @@ class ObjectManipulation : public OG_Settings bool m_uniform_scale {true}; LockButton* m_lock_bnt{ nullptr }; - wxBitmap m_manifold_warning_bmp; + ScalableBitmap m_manifold_warning_bmp; wxStaticBitmap* m_fix_throught_netfab_bitmap; #ifndef __APPLE__ @@ -112,6 +112,7 @@ public: #endif // __APPLE__ void update_manifold_warning_icon_state(const wxString& tooltip); + void msw_rescale(); private: void reset_settings_value(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c221b5066..d45abd479 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -896,8 +896,7 @@ void Sidebar::msw_rescale() p->frequently_changed_parameters->get_og(false)->msw_rescale(); p->object_list->msw_rescale(); - - p->object_manipulation->get_og()->msw_rescale(); + p->object_manipulation->msw_rescale(); p->object_settings->msw_rescale(); p->object_info->msw_rescale(); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index d76e0da93..08069d02b 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -420,14 +420,21 @@ ObjectDataViewModel::~ObjectDataViewModel() m_bitmap_cache = nullptr; } -wxDataViewItem ObjectDataViewModel::Add(const wxString &name, const int extruder) +wxDataViewItem ObjectDataViewModel::Add(const wxString &name, + const int extruder, + const bool has_errors/* = false*/) { const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); auto root = new ObjectDataViewModelNode(name, extruder_str); + // Add error icon if detected auto-repaire + if (has_errors) + root->m_bmp = *m_warning_bmp; + m_objects.push_back(root); // notify control wxDataViewItem child((void*)root); wxDataViewItem parent((void*)NULL); + ItemAdded(parent, child); return child; } @@ -435,6 +442,7 @@ wxDataViewItem ObjectDataViewModel::Add(const wxString &name, const int extruder wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent_item, const wxString &name, const Slic3r::ModelVolumeType volume_type, + const bool has_errors/* = false*/, const int extruder/* = 0*/, const bool create_frst_child/* = true*/) { @@ -448,9 +456,14 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent if (insert_position < 0 || root->GetNthChild(insert_position)->m_type != itInstanceRoot) insert_position = -1; + const bool obj_errors = root->m_bmp.IsOk(); + if (create_frst_child && root->m_volumes_cnt == 0) { - const auto node = new ObjectDataViewModelNode(root, root->m_name, *m_volume_bmps[0], extruder_str, 0); + const Slic3r::ModelVolumeType type = Slic3r::ModelVolumeType::MODEL_PART; + const auto node = new ObjectDataViewModelNode(root, root->m_name, GetVolumeIcon(type, obj_errors), extruder_str, 0); + node->m_volume_type = type; + insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // notify control const wxDataViewItem child((void*)node); @@ -458,12 +471,15 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent root->m_volumes_cnt++; if (insert_position > 0) insert_position++; - - node->m_volume_type = volume_type; } - const auto node = new ObjectDataViewModelNode(root, name, *m_volume_bmps[int(volume_type)], extruder_str, root->m_volumes_cnt); + const auto node = new ObjectDataViewModelNode(root, name, GetVolumeIcon(volume_type, has_errors), extruder_str, root->m_volumes_cnt); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); + + // if part with errors is added, but object wasn't marked, then mark it + if (!obj_errors && has_errors) + root->SetBitmap(*m_warning_bmp); + // notify control const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); @@ -1228,15 +1244,61 @@ void ObjectDataViewModel::Rescale() node->msw_rescale(); if (node->m_type & itVolume) - node->m_bmp = *m_volume_bmps[node->volume_type()]; + node->m_bmp = GetVolumeIcon(node->m_volume_type, node->m_bmp.GetWidth() != node->m_bmp.GetHeight()); if (node->m_type & itObject && node->m_bmp.IsOk()) - node->m_bmp = create_scaled_bitmap(nullptr, "exclamation"); + node->m_bmp = *m_warning_bmp; ItemChanged(item); } } +wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const bool is_marked/* = false*/) +{ + if (!is_marked) + return *m_volume_bmps[static_cast(vol_type)]; + + std::string scaled_bitmap_name = "warning" + std::to_string(static_cast(vol_type)); + scaled_bitmap_name += "-em" + std::to_string(Slic3r::GUI::wxGetApp().em_unit()); + + wxBitmap *bmp = m_bitmap_cache->find(scaled_bitmap_name); + if (bmp == nullptr) { + std::vector bmps; + + bmps.emplace_back(*m_warning_bmp); + bmps.emplace_back(*m_volume_bmps[static_cast(vol_type)]); + + bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps); + } + + return *bmp; +} + +void ObjectDataViewModel::DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object/* = false*/) +{ + if (!item.IsOk()) + return; + + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); + + if (!node->GetBitmap().IsOk() || !(node->GetType() & (itVolume | itObject))) + return; + + if (node->GetType() & itVolume) { + node->SetBitmap(*m_volume_bmps[static_cast(node->volume_type())]); + return; + } + + node->SetBitmap(wxNullBitmap); + if (unmark_object) + { + wxDataViewItemArray children; + GetChildren(item, children); + for (const wxDataViewItem& child : children) + DeleteWarningIcon(child); + } +} + //----------------------------------------------------------------------------- // PrusaDataViewBitmapText //----------------------------------------------------------------------------- @@ -2351,8 +2413,7 @@ void ModeButton::SetState(const bool state) void ModeButton::focus_button(const bool focus) { - wxFont font = GetFont(); - const wxFont& new_font = focus ? font.Bold() : font.GetBaseFont(); + const wxFont& new_font = focus ? Slic3r::GUI::wxGetApp().bold_font() : Slic3r::GUI::wxGetApp().normal_font(); SetFont(new_font); @@ -2378,11 +2439,7 @@ ModeSizer::ModeSizer(wxWindow *parent, int hgap/* = 10*/) : m_mode_btns.reserve(3); for (const auto& button : buttons) { -// int x, y; -// parent->GetTextExtent(button.first, &x, &y, nullptr, nullptr, &Slic3r::GUI::wxGetApp().bold_font()); -// const wxSize size = wxSize(x + button.second.GetWidth() + Slic3r::GUI::wxGetApp().em_unit(), -// y + Slic3r::GUI::wxGetApp().em_unit()); - m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first/*, size*/)); + m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first)); } for (auto btn : m_mode_btns) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 589317f2b..8527e5425 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -323,14 +323,10 @@ public: return false; } - void SetBitmap(const wxBitmap &icon) - { - m_bmp = icon; - } - - ItemType GetType() const { - return m_type; - } + void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } + const wxBitmap& GetBitmap() const { return m_bmp; } + const wxString& GetName() const { return m_name; } + ItemType GetType() const { return m_type; } void SetIdx(const int& idx) { m_idx = idx; @@ -339,9 +335,7 @@ public: m_name = wxString::Format("Instance_%d", m_idx + 1); } - int GetIdx() const { - return m_idx; - } + int GetIdx() const { return m_idx; } // use this function only for childrens void AssignAllVal(ObjectDataViewModelNode& from_node) @@ -374,10 +368,10 @@ public: // Set action icons for node void set_action_icon(); - void update_settings_digest_bitmaps(); - bool update_settings_digest(const std::vector& categories); - int volume_type() const { return int(m_volume_type); } - void msw_rescale(); + void update_settings_digest_bitmaps(); + bool update_settings_digest(const std::vector& categories); + int volume_type() const { return int(m_volume_type); } + void msw_rescale(); private: friend class ObjectDataViewModel; }; @@ -393,6 +387,7 @@ class ObjectDataViewModel :public wxDataViewModel { std::vector m_objects; std::vector m_volume_bmps; + wxBitmap* m_warning_bmp; wxDataViewCtrl* m_ctrl{ nullptr }; @@ -400,10 +395,13 @@ public: ObjectDataViewModel(); ~ObjectDataViewModel(); - wxDataViewItem Add(const wxString &name, const int extruder); + wxDataViewItem Add( const wxString &name, + const int extruder, + const bool has_errors = false); wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item, const wxString &name, const Slic3r::ModelVolumeType volume_type, + const bool has_errors = false, const int extruder = 0, const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); @@ -475,11 +473,16 @@ public: const std::vector& categories); void SetVolumeBitmaps(const std::vector& volume_bmps) { m_volume_bmps = volume_bmps; } + void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; } void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type); void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; } // Rescale bitmaps for existing Items void Rescale(); + + wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, + const bool is_marked = false); + void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false); }; // ---------------------------------------------------------------------------- From 6ddefc6a650345dc99831fd4e280856b494de8e2 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 30 Apr 2019 09:11:57 +0200 Subject: [PATCH 05/15] Some refactoring to fix OSX build --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 1a4245965..2fbf4baa1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1886,7 +1886,8 @@ 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_manifold_warning_icon_state(get_mesh_errors_list(obj_idx, volume_id)); + const wxString& tooltip = get_mesh_errors_list(obj_idx, volume_id); + wxGetApp().obj_manipul()->update_manifold_warning_icon_state(tooltip); } } From 3eacb0a216ded94ec535334f9c0611f7e54ed9ad Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 30 Apr 2019 09:38:23 +0200 Subject: [PATCH 06/15] Next try --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 ++-- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 ++-- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 2fbf4baa1..69c3e3f1b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1886,8 +1886,8 @@ void ObjectList::part_selection_changed() if (item) { wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item)); - const wxString& tooltip = get_mesh_errors_list(obj_idx, volume_id); - wxGetApp().obj_manipul()->update_manifold_warning_icon_state(tooltip); + const wxString tooltip = get_mesh_errors_list(obj_idx, volume_id); + wxGetApp().obj_manipul()->update_warning_icon_state(tooltip); } } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index eea53e828..86d8e9a96 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -66,7 +66,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : return; wxGetApp().obj_list()->fix_through_netfabb(); - update_manifold_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list()); + update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list()); }); return sizer; @@ -365,7 +365,7 @@ void ObjectManipulation::emulate_kill_focus() on_change(option, 0); } -void ObjectManipulation::update_manifold_warning_icon_state(const wxString& tooltip) +void ObjectManipulation::update_warning_icon_state(const wxString& tooltip) { m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetToolTip(tooltip); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index f691dcc83..da9e67d4e 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -9,6 +9,7 @@ class wxStaticText; class LockButton; class wxStaticBitmap; +class wxString; namespace Slic3r { namespace GUI { @@ -111,7 +112,7 @@ public: void emulate_kill_focus(); #endif // __APPLE__ - void update_manifold_warning_icon_state(const wxString& tooltip); + void update_warning_icon_state(const wxString& tooltip); void msw_rescale(); private: From 3bc6c29b7a388fd1ef41d0c4ac16a1cd21f3bf41 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 30 Apr 2019 11:27:41 +0200 Subject: [PATCH 07/15] Added missed include --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +-- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 69c3e3f1b..8c9f4cc4a 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1886,8 +1886,7 @@ void ObjectList::part_selection_changed() if (item) { wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item)); - const wxString tooltip = get_mesh_errors_list(obj_idx, volume_id); - wxGetApp().obj_manipul()->update_warning_icon_state(tooltip); + wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_list(obj_idx, volume_id)); } } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index da9e67d4e..5aa69cd15 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -2,6 +2,7 @@ #define slic3r_GUI_ObjectManipulation_hpp_ #include +#include #include "GUI_ObjectSettings.hpp" #include "GLCanvas3D.hpp" @@ -9,7 +10,6 @@ class wxStaticText; class LockButton; class wxStaticBitmap; -class wxString; namespace Slic3r { namespace GUI { From 11a04f918bf8b05f0d56da45bb8b3e05737ec509 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 30 Apr 2019 15:46:25 +0200 Subject: [PATCH 08/15] ObjectList: Show tooltip for warning icon only instead of whole "Name" cell --- src/slic3r/GUI/GUI_ObjectList.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 8c9f4cc4a..cb0a03547 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -244,7 +244,7 @@ wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx / for (const auto& error : error_msg) if (error.second > 0) - tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); + tooltip += wxString::Format("\t%d %s\n", error.second, _(error.first)); if (is_windows10()) tooltip += _(L("Right button click the icon to fix STL through Netfabb")); @@ -272,8 +272,14 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); - else if (col->GetTitle() == _("Name") ) + else if (col->GetTitle() == _("Name")) { +#ifdef __WXMSW__ + if (pt.x < 2 * wxGetApp().em_unit() || pt.x > 4 * wxGetApp().em_unit()) { + GetMainWindow()->SetToolTip(""); // hide tooltip + return; + } +#endif //__WXMSW__ int obj_idx, vol_idx; get_selected_item_indexes(obj_idx, vol_idx, item); GetMainWindow()->SetToolTip(get_mesh_errors_list(obj_idx, vol_idx)); From 7f37f82ad4696543af0cab8f5b7453644aef639f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 30 Apr 2019 16:59:40 +0200 Subject: [PATCH 09/15] Added comments --- src/slic3r/GUI/GUI_ObjectList.cpp | 5 +++++ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index cb0a03547..bb3bd2844 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -270,6 +270,11 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) HitTest(pt, item, col); if (!item) return; + /* GetMainWindow() return window, associated with wxDataViewCtrl. + * And for this window we should to set tooltips. + * Just this->SetToolTip(tooltip) => has no effect. + */ + if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name")) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 5aa69cd15..78941135c 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -2,7 +2,7 @@ #define slic3r_GUI_ObjectManipulation_hpp_ #include -#include +#include #include "GUI_ObjectSettings.hpp" #include "GLCanvas3D.hpp" From b048669a3bf533ae0158ea9dd16bf6c6090165ea Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 2 May 2019 08:33:38 +0200 Subject: [PATCH 10/15] Changed update_warning_icon_state() signature (next try to fix OSX compilation) --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 6 ++++-- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index bb3bd2844..61ee7e1b8 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1897,7 +1897,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_warning_icon_state(get_mesh_errors_list(obj_idx, volume_id)); + wxGetApp().obj_manipul()->update_warning_icon_state(/*get_mesh_errors_list(obj_idx, volume_id)*/); } } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 86d8e9a96..bb6eec963 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -66,7 +66,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : return; wxGetApp().obj_list()->fix_through_netfabb(); - update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list()); + update_warning_icon_state(/*wxGetApp().obj_list()->get_mesh_errors_list()*/); }); return sizer; @@ -365,8 +365,10 @@ void ObjectManipulation::emulate_kill_focus() on_change(option, 0); } -void ObjectManipulation::update_warning_icon_state(const wxString& tooltip) +void ObjectManipulation::update_warning_icon_state(/*const wxString& tooltip*/) { + const wxString& tooltip = wxGetApp().obj_list()->get_mesh_errors_list(); + m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetToolTip(tooltip); } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 78941135c..1bff4e22f 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -2,7 +2,6 @@ #define slic3r_GUI_ObjectManipulation_hpp_ #include -#include #include "GUI_ObjectSettings.hpp" #include "GLCanvas3D.hpp" @@ -112,7 +111,7 @@ public: void emulate_kill_focus(); #endif // __APPLE__ - void update_warning_icon_state(const wxString& tooltip); + void update_warning_icon_state(/*const wxString& tooltip*/); void msw_rescale(); private: From 88c9948c85a01474be7af47061931c9017e9a946 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 2 May 2019 09:54:18 +0200 Subject: [PATCH 11/15] Fixed typo --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 9 +++------ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 61ee7e1b8..bb3bd2844 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1897,7 +1897,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_warning_icon_state(/*get_mesh_errors_list(obj_idx, volume_id)*/); + wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_list(obj_idx, volume_id)); } } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index bb6eec963..b8c37dcd0 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -66,7 +66,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : return; wxGetApp().obj_list()->fix_through_netfabb(); - update_warning_icon_state(/*wxGetApp().obj_list()->get_mesh_errors_list()*/); + update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list()); }); return sizer; @@ -364,17 +364,14 @@ void ObjectManipulation::emulate_kill_focus() else on_change(option, 0); } +#endif // __APPLE__ -void ObjectManipulation::update_warning_icon_state(/*const wxString& tooltip*/) +void ObjectManipulation::update_warning_icon_state(const wxString& tooltip) { - const wxString& tooltip = wxGetApp().obj_list()->get_mesh_errors_list(); - m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetToolTip(tooltip); } -#endif // __APPLE__ - void ObjectManipulation::reset_settings_value() { m_new_position = Vec3d::Zero(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 1bff4e22f..f86cd6e56 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -111,7 +111,7 @@ public: void emulate_kill_focus(); #endif // __APPLE__ - void update_warning_icon_state(/*const wxString& tooltip*/); + void update_warning_icon_state(const wxString& tooltip); void msw_rescale(); private: From d2107fad2fb2bbd38538666fb8ab9557c9d98e31 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 2 May 2019 16:20:50 +0200 Subject: [PATCH 12/15] Fixed get_object_stl_stats() --- src/libslic3r/Model.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 17769a8e7..271b728b5 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1456,28 +1456,28 @@ stl_stats ModelObject::get_object_stl_stats() const if (this->volumes.size() == 1) return this->volumes[0]->mesh.stl.stats; - stl_stats full_stats; - - // initialise full_stats - full_stats.degenerate_facets= 0; - full_stats.edges_fixed = 0; - full_stats.facets_removed = 0; - full_stats.facets_added = 0; - full_stats.facets_reversed = 0; - full_stats.backwards_edges = 0; - full_stats.normals_fixed = 0; + stl_stats full_stats = this->volumes[0]->mesh.stl.stats; // fill full_stats from all objet's meshes for (ModelVolume* volume : this->volumes) { + if (volume->id() == this->volumes[0]->id()) + continue; + const stl_stats& stats = volume->mesh.stl.stats; + // initialize full_stats (for repaired errors) full_stats.degenerate_facets+= stats.degenerate_facets; full_stats.edges_fixed += stats.edges_fixed; full_stats.facets_removed += stats.facets_removed; full_stats.facets_added += stats.facets_added; full_stats.facets_reversed += stats.facets_reversed; full_stats.backwards_edges += stats.backwards_edges; + + // another used satistics value + if (volume->is_model_part()) + full_stats.volume += stats.volume; + full_stats.number_of_parts += stats.number_of_parts; } return full_stats; From 4be4dc623c097b529b417692c543eae5ec6e4c5c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 3 May 2019 13:09:42 +0200 Subject: [PATCH 13/15] Fixed full statistics calculation (calculate sum of volume and part_count only for solid parts) --- src/libslic3r/Model.cpp | 19 ++++++++++--------- src/slic3r/GUI/GUI_App.cpp | 8 ++++---- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 5 ++++- src/slic3r/GUI/Plater.cpp | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 271b728b5..ec95eb578 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1467,17 +1467,18 @@ stl_stats ModelObject::get_object_stl_stats() const const stl_stats& stats = volume->mesh.stl.stats; // initialize full_stats (for repaired errors) - full_stats.degenerate_facets+= stats.degenerate_facets; - full_stats.edges_fixed += stats.edges_fixed; - full_stats.facets_removed += stats.facets_removed; - full_stats.facets_added += stats.facets_added; - full_stats.facets_reversed += stats.facets_reversed; - full_stats.backwards_edges += stats.backwards_edges; + full_stats.degenerate_facets += stats.degenerate_facets; + full_stats.edges_fixed += stats.edges_fixed; + full_stats.facets_removed += stats.facets_removed; + full_stats.facets_added += stats.facets_added; + full_stats.facets_reversed += stats.facets_reversed; + full_stats.backwards_edges += stats.backwards_edges; // another used satistics value - if (volume->is_model_part()) - full_stats.volume += stats.volume; - full_stats.number_of_parts += stats.number_of_parts; + if (volume->is_model_part()) { + full_stats.volume += stats.volume; + full_stats.number_of_parts += stats.number_of_parts; + } } return full_stats; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 595a968bd..47141a664 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -303,13 +303,13 @@ bool GUI_App::dark_mode_menus() void GUI_App::init_label_colours() { if (dark_mode()) { - m_color_label_modified = wxColour(252, 77, 1); - m_color_label_sys = wxColour(26, 132, 57); - } - else { m_color_label_modified = wxColour(253, 111, 40); m_color_label_sys = wxColour(115, 220, 103); } + else { + m_color_label_modified = wxColour(252, 77, 1); + m_color_label_sys = wxColour(26, 132, 57); + } m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index b8c37dcd0..d50f03050 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -21,9 +21,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) #ifndef __APPLE__ , m_focused_option("") - , m_manifold_warning_bmp(ScalableBitmap(parent, "exclamation")) #endif // __APPLE__ { + m_manifold_warning_bmp = ScalableBitmap(parent, "exclamation"); m_og->set_name(_(L("Object Manipulation"))); m_og->label_width = 12;//125; m_og->set_grid_vgap(5); @@ -77,6 +77,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : def.gui_type = "legend"; def.tooltip = L("Object name"); def.width = 21; +#ifdef __APPLE__ + def.width = 19; +#endif def.default_value = new ConfigOptionString{ " " }; line.append_option(Option(def, "object_name")); m_og->append_line(line); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 07e1e2bae..97845f8be 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -724,7 +724,7 @@ Sidebar::Sidebar(Plater *parent) auto init_btn = [this](wxButton **btn, wxString label) { *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, - wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + wxDefaultSize, wxBU_EXACTFIT); (*btn)->SetFont(wxGetApp().bold_font()); }; From 80d3cbac73f9798db3d739e9deb5f2ca25176203 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 3 May 2019 14:29:28 +0200 Subject: [PATCH 14/15] Temporary fix for crash, if try to add second settings grope for instance --- src/slic3r/GUI/GUI_ObjectList.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 833cd712e..0734028d1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -937,6 +937,13 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) { const std::vector& options = get_options_for_bundle(bundle_name); + /* #ys_FIXME_delete_after_testing ! Temporary workaround to avoid a crash: + * After a right click on an instance all items in the ObjectList are unselected, + * and as a result m_config == nullptr. + */ + if (!m_config) + return; + auto opt_keys = m_config->keys(); const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; @@ -966,6 +973,10 @@ void ObjectList::update_settings_item() const auto settings_item = m_objects_model->IsSettingsItem(item) ? item : m_objects_model->GetSettingsItem(item); select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); + + // update object selection on Plater + if (!m_prevent_canvas_selection_update) + update_selections_on_canvas(); } else { auto panel = wxGetApp().sidebar().scrolled_panel(); From 8be585893a8207dc6628330e31121189c6726c89 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 3 May 2019 16:05:49 +0200 Subject: [PATCH 15/15] Fixed a crash, if try to add second settings grope for instance --- src/slic3r/GUI/GUI_ObjectList.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 64a7ce8a6..09a6e94a8 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1000,13 +1000,7 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) { const std::vector& options = get_options_for_bundle(bundle_name); - /* #ys_FIXME_delete_after_testing ! Temporary workaround to avoid a crash: - * After a right click on an instance all items in the ObjectList are unselected, - * and as a result m_config == nullptr. - */ - if (!m_config) - return; - + assert(m_config); auto opt_keys = m_config->keys(); const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; @@ -2156,6 +2150,11 @@ void ObjectList::update_selections() if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx()) return; } + + // but if there is selected only one of several instances by context menu, + // then select this instance in ObjectList + if (selection.is_single_full_instance()) + sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), selection.get_instance_idx())); } else if (selection.is_single_full_object() || selection.is_multiple_full_object()) {