From ac3b78801a5983e5521141de0944b7098887da80 Mon Sep 17 00:00:00 2001 From: tsmith35 Date: Mon, 9 Sep 2024 15:39:27 -0500 Subject: [PATCH 1/6] Update GCode.cpp per BS PR 4631 --- src/libslic3r/GCode.cpp | 446 +++++++++++++++++++++++----------------- 1 file changed, 253 insertions(+), 193 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 171d68b9480..ae8899a100f 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -602,16 +602,34 @@ static std::vector get_path_of_change_filament(const Print& print) toolchange_gcode_str = toolchange_retract_str + toolchange_gcode_str; // BBS { - // BBS: current position and fan_speed is unclear after interting change_filament_gcode check_add_eol(toolchange_gcode_str); + //BBS: gcode writer doesn't know fan speed after inserting tool change gcode toolchange_gcode_str += ";_FORCE_RESUME_FAN_SPEED\n"; - gcodegen.writer().set_current_position_clear(false); - // BBS: check whether custom gcode changes the z position. Update if changed - double temp_z_after_tool_change; - if (GCodeProcessor::get_last_z_from_gcode(toolchange_gcode_str, temp_z_after_tool_change)) { - Vec3d pos = gcodegen.writer().get_position(); - pos(2) = temp_z_after_tool_change; - gcodegen.writer().set_position(pos); + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = gcodegen.writer().get_position(); + + double temp_x_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_str, 0, temp_x_after_toolchange_gcode)) { + new_pos(0) = temp_x_after_toolchange_gcode; + position_changed = true; + } + + double temp_y_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_str, 1, temp_y_after_toolchange_gcode)) { + new_pos(1) = temp_y_after_toolchange_gcode; + position_changed = true; + } + + double temp_z_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_str, 2, temp_z_after_toolchange_gcode)) { + new_pos(2) = temp_z_after_toolchange_gcode; + position_changed = true; + } + + if (position_changed) { + gcodegen.writer().set_position(new_pos); } } @@ -3356,10 +3374,10 @@ namespace ProcessLayer } // namespace ProcessLayer namespace Skirt { - static void skirt_loops_per_extruder_all_printing(const Print &print, const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) + static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) { // Prime all extruders printing over the 1st layer over the skirt lines. - size_t n_loops = skirt.entities.size(); + size_t n_loops = print.skirt().entities.size(); size_t n_tools = layer_tools.extruders.size(); size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools; @@ -3377,7 +3395,6 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_1st_layer( const Print &print, - const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3387,8 +3404,8 @@ namespace Skirt { std::map> skirt_loops_per_extruder_out; //For sequential print, the following test may fail when extruding the 2nd and other objects. // assert(skirt_done.empty()); - if (skirt_done.empty() && print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt) { - skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); + if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) { + skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); skirt_done.emplace_back(layer_tools.print_z); } return skirt_loops_per_extruder_out; @@ -3396,7 +3413,6 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_other_layers( const Print &print, - const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3404,7 +3420,7 @@ namespace Skirt { // Extrude skirt at the print_z of the raft layers and normal object layers // not at the print_z of the interlaced support material layers. std::map> skirt_loops_per_extruder_out; - if (print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt && + if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt && // Not enough skirt layers printed yet. //FIXME infinite or high skirt does not make sense for sequential print! (skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt())) { @@ -3418,7 +3434,7 @@ namespace Skirt { skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair(0, print.config().skirt_loops.value); #else // Prime all extruders planned for this layer, see - skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); + skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); #endif assert(!skirt_done.empty()); skirt_done.emplace_back(layer_tools.print_z); @@ -3427,33 +3443,6 @@ namespace Skirt { return skirt_loops_per_extruder_out; } - static Point find_start_point(ExtrusionLoop& loop, float start_angle) { - coord_t min_x = std::numeric_limits::max(); - coord_t max_x = std::numeric_limits::min(); - coord_t min_y = min_x; - coord_t max_y = max_x; - - Points pts; - loop.collect_points(pts); - for (Point pt: pts) { - if (pt.x() < min_x) - min_x = pt.x(); - else if (pt.x() > max_x) - max_x = pt.x(); - if (pt.y() < min_y) - min_y = pt.y(); - else if (pt.y() > max_y) - max_y = pt.y(); - } - - Point center((min_x + max_x)/2., (min_y + max_y)/2.); - double r = center.distance_to(Point(min_x, min_y)); - double deg = start_angle * PI / 180; - double shift_x = r * std::cos(deg); - double shift_y = r * std::sin(deg); - return Point(center.x()+shift_x, center.y() + shift_y); - } - } // namespace Skirt // Orca: Klipper can't parse object names with spaces and other spetical characters @@ -3481,57 +3470,6 @@ inline std::string get_instance_name(const PrintObject *object, const PrintInsta return get_instance_name(object, inst.id); } -std::string GCode::generate_skirt(const Print &print, - const ExtrusionEntityCollection &skirt, - const Point& offset, - const LayerTools &layer_tools, - const Layer& layer, - unsigned int extruder_id) -{ - - bool first_layer = (layer.id() == 0 && abs(layer.bottom_z()) < EPSILON); - std::string gcode; - // Extrude skirt at the print_z of the raft layers and normal object layers - // not at the print_z of the interlaced support material layers. - // Map from extruder ID to index of skirt loops to be extruded with that extruder. - std::map> skirt_loops_per_extruder; - skirt_loops_per_extruder = first_layer ? - Skirt::make_skirt_loops_per_extruder_1st_layer(print, skirt, layer_tools, m_skirt_done) : - Skirt::make_skirt_loops_per_extruder_other_layers(print, skirt, layer_tools, m_skirt_done); - - if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { - const std::pair loops = loops_it->second; - - set_origin(unscaled(offset)); - - m_avoid_crossing_perimeters.use_external_mp(); - Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); - double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); - for (size_t i = first_layer ? loops.first : loops.second - 1; i < loops.second; ++i) { - // Adjust flow according to this layer's layer height. - ExtrusionLoop loop = *dynamic_cast(skirt.entities[i]); - for (ExtrusionPath &path : loop.paths) { - path.height = layer_skirt_flow.height(); - path.mm3_per_mm = mm3_per_mm; - } - - //set skirt start point location - if (first_layer && i==loops.first) - this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle)); - - //FIXME using the support_speed of the 1st object printed. - gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); - if (!first_layer) - break; - } - m_avoid_crossing_perimeters.use_external_mp(false); - // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). - if (first_layer && loops.first == 0) - m_avoid_crossing_perimeters.disable_once(); - } - return gcode; -} - // In sequential mode, process_layer is called once per each object and its copy, // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. // In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated. @@ -3668,17 +3606,37 @@ 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; + // insert timelapse_gcode when traditional mode is not used (smooth mode) if(is_BBL_Printer()){ if (printer_structure == PrinterStructure::psI3 && !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); - //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); + + std::string timelapse_gcode = insert_timelapse_gcode(); + gcode += timelapse_gcode; + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 0, temp_x_after_timelapse_gcode)) { + new_pos(0) = temp_x_after_timelapse_gcode; + position_changed = true; + } + + double temp_y_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 1, temp_y_after_timelapse_gcode)) { + new_pos(1) = temp_y_after_timelapse_gcode; + position_changed = true; + } + + double temp_z_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 2, temp_z_after_timelapse_gcode)) { + new_pos(2) = temp_z_after_timelapse_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } } } else { @@ -3783,10 +3741,18 @@ LayerResult GCode::process_layer( m_second_layer_things_done = true; } + // Map from extruder ID to index of skirt loops to be extruded with that extruder. + std::map> skirt_loops_per_extruder; + if (single_object_instance_idx == size_t(-1)) { // Normal (non-sequential) print. gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config()); } + // Extrude skirt at the print_z of the raft layers and normal object layers + // not at the print_z of the interlaced support material layers. + skirt_loops_per_extruder = first_layer ? + Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) : + Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done); // BBS: get next extruder according to flush and soluble auto get_next_extruder = [&](int current_extruder,const std::vector&extruders) { @@ -4026,21 +3992,40 @@ LayerResult GCode::process_layer( // Extrude the skirt, brim, support, perimeters, infill ordered by the extruders. for (unsigned int extruder_id : layer_tools.extruders) { + // insert timelapse_gcode when wipe tower is enabled and traditional mode is used 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); + gcode += this->retract(false, false, LiftType::SpiralLift); 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); + std::string timelapse_gcode = insert_timelapse_gcode(); + gcode += timelapse_gcode; + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 0, temp_x_after_timelapse_gcode)) { + new_pos(0) = temp_x_after_timelapse_gcode; + position_changed = true; + } + + double temp_y_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 1, temp_y_after_timelapse_gcode)) { + new_pos(1) = temp_y_after_timelapse_gcode; + position_changed = true; + } + + double temp_z_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 2, temp_z_after_timelapse_gcode)) { + new_pos(2) = temp_z_after_timelapse_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } has_insert_timelapse_gcode = true; } @@ -4053,9 +4038,28 @@ LayerResult GCode::process_layer( // let analyzer tag generator aware of a role type change if (layer_tools.has_wipe_tower && m_wipe_tower) m_last_processor_extrusion_role = erWipeTower; - - if (print.config().skirt_type == stCombined && !print.skirt().empty()) - gcode += generate_skirt(print, print.skirt(), Point(0,0), layer_tools, layer, extruder_id); + + if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { + const std::pair loops = loops_it->second; + this->set_origin(0., 0.); + m_avoid_crossing_perimeters.use_external_mp(); + Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); + double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); + for (size_t i = (layer.id() == 0) ? loops.first : loops.second - 1; i < loops.second; ++i) { + // Adjust flow according to this layer's layer height. + ExtrusionLoop loop = *dynamic_cast(print.skirt().entities[i]); + for (ExtrusionPath &path : loop.paths) { + path.height = layer_skirt_flow.height(); + path.mm3_per_mm = mm3_per_mm; + } + //FIXME using the support_speed of the 1st object printed. + gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); + } + m_avoid_crossing_perimeters.use_external_mp(false); + // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). + if (first_layer && loops.first == 0) + m_avoid_crossing_perimeters.disable_once(); + } auto objects_by_extruder_it = by_extruder.find(extruder_id); if (objects_by_extruder_it == by_extruder.end()) @@ -4090,17 +4094,8 @@ LayerResult GCode::process_layer( } // BBS - if (print.config().skirt_type == stPerObject && - print.config().print_sequence == PrintSequence::ByObject && - !layer.object()->object_skirt().empty() && - ((layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) - ) - { + if (print.has_skirt() && print.config().print_sequence == PrintSequence::ByObject && prime_extruder && first_layer && extruder_id == first_extruder_id) { for (InstanceToPrint& instance_to_print : instances_to_print) { - - if (instance_to_print.print_object.object_skirt().empty()) - continue; - if (this->m_objSupportsWithBrim.find(instance_to_print.print_object.id()) != this->m_objSupportsWithBrim.end() && print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; @@ -4108,14 +4103,12 @@ LayerResult GCode::process_layer( if (this->m_objsWithBrim.find(instance_to_print.print_object.id()) != this->m_objsWithBrim.end() && print.m_brimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; - if (first_layer) - m_skirt_done.clear(); - - if (layer.id() == 1 && m_skirt_done.size() > 1) - m_skirt_done.erase(m_skirt_done.begin()+1,m_skirt_done.end()); const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; - gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); + set_origin(unscaled(offset)); + for (ExtrusionEntity* ee : layer.object()->object_skirt().entities) + //FIXME using the support_speed of the 1st object printed. + gcode += this->extrude_entity(*ee, "skirt", m_config.support_speed.value); } } @@ -4124,22 +4117,7 @@ LayerResult GCode::process_layer( for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) { if (is_anything_overridden && print_wipe_extrusions == 0) gcode+="; PURGING FINISHED\n"; - for (InstanceToPrint &instance_to_print : instances_to_print) { - if (print.config().skirt_type == stPerObject && - !instance_to_print.print_object.object_skirt().empty() && - print.config().print_sequence == PrintSequence::ByLayer - && - (layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) - { - if (first_layer) - m_skirt_done.clear(); - const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; - gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); - if (instances_to_print.size() > 1 && &instance_to_print != &*(instances_to_print.end() - 1)) - m_skirt_done.pop_back(); - } - const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id]; const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; // To control print speed of the 1st object layer printed over raft interface. @@ -4151,18 +4129,23 @@ LayerResult GCode::process_layer( if (m_config.reduce_crossing_wall) m_avoid_crossing_perimeters.init_layer(*m_layer); +//------------------------------------------------------------------------------ + std::string start_str; + std::string start_str_a; + std::string temp_start_str; if (this->config().gcode_label_objects) { - gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + + start_str_a = std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(inst.id) + "\n"; } // exclude objects if (m_enable_exclude_object) { if (is_BBL_Printer()) { - m_writer.set_object_start_str( + start_str = std::string("; start printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n" + "M624 " + - _encode_label_ids_to_base64({instance_to_print.label_object_id}) + "\n"); + _encode_label_ids_to_base64({instance_to_print.label_object_id}) + "\n"; + m_writer.set_object_start_str(start_str); } else { const auto gflavor = print.config().gcode_flavor.value; if (gflavor == gcfKlipper) { @@ -4175,9 +4158,12 @@ LayerResult GCode::process_layer( } } } + temp_start_str = start_str + start_str_a; + gcode += start_str_a; if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic) m_extrusion_quality_estimator.set_current_object(&instance_to_print.print_object); +//------------------------------------------------------------------------------ // When starting a new object, use the external motion planner for the first travel move. const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; @@ -4261,20 +4247,39 @@ 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 + + // insert timelapse_gcode when no wipe tower, has infill and not first layer 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)) { - gcode += this->retract(false, false, LiftType::NormalLift); - - 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); + gcode += this->retract(false, false, LiftType::SpiralLift); + + std::string timelapse_gcode = insert_timelapse_gcode(); + gcode += timelapse_gcode; + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 0, temp_x_after_timelapse_gcode)) { + new_pos(0) = temp_x_after_timelapse_gcode; + position_changed = true; + } + + double temp_y_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 1, temp_y_after_timelapse_gcode)) { + new_pos(1) = temp_y_after_timelapse_gcode; + position_changed = true; + } + + double temp_z_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 2, temp_z_after_timelapse_gcode)) { + new_pos(2) = temp_z_after_timelapse_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } has_insert_timelapse_gcode = true; @@ -4283,18 +4288,37 @@ LayerResult GCode::process_layer( gcode += this->extrude_perimeters(print, by_region_specific); } else { gcode += this->extrude_perimeters(print, by_region_specific); + + // insert timelapse_gcode when no wipe tower, no infill and is first layer if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { - gcode += this->retract(false, false, LiftType::NormalLift); - - 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); + gcode += this->retract(false, false, LiftType::SpiralLift); + std::string timelapse_gcode = insert_timelapse_gcode(); + gcode += timelapse_gcode; + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 0, temp_x_after_timelapse_gcode)) { + new_pos(0) = temp_x_after_timelapse_gcode; + position_changed = true; + } + + double temp_y_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 1, temp_y_after_timelapse_gcode)) { + new_pos(1) = temp_y_after_timelapse_gcode; + position_changed = true; + } + + double temp_z_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 2, temp_z_after_timelapse_gcode)) { + new_pos(2) = temp_z_after_timelapse_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } has_insert_timelapse_gcode = true; @@ -4361,22 +4385,41 @@ LayerResult GCode::process_layer( BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << log_memory_info(); + // insert timelapse_gcode when no wipe tower and no infill if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) { if (m_support_traditional_timelapse) m_support_traditional_timelapse = false; - gcode += this->retract(false, false, LiftType::NormalLift); + gcode += this->retract(false, false, LiftType::SpiralLift); 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); + std::string timelapse_gcode = insert_timelapse_gcode(); + gcode += timelapse_gcode; + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 0, temp_x_after_timelapse_gcode)) { + new_pos(0) = temp_x_after_timelapse_gcode; + position_changed = true; + } + + double temp_y_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 1, temp_y_after_timelapse_gcode)) { + new_pos(1) = temp_y_after_timelapse_gcode; + position_changed = true; + } + + double temp_z_after_timelapse_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(timelapse_gcode, 2, temp_z_after_timelapse_gcode)) { + new_pos(2) = temp_z_after_timelapse_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } } @@ -6409,16 +6452,33 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool b //BBS { - //BBS: gcode writer doesn't know where the extruder is and whether fan speed is changed after inserting tool change gcode - //Set this flag so that normal lift will be used the first time after tool change. + //BBS: gcode writer doesn't know fan speed after inserting tool change gcode gcode += ";_FORCE_RESUME_FAN_SPEED\n"; - m_writer.set_current_position_clear(false); - //BBS: check whether custom gcode changes the z position. Update if changed - double temp_z_after_tool_change; - if (GCodeProcessor::get_last_z_from_gcode(toolchange_gcode_parsed, temp_z_after_tool_change)) { - Vec3d pos = m_writer.get_position(); - pos(2) = temp_z_after_tool_change; - m_writer.set_position(pos); + + //BBS: check whether custom gcode changes the axis positions. Update if changed. + bool position_changed = false; + Vec3d new_pos = m_writer.get_position(); + + double temp_x_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_parsed, 0, temp_x_after_toolchange_gcode)) { + new_pos(0) = temp_x_after_toolchange_gcode; + position_changed = true; + } + + double temp_y_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_parsed, 1, temp_y_after_toolchange_gcode)) { + new_pos(1) = temp_y_after_toolchange_gcode; + position_changed = true; + } + + double temp_z_after_toolchange_gcode; + if (GCodeProcessor::get_last_pos_from_gcode(toolchange_gcode_parsed, 2, temp_z_after_toolchange_gcode)) { + new_pos(2) = temp_z_after_toolchange_gcode; + position_changed = true; + } + + if (position_changed) { + m_writer.set_position(new_pos); } } } @@ -6666,4 +6726,4 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr // a single object, or for possibly multiple objects with multiple instances. -} // namespace Slic3r +} /* slic3r_GCode_cpp_ */ From e781b4166c5dc39b211eea851148fad4bd26f7bb Mon Sep 17 00:00:00 2001 From: tsmith35 Date: Mon, 9 Sep 2024 15:40:12 -0500 Subject: [PATCH 2/6] Update GCodeProcessor.cpp --- src/libslic3r/GCode/GCodeProcessor.cpp | 41 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 757939637ed..28746c6e26c 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2185,13 +2185,14 @@ int GCodeProcessor::get_gcode_last_filament(const std::string& gcode_str) return out_filament; } -//BBS: get last z position from gcode -bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double& z) +//BBS: get last position from gcode for specified axis +//axis index is the same as Vec3d (X=0, Y=1, Z=2) +bool GCodeProcessor::get_last_pos_from_gcode(const std::string& gcode_str, int axis, double& pos) { int str_size = gcode_str.size(); int start_index = 0; int end_index = 0; - bool is_z_changed = false; + bool is_axis_changed = false; while (end_index < str_size) { //find a full line if (gcode_str[end_index] != '\n') { @@ -2211,24 +2212,32 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double& || line_str.find("G2 ") == 0 || line_str.find("G3 ") == 0)) { - auto z_pos = line_str.find(" Z"); - double temp_z = 0; - if (z_pos != line_str.npos - && z_pos + 2 < line_str.size()) { + std::string axis_str; + if (axis == 0) { + axis_str = "X"; + } else if (axis == 1) { + axis_str = "Y"; + } else if (axis == 2) { + axis_str = "Z"; + } + auto axis_pos = line_str.find(" " + axis_str); + double temp_axis_pos = 0; + if (axis_pos != line_str.npos + && axis_pos + 2 < line_str.size()) { // Try to parse the numeric value. - std::string z_sub = line_str.substr(z_pos + 2); - char* c = &z_sub[0]; - char* end = c + sizeof(z_sub.c_str()); + std::string axis_substr = line_str.substr(axis_pos + 2); + char* start_ptr = &axis_substr[0]; + char* end_ptr = start_ptr + sizeof(axis_substr.c_str()); auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; }; - auto [pend, ec] = fast_float::from_chars(c, end, temp_z); - if (pend != c && is_end_of_word(*pend)) { + auto [parsed_ptr, error_code] = fast_float::from_chars(start_ptr, end_ptr, temp_axis_pos); + if (parsed_ptr != start_ptr && is_end_of_word(*parsed_ptr)) { // The axis value has been parsed correctly. - z = temp_z; - is_z_changed = true; + pos = temp_axis_pos; + is_axis_changed = true; } } } @@ -2237,7 +2246,7 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double& start_index = end_index + 1; end_index = start_index; } - return is_z_changed; + return is_axis_changed; } void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled) @@ -5401,4 +5410,4 @@ void GCodeProcessor::update_slice_warnings() m_result.warnings.shrink_to_fit(); } -} /* namespace Slic3r */ +} /* slic3r_GCodeProcessor_cpp_ */ From f15e956ea880fa728fbc6ce3698fa21f859f54cc Mon Sep 17 00:00:00 2001 From: tsmith35 Date: Mon, 9 Sep 2024 15:40:46 -0500 Subject: [PATCH 3/6] Update GCodeProcessor.hpp --- src/libslic3r/GCode/GCodeProcessor.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 21403cc2053..937108edd31 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -303,7 +303,7 @@ class Print; static bool contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector& found_tag); static int get_gcode_last_filament(const std::string &gcode_str); - static bool get_last_z_from_gcode(const std::string& gcode_str, double& z); + static bool get_last_pos_from_gcode(const std::string& gcode_str, int axis, double& pos); static const float Wipe_Width; static const float Wipe_Height; @@ -984,5 +984,3 @@ class Print; } /* namespace Slic3r */ #endif /* slic3r_GCodeProcessor_hpp_ */ - - From 9c57683d1cd6e1caa489162a9a3af6f63e80196e Mon Sep 17 00:00:00 2001 From: tsmith35 Date: Mon, 9 Sep 2024 23:52:25 -0500 Subject: [PATCH 4/6] Clean up GCode.cpp --- src/libslic3r/GCode.cpp | 159 +++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 42 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ae8899a100f..abb81e79832 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3374,10 +3374,10 @@ namespace ProcessLayer } // namespace ProcessLayer namespace Skirt { - static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) + static void skirt_loops_per_extruder_all_printing(const Print &print, const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) { // Prime all extruders printing over the 1st layer over the skirt lines. - size_t n_loops = print.skirt().entities.size(); + size_t n_loops = skirt.entities.size(); size_t n_tools = layer_tools.extruders.size(); size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools; @@ -3395,6 +3395,7 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_1st_layer( const Print &print, + const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3404,8 +3405,8 @@ namespace Skirt { std::map> skirt_loops_per_extruder_out; //For sequential print, the following test may fail when extruding the 2nd and other objects. // assert(skirt_done.empty()); - if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) { - skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); + if (skirt_done.empty() && print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt) { + skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); skirt_done.emplace_back(layer_tools.print_z); } return skirt_loops_per_extruder_out; @@ -3413,6 +3414,7 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_other_layers( const Print &print, + const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3420,7 +3422,7 @@ namespace Skirt { // Extrude skirt at the print_z of the raft layers and normal object layers // not at the print_z of the interlaced support material layers. std::map> skirt_loops_per_extruder_out; - if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt && + if (print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt && // Not enough skirt layers printed yet. //FIXME infinite or high skirt does not make sense for sequential print! (skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt())) { @@ -3434,7 +3436,7 @@ namespace Skirt { skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair(0, print.config().skirt_loops.value); #else // Prime all extruders planned for this layer, see - skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); + skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); #endif assert(!skirt_done.empty()); skirt_done.emplace_back(layer_tools.print_z); @@ -3443,6 +3445,33 @@ namespace Skirt { return skirt_loops_per_extruder_out; } + static Point find_start_point(ExtrusionLoop& loop, float start_angle) { + coord_t min_x = std::numeric_limits::max(); + coord_t max_x = std::numeric_limits::min(); + coord_t min_y = min_x; + coord_t max_y = max_x; + + Points pts; + loop.collect_points(pts); + for (Point pt: pts) { + if (pt.x() < min_x) + min_x = pt.x(); + else if (pt.x() > max_x) + max_x = pt.x(); + if (pt.y() < min_y) + min_y = pt.y(); + else if (pt.y() > max_y) + max_y = pt.y(); + } + + Point center((min_x + max_x)/2., (min_y + max_y)/2.); + double r = center.distance_to(Point(min_x, min_y)); + double deg = start_angle * PI / 180; + double shift_x = r * std::cos(deg); + double shift_y = r * std::sin(deg); + return Point(center.x()+shift_x, center.y() + shift_y); + } + } // namespace Skirt // Orca: Klipper can't parse object names with spaces and other spetical characters @@ -3470,6 +3499,57 @@ inline std::string get_instance_name(const PrintObject *object, const PrintInsta return get_instance_name(object, inst.id); } +std::string GCode::generate_skirt(const Print &print, + const ExtrusionEntityCollection &skirt, + const Point& offset, + const LayerTools &layer_tools, + const Layer& layer, + unsigned int extruder_id) +{ + + bool first_layer = (layer.id() == 0 && abs(layer.bottom_z()) < EPSILON); + std::string gcode; + // Extrude skirt at the print_z of the raft layers and normal object layers + // not at the print_z of the interlaced support material layers. + // Map from extruder ID to index of skirt loops to be extruded with that extruder. + std::map> skirt_loops_per_extruder; + skirt_loops_per_extruder = first_layer ? + Skirt::make_skirt_loops_per_extruder_1st_layer(print, skirt, layer_tools, m_skirt_done) : + Skirt::make_skirt_loops_per_extruder_other_layers(print, skirt, layer_tools, m_skirt_done); + + if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { + const std::pair loops = loops_it->second; + + set_origin(unscaled(offset)); + + m_avoid_crossing_perimeters.use_external_mp(); + Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); + double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); + for (size_t i = first_layer ? loops.first : loops.second - 1; i < loops.second; ++i) { + // Adjust flow according to this layer's layer height. + ExtrusionLoop loop = *dynamic_cast(skirt.entities[i]); + for (ExtrusionPath &path : loop.paths) { + path.height = layer_skirt_flow.height(); + path.mm3_per_mm = mm3_per_mm; + } + + //set skirt start point location + if (first_layer && i==loops.first) + this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle)); + + //FIXME using the support_speed of the 1st object printed. + gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); + if (!first_layer) + break; + } + m_avoid_crossing_perimeters.use_external_mp(false); + // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). + if (first_layer && loops.first == 0) + m_avoid_crossing_perimeters.disable_once(); + } + return gcode; +} + // In sequential mode, process_layer is called once per each object and its copy, // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. // In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated. @@ -3741,18 +3821,10 @@ LayerResult GCode::process_layer( m_second_layer_things_done = true; } - // Map from extruder ID to index of skirt loops to be extruded with that extruder. - std::map> skirt_loops_per_extruder; - if (single_object_instance_idx == size_t(-1)) { // Normal (non-sequential) print. gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config()); } - // Extrude skirt at the print_z of the raft layers and normal object layers - // not at the print_z of the interlaced support material layers. - skirt_loops_per_extruder = first_layer ? - Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) : - Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done); // BBS: get next extruder according to flush and soluble auto get_next_extruder = [&](int current_extruder,const std::vector&extruders) { @@ -4038,28 +4110,7 @@ LayerResult GCode::process_layer( // let analyzer tag generator aware of a role type change if (layer_tools.has_wipe_tower && m_wipe_tower) m_last_processor_extrusion_role = erWipeTower; - - if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { - const std::pair loops = loops_it->second; - this->set_origin(0., 0.); - m_avoid_crossing_perimeters.use_external_mp(); - Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); - double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); - for (size_t i = (layer.id() == 0) ? loops.first : loops.second - 1; i < loops.second; ++i) { - // Adjust flow according to this layer's layer height. - ExtrusionLoop loop = *dynamic_cast(print.skirt().entities[i]); - for (ExtrusionPath &path : loop.paths) { path.height = layer_skirt_flow.height(); - path.mm3_per_mm = mm3_per_mm; - } - //FIXME using the support_speed of the 1st object printed. - gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); - } - m_avoid_crossing_perimeters.use_external_mp(false); - // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). - if (first_layer && loops.first == 0) - m_avoid_crossing_perimeters.disable_once(); - } auto objects_by_extruder_it = by_extruder.find(extruder_id); if (objects_by_extruder_it == by_extruder.end()) @@ -4094,8 +4145,17 @@ LayerResult GCode::process_layer( } // BBS - if (print.has_skirt() && print.config().print_sequence == PrintSequence::ByObject && prime_extruder && first_layer && extruder_id == first_extruder_id) { + if (print.config().skirt_type == stPerObject && + print.config().print_sequence == PrintSequence::ByObject && + !layer.object()->object_skirt().empty() && + ((layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) + ) + { for (InstanceToPrint& instance_to_print : instances_to_print) { + + if (instance_to_print.print_object.object_skirt().empty()) + continue; + if (this->m_objSupportsWithBrim.find(instance_to_print.print_object.id()) != this->m_objSupportsWithBrim.end() && print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; @@ -4103,12 +4163,14 @@ LayerResult GCode::process_layer( if (this->m_objsWithBrim.find(instance_to_print.print_object.id()) != this->m_objsWithBrim.end() && print.m_brimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; + if (first_layer) + m_skirt_done.clear(); + + if (layer.id() == 1 && m_skirt_done.size() > 1) + m_skirt_done.erase(m_skirt_done.begin()+1,m_skirt_done.end()); const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; - set_origin(unscaled(offset)); - for (ExtrusionEntity* ee : layer.object()->object_skirt().entities) - //FIXME using the support_speed of the 1st object printed. - gcode += this->extrude_entity(*ee, "skirt", m_config.support_speed.value); + gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); } } @@ -4117,7 +4179,22 @@ LayerResult GCode::process_layer( for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) { if (is_anything_overridden && print_wipe_extrusions == 0) gcode+="; PURGING FINISHED\n"; + for (InstanceToPrint &instance_to_print : instances_to_print) { + if (print.config().skirt_type == stPerObject && + !instance_to_print.print_object.object_skirt().empty() && + print.config().print_sequence == PrintSequence::ByLayer + && + (layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) + { + if (first_layer) + m_skirt_done.clear(); + const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; + gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); + if (instances_to_print.size() > 1 && &instance_to_print != &*(instances_to_print.end() - 1)) + m_skirt_done.pop_back(); + } + const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id]; const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; // To control print speed of the 1st object layer printed over raft interface. @@ -4129,7 +4206,6 @@ LayerResult GCode::process_layer( if (m_config.reduce_crossing_wall) m_avoid_crossing_perimeters.init_layer(*m_layer); -//------------------------------------------------------------------------------ std::string start_str; std::string start_str_a; std::string temp_start_str; @@ -4163,7 +4239,6 @@ LayerResult GCode::process_layer( if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic) m_extrusion_quality_estimator.set_current_object(&instance_to_print.print_object); -//------------------------------------------------------------------------------ // When starting a new object, use the external motion planner for the first travel move. const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; From 9cecd87525bdc33c6746ce408b4528629f1c9510 Mon Sep 17 00:00:00 2001 From: tsmith35 Date: Tue, 10 Sep 2024 00:00:37 -0500 Subject: [PATCH 5/6] More cleanup GCode.cpp --- src/libslic3r/GCode.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index abb81e79832..d80e2267094 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3506,7 +3506,7 @@ std::string GCode::generate_skirt(const Print &print, const Layer& layer, unsigned int extruder_id) { - + bool first_layer = (layer.id() == 0 && abs(layer.bottom_z()) < EPSILON); std::string gcode; // Extrude skirt at the print_z of the raft layers and normal object layers @@ -3519,7 +3519,7 @@ std::string GCode::generate_skirt(const Print &print, if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { const std::pair loops = loops_it->second; - + set_origin(unscaled(offset)); m_avoid_crossing_perimeters.use_external_mp(); @@ -4110,7 +4110,9 @@ LayerResult GCode::process_layer( // let analyzer tag generator aware of a role type change if (layer_tools.has_wipe_tower && m_wipe_tower) m_last_processor_extrusion_role = erWipeTower; - path.height = layer_skirt_flow.height(); + + if (print.config().skirt_type == stCombined && !print.skirt().empty()) + gcode += generate_skirt(print, print.skirt(), Point(0,0), layer_tools, layer, extruder_id); auto objects_by_extruder_it = by_extruder.find(extruder_id); if (objects_by_extruder_it == by_extruder.end()) @@ -4152,10 +4154,10 @@ LayerResult GCode::process_layer( ) { for (InstanceToPrint& instance_to_print : instances_to_print) { - + if (instance_to_print.print_object.object_skirt().empty()) continue; - + if (this->m_objSupportsWithBrim.find(instance_to_print.print_object.id()) != this->m_objSupportsWithBrim.end() && print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; @@ -4194,7 +4196,7 @@ LayerResult GCode::process_layer( if (instances_to_print.size() > 1 && &instance_to_print != &*(instances_to_print.end() - 1)) m_skirt_done.pop_back(); } - + const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id]; const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; // To control print speed of the 1st object layer printed over raft interface. From ecd92927593f0c1de39f4e5e01068ee26658acbc Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 11 Sep 2024 11:43:07 -0500 Subject: [PATCH 6/6] Add co-author Co-authored-by: Simon ziehmon@users.noreply.github.com --- src/libslic3r/GCode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index cd0a1680960..d1f813bd924 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -603,10 +603,10 @@ static std::vector get_path_of_change_filament(const Print& print) // BBS { check_add_eol(toolchange_gcode_str); - //BBS: gcode writer doesn't know fan speed after inserting tool change gcode + // BBS: gcode writer doesn't know fan speed after inserting tool change gcode toolchange_gcode_str += ";_FORCE_RESUME_FAN_SPEED\n"; - //BBS: check whether custom gcode changes the axis positions. Update if changed. + // BBS: check whether custom gcode changes the axis positions. Update if changed. bool position_changed = false; Vec3d new_pos = gcodegen.writer().get_position();