From 88bd1890476133f8930b5dd07880da0c480d5282 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 24 Feb 2021 15:50:18 +0100 Subject: [PATCH 1/8] Some code refactoring follow-up https://github.com/prusa3d/PrusaSlicer/commit/33aa6be7b7f3d8b81d6b948f9bd6841db10b61cf and https://github.com/prusa3d/PrusaSlicer/commit/92b1302a082b76de6693799ccdb7922617f21c50 --- src/slic3r/GUI/DoubleSlider.cpp | 24 +--------- src/slic3r/GUI/MainFrame.cpp | 14 ++---- src/slic3r/GUI/Tab.cpp | 82 ++++++++++++--------------------- src/slic3r/GUI/Tab.hpp | 13 ++---- 4 files changed, 39 insertions(+), 94 deletions(-) diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 7d135e0aa3..c12d361120 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -10,6 +10,7 @@ #include "libslic3r/AppConfig.hpp" #include "GUI_Utils.hpp" #include "MsgDialog.hpp" +#include "Tab.hpp" #include #include @@ -2033,27 +2034,6 @@ static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg, double min = -1.0, }, btn_OK->GetId()); } -#if ENABLE_VALIDATE_CUSTOM_GCODE -static bool validate_custom_gcode(const std::string& gcode, const wxString& title) -{ - std::vector tags; - bool invalid = GCodeProcessor::contains_reserved_tags(gcode, 5, tags); - if (invalid) { - wxString reports = _L_PLURAL("The following line", "The following lines", tags.size()); - reports += ":\n"; - for (const std::string& keyword : tags) { - reports += ";" + keyword + "\n"; - } - reports += _L("contain reserved keywords.") + "\n"; - reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation."); - - wxMessageDialog dialog(nullptr, reports, _L("Found reserved keywords in") + " " + title, wxICON_WARNING | wxOK); - dialog.ShowModal(); - } - return !invalid; -} -#endif // ENABLE_VALIDATE_CUSTOM_GCODE - static std::string get_custom_code(const std::string& code_in, double height) { wxString msg_text = _L("Enter custom G-code used on current layer") + ":"; @@ -2072,7 +2052,7 @@ static std::string get_custom_code(const std::string& code_in, double height) return ""; value = dlg.GetValue().ToStdString(); - valid = validate_custom_gcode(value, _L("Custom G-code")); + valid = GUI::Tab::validate_custom_gcode("Custom G-code", value); } while (!valid); return value; #else diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c6d85067e1..386a150f70 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -548,18 +548,10 @@ void MainFrame::init_tabpanel() m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, [this](wxBookCtrlEvent& evt) { wxWindow* panel = m_tabpanel->GetCurrentPage(); if (panel != nullptr) { - TabPrinter* printer_tab = dynamic_cast(panel); - if (printer_tab != nullptr) { - if (!printer_tab->validate_custom_gcodes()) + Tab* tab = dynamic_cast(panel); + if (tab && (tab->type() == Preset::TYPE_FILAMENT || tab->type() == Preset::TYPE_PRINTER)) + if (!tab->validate_custom_gcodes()) evt.Veto(); - return; - } - TabFilament* filament_tab = dynamic_cast(panel); - if (filament_tab != nullptr) { - if (!filament_tab->validate_custom_gcodes()) - evt.Veto(); - return; - } } }); #endif // ENABLE_VALIDATE_CUSTOM_GCODE diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9e8d08d072..fa1f31ab5d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1712,11 +1712,11 @@ void TabPrint::clear_pages() } #if ENABLE_VALIDATE_CUSTOM_GCODE -static bool validate_custom_gcode(wxWindow* parent, const wxString& title, const std::string& gcode) +bool Tab::validate_custom_gcode(const wxString& title, const std::string& gcode) { std::vector tags; bool invalid = GCodeProcessor::contains_reserved_tags(gcode, 5, tags); - if (parent != nullptr && invalid) { + if (invalid) { wxString reports = _L_PLURAL("The following line", "The following lines", tags.size()); reports += ":\n"; for (const std::string& keyword : tags) { @@ -1725,11 +1725,17 @@ static bool validate_custom_gcode(wxWindow* parent, const wxString& title, const reports += _L("contain reserved keywords.") + "\n"; reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation."); - wxMessageDialog dialog(parent, reports, _L("Found reserved keywords in") + " " + title, wxICON_WARNING | wxOK); + wxMessageDialog dialog(wxGetApp().mainframe, reports, _L("Found reserved keywords in") + " " + _(title), wxICON_WARNING | wxOK); dialog.ShowModal(); } return !invalid; } + +static void validate_custom_gcode_cb(Tab* tab, ConfigOptionsGroupShp opt_group, const boost::any& value) { + Tab::validate_custom_gcode(opt_group->title, boost::any_cast(value)); + tab->update_dirty(); + tab->update(); +} #endif // ENABLE_VALIDATE_CUSTOM_GCODE void TabFilament::add_filament_overrides_page() @@ -1957,7 +1963,7 @@ void TabFilament::build() optgroup = page->new_optgroup(L("Start G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Start G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, value); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("start_filament_gcode"); @@ -1969,7 +1975,7 @@ void TabFilament::build() optgroup = page->new_optgroup(L("End G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("End G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, value); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("end_filament_gcode"); @@ -2086,25 +2092,6 @@ void TabFilament::clear_pages() m_cooling_description_line = nullptr; } -#if ENABLE_VALIDATE_CUSTOM_GCODE -bool TabFilament::validate_custom_gcodes() const -{ - auto check_optgroup = [this](const wxString& title, const Slic3r::t_config_option_key& key) { - const ConfigOptionsGroupShp opt_group = m_active_page->get_optgroup(title); - return (opt_group != nullptr) ? - validate_custom_gcode((wxWindow*)this, title, boost::any_cast(opt_group->get_value(key))) : - true; - }; - - bool valid = true; - if (m_active_page->title() == L("Custom G-code")) { - valid &= check_optgroup(L("Start G-code"), "start_filament_gcode"); - valid &= check_optgroup(L("End G-code"), "end_filament_gcode"); - } - return valid; -} -#endif // ENABLE_VALIDATE_CUSTOM_GCODE - wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText, wxString text /*= wxEmptyString*/) { *StaticText = new ogStaticText(parent, text); @@ -2295,7 +2282,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Start G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Start G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("start_gcode"); @@ -2307,7 +2294,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("End G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("End G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("end_gcode"); @@ -2319,7 +2306,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Before layer change G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Before layer change G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("before_layer_gcode"); @@ -2331,7 +2318,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("After layer change G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("After layer change G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("layer_gcode"); @@ -2343,7 +2330,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Tool change G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Tool change G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("toolchange_gcode"); @@ -2355,7 +2342,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Between objects G-code (for sequential printing)"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("between_objects_gcode"); @@ -2367,7 +2354,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Color Change G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Color Change G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("color_change_gcode"); @@ -2378,7 +2365,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Pause Print G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Pause Print G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("pause_print_gcode"); @@ -2389,7 +2376,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(L("Template Custom G-code"), 0); #if ENABLE_VALIDATE_CUSTOM_GCODE optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { - validate_custom_gcode(this, L("Template Custom G-code"), boost::any_cast(value)); + validate_custom_gcode_cb(this, optgroup, boost::any_cast(value)); }; #endif // ENABLE_VALIDATE_CUSTOM_GCODE option = optgroup->get_option("template_custom_gcode"); @@ -3842,28 +3829,17 @@ void TabPrinter::apply_extruder_cnt_from_cache() } #if ENABLE_VALIDATE_CUSTOM_GCODE -bool TabPrinter::validate_custom_gcodes() const +bool Tab::validate_custom_gcodes() { - auto check_optgroup = [this](const wxString& title, const Slic3r::t_config_option_key& key) { - const ConfigOptionsGroupShp opt_group = m_active_page->get_optgroup(title); - return (opt_group != nullptr) ? - validate_custom_gcode((wxWindow*)this, title, boost::any_cast(opt_group->get_value(key))) : - true; - }; - bool valid = true; - if (m_printer_technology == ptFFF) { - if (m_active_page->title() == L("Custom G-code")) { - valid &= check_optgroup(L("Start G-code"), "start_gcode"); - valid &= check_optgroup(L("End G-code"), "end_gcode"); - valid &= check_optgroup(L("Before layer change G-code"), "before_layer_gcode"); - valid &= check_optgroup(L("After layer change G-code"), "layer_gcode"); - valid &= check_optgroup(L("Tool change G-code"), "toolchange_gcode"); - valid &= check_optgroup(L("Between objects G-code (for sequential printing)"), "between_objects_gcode"); - valid &= check_optgroup(L("Color Change G-code"), "color_change_gcode"); - valid &= check_optgroup(L("Pause Print G-code"), "pause_print_gcode"); - valid &= check_optgroup(L("Template Custom G-code"), "template_custom_gcode"); - } + if ((m_type == Preset::TYPE_FILAMENT || + m_type == Preset::TYPE_PRINTER && static_cast(this)->m_printer_technology == ptFFF) && + m_active_page->title() == "Custom G-code") { + for (auto opt_group : m_active_page->m_optgroups) { + assert(opt_group->opt_map().size() == 1); + std::string key = opt_group->opt_map().begin()->first; + valid &= validate_custom_gcode(opt_group->title, boost::any_cast(opt_group->get_value(key))); + } } return valid; } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index add2b3aa5e..fcbe27eb7f 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -348,6 +348,11 @@ public: const std::map& get_category_icon_map() { return m_category_icon; } +#if ENABLE_VALIDATE_CUSTOM_GCODE + static bool validate_custom_gcode(const wxString& title, const std::string& gcode); + bool validate_custom_gcodes(); +#endif // ENABLE_VALIDATE_CUSTOM_GCODE + protected: void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const wxString& path, widget_t widget); wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps); @@ -412,10 +417,6 @@ public: void update() override; void clear_pages() override; bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptFFF; } - -#if ENABLE_VALIDATE_CUSTOM_GCODE - bool validate_custom_gcodes() const; -#endif // ENABLE_VALIDATE_CUSTOM_GCODE }; class TabPrinter : public Tab @@ -474,10 +475,6 @@ public: wxSizer* create_bed_shape_widget(wxWindow* parent); void cache_extruder_cnt(); void apply_extruder_cnt_from_cache(); - -#if ENABLE_VALIDATE_CUSTOM_GCODE - bool validate_custom_gcodes() const; -#endif // ENABLE_VALIDATE_CUSTOM_GCODE }; class TabSLAMaterial : public Tab From 61a5b43ac3812e18006560363848554ce0f56151 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 15:59:09 +0100 Subject: [PATCH 2/8] Fix of Add option to change support interface pattern #1197 New config field for switching the support interface pattern between default (rectilinear for non-soluble interface, concentric for soluble interface), explicit rectilinear and explicit concentric. Also the config layer was reworked a bit to reduce some switch statements on ConfigOptionEnum<> templates. --- src/libslic3r/Config.hpp | 1 + src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 16 ++++++++++ src/libslic3r/PrintConfig.hpp | 16 ++++++++++ src/libslic3r/PrintObject.cpp | 1 + src/libslic3r/SupportMaterial.cpp | 9 ++++-- src/slic3r/GUI/ConfigManipulation.cpp | 3 +- src/slic3r/GUI/Field.cpp | 2 ++ src/slic3r/GUI/GUI.cpp | 11 ++++++- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/OptionsGroup.cpp | 42 ++----------------------- src/slic3r/GUI/Tab.cpp | 1 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 30 ++++-------------- 13 files changed, 66 insertions(+), 70 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 218e8cd0cf..9c9b5d3486 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1313,6 +1313,7 @@ public: ConfigOptionEnum& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionEnum &rhs) const { return this->value == rhs.value; } int getInt() const override { return (int)this->value; } + void setInt(int val) override { this->value = T(val); } bool operator==(const ConfigOption &rhs) const override { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 6a656e6d8f..6c500b84a6 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -429,7 +429,7 @@ const std::vector& Preset::print_options() "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", - "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", + "support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", "support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius", "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b272dbfba3..480ce45901 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2341,6 +2341,22 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(smpRectilinear)); + def = this->add("support_material_interface_pattern", coEnum); + def->label = L("Interface pattern"); + def->category = L("Support material"); + def->tooltip = L("Pattern used to generate support material interface. " + "Default pattern for non-soluble support interface is Rectilinear, " + "while default pattern for soluble support interface is Concentric."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("auto"); + def->enum_values.push_back("rectilinear"); + def->enum_values.push_back("concentric"); + def->enum_labels.push_back(L("Default")); + def->enum_labels.push_back(L("Rectilinear")); + def->enum_labels.push_back(L("Concentric")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(smpRectilinear)); + def = this->add("support_material_spacing", coFloat); def->label = L("Pattern spacing"); def->category = L("Support material"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index aa63e723a6..f563163564 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -65,6 +65,10 @@ enum SupportMaterialPattern { smpRectilinear, smpRectilinearGrid, smpHoneycomb, }; +enum SupportMaterialInterfacePattern { + smipAuto, smipRectilinear, smipConcentric, +}; + enum SeamPosition { spRandom, spNearest, spAligned, spRear }; @@ -207,6 +211,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["auto"] = smipAuto; + keys_map["rectilinear"] = smipRectilinear; + keys_map["concentric"] = smipConcentric; + } + return keys_map; +} + template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -499,6 +513,7 @@ public: ConfigOptionFloat support_material_interface_spacing; ConfigOptionFloatOrPercent support_material_interface_speed; ConfigOptionEnum support_material_pattern; + ConfigOptionEnum support_material_interface_pattern; // Spacing between support material lines (the hatching distance). ConfigOptionFloat support_material_spacing; ConfigOptionFloat support_material_speed; @@ -547,6 +562,7 @@ protected: OPT_PTR(support_material_interface_spacing); OPT_PTR(support_material_interface_speed); OPT_PTR(support_material_pattern); + OPT_PTR(support_material_interface_pattern); OPT_PTR(support_material_spacing); OPT_PTR(support_material_speed); OPT_PTR(support_material_synchronize_layers); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 53403024e4..84fdf3f629 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -568,6 +568,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_extruder" || opt_key == "support_material_extrusion_width" || opt_key == "support_material_interface_layers" + || opt_key == "support_material_interface_pattern" || opt_key == "support_material_interface_contact_loops" || opt_key == "support_material_interface_extruder" || opt_key == "support_material_interface_spacing" diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index ddd68238e0..cfc629e952 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -3573,9 +3573,15 @@ void PrintObjectSupportMaterial::generate_toolpaths( }; std::vector layer_caches(support_layers.size(), LayerCache()); + + const auto fill_type_interface = + (m_object_config->support_material_interface_pattern == smipAuto && m_slicing_params.soluble_interface) || + m_object_config->support_material_interface_pattern == smipConcentric ? + ipConcentric : ipRectilinear; + tbb::parallel_for(tbb::blocked_range(n_raft_layers, support_layers.size()), [this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, - infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath] + infill_pattern, &bbox_object, support_density, fill_type_interface, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath] (const tbb::blocked_range& range) { // Indices of the 1st layer in their respective container at the support layer height. size_t idx_layer_bottom_contact = size_t(-1); @@ -3583,7 +3589,6 @@ void PrintObjectSupportMaterial::generate_toolpaths( size_t idx_layer_intermediate = size_t(-1); size_t idx_layer_interface = size_t(-1); size_t idx_layer_base_interface = size_t(-1); - const auto fill_type_interface = m_slicing_params.soluble_interface ? ipConcentric : ipRectilinear; const auto fill_type_first_layer = ipRectilinear; auto filler_interface = std::unique_ptr(Fill::new_from_type(fill_type_interface)); // Filler for the 1st layer interface, if different from filler_interface. diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 309dc57288..b7cff7c7fc 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -279,7 +279,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_support_interface = config->opt_int("support_material_interface_layers") > 0; bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0; for (auto el : { "support_material_pattern", "support_material_with_sheath", - "support_material_spacing", "support_material_angle", "support_material_interface_layers", + "support_material_spacing", "support_material_angle", + "support_material_interface_pattern", "support_material_interface_layers", "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", "support_material_xy_spacing" }) toggle_field(el, have_support_material); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 02847c40de..7303f4d72d 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1210,6 +1210,8 @@ boost::any& Choice::get_value() m_value = static_cast(ret_enum); else if (m_opt_id.compare("support_material_pattern") == 0) m_value = static_cast(ret_enum); + else if (m_opt_id.compare("support_material_interface_pattern") == 0) + m_value = static_cast(ret_enum); else if (m_opt_id.compare("seam_position") == 0) m_value = static_cast(ret_enum); else if (m_opt_id.compare("host_type") == 0) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index dc81fde216..61ec4d2331 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -104,7 +104,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt return; } - switch (config.def()->get(opt_key)->type) { + const ConfigOptionDef *opt_def = config.def()->get(opt_key); + switch (opt_def->type) { case coFloatOrPercent:{ std::string str = boost::any_cast(value); bool percent = false; @@ -176,6 +177,11 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt } break; case coEnum:{ +#if 0 + auto *opt = opt_def->default_value.get()->clone(); + opt->setInt(0); + config.set_key_value(opt_key, opt); +#else if (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern") @@ -190,6 +196,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("support_material_pattern") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("support_material_interface_pattern") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("seam_position") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("host_type") == 0) @@ -203,6 +211,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt else if(opt_key == "brim_type") config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); } +#endif break; case coPoints:{ if (opt_key == "bed_shape" || opt_key == "thumbnails") { diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5e4dd87890..5247558c77 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -35,7 +35,7 @@ static SettingsBundle FREQ_SETTINGS_BUNDLE_FFF = { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } }, { L("Infill") , { "fill_density", "fill_pattern" } }, { L("Support material") , { "support_material", "support_material_auto", "support_material_threshold", - "support_material_pattern", "support_material_buildplate_only", + "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", "support_material_spacing" } }, { L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } } }; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 7509d40608..b87e2047d4 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -860,46 +860,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config case coInts: ret = config.opt_int(opt_key, idx); break; - case coEnum:{ - if (opt_key == "top_fill_pattern" || - opt_key == "bottom_fill_pattern" || - opt_key == "fill_pattern" ) { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "ironing_type") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "fuzzy_skin") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "gcode_flavor") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "machine_limits_usage") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "support_material_pattern") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "seam_position") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "host_type") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "display_orientation") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "support_pillar_connection_mode") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "printhost_authorization_type") { - ret = static_cast(config.option>(opt_key)->value); - } - else if (opt_key == "brim_type") { - ret = static_cast(config.option>(opt_key)->value); - } - } + case coEnum: + ret = config.option(opt_key)->getInt(); break; case coPoints: if (opt_key == "bed_shape") diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fa1f31ab5d..374789815c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1511,6 +1511,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf"); optgroup->append_single_option_line("support_material_angle", category_path + "pattern-angle"); optgroup->append_single_option_line("support_material_interface_layers", category_path + "interface-layers"); + optgroup->append_single_option_line("support_material_interface_pattern", category_path + "interface-pattern"); optgroup->append_single_option_line("support_material_interface_spacing", category_path + "interface-pattern-spacing"); optgroup->append_single_option_line("support_material_interface_contact_loops", category_path + "interface-loops"); optgroup->append_single_option_line("support_material_buildplate_only", category_path + "support-on-build-plate-only"); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 07a6fc7390..473f7e6e17 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -986,18 +986,17 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets) return true; } -template wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConfig& config, bool is_infill = false) { const ConfigOptionDef& def = config.def()->options.at(opt_key); const std::vector& names = def.enum_labels;//ConfigOptionEnum::get_enum_names(); - T val = config.option>(opt_key)->value; + int val = config.option(opt_key)->getInt(); // Each infill doesn't use all list of infill declared in PrintConfig.hpp. // So we should "convert" val to the correct one if (is_infill) { for (auto key_val : *def.enum_keys_map) - if ((int)key_val.second == (int)val) { + if (int(key_val.second) == val) { auto it = std::find(def.enum_values.begin(), def.enum_values.end(), key_val.first); if (it == def.enum_values.end()) return ""; @@ -1005,7 +1004,7 @@ wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConf } return _L("Undef"); } - return from_u8(_utf8(names[static_cast(val)])); + return from_u8(_utf8(names[val])); } static size_t get_id_from_opt_key(std::string opt_key) @@ -1128,27 +1127,10 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& return out; } case coEnum: { - if (opt_key == "top_fill_pattern" || + return get_string_from_enum(opt_key, config, + opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || - opt_key == "fill_pattern") - return get_string_from_enum(opt_key, config, true); - if (opt_key == "gcode_flavor") - return get_string_from_enum(opt_key, config); - if (opt_key == "machine_limits_usage") - return get_string_from_enum(opt_key, config); - if (opt_key == "ironing_type") - return get_string_from_enum(opt_key, config); - if (opt_key == "support_material_pattern") - return get_string_from_enum(opt_key, config); - if (opt_key == "seam_position") - return get_string_from_enum(opt_key, config); - if (opt_key == "display_orientation") - return get_string_from_enum(opt_key, config); - if (opt_key == "support_pillar_connection_mode") - return get_string_from_enum(opt_key, config); - if (opt_key == "brim_type") - return get_string_from_enum(opt_key, config); - break; + opt_key == "fill_pattern"); } case coPoints: { if (opt_key == "bed_shape") { From 6bdd42b1cfd34fe4171d24c5c59260d1aa9b12bf Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 17:34:51 +0100 Subject: [PATCH 3/8] Fix of Support interface is generated across whole print layer regardless if it's needed or not #4570 Disabled a suspicious piece of legacy code inherited from Slic3r, which tries to fill in spots inside support interfaces. The code was too aggressive and it was doing more harm than good. --- src/libslic3r/SupportMaterial.cpp | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index cfc629e952..b77d81219d 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -572,6 +572,33 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths"; +#if 0 // #ifdef SLIC3R_DEBUG + { + size_t layer_id = 0; + for (int i = 0; i < int(layers_sorted.size());) { + // Find the last layer with roughly the same print_z, find the minimum layer height of all. + // Due to the floating point inaccuracies, the print_z may not be the same even if in theory they should. + int j = i + 1; + coordf_t zmax = layers_sorted[i]->print_z + EPSILON; + bool empty = true; + for (; j < layers_sorted.size() && layers_sorted[j]->print_z <= zmax; ++j) + if (!layers_sorted[j]->polygons.empty()) + empty = false; + if (!empty) { + export_print_z_polygons_to_svg( + debug_out_path("support-%d-%lf-before.svg", iRun, layers_sorted[i]->print_z).c_str(), + layers_sorted.data() + i, j - i); + export_print_z_polygons_and_extrusions_to_svg( + debug_out_path("support-w-fills-%d-%lf-before.svg", iRun, layers_sorted[i]->print_z).c_str(), + layers_sorted.data() + i, j - i, + *object.support_layers()[layer_id]); + ++layer_id; + } + i = j; + } + } +#endif /* SLIC3R_DEBUG */ + // Generate the actual toolpaths and save them into each layer. this->generate_toolpaths(object.support_layers(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers); @@ -3657,21 +3684,23 @@ void PrintObjectSupportMaterial::generate_toolpaths( top_contact_layer.merge(std::move(interface_layer)); } +#if 0 if ( ! interface_layer.empty() && ! base_layer.empty()) { // turn base support into interface when it's contained in our holes // (this way we get wider interface anchoring) - //FIXME one wants to fill in the inner most holes of the interfaces, not all the holes. + //FIXME The intention of the code below is unclear. One likely wanted to just merge small islands of base layers filling in the holes + // inside interface layers, but the code below fills just too much, see GH #4570 Polygons islands = top_level_islands(interface_layer.layer->polygons); polygons_append(interface_layer.layer->polygons, intersection(base_layer.layer->polygons, islands)); base_layer.layer->polygons = diff(base_layer.layer->polygons, islands); } +#endif // Top and bottom contacts, interface layers. for (size_t i = 0; i < 3; ++ i) { MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer); if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty()) continue; - //FIXME When paralellizing, each thread shall have its own copy of the fillers. bool interface_as_base = (&layer_ex == &interface_layer) && m_object_config->support_material_interface_layers.value == 0; //FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore // the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b) From e9875f57a9cdcd32d6244dd38200078f5c2a905c Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 18:08:32 +0100 Subject: [PATCH 4/8] Fix of Unnecessary raft on models with large perimeter but nothing inside. #430 Don't fill in the holes in 1st layer of the raft. The user may apply a higher raft_expansion if one wants a better 1st layer adhesion. --- src/libslic3r/SupportMaterial.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index b77d81219d..cbe9ffb1b6 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -1371,8 +1371,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ if (layer_id == 0) { // This is the first object layer, so the object is being printed on a raft and // we're here just to get the object footprint for the raft. - // We only consider contours and discard holes to get a more continuous raft. +#if 0 + // The following line was filling excessive holes in the raft, see GH #430 overhang_polygons = collect_slices_outer(layer); +#else + // Don't fill in the holes. The user may apply a higher raft_expansion if one wants a better 1st layer adhesion. + overhang_polygons = to_polygons(layer.lslices); +#endif // Expand for better stability. contact_polygons = offset(overhang_polygons, scaled(m_object_config->raft_expansion.value)); } else { From 34417574f5a823994b0e16beb97d2bac877ecf6f Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 18:48:55 +0100 Subject: [PATCH 5/8] Fix of Perl combine infill unit test after a change in raft: 1st object layer over raft is no more printed with bridging infill. --- t/combineinfill.t | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/t/combineinfill.t b/t/combineinfill.t index 282bf467ac..925e5b11d4 100644 --- a/t/combineinfill.t +++ b/t/combineinfill.t @@ -43,9 +43,11 @@ plan tests => 8; my $layers_with_infill = grep $_ > 0, values %layer_infill; is scalar(keys %layers), $layers_with_perimeters+$config->raft_layers, 'expected number of layers'; - # first infill layer is never combined, so we don't consider it - $layers_with_infill--; - $layers_with_perimeters--; + if ($config->raft_layers == 0) { + # first infill layer printed directly on print bed is not combined, so we don't consider it. + $layers_with_infill--; + $layers_with_perimeters--; + } # we expect that infill is generated for half the number of combined layers # plus for each single layer that was not combined (remainder) From 539e80e890abcdd7c19233339f577e1833f203d4 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 19:49:38 +0100 Subject: [PATCH 6/8] Fix of supports create overkill material that actually sopports nothing above it. #2245 When expanding the 1st layer support layer, do it by small steps while trimming with object to avoid supports to leak through object walls. --- src/libslic3r/SupportMaterial.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index cbe9ffb1b6..d9efd75537 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2643,9 +2643,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf } } else if (columns_base != nullptr) { // Expand the bases of the support columns in the 1st layer. - columns_base->polygons = diff( - inflate_factor_1st_layer > 0 ? offset(columns_base->polygons, inflate_factor_1st_layer) : columns_base->polygons, - offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); + { + Polygons &raft = columns_base->polygons; + Polygons trimming = offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS); + if (inflate_factor_1st_layer > SCALED_EPSILON) { + // Inflate in multiple steps to avoid leaking of the support 1st layer through object walls. + auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / m_first_layer_flow.scaled_width()))); + float step = inflate_factor_1st_layer / nsteps; + for (int i = 0; i < nsteps; ++ i) + raft = diff(offset(raft, step), trimming); + } else + raft = diff(raft, trimming); + } if (contacts != nullptr) columns_base->polygons = diff(columns_base->polygons, interface_polygons); if (! brim.empty()) { From 6f5bf71f11b989e056ef8e31ff811548443085c2 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 24 Feb 2021 19:53:50 +0100 Subject: [PATCH 7/8] Fixing some compiler warnings --- src/libslic3r/PrintConfig.hpp | 2 +- src/slic3r/GUI/Tab.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f563163564..c1e3f82cbe 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -513,7 +513,7 @@ public: ConfigOptionFloat support_material_interface_spacing; ConfigOptionFloatOrPercent support_material_interface_speed; ConfigOptionEnum support_material_pattern; - ConfigOptionEnum support_material_interface_pattern; + ConfigOptionEnum support_material_interface_pattern; // Spacing between support material lines (the hatching distance). ConfigOptionFloat support_material_spacing; ConfigOptionFloat support_material_speed; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 374789815c..947c058a4e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3834,7 +3834,7 @@ bool Tab::validate_custom_gcodes() { bool valid = true; if ((m_type == Preset::TYPE_FILAMENT || - m_type == Preset::TYPE_PRINTER && static_cast(this)->m_printer_technology == ptFFF) && + (m_type == Preset::TYPE_PRINTER && static_cast(this)->m_printer_technology == ptFFF)) && m_active_page->title() == "Custom G-code") { for (auto opt_group : m_active_page->m_optgroups) { assert(opt_group->opt_map().size() == 1); From 1e33b95ed71fcee14197501cabc43c6c24dbc68b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 25 Feb 2021 08:23:45 +0100 Subject: [PATCH 8/8] Follow-up of 33aa6be7b7f3d8b81d6b948f9bd6841db10b61cf -> Validation of custom g-code added using vertical slider in preview at gcode generation level --- src/libslic3r/GCode.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f3bffe3316..c7b2c8f784 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -667,6 +667,14 @@ namespace DoExport { break; } } + if (ret.size() < MAX_TAGS_COUNT) { + const CustomGCode::Info& custom_gcode_per_print_z = print.model().custom_gcode_per_print_z; + for (const auto& gcode : custom_gcode_per_print_z.gcodes) { + check(_(L("Custom G-code")), gcode.extra); + if (ret.size() == MAX_TAGS_COUNT) + break; + } + } return ret; }