From 1fee3633a05870c5cb83c7e850f1c0e22c4d1276 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 30 Oct 2017 18:15:41 +0100 Subject: New C++ class AppConfig for maintaining the config.ini New helper function for generating a unified "generated by slic3r" header. --- xs/src/libslic3r/GCode.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 48bf28882..b66861a4a 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -4,6 +4,7 @@ #include "Geometry.hpp" #include "GCode/PrintExtents.hpp" #include "GCode/WipeTowerPrusaMM.hpp" +#include "Utils.hpp" #include #include @@ -11,7 +12,6 @@ #include #include -#include #include #include @@ -462,15 +462,7 @@ bool GCode::_do_export(Print &print, FILE *file) m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; // Write information on the generator. - { - const auto now = boost::posix_time::second_clock::local_time(); - const auto date = now.date(); - fprintf(file, "; generated by Slic3r %s on %04d-%02d-%02d at %02d:%02d:%02d\n\n", - SLIC3R_VERSION, - // Local date in an ANSII format. - int(now.date().year()), int(now.date().month()), int(now.date().day()), - int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds())); - } + fprintf(file, "# %s\n\n", Slic3r::header_slic3r_generated().c_str()); // Write notes (content of the Print Settings tab -> Notes) { std::list lines; -- cgit v1.2.3 From ee84e1773d76f2e993703f4f3d05d13c03c0b2b5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 2 Nov 2017 16:50:08 +0100 Subject: Fixed an incorrect comment separator in generated g-code. --- xs/src/libslic3r/GCode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b66861a4a..93f324a1d 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -462,7 +462,7 @@ bool GCode::_do_export(Print &print, FILE *file) m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; // Write information on the generator. - fprintf(file, "# %s\n\n", Slic3r::header_slic3r_generated().c_str()); + fprintf(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str()); // Write notes (content of the Print Settings tab -> Notes) { std::list lines; -- cgit v1.2.3 From 71b58e24a9671f6a6d9f1e0703505090fd755266 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 6 Nov 2017 15:43:56 +0100 Subject: Fixed a regression bug in the "first layer extrusion width" G-code comment. https://github.com/prusa3d/Slic3r/issues/566 --- xs/src/libslic3r/GCode.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 93f324a1d..f46d35657 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -480,6 +480,7 @@ bool GCode::_do_export(Print &print, FILE *file) { const PrintObject *first_object = print.objects.front(); const double layer_height = first_object->config.layer_height.value; + const double first_layer_height = first_object->config.first_layer_height.get_abs_value(layer_height); for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) { auto region = print.regions[region_id]; fprintf(file, "; external perimeters extrusion width = %.2fmm\n", region->flow(frExternalPerimeter, layer_height, false, false, -1., *first_object).width); @@ -490,7 +491,7 @@ bool GCode::_do_export(Print &print, FILE *file) if (print.has_support_material()) fprintf(file, "; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width); if (print.config.first_layer_extrusion_width.value > 0) - fprintf(file, "; first layer extrusion width = %.2fmm\n", region->flow(frPerimeter, layer_height, false, true, -1., *first_object).width); + fprintf(file, "; first layer extrusion width = %.2fmm\n", region->flow(frPerimeter, first_layer_height, false, true, -1., *first_object).width); fprintf(file, "\n"); } } -- cgit v1.2.3 From 47f193fe2dd78fd1f5d058ade3ff897ce85cfdb8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 17 Nov 2017 11:15:46 +0100 Subject: The PlaceholderParser has been rewritten to use a real boost::spirit::qi parser, accessing the DynamicConfig repository directly. This is a first step towards a full fledged expression interpreter. --- xs/src/libslic3r/GCode.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index f46d35657..12444d1a5 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -887,18 +887,22 @@ void GCode::process_layer( // Set new layer - this will change Z and force a retraction if retract_layer_change is enabled. if (! print.config.before_layer_gcode.value.empty()) { - PlaceholderParser pp(m_placeholder_parser); - pp.set("layer_num", m_layer_index + 1); - pp.set("layer_z", print_z); - gcode += pp.process(print.config.before_layer_gcode.value, m_writer.extruder()->id()) + "\n"; + DynamicConfig config; + config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1)); + config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); + gcode += m_placeholder_parser.process( + print.config.before_layer_gcode.value, m_writer.extruder()->id(), &config) + + "\n"; } gcode += this->change_layer(print_z); // this will increase m_layer_index m_layer = &layer; if (! print.config.layer_gcode.value.empty()) { - PlaceholderParser pp(m_placeholder_parser); - pp.set("layer_num", m_layer_index); - pp.set("layer_z", print_z); - gcode += pp.process(print.config.layer_gcode.value, m_writer.extruder()->id()) + "\n"; + DynamicConfig config; + config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); + config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); + gcode += m_placeholder_parser.process( + print.config.layer_gcode.value, m_writer.extruder()->id(), &config) + + "\n"; } if (! first_layer && ! m_second_layer_things_done) { @@ -2091,10 +2095,12 @@ std::string GCode::set_extruder(unsigned int extruder_id) // append custom toolchange G-code if (m_writer.extruder() != nullptr && !m_config.toolchange_gcode.value.empty()) { - PlaceholderParser pp = m_placeholder_parser; - pp.set("previous_extruder", m_writer.extruder()->id()); - pp.set("next_extruder", extruder_id); - gcode += pp.process(m_config.toolchange_gcode.value, extruder_id) + '\n'; + DynamicConfig config; + config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id())); + config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); + gcode += m_placeholder_parser.process( + m_config.toolchange_gcode.value, extruder_id, &config) + + '\n'; } // if ooze prevention is enabled, park current extruder in the nearest -- cgit v1.2.3 From bb2b180ecc9d3e3dad063c87e9054ee0829ca9a8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 26 Nov 2017 21:23:18 +0100 Subject: Fixed G-code export of custom G-code sections to not add a newline if the custom G-code already ends with a newline. --- xs/src/libslic3r/GCode.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 12444d1a5..3c406389e 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -264,11 +264,14 @@ inline void write(FILE *file, const std::string &what) fwrite(what.data(), 1, what.size(), file); } +// Write a string into a file. Add a newline, if the string does not end with a newline already. +// Used to export a custom G-code section processed by the PlaceholderParser. inline void writeln(FILE *file, const std::string &what) { if (! what.empty()) { write(file, what); - fprintf(file, "\n"); + if (what.back() != '\n') + fprintf(file, "\n"); } } -- cgit v1.2.3 From 672194b475e2ec6d25ed2cc3e6164144a9f7d84e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 28 Nov 2017 15:19:57 +0100 Subject: Ported the between_objects_gcode custom G-code blocks, thanks @lordofhyphens, https://github.com/alexrj/Slic3r/pull/3275 Improved handling of custom G-code blocks: Slic3r will try to extract the target extruder and bed temperatures from the custom G-code blocks. --- xs/src/libslic3r/GCode.cpp | 121 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 22 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 3c406389e..441d254f6 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -538,29 +538,23 @@ bool GCode::_do_export(Print &print, FILE *file) // Disable fan. if (! print.config.cooling.get_at(initial_extruder_id) || print.config.disable_fan_first_layers.get_at(initial_extruder_id)) write(file, m_writer.set_fan(0, true)); - - // Set bed temperature if the start G-code does not contain any bed temp control G-codes. - { - // Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if - // the custom start G-code emited these. - //FIXME Should one parse the custom G-code to initialize the "current" bed temp state at m_writer? - std::string gcode = m_writer.set_bed_temperature(print.config.first_layer_bed_temperature.get_at(initial_extruder_id), true); - if (boost::ifind_first(print.config.start_gcode.value, std::string("M140")).empty() && - boost::ifind_first(print.config.start_gcode.value, std::string("M190")).empty()) - write(file, gcode); - } - // Set extruder(s) temperature before and after start G-code. - this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false); // Let the start-up script prime the 1st printing tool. m_placeholder_parser.set("initial_tool", initial_extruder_id); m_placeholder_parser.set("initial_extruder", initial_extruder_id); m_placeholder_parser.set("current_extruder", initial_extruder_id); - writeln(file, m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id)); + std::string start_gcode = m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id); + + // Set bed temperature if the start G-code does not contain any bed temp control G-codes. + this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true); + // Set extruder(s) temperature before and after start G-code. + this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false); + // Write the custom start G-code + writeln(file, start_gcode); // Process filament-specific gcode in extruder order. for (const std::string &start_gcode : print.config.start_filament_gcode.values) writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); - this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, true); + this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true); // Set other general things. write(file, this->preamble()); @@ -650,9 +644,11 @@ bool GCode::_do_export(Print &print, FILE *file) // Ff we are printing the bottom layer of an object, and we have already finished // another one, set first layer temperatures. This happens before the Z move // is triggered, so machine has more time to reach such temperatures. - write(file, m_writer.set_bed_temperature(print.config.first_layer_bed_temperature.get_at(initial_extruder_id))); - // Set first layer extruder. - this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false); + std::string between_objects_gcode = m_placeholder_parser.process(print.config.between_objects_gcode.value, initial_extruder_id); + // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. + this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); + this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false); + writeln(file, between_objects_gcode); } // Reset the cooling buffer internal state (the current position, feed rate, accelerations). m_cooling_buffer->reset(); @@ -774,15 +770,96 @@ bool GCode::_do_export(Print &print, FILE *file) return true; } +// Parse the custom G-code, try to find mcode_set_temp_dont_wait and mcode_set_temp_and_wait inside the custom G-code. +// Returns true if one of the temp commands are found, and try to parse the target temperature value into temp_out. +static bool custom_gcode_sets_temperature(const std::string &gcode, const int mcode_set_temp_dont_wait, const int mcode_set_temp_and_wait, int &temp_out) +{ + temp_out = -1; + if (gcode.empty()) + return false; + + const char *ptr = gcode.data(); + bool temp_set_by_gcode = false; + while (*ptr != 0) { + // Skip whitespaces. + for (; *ptr == ' ' || *ptr == '\t'; ++ ptr); + if (*ptr == 'M') { + // Line starts with 'M'. It is a machine command. + ++ ptr; + // Parse the M code value. + char *endptr = nullptr; + int mcode = int(strtol(ptr, &endptr, 10)); + if (endptr != nullptr && endptr != ptr && (mcode == mcode_set_temp_dont_wait || mcode == mcode_set_temp_and_wait)) { + // M104/M109 or M140/M190 found. + ptr = endptr; + // Let the caller know that the custom G-code sets the temperature. + temp_set_by_gcode = true; + // Now try to parse the temperature value. + // While not at the end of the line: + while (strchr(";\r\n\0", *ptr) == nullptr) { + // Skip whitespaces. + for (; *ptr == ' ' || *ptr == '\t'; ++ ptr); + if (*ptr == 'S') { + // Skip whitespaces. + for (++ ptr; *ptr == ' ' || *ptr == '\t'; ++ ptr); + // Parse an int. + endptr = nullptr; + long temp_parsed = strtol(ptr, &endptr, 10); + if (endptr > ptr) { + ptr = endptr; + temp_out = temp_parsed; + } + } else { + // Skip this word. + for (; strchr(" \t;\r\n\0", *ptr) == nullptr; ++ ptr); + } + } + } + } + // Skip the rest of the line. + for (; *ptr != 0 && *ptr != '\r' && *ptr != '\n'; ++ ptr); + // Skip the end of line indicators. + for (; *ptr == '\r' || *ptr == '\n'; ++ ptr); + } + return temp_set_by_gcode; +} + +// Write 1st layer bed temperatures into the G-code. +// Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. +// M140 - Set Extruder Temperature +// M190 - Set Extruder Temperature and Wait +void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) +{ + // Initial bed temperature based on the first extruder. + int temp = print.config.first_layer_bed_temperature.get_at(first_printing_extruder_id); + // Is the bed temperature set by the provided custom G-code? + int temp_by_gcode = -1; + bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, temp_by_gcode); + if (temp_by_gcode >= 0 && temp_by_gcode < 1000) + temp = temp_by_gcode; + // Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if + // the custom start G-code emited these. + std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait); + if (! temp_by_gcode) + write(file, set_temp_gcode); +} + // Write 1st layer extruder temperatures into the G-code. // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. -// FIXME this does not work correctly for multi-extruder, single heater configuration as it emits multiple preheat commands for the same heater. // M104 - Set Extruder Temperature // M109 - Set Extruder Temperature and Wait -void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, unsigned int first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) { - if (boost::ifind_first(print.config.start_gcode.value, std::string("M104")).empty() && - boost::ifind_first(print.config.start_gcode.value, std::string("M109")).empty()) { + // Is the bed temperature set by the provided custom G-code? + int temp_by_gcode = -1; + if (custom_gcode_sets_temperature(gcode, 104, 109, temp_by_gcode)) { + // Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code. + int temp = print.config.first_layer_temperature.get_at(first_printing_extruder_id); + if (temp_by_gcode >= 0 && temp_by_gcode < 1000) + temp = temp_by_gcode; + m_writer.set_temperature(temp_by_gcode, wait, first_printing_extruder_id); + } else { + // Custom G-code does not set the extruder temperature. Do it now. if (print.config.single_extruder_multi_material.value) { // Set temperature of the first printing extruder only. int temp = print.config.first_layer_temperature.get_at(first_printing_extruder_id); -- cgit v1.2.3 From 9ca63f16bc23207c06ce51e2486fc9ce5036114f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 28 Nov 2017 15:30:05 +0100 Subject: New PlaceholderParser variable for sequential prints: current_object_idx - zero based index of the object printed. Implements feature request https://github.com/prusa3d/Slic3r/issues/578 --- xs/src/libslic3r/GCode.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 441d254f6..ff144610e 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -543,6 +543,8 @@ bool GCode::_do_export(Print &print, FILE *file) m_placeholder_parser.set("initial_tool", initial_extruder_id); m_placeholder_parser.set("initial_extruder", initial_extruder_id); m_placeholder_parser.set("current_extruder", initial_extruder_id); + // Useful for sequential prints. + m_placeholder_parser.set("current_object_idx", 0); std::string start_gcode = m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id); // Set bed temperature if the start G-code does not contain any bed temp control G-codes. @@ -644,6 +646,7 @@ bool GCode::_do_export(Print &print, FILE *file) // Ff we are printing the bottom layer of an object, and we have already finished // another one, set first layer temperatures. This happens before the Z move // is triggered, so machine has more time to reach such temperatures. + m_placeholder_parser.set("current_object_idx", int(finished_objects)); std::string between_objects_gcode = m_placeholder_parser.process(print.config.between_objects_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); -- cgit v1.2.3 From 3996535e5dea9d223fe5ad9e628bb3b841aeff63 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 16:01:47 +0100 Subject: Changed handling of filament_gcode_start and filament_gcode_end custom G-codes in case of single extruder multiple material setup: At the start of the print, the filament_gcode_start is executed for the active extruder only, and the filament_gcode_start / filament_gcode_end are then executed at each tool change. When the Prusa MM wipe tower is active, the tool changes are handled a bit differently: M900 K0 is emited before the wipe tower extrusions start, and the filament_gcode_start code is executed after the wipe tower extrusions are done. This rule effectively disables the linear advance over the wipe tower. Implements https://github.com/prusa3d/Slic3r/issues/568 --- xs/src/libslic3r/GCode.cpp | 90 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 18 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index ff144610e..3bdc8d321 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -30,6 +30,13 @@ #include namespace Slic3r { + +// Only add a newline in case the current G-code does not end with a newline. +static inline void check_add_eol(std::string &gcode) +{ + if (! gcode.empty() && gcode.back() != '\n') + gcode += '\n'; +} // Plan a travel move while minimizing the number of perimeter crossings. // point is in unscaled coordinates, in the coordinate system of the current active object @@ -157,6 +164,8 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T { std::string gcode; + // Disable linear advance for the wipe tower operations. + gcode += "M900 K0\n"; // Move over the wipe tower. // Retract for a tool change, using the toolchange retract value and setting the priming extra length. gcode += gcodegen.retract(true); @@ -171,8 +180,17 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T // Inform the G-code writer about the changes done behind its back. gcode += tcr.gcode; // Let the m_writer know the current extruder_id, but ignore the generated G-code. - if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)) + if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)) { gcodegen.writer().toolchange(new_extruder_id); + // Append the filament start G-code. + const std::string &start_filament_gcode = gcodegen.config().start_filament_gcode.get_at(new_extruder_id); + if (! start_filament_gcode.empty()) { + // Process the start_filament_gcode for the active filament only. + gcodegen.placeholder_parser().set("current_extruder", new_extruder_id); + gcode += gcodegen.placeholder_parser().process(start_filament_gcode, new_extruder_id); + check_add_eol(gcode); + } + } // A phony move to the end position at the wipe tower. gcodegen.writer().travel_to_xy(Pointf(tcr.end_pos.x, tcr.end_pos.y)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos)); @@ -199,15 +217,25 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen) std::string gcode; if (&m_priming != nullptr && ! m_priming.extrusions.empty()) { + // Disable linear advance for the wipe tower operations. + gcode += "M900 K0\n"; // Let the tool change be executed by the wipe tower class. // Inform the G-code writer about the changes done behind its back. gcode += m_priming.gcode; // Let the m_writer know the current extruder_id, but ignore the generated G-code. - gcodegen.writer().toolchange(m_priming.extrusions.back().tool); + unsigned int current_extruder_id = m_priming.extrusions.back().tool; + gcodegen.writer().toolchange(current_extruder_id); + gcodegen.placeholder_parser().set("current_extruder", current_extruder_id); // A phony move to the end position at the wipe tower. gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos)); - + // Append the filament start G-code, so the linear advance value will be restored. + const std::string &start_filament_gcode = gcodegen.config().start_filament_gcode.get_at(current_extruder_id); + if (! start_filament_gcode.empty()) { + // Process the start_filament_gcode for the active filament only to restore the linear advance value. + gcode += gcodegen.placeholder_parser().process(start_filament_gcode, current_extruder_id); + check_add_eol(gcode); + } // Prepare a future wipe. gcodegen.m_wipe.path.points.clear(); // Start the wipe at the current position. @@ -554,8 +582,10 @@ bool GCode::_do_export(Print &print, FILE *file) // Write the custom start G-code writeln(file, start_gcode); // Process filament-specific gcode in extruder order. - for (const std::string &start_gcode : print.config.start_filament_gcode.values) - writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); + if (! print.config.single_extruder_multi_material) { + for (const std::string &start_gcode : print.config.start_filament_gcode.values) + writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); + } this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true); // Set other general things. @@ -727,8 +757,13 @@ bool GCode::_do_export(Print &print, FILE *file) write(file, this->retract()); write(file, m_writer.set_fan(false)); // Process filament-specific gcode in extruder order. - for (const std::string &end_gcode : print.config.end_filament_gcode.values) - writeln(file, m_placeholder_parser.process(end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()))); + if (print.config.single_extruder_multi_material) { + // Process the end_filament_gcode for the active filament only. + writeln(file, m_placeholder_parser.process(print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id())); + } else { + for (const std::string &end_gcode : print.config.end_filament_gcode.values) + writeln(file, m_placeholder_parser.process(end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()))); + } writeln(file, m_placeholder_parser.process(print.config.end_gcode, m_writer.extruder()->id())); write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% write(file, m_writer.postamble()); @@ -2162,13 +2197,14 @@ GCode::retract(bool toolchange) std::string GCode::set_extruder(unsigned int extruder_id) { - m_placeholder_parser.set("current_extruder", extruder_id); if (!m_writer.need_toolchange(extruder_id)) return ""; // if we are running a single-extruder setup, just set the extruder and return nothing - if (!m_writer.multiple_extruders) + if (!m_writer.multiple_extruders) { + m_placeholder_parser.set("current_extruder", extruder_id); return m_writer.toolchange(extruder_id); + } // prepend retraction on the current extruder std::string gcode = this->retract(true); @@ -2176,23 +2212,41 @@ std::string GCode::set_extruder(unsigned int extruder_id) // Always reset the extrusion path, even if the tool change retract is set to zero. m_wipe.reset_path(); - // append custom toolchange G-code - if (m_writer.extruder() != nullptr && !m_config.toolchange_gcode.value.empty()) { + if (m_writer.extruder() != nullptr) { + // Process the custom end_filament_gcode in case of single_extruder_multi_material. + unsigned int old_extruder_id = m_writer.extruder()->id(); + const std::string &end_filament_gcode = m_config.end_filament_gcode.get_at(old_extruder_id); + if (m_config.single_extruder_multi_material && ! end_filament_gcode.empty()) { + gcode += m_placeholder_parser.process(end_filament_gcode, old_extruder_id); + check_add_eol(gcode); + } + } + + m_placeholder_parser.set("current_extruder", extruder_id); + + if (m_writer.extruder() != nullptr && ! m_config.toolchange_gcode.value.empty()) { + // Process the custom toolchange_gcode. DynamicConfig config; config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id())); config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); - gcode += m_placeholder_parser.process( - m_config.toolchange_gcode.value, extruder_id, &config) - + '\n'; + gcode += m_placeholder_parser.process(m_config.toolchange_gcode.value, extruder_id, &config); + check_add_eol(gcode); } - // if ooze prevention is enabled, park current extruder in the nearest - // standby point and set it to the standby temperature + // If ooze prevention is enabled, park current extruder in the nearest + // standby point and set it to the standby temperature. if (m_ooze_prevention.enable && m_writer.extruder() != nullptr) gcode += m_ooze_prevention.pre_toolchange(*this); - // append the toolchange command + // Append the toolchange command. gcode += m_writer.toolchange(extruder_id); - // set the new extruder to the operating temperature + // Append the filament start G-code for single_extruder_multi_material. + const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id); + if (m_config.single_extruder_multi_material && ! start_filament_gcode.empty()) { + // Process the start_filament_gcode for the active filament only. + gcode += m_placeholder_parser.process(start_filament_gcode, extruder_id); + check_add_eol(gcode); + } + // Set the new extruder to the operating temperature. if (m_ooze_prevention.enable) gcode += m_ooze_prevention.post_toolchange(*this); -- cgit v1.2.3 From cecaf6eabcba735837d9c631bbb79cf9b4aed6b4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 17:55:39 +0100 Subject: Slight optimization of the filament_start_gcode insertion: It is not needed between the purging towers and the wipe tower brim. --- xs/src/libslic3r/GCode.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 3bdc8d321..4e5f8b8fa 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -229,13 +229,6 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen) // A phony move to the end position at the wipe tower. gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos)); - // Append the filament start G-code, so the linear advance value will be restored. - const std::string &start_filament_gcode = gcodegen.config().start_filament_gcode.get_at(current_extruder_id); - if (! start_filament_gcode.empty()) { - // Process the start_filament_gcode for the active filament only to restore the linear advance value. - gcode += gcodegen.placeholder_parser().process(start_filament_gcode, current_extruder_id); - check_add_eol(gcode); - } // Prepare a future wipe. gcodegen.m_wipe.path.points.clear(); // Start the wipe at the current position. -- cgit v1.2.3 From ca0626b168a15381ab499fe7d8153934a7889078 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 1 Dec 2017 18:55:57 +0100 Subject: Fixed regression bugs regarding print validation, fixed crashes when loading a config.ini with "compatible_printers" disabled export of "compatible_printers" into gcode and config.ini Enabled compatibility of printing multiple objects with support / no support with a wipe tower. --- xs/src/libslic3r/GCode.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 4e5f8b8fa..a19fd8b53 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -794,7 +794,8 @@ bool GCode::_do_export(Print &print, FILE *file) for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++ i) { StaticPrintConfig *cfg = configs[i]; for (const std::string &key : cfg->keys()) - fprintf(file, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str()); + if (key != "compatible_printers") + fprintf(file, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str()); } } -- cgit v1.2.3 From 2b0b8e6e688fc60c79edb3f1282b7e06b60dfc17 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Dec 2017 11:57:54 +0100 Subject: Removed the hard-coded priming line when both single_extruder_multi_material and wipe_tower are enabled, and the print prints with a single extruder only. Newly the same situation will be handled through a conditional G-code in the following format: {if not has_wipe_tower} ; Do the priming {endif} --- xs/src/libslic3r/GCode.cpp | 75 ++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index a19fd8b53..bc3a86993 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -241,19 +241,6 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen) return gcode; } -std::string WipeTowerIntegration::prime_single_color_print(const Print & /* print */, unsigned int initial_tool, GCode & /* gcodegen */) -{ - std::string gcode = "\ -G1 Z0.250 F7200.000\n\ -G1 X50.0 E80.0 F1000.0\n\ -G1 X160.0 E20.0 F1000.0\n\ -G1 Z0.200 F7200.000\n\ -G1 X220.0 E13 F1000.0\n\ -G1 X240.0 E0 F1000.0\n\ -G1 E-4 F1000.0\n"; - return gcode; -} - std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, bool finish_layer) { std::string gcode; @@ -530,6 +517,7 @@ bool GCode::_do_export(Print &print, FILE *file) unsigned int initial_extruder_id = (unsigned int)-1; unsigned int final_extruder_id = (unsigned int)-1; size_t initial_print_object_id = 0; + bool has_wipe_tower = false; if (print.config.complete_objects.value) { // Find the 1st printing object, find its tool ordering and the initial extruder ID. for (; initial_print_object_id < print.objects.size(); ++initial_print_object_id) { @@ -544,6 +532,7 @@ bool GCode::_do_export(Print &print, FILE *file) ToolOrdering(print, initial_extruder_id) : print.m_tool_ordering; initial_extruder_id = tool_ordering.first_extruder(); + has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower(); } if (initial_extruder_id == (unsigned int)-1) { // Nothing to print! @@ -566,6 +555,8 @@ bool GCode::_do_export(Print &print, FILE *file) m_placeholder_parser.set("current_extruder", initial_extruder_id); // Useful for sequential prints. m_placeholder_parser.set("current_object_idx", 0); + // For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided. + m_placeholder_parser.set("has_wipe_tower", has_wipe_tower); std::string start_gcode = m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id); // Set bed temperature if the start G-code does not contain any bed temp control G-codes. @@ -575,7 +566,14 @@ bool GCode::_do_export(Print &print, FILE *file) // Write the custom start G-code writeln(file, start_gcode); // Process filament-specific gcode in extruder order. - if (! print.config.single_extruder_multi_material) { + if (print.config.single_extruder_multi_material) { + if (has_wipe_tower) { + // Wipe tower will control the extruder switching, it will call the start_filament_gcode. + } else { + // Only initialize the initial extruder. + writeln(file, m_placeholder_parser.process(print.config.start_filament_gcode.values[initial_extruder_id], initial_extruder_id)); + } + } else { for (const std::string &start_gcode : print.config.start_filament_gcode.values) writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); } @@ -705,32 +703,29 @@ bool GCode::_do_export(Print &print, FILE *file) // All extrusion moves with the same top layer height are extruded uninterrupted. std::vector>> layers_to_print = collect_layers_to_print(print); // Prusa Multi-Material wipe tower. - if (print.has_wipe_tower() && ! layers_to_print.empty()) { - if (tool_ordering.has_wipe_tower()) { - m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get())); - write(file, m_wipe_tower->prime(*this)); - // Verify, whether the print overaps the priming extrusions. - BoundingBoxf bbox_print(get_print_extrusions_extents(print)); - coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON; - for (const PrintObject *print_object : print.objects) - bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz)); - bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz)); - BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print)); - bbox_prime.offset(0.5f); - // Beep for 500ms, tone 800Hz. Yet better, play some Morse. - write(file, this->retract()); - fprintf(file, "M300 S800 P500\n"); - if (bbox_prime.overlap(bbox_print)) { - // Wait for the user to remove the priming extrusions, otherwise they would - // get covered by the print. - fprintf(file, "M1 Remove priming towers and click button.\n"); - } else { - // Just wait for a bit to let the user check, that the priming succeeded. - //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix. - fprintf(file, "M1 S10\n"); - } - } else - write(file, WipeTowerIntegration::prime_single_color_print(print, initial_extruder_id, *this)); + if (has_wipe_tower && ! layers_to_print.empty()) { + m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get())); + write(file, m_wipe_tower->prime(*this)); + // Verify, whether the print overaps the priming extrusions. + BoundingBoxf bbox_print(get_print_extrusions_extents(print)); + coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON; + for (const PrintObject *print_object : print.objects) + bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz)); + bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz)); + BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print)); + bbox_prime.offset(0.5f); + // Beep for 500ms, tone 800Hz. Yet better, play some Morse. + write(file, this->retract()); + fprintf(file, "M300 S800 P500\n"); + if (bbox_prime.overlap(bbox_print)) { + // Wait for the user to remove the priming extrusions, otherwise they would + // get covered by the print. + fprintf(file, "M1 Remove priming towers and click button.\n"); + } else { + // Just wait for a bit to let the user check, that the priming succeeded. + //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix. + fprintf(file, "M1 S10\n"); + } } // Extrude the layers. for (auto &layer : layers_to_print) { -- cgit v1.2.3 From 8746f84fa2b8585270d36b4070693a188e722e33 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 15:54:24 +0100 Subject: Improved error reporting of the PlaceholderParser. The PlaceholderParser is currently used by the GCode.cpp and by Printer.cpp to generate a new name for the exported G-code or SVG file. The PlaceholderParser::process() will throw a runtime_error with a comprehensive error message. The G-code export will include these error messages into the G-code text with !!!!!! separators, and the GUI will inform the user, that the G-code export failed. --- xs/src/libslic3r/GCode.cpp | 78 ++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 27 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index bc3a86993..b5f186630 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -187,7 +187,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T if (! start_filament_gcode.empty()) { // Process the start_filament_gcode for the active filament only. gcodegen.placeholder_parser().set("current_extruder", new_extruder_id); - gcode += gcodegen.placeholder_parser().process(start_filament_gcode, new_extruder_id); + gcode += gcodegen.placeholder_parser_process("start_filament_gcode", start_filament_gcode, new_extruder_id); check_add_eol(gcode); } } @@ -362,7 +362,7 @@ std::vector>> GCode::collec return layers_to_print; } -bool GCode::do_export(Print *print, const char *path) +void GCode::do_export(Print *print, const char *path) { // Remove the old g-code if it exists. boost::nowide::remove(path); @@ -372,23 +372,34 @@ bool GCode::do_export(Print *print, const char *path) FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb"); if (file == nullptr) - return false; + throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); - bool result = this->_do_export(*print, file); + this->m_placeholder_parser_failed_templates.clear(); + this->_do_export(*print, file); fclose(file); - - if (result && boost::nowide::rename(path_tmp.c_str(), path) != 0) { - boost::nowide::cerr << "Failed to remove the output G-code file from " << path_tmp << " to " << path - << ". Is " << path_tmp << " locked?" << std::endl; - result = false; - } - - if (! result) + if (ferror(file)) { boost::nowide::remove(path_tmp.c_str()); - return result; + throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); + } + if (! this->m_placeholder_parser_failed_templates.empty()) { + // G-code export proceeded, but some of the PlaceholderParser substitutions failed. + std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n"; + for (const std::string &name : this->m_placeholder_parser_failed_templates) + msg += std::string("\t") + name + "\n"; + msg += "\nPlease inspect the file "; + msg += path_tmp + " for error messages enclosed between\n"; + msg += " !!!!! Failed to process the custom G-code template ...\n"; + msg += "and\n"; + msg += " !!!!! End of an error report for the custom G-code template ...\n"; + throw std::runtime_error(msg); + } + if (boost::nowide::rename(path_tmp.c_str(), path) != 0) + throw std::runtime_error( + std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' + + "Is " + path_tmp + " locked?" + '\n'); } -bool GCode::_do_export(Print &print, FILE *file) +void GCode::_do_export(Print &print, FILE *file) { // How many times will be change_layer() called? // change_layer() in turn increments the progress bar status. @@ -557,7 +568,7 @@ bool GCode::_do_export(Print &print, FILE *file) m_placeholder_parser.set("current_object_idx", 0); // For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided. m_placeholder_parser.set("has_wipe_tower", has_wipe_tower); - std::string start_gcode = m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id); + std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config.start_gcode.value, initial_extruder_id); // Set bed temperature if the start G-code does not contain any bed temp control G-codes. this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true); @@ -571,11 +582,11 @@ bool GCode::_do_export(Print &print, FILE *file) // Wipe tower will control the extruder switching, it will call the start_filament_gcode. } else { // Only initialize the initial extruder. - writeln(file, m_placeholder_parser.process(print.config.start_filament_gcode.values[initial_extruder_id], initial_extruder_id)); + writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config.start_filament_gcode.values[initial_extruder_id], initial_extruder_id)); } } else { for (const std::string &start_gcode : print.config.start_filament_gcode.values) - writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); + writeln(file, this->placeholder_parser_process("start_gcode", start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front()))); } this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true); @@ -668,7 +679,7 @@ bool GCode::_do_export(Print &print, FILE *file) // another one, set first layer temperatures. This happens before the Z move // is triggered, so machine has more time to reach such temperatures. m_placeholder_parser.set("current_object_idx", int(finished_objects)); - std::string between_objects_gcode = m_placeholder_parser.process(print.config.between_objects_gcode.value, initial_extruder_id); + std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config.between_objects_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false); @@ -747,12 +758,12 @@ bool GCode::_do_export(Print &print, FILE *file) // Process filament-specific gcode in extruder order. if (print.config.single_extruder_multi_material) { // Process the end_filament_gcode for the active filament only. - writeln(file, m_placeholder_parser.process(print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id())); + writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id())); } else { for (const std::string &end_gcode : print.config.end_filament_gcode.values) - writeln(file, m_placeholder_parser.process(end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()))); + writeln(file, this->placeholder_parser_process("end_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()))); } - writeln(file, m_placeholder_parser.process(print.config.end_gcode, m_writer.extruder()->id())); + writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id())); write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% write(file, m_writer.postamble()); @@ -793,8 +804,21 @@ bool GCode::_do_export(Print &print, FILE *file) fprintf(file, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str()); } } +} - return true; +std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) +{ + try { + return m_placeholder_parser.process(templ, current_extruder_id, config_override); + } catch (std::runtime_error &err) { + // Collect the names of failed template substitutions for error reporting. + this->m_placeholder_parser_failed_templates.insert(name); + // Insert the macro error message into the G-code. + return + std::string("!!!!! Failed to process the custom G-code template ") + name + "\n" + + err.what() + + "!!!!! End of an error report for the custom G-code template " + name + "\n"; + } } // Parse the custom G-code, try to find mcode_set_temp_dont_wait and mcode_set_temp_and_wait inside the custom G-code. @@ -997,7 +1021,7 @@ void GCode::process_layer( DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); - gcode += m_placeholder_parser.process( + gcode += this->placeholder_parser_process("before_layer_gcode", print.config.before_layer_gcode.value, m_writer.extruder()->id(), &config) + "\n"; } @@ -1007,7 +1031,7 @@ void GCode::process_layer( DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); - gcode += m_placeholder_parser.process( + gcode += this->placeholder_parser_process("layer_gcode", print.config.layer_gcode.value, m_writer.extruder()->id(), &config) + "\n"; } @@ -2206,7 +2230,7 @@ std::string GCode::set_extruder(unsigned int extruder_id) unsigned int old_extruder_id = m_writer.extruder()->id(); const std::string &end_filament_gcode = m_config.end_filament_gcode.get_at(old_extruder_id); if (m_config.single_extruder_multi_material && ! end_filament_gcode.empty()) { - gcode += m_placeholder_parser.process(end_filament_gcode, old_extruder_id); + gcode += placeholder_parser_process("end_filament_gcode", end_filament_gcode, old_extruder_id); check_add_eol(gcode); } } @@ -2218,7 +2242,7 @@ std::string GCode::set_extruder(unsigned int extruder_id) DynamicConfig config; config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id())); config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); - gcode += m_placeholder_parser.process(m_config.toolchange_gcode.value, extruder_id, &config); + gcode += placeholder_parser_process("toolchange_gcode", m_config.toolchange_gcode.value, extruder_id, &config); check_add_eol(gcode); } @@ -2232,7 +2256,7 @@ std::string GCode::set_extruder(unsigned int extruder_id) const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id); if (m_config.single_extruder_multi_material && ! start_filament_gcode.empty()) { // Process the start_filament_gcode for the active filament only. - gcode += m_placeholder_parser.process(start_filament_gcode, extruder_id); + gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id); check_add_eol(gcode); } // Set the new extruder to the operating temperature. -- cgit v1.2.3 From c34ec9b7d3ea32a92cc58d61fccb1e446687f6f2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 17:38:29 +0100 Subject: PlaceholderParser: Improved error reporting https://github.com/prusa3d/Slic3r/issues/600 Fixed '+' operator for strings. --- xs/src/libslic3r/GCode.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b5f186630..131693b4e 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -814,10 +814,10 @@ std::string GCode::placeholder_parser_process(const std::string &name, const std // Collect the names of failed template substitutions for error reporting. this->m_placeholder_parser_failed_templates.insert(name); // Insert the macro error message into the G-code. - return - std::string("!!!!! Failed to process the custom G-code template ") + name + "\n" + + return + std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" + err.what() + - "!!!!! End of an error report for the custom G-code template " + name + "\n"; + "!!!!! End of an error report for the custom G-code template " + name + "\n\n"; } } -- cgit v1.2.3 From 7892dfd53c083f7b5c26dad04dca0f84ab29b2a7 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 18:40:46 +0100 Subject: Fixed a regression bug in G-code export, where ferror was called on released FILE structure. --- xs/src/libslic3r/GCode.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 131693b4e..528d7132b 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -376,11 +376,13 @@ void GCode::do_export(Print *print, const char *path) this->m_placeholder_parser_failed_templates.clear(); this->_do_export(*print, file); - fclose(file); + fflush(file); if (ferror(file)) { + fclose(file); boost::nowide::remove(path_tmp.c_str()); throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); } + fclose(file); if (! this->m_placeholder_parser_failed_templates.empty()) { // G-code export proceeded, but some of the PlaceholderParser substitutions failed. std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n"; -- cgit v1.2.3 From 8509e4b5f5ca87b5408b878d524051f7324c6908 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 9 Dec 2017 16:39:49 +0100 Subject: Fixes regression error introduced in Slic3r 1.38.2: Slic3r 1.38.3 gcodes not building up bed temperature https://github.com/prusa3d/Slic3r/issues/614 --- xs/src/libslic3r/GCode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xs/src/libslic3r/GCode.cpp') diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 528d7132b..b297ddab0 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -888,12 +888,12 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s // Is the bed temperature set by the provided custom G-code? int temp_by_gcode = -1; bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, temp_by_gcode); - if (temp_by_gcode >= 0 && temp_by_gcode < 1000) + if (temp_set_by_gcode && temp_by_gcode >= 0 && temp_by_gcode < 1000) temp = temp_by_gcode; // Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if // the custom start G-code emited these. std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait); - if (! temp_by_gcode) + if (! temp_set_by_gcode) write(file, set_temp_gcode); } -- cgit v1.2.3