diff --git a/src/libslic3r/Extruder.hpp b/src/libslic3r/Extruder.hpp index df92bf84b31..066a5f56d25 100644 --- a/src/libslic3r/Extruder.hpp +++ b/src/libslic3r/Extruder.hpp @@ -48,9 +48,6 @@ class Extruder double retract_length_toolchange() const; double retract_restart_extra_toolchange() const; - // Constructor for a key object, to be used by the stdlib search functions. - static Extruder key(unsigned int id) { return Extruder(id); } - private: // Private constructor to create a key for a search in std::set. Extruder(unsigned int id) : m_id(id) {} diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 942558f2725..5d0a0d4d958 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1133,11 +1133,9 @@ void GCode::_do_export(Print& print, FILE* file) m_enable_cooling_markers = true; this->apply_print_config(print.config()); - this->set_extruders(print.extruders()); - // Initialize custom gcode - Model* model = print.get_object(0)->model_object()->get_model(); - m_custom_gcode_per_print_z = model->custom_gcode_per_print_z; + // Initialize custom gcode iterator. + m_custom_gcode_per_print_z_it = print.model().custom_gcode_per_print_z.cbegin(); m_volumetric_speed = DoExport::autospeed_volumetric_limit(print); print.throw_if_canceled(); @@ -1221,18 +1219,27 @@ void GCode::_do_export(Print& print, FILE* file) if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1) break; } + // We don't allow switching of extruders per layer by Model::custom_gcode_per_print_z in sequential mode. + // Use the extruder IDs collected from Regions. + this->set_extruders(print.extruders()); } else { // 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.wipe_tower_data().tool_ordering.empty() ? - ToolOrdering(print, initial_extruder_id) : + ToolOrdering(print, initial_extruder_id, false, + // Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object. + // Do it only if all the objects were configured to be printed with a single extruder. + (print.object_extruders().size() == 1) ? &custom_tool_changes(print.model(), (unsigned int)m_config.nozzle_diameter.size()) : nullptr) : print.wipe_tower_data().tool_ordering; has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower(); - initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ? + initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ? // The priming towers will be skipped. tool_ordering.all_extruders().back() : - // Don't skip the priming towers. + // Don't skip the priming towers. tool_ordering.first_extruder(); + // In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z. + // Therefore initialize the printing extruders from there. + this->set_extruders(tool_ordering.all_extruders()); } if (initial_extruder_id == (unsigned int)-1) { // Nothing to print! @@ -1247,7 +1254,7 @@ void GCode::_do_export(Print& print, FILE* file) // #ys_FIXME_no_exported_codes /* /* To avoid change filament for non-used extruder for Multi-material, - * check model->custom_gcode_per_print_z using tool_ordering values + * check print.model().custom_gcode_per_print_z using tool_ordering values * / if (!m_custom_gcode_per_print_z. empty()) { @@ -1283,7 +1290,7 @@ void GCode::_do_export(Print& print, FILE* file) } if (delete_executed) - model->custom_gcode_per_print_z = m_custom_gcode_per_print_z; + print.model().custom_gcode_per_print_z = m_custom_gcode_per_print_z; } */ @@ -1768,6 +1775,174 @@ std::vector GCode::sort_print_object_instances( return out; } +namespace ProcessLayer +{ + + std::string emit_custom_gcode_per_print_z( + // Last processed CustomGCode. + std::vector::const_iterator &custom_gcode_per_print_z_it, + const std::vector::const_iterator custom_gcode_per_print_z_end, + // This layer's print_z. + coordf_t current_print_z, + // ID of the first extruder printing this layer. + unsigned int first_extruder_id, + size_t num_extruders) + { + // Let's issue a filament change command if requested at this layer. + // In case there are more toolchange requests that weren't done yet and should happen simultaneously, erase them all. + // (Layers can be close to each other, model could have been resliced with bigger layer height, ...). + bool has_colorchange = false; + + std::string custom_code; + std::string pause_print_msg; + int m600_before_extruder = -1; + while (custom_gcode_per_print_z_it != custom_gcode_per_print_z_end) { + auto it_next = custom_gcode_per_print_z_it; + if ((++ it_next)->print_z >= current_print_z + EPSILON) + break; + custom_gcode_per_print_z_it = it_next; + } + if (custom_gcode_per_print_z_it != custom_gcode_per_print_z_end && custom_gcode_per_print_z_it->print_z < current_print_z + EPSILON) { + custom_code = custom_gcode_per_print_z_it->gcode; + + if (custom_code == ColorChangeCode && custom_gcode_per_print_z_it->extruder > 0) + m600_before_extruder = custom_gcode_per_print_z_it->extruder - 1; + if (custom_code == PausePrintCode) + pause_print_msg = custom_gcode_per_print_z_it->color; + + // This color change is consumed, don't use it again. + ++ custom_gcode_per_print_z_it; + has_colorchange = true; + } + + // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count + + // don't save "tool_change"(ExtruderChangeCode) code to GCode + std::string gcode; + if (has_colorchange && custom_code != ExtruderChangeCode) { + const bool single_material_print = num_extruders == 1; + + if (custom_code == ColorChangeCode) // color change + { + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_before_extruder) + "\n"; + // add tag for time estimator + gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n"; + + if (!single_material_print && m600_before_extruder >= 0 && first_extruder_id != m600_before_extruder + // && !MMU1 + ) { + //! FIXME_in_fw show message during print pause + gcode += "M601\n"; // pause print + gcode += "M117 Change filament for Extruder " + std::to_string(m600_before_extruder) + "\n"; + } + else + gcode += custom_code + "\n"; + } + else + { + if (custom_code == PausePrintCode) // Pause print + { + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n"; + //! FIXME_in_fw show message during print pause + if (!pause_print_msg.empty()) + gcode += "M117 " + pause_print_msg + "\n"; + // add tag for time estimator + //gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; + } + else // custom Gcode + { + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n"; + // add tag for time estimator + //gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n"; + } + gcode += custom_code + "\n"; + } + } + + return gcode; + } +} // namespace ProcessLayer + +namespace Skirt { + std::map> make_skirt_loops_per_extruder_1st_layer( + const Print &print, + const std::vector &layers, + const LayerTools &layer_tools, + std::vector extruder_ids, + // Heights at which the skirt has already been extruded. + std::vector &skirt_done) + { + // 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; + assert(skirt_done.empty()); + if (print.has_skirt() && ! print.skirt().entities.empty()) { + // Prime all the printing extruders over the skirt lines. + // Reorder the extruders, so that the last used extruder is at the front. + unsigned int first_extruder_id = layer_tools.extruders.front(); + for (size_t i = 1; i < extruder_ids.size(); ++ i) + if (extruder_ids[i] == first_extruder_id) { + // Move the last extruder to the front. + memmove(extruder_ids.data() + 1, extruder_ids.data(), i * sizeof(unsigned int)); + extruder_ids.front() = first_extruder_id; + break; + } + size_t n_loops = print.skirt().entities.size(); + if (n_loops <= extruder_ids.size()) { + for (size_t i = 0; i < n_loops; ++i) + skirt_loops_per_extruder_out[extruder_ids[i]] = std::pair(i, i + 1); + } else { + // Assign skirt loops to the extruders. + std::vector extruder_loops(extruder_ids.size(), 1); + n_loops -= extruder_loops.size(); + while (n_loops > 0) { + for (size_t i = 0; i < extruder_ids.size() && n_loops > 0; ++i, --n_loops) + ++extruder_loops[i]; + } + for (size_t i = 0; i < extruder_ids.size(); ++i) + skirt_loops_per_extruder_out[extruder_ids[i]] = std::make_pair( + (i == 0) ? 0 : extruder_loops[i - 1], + ((i == 0) ? 0 : extruder_loops[i - 1]) + extruder_loops[i]); + } + skirt_done.emplace_back(layer_tools.print_z - (skirt_done.empty() ? 0. : skirt_done.back())); + + } + return skirt_loops_per_extruder_out; + } + + std::map> make_skirt_loops_per_extruder_other_layers( + const Print &print, + const std::vector &layers, + const LayerTools &layer_tools, + // Heights at which the skirt has already been extruded. + std::vector &skirt_done) + { + // 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() && + // 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()) && + // This print_z has not been extruded yet + skirt_done.back() < layer_tools.print_z - EPSILON && + // and this layer is an object layer, or it is a raft layer. + //FIXME one uses the number of raft layers from the 1st object! + (layer_tools.has_object || layers.front().support_layer->id() < (size_t)layers.front().support_layer->object()->config().raft_layers.value)) { + // Extrude all skirts with the current extruder. + unsigned int first_extruder_id = layer_tools.extruders.front(); + skirt_loops_per_extruder_out[first_extruder_id] = std::pair(0, print.config().skirts.value); + assert(!skirt_done.empty()); + skirt_done.emplace_back(layer_tools.print_z - skirt_done.back()); + } + return skirt_loops_per_extruder_out; + } + +} // namespace Skirt + // 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. @@ -1804,7 +1979,7 @@ void GCode::process_layer( if (l.support_layer != nullptr && support_layer == nullptr) support_layer = l.support_layer; } - const Layer &layer = (object_layer != nullptr) ? *object_layer : *support_layer; + const Layer &layer = (object_layer != nullptr) ? *object_layer : *support_layer; coordf_t print_z = layer.print_z; bool first_layer = layer.id() == 0; unsigned int first_extruder_id = layer_tools.extruders.front(); @@ -1868,120 +2043,21 @@ void GCode::process_layer( m_second_layer_things_done = true; } - // Let's issue a filament change command if requested at this layer. - // In case there are more toolchange requests that weren't done yet and should happen simultaneously, erase them all. - // (Layers can be close to each other, model could have been resliced with bigger layer height, ...). - bool colorprint_change = false; - - std::string custom_code = ""; - std::string pause_print_msg = ""; - int m600_before_extruder = -1; - while (!m_custom_gcode_per_print_z.empty() && m_custom_gcode_per_print_z.front().print_z - EPSILON < layer.print_z) { - custom_code = m_custom_gcode_per_print_z.front().gcode; - - if (custom_code == ColorChangeCode && m_custom_gcode_per_print_z.front().extruder > 0) - m600_before_extruder = m_custom_gcode_per_print_z.front().extruder - 1; - if (custom_code == PausePrintCode) - pause_print_msg = m_custom_gcode_per_print_z.front().color; - - m_custom_gcode_per_print_z.erase(m_custom_gcode_per_print_z.begin()); - colorprint_change = true; - } - - // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count - - // don't save "tool_change"(ExtruderChangeCode) code to GCode - if (colorprint_change && custom_code != ExtruderChangeCode) { - const bool single_material_print = print.config().nozzle_diameter.size() == 1; - - if (custom_code == ColorChangeCode) // color change - { - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_before_extruder) + "\n"; - // add tag for time estimator - gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n"; - - if (!single_material_print && m600_before_extruder >= 0 && first_extruder_id != m600_before_extruder - // && !MMU1 - ) { - //! FIXME_in_fw show message during print pause - gcode += "M601\n"; // pause print - gcode += "M117 Change filament for Extruder " + std::to_string(m600_before_extruder) + "\n"; - } - else - gcode += custom_code + "\n"; - } - else - { - if (custom_code == PausePrintCode) // Pause print - { - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n"; - //! FIXME_in_fw show message during print pause - if (!pause_print_msg.empty()) - gcode += "M117 " + pause_print_msg + "\n"; - // add tag for time estimator - //gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; - } - else // custom Gcode - { - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n"; - // add tag for time estimator - //gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n"; - } - gcode += custom_code + "\n"; - } - } - - - // 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. - bool extrude_skirt = - ! print.skirt().entities.empty() && - // Not enough skirt layers printed yet. - (m_skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt()) && - // This print_z has not been extruded yet - (m_skirt_done.empty() ? 0. : m_skirt_done.back()) < print_z - EPSILON && - // and this layer is the 1st layer, or it is an object layer, or it is a raft layer. - (first_layer || object_layer != nullptr || support_layer->id() < (size_t)m_config.raft_layers.value); + // Map from extruder ID to index of skirt loops to be extruded with that extruder. std::map> skirt_loops_per_extruder; - coordf_t skirt_height = 0.; - if (extrude_skirt) { - // Fill in skirt_loops_per_extruder. - skirt_height = print_z - (m_skirt_done.empty() ? 0. : m_skirt_done.back()); - m_skirt_done.push_back(print_z); - if (first_layer) { - // Prime the extruders over the skirt lines. - std::vector extruder_ids = m_writer.extruder_ids(); - // Reorder the extruders, so that the last used extruder is at the front. - for (size_t i = 1; i < extruder_ids.size(); ++ i) - if (extruder_ids[i] == first_extruder_id) { - // Move the last extruder to the front. - memmove(extruder_ids.data() + 1, extruder_ids.data(), i * sizeof(unsigned int)); - extruder_ids.front() = first_extruder_id; - break; - } - size_t n_loops = print.skirt().entities.size(); - if (n_loops <= extruder_ids.size()) { - for (size_t i = 0; i < n_loops; ++i) - skirt_loops_per_extruder[extruder_ids[i]] = std::pair(i, i + 1); - } else { - // Assign skirt loops to the extruders. - std::vector extruder_loops(extruder_ids.size(), 1); - n_loops -= extruder_loops.size(); - while (n_loops > 0) { - for (size_t i = 0; i < extruder_ids.size() && n_loops > 0; ++ i, -- n_loops) - ++ extruder_loops[i]; - } - for (size_t i = 0; i < extruder_ids.size(); ++ i) - skirt_loops_per_extruder[extruder_ids[i]] = std::make_pair( - (i == 0) ? 0 : extruder_loops[i - 1], - ((i == 0) ? 0 : extruder_loops[i - 1]) + extruder_loops[i]); - } - } else - // Extrude all skirts with the current extruder. - skirt_loops_per_extruder[first_extruder_id] = std::pair(0, print.config().skirts.value); + + if (single_object_instance_idx == size_t(-1) && object_layer != nullptr) { + // Normal (non-sequential) print. + gcode += ProcessLayer::emit_custom_gcode_per_print_z( + // input / output + m_custom_gcode_per_print_z_it, + // inputs + print.model().custom_gcode_per_print_z.cend(), layer.print_z, first_extruder_id, print.config().nozzle_diameter.size()); + // 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, layers, layer_tools, m_writer.extruder_ids(), m_skirt_done) : + Skirt::make_skirt_loops_per_extruder_other_layers(print, layers, layer_tools, m_skirt_done); } // Group extrusions by an extruder, then by an object, an island and a region. @@ -2085,7 +2161,7 @@ void GCode::process_layer( continue; // This extrusion is part of certain Region, which tells us which extruder should be used for it: - int correct_extruder_id = Print::get_extruder(*extrusions, region); + int correct_extruder_id = layer_tools.extruder(*extrusions, region); // Let's recover vector of extruder overrides: const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr; @@ -2152,30 +2228,27 @@ void GCode::process_layer( if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower) m_last_analyzer_extrusion_role = erWipeTower; - if (extrude_skirt) { - auto loops_it = skirt_loops_per_extruder.find(extruder_id); - if (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 = true; - Flow skirt_flow = print.skirt_flow(); - for (size_t i = loops.first; i < loops.second; ++ i) { - // Adjust flow according to this layer's layer height. - ExtrusionLoop loop = *dynamic_cast(print.skirt().entities[i]); - Flow layer_skirt_flow(skirt_flow); - layer_skirt_flow.height = (float)skirt_height; - double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); - for (ExtrusionPath &path : loop.paths) { - path.height = (float)layer.height; - path.mm3_per_mm = mm3_per_mm; - } - gcode += this->extrude_loop(loop, "skirt", m_config.support_material_speed.value); + 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 = true; + Flow layer_skirt_flow(print.skirt_flow()); + 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) { + // 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; } - 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 = true; + //FIXME using the support_material_speed of the 1st object printed. + gcode += this->extrude_loop(loop, "skirt", m_config.support_material_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 = true; } // Extrude brim with the extruder of the 1st region. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index d5213d00bab..10644a60b4b 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -197,23 +197,25 @@ class GCode { // append full config to the given string static void append_full_config(const Print& print, std::string& str); + // Object and support extrusions of the same PrintObject at the same print_z. + // public, so that it could be accessed by free helper functions from GCode.cpp + struct LayerToPrint + { + LayerToPrint() : object_layer(nullptr), support_layer(nullptr) {} + const Layer* object_layer; + const SupportLayer* support_layer; + const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; } + const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; } + coordf_t print_z() const { return (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; } + }; + private: #if ENABLE_THUMBNAIL_GENERATOR - void _do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb); + void _do_export(Print &print, FILE *file, ThumbnailsGeneratorCallback thumbnail_cb); #else void _do_export(Print &print, FILE *file); #endif //ENABLE_THUMBNAIL_GENERATOR - // Object and support extrusions of the same PrintObject at the same print_z. - struct LayerToPrint - { - LayerToPrint() : object_layer(nullptr), support_layer(nullptr) {} - const Layer *object_layer; - const SupportLayer *support_layer; - const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; } - const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; } - coordf_t print_z() const { return (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; } - }; static std::vector collect_layers_to_print(const PrintObject &object); static std::vector>> collect_layers_to_print(const Print &print); void process_layer( @@ -372,11 +374,9 @@ class GCode { bool m_second_layer_things_done; // Index of a last object copy extruded. std::pair m_last_obj_copy; - // Extensions for colorprint - now it's not a just color_print_heights, - // there can be some custom gcode. - // Updated before the export and erased during the process, - // so no toolchange occurs twice. - std::vector m_custom_gcode_per_print_z; + // Iterator to Model::custom_gcode_per_print_z, which is being increased by process_layer. + // The Model::custom_gcode_per_print_z may contain color changes, extruder switches, pauses and custom G-codes. + std::vector::const_iterator m_custom_gcode_per_print_z_it; // Time estimators GCodeTimeEstimator m_normal_time_estimator; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 8aed420cbc4..3edb7cf1748 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -34,6 +34,39 @@ bool LayerTools::is_extruder_order(unsigned int a, unsigned int b) const return false; } +// Return a zero based extruder from the region, or extruder_override if overriden. +unsigned int LayerTools::perimeter_extruder(const PrintRegion ®ion) const +{ + assert(region.config().perimeter_extruder.value > 0); + return ((this->extruder_override == 0) ? region.config().perimeter_extruder.value : this->extruder_override) - 1; +} + +unsigned int LayerTools::infill_extruder(const PrintRegion ®ion) const +{ + assert(region.config().infill_extruder.value > 0); + return ((this->extruder_override == 0) ? region.config().infill_extruder.value : this->extruder_override) - 1; +} + +unsigned int LayerTools::solid_infill_extruder(const PrintRegion ®ion) const +{ + assert(region.config().solid_infill_extruder.value > 0); + return ((this->extruder_override == 0) ? region.config().solid_infill_extruder.value : this->extruder_override) - 1; +} + +// Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden. +unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, const PrintRegion ®ion) const +{ + assert(region.config().perimeter_extruder.value > 0); + assert(region.config().infill_extruder.value > 0); + assert(region.config().solid_infill_extruder.value > 0); + // 1 based extruder ID. + unsigned int extruder = ((this->extruder_override == 0) ? + (is_infill(extrusions.role()) ? + (is_solid_infill(extrusions.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) : + region.config().perimeter_extruder.value) : + this->extruder_override); + return (extruder == 0) ? 0 : extruder - 1; +} // For the use case when each object is printed separately // (print.config().complete_objects is true). @@ -54,7 +87,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude } // Collect extruders reuqired to print the layers. - this->collect_extruders(object); + this->collect_extruders(object, nullptr); // Reorder the extruders to minimize tool switches. this->reorder_extruders(first_extruder); @@ -66,7 +99,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude // For the use case when all objects are printed at once. // (print.config().complete_objects is false). -ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material) +ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material, const std::vector> *per_layer_extruder_switches) { m_print_config_ptr = &print.config(); @@ -93,7 +126,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool // Collect extruders reuqired to print the layers. for (auto object : print.objects()) - this->collect_extruders(*object); + this->collect_extruders(*object, (per_layer_extruder_switches != nullptr && ! per_layer_extruder_switches->empty()) ? per_layer_extruder_switches : nullptr); // Reorder the extruders to minimize tool switches. this->reorder_extruders(first_extruder); @@ -119,7 +152,7 @@ void ToolOrdering::initialize_layers(std::vector &zs) } // Collect extruders reuqired to print layers. -void ToolOrdering::collect_extruders(const PrintObject &object) +void ToolOrdering::collect_extruders(const PrintObject &object, const std::vector> *per_layer_extruder_switches) { // Collect the support extruders. for (auto support_layer : object.support_layers()) { @@ -136,9 +169,25 @@ void ToolOrdering::collect_extruders(const PrintObject &object) if (has_support || has_interface) layer_tools.has_support = true; } + + // Extruder overrides are ordered by print_z. + std::vector>::const_iterator it_per_layer_extruder_override; + if (per_layer_extruder_switches != nullptr) + it_per_layer_extruder_override = per_layer_extruder_switches->begin(); + unsigned int extruder_override = 0; + // Collect the object extruders. for (auto layer : object.layers()) { LayerTools &layer_tools = this->tools_for_layer(layer->print_z); + + // Override extruder with the next + if (per_layer_extruder_switches != nullptr) + for (; it_per_layer_extruder_override != per_layer_extruder_switches->end() && it_per_layer_extruder_override->first < layer->print_z + EPSILON; ++ it_per_layer_extruder_override) + extruder_override = (int)it_per_layer_extruder_override->second; + + // Store the current extruder override (set to zero if no overriden), so that layer_tools.wiping_extrusions().is_overridable_and_mark() will use it. + layer_tools.extruder_override = extruder_override; + // What extruders are required to print this object layer? for (size_t region_id = 0; region_id < object.region_volumes.size(); ++ region_id) { const LayerRegion *layerm = (region_id < layer->regions().size()) ? layer->regions()[region_id] : nullptr; @@ -159,12 +208,11 @@ void ToolOrdering::collect_extruders(const PrintObject &object) } if (something_nonoverriddable) - layer_tools.extruders.push_back(region.config().perimeter_extruder.value); + layer_tools.extruders.emplace_back((extruder_override == 0) ? region.config().perimeter_extruder.value : extruder_override); layer_tools.has_object = true; } - bool has_infill = false; bool has_solid_infill = false; bool something_nonoverriddable = false; @@ -183,12 +231,14 @@ void ToolOrdering::collect_extruders(const PrintObject &object) } } - if (something_nonoverriddable || !m_print_config_ptr) - { - if (has_solid_infill) - layer_tools.extruders.push_back(region.config().solid_infill_extruder); - if (has_infill) - layer_tools.extruders.push_back(region.config().infill_extruder); + if (something_nonoverriddable || !m_print_config_ptr) { + if (extruder_override == 0) { + if (has_solid_infill) + layer_tools.extruders.emplace_back(region.config().solid_infill_extruder); + if (has_infill) + layer_tools.extruders.emplace_back(region.config().infill_extruder); + } else if (has_solid_infill || has_infill) + layer_tools.extruders.emplace_back(extruder_override); } if (has_solid_infill || has_infill) layer_tools.has_object = true; @@ -201,7 +251,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object) // make sure that there are some tools for each object layer (e.g. tall wiping object will result in empty extruders vector) if (layer.extruders.empty() && layer.has_object) - layer.extruders.push_back(0); // 0="dontcare" extruder - it will be taken care of in reorder_extruders + layer.extruders.emplace_back(0); // 0="dontcare" extruder - it will be taken care of in reorder_extruders } } @@ -256,11 +306,9 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id) for (unsigned int &extruder_id : lt.extruders) { assert(extruder_id > 0); -- extruder_id; - } + } } - - void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z) { if (m_layer_tools.empty()) @@ -413,7 +461,7 @@ const LayerTools& ToolOrdering::tools_for_layer(coordf_t print_z) const } // This function is called from Print::mark_wiping_extrusions and sets extruder this entity should be printed with (-1 .. as usual) -void WipingExtrusions::set_extruder_override(const ExtrusionEntity* entity, unsigned int copy_id, int extruder, unsigned int num_of_copies) +void WipingExtrusions::set_extruder_override(const ExtrusionEntity* entity, size_t copy_id, int extruder, size_t num_of_copies) { something_overridden = true; @@ -449,11 +497,10 @@ int WipingExtrusions::last_nonsoluble_extruder_on_layer(const PrintConfig& print return (-1); } - // Decides whether this entity could be overridden bool WipingExtrusions::is_overriddable(const ExtrusionEntityCollection& eec, const PrintConfig& print_config, const PrintObject& object, const PrintRegion& region) const { - if (print_config.filament_soluble.get_at(Print::get_extruder(eec, region))) + if (print_config.filament_soluble.get_at(m_layer_tools->extruder(eec, region))) return false; if (object.config().wipe_into_objects) @@ -522,7 +569,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int if (wipe_into_infill_only && ! print.config().infill_first) // In this case we must check that the original extruder is used on this layer before the one we are overridding // (and the perimeters will be finished before the infill is printed): - if (!lt.is_extruder_order(region.config().perimeter_extruder - 1, new_extruder)) + if (!lt.is_extruder_order(lt.perimeter_extruder(region), new_extruder)) continue; if ((!is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume)) { // this infill will be used to wipe this extruder @@ -597,8 +644,8 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print) // Either way, we will now force-override it with something suitable: if (print.config().infill_first || object->config().wipe_into_objects // in this case the perimeter is overridden, so we can override by the last one safely - || lt.is_extruder_order(region.config().perimeter_extruder - 1, last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints - || ! lt.has_extruder(region.config().infill_extruder - 1))) // we have to force override - this could violate infill_first (FIXME) + || lt.is_extruder_order(lt.perimeter_extruder(region), last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints + || ! lt.has_extruder(lt.infill_extruder(region)))) // we have to force override - this could violate infill_first (FIXME) set_extruder_override(fill, copy, (print.config().infill_first ? first_nonsoluble_extruder : last_nonsoluble_extruder), num_of_copies); else { // In this case we can (and should) leave it to be printed normally. diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index ed7aaab436c..1f043d94f4e 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -61,7 +61,7 @@ class WipingExtrusions int last_nonsoluble_extruder_on_layer(const PrintConfig& print_config) const; // This function is called from mark_wiping_extrusions and sets extruder that it should be printed with (-1 .. as usual) - void set_extruder_override(const ExtrusionEntity* entity, unsigned int copy_id, int extruder, unsigned int num_of_copies); + void set_extruder_override(const ExtrusionEntity* entity, size_t copy_id, int extruder, size_t num_of_copies); // Returns true in case that entity is not printed with its usual extruder for a given copy: bool is_entity_overridden(const ExtrusionEntity* entity, size_t copy_id) const { @@ -84,6 +84,7 @@ class LayerTools print_z(z), has_object(false), has_support(false), + extruder_override(0), has_wipe_tower(false), wipe_tower_partitions(0), wipe_tower_layer_height(0.) {} @@ -96,11 +97,21 @@ class LayerTools bool is_extruder_order(unsigned int a, unsigned int b) const; bool has_extruder(unsigned int extruder) const { return std::find(this->extruders.begin(), this->extruders.end(), extruder) != this->extruders.end(); } + // Return a zero based extruder from the region, or extruder_override if overriden. + unsigned int perimeter_extruder(const PrintRegion ®ion) const; + unsigned int infill_extruder(const PrintRegion ®ion) const; + unsigned int solid_infill_extruder(const PrintRegion ®ion) const; + // Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden. + unsigned int extruder(const ExtrusionEntityCollection &extrusions, const PrintRegion ®ion) const; + coordf_t print_z; bool has_object; bool has_support; // Zero based extruder IDs, ordered to minimize tool switches. std::vector extruders; + // If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with. + // If not overriden, it is set to 0. + unsigned int extruder_override; // Will there be anything extruded on this layer for the wipe tower? // Due to the support layers possibly interleaving the object layers, // wipe tower will be disabled for some support only layers. @@ -129,11 +140,11 @@ class ToolOrdering // For the use case when each object is printed separately // (print.config.complete_objects is true). - ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); + ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material = false); // For the use case when all objects are printed at once. // (print.config.complete_objects is false). - ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false); + ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material = false, const std::vector> *per_layer_extruder_switches = nullptr); void clear() { m_layer_tools.clear(); } @@ -160,7 +171,7 @@ class ToolOrdering private: void initialize_layers(std::vector &zs); - void collect_extruders(const PrintObject &object); + void collect_extruders(const PrintObject &object, const std::vector> *per_layer_extruder_switches); void reorder_extruders(unsigned int last_extruder_id); void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z); void collect_extruder_statistics(bool prime_multi_material); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 364ba12ae13..0266eee39e5 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -19,8 +19,8 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config) this->config.apply(print_config, true); m_extrusion_axis = this->config.get_extrusion_axis(); m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; - m_max_acceleration = (print_config.gcode_flavor.value == gcfMarlin) ? - print_config.machine_max_acceleration_extruding.values.front() : 0; + m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin) ? + print_config.machine_max_acceleration_extruding.values.front() : 0); } void GCodeWriter::set_extruders(const std::vector &extruder_ids) @@ -247,9 +247,9 @@ std::string GCodeWriter::toolchange_prefix() const std::string GCodeWriter::toolchange(unsigned int extruder_id) { // set the new extruder - auto it_extruder = std::lower_bound(m_extruders.begin(), m_extruders.end(), Extruder::key(extruder_id)); - assert(it_extruder != m_extruders.end()); - m_extruder = const_cast(&*it_extruder); + auto it_extruder = Slic3r::lower_bound_by_predicate(m_extruders.begin(), m_extruders.end(), [extruder_id](const Extruder &e) { return e.id() < extruder_id; }); + assert(it_extruder != m_extruders.end() && it_extruder->id() == extruder_id); + m_extruder = &*it_extruder; // return the toolchange command // if we are running a single-extruder setup, just set the extruder and return nothing diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 98abdda280b..1631d8590eb 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -74,7 +74,8 @@ class GCodeWriter { Vec3d get_position() const { return m_pos; } private: - std::vector m_extruders; + // Extruders are sorted by their ID, so that binary search is possible. + std::vector m_extruders; std::string m_extrusion_axis; bool m_single_extruder_multi_material; Extruder* m_extruder; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 96a32680e6e..812180641ba 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -598,21 +598,6 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string(); } -std::vector> Model::get_custom_tool_changes(double default_layer_height, size_t num_extruders) const -{ - std::vector> custom_tool_changes; - for (const CustomGCode& custom_gcode : custom_gcode_per_print_z) - if (custom_gcode.gcode == ExtruderChangeCode) { - DynamicPrintConfig config; - // If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders - config.set_key_value("extruder", new ConfigOptionInt(custom_gcode.extruder > num_extruders ? 0 : custom_gcode.extruder)); - // For correct extruders(tools) changing, we should decrease custom_gcode.height value by one default layer height - custom_tool_changes.push_back({ custom_gcode.print_z - default_layer_height, config }); - } - - return custom_tool_changes; -} - ModelObject::~ModelObject() { this->clear_volumes(); @@ -1856,6 +1841,19 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const return ret; } +// Return pairs of sorted by increasing print_z from custom_gcode_per_print_z. +// print_z corresponds to the first layer printed with the new extruder. +std::vector> custom_tool_changes(const Model &model, size_t num_extruders) +{ + std::vector> custom_tool_changes; + for (const Model::CustomGCode &custom_gcode : model.custom_gcode_per_print_z) + if (custom_gcode.gcode == ExtruderChangeCode) { + // If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders + custom_tool_changes.emplace_back(custom_gcode.print_z, static_cast(custom_gcode.extruder > num_extruders ? 1 : custom_gcode.extruder)); + } + return custom_tool_changes; +} + // Test whether the two models contain the same number of ModelObjects with the same set of IDs // ordered in the same order. In that case it is not necessary to kill the background processing. bool model_object_list_equal(const Model &model_old, const Model &model_new) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 44f5049c9f1..26bb4cb92f5 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -838,9 +838,6 @@ class Model final : public ObjectBase // Propose an output path, replace extension. The new_extension shall contain the initial dot. std::string propose_export_file_name_and_path(const std::string &new_extension) const; - // from custom_gcode_per_print_z get just tool_change codes - std::vector> get_custom_tool_changes(double default_layer_height, size_t num_extruders) const; - private: explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); }; void assign_new_unique_ids_recursive(); @@ -857,6 +854,10 @@ class Model final : public ObjectBase #undef OBJECTBASE_DERIVED_COPY_MOVE_CLONE #undef OBJECTBASE_DERIVED_PRIVATE_COPY_MOVE +// Return pairs of sorted by increasing print_z from custom_gcode_per_print_z. +// print_z corresponds to the first layer printed with the new extruder. +extern std::vector> custom_tool_changes(const Model &model, size_t num_extruders); + // Test whether the two models contain the same number of ModelObjects with the same set of IDs // ordered in the same order. In that case it is not necessary to kill the background processing. extern bool model_object_list_equal(const Model &model_old, const Model &model_new); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 02d9da7848e..2d327c70b99 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -638,48 +638,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr); } - // Convert input config ranges into continuous non-overlapping sorted vector of intervals and their configs, - // considering custom_tool_change values - void assign(const t_layer_config_ranges &in, const std::vector> &custom_tool_changes) { - m_ranges.clear(); - m_ranges.reserve(in.size()); - // Input ranges are sorted lexicographically. First range trims the other ranges. - coordf_t last_z = 0; - for (const std::pair &range : in) - if (range.first.second > last_z) { - coordf_t min_z = std::max(range.first.first, 0.); - if (min_z > last_z + EPSILON) { - m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr); - last_z = min_z; - } - if (range.first.second > last_z + EPSILON) { - const DynamicPrintConfig* cfg = &range.second; - m_ranges.emplace_back(t_layer_height_range(last_z, range.first.second), cfg); - last_z = range.first.second; - } - } - - // add ranges for extruder changes from custom_tool_changes - for (size_t i = 0; i < custom_tool_changes.size(); i++) { - const DynamicPrintConfig* cfg = &custom_tool_changes[i].second; - coordf_t cur_Z = custom_tool_changes[i].first; - coordf_t next_Z = i == custom_tool_changes.size()-1 ? DBL_MAX : custom_tool_changes[i+1].first; - if (cur_Z > last_z + EPSILON) { - if (i==0) - m_ranges.emplace_back(t_layer_height_range(last_z, cur_Z), nullptr); - m_ranges.emplace_back(t_layer_height_range(cur_Z, next_Z), cfg); - } - else if (next_Z > last_z + EPSILON) - m_ranges.emplace_back(t_layer_height_range(last_z, next_Z), cfg); - } - - if (m_ranges.empty()) - m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr); - else if (m_ranges.back().second == nullptr) - m_ranges.back().first.second = DBL_MAX; - else if (m_ranges.back().first.second != DBL_MAX) - m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr); - } const DynamicPrintConfig* config(const t_layer_height_range &range) const { auto it = std::lower_bound(m_ranges.begin(), m_ranges.end(), std::make_pair< t_layer_height_range, const DynamicPrintConfig*>(t_layer_height_range(range.first - EPSILON, range.second - EPSILON), nullptr)); // #ys_FIXME_COLOR @@ -733,17 +691,15 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (const ModelObject *model_object : m_model.objects) model_object_status.emplace(model_object->id(), ModelObjectStatus::New); } else { + if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) { + // If custom gcode per layer height was changed, we should stop background processing. + update_apply_status(this->invalidate_steps({ psWipeTower, psGCodeExport })); + m_model.custom_gcode_per_print_z = model.custom_gcode_per_print_z; + } if (model_object_list_equal(m_model, model)) { // The object list did not change. for (const ModelObject *model_object : m_model.objects) model_object_status.emplace(model_object->id(), ModelObjectStatus::Old); - - // But if custom gcode per layer height was changed - if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) { - // we should stop background processing - update_apply_status(this->invalidate_step(psGCodeExport)); - m_model.custom_gcode_per_print_z = model.custom_gcode_per_print_z; - } } else if (model_object_list_extended(m_model, model)) { // Add new objects. Their volumes and configs will be synchronized later. update_apply_status(this->invalidate_step(psGCodeExport)); @@ -835,9 +791,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (PrintObject *print_object : m_objects) print_object_status.emplace(PrintObjectStatus(print_object)); - std::vector> custom_tool_changes = - m_model.get_custom_tool_changes(m_default_object_config.layer_height, num_extruders); - // 3) Synchronize ModelObjects & PrintObjects. for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) { ModelObject &model_object = *m_model.objects[idx_model_object]; @@ -845,9 +798,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ assert(it_status != model_object_status.end()); assert(it_status->status != ModelObjectStatus::Deleted); const ModelObject& model_object_new = *model.objects[idx_model_object]; - // ys_FIXME_COLOR - // const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges); - const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges, custom_tool_changes); + const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges); if (it_status->status == ModelObjectStatus::New) // PrintObject instances will be added in the next loop. continue; @@ -1015,8 +966,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ PrintRegionConfig this_region_config; bool this_region_config_set = false; for (PrintObject *print_object : m_objects) { - if(m_force_update_print_regions && !custom_tool_changes.empty()) - goto print_object_end; const LayerRanges *layer_ranges; { auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id())); @@ -1989,7 +1938,9 @@ void Print::_make_wipe_tower() wipe_volumes.push_back(std::vector(wiping_matrix.begin()+i*number_of_extruders, wiping_matrix.begin()+(i+1)*number_of_extruders)); // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print. - m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true); + m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true, + (this->object_extruders().size() == 1) ? &custom_tool_changes(this->model(), (unsigned int)m_config.nozzle_diameter.size()) : nullptr); + if (! m_wipe_tower_data.tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; @@ -2107,13 +2058,6 @@ void Print::_make_wipe_tower() m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges(); } -// Returns extruder this eec should be printed with, according to PrintRegion config -int Print::get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion) -{ - return is_infill(fill.role()) ? std::max(0, (is_solid_infill(fill.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) - 1) : - std::max(region.config().perimeter_extruder.value - 1, 0); -} - // Generate a recommended G-code output file name based on the format template, default extension, and template parameters // (timestamps, object placeholders derived from the model, current placeholder prameters and print statistics. // Use the final print statistics if available, or just keep the print statistics placeholders if not available yet (before G-code is finalized). diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c434eec4386..89d27e3cb8e 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -369,9 +369,6 @@ class Print : public PrintBaseWithState // If zero, then the print is empty and the print shall not be executed. unsigned int num_object_instances() const; - // Returns extruder this eec should be printed with, according to PrintRegion config: - static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion); - const ExtrusionEntityCollection& skirt() const { return m_skirt; } const ExtrusionEntityCollection& brim() const { return m_brim; } @@ -386,9 +383,6 @@ class Print : public PrintBaseWithState // Accessed by SupportMaterial const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; } - // force update of PrintRegions, when custom_tool_change is not empty and (Re)Slicing is started - void set_force_update_print_regions(bool force_update_print_regions) { m_force_update_print_regions = force_update_print_regions; } - protected: // methods for handling regions PrintRegion* get_region(size_t idx) { return m_regions[idx]; } @@ -431,9 +425,6 @@ class Print : public PrintBaseWithState // Estimated print time, filament consumed. PrintStatistics m_print_statistics; - // flag used - bool m_force_update_print_regions = false; - // To allow GCode to set the Print's GCodeExport step status. friend class GCode; // Allow PrintObject to access m_mutex and m_cancel_callback. diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index a66dcf39c3a..984686e3552 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -132,11 +132,6 @@ class BackgroundSlicingProcess // This "finished" flag does not account for the final export of the output file (.gcode or zipped PNGs), // and it does not account for the OctoPrint scheduling. bool finished() const { return m_print->finished(); } - - void set_force_update_print_regions(bool force_update_print_regions) { - if (m_fff_print) - m_fff_print->set_force_update_print_regions(force_update_print_regions); - } private: void thread_proc(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 011d7e7ce30..dc720ddaee8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3022,7 +3022,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool this->update_print_volume_state(); // Apply new config to the possibly running background task. bool was_running = this->background_process.running(); - this->background_process.set_force_update_print_regions(force_validation); Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config()); // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.