Wiping into infill/objects - invalidation of the wipe tower, bugfixes
This commit is contained in:
parent
73452fd79d
commit
b6455b66bd
@ -1357,7 +1357,7 @@ void GCode::process_layer(
|
|||||||
m_avoid_crossing_perimeters.disable_once = true;
|
m_avoid_crossing_perimeters.disable_once = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print.config.wipe_into_infill.value) {
|
{
|
||||||
gcode += "; INFILL WIPING STARTS\n";
|
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
|
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
|
for (const auto& layer_to_print : layers) { // iterate through all objects
|
||||||
@ -1373,12 +1373,12 @@ void GCode::process_layer(
|
|||||||
overridden.push_back(new_region);
|
overridden.push_back(new_region);
|
||||||
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) {
|
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) {
|
||||||
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
|
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(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);
|
overridden.back().infills.append(*fill);
|
||||||
}
|
}
|
||||||
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->perimeters.entities) {
|
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->perimeters.entities) {
|
||||||
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
|
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(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);
|
overridden.back().perimeters.append((*fill).entities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2527,12 +2527,13 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
|||||||
by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region());
|
by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region());
|
||||||
//out.back().perimeters.append(reg.perimeters); // we will print all perimeters there are
|
//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<reg.infills_per_copy_ids[copy].size(); ++i)
|
for (unsigned int i=0; i<reg.infills_per_copy_ids[copy].size(); ++i)
|
||||||
by_region_per_copy_cache.back().infills.append(*(reg.infills.entities[reg.infills_per_copy_ids[copy][i]]));
|
by_region_per_copy_cache.back().infills.append(*(reg.infills.entities[reg.infills_per_copy_ids[copy][i]]));
|
||||||
|
|
||||||
|
if (!reg.perimeters_per_copy_ids.empty())
|
||||||
for (unsigned int i=0; i<reg.perimeters_per_copy_ids[copy].size(); ++i)
|
for (unsigned int i=0; i<reg.perimeters_per_copy_ids[copy].size(); ++i)
|
||||||
by_region_per_copy_cache.back().perimeters.append(*(reg.perimeters.entities[reg.perimeters_per_copy_ids[copy][i]]));
|
by_region_per_copy_cache.back().perimeters.append(*(reg.perimeters.entities[reg.perimeters_per_copy_ids[copy][i]]));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return by_region_per_copy_cache;
|
return by_region_per_copy_cache;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,11 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||||||
std::vector<PrintStep> steps;
|
std::vector<PrintStep> steps;
|
||||||
std::vector<PrintObjectStep> osteps;
|
std::vector<PrintObjectStep> osteps;
|
||||||
bool invalidated = false;
|
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) {
|
for (const t_config_option_key &opt_key : opt_keys) {
|
||||||
if (steps_ignore.find(opt_key) != steps_ignore.end()) {
|
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,
|
// 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<t_config_option
|
|||||||
|| opt_key == "wipe_tower_rotation_angle"
|
|| opt_key == "wipe_tower_rotation_angle"
|
||||||
|| opt_key == "wipe_tower_bridging"
|
|| opt_key == "wipe_tower_bridging"
|
||||||
|| opt_key == "wiping_volumes_matrix"
|
|| opt_key == "wiping_volumes_matrix"
|
||||||
|| opt_key == "parking_pos_retraction"
|
|| opt_key == u8"parking_pos_retraction"
|
||||||
|| opt_key == "cooling_tube_retraction"
|
|| opt_key == "cooling_tube_retraction"
|
||||||
|| opt_key == "cooling_tube_length"
|
|| opt_key == "cooling_tube_length"
|
||||||
|| opt_key == "extra_loading_move"
|
|| opt_key == "extra_loading_move"
|
||||||
@ -216,7 +221,6 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||||||
osteps.emplace_back(posSupportMaterial);
|
osteps.emplace_back(posSupportMaterial);
|
||||||
steps.emplace_back(psSkirt);
|
steps.emplace_back(psSkirt);
|
||||||
steps.emplace_back(psBrim);
|
steps.emplace_back(psBrim);
|
||||||
steps.emplace_back(psWipeTower);
|
|
||||||
} else {
|
} else {
|
||||||
// for legacy, if we can't handle this option let's invalidate all steps
|
// for legacy, if we can't handle this option let's invalidate all steps
|
||||||
//FIXME invalidate all steps of all objects as well?
|
//FIXME invalidate all steps of all objects as well?
|
||||||
@ -1125,6 +1129,7 @@ void Print::_make_wipe_tower()
|
|||||||
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||||
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full));
|
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
|
// 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)
|
// 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) {
|
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
|
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)
|
if (!first_layer) // unless we're on the first layer, try to assign some infills/objects for the wiping:
|
||||||
volume_to_wipe = mark_wiping_infill(layer_tools, extruder_id, wipe_volumes[current_extruder_id][extruder_id]);
|
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);
|
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;
|
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
|
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
|
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...
|
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;
|
Layer* this_layer = nullptr;
|
||||||
for (unsigned int a = 0; a < objects[i]->layers.size(); ++a) // Finds this layer
|
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) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills;
|
if (objects[i]->config.wipe_into_infill) {
|
||||||
for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections
|
ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills;
|
||||||
auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
|
for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections
|
||||||
if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible
|
auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
|
||||||
if (volume_to_wipe <= 0.f)
|
if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible
|
||||||
break;
|
if (volume_to_wipe <= 0.f)
|
||||||
if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder
|
break;
|
||||||
fill->set_extruder_override(copy, new_extruder);
|
if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder
|
||||||
volume_to_wipe -= fill->total_volume();
|
fill->set_extruder_override(copy, new_extruder);
|
||||||
}
|
volume_to_wipe -= fill->total_volume();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objects[i]->config.wipe_into_objects)
|
if (objects[i]->config.wipe_into_objects)
|
||||||
|
@ -317,7 +317,10 @@ private:
|
|||||||
|
|
||||||
// This function goes through all infill entities, decides which ones will be used for wiping and
|
// 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:
|
// 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?
|
// Has the calculation been canceled?
|
||||||
tbb::atomic<bool> m_canceled;
|
tbb::atomic<bool> m_canceled;
|
||||||
|
@ -1886,6 +1886,7 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
def->default_value = new ConfigOptionFloat(0.);
|
def->default_value = new ConfigOptionFloat(0.);
|
||||||
|
|
||||||
def = this->add("wipe_into_infill", coBool);
|
def = this->add("wipe_into_infill", coBool);
|
||||||
|
def->category = L("Extruders");
|
||||||
def->label = L("Wiping into infill");
|
def->label = L("Wiping into infill");
|
||||||
def->tooltip = L("Wiping after toolchange will be preferentially done inside infills. "
|
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 "
|
"This lowers the amount of waste but may result in longer print time "
|
||||||
|
@ -337,6 +337,7 @@ public:
|
|||||||
ConfigOptionFloatOrPercent support_material_xy_spacing;
|
ConfigOptionFloatOrPercent support_material_xy_spacing;
|
||||||
ConfigOptionFloat xy_size_compensation;
|
ConfigOptionFloat xy_size_compensation;
|
||||||
ConfigOptionBool wipe_into_objects;
|
ConfigOptionBool wipe_into_objects;
|
||||||
|
ConfigOptionBool wipe_into_infill;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||||
@ -374,6 +375,7 @@ protected:
|
|||||||
OPT_PTR(support_material_with_sheath);
|
OPT_PTR(support_material_with_sheath);
|
||||||
OPT_PTR(xy_size_compensation);
|
OPT_PTR(xy_size_compensation);
|
||||||
OPT_PTR(wipe_into_objects);
|
OPT_PTR(wipe_into_objects);
|
||||||
|
OPT_PTR(wipe_into_infill);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -644,7 +646,6 @@ public:
|
|||||||
ConfigOptionFloat wipe_tower_per_color_wipe;
|
ConfigOptionFloat wipe_tower_per_color_wipe;
|
||||||
ConfigOptionFloat wipe_tower_rotation_angle;
|
ConfigOptionFloat wipe_tower_rotation_angle;
|
||||||
ConfigOptionFloat wipe_tower_bridging;
|
ConfigOptionFloat wipe_tower_bridging;
|
||||||
ConfigOptionBool wipe_into_infill;
|
|
||||||
ConfigOptionFloats wiping_volumes_matrix;
|
ConfigOptionFloats wiping_volumes_matrix;
|
||||||
ConfigOptionFloats wiping_volumes_extruders;
|
ConfigOptionFloats wiping_volumes_extruders;
|
||||||
ConfigOptionFloat z_offset;
|
ConfigOptionFloat z_offset;
|
||||||
@ -713,7 +714,6 @@ protected:
|
|||||||
OPT_PTR(wipe_tower_width);
|
OPT_PTR(wipe_tower_width);
|
||||||
OPT_PTR(wipe_tower_per_color_wipe);
|
OPT_PTR(wipe_tower_per_color_wipe);
|
||||||
OPT_PTR(wipe_tower_rotation_angle);
|
OPT_PTR(wipe_tower_rotation_angle);
|
||||||
OPT_PTR(wipe_into_infill);
|
|
||||||
OPT_PTR(wipe_tower_bridging);
|
OPT_PTR(wipe_tower_bridging);
|
||||||
OPT_PTR(wiping_volumes_matrix);
|
OPT_PTR(wiping_volumes_matrix);
|
||||||
OPT_PTR(wiping_volumes_extruders);
|
OPT_PTR(wiping_volumes_extruders);
|
||||||
|
@ -231,7 +231,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
|||||||
|| opt_key == "perimeter_speed"
|
|| opt_key == "perimeter_speed"
|
||||||
|| opt_key == "small_perimeter_speed"
|
|| opt_key == "small_perimeter_speed"
|
||||||
|| opt_key == "solid_infill_speed"
|
|| opt_key == "solid_infill_speed"
|
||||||
|| opt_key == "top_solid_infill_speed") {
|
|| opt_key == "top_solid_infill_speed"
|
||||||
|
|| opt_key == "wipe_into_infill" // when these these two are changed, we only need to invalidate the wipe tower,
|
||||||
|
|| opt_key == "wipe_into_objects" // which we already did at the very beginning - nothing more to be done
|
||||||
|
) {
|
||||||
// these options only affect G-code export, so nothing to invalidate
|
// these options only affect G-code export, so nothing to invalidate
|
||||||
} else {
|
} else {
|
||||||
// for legacy, if we can't handle this option let's invalidate all steps
|
// for legacy, if we can't handle this option let's invalidate all steps
|
||||||
@ -271,6 +274,8 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
||||||
|
// It also decides about what the wipe_into_infill / wipe_into_object features will do,
|
||||||
|
// and that too depends on many of the settings.
|
||||||
invalidated |= this->_print->invalidate_step(psWipeTower);
|
invalidated |= this->_print->invalidate_step(psWipeTower);
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user