From ae62f7b8e4b4258318c0d941963eddfb70e86c15 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Tue, 31 Dec 2024 09:30:46 +0800 Subject: [PATCH] ENH: add timelapse gcode for multi_extruder and add most used_extruder for print by object jira:none Change-Id: I021069e865992828b098d73c0d704ba7edbd55d8 --- src/libslic3r/GCode.cpp | 82 ++++++++++++++-------------- src/libslic3r/GCode.hpp | 2 + src/libslic3r/GCode/ToolOrdering.cpp | 11 +++- src/libslic3r/GCode/ToolOrdering.hpp | 5 +- src/slic3r/GUI/Tab.cpp | 3 +- 5 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 955a59883..09dd3919c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1864,7 +1864,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato std::vector first_non_support_filaments; std::vector print_object_instances_ordering; std::vector::const_iterator print_object_instance_sequential_active; - std::vector extruder_count; std::vector::const_iterator first_has_extrude_print_object; //resize first_non_support_filaments.resize(print.config().nozzle_diameter.size(), -1); @@ -1880,13 +1879,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato bool find_fist_non_support_filament = false; for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) { tool_ordering = ToolOrdering(*(*print_object_instance_sequential_active)->print_object, initial_extruder_id); - //get extruder count - std::vector object_extruder_count = tool_ordering.cal_most_used_extruder(print.config()); - if (extruder_count.empty()) - extruder_count = object_extruder_count; - else - for (size_t extruder_id = 0; extruder_id < object_extruder_count.size(); extruder_id++) - extruder_count[extruder_id] += object_extruder_count[extruder_id]; tool_ordering.sort_and_build_data(*(*print_object_instance_sequential_active)->print_object,initial_extruder_id); if (!find_fist_non_support_filament && tool_ordering.first_extruder() != (unsigned int) -1) { @@ -1911,7 +1903,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Find tool ordering for all the objects at once, and the initial extruder ID. // If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it. tool_ordering = print.tool_ordering(); - extruder_count = tool_ordering.cal_most_used_extruder(print.config()); + tool_ordering.cal_most_used_extruder(print.config()); tool_ordering.assign_custom_gcodes(print); if (tool_ordering.all_extruders().empty()) // No object to print was found, cancel the G-code export. @@ -1967,15 +1959,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato file.write(m_writer.set_additional_fan(0)); } - //set key for most used extruder - //count most used extruder - int max_count_extruder = 0; - for (int extruder_id = 1; extruder_id < extruder_count.size(); extruder_id++) { - if (extruder_count[extruder_id] >= extruder_count[max_count_extruder]) - max_count_extruder = extruder_id; - } - - m_placeholder_parser.set("most_used_physical_extruder_id", print.config().physical_extruder_map.values[max_count_extruder]); // Let the start-up script prime the 1st printing tool. auto match_physical_extruder_for_each_filament = [](std::vector &filaments, const FullPrintConfig &config) { @@ -2288,6 +2271,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Process all layers of a single object instance (sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. + tool_ordering.cal_most_used_extruder(print.config()); this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file, prime_extruder); { @@ -2602,7 +2586,7 @@ void GCode::process_layers( //BBS check_placeholder_parser_failed(); print.throw_if_canceled(); - GCode::LayerResult res = this->process_layer(print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1)); + GCode::LayerResult res = this->process_layer(print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, tool_ordering.get_most_used_extruder(), size_t(-1)); res.gcode_store_pos = layer_to_print_idx - 1; return std::move(res); } @@ -2740,7 +2724,7 @@ void GCode::process_layers( //BBS check_placeholder_parser_failed(); print.throw_if_canceled(); - GCode::LayerResult res = this->process_layer(print, {std::move(layer)}, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx, prime_extruder); + GCode::LayerResult res = this->process_layer(print, {std::move(layer)}, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, tool_ordering.get_most_used_extruder(), single_object_idx, prime_extruder); res.gcode_store_pos = layer_to_print_idx - 1; return std::move(res); } @@ -3302,6 +3286,7 @@ GCode::LayerResult GCode::process_layer( const bool last_layer, // Pairs of PrintObject index and its instance index. const std::vector *ordering, + const int most_used_extruder, // If set to size_t(-1), then print all copies of all objects. // Otherwise print a single copy of a single object. const size_t single_object_instance_idx, @@ -3399,7 +3384,7 @@ GCode::LayerResult GCode::process_layer( PrinterStructure printer_structure = m_config.printer_structure.value; bool need_insert_timelapse_gcode_for_traditional = false; - if (printer_structure == PrinterStructure::psI3 && + if ((printer_structure == PrinterStructure::psI3 || m_config.nozzle_diameter.values.size() == 2)&& !m_spiral_vase && (!m_wipe_tower || !m_wipe_tower->enable_timelapse_print()) && print.config().print_sequence == PrintSequence::ByLayer) { @@ -3408,10 +3393,13 @@ GCode::LayerResult GCode::process_layer( bool has_insert_timelapse_gcode = false; bool has_wipe_tower = (layer_tools.has_wipe_tower && m_wipe_tower); - auto insert_timelapse_gcode = [this, print_z, &print]() -> std::string { + int physical_extruder_id = print.config().physical_extruder_map.get_at(most_used_extruder); + + auto insert_timelapse_gcode = [this, print_z, &print, &physical_extruder_id]() -> std::string { std::string gcode_res; if (!print.config().time_lapse_gcode.value.empty()) { DynamicConfig config; + config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id)); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z)); @@ -3424,7 +3412,9 @@ GCode::LayerResult GCode::process_layer( gcode += this->change_layer(print_z); // this will increase m_layer_index m_layer = &layer; m_object_layer_over_raft = false; - if (printer_structure == PrinterStructure::psI3 && !need_insert_timelapse_gcode_for_traditional && !m_spiral_vase && print.config().print_sequence == PrintSequence::ByLayer) { + if ((printer_structure == PrinterStructure::psI3 || m_config.nozzle_diameter.values.size() == 2) + && !need_insert_timelapse_gcode_for_traditional && !m_spiral_vase + && print.config().print_sequence == PrintSequence::ByLayer) { std::string timepals_gcode = insert_timelapse_gcode(); gcode += timepals_gcode; m_writer.set_current_position_clear(false); @@ -3438,6 +3428,7 @@ GCode::LayerResult GCode::process_layer( } if (! print.config().layer_change_gcode.value.empty()) { DynamicConfig config; + config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id)); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); gcode += this->placeholder_parser_process("layer_change_gcode", @@ -3785,20 +3776,29 @@ GCode::LayerResult GCode::process_layer( if (has_wipe_tower) { if (!m_wipe_tower->is_empty_wipe_tower_gcode(*this, extruder_id, extruder_id == layer_tools.extruders.back())) { if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) { - gcode += this->retract(false, false, LiftType::NormalLift); - m_writer.add_object_change_labels(gcode); - - std::string timepals_gcode = insert_timelapse_gcode(); - gcode += timepals_gcode; - m_writer.set_current_position_clear(false); - //BBS: check whether custom gcode changes the z position. Update if changed - double temp_z_after_timepals_gcode; - if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) { - Vec3d pos = m_writer.get_position(); - pos(2) = temp_z_after_timepals_gcode; - m_writer.set_position(pos); + bool should_insert = true; + if (m_config.nozzle_diameter.values.size() == 2){ + if (!writer().filament() || get_extruder_id(writer().filament()->id()) != most_used_extruder) { + should_insert = false; + } + } + + if (should_insert) { + gcode += this->retract(false, false, LiftType::NormalLift); + m_writer.add_object_change_labels(gcode); + + std::string timepals_gcode = insert_timelapse_gcode(); + gcode += timepals_gcode; + m_writer.set_current_position_clear(false); + // BBS: check whether custom gcode changes the z position. Update if changed + double temp_z_after_timepals_gcode; + if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) { + Vec3d pos = m_writer.get_position(); + pos(2) = temp_z_after_timepals_gcode; + m_writer.set_position(pos); + } + has_insert_timelapse_gcode = true; } - has_insert_timelapse_gcode = true; } gcode += m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()); } @@ -4011,7 +4011,8 @@ GCode::LayerResult GCode::process_layer( //BBS: for first layer, we always print wall firstly to get better bed adhesive force //This behaviour is same with cura if (is_infill_first && !first_layer) { - if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { + if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure == PrinterStructure::psI3 + && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { gcode += this->retract(false, false, LiftType::NormalLift); if (!temp_start_str.empty() && m_writer.empty_object_start_str()) { std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n"; @@ -4040,7 +4041,8 @@ GCode::LayerResult GCode::process_layer( gcode += this->extrude_perimeters(print, by_region_specific); } else { gcode += this->extrude_perimeters(print, by_region_specific); - if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { + if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure == PrinterStructure::psI3 + && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { gcode += this->retract(false, false, LiftType::NormalLift); if (!temp_start_str.empty() && m_writer.empty_object_start_str()) { std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n"; @@ -4126,8 +4128,8 @@ GCode::LayerResult GCode::process_layer( BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << log_memory_info(); - if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) { - if (m_support_traditional_timelapse) + if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) { + if (m_support_traditional_timelapse && printer_structure == PrinterStructure::psI3) m_support_traditional_timelapse = false; gcode += this->retract(false, false, LiftType::NormalLift); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index b98fc42ce..89513a4da 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -340,6 +340,8 @@ private: const bool last_layer, // Pairs of PrintObject index and its instance index. const std::vector *ordering, + // idientiy timelapse pos + const int most_used_extruder, // If set to size_t(-1), then print all copies of all objects. // Otherwise print a single copy of a single object. const size_t single_object_idx = size_t(-1), diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 1948e5e7a..6c7584ff9 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -801,7 +801,7 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material) } } -std::vector ToolOrdering::cal_most_used_extruder(const PrintConfig &config) +void ToolOrdering::cal_most_used_extruder(const PrintConfig &config) { // record std::vector extruder_count; @@ -819,7 +819,14 @@ std::vector ToolOrdering::cal_most_used_extruder(const PrintConfig &config) extruder_count[extruder_id]++; } } - return extruder_count; + + // set key for most used extruder + // count most used extruder + most_used_extruder = 0; + for (int extruder_id = 1; extruder_id < extruder_count.size(); extruder_id++) { + if (extruder_count[extruder_id] >= extruder_count[most_used_extruder]) + most_used_extruder = extruder_id; + } } //BBS: find first non support filament diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index bc39d0dad..29974bda4 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -235,6 +235,7 @@ public: std::vector& layer_tools() { return m_layer_tools; } bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().has_wipe_tower; } + int get_most_used_extruder() const { return most_used_extruder; } /* * called in single extruder mode, the value in map are all 0 * called in dual extruder mode, the value in map will be 0 or 1 @@ -246,7 +247,7 @@ public: // should be called after doing reorder FilamentChangeStats get_filament_change_stats(FilamentChangeMode mode); - std::vector cal_most_used_extruder(const PrintConfig &config); + void cal_most_used_extruder(const PrintConfig &config); bool cal_non_support_filaments(const PrintConfig &config, unsigned int & first_non_support_filament, std::vector & initial_non_support_filaments, @@ -281,6 +282,8 @@ private: FilamentChangeStats m_stats_by_single_extruder; FilamentChangeStats m_stats_by_multi_extruder_curr; FilamentChangeStats m_stats_by_multi_extruder_best; + + int most_used_extruder; }; } // namespace SLic3r diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 46ec65be4..0abb446d8 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -4350,7 +4350,8 @@ void TabPrinter::toggle_options() } if (m_active_page->title() == "Machine gcode") { - toggle_line("time_lapse_gcode", m_preset_bundle->printers.get_edited_preset().config.opt_enum("printer_structure") == PrinterStructure::psI3); + toggle_line("time_lapse_gcode", + m_preset_bundle->printers.get_edited_preset().config.opt_enum("printer_structure") == PrinterStructure::psI3 || m_preset_bundle->get_printer_extruder_count() == 2); } wxString extruder_number; long val = 1;