From 499fdeddd1f1ef3051e97983bea9560268a8534c Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 9 Sep 2019 12:59:17 +0200 Subject: [PATCH 1/2] Custom toolchange gcode is searched for tool-changing command If the custom toolchange gcode switches extruder to the one that is expected, PrusaSlicer does not issue its own T command Otherwise, this command is inserted just after the custom gcode, even in case it is not empty This should prevent issues such as #2884 and #2886 from being reported --- src/libslic3r/GCode.cpp | 39 +++++++++++++++++++++++++++++++---- src/libslic3r/PrintConfig.cpp | 8 +++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index e090ff8da..cd8319869 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -51,6 +51,35 @@ static inline void check_add_eol(std::string &gcode) gcode += '\n'; } + +// Return true if tch_prefix is found in custom_gcode +static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder) +{ + bool ok = false; + size_t from_pos = 0; + size_t pos = 0; + while ((pos = custom_gcode.find(tch_prefix, from_pos)) != std::string::npos) { + if (pos+1 == custom_gcode.size()) + break; + from_pos = pos+1; + // only whitespace is allowed before the command + while (--pos < custom_gcode.size() && custom_gcode[pos] != '\n') { + if (! std::isspace(custom_gcode[pos])) + continue; + } + // we should also check that the extruder changes to what was expected + std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos)); + unsigned num = 0; + if (ss >> num) { + if (num == next_extruder) + ok = true; + else + ok = false; + } + } + return ok; +} + void AvoidCrossingPerimeters::init_external_mp(const Print &print) { m_external_mp = Slic3r::make_unique(union_ex(this->collect_contours_all_layers(print.objects()))); @@ -314,8 +343,8 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T std::string toolchange_command; if (tcr.priming || (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id))) toolchange_command = gcodegen.writer().toolchange(new_extruder_id); - if (toolchange_gcode.empty()) - toolchange_gcode_str = toolchange_command; + if (! custom_gcode_changes_tool(toolchange_gcode_str, gcodegen.writer().toolchange_prefix(), new_extruder_id)) + toolchange_gcode_str += toolchange_command; else { // We have informed the m_writer about the current extruder_id, we can ignore the generated G-code. } @@ -2928,6 +2957,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z) gcode += m_ooze_prevention.pre_toolchange(*this); const std::string& toolchange_gcode = m_config.toolchange_gcode.value; + std::string toolchange_gcode_parsed; // Process the custom toolchange_gcode. If it is empty, insert just a Tn command. if (!toolchange_gcode.empty()) { @@ -2936,13 +2966,14 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z) config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); - gcode += placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config); + toolchange_gcode_parsed = placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config); + gcode += toolchange_gcode_parsed; check_add_eol(gcode); } // We inform the writer about what is happening, but we may not use the resulting gcode. std::string toolchange_command = m_writer.toolchange(extruder_id); - if (toolchange_gcode.empty()) + if (! custom_gcode_changes_tool(toolchange_gcode_parsed, m_writer.toolchange_prefix(), extruder_id)) gcode += toolchange_command; else { // user provided his own toolchange gcode, no need to do anything diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 5236e4e04..6ea94726d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2054,10 +2054,10 @@ void PrintConfigDef::init_fff_params() def = this->add("toolchange_gcode", coString); def->label = L("Tool change G-code"); - def->tooltip = L("This custom code is inserted at every extruder change. If you don't leave this empty, you are " - "expected to take care of the toolchange yourself - PrusaSlicer will not output any other G-code to " - "change the filament. You can use placeholder variables for all Slic3r settings as well as [previous_extruder] " - "and [next_extruder], so e.g. the standard toolchange command can be scripted as T[next_extruder]."); + def->tooltip = L("This custom code is inserted before every toolchange. You can use placeholder variables for all Slic3r settings " + "as well as {previous_extruder} and {next_extruder}. If you explicitely include tool-changing command (such as T{next_extruder}), " + "which changes to the correct extruder, no other such command will be emitted. This allows you to do custom stuff " + "both before and after the toolchange."); def->multiline = true; def->full_width = true; def->height = 5; From 822bc7a91cd98738a0c2725654b88eb5922a2416 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 9 Sep 2019 16:02:39 +0200 Subject: [PATCH 2/2] Fix of previous commit, tooltip update --- src/libslic3r/GCode.cpp | 17 ++++++++--------- src/libslic3r/PrintConfig.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index cd8319869..97da766c9 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -65,17 +65,16 @@ static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std // only whitespace is allowed before the command while (--pos < custom_gcode.size() && custom_gcode[pos] != '\n') { if (! std::isspace(custom_gcode[pos])) - continue; + goto NEXT; } - // we should also check that the extruder changes to what was expected - std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos)); - unsigned num = 0; - if (ss >> num) { - if (num == next_extruder) - ok = true; - else - ok = false; + { + // we should also check that the extruder changes to what was expected + std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos)); + unsigned num = 0; + if (ss >> num) + ok = (num == next_extruder); } +NEXT: ; } return ok; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 6ea94726d..89fdc4f26 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2054,10 +2054,10 @@ void PrintConfigDef::init_fff_params() def = this->add("toolchange_gcode", coString); def->label = L("Tool change G-code"); - def->tooltip = L("This custom code is inserted before every toolchange. You can use placeholder variables for all Slic3r settings " - "as well as {previous_extruder} and {next_extruder}. If you explicitely include tool-changing command (such as T{next_extruder}), " - "which changes to the correct extruder, no other such command will be emitted. This allows you to do custom stuff " - "both before and after the toolchange."); + def->tooltip = L("This custom code is inserted before every toolchange. You can use placeholder variables for all PrusaSlicer settings " + "as well as {previous_extruder} and {next_extruder}. Explicitely including a tool-changing command (such as T{next_extruder}), " + "which changes to the correct extruder, no other such command will be emitted. It is therefore possible to script custom " + "behaviour both before and after the toolchange."); def->multiline = true; def->full_width = true; def->height = 5;