From 88d7620c068a777e639f77a38bad69519468e564 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 9 May 2023 13:42:45 +0200 Subject: [PATCH 1/5] Allow to set specific extruder for the wipe tower (first part) --- src/libslic3r/GCode/ToolOrdering.cpp | 26 ++++++++++++++++++++++++++ src/libslic3r/GCode/ToolOrdering.hpp | 1 + src/libslic3r/GCode/WipeTower.cpp | 2 +- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 1 + src/libslic3r/PrintConfig.cpp | 21 +++++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 1 + src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 9 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 6a8a7a812..acddb137e 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -168,6 +168,11 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); + if (this->insert_wipe_tower_extruder()) { + this->reorder_extruders(first_extruder); + this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); + } + this->collect_extruder_statistics(prime_multi_material); this->mark_skirt_layers(print.config(), max_layer_height); @@ -462,6 +467,27 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ } } +bool ToolOrdering::insert_wipe_tower_extruder() +{ + // In case that wipe_tower_extruder is set to non-zero, we must make sure that the extruder will be in the list. + bool changed = false; + if (m_print_config_ptr->wipe_tower_extruder != 0) { + for (LayerTools& lt : m_layer_tools) { + if (lt.wipe_tower_partitions > 0) { + lt.extruders.emplace_back(m_print_config_ptr->wipe_tower_extruder - 1); + sort_remove_duplicates(lt.extruders); + changed = true; + } + } + // Now convert the 0-based list to 1-based again. + for (LayerTools& lt : m_layer_tools) { + for (auto& extruder : lt.extruders) + ++extruder; + } + } + return changed; +} + void ToolOrdering::collect_extruder_statistics(bool prime_multi_material) { m_first_printing_extruder = (unsigned int)-1; diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 4fb6e56c0..f4685eb9b 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -167,6 +167,7 @@ private: void collect_extruders(const PrintObject &object, const std::vector> &per_layer_extruder_switches); void reorder_extruders(unsigned int last_extruder_id); void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height); + bool insert_wipe_tower_extruder(); void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height); void collect_extruder_statistics(bool prime_multi_material); diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 0853951db..5ce5353db 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -581,7 +581,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config) m_filpar.push_back(FilamentParameters()); m_filpar[idx].material = config.filament_type.get_at(idx); - m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx); + m_filpar[idx].is_soluble = config.wipe_tower_extruder == 0 ? config.filament_soluble.get_at(idx) : (idx != config.wipe_tower_extruder - 1); m_filpar[idx].temperature = config.temperature.get_at(idx); m_filpar[idx].first_layer_temperature = config.first_layer_temperature.get_at(idx); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index b63576a0d..13625748a 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -456,7 +456,7 @@ static std::vector s_Preset_print_options { "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", - "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", + "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "wall_distribution_count", "min_feature_size", "min_bead_width" }; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 0ec88c44f..2487b68e2 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -208,6 +208,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "wipe_tower_bridging" || opt_key == "wipe_tower_extra_spacing" || opt_key == "wipe_tower_no_sparse_layers" + || opt_key == "wipe_tower_extruder" || opt_key == "wiping_volumes_matrix" || opt_key == "parking_pos_retraction" || opt_key == "cooling_tube_retraction" diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 77120bfdf..fa4e885f1 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3235,6 +3235,27 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(10.)); + def = this->add("wipe_tower_extruder", coInt); + def->label = L("Wipe tower extruder"); + def->category = L("Extruders"); + def->tooltip = L("The extruder to use when printing perimeter of the wipe tower. " + "Set to 0 to use the one that is available (non-soluble would be preferred)."); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionInt(0)); + + def = this->add("solid_infill_every_layers", coInt); + def->label = L("Solid infill every"); + def->category = L("Infill"); + def->tooltip = L("This feature allows to force a solid layer every given number of layers. " + "Zero to disable. You can set this to any value (for example 9999); " + "Slic3r will automatically choose the maximum possible number of layers " + "to combine according to nozzle diameter and layer height."); + def->sidetext = L("layers"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInt(0)); + def = this->add("xy_size_compensation", coFloat); def->label = L("XY Size Compensation"); def->category = L("Advanced"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 2a4b3258d..36a63d33d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -829,6 +829,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloat, wipe_tower_cone_angle)) ((ConfigOptionPercent, wipe_tower_extra_spacing)) ((ConfigOptionFloat, wipe_tower_bridging)) + ((ConfigOptionInt, wipe_tower_extruder)) ((ConfigOptionFloats, wiping_volumes_matrix)) ((ConfigOptionFloats, wiping_volumes_extruders)) ((ConfigOptionFloat, z_offset)) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6e6b72f9a..84582f895 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2007,7 +2007,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", "brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", - "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", + "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder", "extruder_colour", "filament_colour", "material_colour", "max_print_height", "printer_model", "printer_technology", // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. "layer_height", "first_layer_height", "min_layer_height", "max_layer_height", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 51b01a5e5..93017714e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1598,6 +1598,7 @@ void TabPrint::build() optgroup->append_single_option_line("solid_infill_extruder"); optgroup->append_single_option_line("support_material_extruder"); optgroup->append_single_option_line("support_material_interface_extruder"); + optgroup->append_single_option_line("wipe_tower_extruder"); optgroup = page->new_optgroup(L("Ooze prevention")); optgroup->append_single_option_line("ooze_prevention"); From 6c00a9dd38c9095efbdebb265735f55129c418ae Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 24 May 2023 12:20:32 +0200 Subject: [PATCH 2/5] Fixed a crash when wipe_tower_extruder is invalid --- src/libslic3r/PrintConfig.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index fa4e885f1..a8cc410ab 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4346,6 +4346,14 @@ void DynamicPrintConfig::normalize_fdm() } } + if (this->has("wipe_tower_extruder")) { + // If invalid, replace with 0. + int extruder = this->opt("wipe_tower_extruder")->value; + int num_extruders = this->opt("nozzle_diameter")->size(); + if (extruder < 0 || extruder > num_extruders) + this->option("wipe_tower_extruder")->setInt(0); + } + if (!this->has("solid_infill_extruder") && this->has("infill_extruder")) this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt()); From f25531484b5b73e1fc16aa13fb60f4d2e0c5f69b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 24 May 2023 16:48:14 +0200 Subject: [PATCH 3/5] Fixed Print::extruders() so it is aware of the wipe_tower_extruder --- src/libslic3r/Print.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 2487b68e2..458671e5b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -329,6 +329,15 @@ std::vector Print::extruders() const std::vector extruders = this->object_extruders(); append(extruders, this->support_material_extruders()); sort_remove_duplicates(extruders); + + // The wipe tower extruder can also be set. When the wipe tower is enabled and it will be generated, + // append its extruder into the list too. + if (has_wipe_tower() && config().wipe_tower_extruder != 0 && extruders.size() > 1) { + assert(config().wipe_tower_extruder > 0 && config().wipe_tower_extruder < int(config().nozzle_diameter.size())); + extruders.emplace_back(config().wipe_tower_extruder - 1); // the config value is 1-based + sort_remove_duplicates(extruders); + } + return extruders; } From 8431595db8d162c6face433dd12d8bd5eef9a77e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 12 May 2023 10:20:09 +0200 Subject: [PATCH 4/5] Allow multiple warnings to be emitted from Print::validate --- src/libslic3r/Print.cpp | 6 +++--- src/libslic3r/Print.hpp | 2 +- src/libslic3r/PrintBase.hpp | 2 +- src/libslic3r/SLAPrint.cpp | 2 +- src/libslic3r/SLAPrint.hpp | 2 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 4 ++-- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 20 ++++++++++---------- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 458671e5b..68dcb2f03 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -468,7 +468,7 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print) boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" }; // Precondition: Print::validate() requires the Print::apply() to be called its invocation. -std::string Print::validate(std::string* warning) const +std::string Print::validate(std::vector* warnings) const { std::vector extruders = this->extruders(); @@ -691,12 +691,12 @@ std::string Print::validate(std::string* warning) const // Do we have custom support data that would not be used? // Notify the user in that case. - if (! object->has_support() && warning) { + if (! object->has_support() && warnings) { for (const ModelVolume* mv : object->model_object()->volumes) { bool has_enforcers = mv->is_support_enforcer() || (mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER)); if (has_enforcers) { - *warning = "_SUPPORTS_OFF"; + warnings->emplace_back("_SUPPORTS_OFF"); break; } } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c96b0ca9a..5c42709b1 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -547,7 +547,7 @@ public: bool has_brim() const; // Returns an empty string if valid, otherwise returns an error message. - std::string validate(std::string* warning = nullptr) const override; + std::string validate(std::vector* warnings = nullptr) const override; double skirt_first_layer_height() const; Flow brim_flow() const; Flow skirt_flow() const; diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 4c009cac8..9c95255d4 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -418,7 +418,7 @@ public: virtual std::vector print_object_ids() const = 0; // Validate the print, return empty string if valid, return error if process() cannot (or should not) be started. - virtual std::string validate(std::string* warning = nullptr) const { return std::string(); } + virtual std::string validate(std::vector* warnings = nullptr) const { return std::string(); } enum ApplyStatus { // No change after the Print::apply() call. diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index c4947851b..1598cd46b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -534,7 +534,7 @@ std::string SLAPrint::output_filename(const std::string &filename_base) const return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config); } -std::string SLAPrint::validate(std::string*) const +std::string SLAPrint::validate(std::vector*) const { for(SLAPrintObject * po : m_objects) { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 126941d82..96ac6f40f 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -494,7 +494,7 @@ public: const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } - std::string validate(std::string* warning = nullptr) const override; + std::string validate(std::vector* warnings = nullptr) const override; // An aggregation of SliceRecord-s from all the print objects for each // occupied layer. Slice record levels dont have to match exactly. diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 763ce5174..8067a6e39 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -549,10 +549,10 @@ bool BackgroundSlicingProcess::empty() const return m_print->empty(); } -std::string BackgroundSlicingProcess::validate(std::string* warning) +std::string BackgroundSlicingProcess::validate(std::vector* warnings) { assert(m_print != nullptr); - return m_print->validate(warning); + return m_print->validate(warnings); } // Apply config over the print. Returns false, if the new config values caused any of the already diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 00a3ab6d0..2b049a4f1 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -132,7 +132,7 @@ public: bool empty() const; // Validate the print. Returns an empty string if valid, returns an error message if invalid. // Call validate before calling start(). - std::string validate(std::string* warning = nullptr); + std::string validate(std::vector* warnings = nullptr); // Set the export path of the G-code. // Once the path is set, the G-code diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 84582f895..cbf64aadd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1849,7 +1849,7 @@ struct Plater::priv void suppress_snapshots() { m_prevent_snapshots++; } void allow_snapshots() { m_prevent_snapshots--; } - void process_validation_warning(const std::string& warning) const; + void process_validation_warning(const std::vector& warning) const; bool background_processing_enabled() const { return this->get_config_bool("background_processing"); } void update_print_volume_state(); @@ -3198,12 +3198,12 @@ void Plater::priv::update_print_volume_state() this->q->model().update_print_volume_state(this->bed.build_volume()); } -void Plater::priv::process_validation_warning(const std::string& warning) const +void Plater::priv::process_validation_warning(const std::vector& warnings) const { - if (warning.empty()) + if (warnings.empty()) notification_manager->close_notification_of_type(NotificationType::ValidateWarning); else { - std::string text = warning; + std::string text = warnings.front(); std::string hypertext = ""; std::function action_fn = [](wxEvtHandler*){ return false; }; @@ -3279,8 +3279,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool // The delayed error message is no more valid. delayed_error_message.clear(); // The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors. - std::string warning; - std::string err = background_process.validate(&warning); + std::vector warnings; + std::string err = background_process.validate(&warnings); if (err.empty()) { notification_manager->set_all_slicing_errors_gray(true); notification_manager->close_notification_of_type(NotificationType::ValidateError); @@ -3289,7 +3289,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool // Pass a warning from validation and either show a notification, // or hide the old one. - process_validation_warning(warning); + process_validation_warning(warnings); if (printer_technology == ptFFF) { GLCanvas3D* canvas = view3D->get_canvas3d(); canvas->reset_sequential_print_clearance(); @@ -3328,8 +3328,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool canvas->request_extra_frame(); } } - std::string warning; - std::string err = background_process.validate(&warning); + std::vector warnings; + std::string err = background_process.validate(&warnings); if (!err.empty()) return return_state; } @@ -3342,7 +3342,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool //actualizate warnings if (invalidated != Print::APPLY_STATUS_UNCHANGED || background_process.empty()) { if (background_process.empty()) - process_validation_warning(std::string()); + process_validation_warning(std::vector()); actualize_slicing_warnings(*this->background_process.current_print()); actualize_object_warnings(*this->background_process.current_print()); show_warning_dialog = false; From 5c3e5f507a92d64bea26685f127f98f6f64963d9 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 16 May 2023 15:47:01 +0200 Subject: [PATCH 5/5] Added a warning whenbed temperatures differ too much --- src/libslic3r/Print.cpp | 11 +++++++++++ src/slic3r/GUI/Plater.cpp | 6 ++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 68dcb2f03..ca3feb04e 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -472,6 +472,17 @@ std::string Print::validate(std::vector* warnings) const { std::vector extruders = this->extruders(); + if (warnings) { + for (size_t a=0; a 15 + || std::abs(m_config.first_layer_bed_temperature.get_at(extruders[a]) - m_config.first_layer_bed_temperature.get_at(extruders[b])) > 15) { + warnings->emplace_back("_BED_TEMPS_DIFFER"); + goto DONE; + } + DONE:; + } + if (m_objects.empty()) return _u8L("All objects are outside of the print volume."); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cbf64aadd..180653f77 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3202,8 +3202,8 @@ void Plater::priv::process_validation_warning(const std::vector& wa { if (warnings.empty()) notification_manager->close_notification_of_type(NotificationType::ValidateWarning); - else { - std::string text = warnings.front(); + + for (std::string text : warnings) { std::string hypertext = ""; std::function action_fn = [](wxEvtHandler*){ return false; }; @@ -3222,6 +3222,8 @@ void Plater::priv::process_validation_warning(const std::vector& wa return true; }; } + if (text == "_BED_TEMPS_DIFFER") + text = _u8L("Bed temperatures for the used filaments differ significantly."); notification_manager->push_notification( NotificationType::ValidateWarning,