diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 97636b4a6..1eaca59d6 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2229,7 +2229,7 @@ void GCode::process_layer( const std::pair loops = loops_it->second; this->set_origin(0., 0.); m_avoid_crossing_perimeters.use_external_mp = true; - Flow layer_skirt_flow(print.skirt_flow()); + Flow layer_skirt_flow(print.skirt_flow(extruder_id)); layer_skirt_flow.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 = loops.first; i < loops.second; ++i) { diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 34b57dcda..a77da4966 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -130,7 +130,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool // Do it only if all the objects were configured to be printed with a single extruder. std::vector> per_layer_extruder_switches; if (auto num_extruders = unsigned(print.config().nozzle_diameter.size()); - num_extruders > 1 && print.object_extruders().size() == 1 && // the current Print's configuration is CustomGCode::MultiAsSingle + num_extruders > 1 && print.object_extruders(print.objects()).size() == 1 && // the current Print's configuration is CustomGCode::MultiAsSingle print.model().custom_gcode_per_print_z.mode == CustomGCode::MultiAsSingle) { // Printing a single extruder platter on a printer with more than 1 extruder (or single-extruder multi-material). // There may be custom per-layer tool changes available at the model. @@ -468,7 +468,7 @@ void ToolOrdering::assign_custom_gcodes(const Print &print) auto num_extruders = unsigned(print.config().nozzle_diameter.size()); CustomGCode::Mode mode = (num_extruders == 1) ? CustomGCode::SingleExtruder : - print.object_extruders().size() == 1 ? CustomGCode::MultiAsSingle : CustomGCode::MultiExtruder; + print.object_extruders(print.objects()).size() == 1 ? CustomGCode::MultiAsSingle : CustomGCode::MultiExtruder; CustomGCode::Mode model_mode = print.model().custom_gcode_per_print_z.mode; std::vector extruder_printing_above(num_extruders, false); auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin(); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 267c16c73..b96efad71 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -302,12 +302,12 @@ bool Print::is_step_done(PrintObjectStep step) const } // returns 0-based indices of used extruders -std::vector Print::object_extruders() const +std::vector Print::object_extruders(const PrintObjectPtrs &objects) const { std::vector extruders; extruders.reserve(m_regions.size() * 3); std::vector region_used(m_regions.size(), false); - for (const PrintObject *object : m_objects) + for (const PrintObject *object : objects) for (const std::vector> &volumes_per_region : object->region_volumes) if (! volumes_per_region.empty()) region_used[&volumes_per_region - &object->region_volumes.front()] = true; @@ -346,7 +346,7 @@ std::vector Print::support_material_extruders() const if (support_uses_current_extruder) // Add all object extruders to the support extruders as it is not know which one will be used to print supports. - append(extruders, this->object_extruders()); + append(extruders, this->object_extruders(m_objects)); sort_remove_duplicates(extruders); return extruders; @@ -355,7 +355,7 @@ std::vector Print::support_material_extruders() const // returns 0-based indices of used extruders std::vector Print::extruders() const { - std::vector extruders = this->object_extruders(); + std::vector extruders = this->object_extruders(m_objects); append(extruders, this->support_material_extruders()); sort_remove_duplicates(extruders); return extruders; @@ -1544,7 +1544,7 @@ double Print::skirt_first_layer_height() const return m_objects.front()->config().get_abs_value("first_layer_height"); } -Flow Print::brim_flow() const +Flow Print::brim_flow(size_t extruder_id) const { ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width; if (width.value <= 0) @@ -1560,13 +1560,13 @@ Flow Print::brim_flow() const return Flow::new_from_config_width( frPerimeter, width, - (float)m_config.nozzle_diameter.get_at(m_regions.front()->config().perimeter_extruder-1), + (float)m_config.nozzle_diameter.get_at(extruder_id), (float)this->skirt_first_layer_height(), 0 ); } -Flow Print::skirt_flow() const +Flow Print::skirt_flow(size_t extruder_id) const { ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width; if (width.value <= 0) @@ -1582,7 +1582,7 @@ Flow Print::skirt_flow() const return Flow::new_from_config_width( frPerimeter, width, - (float)m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1), + (float)m_config.nozzle_diameter.get_at(extruder_id), (float)this->skirt_first_layer_height(), 0 ); @@ -1811,17 +1811,19 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio // but loops must be aligned so can't vary width/spacing // TODO: use each extruder's own flow double first_layer_height = this->skirt_first_layer_height(); - Flow flow = this->skirt_flow(); - float spacing = flow.spacing(); - double mm3_per_mm = flow.mm3_per_mm(); std::vector extruders; std::vector extruders_e_per_mm; { - auto set_extruders = this->extruders(); + std::vector set_extruders = this->object_extruders(objects); + append(set_extruders, this->support_material_extruders()); + sort_remove_duplicates(set_extruders); extruders.reserve(set_extruders.size()); extruders_e_per_mm.reserve(set_extruders.size()); - for (auto &extruder_id : set_extruders) { + for (unsigned int extruder_id : set_extruders) { + Flow flow = this->skirt_flow(extruder_id); + float spacing = flow.spacing(); + double mm3_per_mm = flow.mm3_per_mm(); extruders.push_back(extruder_id); extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &m_config).e_per_mm(mm3_per_mm)); } @@ -1834,14 +1836,21 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. - auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.); + auto distance = float(scale_(m_config.skirt_distance.value) - this->skirt_flow(extruders[extruders.size()-1]).spacing()/2.); + + size_t lines_per_extruder = (n_skirts + extruders.size() - 1) / extruders.size(); + size_t current_lines_per_extruder = n_skirts - lines_per_extruder * (extruders.size() - 1); + // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); - for (size_t i = n_skirts, extruder_idx = 0; i > 0; -- i) { + for (size_t i = n_skirts, extruder_idx = 0, nb_skirts = 1; i > 0; -- i) { + Flow flow = this->skirt_flow(extruders[extruders.size() - (1+ extruder_idx)]); + float spacing = flow.spacing(); + double mm3_per_mm = flow.mm3_per_mm(); this->throw_if_canceled(); // Offset the skirt outside. - distance += float(scale_(spacing)); + distance += float(scale_(spacing/2)); // Generate the skirt centerline. Polygon loop; { @@ -1851,6 +1860,7 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio break; loop = loops.front(); } + distance += float(scale_(spacing / 2)); // Extrude the skirt loop. ExtrusionLoop eloop(elrSkirt); eloop.paths.emplace_back(ExtrusionPath( @@ -1876,7 +1886,13 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio // Enough extruded with the current extruder. Extrude with the next one, // until the prescribed number of skirt loops is extruded. if (extruder_idx + 1 < extruders.size()) - ++ extruder_idx; + if (nb_skirts < current_lines_per_extruder) { + nb_skirts++; + } else { + current_lines_per_extruder = lines_per_extruder; + nb_skirts = 1; + ++extruder_idx; + } } } else { // The skirt lenght is not limited, extrude the skirt with the 1st extruder only. @@ -1889,7 +1905,12 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio //TODO: test if no regression vs old _make_brim. // this new one can extrude brim for an object inside an other object. ExPolygons Print::_make_brim(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out) { - Flow flow = this->brim_flow(); + //get the first extruder in the list for these objects... TODO: replicate gcode generation + std::vector set_extruders = this->object_extruders(objects); + append(set_extruders, this->support_material_extruders()); + sort_remove_duplicates(set_extruders); + Flow flow = this->brim_flow(set_extruders.empty()?m_regions.front()->config().perimeter_extruder - 1: set_extruders.front()); + coord_t brim_offset = scale_(config().brim_offset.value); ExPolygons islands; for (PrintObject *object : objects) { @@ -2024,7 +2045,12 @@ ExPolygons Print::_make_brim(const PrintObjectPtrs &objects, ExtrusionEntityColl } ExPolygons Print::_make_brim_ears(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out) { - Flow flow = this->brim_flow(); + //get the first extruder in the list for these objects... TODO: replicate gcode generation + std::vector set_extruders = this->object_extruders(objects); + append(set_extruders, this->support_material_extruders()); + sort_remove_duplicates(set_extruders); + Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front()); + Points pt_ears; coord_t brim_offset = scale_(config().brim_offset.value); ExPolygons islands; @@ -2113,7 +2139,7 @@ ExPolygons Print::_make_brim_ears(const PrintObjectPtrs &objects, ExtrusionEntit this->throw_if_canceled(); //reorder & extrude them - Polylines lines_sorted = _reorder_brim_polyline(lines, out); + Polylines lines_sorted = _reorder_brim_polyline(lines, out, flow); //push into extrusions extrusion_entities_append_paths( @@ -2130,7 +2156,13 @@ ExPolygons Print::_make_brim_ears(const PrintObjectPtrs &objects, ExtrusionEntit ExPolygons Print::_make_brim_interior(const PrintObjectPtrs &objects, const ExPolygons &unbrimmable_areas, ExtrusionEntityCollection &out) { // Brim is only printed on first layer and uses perimeter extruder. - Flow flow = this->brim_flow(); + + //get the first extruder in the list for these objects... TODO: replicate gcode generation + std::vector set_extruders = this->object_extruders(objects); + append(set_extruders, this->support_material_extruders()); + sort_remove_duplicates(set_extruders); + Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front()); + coord_t brim_offset = scale_(config().brim_offset.value); ExPolygons islands; for (PrintObject *object : objects) { @@ -2219,9 +2251,7 @@ ExPolygons Print::_make_brim_interior(const PrintObjectPtrs &objects, const ExPo } /// reorder & join polyline if their ending are near enough, then extrude the brim from the polyline into 'out'. -Polylines Print::_reorder_brim_polyline(Polylines lines, ExtrusionEntityCollection &out) { - Flow flow = this->brim_flow(); - +Polylines Print::_reorder_brim_polyline(Polylines lines, ExtrusionEntityCollection &out, const Flow &flow) { //reorder them std::sort(lines.begin(), lines.end(), [](const Polyline &a, const Polyline &b)->bool { return a.closest_point(Point(0, 0))->y() < b.closest_point(Point(0, 0))->y(); }); Polylines lines_sorted; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 1b15466c7..64dbab4f5 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -399,10 +399,10 @@ public: // Returns an empty string if valid, otherwise returns an error message. std::string validate() const override; double skirt_first_layer_height() const; - Flow brim_flow() const; - Flow skirt_flow() const; + Flow brim_flow(size_t extruder_id) const; + Flow skirt_flow(size_t extruder_id) const; - std::vector object_extruders() const; + std::vector object_extruders(const PrintObjectPtrs &objects) const; std::vector support_material_extruders() const; std::vector extruders() const; double max_allowed_layer_height() const; @@ -460,7 +460,7 @@ private: ExPolygons _make_brim(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out); ExPolygons _make_brim_ears(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out); ExPolygons _make_brim_interior(const PrintObjectPtrs &objects, const ExPolygons &unbrimmable, ExtrusionEntityCollection &out); - Polylines _reorder_brim_polyline(Polylines lines, ExtrusionEntityCollection &out); + Polylines _reorder_brim_polyline(Polylines lines, ExtrusionEntityCollection &out, const Flow &flow); void _make_wipe_tower(); // Declared here to have access to Model / ModelObject / ModelInstance diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 16d085172..97ad38fc6 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -172,7 +172,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object m_can_merge_support_regions = m_object_config->support_material_extruder.value == m_object_config->support_material_interface_extruder.value; if (! m_can_merge_support_regions && (m_object_config->support_material_extruder.value == 0 || m_object_config->support_material_interface_extruder.value == 0)) { // One of the support extruders is of "don't care" type. - auto object_extruders = m_object->print()->object_extruders(); + auto object_extruders = m_object->print()->object_extruders(m_object->print()->objects()); if (object_extruders.size() == 1 && *object_extruders.begin() == std::max(m_object_config->support_material_extruder.value, m_object_config->support_material_interface_extruder.value)) // Object is printed with the same extruder as the support.