diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 92898c820..ce63a374c 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1357,7 +1357,7 @@ void GCode::process_layer( m_avoid_crossing_perimeters.disable_once = true; } - if (print.config.wipe_into_infill.value) { + { gcode += "; INFILL WIPING STARTS\n"; if (extruder_id != layer_tools.extruders.front()) { // if this is the first extruder on this layer, there was no toolchange for (const auto& layer_to_print : layers) { // iterate through all objects @@ -1373,12 +1373,12 @@ void GCode::process_layer( overridden.push_back(new_region); for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) { auto *fill = dynamic_cast(ee); - if (fill->get_extruder_override(copy_id) == (unsigned int)extruder_id) + if (fill->get_extruder_override(copy_id) == (int)extruder_id) overridden.back().infills.append(*fill); } for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->perimeters.entities) { auto *fill = dynamic_cast(ee); - if (fill->get_extruder_override(copy_id) == (unsigned int)extruder_id) + if (fill->get_extruder_override(copy_id) == (int)extruder_id) overridden.back().perimeters.append((*fill).entities); } } @@ -2527,12 +2527,13 @@ const std::vector& GCode::ObjectByExtru by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region()); //out.back().perimeters.append(reg.perimeters); // we will print all perimeters there are - if (!reg.infills_per_copy_ids.empty()) { + if (!reg.infills_per_copy_ids.empty()) for (unsigned int i=0; i steps; std::vector osteps; bool invalidated = false; + + // Always invalidate the wipe tower. This is probably necessary because of the wipe_into_infill / wipe_into_objects + // features - nearly anything can influence what should (and could) be wiped into. + steps.emplace_back(psWipeTower); + for (const t_config_option_key &opt_key : opt_keys) { if (steps_ignore.find(opt_key) != steps_ignore.end()) { // These options only affect G-code export or they are just notes without influence on the generated G-code, @@ -201,7 +206,7 @@ bool Print::invalidate_state_by_config_options(const std::vector( wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full)); + reset_wiping_extrusions(); // if this is not the first time the wipe tower is generated, some extrusions might remember their last wiping status // Lets go through the wipe tower layers and determine pairs of extruder changes for each // to pass to wipe_tower (so that it can use it for planning the layout of the tower) @@ -1138,8 +1143,8 @@ void Print::_make_wipe_tower() if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange - if (config.wipe_into_infill && !first_layer) - volume_to_wipe = mark_wiping_infill(layer_tools, extruder_id, wipe_volumes[current_extruder_id][extruder_id]); + if (!first_layer) // unless we're on the first layer, try to assign some infills/objects for the wiping: + volume_to_wipe = mark_wiping_extrusions(layer_tools, extruder_id, wipe_volumes[current_extruder_id][extruder_id]); wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe); current_extruder_id = extruder_id; @@ -1176,12 +1181,31 @@ void Print::_make_wipe_tower() -float Print::mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe) +void Print::reset_wiping_extrusions() { + for (size_t i = 0; i < objects.size(); ++ i) { + for (auto& this_layer : objects[i]->layers) { + for (size_t region_id = 0; region_id < objects[i]->print()->regions.size(); ++ region_id) { + for (unsigned int copy = 0; copy < objects[i]->_shifted_copies.size(); ++copy) { + this_layer->regions[region_id]->fills.set_extruder_override(copy, -1); + this_layer->regions[region_id]->perimeters.set_extruder_override(copy, -1); + } + } + } + } +} + + + +float Print::mark_wiping_extrusions(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe) { const float min_infill_volume = 0.f; // ignore infill with smaller volume than this if (!config.filament_soluble.get_at(new_extruder)) { // Soluble filament cannot be wiped in a random infill for (size_t i = 0; i < objects.size(); ++ i) { // Let's iterate through all objects... + + if (!objects[i]->config.wipe_into_infill && !objects[i]->config.wipe_into_objects) + continue; + Layer* this_layer = nullptr; for (unsigned int a = 0; a < objects[i]->layers.size(); ++a) // Finds this layer if (std::abs(layer_tools.print_z - objects[i]->layers[a]->print_z) < EPSILON) { @@ -1210,16 +1234,18 @@ float Print::mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, uns continue; } - ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills; - for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections - auto* fill = dynamic_cast(ee); - if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible - if (volume_to_wipe <= 0.f) - break; - if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder - fill->set_extruder_override(copy, new_extruder); - volume_to_wipe -= fill->total_volume(); - } + if (objects[i]->config.wipe_into_infill) { + ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills; + for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections + auto* fill = dynamic_cast(ee); + if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible + if (volume_to_wipe <= 0.f) + break; + if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder + fill->set_extruder_override(copy, new_extruder); + volume_to_wipe -= fill->total_volume(); + } + } } if (objects[i]->config.wipe_into_objects) diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 77b47fb83..77787063e 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -317,7 +317,10 @@ private: // This function goes through all infill entities, decides which ones will be used for wiping and // marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower: - float mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe); + float mark_wiping_extrusions(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe); + + // A function to go through all entities and unsets their extruder_override flag + void reset_wiping_extrusions(); // Has the calculation been canceled? tbb::atomic m_canceled; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 98b111a4d..d00f7974e 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1886,6 +1886,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloat(0.); def = this->add("wipe_into_infill", coBool); + def->category = L("Extruders"); def->label = L("Wiping into infill"); def->tooltip = L("Wiping after toolchange will be preferentially done inside infills. " "This lowers the amount of waste but may result in longer print time " diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index f638a7674..92ead2927 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -337,6 +337,7 @@ public: ConfigOptionFloatOrPercent support_material_xy_spacing; ConfigOptionFloat xy_size_compensation; ConfigOptionBool wipe_into_objects; + ConfigOptionBool wipe_into_infill; protected: void initialize(StaticCacheBase &cache, const char *base_ptr) @@ -374,6 +375,7 @@ protected: OPT_PTR(support_material_with_sheath); OPT_PTR(xy_size_compensation); OPT_PTR(wipe_into_objects); + OPT_PTR(wipe_into_infill); } }; @@ -644,7 +646,6 @@ public: ConfigOptionFloat wipe_tower_per_color_wipe; ConfigOptionFloat wipe_tower_rotation_angle; ConfigOptionFloat wipe_tower_bridging; - ConfigOptionBool wipe_into_infill; ConfigOptionFloats wiping_volumes_matrix; ConfigOptionFloats wiping_volumes_extruders; ConfigOptionFloat z_offset; @@ -713,7 +714,6 @@ protected: OPT_PTR(wipe_tower_width); OPT_PTR(wipe_tower_per_color_wipe); OPT_PTR(wipe_tower_rotation_angle); - OPT_PTR(wipe_into_infill); OPT_PTR(wipe_tower_bridging); OPT_PTR(wiping_volumes_matrix); OPT_PTR(wiping_volumes_extruders); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index b0341db16..1c403acdb 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -231,7 +231,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector_print->invalidate_step(psWipeTower); return invalidated; }