mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 02:41:58 +08:00
Merge branch 'lh_m600' into master_27x
This commit is contained in:
commit
ad61f74e3f
@ -72,6 +72,22 @@ std::vector<std::pair<double, unsigned int>> custom_tool_changes(const Info& cus
|
||||
return custom_tool_changes;
|
||||
}
|
||||
|
||||
// Return pairs of <print_z, 1-based extruder ID> sorted by increasing print_z from custom_gcode_per_print_z.
|
||||
// Where print_z corresponds to the layer on which we perform a color change for the specified extruder.
|
||||
std::vector<std::pair<double, unsigned int>> custom_color_changes(const Info& custom_gcode_per_print_z, size_t num_extruders)
|
||||
{
|
||||
std::vector<std::pair<double, unsigned int>> custom_color_changes;
|
||||
for (const Item& custom_gcode : custom_gcode_per_print_z.gcodes)
|
||||
if (custom_gcode.type == ColorChange) {
|
||||
// If extruder count in PrinterSettings was changed, ignore custom g-codes for extruder ids bigger than num_extruders.
|
||||
assert(custom_gcode.extruder >= 0);
|
||||
if (size_t(custom_gcode.extruder) <= num_extruders) {
|
||||
custom_color_changes.emplace_back(custom_gcode.print_z, static_cast<unsigned int>(custom_gcode.extruder));
|
||||
}
|
||||
}
|
||||
return custom_color_changes;
|
||||
}
|
||||
|
||||
} // namespace CustomGCode
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -91,6 +91,10 @@ extern void check_mode_for_custom_gcode_per_print_z(Info& info);
|
||||
// print_z corresponds to the first layer printed with the new extruder.
|
||||
std::vector<std::pair<double, unsigned int>> custom_tool_changes(const Info& custom_gcode_per_print_z, size_t num_extruders);
|
||||
|
||||
// Return pairs of <print_z, 1-based extruder ID> sorted by increasing print_z from custom_gcode_per_print_z.
|
||||
// Where print_z corresponds to the layer on which we perform a color change for the specified extruder.
|
||||
std::vector<std::pair<double, unsigned int>> custom_color_changes(const Info& custom_gcode_per_print_z, size_t num_extruders);
|
||||
|
||||
} // namespace CustomGCode
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -1901,84 +1901,92 @@ std::vector<GCodeGenerator::InstanceToPrint> GCodeGenerator::sort_print_object_i
|
||||
namespace ProcessLayer
|
||||
{
|
||||
|
||||
static std::string emit_custom_color_change_gcode_per_print_z(
|
||||
GCodeGenerator &gcodegen,
|
||||
const CustomGCode::Item &custom_gcode,
|
||||
unsigned int current_extruder_id,
|
||||
unsigned int first_extruder_id, // ID of the first extruder printing this layer.
|
||||
const PrintConfig &config
|
||||
) {
|
||||
const bool single_extruder_multi_material = config.single_extruder_multi_material;
|
||||
const bool single_extruder_printer = config.nozzle_diameter.size() == 1;
|
||||
const bool color_change = custom_gcode.type == CustomGCode::ColorChange;
|
||||
|
||||
std::string gcode;
|
||||
|
||||
int color_change_extruder = -1;
|
||||
if (color_change && custom_gcode.extruder > 0)
|
||||
color_change_extruder = custom_gcode.extruder - 1;
|
||||
|
||||
assert(color_change_extruder >= 0);
|
||||
// Color Change or Tool Change as Color Change.
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Color_Change) + ",T" + std::to_string(color_change_extruder) + "," + custom_gcode.color + "\n";
|
||||
|
||||
DynamicConfig cfg;
|
||||
cfg.set_key_value("color_change_extruder", new ConfigOptionInt(color_change_extruder));
|
||||
if (single_extruder_multi_material && !single_extruder_printer && color_change_extruder >= 0 && first_extruder_id != unsigned(color_change_extruder)) {
|
||||
//! FIXME_in_fw show message during print pause
|
||||
// FIXME: Why is pause_print_gcode here? Why is it supplied "color_change_extruder"?
|
||||
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg);
|
||||
gcode += "\n";
|
||||
gcode += "M117 Change filament for Extruder " + std::to_string(color_change_extruder) + "\n";
|
||||
} else {
|
||||
gcode += gcodegen.placeholder_parser_process("color_change_gcode", config.color_change_gcode, current_extruder_id, &cfg);
|
||||
gcode += "\n";
|
||||
//FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after
|
||||
// return from M600. Thus the G-code generated by the following line is ignored.
|
||||
// see GH issue #6362
|
||||
gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
static std::string emit_custom_gcode_per_print_z(
|
||||
GCodeGenerator &gcodegen,
|
||||
const CustomGCode::Item *custom_gcode,
|
||||
const CustomGCode::Item &custom_gcode,
|
||||
unsigned int current_extruder_id,
|
||||
// ID of the first extruder printing this layer.
|
||||
unsigned int first_extruder_id,
|
||||
const PrintConfig &config)
|
||||
{
|
||||
std::string gcode;
|
||||
bool single_extruder_printer = config.nozzle_diameter.size() == 1;
|
||||
|
||||
if (custom_gcode != nullptr) {
|
||||
// Extruder switches are processed by LayerTools, they should be filtered out.
|
||||
assert(custom_gcode->type != CustomGCode::ToolChange);
|
||||
// Extruder switches are processed by LayerTools, they should be filtered out.
|
||||
assert(custom_gcode.type != CustomGCode::ToolChange);
|
||||
|
||||
CustomGCode::Type gcode_type = custom_gcode->type;
|
||||
bool color_change = gcode_type == CustomGCode::ColorChange;
|
||||
bool tool_change = gcode_type == CustomGCode::ToolChange;
|
||||
// Tool Change is applied as Color Change for a single extruder printer only.
|
||||
assert(! tool_change || single_extruder_printer);
|
||||
CustomGCode::Type gcode_type = custom_gcode.type;
|
||||
const bool color_change = gcode_type == CustomGCode::ColorChange;
|
||||
const bool tool_change = gcode_type == CustomGCode::ToolChange;
|
||||
// Tool Change is applied as Color Change for a single extruder printer only.
|
||||
assert(!tool_change || config.nozzle_diameter.size() == 1);
|
||||
|
||||
std::string pause_print_msg;
|
||||
int m600_extruder_before_layer = -1;
|
||||
if (color_change && custom_gcode->extruder > 0)
|
||||
m600_extruder_before_layer = custom_gcode->extruder - 1;
|
||||
else if (gcode_type == CustomGCode::PausePrint)
|
||||
pause_print_msg = custom_gcode->extra;
|
||||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||
if (color_change || tool_change) {
|
||||
gcode += emit_custom_color_change_gcode_per_print_z(gcodegen, custom_gcode, current_extruder_id, first_extruder_id, config);
|
||||
} else {
|
||||
if (gcode_type == CustomGCode::PausePrint) { // Pause print
|
||||
const std::string pause_print_msg = custom_gcode.extra;
|
||||
|
||||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||
if (color_change || tool_change)
|
||||
{
|
||||
assert(m600_extruder_before_layer >= 0);
|
||||
// Color Change or Tool Change as Color Change.
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Color_Change) + ",T" + std::to_string(m600_extruder_before_layer) + "," + custom_gcode->color + "\n";
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n";
|
||||
//! FIXME_in_fw show message during print pause
|
||||
if (!pause_print_msg.empty())
|
||||
gcode += "M117 " + pause_print_msg + "\n";
|
||||
|
||||
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
|
||||
// && !MMU1
|
||||
) {
|
||||
//! FIXME_in_fw show message during print pause
|
||||
// FIXME: Why is pause_print_gcode here? Why is it supplied "color_change_extruder"? Why is that not
|
||||
// passed to color_change_gcode below?
|
||||
DynamicConfig cfg;
|
||||
cfg.set_key_value("color_change_extruder", new ConfigOptionInt(m600_extruder_before_layer));
|
||||
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg);
|
||||
gcode += "\n";
|
||||
gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
}
|
||||
else {
|
||||
gcode += gcodegen.placeholder_parser_process("color_change_gcode", config.color_change_gcode, current_extruder_id);
|
||||
gcode += "\n";
|
||||
//FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after
|
||||
// return from M600. Thus the G-code generated by the following line is ignored.
|
||||
// see GH issue #6362
|
||||
gcodegen.writer().unretract();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gcode_type == CustomGCode::PausePrint) // Pause print
|
||||
{
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n";
|
||||
//! FIXME_in_fw show message during print pause
|
||||
if (!pause_print_msg.empty())
|
||||
gcode += "M117 " + pause_print_msg + "\n";
|
||||
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id);
|
||||
}
|
||||
else {
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Custom_Code) + "\n";
|
||||
if (gcode_type == CustomGCode::Template) // Template Custom Gcode
|
||||
gcode += gcodegen.placeholder_parser_process("template_custom_gcode", config.template_custom_gcode, current_extruder_id);
|
||||
else // custom Gcode
|
||||
gcode += custom_gcode->extra;
|
||||
|
||||
}
|
||||
gcode += "\n";
|
||||
DynamicConfig cfg;
|
||||
cfg.set_key_value("color_change_extruder", new ConfigOptionInt(int(current_extruder_id)));
|
||||
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg);
|
||||
} else {
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Custom_Code) + "\n";
|
||||
if (gcode_type == CustomGCode::Template) // Template Custom Gcode
|
||||
gcode += gcodegen.placeholder_parser_process("template_custom_gcode", config.template_custom_gcode, current_extruder_id);
|
||||
else // custom Gcode
|
||||
gcode += custom_gcode.extra;
|
||||
}
|
||||
gcode += "\n";
|
||||
}
|
||||
|
||||
return gcode;
|
||||
@ -2247,16 +2255,6 @@ LayerResult GCodeGenerator::process_layer(
|
||||
// Map from extruder ID to <begin, end> index of skirt loops to be extruded with that extruder.
|
||||
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder;
|
||||
|
||||
if (single_object_instance_idx == size_t(-1)) {
|
||||
// Normal (non-sequential) print.
|
||||
std::string custom_gcode = ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
|
||||
if (layer_tools.custom_gcode != nullptr && layer_tools.custom_gcode->type == CustomGCode::ColorChange) {
|
||||
// We have a color change to do on this layer, but we want to do it immediately before the first extrusion instead of now, in order to fix GH #2672
|
||||
m_pending_pre_extrusion_gcode = custom_gcode;
|
||||
} else {
|
||||
gcode += custom_gcode;
|
||||
}
|
||||
}
|
||||
// Extrude skirt at the print_z of the raft layers and normal object layers
|
||||
// not at the print_z of the interlaced support material layers.
|
||||
skirt_loops_per_extruder = first_layer ?
|
||||
@ -2275,6 +2273,23 @@ LayerResult GCodeGenerator::process_layer(
|
||||
}
|
||||
}
|
||||
|
||||
const bool has_custom_gcode_to_emit = single_object_instance_idx == size_t(-1) && layer_tools.custom_gcode != nullptr;
|
||||
const int extruder_id_for_custom_gcode = int(layer_tools.extruder_needed_for_color_changer) - 1;
|
||||
|
||||
if (has_custom_gcode_to_emit && extruder_id_for_custom_gcode == -1) {
|
||||
// Normal (non-sequential) print with some custom code without picking a specific extruder before it.
|
||||
// If we don't need to pick a specific extruder before the color change, we can just emit a custom g-code.
|
||||
// Otherwise, we will emit the g-code after picking the specific extruder.
|
||||
|
||||
std::string custom_gcode = ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
|
||||
if (layer_tools.custom_gcode->type == CustomGCode::ColorChange) {
|
||||
// We have a color change to do on this layer, but we want to do it immediately before the first extrusion instead of now, in order to fix GH #2672.
|
||||
m_pending_pre_extrusion_gcode = custom_gcode;
|
||||
} else {
|
||||
gcode += custom_gcode;
|
||||
}
|
||||
}
|
||||
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
@ -2286,6 +2301,13 @@ LayerResult GCodeGenerator::process_layer(
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
m_last_processor_extrusion_role = GCodeExtrusionRole::WipeTower;
|
||||
|
||||
if (has_custom_gcode_to_emit && extruder_id_for_custom_gcode == int(extruder_id)) {
|
||||
assert(m_writer.extruder()->id() == extruder_id_for_custom_gcode);
|
||||
assert(m_pending_pre_extrusion_gcode.empty());
|
||||
// Now we have picked the right extruder, so we can emit the custom g-code.
|
||||
gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
|
||||
}
|
||||
|
||||
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
|
||||
const std::pair<size_t, size_t> loops = loops_it->second;
|
||||
this->set_origin(0., 0.);
|
||||
|
@ -110,7 +110,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
|
||||
double max_layer_height = calc_max_layer_height(object.print()->config(), object.config().layer_height);
|
||||
|
||||
// Collect extruders required to print the layers.
|
||||
this->collect_extruders(object, std::vector<std::pair<double, unsigned int>>());
|
||||
this->collect_extruders(object, std::vector<std::pair<double, unsigned int>>(), std::vector<std::pair<double, unsigned int>>());
|
||||
|
||||
// Reorder the extruders to minimize tool switches.
|
||||
this->reorder_extruders(first_extruder);
|
||||
@ -156,17 +156,24 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
||||
// 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.
|
||||
std::vector<std::pair<double, unsigned int>> 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
|
||||
auto num_extruders = unsigned(print.config().nozzle_diameter.size());
|
||||
if (num_extruders > 1 && print.object_extruders().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.
|
||||
per_layer_extruder_switches = custom_tool_changes(print.model().custom_gcode_per_print_z, num_extruders);
|
||||
}
|
||||
|
||||
// Collect extruders reuqired to print the layers.
|
||||
// Color changes for each layer to determine which extruder needs to be picked before color change.
|
||||
// This is done just for multi-extruder printers without enabled Single Extruder Multi Material (tool changer printers).
|
||||
std::vector<std::pair<double, unsigned int>> per_layer_color_changes;
|
||||
if (num_extruders > 1 && print.model().custom_gcode_per_print_z.mode == CustomGCode::MultiExtruder && !print.config().single_extruder_multi_material) {
|
||||
per_layer_color_changes = custom_color_changes(print.model().custom_gcode_per_print_z, num_extruders);
|
||||
}
|
||||
|
||||
// Collect extruders required to print the layers.
|
||||
for (auto object : print.objects())
|
||||
this->collect_extruders(*object, per_layer_extruder_switches);
|
||||
this->collect_extruders(*object, per_layer_extruder_switches, per_layer_color_changes);
|
||||
|
||||
// Reorder the extruders to minimize tool switches.
|
||||
this->reorder_extruders(first_extruder);
|
||||
@ -219,8 +226,11 @@ void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
||||
}
|
||||
|
||||
// Collect extruders reuqired to print layers.
|
||||
void ToolOrdering::collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches)
|
||||
{
|
||||
void ToolOrdering::collect_extruders(
|
||||
const PrintObject &object,
|
||||
const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches,
|
||||
const std::vector<std::pair<double, unsigned int>> &per_layer_color_changes
|
||||
) {
|
||||
// Collect the support extruders.
|
||||
for (auto support_layer : object.support_layers()) {
|
||||
LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z);
|
||||
@ -238,10 +248,11 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
||||
}
|
||||
|
||||
// Extruder overrides are ordered by print_z.
|
||||
std::vector<std::pair<double, unsigned int>>::const_iterator it_per_layer_extruder_override;
|
||||
it_per_layer_extruder_override = per_layer_extruder_switches.begin();
|
||||
std::vector<std::pair<double, unsigned int>>::const_iterator it_per_layer_extruder_override = per_layer_extruder_switches.begin();
|
||||
unsigned int extruder_override = 0;
|
||||
|
||||
std::vector<std::pair<double, unsigned int>>::const_iterator it_per_layer_color_changes = per_layer_color_changes.begin();
|
||||
|
||||
// Collect the object extruders.
|
||||
for (auto layer : object.layers()) {
|
||||
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
||||
@ -253,6 +264,15 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
||||
// 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;
|
||||
|
||||
// Append the extruder needed to be picked before performing the color change.
|
||||
for (; it_per_layer_color_changes != per_layer_color_changes.end() && it_per_layer_color_changes->first < layer->print_z + EPSILON; ++it_per_layer_color_changes) {
|
||||
if (std::abs(it_per_layer_color_changes->first - layer->print_z) < EPSILON) {
|
||||
assert(layer_tools.extruder_needed_for_color_changer == 0); // Just on color change per layer is allowed.
|
||||
layer_tools.extruder_needed_for_color_changer = it_per_layer_color_changes->second;
|
||||
layer_tools.extruders.emplace_back(it_per_layer_color_changes->second);
|
||||
}
|
||||
}
|
||||
|
||||
// What extruders are required to print this object layer?
|
||||
for (const LayerRegion *layerm : layer->regions()) {
|
||||
const PrintRegion ®ion = layerm->region();
|
||||
@ -370,6 +390,11 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id)
|
||||
std::swap(lt.extruders[i], lt.extruders.front());
|
||||
break;
|
||||
}
|
||||
} else if (lt.extruder_needed_for_color_changer != 0) {
|
||||
// Put the extruder needed for performing the color change at the beginning.
|
||||
auto it = std::find(lt.extruders.begin(), lt.extruders.end(), lt.extruder_needed_for_color_changer);
|
||||
assert(it != lt.extruders.end());
|
||||
std::rotate(lt.extruders.begin(), it, it + 1);
|
||||
}
|
||||
}
|
||||
last_extruder_id = lt.extruders.back();
|
||||
|
@ -98,6 +98,9 @@ public:
|
||||
// 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 = 0;
|
||||
// For multi-extruder printers, when there is a color change, this contains an extruder (1 based) on which the color change will be performed.
|
||||
// Otherwise, it is set to 0.
|
||||
unsigned int extruder_needed_for_color_changer = 0;
|
||||
// Should a skirt be printed at this layer?
|
||||
// Layers are marked for infinite skirt aka draft shield. Not all the layers have to be printed.
|
||||
bool has_skirt = false;
|
||||
@ -169,7 +172,7 @@ public:
|
||||
|
||||
private:
|
||||
void initialize_layers(std::vector<coordf_t> &zs);
|
||||
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches);
|
||||
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches, const std::vector<std::pair<double, unsigned int>> &per_layer_color_changes);
|
||||
void reorder_extruders(unsigned int last_extruder_id);
|
||||
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height);
|
||||
bool insert_wipe_tower_extruder();
|
||||
|
@ -1,7 +1,7 @@
|
||||
///|/ Copyright (c) Prusa Research 2021 - 2023 Enrico Turri @enricoturri1966, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Lukáš Hejl @hejllukas, Roman Beránek @zavorka
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
///|/ Copyright (c) Prusa Research 2021 - 2023 Enrico Turri @enricoturri1966, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Lukáš Hejl @hejllukas, Roman Beránek @zavorka
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "Model.hpp"
|
||||
#include "Print.hpp"
|
||||
|
||||
@ -169,34 +169,37 @@ static bool layer_height_ranges_equal(const t_layer_config_ranges &lr1, const t_
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if va == vb when all CustomGCode items that are not ToolChangeCode are ignored.
|
||||
static bool custom_per_printz_gcodes_tool_changes_differ(const std::vector<CustomGCode::Item> &va, const std::vector<CustomGCode::Item> &vb)
|
||||
{
|
||||
// Returns true if va == vb when all CustomGCode items that are not the specified type (not_ignore_type) are ignored.
|
||||
static bool custom_per_printz_gcodes_tool_changes_differ(
|
||||
const std::vector<CustomGCode::Item> &va,
|
||||
const std::vector<CustomGCode::Item> &vb,
|
||||
CustomGCode::Type not_ignore_type
|
||||
) {
|
||||
auto it_a = va.begin();
|
||||
auto it_b = vb.begin();
|
||||
while (it_a != va.end() || it_b != vb.end()) {
|
||||
if (it_a != va.end() && it_a->type != CustomGCode::ToolChange) {
|
||||
// Skip any CustomGCode items, which are not tool changes.
|
||||
if (it_a != va.end() && it_a->type != not_ignore_type) {
|
||||
// Skip any CustomGCode items, which are not equal to not_ignore_type.
|
||||
++ it_a;
|
||||
continue;
|
||||
}
|
||||
if (it_b != vb.end() && it_b->type != CustomGCode::ToolChange) {
|
||||
// Skip any CustomGCode items, which are not tool changes.
|
||||
if (it_b != vb.end() && it_b->type != not_ignore_type) {
|
||||
// Skip any CustomGCode items, which are not equal to not_ignore_type.
|
||||
++ it_b;
|
||||
continue;
|
||||
}
|
||||
if (it_a == va.end() || it_b == vb.end())
|
||||
// va or vb contains more Tool Changes than the other.
|
||||
// va or vb contains more items of not_ignore_type than the other.
|
||||
return true;
|
||||
assert(it_a->type == CustomGCode::ToolChange);
|
||||
assert(it_b->type == CustomGCode::ToolChange);
|
||||
assert(it_a->type == not_ignore_type);
|
||||
assert(it_b->type == not_ignore_type);
|
||||
if (*it_a != *it_b)
|
||||
// The two Tool Changes differ.
|
||||
// The two items of not_ignore_type differ.
|
||||
return true;
|
||||
++ it_a;
|
||||
++ it_b;
|
||||
}
|
||||
// There is no change in custom Tool Changes.
|
||||
// There is no change in specified not_ignore_type items.
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1059,11 +1062,20 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
model_object_status_db.add(*model_object, ModelObjectStatus::New);
|
||||
} else {
|
||||
if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) {
|
||||
update_apply_status(num_extruders_changed ||
|
||||
// Tool change G-codes are applied as color changes for a single extruder printer, no need to invalidate tool ordering.
|
||||
//FIXME The tool ordering may be invalidated unnecessarily if the custom_gcode_per_print_z.mode is not applicable
|
||||
// to the active print / model state, and then it is reset, so it is being applicable, but empty, thus the effect is the same.
|
||||
(num_extruders > 1 && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes)) ?
|
||||
const CustomGCode::Mode current_mode = m_model.custom_gcode_per_print_z.mode;
|
||||
const CustomGCode::Mode next_mode = model.custom_gcode_per_print_z.mode;
|
||||
|
||||
const bool multi_extruder_differ = (current_mode == next_mode) && (current_mode == CustomGCode::MultiExtruder || next_mode == CustomGCode::MultiExtruder);
|
||||
// Tool change G-codes are applied as color changes for a single extruder printer, no need to invalidate tool ordering.
|
||||
// FIXME The tool ordering may be invalidated unnecessarily if the custom_gcode_per_print_z.mode is not applicable
|
||||
// to the active print / model state, and then it is reset, so it is being applicable, but empty, thus the effect is the same.
|
||||
const bool tool_change_differ = num_extruders > 1 && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes, CustomGCode::ToolChange);
|
||||
// For multi-extruder printers, we perform a tool change before a color change.
|
||||
// So, in that case, we must invalidate tool ordering and wipe tower even if custom color change g-codes differ.
|
||||
const bool color_change_differ = num_extruders > 1 && (next_mode == CustomGCode::MultiExtruder) && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes, CustomGCode::ColorChange);
|
||||
|
||||
update_apply_status(
|
||||
(num_extruders_changed || tool_change_differ || multi_extruder_differ || color_change_differ) ?
|
||||
// The Tool Ordering and the Wipe Tower are no more valid.
|
||||
this->invalidate_steps({ psWipeTower, psGCodeExport }) :
|
||||
// There is no change in Tool Changes stored in custom_gcode_per_print_z, therefore there is no need to update Tool Ordering.
|
||||
|
@ -5397,6 +5397,8 @@ static std::map<t_custom_gcode_key, t_config_option_keys> s_CustomGcodeSpecificP
|
||||
{"before_layer_gcode", {"layer_num", "layer_z", "max_layer_z"}},
|
||||
{"layer_gcode", {"layer_num", "layer_z", "max_layer_z"}},
|
||||
{"toolchange_gcode", {"layer_num", "layer_z", "max_layer_z", "previous_extruder", "next_extruder", "toolchange_z"}},
|
||||
{"color_change_gcode", {"color_change_extruder"}},
|
||||
{"pause_print_gcode", {"color_change_extruder"}},
|
||||
};
|
||||
|
||||
const std::map<t_custom_gcode_key, t_config_option_keys>& custom_gcode_specific_placeholders()
|
||||
@ -5435,6 +5437,10 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef()
|
||||
def = this->add("toolchange_z", coFloat);
|
||||
def->label = L("Toolchange Z");
|
||||
def->tooltip = L("Height above the print bed when the toolchange takes place. Usually the same as layer_z, but can be different.");
|
||||
|
||||
def = this->add("color_change_extruder", coInt);
|
||||
def->label = L("Color change extruder");
|
||||
def->tooltip = L("Index of the extruder for which color change will be performed. The index is zero based (first extruder has index 0).");
|
||||
}
|
||||
|
||||
const CustomGcodeSpecificConfigDef custom_gcode_specific_config_def;
|
||||
|
Loading…
x
Reference in New Issue
Block a user