From 306b54bc0a78ba768aa7544f117c2884a3af833e Mon Sep 17 00:00:00 2001 From: Justin Schuh Date: Tue, 21 Sep 2021 06:50:04 -0700 Subject: [PATCH 01/57] Fix float accuracy issue when thick_bridges is off (#6957) --- src/libslic3r/PrintObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d9a4f2670..74ef27bd7 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1447,7 +1447,7 @@ void PrintObject::bridge_over_infill() Polygons to_bridge_pp = internal_solid; // iterate through lower layers spanned by bridge_flow - double bottom_z = layer->print_z - bridge_flow.height(); + double bottom_z = layer->print_z - bridge_flow.height() - EPSILON; for (int i = int(layer_it - m_layers.begin()) - 1; i >= 0; --i) { const Layer* lower_layer = m_layers[i]; From a5a7f64db08bbd1c93c0800b3f96d0e372ca1e40 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 21 Sep 2021 16:03:30 +0200 Subject: [PATCH 02/57] Mesh statistics for imported STLs: Added backwards_edges to open_edges, so that a mesh with incorrectly oriented faces will not be considered a manifold. Added assert for 3D convex hulls constructed by QHull. They shall be manifold (however sometimes they are not). --- src/libslic3r/TriangleMesh.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 183b195a1..73ac2eade 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -191,7 +191,7 @@ bool TriangleMesh::ReadSTLFile(const char* input_file, bool repair) auto facets_w_1_bad_edge = stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge; auto facets_w_2_bad_edge = stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge; auto facets_w_3_bad_edge = stl.stats.number_of_facets - stl.stats.connected_facets_1_edge; - m_stats.open_edges = facets_w_1_bad_edge + facets_w_2_bad_edge * 2 + facets_w_3_bad_edge * 3; + m_stats.open_edges = stl.stats.backwards_edges + facets_w_1_bad_edge + facets_w_2_bad_edge * 2 + facets_w_3_bad_edge * 3; m_stats.edges_fixed = stl.stats.edges_fixed; m_stats.degenerate_facets = stl.stats.degenerate_facets; @@ -507,7 +507,9 @@ TriangleMesh TriangleMesh::convex_hull_3d() const } } - return TriangleMesh { std::move(dst_vertices), std::move(dst_facets) }; + TriangleMesh mesh{ std::move(dst_vertices), std::move(dst_facets) }; + assert(mesh.stats().manifold()); + return mesh; } std::vector TriangleMesh::slice(const std::vector &z) const From 238e65e45515da63c0a0ea5283b8a5e91ef1353d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 21 Sep 2021 17:18:12 +0200 Subject: [PATCH 03/57] Improvements for statistics information: + Show 2 groups of errors: "Auto-repared" and "Remaning". + Use different icons for volumes with/without remaining errors + Fixed update of the ObjectList warnings icons after switch the color mode of a PrusaSlicer + Some code refactoring: Use same code for tooltips for "exclamation"-icon from an ObjectList and from a Sidebar->ObjectInfo --- resources/icons/exclamation_manifold.svg | 17 +++++ .../icons/white/exclamation_manifold.svg | 17 +++++ src/libslic3r/Model.cpp | 1 + src/slic3r/GUI/GUI_App.cpp | 4 +- src/slic3r/GUI/GUI_ObjectList.cpp | 54 +++++++++----- src/slic3r/GUI/GUI_ObjectList.hpp | 12 ++-- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 10 ++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- src/slic3r/GUI/ObjectDataViewModel.cpp | 70 ++++++++++++------- src/slic3r/GUI/ObjectDataViewModel.hpp | 19 +++-- src/slic3r/GUI/Plater.cpp | 39 +++++------ 11 files changed, 163 insertions(+), 82 deletions(-) create mode 100644 resources/icons/exclamation_manifold.svg create mode 100644 resources/icons/white/exclamation_manifold.svg diff --git a/resources/icons/exclamation_manifold.svg b/resources/icons/exclamation_manifold.svg new file mode 100644 index 000000000..cd8ba5954 --- /dev/null +++ b/resources/icons/exclamation_manifold.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/resources/icons/white/exclamation_manifold.svg b/resources/icons/white/exclamation_manifold.svg new file mode 100644 index 000000000..a18590167 --- /dev/null +++ b/resources/icons/white/exclamation_manifold.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8337ab384..b42dfb6a4 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1615,6 +1615,7 @@ TriangleMeshStats ModelObject::get_object_stl_stats() const const TriangleMeshStats& stats = volume->mesh().stats(); // initialize full_stats (for repaired errors) + full_stats.open_edges += stats.open_edges; full_stats.degenerate_facets += stats.degenerate_facets; full_stats.edges_fixed += stats.edges_fixed; full_stats.facets_removed += stats.facets_removed; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 23ce889df..8689f43cd 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1403,9 +1403,8 @@ void GUI_App::force_colors_update() void GUI_App::update_ui_from_settings() { update_label_colours(); - mainframe->update_ui_from_settings(); - #ifdef _WIN32 + // Upadte UU colors before Update UI from settings if (m_force_colors_update) { m_force_colors_update = false; mainframe->force_color_changed(); @@ -1414,6 +1413,7 @@ void GUI_App::update_ui_from_settings() m_wizard->force_color_changed(); } #endif + mainframe->update_ui_from_settings(); } void GUI_App::persist_window_geometry(wxTopLevelWindow *window, bool default_maximized) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 35e5bb83e..7c019337e 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -382,12 +382,17 @@ int ObjectList::get_mesh_errors_count(const int obj_idx, const int vol_idx /*= - 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 +static std::string get_warning_icon_name(const TriangleMeshStats& stats) +{ + return stats.repaired() ? (stats.manifold() ? "exclamation_manifold" : "exclamation") : ""; +} + +std::pair ObjectList::get_mesh_errors(const int obj_idx, const int vol_idx /*= -1*/, bool from_plater /*= false*/) const { const int errors = get_mesh_errors_count(obj_idx, vol_idx); if (errors == 0) - return ""; // hide tooltip + return { "", "" }; // hide tooltip // Create tooltip string, if there are errors wxString tooltip = format_wxstr(_L_PLURAL("Auto-repaired %1$d error", "Auto-repaired %1$d errors", errors), errors) + ":\n"; @@ -407,21 +412,26 @@ wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx / if (stats.backwards_edges > 0) tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d backwards edge", "%1$d backwards edges", stats.backwards_edges), stats.backwards_edges) + "\n"; - if (is_windows10()) - tooltip += _L("Right button click the icon to fix STL through Netfabb"); + if (!stats.manifold()) { + tooltip += _L("Remaning errors") + ":\n"; + tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d open edge", "%1$d open edges", stats.open_edges), stats.open_edges) + "\n"; + } - return tooltip; + if (is_windows10() && !from_plater) + tooltip += "\n" + _L("Right button click the icon to fix STL through Netfabb"); + + return { tooltip, get_warning_icon_name(stats) }; } -wxString ObjectList::get_mesh_errors_list() +std::pair ObjectList::get_mesh_errors(bool from_plater /*= false*/) { if (!GetSelection()) - return ""; + return { "", "" }; int obj_idx, vol_idx; get_selected_item_indexes(obj_idx, vol_idx); - return get_mesh_errors_list(obj_idx, vol_idx); + return get_mesh_errors(obj_idx, vol_idx, from_plater); } void ObjectList::set_tooltip_for_item(const wxPoint& pt) @@ -459,7 +469,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) { int obj_idx, vol_idx; get_selected_item_indexes(obj_idx, vol_idx, item); - tooltip = get_mesh_errors_list(obj_idx, vol_idx); + tooltip = get_mesh_errors(obj_idx, vol_idx).first; } GetMainWindow()->SetToolTip(tooltip); @@ -1775,8 +1785,12 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) 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(parent); + 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())); + } m_objects_model->Delete(item); update_info_items(obj_idx); @@ -1985,7 +1999,7 @@ void ObjectList::split() for (const ModelVolume* volume : model_object->volumes) { const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(parent, from_u8(volume->name), volume->type(),// is_modifier() ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, - volume->get_mesh_errors_count()>0, + get_warning_icon_name(volume->mesh().stats()), volume->config.has("extruder") ? volume->config.extruder() : 0, false); // add settings to the part, if it has those @@ -2484,7 +2498,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_list(obj_idx, volume_id)); + wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors(obj_idx, volume_id)); } } @@ -2627,7 +2641,7 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed) const wxString& item_name = from_u8(model_object->name); const auto item = m_objects_model->Add(item_name, model_object->config.has("extruder") ? model_object->config.extruder() : 0, - get_mesh_errors_count(obj_idx) > 0); + get_warning_icon_name(model_object->mesh().stats())); update_info_items(obj_idx, nullptr, call_selection_changed); @@ -2637,7 +2651,7 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed) const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item, from_u8(volume->name), volume->type(), - volume->get_mesh_errors_count()>0, + get_warning_icon_name(volume->mesh().stats()), volume->config.has("extruder") ? volume->config.extruder() : 0, false); add_settings_item(vol_item, &volume->config.get()); @@ -2746,6 +2760,8 @@ void ObjectList::delete_from_model_and_list(const std::vector& it // 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())); } wxGetApp().plater()->canvas3D()->ensure_on_bed(item->obj_idx, printer_technology() != ptSLA); } @@ -4162,8 +4178,10 @@ void ObjectList::update_item_error_icon(const int obj_idx, const int vol_idx) co // unmark fixed item only m_objects_model->DeleteWarningIcon(item); } - else - m_objects_model->AddWarningIcon(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())); + } } void ObjectList::msw_rescale() @@ -4294,7 +4312,7 @@ wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(int obj_idx, s for (const ModelVolume* volume : object->volumes) { wxDataViewItem vol_item = m_objects_model->AddVolumeChild(object_item, from_u8(volume->name), volume->type(), - volume->get_mesh_errors_count() > 0, + get_warning_icon_name(volume->mesh().stats()), volume->config.has("extruder") ? volume->config.extruder() : 0, false); // add settings to the part, if it has those diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 0fbad1919..491bd2684 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -210,12 +210,12 @@ public: 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; - /* 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(); + // 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, bool from_plater = false) const; + std::pair get_mesh_errors(bool from_plater = false); 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 d35def196..6eaa6316d 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -132,7 +132,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()); }); sizer->Add(m_fix_throught_netfab_bitmap); @@ -776,8 +776,12 @@ void ObjectManipulation::update_item_name(const wxString& item_name) m_item_name->SetLabel(item_name); } -void ObjectManipulation::update_warning_icon_state(const wxString& tooltip) -{ +void ObjectManipulation::update_warning_icon_state(const std::pair& warning) +{ + if (const std::string& warning_icon_name = warning.second; + !warning_icon_name.empty()) + m_manifold_warning_bmp = ScalableBitmap(m_parent, warning_icon_name); + const wxString& tooltip = warning.first; 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 92ba01775..9b77591be 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -194,7 +194,7 @@ public: #endif // __APPLE__ void update_item_name(const wxString &item_name); - void update_warning_icon_state(const wxString& tooltip); + void update_warning_icon_state(const std::pair& 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 8ceb3cc23..746a99a2f 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -37,6 +37,7 @@ void ObjectDataViewModelNode::init_container() static constexpr char LayerRootIcon[] = "edit_layers_all"; static constexpr char LayerIcon[] = "edit_layers_some"; static constexpr char WarningIcon[] = "exclamation"; +static constexpr char WarningManifoldIcon[] = "exclamation_manifold"; struct InfoItemAtributes { std::string name; @@ -57,13 +58,15 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* pare Slic3r::ModelVolumeType type, const wxBitmap& bmp, const wxString& extruder, - const int idx/* = -1*/) : + const int idx/* = -1*/, + const std::string& warning_icon_name /*= std::string*/) : m_parent(parent), m_name(sub_obj_name), m_type(itVolume), m_volume_type(type), m_idx(idx), - m_extruder(type == Slic3r::ModelVolumeType::MODEL_PART || type == Slic3r::ModelVolumeType::PARAMETER_MODIFIER ? extruder : "") + m_extruder(type == Slic3r::ModelVolumeType::MODEL_PART || type == Slic3r::ModelVolumeType::PARAMETER_MODIFIER ? extruder : ""), + m_warning_icon_name(warning_icon_name) { m_bmp = bmp; set_action_and_extruder_icons(); @@ -170,6 +173,13 @@ void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable) create_scaled_bitmap(m_printable == piPrintable ? "eye_open.png" : "eye_closed.png"); } +void ObjectDataViewModelNode::set_warning_icon(const std::string& warning_icon_name) +{ + m_warning_icon_name = warning_icon_name; + if (warning_icon_name.empty()) + m_bmp = m_empty_bmp; +} + void ObjectDataViewModelNode::update_settings_digest_bitmaps() { m_bmp = m_empty_bmp; @@ -316,6 +326,8 @@ ObjectDataViewModel::ObjectDataViewModel() m_volume_bmps = MenuFactory::get_volume_bitmaps(); m_warning_bmp = create_scaled_bitmap(WarningIcon); + m_warning_manifold_bmp = create_scaled_bitmap(WarningManifoldIcon); + for (auto item : INFO_ITEMS) m_info_bmps[item.first] = create_scaled_bitmap(item.second.bmp_name); } @@ -328,15 +340,19 @@ ObjectDataViewModel::~ObjectDataViewModel() m_bitmap_cache = nullptr; } +wxBitmap& ObjectDataViewModel::GetWarningBitmap(const std::string& warning_icon_name) +{ + return warning_icon_name.empty() ? m_empty_bmp : warning_icon_name == WarningIcon ? m_warning_bmp : m_warning_manifold_bmp; +} + wxDataViewItem ObjectDataViewModel::Add(const wxString &name, const int extruder, - const bool has_errors/* = false*/) + const std::string& warning_icon_name/* = std::string()*/ ) { - const wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder); + const wxString extruder_str = extruder == 0 ? _L("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; + // Add warning icon if detected auto-repaire + root->SetWarningBitmap(GetWarningBitmap(warning_icon_name), warning_icon_name); m_objects.push_back(root); // notify control @@ -350,7 +366,7 @@ wxDataViewItem ObjectDataViewModel::Add(const wxString &name, wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent_item, const wxString &name, const Slic3r::ModelVolumeType volume_type, - const bool has_errors/* = false*/, + const std::string& warning_icon_name/* = std::string()*/, const int extruder/* = 0*/, const bool create_frst_child/* = true*/) { @@ -364,12 +380,10 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent if (insert_position < 0) insert_position = get_root_idx(root, itInstanceRoot); - const bool obj_errors = root->m_bmp.IsOk(); - if (create_frst_child && root->m_volumes_cnt == 0) { const Slic3r::ModelVolumeType type = Slic3r::ModelVolumeType::MODEL_PART; - const auto node = new ObjectDataViewModelNode(root, root->m_name, type, GetVolumeIcon(type, obj_errors), extruder_str, 0); + const auto node = new ObjectDataViewModelNode(root, root->m_name, type, GetVolumeIcon(type, root->m_warning_icon_name), extruder_str, 0, root->m_warning_icon_name); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // notify control @@ -380,12 +394,13 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent if (insert_position >= 0) insert_position++; } - const auto node = new ObjectDataViewModelNode(root, name, volume_type, GetVolumeIcon(volume_type, has_errors), extruder_str, root->m_volumes_cnt); + const auto node = new ObjectDataViewModelNode(root, name, volume_type, GetVolumeIcon(volume_type, warning_icon_name), extruder_str, root->m_volumes_cnt, warning_icon_name); 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); + if (!warning_icon_name.empty() && warning_icon_name != root->m_warning_icon_name && + (root->m_warning_icon_name.empty() || root->m_warning_icon_name == WarningManifoldIcon) ) + root->SetWarningBitmap(GetWarningBitmap(warning_icon_name), warning_icon_name); // notify control const wxDataViewItem child((void*)node); @@ -1665,6 +1680,7 @@ void ObjectDataViewModel::Rescale() { m_volume_bmps = MenuFactory::get_volume_bitmaps(); m_warning_bmp = create_scaled_bitmap(WarningIcon); + m_warning_manifold_bmp = create_scaled_bitmap(WarningManifoldIcon); wxDataViewItemArray all_items; GetAllChildren(wxDataViewItem(0), all_items); @@ -1680,10 +1696,10 @@ void ObjectDataViewModel::Rescale() switch (node->m_type) { case itObject: - if (node->m_bmp.IsOk()) node->m_bmp = m_warning_bmp; + if (node->m_bmp.IsOk()) node->m_bmp = GetWarningBitmap(node->m_warning_icon_name); break; case itVolume: - node->m_bmp = GetVolumeIcon(node->m_volume_type, node->m_bmp.GetWidth() != node->m_bmp.GetHeight()); + node->m_bmp = GetVolumeIcon(node->m_volume_type, node->m_warning_icon_name); break; case itLayerRoot: node->m_bmp = create_scaled_bitmap(LayerRootIcon); @@ -1697,19 +1713,19 @@ void ObjectDataViewModel::Rescale() } } -wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const bool is_marked/* = false*/) +wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const std::string& warning_icon_name/* = std::string()*/) { - if (!is_marked) + if (warning_icon_name.empty()) 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()); + std::string scaled_bitmap_name = warning_icon_name + std::to_string(static_cast(vol_type)); + scaled_bitmap_name += "-em" + std::to_string(wxGetApp().em_unit()) + (wxGetApp().dark_mode() ? "-dm" : "-lm"); wxBitmap *bmp = m_bitmap_cache->find(scaled_bitmap_name); if (bmp == nullptr) { std::vector bmps; - bmps.emplace_back(m_warning_bmp); + bmps.emplace_back(GetWarningBitmap(warning_icon_name)); bmps.emplace_back(m_volume_bmps[static_cast(vol_type)]); bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps); @@ -1718,20 +1734,20 @@ wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_ty return *bmp; } -void ObjectDataViewModel::AddWarningIcon(const wxDataViewItem& item) +void ObjectDataViewModel::AddWarningIcon(const wxDataViewItem& item, const std::string& warning_icon_name) { if (!item.IsOk()) return; ObjectDataViewModelNode *node = static_cast(item.GetID()); if (node->GetType() & itObject) { - node->SetBitmap(m_warning_bmp); + node->SetWarningBitmap(GetWarningBitmap(warning_icon_name), warning_icon_name); return; } if (node->GetType() & itVolume) { - node->SetBitmap(GetVolumeIcon(node->GetVolumeType(), true)); - node->GetParent()->SetBitmap(m_warning_bmp); + node->SetWarningBitmap(GetVolumeIcon(node->GetVolumeType(), warning_icon_name), warning_icon_name); + node->GetParent()->SetWarningBitmap(GetWarningBitmap(warning_icon_name), warning_icon_name); return; } } @@ -1747,11 +1763,11 @@ void ObjectDataViewModel::DeleteWarningIcon(const wxDataViewItem& item, const bo return; if (node->GetType() & itVolume) { - node->SetBitmap(m_volume_bmps[static_cast(node->volume_type())]); + node->SetWarningBitmap(m_volume_bmps[static_cast(node->volume_type())], ""); return; } - node->SetBitmap(wxNullBitmap); + node->SetWarningBitmap(wxNullBitmap, ""); if (unmark_object) { wxDataViewItemArray children; diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index f65f829f4..95e53babd 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -78,6 +78,7 @@ class ObjectDataViewModelNode wxBitmap m_action_icon; PrintIndicator m_printable {piUndef}; wxBitmap m_printable_icon; + std::string m_warning_icon_name{ "" }; std::string m_action_icon_name = ""; ModelVolumeType m_volume_type; @@ -100,7 +101,8 @@ public: Slic3r::ModelVolumeType type, const wxBitmap& bmp, const wxString& extruder, - const int idx = -1); + const int idx = -1, + const std::string& warning_icon_name = std::string()); ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const t_layer_height_range& layer_range, @@ -179,6 +181,7 @@ public: void SetVolumeType(ModelVolumeType type) { m_volume_type = type; } void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } void SetExtruder(const wxString &extruder) { m_extruder = extruder; } + void SetWarningBitmap(const wxBitmap& icon, const std::string& warning_icon_name) { m_bmp = icon; m_warning_icon_name = warning_icon_name; } const wxBitmap& GetBitmap() const { return m_bmp; } const wxString& GetName() const { return m_name; } ItemType GetType() const { return m_type; } @@ -225,6 +228,8 @@ public: void set_extruder_icon(); // Set printable icon for node void set_printable_icon(PrintIndicator printable); + // Set warning icon for node + void set_warning_icon(const std::string& warning_icon); void update_settings_digest_bitmaps(); bool update_settings_digest(const std::vector& categories); @@ -253,7 +258,9 @@ class ObjectDataViewModel :public wxDataViewModel std::vector m_objects; std::vector m_volume_bmps; std::map m_info_bmps; + wxBitmap m_empty_bmp; wxBitmap m_warning_bmp; + wxBitmap m_warning_manifold_bmp; wxDataViewCtrl* m_ctrl { nullptr }; @@ -263,11 +270,11 @@ public: wxDataViewItem Add( const wxString &name, const int extruder, - const bool has_errors = false); + const std::string& warning_icon_name = std::string()); wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item, const wxString &name, const Slic3r::ModelVolumeType volume_type, - const bool has_errors = false, + const std::string& warning_icon_name = std::string(), const int extruder = 0, const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); @@ -378,8 +385,8 @@ public: void Rescale(); wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, - const bool is_marked = false); - void AddWarningIcon(const wxDataViewItem& item); + 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); t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const; @@ -392,6 +399,8 @@ private: wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type); wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item); void AddAllChildren(const wxDataViewItem& parent); + + wxBitmap& GetWarningBitmap(const std::string& warning_icon_name); }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 89b30a47f..4ffa7dc13 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -125,6 +125,7 @@ wxDEFINE_EVENT(EVT_EXPORT_BEGAN, wxCommandEvent); class ObjectInfo : public wxStaticBoxSizer { + std::string m_warning_icon_name{ "exclamation" }; public: ObjectInfo(wxWindow *parent); @@ -142,6 +143,7 @@ public: bool showing_manifold_warning_icon; void show_sizer(bool show); void msw_rescale(); + void update_warning_icon(const std::string& warning_icon_name); }; ObjectInfo::ObjectInfo(wxWindow *parent) : @@ -175,7 +177,7 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : info_manifold_text->SetFont(wxGetApp().small_font()); info_manifold = new wxStaticText(parent, wxID_ANY, ""); info_manifold->SetFont(wxGetApp().small_font()); - manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, create_scaled_bitmap("exclamation")); + manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, create_scaled_bitmap(m_warning_icon_name)); auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL); sizer_manifold->Add(info_manifold_text, 0); sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2); @@ -194,7 +196,15 @@ void ObjectInfo::show_sizer(bool show) void ObjectInfo::msw_rescale() { - manifold_warning_icon->SetBitmap(create_scaled_bitmap("exclamation")); + manifold_warning_icon->SetBitmap(create_scaled_bitmap(m_warning_icon_name)); +} + +void ObjectInfo::update_warning_icon(const std::string& warning_icon_name) +{ + if (warning_icon_name.empty()) + return; + m_warning_icon_name = warning_icon_name; + manifold_warning_icon->SetBitmap(create_scaled_bitmap(m_warning_icon_name)); } enum SlicedInfoIdx @@ -1129,30 +1139,19 @@ void Sidebar::show_info_sizer() p->object_info->info_size->SetLabel(wxString::Format("%.2f x %.2f x %.2f",size(0)*koef, size(1)*koef, size(2)*koef)); p->object_info->info_materials->SetLabel(wxString::Format("%d", static_cast(model_object->materials_count()))); - const auto& stats = model_object->get_object_stl_stats();//model_object->volumes.front()->mesh.stl.stats; + const auto& stats = model_object->get_object_stl_stats(); p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume*pow(koef,3))); p->object_info->info_facets->SetLabel(format_wxstr(_L_PLURAL("%1% (%2$d shell)", "%1% (%2$d shells)", stats.number_of_parts), static_cast(model_object->facets_count()), stats.number_of_parts)); - int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_reversed + stats.backwards_edges; - if (errors > 0) { - wxString tooltip = format_wxstr(_L_PLURAL("Auto-repaired %1$d error", "Auto-repaired %1$d errors", errors), errors); - p->object_info->info_manifold->SetLabel(tooltip); + if (stats.repaired()) { + int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + stats.facets_reversed + stats.backwards_edges; + p->object_info->info_manifold->SetLabel(format_wxstr(_L_PLURAL("Auto-repaired %1$d error", "Auto-repaired %1$d errors", errors), errors)); - tooltip += ":\n"; - if (stats.degenerate_facets > 0) - tooltip += format_wxstr(_L_PLURAL("%1$d degenerate facet", "%1$d degenerate facets", stats.degenerate_facets), stats.degenerate_facets) + ", "; - if (stats.edges_fixed > 0) - tooltip += format_wxstr(_L_PLURAL("%1$d edge fixed", "%1$d edges fixed", stats.edges_fixed), stats.edges_fixed) + ", "; - if (stats.facets_removed > 0) - tooltip += format_wxstr(_L_PLURAL("%1$d facet removed", "%1$d facets removed", stats.facets_removed), stats.facets_removed) + ", "; - if (stats.facets_reversed > 0) - tooltip += format_wxstr(_L_PLURAL("%1$d facet reversed", "%1$d facets reversed", stats.facets_reversed), stats.facets_reversed) + ", "; - if (stats.backwards_edges > 0) - tooltip += format_wxstr(_L_PLURAL("%1$d backwards edge", "%1$d backwards edges", stats.backwards_edges), stats.backwards_edges) + ", "; - tooltip.RemoveLast(2);//remove last coma + auto mesh_errors = obj_list()->get_mesh_errors(true); + wxString tooltip = mesh_errors.first; + p->object_info->update_warning_icon(mesh_errors.second); p->object_info->showing_manifold_warning_icon = true; p->object_info->info_manifold->SetToolTip(tooltip); p->object_info->manifold_warning_icon->SetToolTip(tooltip); From 30d13c99b7c30cc5cde966bbdf7a869fad3b593e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 21 Sep 2021 22:41:55 +0200 Subject: [PATCH 04/57] Added a missing include (GCC 11.1). --- src/libslic3r/GCodeReader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index 657f47f0e..7b106463a 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include From 96b88f5b29f14d23f022d627b62e7c64883dcef8 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 22 Sep 2021 10:50:04 +0200 Subject: [PATCH 05/57] Fixed crash with zero support base spacing. Zero support base spacing is newly allowed, switching from the "support base" infill pattern to rectilinar infill pattern. Why someone would want to use a solid infill for support base eludes me, but it is simpler to support it instead of working out some rules on minimum support base density. Fixes Support patern spacing set to zero causing crash #6989 --- src/libslic3r/SupportMaterial.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index f727d334d..2bcf99c57 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -721,9 +721,9 @@ public: #ifdef SUPPORT_USE_AGG_RASTERIZER m_bbox = bbox; // Oversample the grid to avoid leaking of supports through or around the object walls. - int oversampling = std::min(8, int(scale_(m_support_spacing) / (scale_(params.extrusion_width) + 100))); - m_pixel_size = scale_(m_support_spacing / oversampling); - assert(scale_(params.extrusion_width) + 20 < m_pixel_size); + int extrusion_width_scaled = scale_(params.extrusion_width); + int oversampling = std::clamp(int(scale_(m_support_spacing) / (extrusion_width_scaled + 100)), 1, 8); + m_pixel_size = std::max(extrusion_width_scaled + 21, scale_(m_support_spacing / oversampling)); // Add one empty column / row boundaries. m_bbox.offset(m_pixel_size); // Grid size fitting the support polygons plus one pixel boundary around the polygons. @@ -2600,8 +2600,6 @@ void PrintObjectSupportMaterial::generate_base_layers( // No top contacts -> no intermediate layers will be produced. return; - // coordf_t fillet_radius_scaled = scale_(m_object_config->support_material_spacing); - BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_base_layers() in parallel - start"; tbb::parallel_for( tbb::blocked_range(0, intermediate_layers.size()), @@ -2696,6 +2694,7 @@ void PrintObjectSupportMaterial::generate_base_layers( layer_intermediate.layer_type = sltBase; #if 0 + // coordf_t fillet_radius_scaled = scale_(m_object_config->support_material_spacing); // Fillet the base polygons and trim them again with the top, interface and contact layers. $base->{$i} = diff( offset2( @@ -3784,7 +3783,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // Prepare fillers. SupportMaterialPattern support_pattern = m_object_config->support_material_pattern; bool with_sheath = m_object_config->support_material_with_sheath; - InfillPattern infill_pattern = (support_pattern == smpHoneycomb ? ipHoneycomb : ipSupportBase); + InfillPattern infill_pattern = support_pattern == smpHoneycomb ? ipHoneycomb : (support_density < 1.05 ? ipRectilinear : ipSupportBase); std::vector angles; angles.push_back(base_angle); From a6261ff4741dedbb992adb828ca6127767914d9a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 21 Sep 2021 09:31:15 +0200 Subject: [PATCH 06/57] Fix of #6898 (finishing slicing interfered with dragging gizmos) --- src/slic3r/GUI/Plater.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4ffa7dc13..e76ff2449 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3918,20 +3918,16 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) void Plater::priv::on_slicing_completed(wxCommandEvent & evt) { - switch (this->printer_technology) { - case ptFFF: - this->update_fff_scene(); - break; - case ptSLA: - if (view3D->is_dragging()) - delayed_scene_refresh = true; + if (view3D->is_dragging()) // updating scene now would interfere with the gizmo dragging + delayed_scene_refresh = true; + else { + if (this->printer_technology == ptFFF) + this->update_fff_scene(); else this->update_sla_scene(); - break; - default: break; } - } + void Plater::priv::on_export_began(wxCommandEvent& evt) { if (show_warning_dialog) @@ -4050,17 +4046,13 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) this->object_list_changed(); // refresh preview - switch (this->printer_technology) { - case ptFFF: - this->update_fff_scene(); - break; - case ptSLA: - if (view3D->is_dragging()) - delayed_scene_refresh = true; + if (view3D->is_dragging()) // updating scene now would interfere with the gizmo dragging + delayed_scene_refresh = true; + else { + if (this->printer_technology == ptFFF) + this->update_fff_scene(); else this->update_sla_scene(); - break; - default: break; } if (evt.cancelled()) { From 67e519d3ab8f56d9ab5d6759d1b92ee9131ead8c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Sep 2021 11:38:08 +0200 Subject: [PATCH 07/57] #6983 - Fixed preview when switching to it after automatic background processing is completed --- src/slic3r/GUI/Plater.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4ffa7dc13..dff4f197e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3750,10 +3750,10 @@ void Plater::priv::set_current_panel(wxPanel* panel) if (view3D->is_reload_delayed()) { // Delayed loading of the 3D scene. - if (this->printer_technology == ptSLA) { + if (printer_technology == ptSLA) { // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. - this->update_restart_background_process(true, false); + update_restart_background_process(true, false); } else view3D->reload_scene(true); } @@ -3776,8 +3776,14 @@ void Plater::priv::set_current_panel(wxPanel* panel) // FIXME: it may be better to have a single function making this check and let it be called wherever needed bool export_in_progress = this->background_process.is_export_scheduled(); bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside; - if (!model.objects.empty() && !export_in_progress && model_fits) - this->q->reslice(); + if (!model.objects.empty() && !export_in_progress && model_fits) { +#if ENABLE_SEAMS_USING_MODELS + // the following call is needed to ensure that GCodeViewer buffers are initialized + // before calling reslice() when background processing is active + preview->SetFocusFromKbd(); +#endif // ENABLE_SEAMS_USING_MODELS + q->reslice(); + } // keeps current gcode preview, if any preview->reload_print(true); From d57d3f99d0874c09700e1a4b780caa14fe788d6e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 22 Sep 2021 11:39:47 +0200 Subject: [PATCH 08/57] Fix of #3969 (crash if $USER is not set) --- src/slic3r/GUI/RemovableDriveManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index 593d8241d..5fb8b0132 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -201,9 +201,7 @@ namespace search_for_drives_internal struct stat buf; stat(path.c_str(), &buf); uid_t uid = buf.st_uid; - std::string username(std::getenv("USER")); - struct passwd *pw = getpwuid(uid); - if (pw != 0 && pw->pw_name == username) + if (getuid() == uid) out.emplace_back(DriveData{ boost::filesystem::basename(boost::filesystem::path(path)), path }); } } @@ -245,7 +243,7 @@ std::vector RemovableDriveManager::search_for_removable_drives() cons search_for_drives_internal::search_path("/media/*", "/media", current_drives); //search_path("/Volumes/*", "/Volumes"); - std::string path(std::getenv("USER")); + std::string path = wxGetUserId().ToUTF8().data(); std::string pp(path); //search /media/USERNAME/* folder From 846b868215e1a35778c52ce8836346da977d592d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 22 Sep 2021 12:39:19 +0200 Subject: [PATCH 09/57] Follow up ff82c82f - Fixed ModeButtons refreshing --- src/slic3r/GUI/wxExtensions.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index a3d6384e0..5e703a37b 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -672,10 +672,9 @@ void ModeButton::focus_button(const bool focus) Slic3r::GUI::wxGetApp().normal_font(); SetFont(new_font); -//#ifdef _WIN32 -// GetParent()->Refresh(); -//#else -#ifndef _WIN32 +#ifdef _WIN32 + GetParent()->Refresh(); // force redraw a background of the selected mode button +#else SetForegroundColour(wxSystemSettings::GetColour(focus ? wxSYS_COLOUR_BTNTEXT : #if defined (__linux__) && defined (__WXGTK3__) wxSYS_COLOUR_GRAYTEXT From 8f064dd15511710641d08d0f3303494e90f0b352 Mon Sep 17 00:00:00 2001 From: Oleksandra Yushchenko Date: Wed, 22 Sep 2021 12:44:13 +0200 Subject: [PATCH 10/57] Check unsaved changes (#6991) * Check Unsaved changes (partially related to #5903) + Allow create new project when Plater is empty, but some of presets are modified (related to #5903) + When creating new project allow Keep or Discard modification from previous project + Added check of changes: * before any load project (including DnD and "Load From Recent Projects") * before preset updater * when configuration is changing from the ConfigWizard + Dialog caption is added for each check + Create/Destroy ConfigWizard every time when it's called * Check Unsaved changes: Next Improvements + For dialog "Save project changes" added a reason of saving and name of the current project (or "Untitled") + UnsavedChangesDialog: Headers are extended to better explain the reason + Preferences: Fixed tooltiops for "Always ask for unsaved changes when..." + Suppress "Remember my choice" checkbox for actions which are not frequently used * Fixed behavior of the application when try to save changed project but "Cancel" button is selected in "Save file as..." dialog * Check unsaved changes: Improvements for Config Wizard - Check all cases when presets should be updated + Fixed info line for Materials pages. Text of the info relates to the printer technology now * Improved suggested name for a project when Application is closing * Fixed Linux/OSX build warnings --- src/libslic3r/AppConfig.cpp | 3 + src/slic3r/GUI/ConfigWizard.cpp | 84 ++++++++++-- src/slic3r/GUI/ConfigWizard_private.hpp | 2 +- src/slic3r/GUI/ExtraRenderers.cpp | 18 ++- src/slic3r/GUI/GUI_App.cpp | 174 ++++++++++++++++++------ src/slic3r/GUI/GUI_App.hpp | 7 +- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 26 ++-- src/slic3r/GUI/MainFrame.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 84 ++++++++---- src/slic3r/GUI/Plater.hpp | 2 +- src/slic3r/GUI/Preferences.cpp | 17 ++- src/slic3r/GUI/Tab.cpp | 20 ++- src/slic3r/GUI/Tab.hpp | 2 +- src/slic3r/GUI/UnsavedChangesDialog.cpp | 151 ++++++++++++-------- src/slic3r/GUI/UnsavedChangesDialog.hpp | 24 +++- src/slic3r/Utils/PresetUpdater.cpp | 22 +-- 17 files changed, 462 insertions(+), 178 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 177d8d708..f3a1d5988 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -139,6 +139,9 @@ void AppConfig::set_defaults() if (get("default_action_on_select_preset").empty()) set("default_action_on_select_preset", "none"); // , "transfer", "discard" or "save" + if (get("default_action_on_new_project").empty()) + set("default_action_on_new_project", "none"); // , "keep(transfer)", "discard" or "save" + if (get("color_mapinulation_panel").empty()) set("color_mapinulation_panel", "0"); diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 3f388f485..ee6e3d5ab 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -41,6 +41,7 @@ #include "format.hpp" #include "MsgDialog.hpp" #include "libslic3r/libslic3r.h" +#include "UnsavedChangesDialog.hpp" #if defined(__linux__) && defined(__WXGTK3__) #define wxLinux_gtk3 true @@ -741,10 +742,10 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector* are not compatible with some installed printers."); + wxString first_line = format_wxstr(_L("%1% marked with * are not compatible with some installed printers."), materials->technology == T_FFF ? _L("Filaments") : _L("SLA materials")); wxString text; if (all_printers) { - wxString second_line = _L("All installed printers are compatible with the selected filament."); + wxString second_line = format_wxstr(_L("All installed printers are compatible with the selected %1%."), materials->technology == T_FFF ? _L("filament") : _L("SLA material")); text = wxString::Format( "" "