From 830da1f8e490abd2b7ecf312d85759b8f2f5f8b6 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 13:43:02 +0100 Subject: [PATCH 01/69] Fixed a regression bug of handling the obsolete config parameters, causing crashes. --- xs/src/libslic3r/Config.cpp | 2 +- xs/src/libslic3r/PrintConfig.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index d7671c82f..728ed608b 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -243,7 +243,7 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con for (const auto &opt : def->options) { for (const t_config_option_key &opt_key2 : opt.second.aliases) { if (opt_key2 == opt_key) { - opt_key = opt_key2; + opt_key = opt.first; optdef = &opt.second; break; } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 217f9bdef..ed54d9b6c 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -245,6 +245,7 @@ PrintConfigDef::PrintConfigDef() def->enum_labels.push_back("Hilbert Curve"); def->enum_labels.push_back("Archimedean Chords"); def->enum_labels.push_back("Octagram Spiral"); + // solid_fill_pattern is an obsolete equivalent to external_fill_pattern. def->aliases.push_back("solid_fill_pattern"); def->default_value = new ConfigOptionEnum(ipRectilinear); From 8807d288d7af21727dd371d5bcf6d9e68f02d229 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 15:51:51 +0100 Subject: [PATCH 02/69] Fixed a regression issue when starting Slic3r with non-existent datadir. --- xs/src/slic3r/GUI/PresetBundle.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 3855760c2..29afc07cd 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -64,12 +64,11 @@ PresetBundle::~PresetBundle() void PresetBundle::setup_directories() { - boost::filesystem::path dir = boost::filesystem::canonical(Slic3r::data_dir()); - if (! boost::filesystem::is_directory(dir)) - throw std::runtime_error(std::string("datadir does not exist: ") + Slic3r::data_dir()); - std::initializer_list names = { "print", "filament", "printer" }; - for (const char *name : names) { - boost::filesystem::path subdir = (dir / name).make_preferred(); + boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir()); + std::initializer_list paths = { data_dir, data_dir / "print", data_dir / "filament", data_dir / "printer" }; + for (const boost::filesystem::path &path : paths) { + boost::filesystem::path subdir = path; + subdir.make_preferred(); if (! boost::filesystem::is_directory(subdir) && ! boost::filesystem::create_directory(subdir)) throw std::runtime_error(std::string("Slic3r was unable to create its data directory at ") + subdir.string()); From 3996535e5dea9d223fe5ad9e628bb3b841aeff63 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 16:01:47 +0100 Subject: [PATCH 03/69] 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 ++++++++++++++++++++++++++++++-------- xs/src/libslic3r/GCode.hpp | 1 + 2 files changed, 73 insertions(+), 18 deletions(-) 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); diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index aa90ac968..7c6af25b6 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -143,6 +143,7 @@ public: const FullPrintConfig &config() const { return m_config; } const Layer* layer() const { return m_layer; } GCodeWriter& writer() { return m_writer; } + PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } bool enable_cooling_markers() const { return m_enable_cooling_markers; } // For Perl bindings, to be used exclusively by unit tests. From bff7065360bfa99fc9033db5a1c21b5186ecd17c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 16:24:48 +0100 Subject: [PATCH 04/69] Fixed a bug in the support generator: There was half extrusion width gap created between the support and the support sheath. Now the support sheath will overlap with the support base by 10% of the extrusion width by default. --- xs/src/libslic3r/SupportMaterial.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 7a05cf998..c17468e70 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -2569,7 +2569,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // TODO: use brim ordering algorithm to_infill_polygons = to_polygons(to_infill); // TODO: use offset2_ex() - to_infill = offset_ex(to_infill, float(- flow.scaled_spacing())); + to_infill = offset_ex(to_infill, float(- 0.4 * flow.scaled_spacing())); extrusion_entities_append_paths( support_layer.support_fills.entities, to_polylines(STDMOVE(to_infill_polygons)), @@ -2776,7 +2776,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // TODO: use brim ordering algorithm Polygons to_infill_polygons = to_polygons(to_infill); // TODO: use offset2_ex() - to_infill = offset_ex(to_infill, - float(flow.scaled_spacing())); + to_infill = offset_ex(to_infill, - 0.4 * float(flow.scaled_spacing())); extrusion_entities_append_paths( base_layer.extrusions, to_polylines(STDMOVE(to_infill_polygons)), From a617e02ae667e49215ec577a7b0bfb9ccc2e0b3f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 17:45:03 +0100 Subject: [PATCH 05/69] New hot key for auto arrange: 'a'. --- lib/Slic3r/GUI/Plater.pm | 1 + lib/Slic3r/GUI/Plater/3D.pm | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index a6915bb7c..35e40b83c 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -99,6 +99,7 @@ sub new { $self->{canvas3D}->set_on_select_object($on_select_object); $self->{canvas3D}->set_on_double_click($on_double_click); $self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); }); + $self->{canvas3D}->set_on_arrange(sub { $self->arrange }); $self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') }); $self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') }); $self->{canvas3D}->set_on_scale_object_uniformly(sub { $self->changescale(undef) }); diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index 503a3d159..1c123e741 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -9,7 +9,7 @@ use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR); use base qw(Slic3r::GUI::3DScene Class::Accessor); __PACKAGE__->mk_accessors(qw( - on_rotate_object_left on_rotate_object_right on_scale_object_uniformly + on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly on_remove_object on_increase_objects on_decrease_objects)); sub new { @@ -88,7 +88,9 @@ sub new { $event->Skip; } else { my $key = $event->GetKeyCode; - if ($key == ord('l')) { + if ($key == ord('a')) { + $self->on_arrange->() if $self->on_arrange; + } elsif ($key == ord('l')) { $self->on_rotate_object_left->() if $self->on_rotate_object_left; } elsif ($key == ord('r')) { $self->on_rotate_object_right->() if $self->on_rotate_object_right; @@ -122,6 +124,11 @@ sub set_on_right_click { $self->on_right_click($cb); } +sub set_on_arrange { + my ($self, $cb) = @_; + $self->on_arrange($cb); +} + sub set_on_rotate_object_left { my ($self, $cb) = @_; $self->on_rotate_object_left($cb); From cecaf6eabcba735837d9c631bbb79cf9b4aed6b4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 17:55:39 +0100 Subject: [PATCH 06/69] 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 ------- xs/src/slic3r/GUI/PresetBundle.cpp | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) 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. diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 29afc07cd..b216cf70a 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -556,9 +556,9 @@ static inline int hex_digit_to_int(const char c) static inline bool parse_color(const std::string &scolor, unsigned char *rgb_out) { rgb_out[0] = rgb_out[1] = rgb_out[2] = 0; - const char *c = scolor.data() + 1; if (scolor.size() != 7 || scolor.front() != '#') return false; + const char *c = scolor.data() + 1; for (size_t i = 0; i < 3; ++ i) { int digit1 = hex_digit_to_int(*c ++); int digit2 = hex_digit_to_int(*c ++); From d161d4f78cd1f3ebcc4de1878574094225447fe6 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 18:26:15 +0100 Subject: [PATCH 07/69] There is a hack applied to add accelerator keys to the menu without being registered. Unfortunately this hack works on wxWidgets on Windows. On OSX or Linux, a warning is emited and no accelerator key is shown on the menu. This commit just removes the warnings, it does not add the menu accelerators. https://github.com/prusa3d/Slic3r/issues/539 --- lib/Slic3r/GUI/MainFrame.pm | 15 ++++++++------- lib/Slic3r/GUI/Plater.pm | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 09a64ca4b..2f93899a4 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -274,13 +274,14 @@ sub _init_menubar { # \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators, # as the simple numeric accelerators spoil all numeric data entry. # The camera control accelerators are captured by 3DScene Perl module instead. - $self->_append_menu_item($self->{viewMenu}, "Iso\t\xA00" , 'Iso View' , sub { $self->select_view('iso' ); }); - $self->_append_menu_item($self->{viewMenu}, "Top\t\xA01" , 'Top View' , sub { $self->select_view('top' ); }); - $self->_append_menu_item($self->{viewMenu}, "Bottom\t\xA02" , 'Bottom View' , sub { $self->select_view('bottom' ); }); - $self->_append_menu_item($self->{viewMenu}, "Front\t\xA03" , 'Front View' , sub { $self->select_view('front' ); }); - $self->_append_menu_item($self->{viewMenu}, "Rear\t\xA04" , 'Rear View' , sub { $self->select_view('rear' ); }); - $self->_append_menu_item($self->{viewMenu}, "Left\t\xA05" , 'Left View' , sub { $self->select_view('left' ); }); - $self->_append_menu_item($self->{viewMenu}, "Right\t\xA06" , 'Right View' , sub { $self->select_view('right' ); }); + my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] }; + $self->_append_menu_item($self->{viewMenu}, $accel->('Iso', '0'), 'Iso View' , sub { $self->select_view('iso' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Top', '1'), 'Top View' , sub { $self->select_view('top' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Bottom', '2'), 'Bottom View' , sub { $self->select_view('bottom' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Front', '3'), 'Front View' , sub { $self->select_view('front' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Rear', '4'), 'Rear View' , sub { $self->select_view('rear' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Left', '5'), 'Left View' , sub { $self->select_view('left' ); }); + $self->_append_menu_item($self->{viewMenu}, $accel->('Right', '6'), 'Right View' , sub { $self->select_view('right' ); }); } # Help menu diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 35e40b83c..5ae6ae352 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1918,13 +1918,14 @@ sub object_menu { my $frame = $self->GetFrame; my $menu = Wx::Menu->new; - $frame->_append_menu_item($menu, "Delete\t\xA0Del", 'Remove the selected object', sub { + my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] }; + $frame->_append_menu_item($menu, $accel->('Delete', 'Del'), 'Remove the selected object', sub { $self->remove; }, undef, 'brick_delete.png'); - $frame->_append_menu_item($menu, "Increase copies\t\xA0+", 'Place one more copy of the selected object', sub { + $frame->_append_menu_item($menu, $accel->('Increase copies', '+'), 'Place one more copy of the selected object', sub { $self->increase; }, undef, 'add.png'); - $frame->_append_menu_item($menu, "Decrease copies\t\xA0-", 'Remove one copy of the selected object', sub { + $frame->_append_menu_item($menu, $accel->('Decrease copies', '-'), 'Remove one copy of the selected object', sub { $self->decrease; }, undef, 'delete.png'); $frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub { From 488feb23352b07c27b07468408f1318dd745810f Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sat, 2 Sep 2017 13:36:20 -0500 Subject: [PATCH 08/69] Added --no-gui flag to force CLI usage (allows for CLI usage with AppImage build). Forced --gui flag in AppImage build. --- README.md | 2 ++ slic3r.pl | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d9f90b01..40c22b98a 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ The author of the Silk icon set is Mark James. --gui Forces the GUI launch instead of command line slicing (if you supply a model file, it will be loaded into the plater) --no-plater Disable the plater tab + --no-gui Forces the command line slicing instead of gui. + This takes precedence over --gui if both are present. --autosave Automatically export current configuration to the specified file Output options: diff --git a/slic3r.pl b/slic3r.pl index e49457c20..3a13c8230 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -31,6 +31,7 @@ my %cli_options = (); 'debug' => \$Slic3r::debug, 'gui' => \$opt{gui}, + 'no-gui' => \$opt{no_gui}, 'o|output=s' => \$opt{output}, 'save=s' => \$opt{save}, @@ -102,7 +103,7 @@ $config->apply($cli_config); # launch GUI my $gui; -if ((!@ARGV || $opt{gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") { +if ((!@ARGV || $opt{gui}) && !(!@ARGV || $opt{no_gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") { { no warnings 'once'; $Slic3r::GUI::datadir = Slic3r::decode_path($opt{datadir} // ''); @@ -267,6 +268,8 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ... --gui Forces the GUI launch instead of command line slicing (if you supply a model file, it will be loaded into the plater) --no-plater Disable the plater tab + --no-gui Forces the command line slicing instead of gui. + This takes precedence over --gui if both are present. --autosave Automatically export current configuration to the specified file Output options: From 91e1dc639d0fb4e58bf94f9953d20bbddbc0be91 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 19:00:26 +0100 Subject: [PATCH 09/69] Fix of the preceding cherry pick. --- slic3r.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slic3r.pl b/slic3r.pl index 3a13c8230..afddc77d3 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -103,7 +103,7 @@ $config->apply($cli_config); # launch GUI my $gui; -if ((!@ARGV || $opt{gui}) && !(!@ARGV || $opt{no_gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") { +if ((!@ARGV || $opt{gui}) && !$opt{no_gui} && !$opt{save} && eval "require Slic3r::GUI; 1") { { no warnings 'once'; $Slic3r::GUI::datadir = Slic3r::decode_path($opt{datadir} // ''); From 752d72f58d91abadf061be00fde9ba19be345919 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 19:04:07 +0100 Subject: [PATCH 10/69] Increased fill rate of the support 1st layer from 50% to 70%. --- xs/src/libslic3r/SupportMaterial.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index c17468e70..07943fb15 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -2602,7 +2602,8 @@ void PrintObjectSupportMaterial::generate_toolpaths( // Base flange. filler->angle = raft_angle_1st_layer; filler->spacing = m_first_layer_flow.spacing(); - density = 0.5f; + // 70% of density on the 1st layer. + density = 0.7f; } else if (support_layer_id >= m_slicing_params.base_raft_layers) { filler->angle = raft_angle_interface; // We don't use $base_flow->spacing because we need a constant spacing From a0268a190651615ff85229e2e6115702921666ba Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 20:13:05 +0100 Subject: [PATCH 11/69] Some other accelerator keys were not displayed on Linux and OSX correctly. Suppress them on these systems. --- lib/Slic3r/GUI/Plater.pm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 5ae6ae352..aeefbe6a3 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1495,6 +1495,7 @@ sub reload_from_disk { return if !defined $obj_idx; my $model_object = $self->{model}->objects->[$obj_idx]; + #FIXME convert to local file encoding return if !$model_object->input_file || !-e $model_object->input_file; @@ -1505,12 +1506,14 @@ sub reload_from_disk { my $o = $self->{model}->objects->[$new_obj_idx]; $o->clear_instances; $o->add_instance($_) for @{$model_object->instances}; + #$o->invalidate_bounding_box; if ($o->volumes_count == $model_object->volumes_count) { for my $i (0..($o->volumes_count-1)) { $o->get_volume($i)->config->apply($model_object->get_volume($i)->config); } } + #FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile, layer_height_profile_valid, } $self->remove($obj_idx); @@ -1932,10 +1935,10 @@ sub object_menu { $self->set_number_of_copies; }, undef, 'textfield.png'); $menu->AppendSeparator(); - $frame->_append_menu_item($menu, "Rotate 45° clockwise\t\xA0l", 'Rotate the selected object by 45° clockwise', sub { + $frame->_append_menu_item($menu, $accel->('Rotate 45° clockwise', 'l'), 'Rotate the selected object by 45° clockwise', sub { $self->rotate(-45, Z, 'relative'); }, undef, 'arrow_rotate_clockwise.png'); - $frame->_append_menu_item($menu, "Rotate 45° counter-clockwise\t\xA0r", 'Rotate the selected object by 45° counter-clockwise', sub { + $frame->_append_menu_item($menu, $accel->('Rotate 45° counter-clockwise', 'r'), 'Rotate the selected object by 45° counter-clockwise', sub { $self->rotate(+45, Z, 'relative'); }, undef, 'arrow_rotate_anticlockwise.png'); @@ -1968,7 +1971,7 @@ sub object_menu { my $scaleMenu = Wx::Menu->new; my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis'); $frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png'); - $frame->_append_menu_item($scaleMenu, "Uniformly…\t\xA0s", 'Scale the selected object along the XYZ axes', sub { + $frame->_append_menu_item($scaleMenu, $accel->('Uniformly…', 's'), 'Scale the selected object along the XYZ axes', sub { $self->changescale(undef); }); $frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub { From 354408c7e62f022d86a87fbc13301d4f6d488298 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Nov 2017 20:25:59 +0100 Subject: [PATCH 12/69] Load the wxWidgets PNG handler only once. --- lib/Slic3r/GUI.pm | 2 +- xs/src/slic3r/GUI/PresetBundle.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 2dc560cad..a8799c458 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -112,7 +112,7 @@ sub OnInit { $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; # application frame - Wx::Image::AddHandler(Wx::PNGHandler->new); + Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || Wx::Image::AddHandler(Wx::PNGHandler->new); $self->{mainframe} = my $frame = Slic3r::GUI::MainFrame->new( # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. no_controller => $self->{app_config}->get('no_controller'), diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index b216cf70a..143e34e7f 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -34,7 +34,8 @@ PresetBundle::PresetBundle() : m_bitmapCompatible(new wxBitmap), m_bitmapIncompatible(new wxBitmap) { - ::wxInitAllImageHandlers(); + if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) + wxImage::AddHandler(new wxPNGHandler); // Create the ID config keys, as they are not part of the Static print config classes. this->prints.preset(0).config.opt_string("print_settings_id", true); From ca0626b168a15381ab499fe7d8153934a7889078 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 1 Dec 2017 18:55:57 +0100 Subject: [PATCH 13/69] 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 ++- xs/src/libslic3r/Slicing.hpp | 2 +- xs/src/slic3r/GUI/PresetBundle.cpp | 27 ++++++++++++++++++++++++--- xs/src/slic3r/GUI/PresetBundle.hpp | 2 +- xs/xsp/Print.xsp | 7 ++++--- 5 files changed, 32 insertions(+), 9 deletions(-) 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()); } } diff --git a/xs/src/libslic3r/Slicing.hpp b/xs/src/libslic3r/Slicing.hpp index 1534e19f5..b4a074bb5 100644 --- a/xs/src/libslic3r/Slicing.hpp +++ b/xs/src/libslic3r/Slicing.hpp @@ -103,7 +103,7 @@ inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters sp1.layer_height == sp2.layer_height && sp1.min_layer_height == sp2.min_layer_height && sp1.max_layer_height == sp2.max_layer_height && - sp1.max_suport_layer_height == sp2.max_suport_layer_height && +// sp1.max_suport_layer_height == sp2.max_suport_layer_height && sp1.first_print_layer_height == sp2.first_print_layer_height && sp1.first_object_layer_height == sp2.first_object_layer_height && sp1.first_object_layer_bridging == sp2.first_object_layer_bridging && diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 143e34e7f..1f872ffd6 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -1,4 +1,4 @@ -//#undef NDEBUGc +//#undef NDEBUG #include #include "PresetBundle.hpp" @@ -216,6 +216,8 @@ DynamicPrintConfig PresetBundle::full_config() const } } } + + out.erase("compatible_printers"); static const char *keys[] = { "perimeter", "infill", "solid_infill", "support_material", "support_material_interface" }; for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++ i) { @@ -278,8 +280,19 @@ void PresetBundle::load_config_file(const std::string &path) } // Load a config file from a boost property_tree. This is a private method called from load_config_file. -void PresetBundle::load_config_file_config(const std::string &path, const DynamicPrintConfig &config) +void PresetBundle::load_config_file_config(const std::string &path, DynamicPrintConfig &&config) { + // The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway, + // but some of the alpha versions of Slic3r did. + { + ConfigOption *opt_compatible = config.optptr("compatible_printers"); + if (opt_compatible != nullptr) { + assert(opt_compatible->type() == coStrings); + if (opt_compatible->type() == coStrings) + static_cast(opt_compatible)->values.clear(); + } + } + // 1) Create a name from the file name. // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles. std::string name = boost::filesystem::path(path).filename().string(); @@ -310,7 +323,7 @@ void PresetBundle::load_config_file_config(const std::string &path, const Dynami if (other_opt->is_scalar()) { for (size_t i = 0; i < configs.size(); ++ i) configs[i].option(key, false)->set(other_opt); - } else { + } else if (key != "compatible_printers") { for (size_t i = 0; i < configs.size(); ++ i) static_cast(configs[i].option(key, false))->set_at(other_opt, 0, i); } @@ -368,6 +381,14 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const } assert(! preset_name_dst.empty()); // Save preset_src->config into collection_dst under preset_name_dst. + // The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway, + // but some of the alpha versions of Slic3r did. + ConfigOption *opt_compatible = preset_src->config.optptr("compatible_printers"); + if (opt_compatible != nullptr) { + assert(opt_compatible->type() == coStrings); + if (opt_compatible->type() == coStrings) + static_cast(opt_compatible)->values.clear(); + } collection_dst.load_preset(path, preset_name_dst, std::move(preset_src->config), activate).is_external = true; return preset_name_dst; }; diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 571dea0be..451ec69c1 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -78,7 +78,7 @@ public: void update_compatible_with_printer(bool select_other_if_incompatible); private: - void load_config_file_config(const std::string &path, const DynamicPrintConfig &config); + void load_config_file_config(const std::string &path, DynamicPrintConfig &&config); void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree); bool load_compatible_bitmaps(); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 852f0dde0..bdf7b8991 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -215,10 +215,11 @@ _constant() bool has_infinite_skirt(); bool has_skirt(); std::vector extruders() const; - void validate() %code%{ + int validate() %code%{ std::string err = THIS->validate(); - if (! err.empty()) - throw std::invalid_argument(err.c_str()); + if (! err.empty()) + croak("Configuration is not valid: %s\n", err.c_str()); + RETVAL = 1; %}; Clone bounding_box(); Clone total_bounding_box(); From 73a539780a61621c1f2c3469d2ef74c2a00c62d8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 1 Dec 2017 18:56:32 +0100 Subject: [PATCH 14/69] Bumped up a version number. --- xs/src/libslic3r/libslic3r.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 644190d6a..9d2451869 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -14,7 +14,7 @@ #include #define SLIC3R_FORK_NAME "Slic3r Prusa Edition" -#define SLIC3R_VERSION "1.38.2" +#define SLIC3R_VERSION "1.38.3" #define SLIC3R_BUILD "UNKNOWN" typedef long coord_t; From 16bd3fc62457221f84f211fe90df31382a601f48 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 3 Dec 2017 09:43:00 +0100 Subject: [PATCH 15/69] Fixed an extruder ordering bug on the 1st layer wipe tower. This is a regression after introducing the extruder priming areas at the edge of the print bed. --- xs/src/libslic3r/GCode/ToolOrdering.hpp | 4 ++-- xs/src/libslic3r/GCode/WipeTower.hpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/libslic3r/Print.cpp | 12 ++++++++---- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/xs/src/libslic3r/GCode/ToolOrdering.hpp index fe2c394c5..abf1aa6b2 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.hpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.hpp @@ -53,14 +53,14 @@ public: void clear() { m_layer_tools.clear(); } - // Get the first extruder printing the layer_tools, returns -1 if there is no layer printed. + // Get the first extruder printing, including the extruder priming areas, returns -1 if there is no layer printed. unsigned int first_extruder() const { return m_first_printing_extruder; } // Get the first extruder printing the layer_tools, returns -1 if there is no layer printed. unsigned int last_extruder() const { return m_last_printing_extruder; } // For a multi-material print, the printing extruders are ordered in the order they shall be primed. - std::vector all_extruders() const { return m_all_printing_extruders; } + const std::vector& all_extruders() const { return m_all_printing_extruders; } // Find LayerTools with the closest print_z. LayerTools& tools_for_layer(coordf_t print_z); diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index c21c1710b..2c92e16e6 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -109,7 +109,7 @@ public: // print_z of the first layer. float first_layer_height, // Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object. - std::vector tools, + const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. bool last_wipe_inside_wipe_tower, diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 951d71075..b81a8b04b 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -368,7 +368,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // print_z of the first layer. float first_layer_height, // Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object. - std::vector tools, + const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. bool last_wipe_inside_wipe_tower, diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 15a96d367..b8c7ab31f 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -112,7 +112,7 @@ public: // print_z of the first layer. float first_layer_height, // Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object. - std::vector tools, + const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. bool last_wipe_inside_wipe_tower, diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 78ebf9294..c25e5de7d 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -974,7 +974,6 @@ void Print::_make_wipe_tower() // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print. m_tool_ordering = ToolOrdering(*this, (unsigned int)-1, true); - unsigned int initial_extruder_id = m_tool_ordering.first_extruder(); if (! m_tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; @@ -983,7 +982,7 @@ void Print::_make_wipe_tower() WipeTowerPrusaMM wipe_tower( float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - initial_extruder_id); + m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); @@ -1006,7 +1005,8 @@ void Print::_make_wipe_tower() // Generate the wipe tower layers. m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); - unsigned int current_extruder_id = initial_extruder_id; + // Set current_extruder_id to the last extruder primed. + unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) { if (! layer_tools.has_wipe_tower) // This is a support only layer, or the wipe tower does not reach to this height. @@ -1021,7 +1021,11 @@ void Print::_make_wipe_tower() last_layer); std::vector tool_changes; for (unsigned int extruder_id : layer_tools.extruders) - if ((first_layer && extruder_id == initial_extruder_id) || extruder_id != current_extruder_id) { + // Call the wipe_tower.tool_change() at the first layer for the initial extruder + // to extrude the wipe tower brim, + if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || + // or when an extruder shall be switched. + extruder_id != current_extruder_id) { tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, extruder_id == layer_tools.extruders.back(), WipeTower::PURPOSE_EXTRUDE)); current_extruder_id = extruder_id; } From 8af329e660904653f210e959d73ae4269b5a459c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Dec 2017 10:48:40 +0100 Subject: [PATCH 16/69] Added Perl to C++ interfaces for creating the preset editor pages from C++ and to add debugging menus from C++. These lightweigth interfaces should help new team members to hack the UI without a Perl knowledge. --- lib/Slic3r/GUI.pm | 1 + lib/Slic3r/GUI/MainFrame.pm | 8 ++++++ xs/src/slic3r/GUI/GUI.cpp | 49 +++++++++++++++++++++++++++++++++++++ xs/src/slic3r/GUI/GUI.hpp | 15 ++++++++++++ xs/xsp/GUI.xsp | 15 ++++++++++++ 5 files changed, 88 insertions(+) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a8799c458..78e82a6ef 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -79,6 +79,7 @@ sub OnInit { # Windows: "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r" # Mac: "~/Library/Application Support/Slic3r" Slic3r::set_data_dir($datadir || Wx::StandardPaths::Get->GetUserDataDir); + Slic3r::GUI::set_wxapp($self); $self->{notifier} = Slic3r::GUI::Notifier->new; $self->{app_config} = Slic3r::GUI::AppConfig->new; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 2f93899a4..370bac2ed 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -22,6 +22,7 @@ sub new { my ($class, %params) = @_; my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE); + Slic3r::GUI::set_main_frame($self); if ($^O eq 'MSWin32') { # Load the icon either from the exe, or from the ico file. my $iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe'; @@ -92,6 +93,8 @@ sub _init_tabpanel { my ($self) = @_; $self->{tabpanel} = my $panel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); + Slic3r::GUI::set_tab_panel($panel); + EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub { my $panel = $self->{tabpanel}->GetCurrentPage; $panel->OnActivate if $panel->can('OnActivate'); @@ -145,6 +148,9 @@ sub _init_tabpanel { $tab->load_current_preset; $panel->AddPage($tab, $tab->title); } + +#TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view. +# Slic3r::GUI::create_preset_tab("print"); if ($self->{plater}) { $self->{plater}->on_select_preset(sub { @@ -330,6 +336,8 @@ sub _init_menubar { $menubar->Append($windowMenu, "&Window"); $menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu}; $menubar->Append($helpMenu, "&Help"); + # Add an optional debug menu. In production code, the add_debug_menu() call should do nothing. + Slic3r::GUI::add_debug_menu($menubar); $self->SetMenuBar($menubar); } } diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 63cc7749d..8db0508f1 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -13,6 +13,14 @@ #pragma comment(lib, "user32.lib") #endif +#include +#include +#include +#include +#include +#include +#include + namespace Slic3r { namespace GUI { #if __APPLE__ @@ -134,4 +142,45 @@ void break_to_debugger() #endif /* _WIN32 */ } +// Passing the wxWidgets GUI classes instantiated by the Perl part to C++. +wxApp *g_wxApp = nullptr; +wxFrame *g_wxMainFrame = nullptr; +wxNotebook *g_wxTabPanel = nullptr; + +void set_wxapp(wxApp *app) +{ + g_wxApp = app; +} + +void set_main_frame(wxFrame *main_frame) +{ + g_wxMainFrame = main_frame; +} + +void set_tab_panel(wxNotebook *tab_panel) +{ + g_wxTabPanel = tab_panel; +} + +void add_debug_menu(wxMenuBar *menu) +{ +#if 0 + auto debug_menu = new wxMenu(); + debug_menu->Append(wxWindow::NewControlId(1), "Some debug"); + menu->Append(debug_menu, _T("&Debug")); +#endif +} + +void create_preset_tab(const char *name) +{ + auto *panel = new wxPanel(g_wxTabPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); + // Vertical sizer to hold the choice menu and the rest of the page. + auto *sizer = new wxBoxSizer(wxVERTICAL); + sizer->SetSizeHints(panel); + panel->SetSizer(sizer); + auto *button = new wxButton(panel, wxID_ANY, "Hello World", wxDefaultPosition, wxDefaultSize, 0); + sizer->Add(button, 0, 0, 0); + g_wxTabPanel->AddPage(panel, name); +} + } } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 955a1cd8d..3634e0bc8 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -4,6 +4,11 @@ #include #include +class wxApp; +class wxFrame; +class wxMenuBar; +class wxNotebook; + namespace Slic3r { namespace GUI { void disable_screensaver(); @@ -12,6 +17,16 @@ std::vector scan_serial_ports(); bool debugged(); void break_to_debugger(); +// Passing the wxWidgets GUI classes instantiated by the Perl part to C++. +void set_wxapp(wxApp *app); +void set_main_frame(wxFrame *main_frame); +void set_tab_panel(wxNotebook *tab_panel); + +void add_debug_menu(wxMenuBar *menu); +// Create a new preset tab (print, filament or printer), +// add it at the end of the tab panel. +void create_preset_tab(const char *name); + } } #endif diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index ce3c178a1..d6b55dbf1 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -22,3 +22,18 @@ bool debugged() void break_to_debugger() %code{% Slic3r::GUI::break_to_debugger(); %}; + +void set_wxapp(SV *ui) + %code%{ Slic3r::GUI::set_wxapp((wxApp*)wxPli_sv_2_object(aTHX_ ui, "Wx::App")); %}; + +void set_main_frame(SV *ui) + %code%{ Slic3r::GUI::set_main_frame((wxFrame*)wxPli_sv_2_object(aTHX_ ui, "Wx::Frame")); %}; + +void set_tab_panel(SV *ui) + %code%{ Slic3r::GUI::set_tab_panel((wxNotebook*)wxPli_sv_2_object(aTHX_ ui, "Wx::Notebook")); %}; + +void add_debug_menu(SV *ui) + %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar")); %}; + +void create_preset_tab(const char *name) + %code%{ Slic3r::GUI::create_preset_tab(name); %}; From 2b0b8e6e688fc60c79edb3f1282b7e06b60dfc17 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Dec 2017 11:57:54 +0100 Subject: [PATCH 17/69] 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 ++++++++++++-------------- xs/src/libslic3r/GCode.hpp | 1 - xs/src/libslic3r/PlaceholderParser.hpp | 1 + 3 files changed, 36 insertions(+), 41 deletions(-) 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) { diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 7c6af25b6..72c39fe38 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -90,7 +90,6 @@ public: m_brim_done(false) {} std::string prime(GCode &gcodegen); - static std::string prime_single_color_print(const Print & /* print */, unsigned int initial_tool, GCode & /* gcodegen */); void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; } std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer); std::string finalize(GCode &gcodegen); diff --git a/xs/src/libslic3r/PlaceholderParser.hpp b/xs/src/libslic3r/PlaceholderParser.hpp index 9ec2eedea..25264d461 100644 --- a/xs/src/libslic3r/PlaceholderParser.hpp +++ b/xs/src/libslic3r/PlaceholderParser.hpp @@ -22,6 +22,7 @@ public: void set(const std::string &key, const std::string &value) { this->set(key, new ConfigOptionString(value)); } void set(const std::string &key, int value) { this->set(key, new ConfigOptionInt(value)); } void set(const std::string &key, unsigned int value) { this->set(key, int(value)); } + void set(const std::string &key, bool value) { this->set(key, new ConfigOptionBool(value)); } void set(const std::string &key, double value) { this->set(key, new ConfigOptionFloat(value)); } void set(const std::string &key, const std::vector &values) { this->set(key, new ConfigOptionStrings(values)); } void set(const std::string &key, ConfigOption *opt) { m_config.set_key_value(key, opt); } From fb1bebd982c6a92ccb5217f2d0530d0bcf42ce76 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Dec 2017 17:42:35 +0100 Subject: [PATCH 18/69] PlaceholderParser: simplistic extension to parse UTF8 characters in the G-code and string constants. Solves https://github.com/prusa3d/Slic3r/issues/600 --- xs/src/libslic3r/PlaceholderParser.cpp | 40 ++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 060252387..6c90a6eb6 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -22,6 +22,8 @@ #endif #include +// Unicode iterator to iterate over utf8. +#include // Spirit v2.5 allows you to suppress automatic generation // of predefined terminals to speed up complation. With @@ -598,6 +600,39 @@ namespace client template static bool parse_inf(It&, It const&, Attr&) { return false; } }; + struct unicode_char_parser : qi::primitive_parser + { + // Define the attribute type exposed by this parser component + template + struct attribute + { + typedef wchar_t type; + }; + + // This function is called during the actual parsing process + template + bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr) const + { + skip_over(first, last, skipper); + if (first == last) return false; + + boost::u8_to_u32_iterator f(first); + boost::u8_to_u32_iterator l(last); + if (f == l) return false; + + attr = *f++; + first = f.base(); + return true; + } + + // This function is called during error handling to create a human readable string for the error context. + template + spirit::info what(Context&) const + { + return spirit::info("unicode_char"); + } + }; + /////////////////////////////////////////////////////////////////////////// // Our calculator grammar /////////////////////////////////////////////////////////////////////////// @@ -617,6 +652,7 @@ namespace client qi::no_skip_type no_skip; qi::real_parser strict_double; spirit::ascii::char_type char_; + unicode_char_parser utf8char; spirit::bool_type bool_; spirit::int_type int_; spirit::double_type double_; @@ -649,7 +685,7 @@ namespace client // Free-form text up to a first brace, including spaces and newlines. // The free-form text will be inserted into the processed text without a modification. - text = no_skip[raw[+(char_ - '[' - '{')]]; + text = no_skip[raw[+(utf8char - char_('[') - char_('{'))]]; text.name("text"); // New style of macro expansion. @@ -749,7 +785,7 @@ namespace client | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] | (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ] - | raw[lexeme['"' > *((char_ - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] + | raw[lexeme['"' > *((utf8char - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] [ px::bind(&FactorActions::string_, _1, _val) ] ); factor.name("factor"); From 1244fd09eba10f301278778dc9d10e0b752b8c76 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Dec 2017 18:22:42 +0100 Subject: [PATCH 19/69] More efficient utf8 parser for the PlaceholderParser. --- xs/src/libslic3r/PlaceholderParser.cpp | 63 +++++++++++++++++++------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 6c90a6eb6..b09e06133 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -600,37 +600,66 @@ namespace client template static bool parse_inf(It&, It const&, Attr&) { return false; } }; - struct unicode_char_parser : qi::primitive_parser + // This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character. + // If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown. + struct utf8_char_skipper_parser : qi::primitive_parser { // Define the attribute type exposed by this parser component template struct attribute { - typedef wchar_t type; - }; + typedef wchar_t type; + }; // This function is called during the actual parsing process template bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr) const { - skip_over(first, last, skipper); - if (first == last) return false; - - boost::u8_to_u32_iterator f(first); - boost::u8_to_u32_iterator l(last); - if (f == l) return false; - - attr = *f++; - first = f.base(); - return true; - } + // The skipper shall always be empty, any white space will be accepted. + // skip_over(first, last, skipper); + if (first == last) + return false; + // Iterator over the UTF-8 sequence. + auto it = first; + // Read the first byte of the UTF-8 sequence. + unsigned char c = static_cast(*it ++); + // UTF-8 sequence must not start with a continuation character: + if ((c & 0xC0) == 0x80) + goto err; + // Skip high surrogate first if there is one. + // If the most significant bit with a zero in it is in position + // 8-N then there are N bytes in this UTF-8 sequence: + unsigned int cnt = 0; + { + unsigned char mask = 0x80u; + unsigned int result = 0; + while (c & mask) { + ++ result; + mask >>= 1; + } + cnt = (result == 0) ? 1 : ((result > 4) ? 4 : result); + } + // Since we haven't read in a value, we need to validate the code points: + for (-- cnt; cnt > 0; -- cnt) { + if (it == last) + goto err; + c = static_cast(*it ++); + // We must have a continuation byte: + if (cnt > 1 && (c & 0xC0) != 0x80) + goto err; + } + first = it; + return true; + err: + boost::throw_exception(qi::expectation_failure(first, last, spirit::info("Invalid utf8 sequence"))); + } // This function is called during error handling to create a human readable string for the error context. template - spirit::info what(Context&) const + spirit::info what(Context&) const { return spirit::info("unicode_char"); - } + } }; /////////////////////////////////////////////////////////////////////////// @@ -652,7 +681,7 @@ namespace client qi::no_skip_type no_skip; qi::real_parser strict_double; spirit::ascii::char_type char_; - unicode_char_parser utf8char; + utf8_char_skipper_parser utf8char; spirit::bool_type bool_; spirit::int_type int_; spirit::double_type double_; From 8746f84fa2b8585270d36b4070693a188e722e33 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 15:54:24 +0100 Subject: [PATCH 20/69] 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. --- lib/Slic3r/GUI/MainFrame.pm | 1 + lib/Slic3r/GUI/Plater.pm | 9 +- lib/Slic3r/Print.pm | 10 +- slic3r.pl | 2 + xs/src/libslic3r/GCode.cpp | 78 ++++++---- xs/src/libslic3r/GCode.hpp | 10 +- xs/src/libslic3r/PlaceholderParser.cpp | 188 +++++++++++-------------- xs/src/libslic3r/Print.cpp | 6 +- xs/xsp/GCode.xsp | 9 +- xs/xsp/PlaceholderParser.xsp | 8 +- xs/xsp/Print.xsp | 10 +- 11 files changed, 190 insertions(+), 141 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 370bac2ed..5ae6ac08f 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -422,6 +422,7 @@ sub quick_slice { if ($params{reslice}) { $output_file = $qs_last_output_file if defined $qs_last_output_file; } elsif ($params{save_as}) { + # The following line may die if the output_filename_format template substitution fails. $output_file = $sprint->output_filepath; $output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg}; my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:', diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index aeefbe6a3..0cb433309 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1291,9 +1291,11 @@ sub export_gcode { # select output file if ($output_file) { - $self->{export_gcode_output_file} = $self->{print}->output_filepath($output_file); + $self->{export_gcode_output_file} = eval { $self->{print}->output_filepath($output_file) }; + Slic3r::GUI::catch_error($self) and return; } else { - my $default_output_file = $self->{print}->output_filepath($main::opt{output} // ''); + my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; + Slic3r::GUI::catch_error($self) and return; my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)), basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); @@ -1544,7 +1546,8 @@ sub export_amf { sub _get_export_file { my ($self, $format) = @_; my $suffix = $format eq 'STL' ? '.stl' : '.amf.xml'; - my $output_file = $self->{print}->output_filepath($main::opt{output} // ''); + my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; + Slic3r::GUI::catch_error($self) and return undef; $output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/; my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file), basename($output_file), &Slic3r::GUI::MODEL_WILDCARD, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 1613b7e45..12ad2f12f 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -65,6 +65,9 @@ sub process { } # G-code export process, running at a background thread. +# The export_gcode may die for various reasons (fails to process output_filename_format, +# write error into the G-code, cannot execute post-processing scripts). +# It is up to the caller to show an error message. sub export_gcode { my $self = shift; my %params = @_; @@ -73,11 +76,12 @@ sub export_gcode { $self->process; # output everything to a G-code file + # The following call may die if the output_filename_format template substitution fails. my $output_file = $self->output_filepath($params{output_file} // ''); $self->status_cb->(90, "Exporting G-code" . ($output_file ? " to $output_file" : "")); - die "G-code export to " . $output_file . " failed\n" - if ! Slic3r::GCode->new->do_export($self, $output_file); + # The following line may die for multiple reasons. + Slic3r::GCode->new->do_export($self, $output_file); # run post-processing scripts if (@{$self->config->post_process}) { @@ -99,6 +103,7 @@ sub export_gcode { } # Export SVG slices for the offline SLA printing. +# The export_svg is expected to be executed inside an eval block. sub export_svg { my $self = shift; my %params = @_; @@ -107,6 +112,7 @@ sub export_svg { my $fh = $params{output_fh}; if (!$fh) { + # The following line may die if the output_filename_format template substitution fails. my $output_file = $self->output_filepath($params{output_file}); $output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/; Slic3r::open(\$fh, ">", $output_file) or die "Failed to open $output_file for writing\n"; diff --git a/slic3r.pl b/slic3r.pl index afddc77d3..c2bee2219 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -219,6 +219,8 @@ if (@ARGV) { # slicing from command line $sprint->export_svg; } else { my $t0 = [gettimeofday]; + # The following call may die if the output_filename_format template substitution fails, + # if the file cannot be written into, or if the post processing scripts cannot be executed. $sprint->export_gcode; # output some statistics 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. diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 72c39fe38..2fd3b39d3 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -130,7 +130,8 @@ public: {} ~GCode() {} - bool do_export(Print *print, const char *path); + // throws std::runtime_exception + void do_export(Print *print, const char *path); // Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests. const Pointf& origin() const { return m_origin; } @@ -143,6 +144,9 @@ public: const Layer* layer() const { return m_layer; } GCodeWriter& writer() { return m_writer; } PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } + // Process a template through the placeholder parser, collect error messages to be reported + // inside the generated string and after the G-code export finishes. + std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr); bool enable_cooling_markers() const { return m_enable_cooling_markers; } // For Perl bindings, to be used exclusively by unit tests. @@ -151,7 +155,7 @@ public: void apply_print_config(const PrintConfig &print_config); protected: - bool _do_export(Print &print, FILE *file); + void _do_export(Print &print, FILE *file); // Object and support extrusions of the same PrintObject at the same print_z. struct LayerToPrint @@ -223,6 +227,8 @@ protected: FullPrintConfig m_config; GCodeWriter m_writer; PlaceholderParser m_placeholder_parser; + // Collection of templates, on which the placeholder substitution failed. + std::set m_placeholder_parser_failed_templates; OozePrevention m_ooze_prevention; Wipe m_wipe; AvoidCrossingPerimeters m_avoid_crossing_perimeters; diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index b09e06133..f9f72a9e9 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -368,7 +368,7 @@ namespace client value = lhs.to_string() == rhs.to_string(); } else { boost::throw_exception(qi::expectation_failure( - lhs.it_range.begin(), rhs.it_range.end(), spirit::info("Cannot compare the types."))); + lhs.it_range.begin(), rhs.it_range.end(), spirit::info("*Cannot compare the types."))); } lhs.type = TYPE_BOOL; lhs.data.b = (op == '=') ? value : !value; @@ -387,7 +387,7 @@ namespace client void throw_exception(const char *message) const { boost::throw_exception(qi::expectation_failure( - this->it_range.begin(), this->it_range.end(), spirit::info(message))); + this->it_range.begin(), this->it_range.end(), spirit::info(std::string("*") + message))); } void throw_if_not_numeric(const char *message) const @@ -417,6 +417,7 @@ namespace client const PlaceholderParser *pp = nullptr; const DynamicConfig *config_override = nullptr; const size_t current_extruder_id = 0; + std::string error_message; const ConfigOption* resolve_symbol(const std::string &opt_key) const { @@ -444,26 +445,22 @@ namespace client opt = ctx->resolve_symbol(opt_key_str.substr(0, idx)); if (opt != nullptr) { if (! opt->is_vector()) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Trying to index a scalar variable"))); + ctx->throw_exception("Trying to index a scalar variable", opt_key); char *endptr = nullptr; idx = strtol(opt_key_str.c_str() + idx + 1, &endptr, 10); if (endptr == nullptr || *endptr != 0) - boost::throw_exception(qi::expectation_failure( - opt_key.begin() + idx + 1, opt_key.end(), spirit::info("Invalid vector index"))); + ctx->throw_exception("Invalid vector index", boost::iterator_range(opt_key.begin() + idx + 1, opt_key.end())); } } } if (opt == nullptr) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Variable does not exist"))); + ctx->throw_exception("Variable does not exist", boost::iterator_range(opt_key.begin(), opt_key.end())); if (opt->is_scalar()) output = opt->serialize(); else { const ConfigOptionVectorBase *vec = static_cast(opt); if (vec->empty()) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Indexing an empty vector variable"))); + ctx->throw_exception("Indexing an empty vector variable", opt_key); output = vec->vserialize()[(idx >= vec->size()) ? 0 : idx]; } } @@ -484,23 +481,18 @@ namespace client opt = ctx->resolve_symbol(opt_key_str); } if (! opt->is_vector()) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Trying to index a scalar variable"))); + ctx->throw_exception("Trying to index a scalar variable", opt_key); const ConfigOptionVectorBase *vec = static_cast(opt); if (vec->empty()) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Indexing an empty vector variable"))); + ctx->throw_exception("Indexing an empty vector variable", boost::iterator_range(opt_key.begin(), opt_key.end())); const ConfigOption *opt_index = ctx->resolve_symbol(std::string(opt_vector_index.begin(), opt_vector_index.end())); if (opt_index == nullptr) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Variable does not exist"))); + ctx->throw_exception("Variable does not exist", opt_key); if (opt_index->type() != coInt) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Indexing variable has to be integer"))); + ctx->throw_exception("Indexing variable has to be integer", opt_key); int idx = opt_index->getInt(); if (idx < 0) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Negative vector index"))); + ctx->throw_exception("Negative vector index", opt_key); output = vec->vserialize()[(idx >= (int)vec->size()) ? 0 : idx]; } @@ -512,8 +504,7 @@ namespace client { const ConfigOption *opt = ctx->resolve_symbol(std::string(opt_key.begin(), opt_key.end())); if (opt == nullptr) - boost::throw_exception(qi::expectation_failure( - opt_key.begin(), opt_key.end(), spirit::info("Not a variable name"))); + ctx->throw_exception("Not a variable name", opt_key); output.opt = opt; output.it_range = opt_key; } @@ -525,8 +516,7 @@ namespace client expr &output) { if (opt.opt->is_vector()) - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("Referencing a scalar variable in a vector context"))); + ctx->throw_exception("Referencing a scalar variable in a vector context", opt.it_range); switch (opt.opt->type()) { case coFloat: output.set_d(opt.opt->getFloat()); break; case coInt: output.set_i(opt.opt->getInt()); break; @@ -535,11 +525,9 @@ namespace client case coPoint: output.set_s(opt.opt->serialize()); break; case coBool: output.set_b(opt.opt->getBool()); break; case coFloatOrPercent: - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("FloatOrPercent variables are not supported"))); + ctx->throw_exception("FloatOrPercent variables are not supported", opt.it_range); default: - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("Unknown scalar variable type"))); + ctx->throw_exception("Unknown scalar variable type", opt.it_range); } output.it_range = opt.it_range; } @@ -553,12 +541,10 @@ namespace client expr &output) { if (opt.opt->is_scalar()) - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("Referencing a vector variable in a scalar context"))); + ctx->throw_exception("Referencing a vector variable in a scalar context", opt.it_range); const ConfigOptionVectorBase *vec = static_cast(opt.opt); if (vec->empty()) - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("Indexing an empty vector variable"))); + ctx->throw_exception("Indexing an empty vector variable", opt.it_range); size_t idx = (index < 0) ? 0 : (index >= int(vec->size())) ? 0 : size_t(index); switch (opt.opt->type()) { case coFloats: output.set_d(static_cast(opt.opt)->values[idx]); break; @@ -568,8 +554,7 @@ namespace client case coPoints: output.set_s(static_cast(opt.opt)->values[idx].dump_perl()); break; case coBools: output.set_b(static_cast(opt.opt)->values[idx] != 0); break; default: - boost::throw_exception(qi::expectation_failure( - opt.it_range.begin(), opt.it_range.end(), spirit::info("Unknown vector variable type"))); + ctx->throw_exception("Unknown vector variable type", opt.it_range); } output.it_range = boost::iterator_range(opt.it_range.begin(), it_end); } @@ -579,10 +564,54 @@ namespace client template static void evaluate_index(expr &expr_index, int &output) { - if (expr_index.type != expr::TYPE_INT) + if (expr_index.type != expr::TYPE_INT) expr_index.throw_exception("Non-integer index is not allowed to address a vector variable."); output = expr_index.i(); } + + template + static void throw_exception(const std::string &msg, const boost::iterator_range &it_range) + { + // An asterix is added to the start of the string to differentiate the boost::spirit::info::tag content + // between the grammer terminal / non-terminal symbol name and a free-form error message. + boost::throw_exception(qi::expectation_failure(it_range.begin(), it_range.end(), spirit::info(std::string("*") + msg))); + } + + template + static void process_error_message(const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end) + { + struct expectation_printer + { + expectation_printer(std::string &msg) : result(msg) {} + std::string &result; + void element(std::string const& tag, std::string const& value, int depth) + { + // Indent to depth. + for (int i = 0; i < depth * 4; ++ i) + result += ' '; + if (tag.empty() || tag.front() != '*') { + if (depth == 0) + this->result += "Expecting "; + this->result += "tag: "; + this->result += tag; + } else + this->result += tag.substr(1); + if (! value.empty()) { + this->result += ", value: "; + this->result += value; + } + this->result += '\n'; + } + }; + + std::string &msg = const_cast(context)->error_message; + msg += "Error! "; + expectation_printer ep(msg); + spirit::basic_info_walker walker(ep, info.tag, 0); + boost::apply_visitor(walker, info.value); + msg += " got: \""; + msg += std::string(it_begin, it_end) + "\"\n"; + } }; // For debugging the boost::spirit parsers. Print out the string enclosed in it_range. @@ -651,7 +680,8 @@ namespace client first = it; return true; err: - boost::throw_exception(qi::expectation_failure(first, last, spirit::info("Invalid utf8 sequence"))); + MyContext::throw_exception("Invalid utf8 sequence", boost::iterator_range(first, last)); + return false; } // This function is called during error handling to create a human readable string for the error context. @@ -692,6 +722,8 @@ namespace client qi::_val_type _val; qi::_1_type _1; qi::_2_type _2; + qi::_3_type _3; + qi::_4_type _4; qi::_a_type _a; qi::_b_type _b; qi::_r1_type _r1; @@ -701,6 +733,7 @@ namespace client // Without it, some of the errors would not trigger the error handler. start = eps > text_block(_r1); start.name("start"); + qi::on_error(start, px::bind(&MyContext::process_error_message, _r1, _4, _3, _2)); text_block = *( text [_val+=_1] @@ -831,16 +864,6 @@ namespace client variable_reference = identifier [ px::bind(&MyContext::resolve_variable, _r1, _1, _val) ]; variable_reference.name("variable reference"); -/* - qi::on_error(start, - phx::ref(std::cout) - << "Error! Expecting " - << qi::_4 - << " here: '" - << px::construct(qi::_3, qi::_2) - << "'\n" - ); -*/ keywords.add ("and") @@ -907,69 +930,30 @@ namespace client }; } -struct printer -{ - typedef spirit::utf8_string string; - - void element(string const& tag, string const& value, int depth) const - { - for (int i = 0; i < (depth*4); ++i) // indent to depth - std::cout << ' '; - std::cout << "tag: " << tag; - if (value != "") - std::cout << ", value: " << value; - std::cout << std::endl; - } -}; - -void print_info(spirit::info const& what) -{ - using spirit::basic_info_walker; - printer pr; - basic_info_walker walker(pr, what.tag, 0); - boost::apply_visitor(walker, what.value); -} - std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const { typedef std::string::const_iterator iterator_type; typedef client::calculator calculator; - spirit::ascii::space_type space; // Our skipper - calculator calc; // Our grammar - + // Our whitespace skipper. + spirit::ascii::space_type space; + // Our grammar. + calculator calc; + // Iterators over the source template. std::string::const_iterator iter = templ.begin(); - std::string::const_iterator end = templ.end(); - //std::string result; - std::string result; - bool r = false; - try { - client::MyContext context; - context.pp = this; - context.config_override = config_override; - r = phrase_parse(iter, end, calc(&context), space, result); - } catch (qi::expectation_failure const& x) { - std::cout << "expected: "; print_info(x.what_); - std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl; + std::string::const_iterator end = templ.end(); + // Accumulator for the processed template. + std::string output; + client::MyContext context; + context.pp = this; + context.config_override = config_override; + bool res = phrase_parse(iter, end, calc(&context), space, output); + if (! context.error_message.empty()) { + if (context.error_message.back() != '\n' && context.error_message.back() != '\r') + context.error_message += '\n'; + throw std::runtime_error(context.error_message); } - - if (r && iter == end) - { -// std::cout << "-------------------------\n"; -// std::cout << "Parsing succeeded\n"; -// std::cout << "result = " << result << std::endl; -// std::cout << "-------------------------\n"; - } - else - { - std::string rest(iter, end); - std::cout << "-------------------------\n"; - std::cout << "Parsing failed\n"; - std::cout << "stopped at: \" " << rest << "\"\n"; - std::cout << "source: \n" << templ; - std::cout << "-------------------------\n"; - } - return result; + return output; } } diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index c25e5de7d..190fbfe6e 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1075,7 +1075,11 @@ void Print::_make_wipe_tower() std::string Print::output_filename() { this->placeholder_parser.update_timestamp(); - return this->placeholder_parser.process(this->config.output_filename_format.value, 0); + try { + return this->placeholder_parser.process(this->config.output_filename_format.value, 0); + } catch (std::runtime_error &err) { + throw std::runtime_error(std::string("Failed processing of the output_filename_format template.\n") + err.what()); + } } std::string Print::output_filepath(const std::string &path) diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp index 92341394f..9e6df85dc 100644 --- a/xs/xsp/GCode.xsp +++ b/xs/xsp/GCode.xsp @@ -17,7 +17,14 @@ %name{Slic3r::GCode} class GCode { GCode(); ~GCode(); - std::string do_export(Print *print, const char *path); + void do_export(Print *print, const char *path) + %code%{ + try { + THIS->do_export(print, path); + } catch (std::exception& e) { + croak(e.what()); + } + %}; Ref origin() %code{% RETVAL = &(THIS->origin()); %}; diff --git a/xs/xsp/PlaceholderParser.xsp b/xs/xsp/PlaceholderParser.xsp index 08630f9d5..ab06450f9 100644 --- a/xs/xsp/PlaceholderParser.xsp +++ b/xs/xsp/PlaceholderParser.xsp @@ -14,5 +14,11 @@ %code%{ THIS->apply_config(*config); %}; void set(std::string key, int value); std::string process(std::string str) const - %code%{ RETVAL = THIS->process(str, 0); %}; + %code%{ + try { + RETVAL = THIS->process(str, 0); + } catch (std::exception& e) { + croak(e.what()); + } + %}; }; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index bdf7b8991..1148fd4aa 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -206,8 +206,14 @@ _constant() double max_allowed_layer_height() const; bool has_support_material() const; void auto_assign_extruders(ModelObject* model_object); - std::string output_filename(); - std::string output_filepath(std::string path = ""); + std::string output_filepath(std::string path = "") + %code%{ + try { + RETVAL = THIS->output_filepath(path); + } catch (std::exception& e) { + croak(e.what()); + } + %}; void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config(DynamicPrintConfig* config) From c34ec9b7d3ea32a92cc58d61fccb1e446687f6f2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 17:38:29 +0100 Subject: [PATCH 21/69] PlaceholderParser: Improved error reporting https://github.com/prusa3d/Slic3r/issues/600 Fixed '+' operator for strings. --- xs/src/libslic3r/GCode.cpp | 6 +- xs/src/libslic3r/PlaceholderParser.cpp | 96 +++++++++++++++----------- 2 files changed, 57 insertions(+), 45 deletions(-) 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"; } } diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index f9f72a9e9..ed75508ac 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -280,22 +280,31 @@ namespace client expr &operator+=(const expr &rhs) { - const char *err_msg = "Cannot multiply with non-numeric type."; - this->throw_if_not_numeric(err_msg); - rhs.throw_if_not_numeric(err_msg); - if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) { - double d = this->as_d() + rhs.as_d(); - this->data.d = d; - this->type = TYPE_DOUBLE; - } else - this->data.i += rhs.i(); + if (this->type == TYPE_STRING) { + // Convert the right hand side to string and append. + *this->data.s += rhs.to_string(); + } else if (rhs.type == TYPE_STRING) { + // Conver the left hand side to string, append rhs. + this->data.s = new std::string(this->to_string() + rhs.s()); + this->type = TYPE_STRING; + } else { + const char *err_msg = "Cannot add non-numeric types."; + this->throw_if_not_numeric(err_msg); + rhs.throw_if_not_numeric(err_msg); + if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) { + double d = this->as_d() + rhs.as_d(); + this->data.d = d; + this->type = TYPE_DOUBLE; + } else + this->data.i += rhs.i(); + } this->it_range = boost::iterator_range(this->it_range.begin(), rhs.it_range.end()); return *this; } expr &operator-=(const expr &rhs) { - const char *err_msg = "Cannot multiply with non-numeric type."; + const char *err_msg = "Cannot subtract non-numeric types."; this->throw_if_not_numeric(err_msg); rhs.throw_if_not_numeric(err_msg); if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) { @@ -578,39 +587,42 @@ namespace client } template - static void process_error_message(const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end) + static void process_error_message(const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end, const Iterator &it_error) { - struct expectation_printer - { - expectation_printer(std::string &msg) : result(msg) {} - std::string &result; - void element(std::string const& tag, std::string const& value, int depth) - { - // Indent to depth. - for (int i = 0; i < depth * 4; ++ i) - result += ' '; - if (tag.empty() || tag.front() != '*') { - if (depth == 0) - this->result += "Expecting "; - this->result += "tag: "; - this->result += tag; - } else - this->result += tag.substr(1); - if (! value.empty()) { - this->result += ", value: "; - this->result += value; - } - this->result += '\n'; - } - }; - std::string &msg = const_cast(context)->error_message; - msg += "Error! "; - expectation_printer ep(msg); - spirit::basic_info_walker walker(ep, info.tag, 0); - boost::apply_visitor(walker, info.value); - msg += " got: \""; - msg += std::string(it_begin, it_end) + "\"\n"; + std::string first(it_begin, it_error); + std::string last(it_error, it_end); + auto first_pos = first.rfind('\n'); + auto last_pos = last.find('\n'); + int line_nr = 1; + if (first_pos == std::string::npos) + first_pos = 0; + else { + // Calculate the current line number. + for (size_t i = 0; i <= first_pos; ++ i) + if (first[i] == '\n') + ++ line_nr; + ++ first_pos; + } + auto error_line = std::string(first, first_pos) + std::string(last, 0, last_pos); + // Position of the it_error from the start of its line. + auto error_pos = (it_error - it_begin) - first_pos; + msg += "Parsing error at line " + std::to_string(line_nr); + if (! info.tag.empty() && info.tag.front() == '*') { + // The gat contains an explanatory string. + msg += ": "; + msg += info.tag.substr(1); + } else { + // A generic error report based on the nonterminal or terminal symbol name. + msg += ". Expecting tag "; + msg += info.tag; + } + msg += '\n'; + msg += error_line; + msg += '\n'; + for (size_t i = 0; i < error_pos; ++ i) + msg += ' '; + msg += "^\n"; } }; @@ -733,7 +745,7 @@ namespace client // Without it, some of the errors would not trigger the error handler. start = eps > text_block(_r1); start.name("start"); - qi::on_error(start, px::bind(&MyContext::process_error_message, _r1, _4, _3, _2)); + qi::on_error(start, px::bind(&MyContext::process_error_message, _r1, _4, _1, _2, _3)); text_block = *( text [_val+=_1] From 0a2be9d7bf22faba489a1a66c4a3ebbcdca87cba Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 17:52:12 +0100 Subject: [PATCH 22/69] Fixed compilation on unices. --- xs/src/libslic3r/PlaceholderParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index ed75508ac..8f2f6d6e7 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -664,13 +664,13 @@ namespace client auto it = first; // Read the first byte of the UTF-8 sequence. unsigned char c = static_cast(*it ++); + unsigned int cnt = 0; // UTF-8 sequence must not start with a continuation character: if ((c & 0xC0) == 0x80) goto err; // Skip high surrogate first if there is one. // If the most significant bit with a zero in it is in position // 8-N then there are N bytes in this UTF-8 sequence: - unsigned int cnt = 0; { unsigned char mask = 0x80u; unsigned int result = 0; From 7892dfd53c083f7b5c26dad04dca0f84ab29b2a7 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 18:40:46 +0100 Subject: [PATCH 23/69] 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(-) 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"; From b0f84c5cb2368eea3683be9ea876a07b8a3bfdc5 Mon Sep 17 00:00:00 2001 From: qtux Date: Tue, 5 Dec 2017 19:05:49 +0100 Subject: [PATCH 24/69] Add used filament length to the "Sliced Info" box (#585) --- lib/Slic3r/GUI/Plater.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 0cb433309..f1db05dc4 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -430,6 +430,7 @@ sub new { $grid_sizer->AddGrowableCol(3, 1); $print_info_sizer->Add($grid_sizer, 0, wxEXPAND); my @info = ( + fil_m => "Used Filament (m)", fil_mm3 => "Used Filament (mm^3)", fil_g => "Used Filament (g)", cost => "Cost", @@ -1426,6 +1427,7 @@ sub on_export_completed { $self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost)); $self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight)); $self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume)); + $self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000)); $self->{"print_info_box_show"}->(1); # this updates buttons status From 2eeca93a971b07248caed9730dc65fb51bb7d76c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Dec 2017 20:06:19 +0100 Subject: [PATCH 25/69] Feature Request: Add to Plater: Ctrl+O implements https://github.com/prusa3d/Slic3r/issues/379 thanks @alexrj --- lib/Slic3r/GUI/MainFrame.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 5ae6ac08f..498ebafe5 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -171,6 +171,9 @@ sub _init_menubar { # File menu my $fileMenu = Wx::Menu->new; { + wxTheApp->append_menu_item($fileMenu, "Open STL/OBJ/AMF…\tCtrl+O", 'Open a model', sub { + $self->{plater}->add if $self->{plater}; + }, undef, undef); #'brick_add.png'); $self->_append_menu_item($fileMenu, "&Load Config…\tCtrl+L", 'Load exported configuration file', sub { $self->load_config_file; }, undef, 'plugin_add.png'); From 75dcdb84b1996a2ae507643042df504e1cd5d056 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 6 Dec 2017 16:47:53 +0100 Subject: [PATCH 26/69] Fix of a crash due to the way how the presets are sorted and searched for in the PresetCollection: The 1st preset is always the "-- default --" even if there are some presets starting with an ASCII character lower than '-'. https://github.com/prusa3d/Slic3r/issues/603 --- xs/src/slic3r/GUI/Preset.cpp | 19 +++++++++---------- xs/src/slic3r/GUI/Preset.hpp | 12 ++++++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index e4b0448cf..4b21b18a0 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -283,10 +283,11 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select) { - Preset key(m_type, name); - auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key); - if (it == m_presets.end() || it->name != name) + auto it = this->find_preset_internal(name); + if (it == m_presets.end() || it->name != name) { + // The preset was not found. Create a new preset. it = m_presets.emplace(it, Preset(m_type, name, false)); + } Preset &preset = *it; preset.file = path; preset.config = std::move(config); @@ -301,9 +302,8 @@ void PresetCollection::save_current_preset(const std::string &new_name) { // 1) Find the preset with a new_name or create a new one, // initialize it with the edited config. - Preset key(m_type, new_name, false); - auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key); - if (it != m_presets.end() && it->name == key.name) { + auto it = this->find_preset_internal(new_name); + if (it != m_presets.end() && it->name == new_name) { // Preset with the same name found. Preset &preset = *it; if (preset.is_default) @@ -356,7 +356,7 @@ bool PresetCollection::load_bitmap_default(const std::string &file_name) Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found) { Preset key(m_type, name, false); - auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key); + auto it = this->find_preset_internal(name); // Ensure that a temporary copy is returned if the preset found is currently selected. return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin()) : first_visible_if_not_found ? &this->first_visible() : nullptr; @@ -509,10 +509,9 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b { std::string name = Preset::remove_suffix_modified(name_w_suffix); // 1) Try to find the preset by its name. - Preset key(m_type, name, false); - auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key); + auto it = this->find_preset_internal(name); size_t idx = 0; - if (it != m_presets.end() && it->name == key.name) + if (it != m_presets.end() && it->name == name) // Preset found by its name. idx = it - m_presets.begin(); else { diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index f44fd1590..74ae7411c 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -212,6 +212,18 @@ private: PresetCollection(const PresetCollection &other); PresetCollection& operator=(const PresetCollection &other); + // Find a preset in the sorted list of presets. + // The "-- default -- " preset is always the first, so it needs + // to be handled differently. + std::deque::iterator find_preset_internal(const std::string &name) + { + Preset key(m_type, name); + auto it = std::lower_bound(m_presets.begin() + 1, m_presets.end(), key); + return (it == m_presets.end() && m_presets.front().name == name) ? m_presets.begin() : it; + } + std::deque::const_iterator find_preset_internal(const std::string &name) const + { return const_cast(this)->find_preset_internal(name); } + // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER. Preset::Type m_type; // List of presets, starting with the "- default -" preset. From f0e154d54c44583d89d64645b216786af973582f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 9 Dec 2017 15:49:43 +0100 Subject: [PATCH 27/69] Bumped up the build version. --- xs/src/libslic3r/libslic3r.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 9d2451869..f71311e7f 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -14,7 +14,7 @@ #include #define SLIC3R_FORK_NAME "Slic3r Prusa Edition" -#define SLIC3R_VERSION "1.38.3" +#define SLIC3R_VERSION "1.38.4" #define SLIC3R_BUILD "UNKNOWN" typedef long coord_t; From 8509e4b5f5ca87b5408b878d524051f7324c6908 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 9 Dec 2017 16:39:49 +0100 Subject: [PATCH 28/69] 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(-) 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); } From 9a80ff57b26b41bf1e4ad275ccd8416cd0d567b0 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 9 Dec 2017 18:48:21 +0100 Subject: [PATCH 29/69] Improved robustness of handling preset files stored into a wrong location. Fixes https://github.com/prusa3d/Slic3r/issues/616 --- xs/src/slic3r/GUI/Preset.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 4b21b18a0..8ba3029ba 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -79,7 +79,8 @@ void Preset::set_num_extruders(DynamicPrintConfig &config, unsigned int num_extr auto *opt = config.option(key, false); assert(opt != nullptr); assert(opt->is_vector()); - static_cast(opt)->resize(num_extruders, defaults.option(key)); + if (opt != nullptr && opt->is_vector()) + static_cast(opt)->resize(num_extruders, defaults.option(key)); } } From 657f2734f19da1d6483b9d70b5d8102e727bc34b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 13:19:44 +0100 Subject: [PATCH 30/69] Extended the Config Wizard to offer a selection of config bundles bundled with Slic3r installation, and install it into user's Slic3r profile. These bundled config bundles will be contained in the Slic3r source tree under Slic3r/resources/profiles. Breaking change! The Slic3r user directory has been renamed to Slic3rPE for the Prusa Edition. Also it is likely, that the Slic3rPE directory will be reorganized before the final 1.38 release to reserve space for temporary profiles downloaded from the Internet. --- lib/Slic3r.pm | 1 + lib/Slic3r/GUI.pm | 2 +- lib/Slic3r/GUI/ConfigWizard.pm | 81 +++++++++++++++++++++++++--------- lib/Slic3r/GUI/MainFrame.pm | 42 ++++++++++++++---- xs/src/libslic3r/Utils.hpp | 5 +++ xs/src/libslic3r/utils.cpp | 12 +++++ xs/xsp/XS.xsp | 12 +++++ 7 files changed, 125 insertions(+), 30 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 53b2e3663..45eedc48d 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -42,6 +42,7 @@ use FindBin; # Let the XS module know where the GUI resources reside. set_var_dir(decode_path($FindBin::Bin) . "/var"); +set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '/Resources' : '/resources')); use Moo 1.003001; diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 78e82a6ef..7157f7e92 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -70,7 +70,7 @@ our $grey = Wx::Colour->new(200,200,200); sub OnInit { my ($self) = @_; - $self->SetAppName('Slic3r'); + $self->SetAppName('Slic3rPE'); $self->SetAppDisplayName('Slic3r Prusa Edition'); Slic3r::debugf "wxWidgets version %s, Wx version %s\n", &Wx::wxVERSION_STRING, $Wx::VERSION; diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index e540f9ea7..c18741396 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -14,14 +14,14 @@ our $wizard = 'Wizard'; $wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK; sub new { - my $class = shift; - my ($parent) = @_; + my ($class, $parent, $presets) = @_; my $self = $class->SUPER::new($parent, -1, "Configuration $wizard"); # initialize an empty repository $self->{config} = Slic3r::Config->new; - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self)); + my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self); + $self->add_page($welcome_page); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self)); @@ -32,12 +32,13 @@ sub new { $_->build_index for @{$self->{pages}}; + $welcome_page->set_selection_presets([@{$presets}, 'Other']); + return $self; } sub add_page { - my $self = shift; - my ($page) = @_; + my ($self, $page) = @_; my $n = push @{$self->{pages}}, $page; # add first page to the page area sizer @@ -48,13 +49,13 @@ sub add_page { } sub run { - my $self = shift; - + my ($self) = @_; + my $result = undef; if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) { - - # it would be cleaner to have these defined inside each page class, - # in some event getting called before leaving the page - { + my $preset_name = $self->{pages}[0]->{preset_name}; + if ($preset_name eq 'Other') { + # it would be cleaner to have these defined inside each page class, + # in some event getting called before leaving the page # set first_layer_height + layer_height based on nozzle_diameter my $nozzle = $self->{config}->nozzle_diameter; $self->{config}->set('first_layer_height', $nozzle->[0]); @@ -66,14 +67,13 @@ sub run { # set first_layer_bed_temperature to temperature + 5 $self->{config}->set('first_layer_bed_temperature', [ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]); + $result = $self->{config}; + } else { + $result = $preset_name; } - - $self->Destroy; - return $self->{config}; - } else { - $self->Destroy; - return undef; } + $self->Destroy; + return $result; } package Slic3r::GUI::ConfigWizard::Index; @@ -127,6 +127,8 @@ sub repaint { $dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index}; $dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gap), $label_w, $label_h)); + # Only show the first bullet if this is the only wizard page to be displayed. + last if $i == 0 && $self->{just_welcome}; $i++; } @@ -263,19 +265,58 @@ sub config { package Slic3r::GUI::ConfigWizard::Page::Welcome; use base 'Slic3r::GUI::ConfigWizard::Page'; +use Wx qw(:misc :sizer wxID_FORWARD); +use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE); sub new { my $class = shift; my ($parent) = @_; my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); + $self->{full_wizard_workflow} = 1; - $self->append_text('Hello, welcome to Slic3r! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); - $self->append_text('To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); - $self->append_text('To continue, click Next.'); + $self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); + $self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.'); + # To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); + $self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.'); + + $self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); + $self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); + + EVT_CHOICE($parent, $choice, sub { + my $sel = $self->{choice}->GetStringSelection; + $self->{preset_name} = $sel; + $self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq '')); + }); + + EVT_ACTIVATE($parent, sub { + $self->set_full_wizard_workflow($self->{preset_name} eq 'Other'); + }); return $self; } +sub set_full_wizard_workflow { + my ($self, $full_workflow) = @_; + $self->{full_wizard_workflow} = $full_workflow; + $self->{index}->{just_welcome} = !$full_workflow; + $self->{index}->Refresh; + my $next_button = $self->GetParent->FindWindow(wxID_FORWARD); + $next_button->SetLabel($full_workflow ? "&Next >" : "&Finish"); +} + +# Set the preset names, select the first item. +sub set_selection_presets { + my ($self, $names) = @_; + $self->{choice}->Append($names); + $self->{choice}->SetSelection(0); + $self->{preset_name} = $names->[0]; +} + +sub GetNext { + my $self = shift; + return $self->{full_wizard_workflow} ? $self->{next_page} : undef; +} + package Slic3r::GUI::ConfigWizard::Page::Firmware; use base 'Slic3r::GUI::ConfigWizard::Page'; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 498ebafe5..a6baef8f9 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -617,16 +617,40 @@ sub config_wizard { my ($self) = @_; # Exit wizard if there are unsaved changes and the user cancels the action. return unless $self->check_unsaved_changes; - if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) { - for my $tab (values %{$self->{options_tabs}}) { - # Select the first visible preset, force. - $tab->select_preset(undef, 1); + # Enumerate the profiles bundled with the Slic3r installation under resources/profiles. + my $directory = Slic3r::resources_dir() . "/profiles"; + my @profiles = (); + if (opendir(DIR, Slic3r::encode_path($directory))) { + while (my $file = readdir(DIR)) { + if ($file =~ /\.ini$/) { + $file =~ s/\.ini$//; + push @profiles, Slic3r::decode_path($file); + } } - # Load the config over the previously selected defaults. - $self->load_config($config); - for my $tab (values %{$self->{options_tabs}}) { - # Save the settings under a new name, select the name. - $tab->save_preset('My Settings'); + closedir(DIR); + } + # Open the wizard. + if (my $config = Slic3r::GUI::ConfigWizard->new($self, \@profiles)->run) { + if (ref($config)) { + # Wizard returned a config. Add the config to each of the preset types. + for my $tab (values %{$self->{options_tabs}}) { + # Select the first visible preset, force. + $tab->select_preset(undef, 1); + } + # Load the config over the previously selected defaults. + $self->load_config($config); + for my $tab (values %{$self->{options_tabs}}) { + # Save the settings under a new name, select the name. + $tab->save_preset('My Settings'); + } + } else { + # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. + eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $config . '.ini'); }; + Slic3r::GUI::catch_error($self) and return; + # Load the currently selected preset into the GUI, update the preset selection box. + foreach my $tab (values %{$self->{options_tabs}}) { + $tab->load_current_preset; + } } } } diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp index 308a2a118..d988de860 100644 --- a/xs/src/libslic3r/Utils.hpp +++ b/xs/src/libslic3r/Utils.hpp @@ -15,6 +15,11 @@ const std::string& var_dir(); // Return a full resource path for a file_name. std::string var(const std::string &file_name); +// Set a path with various static definition data (for example the initial config bundles). +void set_resources_dir(const std::string &path); +// Return a full path to the resources directory. +const std::string& resources_dir(); + // Set a path with preset files. void set_data_dir(const std::string &path); // Return a full path to the GUI resource files. diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index f4c03ef50..53efa466b 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -89,6 +89,18 @@ std::string var(const std::string &file_name) return file.string(); } +static std::string g_resources_dir; + +void set_resources_dir(const std::string &dir) +{ + g_resources_dir = dir; +} + +const std::string& resources_dir() +{ + return g_resources_dir; +} + static std::string g_data_dir; void set_data_dir(const std::string &dir) diff --git a/xs/xsp/XS.xsp b/xs/xsp/XS.xsp index 2be42d383..d59f826b7 100644 --- a/xs/xsp/XS.xsp +++ b/xs/xsp/XS.xsp @@ -60,6 +60,18 @@ var_dir() RETVAL = const_cast(Slic3r::var_dir().c_str()); OUTPUT: RETVAL +void +set_resources_dir(dir) + char *dir; + CODE: + Slic3r::set_resources_dir(dir); + +char* +resources_dir() + CODE: + RETVAL = const_cast(Slic3r::resources_dir().c_str()); + OUTPUT: RETVAL + std::string var(file_name) const char *file_name; From 98fdb46da9741a4624a427b00ef355b7ee25abc6 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 13:21:06 +0100 Subject: [PATCH 31/69] Added a first config bundle for the Prusa MK2 & MK3 machines. --- ...l Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini | 3629 +++++++++++++++++ 1 file changed, 3629 insertions(+) create mode 100644 resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini diff --git a/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini b/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini new file mode 100644 index 000000000..ae21f862d --- /dev/null +++ b/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini @@ -0,0 +1,3629 @@ +# generated by Slic3r Prusa Edition 1.38.4 on 2017-12-10 at 09:05:01 + +[print:0.05mm DETAIL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 10 +bridge_acceleration = 300 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode" +complete_objects = 0 +default_acceleration = 500 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 20 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 25% +fill_pattern = cubic +first_layer_acceleration = 500 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 20 +gcode_comments = 0 +infill_acceleration = 800 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.5 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 30 +interface_shells = 0 +layer_height = 0.05 +max_print_speed = 80 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 300 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 30 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 15 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 30 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.3 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 1.5 +support_material_speed = 30 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 20 +top_solid_layers = 15 +travel_speed = 180 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.05mm DETAIL 0.25 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 10 +bridge_acceleration = 300 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle" +complete_objects = 0 +default_acceleration = 500 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0 +external_perimeter_speed = 20 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.28 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 500 +first_layer_extrusion_width = 0.3 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 20 +gcode_comments = 0 +infill_acceleration = 800 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 20 +interface_shells = 0 +layer_height = 0.05 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 300 +perimeter_extruder = 1 +perimeter_extrusion_width = 0 +perimeter_speed = 20 +perimeters = 4 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 10 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0 +solid_infill_speed = 20 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.18 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 0 +support_material_interface_spacing = 0.15 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 1 +support_material_speed = 20 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 150% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0 +top_solid_infill_speed = 20 +top_solid_layers = 15 +travel_speed = 200 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.05mm DETAIL MK3] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 10 +bridge_acceleration = 300 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK3" +complete_objects = 0 +default_acceleration = 500 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 20 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 25% +fill_pattern = cubic +first_layer_acceleration = 500 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 20 +gcode_comments = 0 +infill_acceleration = 800 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.5 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 30 +interface_shells = 0 +layer_height = 0.05 +max_print_speed = 80 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 300 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 30 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 15 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 30 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.3 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 1.5 +support_material_speed = 30 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 20 +top_solid_layers = 15 +travel_speed = 180 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.10mm DETAIL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 7 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.1 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 50 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 50 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 40 +top_solid_layers = 9 +travel_speed = 120 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.10mm DETAIL 0.25 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 7 +bridge_acceleration = 600 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.25 +external_perimeter_speed = 20 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.25 +fill_angle = 45 +fill_density = 15% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.25 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 1600 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.25 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 40 +interface_shells = 0 +layer_height = 0.1 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 600 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.25 +perimeter_speed = 25 +perimeters = 4 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 10 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.25 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.18 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 0 +support_material_interface_spacing = 0.15 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 1 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 150% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.25 +top_solid_infill_speed = 30 +top_solid_layers = 9 +travel_speed = 120 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.10mm DETAIL MK3] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 30 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK3" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 3500 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 35% +infill_speed = 200 +interface_shells = 0 +layer_height = 0.1 +max_print_speed = 250 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 200 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 50 +top_solid_layers = 5 +travel_speed = 250 +wipe_tower = 0 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm 100mms Linear Advance] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 50 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 100 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 150 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 30 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 100 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 60 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 70 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 5 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 50 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 50 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 40 +top_solid_layers = 7 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL 0.25 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 5 +bridge_acceleration = 600 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.25 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.25 +external_perimeter_speed = 20 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.25 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.25 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 1600 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.25 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 40 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 600 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.25 +perimeter_speed = 25 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 10 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.25 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.2 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 0 +support_material_interface_spacing = 0.15 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 1 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 35 +support_material_with_sheath = 0 +support_material_xy_spacing = 150% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.25 +top_solid_infill_speed = 30 +top_solid_layers = 7 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL 0.6 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 5 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.61 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.67 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.75 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.65 +perimeter_speed = 50 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 50 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.6 +top_solid_infill_speed = 40 +top_solid_layers = 7 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL MK3] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 30 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK3" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 3500 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 35% +infill_speed = 200 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 250 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 200 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 50 +top_solid_layers = 5 +travel_speed = 250 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL SOLUBLE FULL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 5 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 25 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft/skirt extruder & Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 40 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 4 +support_material_extrusion_width = 0.45 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.1 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 1 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 30 +top_solid_layers = 7 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm OPTIMAL SOLUBLE INTERFACE] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 5 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 25 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.15 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 40 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.45 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 3 +support_material_interface_spacing = 0.1 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 0 +support_material_xy_spacing = 120% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 30 +top_solid_layers = 7 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm 100mms Linear Advance] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 50 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 100 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 150 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 30 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 100 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 60 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 70 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm NORMAL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 50 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 50 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 40 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm NORMAL 0.6 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.61 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.67 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.75 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.65 +perimeter_speed = 50 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 50 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.6 +top_solid_infill_speed = 40 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm NORMAL MK3] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 30 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK3" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 3500 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 35% +infill_speed = 200 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 250 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 200 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 50 +top_solid_layers = 5 +travel_speed = 250 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm NORMAL SOLUBLE FULL] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 30 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft/skirt extruder & Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 40 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 4 +support_material_extrusion_width = 0.45 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.1 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 1 +support_material_xy_spacing = 120% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 30 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.20mm NORMAL SOLUBLE INTERFACE] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 30 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.2 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 40 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.45 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 3 +support_material_interface_spacing = 0.1 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 0 +support_material_xy_spacing = 120% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 30 +top_solid_layers = 5 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.35mm FAST] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 3 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.7 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.35 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.43 +perimeter_speed = 50 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.7 +solid_infill_speed = 60 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.43 +top_solid_infill_speed = 50 +top_solid_layers = 4 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.35mm FAST 0.6 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 7 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.61 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.67 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.75 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.35 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.65 +perimeter_speed = 50 +perimeters = 3 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 60 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.6 +top_solid_infill_speed = 50 +top_solid_layers = 9 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.35mm FAST MK3] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 4 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 30 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK3" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 40 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 3500 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.7 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 35% +infill_speed = 200 +interface_shells = 0 +layer_height = 0.35 +max_print_speed = 250 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 0 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.7 +solid_infill_speed = 200 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.35 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 50 +top_solid_layers = 4 +travel_speed = 250 +wipe_tower = 1 +wipe_tower_per_color_wipe = 15 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.35mm FAST sol full 0.6 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 3 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 30 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.67 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.75 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.35 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.65 +perimeter_speed = 40 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 60 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 4 +support_material_extrusion_width = 0.55 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 3 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 0 +support_material_xy_spacing = 120% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.57 +top_solid_infill_speed = 50 +top_solid_layers = 4 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.35mm FAST sol int 0.6 nozzle] +avoid_crossing_perimeters = 0 +bottom_solid_layers = 3 +bridge_acceleration = 1000 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 20 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +complete_objects = 0 +default_acceleration = 1000 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 30 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.67 +fill_angle = 45 +fill_density = 20% +fill_pattern = cubic +first_layer_acceleration = 1000 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.2 +first_layer_speed = 30 +gap_fill_speed = 40 +gcode_comments = 0 +infill_acceleration = 2000 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.75 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 60 +interface_shells = 0 +layer_height = 0.35 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = [input_filename_base].gcode +overhangs = 1 +perimeter_acceleration = 800 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.65 +perimeter_speed = 40 +perimeters = 2 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 0 +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 60 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 1 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.55 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 4 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 1 +support_material_threshold = 80 +support_material_with_sheath = 0 +support_material_xy_spacing = 150% +thin_walls = 0 +threads = 4 +top_infill_extrusion_width = 0.57 +top_solid_infill_speed = 50 +top_solid_layers = 4 +travel_speed = 120 +wipe_tower = 1 +wipe_tower_per_color_wipe = 20 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[filament:ColorFabb Brass Bronze 1.75mm] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1.3 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #804040 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 210 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 210 + +[filament:ColorFabb HT 1.75mm] +bed_temperature = 105 +bridge_fan_speed = 30 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 10 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 105 +first_layer_temperature = 270 +max_fan_speed = 20 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 270 + +[filament:ColorFabb PLA-PHA] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 15 +filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 215 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 210 + +[filament:ColorFabb Woodfil 1.75mm] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1.2 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #804040 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 200 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 200 + +[filament:ColorFabb XT 1.75mm] +bed_temperature = 65 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 90 +first_layer_temperature = 240 +max_fan_speed = 50 +min_fan_speed = 30 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 240 + +[filament:ColorFabb XT-CF20 1.75mm] +bed_temperature = 90 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1.2 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #804040 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 1 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 90 +first_layer_temperature = 260 +max_fan_speed = 50 +min_fan_speed = 30 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 260 + +[filament:ColorFabb nGen 1.75mm] +bed_temperature = 85 +bridge_fan_speed = 40 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 10 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = NGEN +first_layer_bed_temperature = 85 +first_layer_temperature = 240 +max_fan_speed = 35 +min_fan_speed = 20 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 240 + +[filament:ColorFabb nGen flex] +bed_temperature = 85 +bridge_fan_speed = 40 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 10 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 5 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = FLEX +first_layer_bed_temperature = 85 +first_layer_temperature = 260 +max_fan_speed = 35 +min_fan_speed = 20 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 260 + +[filament:E3D Edge] +bed_temperature = 90 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 85 +first_layer_temperature = 230 +max_fan_speed = 50 +min_fan_speed = 30 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 240 + +[filament:E3D PC-ABS 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 100 +first_layer_temperature = 270 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 270 + +[filament:Fillamentum ABS 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = ABS +first_layer_bed_temperature = 100 +first_layer_temperature = 240 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 240 + +[filament:Fillamentum ASA 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 100 +first_layer_temperature = 265 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 265 + +[filament:Fillamentum CPE HG100 HM100] +bed_temperature = 90 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "CPE HG100 , CPE HM100" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 90 +first_layer_temperature = 260 +max_fan_speed = 80 +min_fan_speed = 80 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 260 + +[filament:Fillamentum Timberfil] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1.2 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #804040 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 190 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 190 + +[filament:Generic ABS 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS" +filament_settings_id = +filament_soluble = 0 +filament_type = ABS +first_layer_bed_temperature = 100 +first_layer_temperature = 255 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 255 + +[filament:Generic PET 1.75mm] +bed_temperature = 90 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 85 +first_layer_temperature = 230 +max_fan_speed = 50 +min_fan_speed = 30 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 240 + +[filament:Generic PLA 1.75mm] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 15 +filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 215 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 210 + +[filament:Polymaker PC-Max] +bed_temperature = 120 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS" +filament_settings_id = +filament_soluble = 0 +filament_type = ABS +first_layer_bed_temperature = 120 +first_layer_temperature = 270 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 270 + +[filament:Primavalue PVA] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 100 +filament_colour = #FFFFD7 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "List of materials tested with standart PVA print settings for MK2:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'\nVerbatim BVOH" +filament_settings_id = +filament_soluble = 1 +filament_type = PVA +first_layer_bed_temperature = 60 +first_layer_temperature = 195 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 195 + +[filament:Prusa ABS 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 30 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS" +filament_settings_id = +filament_soluble = 0 +filament_type = ABS +first_layer_bed_temperature = 100 +first_layer_temperature = 255 +max_fan_speed = 30 +min_fan_speed = 10 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 255 + +[filament:Prusa HIPS 1.75mm] +bed_temperature = 100 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 0.9 +fan_always_on = 1 +fan_below_layer_time = 10 +filament_colour = #FFFFD7 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 13 +filament_notes = "" +filament_settings_id = +filament_soluble = 1 +filament_type = HIPS +first_layer_bed_temperature = 100 +first_layer_temperature = 220 +max_fan_speed = 20 +min_fan_speed = 20 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 220 + +[filament:Prusa PET 1.75mm] +bed_temperature = 90 +bridge_fan_speed = 50 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 85 +first_layer_temperature = 230 +max_fan_speed = 50 +min_fan_speed = 30 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +temperature = 240 + +[filament:Prusa PLA 1.75mm] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 15 +filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 215 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 210 + +[filament:SemiFlex or Flexfill 98A] +bed_temperature = 50 +bridge_fan_speed = 100 +compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK3" +cooling = 0 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1.2 +fan_always_on = 0 +fan_below_layer_time = 100 +filament_colour = #00CA0A +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 2.5 +filament_notes = "List of materials tested with FLEX print settings & FLEX material settings for MK2:\n\nFillamentum Flex 98A\nFillamentum Flex 92A\nPlasty Mladeč PP\nPlasty Mladeč TPE32 \nPlasty Mladeč TPE88" +filament_settings_id = +filament_soluble = 0 +filament_type = FLEX +first_layer_bed_temperature = 50 +first_layer_temperature = 220 +max_fan_speed = 90 +min_fan_speed = 70 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 230 + +[filament:Taulman Bridge 1.75mm] +bed_temperature = 50 +bridge_fan_speed = 40 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #DEE0E6 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 90 +first_layer_temperature = 240 +max_fan_speed = 5 +min_fan_speed = 0 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 250 + +[filament:Taulman T-Glase 1.75mm] +bed_temperature = 90 +bridge_fan_speed = 40 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "" +filament_settings_id = +filament_soluble = 0 +filament_type = PET +first_layer_bed_temperature = 90 +first_layer_temperature = 240 +max_fan_speed = 5 +min_fan_speed = 0 +min_print_speed = 5 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +temperature = 240 + +[filament:Verbatim BVOH] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +cooling = 0 +disable_fan_first_layers = 1 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 100 +filament_colour = #FFFFD7 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 10 +filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_settings_id = +filament_soluble = 1 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 215 +max_fan_speed = 100 +min_fan_speed = 85 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 210 + +[filament:Verbatim PP] +bed_temperature = 100 +bridge_fan_speed = 100 +compatible_printers = +cooling = 1 +disable_fan_first_layers = 2 +end_filament_gcode = "; Filament-specific end gcode" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_colour = #DEE0E6 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_max_volumetric_speed = 5 +filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA" +filament_settings_id = +filament_soluble = 0 +filament_type = PLA +first_layer_bed_temperature = 100 +first_layer_temperature = 220 +max_fan_speed = 100 +min_fan_speed = 100 +min_print_speed = 15 +slowdown_below_layer_time = 10 +start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +temperature = 220 + +[printer:Original Prusa i3 MK2] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 0 +end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25 +min_layer_height = 0.07 +nozzle_diameter = 0.4 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 0.8 +retract_length_toolchange = 3 +retract_lift = 0.5 +retract_lift_above = 1 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 35 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 0 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 0.25 nozzle] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 0 +end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.1 +min_layer_height = 0.05 +nozzle_diameter = 0.25 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 1 +retract_length_toolchange = 3 +retract_lift = 0.5 +retract_lift_above = 1 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 50 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 0 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 0 +wipe = 1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 0.6 nozzle] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 0 +end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.35 +min_layer_height = 0.1 +nozzle_diameter = 0.6 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 0.8 +retract_length_toolchange = 3 +retract_lift = 0.5 +retract_lift_above = 1 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 35 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 0 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 MM Single Mode] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 50 +end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; fan off\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n +extruder_colour = #FFAA55 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25 +min_layer_height = 0.07 +nozzle_diameter = 0.4 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 3 +retract_before_wipe = 0% +retract_layer_change = 0 +retract_length = 4 +retract_length_toolchange = 6 +retract_lift = 0.5 +retract_lift_above = 0 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 80 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 1 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 MM Single Mode 0.6 nozzle] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 50 +end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; fan off\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n +extruder_colour = #FFAA55 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25 +min_layer_height = 0.07 +nozzle_diameter = 0.6 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 3 +retract_before_wipe = 0% +retract_layer_change = 0 +retract_length = 4 +retract_length_toolchange = 6 +retract_lift = 0.5 +retract_lift_above = 0 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 80 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 1 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 MultiMaterial] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 50,50,50,50 +end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.\nG1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\n{endif}\nM107 ; fan off\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors +extruder_colour = #FFAA55;#5182DB;#4ECDD3;#FB7259 +extruder_offset = 0x0,0x0,0x0,0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25,0.25,0.25,0.25 +min_layer_height = 0.07,0.07,0.07,0.07 +nozzle_diameter = 0.4,0.4,0.4,0.4 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 3,3,3,3 +retract_before_wipe = 60%,60%,60%,60% +retract_layer_change = 0,0,0,0 +retract_length = 4,4,4,4 +retract_length_toolchange = 4,4,4,4 +retract_lift = 0.5,0.5,0.5,0.5 +retract_lift_above = 0,0,0,0 +retract_lift_below = 199,199,199,199 +retract_restart_extra = 0,0,0,0 +retract_restart_extra_toolchange = 0,0,0,0 +retract_speed = 80,80,80,80 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 1 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_wipe_tower}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\n{endif}\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 0 +wipe = 1,1,1,1 +z_offset = 0 + +[printer:Original Prusa i3 MK2 MultiMaterial 0.6 nozzle] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 50,50,50,50 +end_gcode = {if not has_wipe_tower}\nG1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\n{endif}\nM107 ; fan off\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n +extruder_colour = #FFAA55;#5182DB;#4ECDD3;#FB7259 +extruder_offset = 0x0,0x0,0x0,0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25,0.25,0.25,0.25 +min_layer_height = 0.07,0.07,0.07,0.07 +nozzle_diameter = 0.6,0.6,0.6,0.6 +octoprint_apikey = +octoprint_host = +printer_notes = +printer_settings_id = +retract_before_travel = 3,3,3,3 +retract_before_wipe = 60%,60%,60%,60% +retract_layer_change = 0,0,0,0 +retract_length = 4,4,4,4 +retract_length_toolchange = 4,4,4,4 +retract_lift = 0.5,0.5,0.5,0.5 +retract_lift_above = 0,0,0,0 +retract_lift_below = 199,199,199,199 +retract_restart_extra = 0,0,0,0 +retract_restart_extra_toolchange = 0,0,0,0 +retract_speed = 80,80,80,80 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 1 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\n{if not has_wipe_tower}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\n{endif}\nG92 E0.0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 0 +wipe = 1,1,1,1 +z_offset = 0 + +[printer:Original Prusa i3 MK3] +bed_shape = 0x0,250x0,250x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +between_objects_gcode = +deretract_speed = 0 +end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = reprap +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.25 +min_layer_height = 0.07 +nozzle_diameter = 0.4 +octoprint_apikey = +octoprint_host = +printer_notes = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 0.8 +retract_length_toolchange = 3 +retract_lift = 0.5 +retract_lift_above = 1 +retract_lift_below = 199 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 35 +serial_port = +serial_speed = 250000 +single_extruder_multi_material = 0 +start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside pritn area\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 + +[presets] +print = 0.15mm 100mms Linear Advance +printer = Original Prusa i3 MK2 +filament = Prusa PLA 1.75mm From 455f9befbcb190da3ad412d8c0eb412ed70e44e0 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 20:51:45 +0100 Subject: [PATCH 32/69] Moved the icons and images from Slic3r/var to Slic3r/resources/icons to simplify installation of application static data (icons, images and printer profiles) onto a target system. --- {var => resources/icons}/Slic3r-console.ico | Bin {var => resources/icons}/Slic3r.icns | Bin {var => resources/icons}/Slic3r.ico | Bin {var => resources/icons}/Slic3r.png | Bin {var => resources/icons}/Slic3r_128px.png | Bin {var => resources/icons}/Slic3r_192px.png | Bin .../icons}/Slic3r_192px_transparent.png | Bin {var => resources/icons}/add.png | Bin {var => resources/icons}/application_view_tile.png | Bin {var => resources/icons}/arrow_down.png | Bin {var => resources/icons}/arrow_left.png | Bin {var => resources/icons}/arrow_out.png | Bin {var => resources/icons}/arrow_refresh.png | Bin {var => resources/icons}/arrow_right.png | Bin .../icons}/arrow_rotate_anticlockwise.png | Bin {var => resources/icons}/arrow_rotate_clockwise.png | Bin {var => resources/icons}/arrow_up.png | Bin {var => resources/icons}/box.png | Bin {var => resources/icons}/brick.png | Bin {var => resources/icons}/brick_add.png | Bin {var => resources/icons}/brick_delete.png | Bin {var => resources/icons}/brick_go.png | Bin {var => resources/icons}/bricks.png | Bin {var => resources/icons}/building.png | Bin {var => resources/icons}/bullet_arrow_down.png | Bin {var => resources/icons}/bullet_arrow_up.png | Bin {var => resources/icons}/bullet_black.png | Bin {var => resources/icons}/bullet_blue.png | Bin {var => resources/icons}/bullet_green.png | Bin {var => resources/icons}/bullet_red.png | Bin {var => resources/icons}/bullet_white.png | Bin {var => resources/icons}/cog.png | Bin {var => resources/icons}/cog_go.png | Bin {var => resources/icons}/control_pause.png | Bin {var => resources/icons}/control_pause_blue.png | Bin {var => resources/icons}/control_play.png | Bin {var => resources/icons}/control_play_blue.png | Bin {var => resources/icons}/control_stop.png | Bin {var => resources/icons}/control_stop_blue.png | Bin {var => resources/icons}/cross.png | Bin {var => resources/icons}/delete.png | Bin {var => resources/icons}/disk.png | Bin {var => resources/icons}/error.png | Bin {var => resources/icons}/flag-green-icon.png | Bin {var => resources/icons}/flag-red-icon.png | Bin {var => resources/icons}/funnel.png | Bin {var => resources/icons}/hourglass.png | Bin {var => resources/icons}/house.png | Bin {var => resources/icons}/infill.png | Bin {var => resources/icons}/joystick.png | Bin {var => resources/icons}/layers.png | Bin {var => resources/icons}/lorry_add.png | Bin {var => resources/icons}/lorry_go.png | Bin {var => resources/icons}/note.png | Bin {var => resources/icons}/package.png | Bin {var => resources/icons}/package_green.png | Bin {var => resources/icons}/page_white_go.png | Bin {var => resources/icons}/plugin.png | Bin {var => resources/icons}/plugin_add.png | Bin {var => resources/icons}/plugin_go.png | Bin {var => resources/icons}/printer_empty.png | Bin {var => resources/icons}/reslice.png | Bin {var => resources/icons}/shape_flip_horizontal.png | Bin {var => resources/icons}/shape_handles.png | Bin {var => resources/icons}/shape_ungroup.png | Bin {var => resources/icons}/spool.png | Bin {var => resources/icons}/tag_blue.png | Bin {var => resources/icons}/textfield.png | Bin {var => resources/icons}/time.png | Bin {var => resources/icons}/variable_layer_height.png | Bin .../icons}/variable_layer_height_reset.png | Bin .../icons}/variable_layer_height_tooltip.png | Bin {var => resources/icons}/wand.png | Bin {var => resources/icons}/wrench.png | Bin {var => resources/icons}/zoom.png | Bin 75 files changed, 0 insertions(+), 0 deletions(-) rename {var => resources/icons}/Slic3r-console.ico (100%) rename {var => resources/icons}/Slic3r.icns (100%) rename {var => resources/icons}/Slic3r.ico (100%) rename {var => resources/icons}/Slic3r.png (100%) rename {var => resources/icons}/Slic3r_128px.png (100%) rename {var => resources/icons}/Slic3r_192px.png (100%) rename {var => resources/icons}/Slic3r_192px_transparent.png (100%) rename {var => resources/icons}/add.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/application_view_tile.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/arrow_down.png (100%) rename {var => resources/icons}/arrow_left.png (100%) rename {var => resources/icons}/arrow_out.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/arrow_refresh.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/arrow_right.png (100%) rename {var => resources/icons}/arrow_rotate_anticlockwise.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/arrow_rotate_clockwise.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/arrow_up.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/box.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/brick.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/brick_add.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/brick_delete.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/brick_go.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bricks.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/building.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bullet_arrow_down.png (100%) rename {var => resources/icons}/bullet_arrow_up.png (100%) rename {var => resources/icons}/bullet_black.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bullet_blue.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bullet_green.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bullet_red.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/bullet_white.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/cog.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/cog_go.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/control_pause.png (100%) rename {var => resources/icons}/control_pause_blue.png (100%) rename {var => resources/icons}/control_play.png (100%) rename {var => resources/icons}/control_play_blue.png (100%) rename {var => resources/icons}/control_stop.png (100%) rename {var => resources/icons}/control_stop_blue.png (100%) rename {var => resources/icons}/cross.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/delete.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/disk.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/error.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/flag-green-icon.png (100%) rename {var => resources/icons}/flag-red-icon.png (100%) rename {var => resources/icons}/funnel.png (100%) rename {var => resources/icons}/hourglass.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/house.png (100%) rename {var => resources/icons}/infill.png (100%) rename {var => resources/icons}/joystick.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/layers.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/lorry_add.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/lorry_go.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/note.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/package.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/package_green.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/page_white_go.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/plugin.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/plugin_add.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/plugin_go.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/printer_empty.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/reslice.png (100%) rename {var => resources/icons}/shape_flip_horizontal.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/shape_handles.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/shape_ungroup.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/spool.png (100%) rename {var => resources/icons}/tag_blue.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/textfield.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/time.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/variable_layer_height.png (100%) rename {var => resources/icons}/variable_layer_height_reset.png (100%) rename {var => resources/icons}/variable_layer_height_tooltip.png (100%) rename {var => resources/icons}/wand.png (100%) rename {var => resources/icons}/wrench.png (100%) mode change 100755 => 100644 rename {var => resources/icons}/zoom.png (100%) mode change 100755 => 100644 diff --git a/var/Slic3r-console.ico b/resources/icons/Slic3r-console.ico similarity index 100% rename from var/Slic3r-console.ico rename to resources/icons/Slic3r-console.ico diff --git a/var/Slic3r.icns b/resources/icons/Slic3r.icns similarity index 100% rename from var/Slic3r.icns rename to resources/icons/Slic3r.icns diff --git a/var/Slic3r.ico b/resources/icons/Slic3r.ico similarity index 100% rename from var/Slic3r.ico rename to resources/icons/Slic3r.ico diff --git a/var/Slic3r.png b/resources/icons/Slic3r.png similarity index 100% rename from var/Slic3r.png rename to resources/icons/Slic3r.png diff --git a/var/Slic3r_128px.png b/resources/icons/Slic3r_128px.png similarity index 100% rename from var/Slic3r_128px.png rename to resources/icons/Slic3r_128px.png diff --git a/var/Slic3r_192px.png b/resources/icons/Slic3r_192px.png similarity index 100% rename from var/Slic3r_192px.png rename to resources/icons/Slic3r_192px.png diff --git a/var/Slic3r_192px_transparent.png b/resources/icons/Slic3r_192px_transparent.png similarity index 100% rename from var/Slic3r_192px_transparent.png rename to resources/icons/Slic3r_192px_transparent.png diff --git a/var/add.png b/resources/icons/add.png old mode 100755 new mode 100644 similarity index 100% rename from var/add.png rename to resources/icons/add.png diff --git a/var/application_view_tile.png b/resources/icons/application_view_tile.png old mode 100755 new mode 100644 similarity index 100% rename from var/application_view_tile.png rename to resources/icons/application_view_tile.png diff --git a/var/arrow_down.png b/resources/icons/arrow_down.png similarity index 100% rename from var/arrow_down.png rename to resources/icons/arrow_down.png diff --git a/var/arrow_left.png b/resources/icons/arrow_left.png similarity index 100% rename from var/arrow_left.png rename to resources/icons/arrow_left.png diff --git a/var/arrow_out.png b/resources/icons/arrow_out.png old mode 100755 new mode 100644 similarity index 100% rename from var/arrow_out.png rename to resources/icons/arrow_out.png diff --git a/var/arrow_refresh.png b/resources/icons/arrow_refresh.png old mode 100755 new mode 100644 similarity index 100% rename from var/arrow_refresh.png rename to resources/icons/arrow_refresh.png diff --git a/var/arrow_right.png b/resources/icons/arrow_right.png similarity index 100% rename from var/arrow_right.png rename to resources/icons/arrow_right.png diff --git a/var/arrow_rotate_anticlockwise.png b/resources/icons/arrow_rotate_anticlockwise.png old mode 100755 new mode 100644 similarity index 100% rename from var/arrow_rotate_anticlockwise.png rename to resources/icons/arrow_rotate_anticlockwise.png diff --git a/var/arrow_rotate_clockwise.png b/resources/icons/arrow_rotate_clockwise.png old mode 100755 new mode 100644 similarity index 100% rename from var/arrow_rotate_clockwise.png rename to resources/icons/arrow_rotate_clockwise.png diff --git a/var/arrow_up.png b/resources/icons/arrow_up.png old mode 100755 new mode 100644 similarity index 100% rename from var/arrow_up.png rename to resources/icons/arrow_up.png diff --git a/var/box.png b/resources/icons/box.png old mode 100755 new mode 100644 similarity index 100% rename from var/box.png rename to resources/icons/box.png diff --git a/var/brick.png b/resources/icons/brick.png old mode 100755 new mode 100644 similarity index 100% rename from var/brick.png rename to resources/icons/brick.png diff --git a/var/brick_add.png b/resources/icons/brick_add.png old mode 100755 new mode 100644 similarity index 100% rename from var/brick_add.png rename to resources/icons/brick_add.png diff --git a/var/brick_delete.png b/resources/icons/brick_delete.png old mode 100755 new mode 100644 similarity index 100% rename from var/brick_delete.png rename to resources/icons/brick_delete.png diff --git a/var/brick_go.png b/resources/icons/brick_go.png old mode 100755 new mode 100644 similarity index 100% rename from var/brick_go.png rename to resources/icons/brick_go.png diff --git a/var/bricks.png b/resources/icons/bricks.png old mode 100755 new mode 100644 similarity index 100% rename from var/bricks.png rename to resources/icons/bricks.png diff --git a/var/building.png b/resources/icons/building.png old mode 100755 new mode 100644 similarity index 100% rename from var/building.png rename to resources/icons/building.png diff --git a/var/bullet_arrow_down.png b/resources/icons/bullet_arrow_down.png similarity index 100% rename from var/bullet_arrow_down.png rename to resources/icons/bullet_arrow_down.png diff --git a/var/bullet_arrow_up.png b/resources/icons/bullet_arrow_up.png similarity index 100% rename from var/bullet_arrow_up.png rename to resources/icons/bullet_arrow_up.png diff --git a/var/bullet_black.png b/resources/icons/bullet_black.png old mode 100755 new mode 100644 similarity index 100% rename from var/bullet_black.png rename to resources/icons/bullet_black.png diff --git a/var/bullet_blue.png b/resources/icons/bullet_blue.png old mode 100755 new mode 100644 similarity index 100% rename from var/bullet_blue.png rename to resources/icons/bullet_blue.png diff --git a/var/bullet_green.png b/resources/icons/bullet_green.png old mode 100755 new mode 100644 similarity index 100% rename from var/bullet_green.png rename to resources/icons/bullet_green.png diff --git a/var/bullet_red.png b/resources/icons/bullet_red.png old mode 100755 new mode 100644 similarity index 100% rename from var/bullet_red.png rename to resources/icons/bullet_red.png diff --git a/var/bullet_white.png b/resources/icons/bullet_white.png old mode 100755 new mode 100644 similarity index 100% rename from var/bullet_white.png rename to resources/icons/bullet_white.png diff --git a/var/cog.png b/resources/icons/cog.png old mode 100755 new mode 100644 similarity index 100% rename from var/cog.png rename to resources/icons/cog.png diff --git a/var/cog_go.png b/resources/icons/cog_go.png old mode 100755 new mode 100644 similarity index 100% rename from var/cog_go.png rename to resources/icons/cog_go.png diff --git a/var/control_pause.png b/resources/icons/control_pause.png similarity index 100% rename from var/control_pause.png rename to resources/icons/control_pause.png diff --git a/var/control_pause_blue.png b/resources/icons/control_pause_blue.png similarity index 100% rename from var/control_pause_blue.png rename to resources/icons/control_pause_blue.png diff --git a/var/control_play.png b/resources/icons/control_play.png similarity index 100% rename from var/control_play.png rename to resources/icons/control_play.png diff --git a/var/control_play_blue.png b/resources/icons/control_play_blue.png similarity index 100% rename from var/control_play_blue.png rename to resources/icons/control_play_blue.png diff --git a/var/control_stop.png b/resources/icons/control_stop.png similarity index 100% rename from var/control_stop.png rename to resources/icons/control_stop.png diff --git a/var/control_stop_blue.png b/resources/icons/control_stop_blue.png similarity index 100% rename from var/control_stop_blue.png rename to resources/icons/control_stop_blue.png diff --git a/var/cross.png b/resources/icons/cross.png old mode 100755 new mode 100644 similarity index 100% rename from var/cross.png rename to resources/icons/cross.png diff --git a/var/delete.png b/resources/icons/delete.png old mode 100755 new mode 100644 similarity index 100% rename from var/delete.png rename to resources/icons/delete.png diff --git a/var/disk.png b/resources/icons/disk.png old mode 100755 new mode 100644 similarity index 100% rename from var/disk.png rename to resources/icons/disk.png diff --git a/var/error.png b/resources/icons/error.png old mode 100755 new mode 100644 similarity index 100% rename from var/error.png rename to resources/icons/error.png diff --git a/var/flag-green-icon.png b/resources/icons/flag-green-icon.png similarity index 100% rename from var/flag-green-icon.png rename to resources/icons/flag-green-icon.png diff --git a/var/flag-red-icon.png b/resources/icons/flag-red-icon.png similarity index 100% rename from var/flag-red-icon.png rename to resources/icons/flag-red-icon.png diff --git a/var/funnel.png b/resources/icons/funnel.png similarity index 100% rename from var/funnel.png rename to resources/icons/funnel.png diff --git a/var/hourglass.png b/resources/icons/hourglass.png old mode 100755 new mode 100644 similarity index 100% rename from var/hourglass.png rename to resources/icons/hourglass.png diff --git a/var/house.png b/resources/icons/house.png similarity index 100% rename from var/house.png rename to resources/icons/house.png diff --git a/var/infill.png b/resources/icons/infill.png similarity index 100% rename from var/infill.png rename to resources/icons/infill.png diff --git a/var/joystick.png b/resources/icons/joystick.png old mode 100755 new mode 100644 similarity index 100% rename from var/joystick.png rename to resources/icons/joystick.png diff --git a/var/layers.png b/resources/icons/layers.png old mode 100755 new mode 100644 similarity index 100% rename from var/layers.png rename to resources/icons/layers.png diff --git a/var/lorry_add.png b/resources/icons/lorry_add.png old mode 100755 new mode 100644 similarity index 100% rename from var/lorry_add.png rename to resources/icons/lorry_add.png diff --git a/var/lorry_go.png b/resources/icons/lorry_go.png old mode 100755 new mode 100644 similarity index 100% rename from var/lorry_go.png rename to resources/icons/lorry_go.png diff --git a/var/note.png b/resources/icons/note.png old mode 100755 new mode 100644 similarity index 100% rename from var/note.png rename to resources/icons/note.png diff --git a/var/package.png b/resources/icons/package.png old mode 100755 new mode 100644 similarity index 100% rename from var/package.png rename to resources/icons/package.png diff --git a/var/package_green.png b/resources/icons/package_green.png old mode 100755 new mode 100644 similarity index 100% rename from var/package_green.png rename to resources/icons/package_green.png diff --git a/var/page_white_go.png b/resources/icons/page_white_go.png old mode 100755 new mode 100644 similarity index 100% rename from var/page_white_go.png rename to resources/icons/page_white_go.png diff --git a/var/plugin.png b/resources/icons/plugin.png old mode 100755 new mode 100644 similarity index 100% rename from var/plugin.png rename to resources/icons/plugin.png diff --git a/var/plugin_add.png b/resources/icons/plugin_add.png old mode 100755 new mode 100644 similarity index 100% rename from var/plugin_add.png rename to resources/icons/plugin_add.png diff --git a/var/plugin_go.png b/resources/icons/plugin_go.png old mode 100755 new mode 100644 similarity index 100% rename from var/plugin_go.png rename to resources/icons/plugin_go.png diff --git a/var/printer_empty.png b/resources/icons/printer_empty.png old mode 100755 new mode 100644 similarity index 100% rename from var/printer_empty.png rename to resources/icons/printer_empty.png diff --git a/var/reslice.png b/resources/icons/reslice.png similarity index 100% rename from var/reslice.png rename to resources/icons/reslice.png diff --git a/var/shape_flip_horizontal.png b/resources/icons/shape_flip_horizontal.png old mode 100755 new mode 100644 similarity index 100% rename from var/shape_flip_horizontal.png rename to resources/icons/shape_flip_horizontal.png diff --git a/var/shape_handles.png b/resources/icons/shape_handles.png old mode 100755 new mode 100644 similarity index 100% rename from var/shape_handles.png rename to resources/icons/shape_handles.png diff --git a/var/shape_ungroup.png b/resources/icons/shape_ungroup.png old mode 100755 new mode 100644 similarity index 100% rename from var/shape_ungroup.png rename to resources/icons/shape_ungroup.png diff --git a/var/spool.png b/resources/icons/spool.png similarity index 100% rename from var/spool.png rename to resources/icons/spool.png diff --git a/var/tag_blue.png b/resources/icons/tag_blue.png old mode 100755 new mode 100644 similarity index 100% rename from var/tag_blue.png rename to resources/icons/tag_blue.png diff --git a/var/textfield.png b/resources/icons/textfield.png old mode 100755 new mode 100644 similarity index 100% rename from var/textfield.png rename to resources/icons/textfield.png diff --git a/var/time.png b/resources/icons/time.png old mode 100755 new mode 100644 similarity index 100% rename from var/time.png rename to resources/icons/time.png diff --git a/var/variable_layer_height.png b/resources/icons/variable_layer_height.png similarity index 100% rename from var/variable_layer_height.png rename to resources/icons/variable_layer_height.png diff --git a/var/variable_layer_height_reset.png b/resources/icons/variable_layer_height_reset.png similarity index 100% rename from var/variable_layer_height_reset.png rename to resources/icons/variable_layer_height_reset.png diff --git a/var/variable_layer_height_tooltip.png b/resources/icons/variable_layer_height_tooltip.png similarity index 100% rename from var/variable_layer_height_tooltip.png rename to resources/icons/variable_layer_height_tooltip.png diff --git a/var/wand.png b/resources/icons/wand.png similarity index 100% rename from var/wand.png rename to resources/icons/wand.png diff --git a/var/wrench.png b/resources/icons/wrench.png old mode 100755 new mode 100644 similarity index 100% rename from var/wrench.png rename to resources/icons/wrench.png diff --git a/var/zoom.png b/resources/icons/zoom.png old mode 100755 new mode 100644 similarity index 100% rename from var/zoom.png rename to resources/icons/zoom.png From ca4bd96d5d31c5515fd14b144c3b281876861c11 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 21:14:03 +0100 Subject: [PATCH 33/69] Modification of Slic3r to search the icons in resources/icons after they have been moved from var --- lib/Slic3r.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 45eedc48d..68579af81 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -41,8 +41,8 @@ warn "Running Slic3r under Perl 5.16 is neither supported nor recommended\n" use FindBin; # Let the XS module know where the GUI resources reside. -set_var_dir(decode_path($FindBin::Bin) . "/var"); -set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '/Resources' : '/resources')); +set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '../Resources' : '/resources')); +set_var_dir(resources_dir() . "/icons"); use Moo 1.003001; From 679aa2822c71e77624e68e83305fe8638b062a39 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 22:11:00 +0100 Subject: [PATCH 34/69] Moved the Slic3rPE/print,filament,printer folders to Slic3rPE/presets/print,filament,printer to separate the presets from further data stored into the Slic3rPE directory. --- lib/Slic3r/GUI.pm | 8 ++------ lib/Slic3r/GUI/Tab.pm | 2 +- xs/src/libslic3r/Utils.hpp | 5 ----- xs/src/libslic3r/utils.cpp | 13 ------------- xs/src/slic3r/GUI/PresetBundle.cpp | 15 ++++++++++++--- xs/src/slic3r/GUI/PresetBundle.hpp | 4 ++-- xs/xsp/GUI_Preset.xsp | 7 ++++--- xs/xsp/XS.xsp | 8 -------- 8 files changed, 21 insertions(+), 41 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 7157f7e92..5176c9c91 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -100,16 +100,12 @@ sub OnInit { # Suppress the '- default -' presets. $self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0); - eval { - $self->{preset_bundle}->load_presets(Slic3r::data_dir); - }; + eval { $self->{preset_bundle}->load_presets }; if ($@) { warn $@ . "\n"; show_error(undef, $@); } - eval { - $self->{preset_bundle}->load_selections($self->{app_config}); - }; + eval { $self->{preset_bundle}->load_selections($self->{app_config}) }; $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; # application frame diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 907be7872..30429e88b 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -147,7 +147,7 @@ sub save_preset { return unless $dlg->ShowModal == wxID_OK; $name = $dlg->get_name; } - # Save the preset into Slic3r::data_dir/section_name/preset_name.ini + # Save the preset into Slic3r::data_dir/presets/section_name/preset_name.ini eval { $self->{presets}->save_current_preset($name); }; Slic3r::GUI::catch_error($self) and return; # Add the new item into the UI component, remove dirty flags and activate the saved item. diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp index d988de860..3afbc912f 100644 --- a/xs/src/libslic3r/Utils.hpp +++ b/xs/src/libslic3r/Utils.hpp @@ -24,11 +24,6 @@ const std::string& resources_dir(); void set_data_dir(const std::string &path); // Return a full path to the GUI resource files. const std::string& data_dir(); -// Return a full path to a configuration file given its file name.. -std::string config_path(const std::string &file_name); -// Return a full path to a configuration file given the section and name. -// The suffix ".ini" will be added if it is missing in the name. -std::string config_path(const std::string §ion, const std::string &name); extern std::string encode_path(const char *src); extern std::string decode_path(const char *src); diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 53efa466b..ee579161f 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -113,19 +113,6 @@ const std::string& data_dir() return g_data_dir; } -std::string config_path(const std::string &file_name) -{ - auto file = (boost::filesystem::path(g_data_dir) / file_name).make_preferred(); - return file.string(); -} - -std::string config_path(const std::string §ion, const std::string &name) -{ - auto file_name = boost::algorithm::iends_with(name, ".ini") ? name : name + ".ini"; - auto file = (boost::filesystem::path(g_data_dir) / section / file_name).make_preferred(); - return file.string(); -} - } // namespace Slic3r #ifdef SLIC3R_HAS_BROKEN_CROAK diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 1f872ffd6..76fe3ae95 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -66,7 +66,12 @@ PresetBundle::~PresetBundle() void PresetBundle::setup_directories() { boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir()); - std::initializer_list paths = { data_dir, data_dir / "print", data_dir / "filament", data_dir / "printer" }; + std::initializer_list paths = { + data_dir, + data_dir / "presets", + data_dir / "presets" / "print", + data_dir / "presets" / "filament", + data_dir / "presets" / "printer" }; for (const boost::filesystem::path &path : paths) { boost::filesystem::path subdir = path; subdir.make_preferred(); @@ -76,9 +81,10 @@ void PresetBundle::setup_directories() } } -void PresetBundle::load_presets(const std::string &dir_path) +void PresetBundle::load_presets() { std::string errors_cummulative; + const std::string dir_path = data_dir() + "/presets"; try { this->prints.load_presets(dir_path, "print"); } catch (const std::runtime_error &err) { @@ -465,8 +471,11 @@ size_t PresetBundle::load_configbundle(const std::string &path) for (auto &kvp : section.second) config.set_deserialize(kvp.first, kvp.second.data()); Preset::normalize(config); + // Decide a full path to this .ini file. + auto file_name = boost::algorithm::iends_with(preset_name, ".ini") ? preset_name : preset_name + ".ini"; + auto file_path = (boost::filesystem::path(data_dir()) / "presets" / presets->name() / file_name).make_preferred(); // Load the preset into the list of presets, save it to disk. - presets->load_preset(Slic3r::config_path(presets->name(), preset_name), preset_name, std::move(config), false).save(); + presets->load_preset(file_path.string(), preset_name, std::move(config), false).save(); ++ presets_loaded; } } diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 451ec69c1..238e7c802 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -17,8 +17,8 @@ public: void setup_directories(); - // Load ini files of all types (print, filament, printer) from the provided directory path. - void load_presets(const std::string &dir_path); + // Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets. + void load_presets(); // Load selections (current print, current filaments, current printer) from config.ini // This is done just once on application start up. diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index a7fbdd07f..d6af38d15 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -106,12 +106,13 @@ PresetCollection::arrayref() croak("Cannot create configuration directories:\n%s\n", e.what()); } %}; - void load_presets(const char *dir_path) + void load_presets() %code%{ try { - THIS->load_presets(dir_path); + THIS->load_presets(); } catch (std::exception& e) { - croak("Loading of Slic3r presets from %s failed.\n\n%s\n", dir_path, e.what()); + croak("Loading of Slic3r presets from %s failed.\n\n%s\n", + Slic3r::data_dir().c_str(), e.what()); } %}; void load_config_file(const char *path) diff --git a/xs/xsp/XS.xsp b/xs/xsp/XS.xsp index d59f826b7..b2f772834 100644 --- a/xs/xsp/XS.xsp +++ b/xs/xsp/XS.xsp @@ -91,14 +91,6 @@ data_dir() RETVAL = const_cast(Slic3r::data_dir().c_str()); OUTPUT: RETVAL -std::string -config_path(section, name) - const char *section; - const char *name; - CODE: - RETVAL = Slic3r::config_path(section, name); - OUTPUT: RETVAL - std::string encode_path(src) const char *src; From ae5863f5e043a92188377c4673b4efd87ca09976 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 10 Dec 2017 23:27:22 +0100 Subject: [PATCH 35/69] Fixed a typo in a path to Resources on OSX. --- lib/Slic3r.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 68579af81..22a6ee389 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -41,7 +41,7 @@ warn "Running Slic3r under Perl 5.16 is neither supported nor recommended\n" use FindBin; # Let the XS module know where the GUI resources reside. -set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '../Resources' : '/resources')); +set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '/../Resources' : '/resources')); set_var_dir(resources_dir() . "/icons"); use Moo 1.003001; From 19388285205ff46379ce0f9b0291aff1badd6568 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 11 Dec 2017 09:31:29 +0100 Subject: [PATCH 36/69] Slic3r version was not set by the placeholder parser. https://github.com/prusa3d/Slic3r/issues/615 --- xs/src/libslic3r/PlaceholderParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 8f2f6d6e7..77ef64e8d 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -56,7 +56,7 @@ namespace Slic3r { PlaceholderParser::PlaceholderParser() { - this->set("version", SLIC3R_VERSION); + this->set("version", std::string(SLIC3R_VERSION)); this->apply_env_variables(); this->update_timestamp(); } From 61e6f23ed2d3366cc7370ba75ddd0d1c1404f6f5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 11 Dec 2017 17:19:55 +0100 Subject: [PATCH 37/69] Fix of "Multimaterial printer switches filament at the wrong time during a print" https://github.com/prusa3d/Slic3r/issues/607 There was a single layer between the raft top and the object first layer missing on the wipe tower, and after this missing layer all the tool changes were shifted by one layer, meaning two color print had the colors switched. --- xs/src/libslic3r/GCode/ToolOrdering.cpp | 28 +++++++++++++++---- xs/src/libslic3r/GCode/ToolOrdering.hpp | 2 ++ xs/src/libslic3r/Layer.hpp | 4 ++- xs/src/libslic3r/Print.cpp | 37 +++++++++++++++++++++++++ xs/src/libslic3r/SupportMaterial.cpp | 12 ++------ xs/xsp/Layer.xsp | 26 ----------------- xs/xsp/Print.xsp | 1 - 7 files changed, 67 insertions(+), 43 deletions(-) diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index 0ffdbcc43..a8954eca5 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -1,7 +1,16 @@ #include "Print.hpp" #include "ToolOrdering.hpp" -#include +// #define SLIC3R_DEBUG + +// Make assert active if SLIC3R_DEBUG +#ifdef SLIC3R_DEBUG + #define DEBUG + #define _DEBUG + #undef NDEBUG +#endif + +#include #include namespace Slic3r { @@ -257,11 +266,18 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z)); // Find the 1st layer above lt_new. for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z; ++ j); - LayerTools <_extra = (m_layer_tools[j].print_z == lt_new.print_z) ? - m_layer_tools[j] : - *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); - lt_extra.has_wipe_tower = true; - lt_extra.wipe_tower_partitions = lt_object.wipe_tower_partitions; + if (m_layer_tools[j].print_z == lt_new.print_z) { + m_layer_tools[j].has_wipe_tower = true; + } else { + LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); + LayerTools <_prev = m_layer_tools[j - 1]; + LayerTools <_next = m_layer_tools[j + 1]; + assert(! lt_prev.extruders.empty() && ! lt_next.extruders.empty()); + assert(lt_prev.extruders.back() == lt_next.extruders.front()); + lt_extra.has_wipe_tower = true; + lt_extra.extruders.push_back(lt_next.extruders.front()); + lt_extra.wipe_tower_partitions = lt_next.wipe_tower_partitions; + } } } break; diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/xs/src/libslic3r/GCode/ToolOrdering.hpp index abf1aa6b2..c92806b19 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.hpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.hpp @@ -69,6 +69,8 @@ public: const LayerTools& front() const { return m_layer_tools.front(); } const LayerTools& back() const { return m_layer_tools.back(); } + std::vector::const_iterator begin() const { return m_layer_tools.begin(); } + std::vector::const_iterator end() const { return m_layer_tools.end(); } bool empty() const { return m_layer_tools.empty(); } const std::vector& layer_tools() const { return m_layer_tools; } bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().wipe_tower_partitions > 0; } diff --git a/xs/src/libslic3r/Layer.hpp b/xs/src/libslic3r/Layer.hpp index f8fdcdd4d..f3b460443 100644 --- a/xs/src/libslic3r/Layer.hpp +++ b/xs/src/libslic3r/Layer.hpp @@ -161,7 +161,9 @@ public: // Is there any valid extrusion assigned to this LayerRegion? virtual bool has_extrusions() const { return ! support_fills.empty(); } -protected: +//protected: + // The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower + // between the raft and the object first layer. SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) : Layer(id, object, height, print_z, slice_z) {} virtual ~SupportLayer() {} diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 190fbfe6e..773998394 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -978,6 +978,43 @@ void Print::_make_wipe_tower() // Don't generate any wipe tower. return; + // Check whether there are any layers in m_tool_ordering, which are marked with has_wipe_tower, + // they print neither object, nor support. These layers are above the raft and below the object, and they + // shall be added to the support layers to be printed. + // see https://github.com/prusa3d/Slic3r/issues/607 + { + size_t idx_begin = size_t(-1); + size_t idx_end = m_tool_ordering.layer_tools().size(); + // Find the first wipe tower layer, which does not have a counterpart in an object or a support layer. + for (size_t i = 0; i < idx_end; ++ i) { + const ToolOrdering::LayerTools < = m_tool_ordering.layer_tools()[i]; + if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) { + idx_begin = i; + break; + } + } + if (idx_begin != size_t(-1)) { + // Find the position in this->objects.first()->support_layers to insert these new support layers. + double wipe_tower_new_layer_print_z_first = m_tool_ordering.layer_tools()[idx_begin].print_z; + SupportLayerPtrs::iterator it_layer = this->objects.front()->support_layers.begin(); + for (; (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer) ; + // Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer. + for (size_t i = idx_begin; i < idx_end; ++ i) { + ToolOrdering::LayerTools < = const_cast(m_tool_ordering.layer_tools()[i]); + if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support)) + break; + lt.has_support = true; + // Insert the new support layer. + //FIXME the support layer ID is duplicated, but Vojtech hopes it is not being used anywhere anyway. + double height = lt.print_z - m_tool_ordering.layer_tools()[i-1].print_z; + auto *new_layer = new SupportLayer((*it_layer)->id(), this->objects.front(), + height, lt.print_z, lt.print_z - 0.5 * height); + it_layer = this->objects.front()->support_layers.insert(it_layer, new_layer); + ++ it_layer; + } + } + } + // Initialize the wipe tower. WipeTowerPrusaMM wipe_tower( float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 07943fb15..b8df67ba6 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -373,15 +373,9 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) height_min = std::min(height_min, layer.height); } if (! empty) { - object.add_support_layer(layer_id, height_min, zavg); - if (layer_id > 0) { - // Inter-link the support layers into a linked list. - SupportLayer *sl1 = object.support_layers[object.support_layer_count() - 2]; - SupportLayer *sl2 = object.support_layers.back(); - sl1->upper_layer = sl2; - sl2->lower_layer = sl1; - } - ++layer_id; + // Here the upper_layer and lower_layer pointers are left to null at the support layers, + // as they are never used. These pointers are candidates for removal. + object.add_support_layer(layer_id ++, height_min, zavg); } i = j; } diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index 71fc540dc..4f09fb521 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -50,10 +50,6 @@ int id(); void set_id(int id); Ref object(); - Ref upper_layer() - %code%{ RETVAL = THIS->upper_layer; %}; - Ref lower_layer() - %code%{ RETVAL = THIS->lower_layer; %}; bool slicing_errors() %code%{ RETVAL = THIS->slicing_errors; %}; coordf_t slice_z() @@ -63,15 +59,6 @@ coordf_t height() %code%{ RETVAL = THIS->height; %}; - void set_upper_layer(Layer *layer) - %code%{ THIS->upper_layer = layer; %}; - void set_lower_layer(Layer *layer) - %code%{ THIS->lower_layer = layer; %}; - bool has_upper_layer() - %code%{ RETVAL = (THIS->upper_layer != NULL); %}; - bool has_lower_layer() - %code%{ RETVAL = (THIS->lower_layer != NULL); %}; - size_t region_count(); Ref get_region(int idx); Ref add_region(PrintRegion* print_region); @@ -112,10 +99,6 @@ int id(); void set_id(int id); Ref object(); - Ref upper_layer() - %code%{ RETVAL = (SupportLayer*)THIS->upper_layer; %}; - Ref lower_layer() - %code%{ RETVAL = (SupportLayer*)THIS->lower_layer; %}; bool slicing_errors() %code%{ RETVAL = THIS->slicing_errors; %}; coordf_t slice_z() @@ -125,15 +108,6 @@ coordf_t height() %code%{ RETVAL = THIS->height; %}; - void set_upper_layer(SupportLayer *layer) - %code%{ THIS->upper_layer = layer; %}; - void set_lower_layer(SupportLayer *layer) - %code%{ THIS->lower_layer = layer; %}; - bool has_upper_layer() - %code%{ RETVAL = (THIS->upper_layer != NULL); %}; - bool has_lower_layer() - %code%{ RETVAL = (THIS->lower_layer != NULL); %}; - size_t region_count(); Ref get_region(int idx); Ref add_region(PrintRegion* print_region); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 1148fd4aa..2e418253b 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -91,7 +91,6 @@ _constant() size_t support_layer_count(); void clear_support_layers(); Ref get_support_layer(int idx); - Ref add_support_layer(int id, coordf_t height, coordf_t print_z); bool step_done(PrintObjectStep step) %code%{ RETVAL = THIS->state.is_done(step); %}; From 743fc9dbd0fede7dc89f784a4f6fcae46ef856d1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 11 Dec 2017 18:00:51 +0100 Subject: [PATCH 38/69] Workaround for buggy Intel HD Graphics OpenGL drivers: Fall back to OpenGL 1.1 by a "use_legacy_opengl" preferences switch. https://github.com/prusa3d/Slic3r/issues/233 https://github.com/prusa3d/Slic3r/issues/268 https://github.com/prusa3d/Slic3r/issues/619 --- lib/Slic3r/GUI/3DScene.pm | 12 +++++++++++- lib/Slic3r/GUI/Preferences.pm | 10 +++++++++- xs/src/slic3r/GUI/AppConfig.cpp | 4 ++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 51c822590..7fae4894a 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -15,7 +15,7 @@ package Slic3r::GUI::3DScene::Base; use strict; use warnings; -use Wx qw(:timer :bitmap :icon :dialog); +use Wx qw(wxTheApp :timer :bitmap :icon :dialog); use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); # must load OpenGL *before* Wx::GLCanvas use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); @@ -956,6 +956,16 @@ sub UseVBOs { my ($self) = @_; if (! defined ($self->{use_VBOs})) { + my $use_legacy = wxTheApp->{app_config}->get('use_legacy_opengl'); + if ($use_legacy eq '1') { + # Disable OpenGL 2.0 rendering. + $self->{use_VBOs} = 0; + # Don't enable the layer editing tool. + $self->{layer_editing_enabled} = 0; + # 2 means failed + $self->{layer_editing_initialized} = 2; + return 0; + } # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized # first when an OpenGL widget is shown for the first time. How ugly. return 0 if (! $self->init && $^O eq 'linux'); diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index d20ccb53f..0f0f319fe 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -72,6 +72,13 @@ sub new { 'if they are marked as incompatible with the active printer', default => $app_config->get("show_incompatible_presets"), )); + $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( + opt_id => 'use_legacy_opengl', + type => 'bool', + label => 'Use legacy OpenGL 1.1 rendering', + tooltip => 'If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may try to check this checkbox. This will disable the layer height editing, so it is likely better to upgrade your graphics driver.', + default => $app_config->get("use_legacy_opengl"), + )); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); @@ -90,7 +97,8 @@ sub _accept { my ($self) = @_; if (defined($self->{values}{no_controller}) || - defined($self->{values}{no_defaults})) { + defined($self->{values}{no_defaults}) || + defined($self->{values}{use_legacy_opengl})) { Slic3r::GUI::warning_catcher($self)->("You need to restart Slic3r to make the changes effective."); } diff --git a/xs/src/slic3r/GUI/AppConfig.cpp b/xs/src/slic3r/GUI/AppConfig.cpp index 3161c5b78..9378a2094 100644 --- a/xs/src/slic3r/GUI/AppConfig.cpp +++ b/xs/src/slic3r/GUI/AppConfig.cpp @@ -45,6 +45,10 @@ void AppConfig::set_defaults() // Version check is enabled by default in the config, but it is not implemented yet. if (get("version_check").empty()) set("version_check", "1"); + // Use OpenGL 1.1 even if OpenGL 2.0 is available. This is mainly to support some buggy Intel HD Graphics drivers. + // https://github.com/prusa3d/Slic3r/issues/233 + if (get("use_legacy_opengl").empty()) + set("use_legacy_opengl", "0"); } void AppConfig::load() From 74cb74f1fc9c84e50be55b08641ca23bf0bc16f1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 12 Dec 2017 13:43:36 +0100 Subject: [PATCH 39/69] Increased maximum allowed temperature to 1500 centigrades as someone is seemingly uses Slic3r to print glass :-) https://github.com/prusa3d/Slic3r/issues/629 --- xs/src/libslic3r/PrintConfig.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index ed54d9b6c..f9edc9b2f 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -14,6 +14,9 @@ PrintConfigDef::PrintConfigDef() t_optiondef_map &Options = this->options; ConfigOptionDef* def; + + // Maximum extruder temperature, bumped to 1500 to support printing of glass. + const int max_temp = 1500; def = this->add("avoid_crossing_perimeters", coBool); def->label = "Avoid crossing perimeters"; @@ -611,7 +614,7 @@ PrintConfigDef::PrintConfigDef() "during print, set this to zero to disable temperature control commands in the output file."; def->cli = "first-layer-temperature=i@"; def->min = 0; - def->max = 500; + def->max = max_temp; def->default_value = new ConfigOptionInts { 200 }; def = this->add("gap_fill_speed", coFloat); @@ -1315,8 +1318,8 @@ PrintConfigDef::PrintConfigDef() "Enables a full-height \"sacrificial\" skirt on which the nozzles are periodically wiped."; def->sidetext = "∆°C"; def->cli = "standby-temperature-delta=i"; - def->min = -500; - def->max = 500; + def->min = -max_temp; + def->max = max_temp; def->default_value = new ConfigOptionInt(-5); def = this->add("start_gcode", coString); @@ -1556,7 +1559,7 @@ PrintConfigDef::PrintConfigDef() def->cli = "temperature=i@"; def->full_label = "Temperature"; def->max = 0; - def->max = 500; + def->max = max_temp; def->default_value = new ConfigOptionInts { 200 }; def = this->add("thin_walls", coBool); From 673e98bc83a89bbb08bce91a4e843900816770e2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 12 Dec 2017 20:47:36 +0100 Subject: [PATCH 40/69] When the legacy OpenGL 1.2 is enforced, suppress anti aliasing as well. Let's hope it will be a valid workaround for the reoccuring buggy Intel HD Graphics driver issue. --- lib/Slic3r/GUI/3DScene.pm | 1 + lib/Slic3r/GUI/Preferences.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 7fae4894a..730216a8b 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -108,6 +108,7 @@ sub new { # We can only enable multi sample anti aliasing wih wxWidgets 3.0.3 and with a hacked Wx::GLCanvas, # which exports some new WX_GL_XXX constants, namely WX_GL_SAMPLE_BUFFERS and WX_GL_SAMPLES. my $can_multisample = + ! wxTheApp->{app_config}->get('use_legacy_opengl') && Wx::wxVERSION >= 3.000003 && defined Wx::GLCanvas->can('WX_GL_SAMPLE_BUFFERS') && defined Wx::GLCanvas->can('WX_GL_SAMPLES'); diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 0f0f319fe..703a7a762 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -76,7 +76,7 @@ sub new { opt_id => 'use_legacy_opengl', type => 'bool', label => 'Use legacy OpenGL 1.1 rendering', - tooltip => 'If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may try to check this checkbox. This will disable the layer height editing, so it is likely better to upgrade your graphics driver.', + tooltip => 'If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may try to check this checkbox. This will disable the layer height editing and anti aliasing, so it is likely better to upgrade your graphics driver.', default => $app_config->get("use_legacy_opengl"), )); From 91e847cb7671b683d8de1747b3ef0a3c4715fba1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 10:32:25 +0100 Subject: [PATCH 41/69] Yet another fix for https://github.com/prusa3d/Slic3r/issues/607. Use EPSILON to match two layers by their floating point Z height. --- xs/src/libslic3r/GCode/ToolOrdering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index a8954eca5..271b75ef3 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -265,8 +265,8 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ // Insert one additional wipe tower layer between lh.print_z and lt_object.print_z. LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z)); // Find the 1st layer above lt_new. - for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z; ++ j); - if (m_layer_tools[j].print_z == lt_new.print_z) { + for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z - EPSILON; ++ j); + if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) { m_layer_tools[j].has_wipe_tower = true; } else { LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); From 21b4e62e6e9ee9e8bdb352338ac74cc972b4a507 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 14:00:14 +0100 Subject: [PATCH 42/69] Fixed handling of print and filament presets incompatible with the newly selected print profile, fixed loading of print and filament tab pages after the print or filament preset has been changed to be compatible with a newly selected printer. --- lib/Slic3r/GUI/MainFrame.pm | 16 +++--- lib/Slic3r/GUI/Plater.pm | 1 + lib/Slic3r/GUI/Tab.pm | 105 +++++++++++++++++++++-------------- xs/src/slic3r/GUI/Preset.cpp | 22 +++----- xs/xsp/GUI_Preset.xsp | 1 + 5 files changed, 81 insertions(+), 64 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index a6baef8f9..eae598a09 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -7,7 +7,7 @@ use utf8; use File::Basename qw(basename dirname); use FindBin; -use List::Util qw(min); +use List::Util qw(min first); use Slic3r::Geometry qw(X Y); use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog :font :icon wxTheApp); @@ -132,12 +132,14 @@ sub _init_tabpanel { $self->{plater}->update_presets($tab_name, @_); if ($tab_name eq 'printer') { # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. - wxTheApp->{preset_bundle}->print->update_tab_ui( - $self->{options_tabs}{'print'}->{presets_choice}, - $self->{options_tabs}{'print'}->{show_incompatible_presets}); - wxTheApp->{preset_bundle}->filament->update_tab_ui( - $self->{options_tabs}{'filament'}->{presets_choice}, - $self->{options_tabs}{'filament'}->{show_incompatible_presets}); + my ($presets, $reload_dependent_tabs) = @_; + for my $tab_name_other (qw(print filament)) { + # If the printer tells us that the print or filament preset has been switched or invalidated, + # refresh the print or filament tab page. Otherwise just refresh the combo box. + my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) + ? 'load_current_preset' : 'update_tab_ui'; + $self->{options_tabs}{$tab_name_other}->$update_action; + } # Update the controller printers. $self->{controller}->update_presets(@_) if $self->{controller}; } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index f1db05dc4..f22e6237d 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -506,6 +506,7 @@ sub _on_select_preset { wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection); } if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { + # Only update the platter UI for the 2nd and other filaments. wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice); } else { # call GetSelection() in scalar context as it's context-aware diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 30429e88b..fa8d881b0 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -151,7 +151,7 @@ sub save_preset { eval { $self->{presets}->save_current_preset($name); }; Slic3r::GUI::catch_error($self) and return; # Add the new item into the UI component, remove dirty flags and activate the saved item. - $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); + $self->update_tab_ui; # Update the selection boxes at the platter. $self->_on_presets_changed; } @@ -177,7 +177,7 @@ sub _toggle_show_hide_incompatible { my ($self) = @_; $self->{show_incompatible_presets} = ! $self->{show_incompatible_presets}; $self->_update_show_hide_incompatible_button; - $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); + $self->update_tab_ui; } sub _update_show_hide_incompatible_button { @@ -223,8 +223,9 @@ sub _update {} # to update the "dirty" flags of the selection boxes, # to uddate number of "filament" selection boxes when the number of extruders change. sub _on_presets_changed { - my ($self) = @_; - $self->{on_presets_changed}->($self->{presets}) if $self->{on_presets_changed}; + my ($self, $reload_dependent_tabs) = @_; + $self->{on_presets_changed}->($self->{presets}, $reload_dependent_tabs) + if $self->{on_presets_changed}; } # For the printer profile, generate the extruder pages after a preset is loaded. @@ -237,11 +238,12 @@ sub may_discard_current_dirty_preset my ($self, $presets, $new_printer_name) = @_; $presets //= $self->{presets}; # Display a dialog showing the dirty options in a human readable form. - my $old_preset = $presets->get_current_preset; - my $type_name = $presets->name; - my $name = $old_preset->default ? + my $old_preset = $presets->get_current_preset; + my $type_name = $presets->name; + my $tab = ' '; + my $name = $old_preset->default ? ('Default ' . $type_name . ' preset') : - ($type_name . " preset \"" . $old_preset->name . "\""); + ($type_name . " preset\n$tab" . $old_preset->name); # Collect descriptions of the dirty options. my @option_names = (); foreach my $opt_key (@{$presets->current_dirty_options}) { @@ -251,10 +253,10 @@ sub may_discard_current_dirty_preset push @option_names, $name; } # Show a confirmation dialog with the list of dirty options. - my $changes = join "\n", map "- $_", @option_names; + my $changes = join "\n", map "$tab$_", @option_names; my $message = (defined $new_printer_name) ? - "$name is not compatible with printer \"$new_printer_name\"\n and it has unsaved changes:" : - "$name has unsaved changes:"; + "$name\n\nis not compatible with printer\n$tab$new_printer_name\n\nand it has the following unsaved changes:" : + "$name\n\nhas the following unsaved changes:"; my $confirm = Wx::MessageDialog->new($self, $message . "\n$changes\n\nDiscard changes and continue anyway?", 'Unsaved Changes', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); @@ -267,9 +269,11 @@ sub may_discard_current_dirty_preset sub select_preset { my ($self, $name, $force) = @_; $force //= 0; - my $current_dirty = $self->{presets}->current_is_dirty; - my $canceled = 0; - my $printer_tab = $self->{presets}->name eq 'printer'; + my $presets = $self->{presets}; + my $current_dirty = $presets->current_is_dirty; + my $canceled = 0; + my $printer_tab = $presets->name eq 'printer'; + my @reload_dependent_tabs = (); if (! $force && $current_dirty && ! $self->may_discard_current_dirty_preset) { $canceled = 1; } elsif ($printer_tab) { @@ -278,49 +282,57 @@ sub select_preset { # If they are not compatible and the the current print or filament are dirty, let user decide # whether to discard the changes or keep the current printer selection. my $new_printer_name = $name // ''; - my $new_printer_preset = $self->{presets}->find_preset($new_printer_name, 1); - # my $new_nozzle_dmrs = $new_printer_preset->config->get('nozzle_diameter'); - my $print_presets = wxTheApp->{preset_bundle}->print; - if ($print_presets->current_is_dirty && - ! $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name)) { - if ($self->may_discard_current_dirty_preset($print_presets, $new_printer_name)) { - $canceled = 1; - } else { - $print_presets->discard_current_changes; - } + my $new_printer_preset = $presets->find_preset($new_printer_name, 1); + my $print_presets = wxTheApp->{preset_bundle}->print; + my $print_preset_dirty = $print_presets->current_is_dirty; + my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + $canceled = $print_preset_dirty && ! $print_preset_compatible && + ! $self->may_discard_current_dirty_preset($print_presets, $new_printer_name); + my $filament_presets = wxTheApp->{preset_bundle}->filament; + my $filament_preset_dirty = $filament_presets->current_is_dirty; + my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + if (! $canceled) { + $canceled = $filament_preset_dirty && ! $filament_preset_compatible && + ! $self->may_discard_current_dirty_preset($filament_presets, $new_printer_name); } - my $filament_presets = wxTheApp->{preset_bundle}->filament; - # if ((@$new_nozzle_dmrs <= 1) && - if (! $canceled && $filament_presets->current_is_dirty && - ! $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name)) { - if ($self->may_discard_current_dirty_preset($filament_presets, $new_printer_name)) { - $canceled = 1; - } else { - $filament_presets->discard_current_changes; + if (! $canceled) { + if (! $print_preset_compatible) { + # The preset will be switched to a different, compatible preset, or the '-- default --'. + push @reload_dependent_tabs, 'print'; + $print_presets->discard_current_changes if $print_preset_dirty; + } + if (! $filament_preset_compatible) { + # The preset will be switched to a different, compatible preset, or the '-- default --'. + push @reload_dependent_tabs, 'filament'; + $filament_presets->discard_current_changes if $filament_preset_dirty; } } } if ($canceled) { - $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); - # Trigger the on_presets_changed event so that we also restore the previous value in the plater selector. + $self->update_tab_ui; + # Trigger the on_presets_changed event so that we also restore the previous value in the plater selector, + # if this action was initiated from the platter. $self->_on_presets_changed; } else { + $presets->discard_current_changes if $current_dirty; if (defined $name) { - $self->{presets}->select_preset_by_name($name); + $presets->select_preset_by_name($name); } else { - $self->{presets}->select_preset(0); + $presets->select_preset(0); } # Mark the print & filament enabled if they are compatible with the currently selected preset. + # The following method should not discard changes of current print or filament presets on change of a printer profile, + # if they are compatible with the current printer. wxTheApp->{preset_bundle}->update_compatible_with_printer(1) if $current_dirty || $printer_tab; # Initialize the UI from the current preset. - $self->load_current_preset; + $self->load_current_preset(\@reload_dependent_tabs); } } # Initialize the UI from the current preset. sub load_current_preset { - my ($self) = @_; + my ($self, $dependent_tab_names) = @_; my $preset = $self->{presets}->get_current_preset; eval { local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); @@ -337,8 +349,8 @@ sub load_current_preset { # preset dirty again # (not sure this is true anymore now that update_dirty is idempotent) wxTheApp->CallAfter(sub { - $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); - $self->_on_presets_changed; + $self->update_tab_ui; + $self->_on_presets_changed($dependent_tab_names); }); } @@ -430,8 +442,13 @@ sub _load_key_value { $self->{config}->set($opt_key, $value); # Mark the print & filament enabled if they are compatible with the currently selected preset. if ($opt_key eq 'compatible_printers') { + my $was_compatible = $self->{presets}->get_edited_preset->compatible; wxTheApp->{preset_bundle}->update_compatible_with_printer(0); - $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); + if ($was_compatible != $self->{presets}->get_edited_preset->compatible) { + # This is certainly not a tab page. + # Trigger the on_presets_changed event so that we also update the "compatible" flag at the plater selector. + $self->_on_presets_changed; + } } else { $self->{presets}->update_dirty_ui($self->{presets_choice}); } @@ -538,10 +555,14 @@ sub update_ui_from_settings { } else { if ($self->{show_incompatible_presets}) { $self->{show_incompatible_presets} = 0; - $self->{presets}->update_tab_ui($self->{presets_choice}, 0); + $self->update_tab_ui; } } } +sub update_tab_ui { + my ($self) = @_; + $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}) +} package Slic3r::GUI::Tab::Print; use base 'Slic3r::GUI::Tab'; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 8ba3029ba..89a11f1f9 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -397,29 +397,19 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) void PresetCollection::update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible) { - size_t num_visible = 0; for (size_t idx_preset = 1; idx_preset < m_presets.size(); ++ idx_preset) { bool selected = idx_preset == m_idx_selected; Preset &preset_selected = m_presets[idx_preset]; Preset &preset_edited = selected ? m_edited_preset : preset_selected; - if (preset_edited.update_compatible_with_printer(active_printer)) - // Mark compatible presets as visible. - preset_selected.is_visible = true; - else if (selected && select_other_if_incompatible) { - preset_selected.is_visible = false; + if (! preset_edited.update_compatible_with_printer(active_printer) && + selected && select_other_if_incompatible) m_idx_selected = (size_t)-1; - } if (selected) preset_selected.is_compatible = preset_edited.is_compatible; - if (preset_selected.is_visible) - ++ num_visible; } if (m_idx_selected == (size_t)-1) - // Find some other visible preset. - this->select_preset(first_visible_idx()); - else if (num_visible == 0) - // Show the "-- default --" preset. - m_presets.front().is_visible = true; + // Find some other compatible preset, or the "-- default --" preset. + this->select_preset(first_compatible_idx()); } // Save the preset under a new name. If the name is different from the old one, @@ -460,7 +450,7 @@ void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatibl ui->Clear(); for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; - if (! show_incompatible && ! preset.is_compatible && i != m_idx_selected) + if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) continue; const wxBitmap *bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), @@ -494,6 +484,8 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) return was_dirty != is_dirty; } +// Select a new preset. This resets all the edits done to the currently selected preset. +// If the preset with index idx does not exist, a first visible preset is selected. Preset& PresetCollection::select_preset(size_t idx) { for (Preset &preset : m_presets) diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index d6af38d15..675b06eaf 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -14,6 +14,7 @@ bool external() %code%{ RETVAL = THIS->is_external; %}; bool visible() %code%{ RETVAL = THIS->is_visible; %}; bool dirty() %code%{ RETVAL = THIS->is_dirty; %}; + bool compatible() %code%{ RETVAL = THIS->is_compatible; %}; bool is_compatible_with_printer(char *active_printer) const; const char* name() %code%{ RETVAL = THIS->name.c_str(); %}; From 898c697f13ea09ef428a3425a6ecf8f04bde1cb2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 14:12:47 +0100 Subject: [PATCH 43/69] Update the maximum volumetric flow hint at the filament page when the page gets activated, so that the print & printer profile changes are reflected immediately. --- lib/Slic3r/GUI/Tab.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index fa8d881b0..52ee761b9 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -1243,6 +1243,12 @@ sub _update { for qw(min_fan_speed disable_fan_first_layers); } +sub OnActivate { + my ($self) = @_; + $self->{volumetric_speed_description_line}->SetText( + Slic3r::GUI::PresetHints::maximum_volumetric_flow_description(wxTheApp->{preset_bundle})); +} + package Slic3r::GUI::Tab::Printer; use base 'Slic3r::GUI::Tab'; use Wx qw(wxTheApp :sizer :button :bitmap :misc :id :icon :dialog); From d47dc5da3e9c0f448e52f205de462577223fdfd3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 14:44:27 +0100 Subject: [PATCH 44/69] Fixed update of "dirty" profile when the "compatible_printers" option appears (filter is active) or disappears (no filter active, compatible with any printer). --- lib/Slic3r/GUI/Tab.pm | 9 +-------- xs/src/slic3r/GUI/Preset.cpp | 12 ++++++++++++ xs/src/slic3r/GUI/Preset.hpp | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 52ee761b9..223c06749 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -442,16 +442,9 @@ sub _load_key_value { $self->{config}->set($opt_key, $value); # Mark the print & filament enabled if they are compatible with the currently selected preset. if ($opt_key eq 'compatible_printers') { - my $was_compatible = $self->{presets}->get_edited_preset->compatible; wxTheApp->{preset_bundle}->update_compatible_with_printer(0); - if ($was_compatible != $self->{presets}->get_edited_preset->compatible) { - # This is certainly not a tab page. - # Trigger the on_presets_changed event so that we also update the "compatible" flag at the plater selector. - $self->_on_presets_changed; - } - } else { - $self->{presets}->update_dirty_ui($self->{presets_choice}); } + $self->{presets}->update_dirty_ui($self->{presets_choice}); $self->_on_presets_changed; $self->_update; } diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 89a11f1f9..5f4afc8d2 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -484,6 +484,18 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) return was_dirty != is_dirty; } +std::vector PresetCollection::current_dirty_options() const +{ + std::vector changed = this->get_selected_preset().config.diff(this->get_edited_preset().config); + // The "compatible_printers" option key is handled differently from the others: + // It is not mandatory. If the key is missing, it means it is compatible with any printer. + // If the key exists and it is empty, it means it is compatible with no printer. + const char compatible_printers[] = "compatible_printers"; + if (this->get_selected_preset().config.has(compatible_printers) != this->get_edited_preset().config.has(compatible_printers)) + changed.emplace_back(compatible_printers); + return changed; +} + // Select a new preset. This resets all the edits done to the currently selected preset. // If the preset with index idx does not exist, a first visible preset is selected. Preset& PresetCollection::select_preset(size_t idx) diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 74ae7411c..196c13599 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -159,7 +159,7 @@ public: // Return a preset by an index. If the preset is active, a temporary copy is returned. Preset& preset(size_t idx) { return (int(idx) == m_idx_selected) ? m_edited_preset : m_presets[idx]; } const Preset& preset(size_t idx) const { return const_cast(this)->preset(idx); } - void discard_current_changes() { m_edited_preset = m_presets[m_idx_selected]; } + void discard_current_changes() { m_presets[m_idx_selected].reset_dirty(); m_edited_preset = m_presets[m_idx_selected]; } // Return a preset by its name. If the preset is active, a temporary copy is returned. // If a preset is not found by its name, null is returned. @@ -185,9 +185,9 @@ public: size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } // Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ. - bool current_is_dirty() { return ! this->current_dirty_options().empty(); } + bool current_is_dirty() const { return ! this->current_dirty_options().empty(); } // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. - std::vector current_dirty_options() { return this->get_selected_preset().config.diff(this->get_edited_preset().config); } + std::vector current_dirty_options() const; // Update the choice UI from the list of presets. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. From 38ecfa8467ab47da12f10c8a1d61d6d8ef41001e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 15:03:14 +0100 Subject: [PATCH 45/69] Updated the build instructions on OSX due to breaking changes caused by the perlbrew system. --- doc/How_to_build_Slic3r.txt | 39 +++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/doc/How_to_build_Slic3r.txt b/doc/How_to_build_Slic3r.txt index 0c5c709b0..6c261d652 100644 --- a/doc/How_to_build_Slic3r.txt +++ b/doc/How_to_build_Slic3r.txt @@ -1,6 +1,6 @@ -How to build Slic3r on Mac OS X 10.7 Lion 64bit +How to build Slic3r on Mac OS X 10.9 Maveric --------------------------------------------- -Vojtech Bubnik, 2016-04-26 +Vojtech Bubnik, 2017-12-12 1) Install Mac OS X 10.7 Lion 64 bit with X Code @@ -55,6 +55,9 @@ brew install boost --universal Install dylibbundler tool. The dylibbundler tool serves to collect dependent dynamic libraries and fix their linkage. Execute brew install dylibbundler +Install cmake +brew install cmake + 3) Install perl --------------- @@ -62,18 +65,31 @@ We don't want to distribute perl pre-installed on the Mac OS box. First, the sys http://perlbrew.pl/ First install perlbrew -\curl -L http://install.perlbrew.pl | bash +curl -L http://install.perlbrew.pl | bash Then compile the newest perl with the rellocatable @INC path and with multithreading enabled, execute following line: -perlbrew install --threads -Duserelocatableinc --switch perl-5.22.0 +perlbrew install --threads -Duserelocatableinc --switch perl-5.26.1 The --switch parameter switches the active perl to the currently compiled one. Available perl versions could be listed by calling perlbrew available +Switch to the newly compiled perl +perl5/perlbrew/bin/perlbrew switch perl-5.26.1 +Install cpanm +perlbrew install-cpanm Initialize CPAN, install PAR and PAR::Packer modules execute cpan command, from the cpan prompt, run install App::cpanminus +install ExtUtils::CppGuess +install ExtUtils::Typemaps +install ExtUtils::Typemaps::Basic install PAR install PAR::Packer +install Module::Build +install Module::Pluggable +install Module::Runtime +install Moo +install Test::Pod +install Test::Pod::Coverage quit 4) Download and install Slic3r @@ -92,6 +108,21 @@ to have the model sliced. 5) Download and compile the GUI libraries needed to execute Slic3r in GUI mode ------------------------------------------------------------------------------ +Building the Perl Alien-Wx containing a wxWidgets library: +We use wxWidgets-3.0.3. +patch wxWidgets-3.0.3//src/osx/cocoa/textctrl.mm , see https://github.com/prusa3d/Slic3r/issues/600 +perl -I. Build.PL --wxWidgets-extraflags="--with-osx_cocoa --with-macosx-version-min=10.9 --with-macosx-sdk=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk --with-libjpeg=builtin --with-libpng=builtin --with-regex=builtin --with-libtiff=builtin --with-zlib=builtin --with-expat=builtin --with-opengl" +perl -I. Build +perl -I. Build test +perl -I. Build + +Building the Perl Wx package: +cpan install Wx + +Building the Perl OpenGL package: +OpenGL needs to be patched to support MSAA, see the Windows patch. + + For the current Slic3r 1.2.30 code base, set the environment variable SLIC3R_STATIC to link a static version of the boost library: export SLIC3R_STATIC=1 From 08b74f8caf6e91485fd1d720ac01a93913e8a938 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 13 Dec 2017 15:35:00 +0100 Subject: [PATCH 46/69] Fix of the wipe tower priming towers. The priming towers were printed at the homing height on the MK2MM printer, not at the 1st layer height. --- xs/src/libslic3r/GCode.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b297ddab0..25fbc0139 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -501,23 +501,21 @@ void GCode::_do_export(Print &print, FILE *file) fprintf(file, "\n"); } // Write some terse information on the slicing parameters. - { - 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); - fprintf(file, "; perimeters extrusion width = %.2fmm\n", region->flow(frPerimeter, layer_height, false, false, -1., *first_object).width); - fprintf(file, "; infill extrusion width = %.2fmm\n", region->flow(frInfill, layer_height, false, false, -1., *first_object).width); - fprintf(file, "; solid infill extrusion width = %.2fmm\n", region->flow(frSolidInfill, layer_height, false, false, -1., *first_object).width); - fprintf(file, "; top infill extrusion width = %.2fmm\n", region->flow(frTopSolidInfill, layer_height, false, false, -1., *first_object).width); - 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, first_layer_height, false, true, -1., *first_object).width); - fprintf(file, "\n"); - } + 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); + fprintf(file, "; perimeters extrusion width = %.2fmm\n", region->flow(frPerimeter, layer_height, false, false, -1., *first_object).width); + fprintf(file, "; infill extrusion width = %.2fmm\n", region->flow(frInfill, layer_height, false, false, -1., *first_object).width); + fprintf(file, "; solid infill extrusion width = %.2fmm\n", region->flow(frSolidInfill, layer_height, false, false, -1., *first_object).width); + fprintf(file, "; top infill extrusion width = %.2fmm\n", region->flow(frTopSolidInfill, layer_height, false, false, -1., *first_object).width); + 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, first_layer_height, false, true, -1., *first_object).width); + fprintf(file, "\n"); } // Prepare the helper object for replacing placeholders in custom G-code and output filename. @@ -718,6 +716,7 @@ void GCode::_do_export(Print &print, FILE *file) // Prusa Multi-Material wipe tower. 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_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); write(file, m_wipe_tower->prime(*this)); // Verify, whether the print overaps the priming extrusions. BoundingBoxf bbox_print(get_print_extrusions_extents(print)); From d30c154e796013133d3e2eb0a666687cb964285e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 09:40:45 +0100 Subject: [PATCH 47/69] Reverted the introduction of the "presets" subdir to store the print/filament/printer profiles. The change has been reverted to support the upstream slic3r using the --datadir. While there are breaking changes in the PlaceholderParser, if the new macro processing is not used, the two slic3rs are still mostly interchangeable. The "presets" subdir may be enabled with the SLIC3R_PROFILE_USE_PRESETS_SUBDIR and it may happen, that it will be activated one day if ever the two slci3rs diverge too much. --- xs/src/slic3r/GUI/PresetBundle.cpp | 33 +++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 76fe3ae95..9fb0f21bf 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -25,6 +25,10 @@ #include "../../libslic3r/PlaceholderParser.hpp" #include "../../libslic3r/Utils.hpp" +// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir. +// This breaks compatibility with the upstream Slic3r if the --datadir is used to switch between the two versions. +// #define SLIC3R_PROFILE_USE_PRESETS_SUBDIR + namespace Slic3r { PresetBundle::PresetBundle() : @@ -68,10 +72,19 @@ void PresetBundle::setup_directories() boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir()); std::initializer_list paths = { data_dir, +#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR + // Store the print/filament/printer presets into a "presets" directory. data_dir / "presets", data_dir / "presets" / "print", data_dir / "presets" / "filament", - data_dir / "presets" / "printer" }; + data_dir / "presets" / "printer" +#else + // Store the print/filament/printer presets at the same location as the upstream Slic3r. + data_dir / "print", + data_dir / "filament", + data_dir / "printer" +#endif + }; for (const boost::filesystem::path &path : paths) { boost::filesystem::path subdir = path; subdir.make_preferred(); @@ -84,7 +97,14 @@ void PresetBundle::setup_directories() void PresetBundle::load_presets() { std::string errors_cummulative; - const std::string dir_path = data_dir() + "/presets"; + const std::string dir_path = data_dir() +#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR + // Store the print/filament/printer presets into a "presets" directory. + + "/presets" +#else + // Store the print/filament/printer presets at the same location as the upstream Slic3r. +#endif + ; try { this->prints.load_presets(dir_path, "print"); } catch (const std::runtime_error &err) { @@ -473,7 +493,14 @@ size_t PresetBundle::load_configbundle(const std::string &path) Preset::normalize(config); // Decide a full path to this .ini file. auto file_name = boost::algorithm::iends_with(preset_name, ".ini") ? preset_name : preset_name + ".ini"; - auto file_path = (boost::filesystem::path(data_dir()) / "presets" / presets->name() / file_name).make_preferred(); + auto file_path = (boost::filesystem::path(data_dir()) +#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR + // Store the print/filament/printer presets into a "presets" directory. + / "presets" +#else + // Store the print/filament/printer presets at the same location as the upstream Slic3r. +#endif + / presets->name() / file_name).make_preferred(); // Load the preset into the list of presets, save it to disk. presets->load_preset(file_path.string(), preset_name, std::move(config), false).save(); ++ presets_loaded; From cdab27d337e13d9f4e051caa4a76154cf49048e6 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 09:50:38 +0100 Subject: [PATCH 48/69] Enabled a long wipe when moving away from the wipe tower to reduce stringing. --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index b81a8b04b..858845e3d 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -579,7 +579,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .extrude(box.ld, 3200).extrude(box.rd) .extrude(box.ru).extrude(box.lu); // Wipe the nozzle. - if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + //if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. writer.travel(box.ru, 7200) .travel(box.lu); } else @@ -686,8 +687,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b // Move to the front left corner. writer.travel(wipeTower_box.ld, 7000); - if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + //if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) // Wipe along the front edge. + // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. writer.travel(wipeTower_box.rd) .travel(wipeTower_box.ld); @@ -1004,8 +1006,10 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .extrude(fill_box.rd + xy(- m_perimeter_width, m_perimeter_width)); } - if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + // if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + if (true) // Wipe along the front side of the current wiping box. + // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. writer.travel(fill_box.ld + xy( m_perimeter_width, m_perimeter_width / 2), 7200) .travel(fill_box.rd + xy(- m_perimeter_width, m_perimeter_width / 2)); else From eaaac8b2a4161148b0bbb4267bc866a0d80ab8e1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 11:35:38 +0100 Subject: [PATCH 49/69] Fixed a regression bug due to some Perl to C++ porting of a configuration layer. Fixes https://github.com/prusa3d/Slic3r/issues/627 --- slic3r.pl | 4 ++-- utils/view-toolpaths.pl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/slic3r.pl b/slic3r.pl index c2bee2219..a3cc3cfc2 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -71,10 +71,10 @@ my @external_configs = (); if ($opt{load}) { foreach my $configfile (@{$opt{load}}) { if (-e $configfile) { - push @external_configs, Slic3r::Config->load($configfile); + push @external_configs, Slic3r::Config::load($configfile); } elsif (-e "$FindBin::Bin/$configfile") { printf STDERR "Loading $FindBin::Bin/$configfile\n"; - push @external_configs, Slic3r::Config->load("$FindBin::Bin/$configfile"); + push @external_configs, Slic3r::Config::load("$FindBin::Bin/$configfile"); } else { $opt{ignore_nonexistent_config} or die "Cannot find specified configuration file ($configfile).\n"; } diff --git a/utils/view-toolpaths.pl b/utils/view-toolpaths.pl index 234a8123d..e064885ca 100755 --- a/utils/view-toolpaths.pl +++ b/utils/view-toolpaths.pl @@ -35,7 +35,7 @@ my %opt = (); # load config my $config = Slic3r::Config::new_from_defaults; if ($opt{load}) { - $config->apply(Slic3r::Config->load($opt{load})); + $config->apply(Slic3r::Config::load($opt{load})); } # init print From d65835f89b2d7138e5225bc1ddb4931f09ad4f73 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 13:26:44 +0100 Subject: [PATCH 50/69] Improvement of region classification numerical stability. The Clipper library is not stable when calcuating offsets of contours with holes. Replaced a single call of offset2 with offset_ex(offset_ex()). This is not the most efficient solution, but it fixes this problem. Fixes https://github.com/prusa3d/Slic3r/issues/456 --- xs/src/libslic3r/PrintObject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index fc2979c20..c61fc102b 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -447,7 +447,8 @@ void PrintObject::detect_surfaces_type() to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) : to_polygons(upper_layer->slices); surfaces_append(top, - offset2_ex(diff(layerm_slices_surfaces, upper_slices, true), -offset, offset), + //FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice. + offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset), stTop); } else { // if no upper layer, all surfaces of this one are solid From 4bbe328117687ca34889cff4c72e237b25417379 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 13:47:22 +0100 Subject: [PATCH 51/69] Config wizard will prompt user to copy the profiles from Slic3r to Slic3rPE if the datadir is left to the default value (which is Slic3r), and Slic3rPE directory exists. --- lib/Slic3r/GUI/ConfigWizard.pm | 19 +++++++++++++++++++ xs/src/libslic3r/utils.cpp | 2 ++ 2 files changed, 21 insertions(+) diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index c18741396..be6fb2575 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -274,8 +274,27 @@ sub new { my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); $self->{full_wizard_workflow} = 1; + # Test for the existence of the old config path. + my $message_has_legacy; + { + my $datadir = Slic3r::data_dir; + if ($datadir =~ /Slic3rPE/) { + # Check for existence of the legacy Slic3r directory. + my $datadir_legacy = substr $datadir, 0, -2; + my $dir_enc = Slic3r::encode_path($datadir_legacy); + if (-e $dir_enc && -d $dir_enc && + -e ($dir_enc . '/print') && -d ($dir_enc . '/print') && + -e ($dir_enc . '/filament') && -d ($dir_enc . '/filament') && + -e ($dir_enc . '/printer') && -d ($dir_enc . '/printer') && + -e ($dir_enc . '/slic3r.ini')) { + $message_has_legacy = "Starting with Slic3r 1.38.4, the user profile directory has been renamed to $datadir. You may consider closing Slic3r and renaming $datadir_legacy to $datadir."; + } + } + } + $self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); $self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.'); + $self->append_text($message_has_legacy) if defined $message_has_legacy; # To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); $self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.'); diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index ee579161f..ef05dcae7 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -193,6 +193,7 @@ confess_at(const char *file, int line, const char *func, namespace Slic3r { +// Encode an UTF-8 string to the local code page. std::string encode_path(const char *src) { #ifdef WIN32 @@ -210,6 +211,7 @@ std::string encode_path(const char *src) #endif /* WIN32 */ } +// Encode an 8-bit string from a local code page to UTF-8. std::string decode_path(const char *src) { #ifdef WIN32 From 88e9ba510b966490212238ad32f7b3cc895696fe Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 14 Dec 2017 17:35:06 +0100 Subject: [PATCH 52/69] Run the wizard from OnIdle routine to be executed first after the UI is initialized. This is necessary for the UI to initialize correctly on OSX. --- lib/Slic3r/GUI.pm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 5176c9c91..6e5279727 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -116,9 +116,6 @@ sub OnInit { no_plater => $no_plater, ); $self->SetTopWindow($frame); - if ($run_wizard) { - $self->{mainframe}->config_wizard; - } EVT_IDLE($frame, sub { while (my $cb = shift @cb) { @@ -126,6 +123,14 @@ sub OnInit { } $self->{app_config}->save if $self->{app_config}->dirty; }); + + if ($run_wizard) { + # On OSX the UI was not initialized correctly if the wizard was called + # before the UI was up and running. + $self->CallAfter(sub { + $self->{mainframe}->config_wizard; + }); + } return 1; } From bbfb9a4190adea0a2864ecf3a98cb0ab9942035e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 15 Dec 2017 17:14:24 +0100 Subject: [PATCH 53/69] Added regex matching operators to the conditional G-code processor in a form similar to Perl: Following expression returns true, if the variable matches the regex: variable =~ /regex/ Following expression returns true, if the variable does not match the regex: variable !~ /regex/ --- xs/src/libslic3r/PlaceholderParser.cpp | 41 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 77ef64e8d..b9f6b803e 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -22,6 +22,7 @@ #endif #include +#include // Unicode iterator to iterate over utf8. #include @@ -382,9 +383,37 @@ namespace client lhs.type = TYPE_BOOL; lhs.data.b = (op == '=') ? value : !value; } - static void equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '='); } + static void equal (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '='); } static void not_equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '!'); } + static void regex_op(expr &lhs, boost::iterator_range &rhs, char op) + { + const std::string *subject = nullptr; + const std::string *mask = nullptr; + if (lhs.type == TYPE_STRING) { + // One type is string, the other could be converted to string. + subject = &lhs.s(); + } else { + lhs.throw_exception("Left hand side of a regex match must be a string."); + } + try { + std::string pattern(++ rhs.begin(), -- rhs.end()); + bool result = boost::regex_match(*subject, boost::regex(pattern)); + if (op == '!') + result = ! result; + lhs.reset(); + lhs.type = TYPE_BOOL; + lhs.data.b = result; + } catch (boost::regex_error &ex) { + // Syntax error in the regular expression + boost::throw_exception(qi::expectation_failure( + rhs.begin(), rhs.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what()))); + } + } + + static void regex_matches (expr &lhs, boost::iterator_range &rhs) { return regex_op(lhs, rhs, '='); } + static void regex_doesnt_match(expr &lhs, boost::iterator_range &rhs) { return regex_op(lhs, rhs, '!'); } + static void set_if(bool &cond, bool ¬_yet_consumed, std::string &str_in, std::string &str_out) { if (cond && not_yet_consumed) { @@ -810,6 +839,8 @@ namespace client >> *( ("==" > additive_expression(_r1) ) [px::bind(&expr::equal, _val, _1)] | ("!=" > additive_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] | ("<>" > additive_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] + | ("=~" > regular_expression ) [px::bind(&expr::regex_matches, _val, _1)] + | ("!~" > regular_expression ) [px::bind(&expr::regex_doesnt_match, _val, _1)] ); bool_expr.name("bool expression"); @@ -877,6 +908,9 @@ namespace client [ px::bind(&MyContext::resolve_variable, _r1, _1, _val) ]; variable_reference.name("variable reference"); + regular_expression = raw[lexeme['/' > *((utf8char - char_('\\') - char_('/')) | ('\\' > char_)) > '/']]; + regular_expression.name("regular_expression"); + keywords.add ("and") ("if") @@ -905,6 +939,7 @@ namespace client debug(factor); debug(scalar_variable_reference); debug(variable_reference); + debug(regular_expression); } } @@ -919,9 +954,11 @@ namespace client // Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index]. qi::rule legacy_variable_expansion; // Parsed identifier name. - qi::rule(), spirit::ascii::space_type> identifier; + qi::rule(), spirit::ascii::space_type> identifier; // Math expression consisting of +- operators over terms. qi::rule(const MyContext*), spirit::ascii::space_type> additive_expression; + // Rule to capture a regular expression enclosed in //. + qi::rule(), spirit::ascii::space_type> regular_expression; // Boolean expressions over expressions. qi::rule(const MyContext*), spirit::ascii::space_type> bool_expr; // Evaluate boolean expression into bool. From bb61de83795b10f77107e81384b62405ba2bbc89 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 18 Dec 2017 12:14:09 +0100 Subject: [PATCH 54/69] Fixed a regression error: The "current_extruder" identifier was not set at the placeholder parser. Implemented a new PlaceholderParser::evaluate_boolean_expression() functionality to evaluate just a boolean expression using the full expressive power of the macro processing syntax. This function will now be used for deciding, which print or filament preset is compatible with which printer preset. --- lib/Slic3r.pm | 4 ++ t/custom_gcode.t | 10 +++- xs/src/libslic3r/PlaceholderParser.cpp | 71 ++++++++++++++++++++------ xs/src/libslic3r/PlaceholderParser.hpp | 10 +++- xs/xsp/PlaceholderParser.xsp | 9 ++++ 5 files changed, 84 insertions(+), 20 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 22a6ee389..66039ddf0 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -80,6 +80,10 @@ my $paused = 0; $Slic3r::loglevel = (defined($ENV{'SLIC3R_LOGLEVEL'}) && $ENV{'SLIC3R_LOGLEVEL'} =~ /^[1-9]/) ? $ENV{'SLIC3R_LOGLEVEL'} : 0; set_logging_level($Slic3r::loglevel); +# Let the palceholder parser evaluate one expression to initialize its local static macro_processor +# class instance in a thread safe manner. +Slic3r::GCode::PlaceholderParser->new->evaluate_boolean_expression('1==1'); + sub spawn_thread { my ($cb) = @_; @_ = (); diff --git a/t/custom_gcode.t b/t/custom_gcode.t index 1ccf738aa..75ce0b868 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -1,4 +1,4 @@ -use Test::More tests => 49; +use Test::More tests => 55; use strict; use warnings; @@ -67,6 +67,14 @@ use Slic3r::Test; is $parser->process('{2*foo*(3-12)}'), '0', 'math: 2*foo*(3-12)'; is $parser->process('{2*bar*(3-12)}'), '-36', 'math: 2*bar*(3-12)'; ok abs($parser->process('{2.5*bar*(3-12)}') - -45) < 1e-7, 'math: 2.5*bar*(3-12)'; + + # Test the boolean expression parser. + is $parser->evaluate_boolean_expression('12 == 12'), 1, 'boolean expression parser: 12 == 12'; + is $parser->evaluate_boolean_expression('12 != 12'), 0, 'boolean expression parser: 12 != 12'; + is $parser->evaluate_boolean_expression('"has some PATTERN embedded" =~ /.*PATTERN.*/'), 1, 'boolean expression parser: regex matches'; + is $parser->evaluate_boolean_expression('"has some PATTERN embedded" =~ /.*PTRN.*/'), 0, 'boolean expression parser: regex does not match'; + is $parser->evaluate_boolean_expression('foo + 2 == bar'), 1, 'boolean expression parser: accessing variables, equal'; + is $parser->evaluate_boolean_expression('foo + 3 == bar'), 0, 'boolean expression parser: accessing variables, not equal'; } { diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index b9f6b803e..0b33304a8 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -361,6 +361,13 @@ namespace client out = self.b(); } + static void evaluate_boolean_to_string(expr &self, std::string &out) + { + if (self.type != TYPE_BOOL) + self.throw_exception("Not a boolean expression"); + out = self.b() ? "true" : "false"; + } + // Is lhs==rhs? Store the result into lhs. static void compare_op(expr &lhs, expr &rhs, char op) { @@ -452,18 +459,23 @@ namespace client } struct MyContext { - const PlaceholderParser *pp = nullptr; - const DynamicConfig *config_override = nullptr; - const size_t current_extruder_id = 0; + const DynamicConfig *config = nullptr; + const DynamicConfig *config_override = nullptr; + size_t current_extruder_id = 0; + // If false, the macro_processor will evaluate a full macro. + // If true, the macro processor will evaluate just a boolean condition using the full expressive power of the macro processor. + bool just_boolean_expression = false; std::string error_message; + static void evaluate_full_macro(const MyContext *ctx, bool &result) { result = ! ctx->just_boolean_expression; } + const ConfigOption* resolve_symbol(const std::string &opt_key) const { const ConfigOption *opt = nullptr; if (config_override != nullptr) opt = config_override->option(opt_key); if (opt == nullptr) - opt = pp->option(opt_key); + opt = config->option(opt_key); return opt; } @@ -734,13 +746,13 @@ namespace client }; /////////////////////////////////////////////////////////////////////////// - // Our calculator grammar + // Our macro_processor grammar /////////////////////////////////////////////////////////////////////////// // Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html template - struct calculator : qi::grammar + struct macro_processor : qi::grammar, spirit::ascii::space_type> { - calculator() : calculator::base_type(start) + macro_processor() : macro_processor::base_type(start) { using namespace qi::labels; qi::alpha_type alpha; @@ -772,7 +784,13 @@ namespace client // Starting symbol of the grammer. // The leading eps is required by the "expectation point" operator ">". // Without it, some of the errors would not trigger the error handler. - start = eps > text_block(_r1); + // Also the start symbol switches between the "full macro syntax" and a "boolean expression only", + // depending on the context->just_boolean_expression flag. This way a single static expression parser + // could serve both purposes. + start = eps[px::bind(&MyContext::evaluate_full_macro, _r1, _a)] > + ( eps(_a==true) > text_block(_r1) [_val=_1] + | bool_expr(_r1) [ px::bind(&expr::evaluate_boolean_to_string, _1, _val) ] + ); start.name("start"); qi::on_error(start, px::bind(&MyContext::process_error_message, _r1, _4, _1, _2, _3)); @@ -944,7 +962,7 @@ namespace client } // The start of the grammar. - qi::rule start; + qi::rule, spirit::ascii::space_type> start; // A free-form text. qi::rule text; // A free-form text, possibly empty, possibly containing macro expansions. @@ -979,24 +997,23 @@ namespace client }; } -std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const +static std::string process_macro(const std::string &templ, client::MyContext &context) { typedef std::string::const_iterator iterator_type; - typedef client::calculator calculator; + typedef client::macro_processor macro_processor; // Our whitespace skipper. spirit::ascii::space_type space; - // Our grammar. - calculator calc; + // Our grammar, statically allocated inside the method, meaning it will be allocated the first time + // PlaceholderParser::process() runs. + //FIXME this kind of initialization is not thread safe! + static macro_processor macro_processor_instance; // Iterators over the source template. std::string::const_iterator iter = templ.begin(); std::string::const_iterator end = templ.end(); // Accumulator for the processed template. std::string output; - client::MyContext context; - context.pp = this; - context.config_override = config_override; - bool res = phrase_parse(iter, end, calc(&context), space, output); + bool res = phrase_parse(iter, end, macro_processor_instance(&context), space, output); if (! context.error_message.empty()) { if (context.error_message.back() != '\n' && context.error_message.back() != '\r') context.error_message += '\n'; @@ -1005,4 +1022,24 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu return output; } +std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const +{ + client::MyContext context; + context.config = &this->config(); + context.config_override = config_override; + context.current_extruder_id = current_extruder_id; + return process_macro(templ, context); +} + +// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. +// Throws std::runtime_error on syntax or runtime error. +bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config) +{ + client::MyContext context; + context.config = &config; + // Let the macro processor parse just a boolean expression, not the full macro language. + context.just_boolean_expression = true; + return process_macro(templ, context) == "true"; +} + } diff --git a/xs/src/libslic3r/PlaceholderParser.hpp b/xs/src/libslic3r/PlaceholderParser.hpp index 25264d461..ec2b837ad 100644 --- a/xs/src/libslic3r/PlaceholderParser.hpp +++ b/xs/src/libslic3r/PlaceholderParser.hpp @@ -26,11 +26,17 @@ public: void set(const std::string &key, double value) { this->set(key, new ConfigOptionFloat(value)); } void set(const std::string &key, const std::vector &values) { this->set(key, new ConfigOptionStrings(values)); } void set(const std::string &key, ConfigOption *opt) { m_config.set_key_value(key, opt); } - const ConfigOption* option(const std::string &key) const { return m_config.option(key); } + const DynamicConfig& config() const { return m_config; } + const ConfigOption* option(const std::string &key) const { return m_config.option(key); } - // Fill in the template. + // Fill in the template using a macro processing language. + // Throws std::runtime_error on syntax or runtime error. std::string process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr) const; + // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. + // Throws std::runtime_error on syntax or runtime error. + static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config); + private: DynamicConfig m_config; }; diff --git a/xs/xsp/PlaceholderParser.xsp b/xs/xsp/PlaceholderParser.xsp index ab06450f9..244f89cf8 100644 --- a/xs/xsp/PlaceholderParser.xsp +++ b/xs/xsp/PlaceholderParser.xsp @@ -21,4 +21,13 @@ croak(e.what()); } %}; + + bool evaluate_boolean_expression(const char *str) const + %code%{ + try { + RETVAL = THIS->evaluate_boolean_expression(str, THIS->config()); + } catch (std::exception& e) { + croak(e.what()); + } + %}; }; From 6b81f43206b1a83b4bc8d6d830b31f7c9c477cc2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 18 Dec 2017 15:07:38 +0100 Subject: [PATCH 55/69] First implementation of the "compatible_printers_condition" for the print and filament profiles. Added documentation for building the boost library for Slic3r on Linux. --- doc/How_to_build_Slic3r.txt | 11 ++++++++++ lib/Slic3r/GUI/Tab.pm | 15 ++++++++++++-- xs/src/libslic3r/PrintConfig.cpp | 7 +++++++ xs/src/slic3r/GUI/Preset.cpp | 33 +++++++++++++++++++++--------- xs/src/slic3r/GUI/Preset.hpp | 6 +++--- xs/src/slic3r/GUI/PresetBundle.cpp | 6 ++++-- xs/xsp/GUI_Preset.xsp | 3 ++- 7 files changed, 63 insertions(+), 18 deletions(-) diff --git a/doc/How_to_build_Slic3r.txt b/doc/How_to_build_Slic3r.txt index 6c261d652..a1d112981 100644 --- a/doc/How_to_build_Slic3r.txt +++ b/doc/How_to_build_Slic3r.txt @@ -302,3 +302,14 @@ Debugging the C++ code works fine using the latest Eclipse for C++ and the gdb o It is yet a bit more complicated. The Strawberry MINGW is compiled for a different C++ exception passing model (SJLJ) than the other MINGWs, so one cannot simply combine MINGWs on Windows. For an unknown reason the nice debugger of the QT Creator hangs when debugging the C++ compiled by the Strawberry MINGW. Mabe it is because of the different exception passing models. And to disable optimization of the C/C++ code, one has to manually modify Config_heavy.pl in the Perl central installation. The SLIC3R_DEBUG environment variable did not override all the -O2 and -O3 flags that the perl build adds the gcc execution line. + +---------------------------------------------------------------------- + +Building boost. + +One may save compilation time by compiling just what Slic3r needs. +./bootstrap.sh --with-libraries=system,filesystem,thread,log,locale,regex +The -fPIC flag is required on Linux to make the static libraries rellocatable, +so they could be embedded into a shared library. +./bjam -a link=static variant=release threading=multi cxxflags=-fPIC cflags=-fPIC +To install on Linux to /usr/local/..., run the line above with the additional install keyword and with sudo. diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 223c06749..f7ea01a6f 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -150,6 +150,8 @@ sub save_preset { # Save the preset into Slic3r::data_dir/presets/section_name/preset_name.ini eval { $self->{presets}->save_current_preset($name); }; Slic3r::GUI::catch_error($self) and return; + # Mark the print & filament enabled if they are compatible with the currently selected preset. + wxTheApp->{preset_bundle}->update_compatible_with_printer(0); # Add the new item into the UI component, remove dirty flags and activate the saved item. $self->update_tab_ui; # Update the selection boxes at the platter. @@ -285,12 +287,12 @@ sub select_preset { my $new_printer_preset = $presets->find_preset($new_printer_name, 1); my $print_presets = wxTheApp->{preset_bundle}->print; my $print_preset_dirty = $print_presets->current_is_dirty; - my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); $canceled = $print_preset_dirty && ! $print_preset_compatible && ! $self->may_discard_current_dirty_preset($print_presets, $new_printer_name); my $filament_presets = wxTheApp->{preset_bundle}->filament; my $filament_preset_dirty = $filament_presets->current_is_dirty; - my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); if (! $canceled) { $canceled = $filament_preset_dirty && ! $filament_preset_compatible && ! $self->may_discard_current_dirty_preset($filament_presets, $new_printer_name); @@ -442,6 +444,7 @@ sub _load_key_value { $self->{config}->set($opt_key, $value); # Mark the print & filament enabled if they are compatible with the currently selected preset. if ($opt_key eq 'compatible_printers') { +# $opt_key eq 'compatible_printers_condition') { wxTheApp->{preset_bundle}->update_compatible_with_printer(0); } $self->{presets}->update_dirty_ui($self->{presets_choice}); @@ -838,6 +841,10 @@ sub build { widget => $self->_compatible_printers_widget, ); $optgroup->append_line($line); + + my $option = $optgroup->get_option('compatible_printers_condition'); + $option->full_width(1); + $optgroup->append_single_option_line($option); } } } @@ -1207,6 +1214,10 @@ sub build { widget => $self->_compatible_printers_widget, ); $optgroup->append_line($line); + + my $option = $optgroup->get_option('compatible_printers_condition'); + $option->full_width(1); + $optgroup->append_single_option_line($option); } } } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index f9edc9b2f..902914536 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -139,6 +139,13 @@ PrintConfigDef::PrintConfigDef() def->label = "Compatible printers"; def->default_value = new ConfigOptionStrings(); + def = this->add("compatible_printers_condition", coString); + def->label = "Compatible printers condition"; + def->tooltip = "A boolean expression using the configuration values of an active printer profile. " + "If this expression evaluates to true, this profile is considered compatible " + "with the active printer profile."; + def->default_value = new ConfigOptionString(); + def = this->add("complete_objects", coBool); def->label = "Complete individual objects"; def->tooltip = "When printing multiple objects or copies, this feature will complete " diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 5f4afc8d2..a132af133 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -21,6 +21,7 @@ #include "../../libslic3r/libslic3r.h" #include "../../libslic3r/Utils.hpp" +#include "../../libslic3r/PlaceholderParser.hpp" namespace Slic3r { @@ -141,16 +142,26 @@ std::string Preset::label() const return this->name + (this->is_dirty ? g_suffix_modified : ""); } -bool Preset::is_compatible_with_printer(const std::string &active_printer) const +bool Preset::is_compatible_with_printer(const Preset &active_printer) const { + auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); + if (condition != nullptr && ! condition->value.empty()) { + try { + return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config); + } catch (const std::runtime_error &err) { + //FIXME in case of an error, return "compatible with everything". + printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); + return true; + } + } auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); - return this->is_default || active_printer.empty() || + return this->is_default || active_printer.name.empty() || compatible_printers == nullptr || compatible_printers->values.empty() || - std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer) != + std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != compatible_printers->values.end(); } -bool Preset::update_compatible_with_printer(const std::string &active_printer) +bool Preset::update_compatible_with_printer(const Preset &active_printer) { return this->is_compatible = is_compatible_with_printer(active_printer); } @@ -180,7 +191,7 @@ const std::vector& Preset::print_options() "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", - "compatible_printers" + "compatible_printers", "compatible_printers_condition" }; return s_opts; } @@ -193,7 +204,7 @@ const std::vector& Preset::filament_options() "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode", - "compatible_printers" + "compatible_printers", "compatible_printers_condition" }; return s_opts; } @@ -395,7 +406,7 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) } } -void PresetCollection::update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible) +void PresetCollection::update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible) { for (size_t idx_preset = 1; idx_preset < m_presets.size(); ++ idx_preset) { bool selected = idx_preset == m_idx_selected; @@ -490,9 +501,11 @@ std::vector PresetCollection::current_dirty_options() const // The "compatible_printers" option key is handled differently from the others: // It is not mandatory. If the key is missing, it means it is compatible with any printer. // If the key exists and it is empty, it means it is compatible with no printer. - const char compatible_printers[] = "compatible_printers"; - if (this->get_selected_preset().config.has(compatible_printers) != this->get_edited_preset().config.has(compatible_printers)) - changed.emplace_back(compatible_printers); + std::initializer_list optional_keys { "compatible_printers", "compatible_printers_condition" }; + for (auto &opt_key : optional_keys) { + if (this->get_selected_preset().config.has(opt_key) != this->get_edited_preset().config.has(opt_key)) + changed.emplace_back(opt_key); + } return changed; } diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 196c13599..36bc0b335 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -79,9 +79,9 @@ public: void set_dirty(bool dirty = true) { this->is_dirty = dirty; } void reset_dirty() { this->is_dirty = false; } - bool is_compatible_with_printer(const std::string &active_printer) const; + bool is_compatible_with_printer(const Preset &active_printer) const; // Mark this preset as compatible if it is compatible with active_printer. - bool update_compatible_with_printer(const std::string &active_printer); + bool update_compatible_with_printer(const Preset &active_printer); // Resize the extruder specific fields, initialize them with the content of the 1st extruder. void set_num_extruders(unsigned int n) { set_num_extruders(this->config, n); } @@ -180,7 +180,7 @@ public: size_t size() const { return this->m_presets.size(); } // For Print / Filament presets, disable those, which are not compatible with the printer. - void update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible); + void update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible); size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 9fb0f21bf..4dc2e56ce 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -47,7 +47,9 @@ PresetBundle::PresetBundle() : this->printers.preset(0).config.opt_string("print_settings_id", true); // Create the "compatible printers" keys, as they are not part of the Static print config classes. this->filaments.preset(0).config.optptr("compatible_printers", true); + this->filaments.preset(0).config.optptr("compatible_printers_condition", true); this->prints.preset(0).config.optptr("compatible_printers", true); + this->prints.preset(0).config.optptr("compatible_printers_condition", true); this->prints .load_bitmap_default("cog.png"); this->filaments.load_bitmap_default("spool.png"); @@ -537,8 +539,8 @@ void PresetBundle::update_multi_material_filament_presets() void PresetBundle::update_compatible_with_printer(bool select_other_if_incompatible) { - this->prints.update_compatible_with_printer(this->printers.get_selected_preset().name, select_other_if_incompatible); - this->filaments.update_compatible_with_printer(this->printers.get_selected_preset().name, select_other_if_incompatible); + this->prints.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); + this->filaments.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); if (select_other_if_incompatible) { // Verify validity of the current filament presets. for (std::string &filament_name : this->filament_presets) { diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 675b06eaf..905ff4ecd 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -15,7 +15,8 @@ bool visible() %code%{ RETVAL = THIS->is_visible; %}; bool dirty() %code%{ RETVAL = THIS->is_dirty; %}; bool compatible() %code%{ RETVAL = THIS->is_compatible; %}; - bool is_compatible_with_printer(char *active_printer) const; + bool is_compatible_with_printer(Preset *active_printer) + %code%{ RETVAL = THIS->is_compatible_with_printer(*active_printer); %}; const char* name() %code%{ RETVAL = THIS->name.c_str(); %}; const char* file() %code%{ RETVAL = THIS->file.c_str(); %}; From a402b1b83dced4a8e6a23ff1c6ac0a8e82a5a63a Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 16:48:14 +0100 Subject: [PATCH 56/69] Implemented <,>,<=,>=,or,and,||,&& operators. --- t/custom_gcode.t | 26 +++- xs/src/libslic3r/PlaceholderParser.cpp | 181 ++++++++++++++++++------- xs/src/libslic3r/PlaceholderParser.hpp | 2 +- xs/src/slic3r/GUI/Preset.cpp | 23 +++- xs/src/slic3r/GUI/Preset.hpp | 4 +- 5 files changed, 178 insertions(+), 58 deletions(-) diff --git a/t/custom_gcode.t b/t/custom_gcode.t index 75ce0b868..5d3602483 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -1,4 +1,4 @@ -use Test::More tests => 55; +use Test::More tests => 71; use strict; use warnings; @@ -47,9 +47,13 @@ use Slic3r::Test; { my $parser = Slic3r::GCode::PlaceholderParser->new; - $parser->apply_config(my $config = Slic3r::Config::new_from_defaults); + my $config = Slic3r::Config::new_from_defaults; + $config->set('printer_notes', ' PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 '); + $config->set('nozzle_diameter', [0.6, 0.6, 0.6, 0.6]); + $parser->apply_config($config); $parser->set('foo' => 0); $parser->set('bar' => 2); + $parser->set('num_extruders' => 4); is $parser->process('[temperature_[foo]]'), $config->temperature->[0], "nested config options (legacy syntax)"; @@ -75,6 +79,24 @@ use Slic3r::Test; is $parser->evaluate_boolean_expression('"has some PATTERN embedded" =~ /.*PTRN.*/'), 0, 'boolean expression parser: regex does not match'; is $parser->evaluate_boolean_expression('foo + 2 == bar'), 1, 'boolean expression parser: accessing variables, equal'; is $parser->evaluate_boolean_expression('foo + 3 == bar'), 0, 'boolean expression parser: accessing variables, not equal'; + + is $parser->evaluate_boolean_expression('(12 == 12) and (13 != 14)'), 1, 'boolean expression parser: (12 == 12) and (13 != 14)'; + is $parser->evaluate_boolean_expression('(12 == 12) && (13 != 14)'), 1, 'boolean expression parser: (12 == 12) && (13 != 14)'; + is $parser->evaluate_boolean_expression('(12 == 12) or (13 == 14)'), 1, 'boolean expression parser: (12 == 12) or (13 == 14)'; + is $parser->evaluate_boolean_expression('(12 == 12) || (13 == 14)'), 1, 'boolean expression parser: (12 == 12) || (13 == 14)'; + is $parser->evaluate_boolean_expression('(12 == 12) and not (13 == 14)'), 1, 'boolean expression parser: (12 == 12) and not (13 == 14)'; + is $parser->evaluate_boolean_expression('(12 == 12) ? (1 - 1 == 0) : (2 * 2 == 3)'), 1, 'boolean expression parser: ternary true'; + is $parser->evaluate_boolean_expression('(12 == 21/2) ? (1 - 1 == 0) : (2 * 2 == 3)'), 0, 'boolean expression parser: ternary false'; + is $parser->evaluate_boolean_expression('(12 == 13) ? (1 - 1 == 3) : (2 * 2 == 4)"'), 1, 'boolean expression parser: ternary false'; + is $parser->evaluate_boolean_expression('(12 == 2 * 6) ? (1 - 1 == 3) : (2 * 2 == 4)"'), 0, 'boolean expression parser: ternary true'; + is $parser->evaluate_boolean_expression('12 < 3'), 0, 'boolean expression parser: lower than - false'; + is $parser->evaluate_boolean_expression('12 < 22'), 1, 'boolean expression parser: lower than - true'; + is $parser->evaluate_boolean_expression('12 > 3'), 1, 'boolean expression parser: lower than - true'; + is $parser->evaluate_boolean_expression('12 > 22'), 0, 'boolean expression parser: lower than - false'; + + is $parser->evaluate_boolean_expression('printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1'), 1, 'complex expression'; + is $parser->evaluate_boolean_expression('printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.6 and num_extruders>1)'), 1, 'complex expression2'; + is $parser->evaluate_boolean_expression('printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.3 and num_extruders>1)'), 0, 'complex expression3'; } { diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 0b33304a8..027ef4310 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -369,29 +369,50 @@ namespace client } // Is lhs==rhs? Store the result into lhs. - static void compare_op(expr &lhs, expr &rhs, char op) + static void compare_op(expr &lhs, expr &rhs, char op, bool invert) { bool value = false; if ((lhs.type == TYPE_INT || lhs.type == TYPE_DOUBLE) && (rhs.type == TYPE_INT || rhs.type == TYPE_DOUBLE)) { // Both types are numeric. - value = (lhs.type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) ? - (lhs.as_d() == rhs.as_d()) : (lhs.i() == rhs.i()); + switch (op) { + case '=': + value = (lhs.type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) ? + (std::abs(lhs.as_d() - rhs.as_d()) < 1e-8) : (lhs.i() == rhs.i()); + break; + case '<': + value = (lhs.type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) ? + (lhs.as_d() < rhs.as_d()) : (lhs.i() < rhs.i()); + break; + case '>': + default: + value = (lhs.type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) ? + (lhs.as_d() > rhs.as_d()) : (lhs.i() > rhs.i()); + break; + } } else if (lhs.type == TYPE_BOOL && rhs.type == TYPE_BOOL) { // Both type are bool. + if (op != '=') + boost::throw_exception(qi::expectation_failure( + lhs.it_range.begin(), rhs.it_range.end(), spirit::info("*Cannot compare the types."))); value = lhs.b() == rhs.b(); } else if (lhs.type == TYPE_STRING || rhs.type == TYPE_STRING) { // One type is string, the other could be converted to string. - value = lhs.to_string() == rhs.to_string(); + value = (op == '=') ? (lhs.to_string() == rhs.to_string()) : + (op == '<') ? (lhs.to_string() < rhs.to_string()) : (lhs.to_string() > rhs.to_string()); } else { boost::throw_exception(qi::expectation_failure( lhs.it_range.begin(), rhs.it_range.end(), spirit::info("*Cannot compare the types."))); } lhs.type = TYPE_BOOL; - lhs.data.b = (op == '=') ? value : !value; + lhs.data.b = invert ? ! value : value; } - static void equal (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '='); } - static void not_equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '!'); } + static void equal (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '=', false); } + static void not_equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '=', true ); } + static void lower (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '<', false); } + static void greater (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '>', false); } + static void leq (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '>', true ); } + static void geq (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '<', true ); } static void regex_op(expr &lhs, boost::iterator_range &rhs, char op) { @@ -421,6 +442,32 @@ namespace client static void regex_matches (expr &lhs, boost::iterator_range &rhs) { return regex_op(lhs, rhs, '='); } static void regex_doesnt_match(expr &lhs, boost::iterator_range &rhs) { return regex_op(lhs, rhs, '!'); } + static void logical_op(expr &lhs, expr &rhs, char op) + { + bool value = false; + if (lhs.type == TYPE_BOOL && rhs.type == TYPE_BOOL) { + value = (op == '|') ? (lhs.b() || rhs.b()) : (lhs.b() && rhs.b()); + } else { + boost::throw_exception(qi::expectation_failure( + lhs.it_range.begin(), rhs.it_range.end(), spirit::info("*Cannot apply logical operation to non-boolean operators."))); + } + lhs.type = TYPE_BOOL; + lhs.data.b = value; + } + static void logical_or (expr &lhs, expr &rhs) { logical_op(lhs, rhs, '|'); } + static void logical_and(expr &lhs, expr &rhs) { logical_op(lhs, rhs, '&'); } + + static void ternary_op(expr &lhs, expr &rhs1, expr &rhs2) + { + bool value = false; + if (lhs.type != TYPE_BOOL) + lhs.throw_exception("Not a boolean expression"); + if (lhs.b()) + lhs = std::move(rhs1); + else + lhs = std::move(rhs2); + } + static void set_if(bool &cond, bool ¬_yet_consumed, std::string &str_in, std::string &str_out) { if (cond && not_yet_consumed) { @@ -789,7 +836,7 @@ namespace client // could serve both purposes. start = eps[px::bind(&MyContext::evaluate_full_macro, _r1, _a)] > ( eps(_a==true) > text_block(_r1) [_val=_1] - | bool_expr(_r1) [ px::bind(&expr::evaluate_boolean_to_string, _1, _val) ] + | conditional_expression(_r1) [ px::bind(&expr::evaluate_boolean_to_string, _1, _val) ] ); start.name("start"); qi::on_error(start, px::bind(&MyContext::process_error_message, _r1, _4, _1, _2, _3)); @@ -852,34 +899,54 @@ namespace client raw[lexeme[(alpha | '_') >> *(alnum | '_')]]; identifier.name("identifier"); - bool_expr = - additive_expression(_r1) [_val = _1] - >> *( ("==" > additive_expression(_r1) ) [px::bind(&expr::equal, _val, _1)] - | ("!=" > additive_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] - | ("<>" > additive_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] - | ("=~" > regular_expression ) [px::bind(&expr::regex_matches, _val, _1)] - | ("!~" > regular_expression ) [px::bind(&expr::regex_doesnt_match, _val, _1)] + conditional_expression = + logical_or_expression(_r1) [_val = _1] + >> -('?' > conditional_expression(_r1) > ':' > conditional_expression(_r1)) [px::bind(&expr::ternary_op, _val, _1, _2)]; + + logical_or_expression = + logical_and_expression(_r1) [_val = _1] + >> *( ((kw["or"] | "||") > logical_and_expression(_r1) ) [px::bind(&expr::logical_or, _val, _1)] ); + + logical_and_expression = + equality_expression(_r1) [_val = _1] + >> *( ((kw["and"] | "&&") > equality_expression(_r1) ) [px::bind(&expr::logical_and, _val, _1)] ); + + equality_expression = + relational_expression(_r1) [_val = _1] + >> *( ("==" > relational_expression(_r1) ) [px::bind(&expr::equal, _val, _1)] + | ("!=" > relational_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] + | ("<>" > relational_expression(_r1) ) [px::bind(&expr::not_equal, _val, _1)] + | ("=~" > regular_expression ) [px::bind(&expr::regex_matches, _val, _1)] + | ("!~" > regular_expression ) [px::bind(&expr::regex_doesnt_match, _val, _1)] ); - bool_expr.name("bool expression"); + equality_expression.name("bool expression"); // Evaluate a boolean expression stored as expr into a boolean value. - // Throw if the bool_expr does not produce a expr of boolean type. - bool_expr_eval = bool_expr(_r1) [ px::bind(&expr::evaluate_boolean, _1, _val) ]; + // Throw if the equality_expression does not produce a expr of boolean type. + bool_expr_eval = conditional_expression(_r1) [ px::bind(&expr::evaluate_boolean, _1, _val) ]; bool_expr_eval.name("bool_expr_eval"); + relational_expression = + additive_expression(_r1) [_val = _1] + >> *( (lit('<') > additive_expression(_r1) ) [px::bind(&expr::lower, _val, _1)] + | (lit('>') > additive_expression(_r1) ) [px::bind(&expr::greater, _val, _1)] + | ("<=" > additive_expression(_r1) ) [px::bind(&expr::leq, _val, _1)] + | (">=" > additive_expression(_r1) ) [px::bind(&expr::geq, _val, _1)] + ); + additive_expression = - term(_r1) [_val = _1] - >> *( (lit('+') > term(_r1) ) [_val += _1] - | (lit('-') > term(_r1) ) [_val -= _1] + multiplicative_expression(_r1) [_val = _1] + >> *( (lit('+') > multiplicative_expression(_r1) ) [_val += _1] + | (lit('-') > multiplicative_expression(_r1) ) [_val -= _1] ); additive_expression.name("additive_expression"); - term = - factor(_r1) [_val = _1] - >> *( (lit('*') > factor(_r1) ) [_val *= _1] - | (lit('/') > factor(_r1) ) [_val /= _1] + multiplicative_expression = + unary_expression(_r1) [_val = _1] + >> *( (lit('*') > unary_expression(_r1) ) [_val *= _1] + | (lit('/') > unary_expression(_r1) ) [_val /= _1] ); - term.name("term"); + multiplicative_expression.name("multiplicative_expression"); struct FactorActions { static void set_start_pos(Iterator &start_pos, expr &out) @@ -899,19 +966,19 @@ namespace client static void not_(expr &value, expr &out) { out = value.unary_not(out.it_range.begin()); } }; - factor = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> ( - scalar_variable_reference(_r1) [ _val = _1 ] - | (lit('(') > additive_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] - | (lit('-') > factor(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ] - | (lit('+') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] - | ((kw["not"] | '!') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ] - | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] - | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] - | (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ] + unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> ( + scalar_variable_reference(_r1) [ _val = _1 ] + | (lit('(') > conditional_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] + | (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ] + | (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] + | ((kw["not"] | '!') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ] + | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] + | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] + | (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ] | raw[lexeme['"' > *((utf8char - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] - [ px::bind(&FactorActions::string_, _1, _val) ] + [ px::bind(&FactorActions::string_, _1, _val) ] ); - factor.name("factor"); + unary_expression.name("unary_expression"); scalar_variable_reference = variable_reference(_r1)[_a=_1] >> @@ -950,17 +1017,24 @@ namespace client debug(switch_output); debug(legacy_variable_expansion); debug(identifier); - debug(bool_expr); + debug(conditional_expression); + debug(logical_or_expression); + debug(logical_and_expression); + debug(equality_expression); debug(bool_expr_eval); + debug(relational_expression); debug(additive_expression); - debug(term); - debug(factor); + debug(multiplicative_expression); + debug(unary_expression); debug(scalar_variable_reference); debug(variable_reference); debug(regular_expression); } } + // Generic expression over expr. + typedef qi::rule(const MyContext*), spirit::ascii::space_type> RuleExpression; + // The start of the grammar. qi::rule, spirit::ascii::space_type> start; // A free-form text. @@ -973,18 +1047,26 @@ namespace client qi::rule legacy_variable_expansion; // Parsed identifier name. qi::rule(), spirit::ascii::space_type> identifier; - // Math expression consisting of +- operators over terms. - qi::rule(const MyContext*), spirit::ascii::space_type> additive_expression; + // Ternary operator (?:) over logical_or_expression. + RuleExpression conditional_expression; + // Logical or over logical_and_expressions. + RuleExpression logical_or_expression; + // Logical and over relational_expressions. + RuleExpression logical_and_expression; + // <, >, <=, >= + RuleExpression relational_expression; + // Math expression consisting of +- operators over multiplicative_expressions. + RuleExpression additive_expression; + // Boolean expressions over expressions. + RuleExpression equality_expression; + // Math expression consisting of */ operators over factors. + RuleExpression multiplicative_expression; + // Number literals, functions, braced expressions, variable references, variable indexing references. + RuleExpression unary_expression; // Rule to capture a regular expression enclosed in //. qi::rule(), spirit::ascii::space_type> regular_expression; - // Boolean expressions over expressions. - qi::rule(const MyContext*), spirit::ascii::space_type> bool_expr; // Evaluate boolean expression into bool. qi::rule bool_expr_eval; - // Math expression consisting of */ operators over factors. - qi::rule(const MyContext*), spirit::ascii::space_type> term; - // Number literals, functions, braced expressions, variable references, variable indexing references. - qi::rule(const MyContext*), spirit::ascii::space_type> factor; // Reference of a scalar variable, or reference to a field of a vector variable. qi::rule(const MyContext*), qi::locals, int>, spirit::ascii::space_type> scalar_variable_reference; // Rule to translate an identifier to a ConfigOption, or to fail. @@ -1033,10 +1115,11 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. // Throws std::runtime_error on syntax or runtime error. -bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config) +bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override) { client::MyContext context; context.config = &config; + context.config_override = config_override; // Let the macro processor parse just a boolean expression, not the full macro language. context.just_boolean_expression = true; return process_macro(templ, context) == "true"; diff --git a/xs/src/libslic3r/PlaceholderParser.hpp b/xs/src/libslic3r/PlaceholderParser.hpp index ec2b837ad..4e0aa9ee2 100644 --- a/xs/src/libslic3r/PlaceholderParser.hpp +++ b/xs/src/libslic3r/PlaceholderParser.hpp @@ -35,7 +35,7 @@ public: // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. // Throws std::runtime_error on syntax or runtime error. - static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config); + static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr); private: DynamicConfig m_config; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index a132af133..adc996030 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -142,12 +142,12 @@ std::string Preset::label() const return this->name + (this->is_dirty ? g_suffix_modified : ""); } -bool Preset::is_compatible_with_printer(const Preset &active_printer) const +bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const { auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); if (condition != nullptr && ! condition->value.empty()) { try { - return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config); + return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config, extra_config); } catch (const std::runtime_error &err) { //FIXME in case of an error, return "compatible with everything". printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); @@ -161,9 +161,18 @@ bool Preset::is_compatible_with_printer(const Preset &active_printer) const compatible_printers->values.end(); } -bool Preset::update_compatible_with_printer(const Preset &active_printer) +bool Preset::is_compatible_with_printer(const Preset &active_printer) const { - return this->is_compatible = is_compatible_with_printer(active_printer); + DynamicPrintConfig config; + config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); + config.set_key_value("num_extruders", new ConfigOptionInt( + (int)static_cast(active_printer.config.option("nozzle_diameter"))->values.size())); + return this->is_compatible_with_printer(active_printer, &config); +} + +bool Preset::update_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) +{ + return this->is_compatible = is_compatible_with_printer(active_printer, extra_config); } const std::vector& Preset::print_options() @@ -408,11 +417,15 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) void PresetCollection::update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible) { + DynamicPrintConfig config; + config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); + config.set_key_value("num_extruders", new ConfigOptionInt( + (int)static_cast(active_printer.config.option("nozzle_diameter"))->values.size())); for (size_t idx_preset = 1; idx_preset < m_presets.size(); ++ idx_preset) { bool selected = idx_preset == m_idx_selected; Preset &preset_selected = m_presets[idx_preset]; Preset &preset_edited = selected ? m_edited_preset : preset_selected; - if (! preset_edited.update_compatible_with_printer(active_printer) && + if (! preset_edited.update_compatible_with_printer(active_printer, &config) && selected && select_other_if_incompatible) m_idx_selected = (size_t)-1; if (selected) diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 36bc0b335..bfb7d6e20 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -79,9 +79,11 @@ public: void set_dirty(bool dirty = true) { this->is_dirty = dirty; } void reset_dirty() { this->is_dirty = false; } + bool is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const; bool is_compatible_with_printer(const Preset &active_printer) const; + // Mark this preset as compatible if it is compatible with active_printer. - bool update_compatible_with_printer(const Preset &active_printer); + bool update_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config); // Resize the extruder specific fields, initialize them with the content of the 1st extruder. void set_num_extruders(unsigned int n) { set_num_extruders(this->config, n); } From 5a768ddd7b4d72088878266b363454248ea0b32a Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 17:10:28 +0100 Subject: [PATCH 57/69] Updated the bundled config profile with the new compatible_printers_condition. --- ...l Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini | 210 +++++++++++------- 1 file changed, 131 insertions(+), 79 deletions(-) diff --git a/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini b/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini index ae21f862d..cb076ac35 100644 --- a/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini +++ b/resources/profiles/Original Prusa i3 MK3, MK2S, MK2 and MK2S-MMU.ini @@ -1,4 +1,4 @@ -# generated by Slic3r Prusa Edition 1.38.4 on 2017-12-10 at 09:05:01 +# generated by Slic3r Prusa Edition 1.38.4 on 2017-12-19 at 17:08:04 [print:0.05mm DETAIL] avoid_crossing_perimeters = 0 @@ -9,7 +9,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders==1 complete_objects = 0 default_acceleration = 500 dont_support_bridges = 1 @@ -114,7 +115,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders==1 complete_objects = 0 default_acceleration = 500 dont_support_bridges = 1 @@ -219,7 +221,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ complete_objects = 0 default_acceleration = 500 dont_support_bridges = 1 @@ -324,7 +327,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders==1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -429,7 +433,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -534,7 +539,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 30 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -639,7 +645,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -744,7 +751,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -849,7 +857,8 @@ bridge_flow_ratio = 0.7 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.25 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.25 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.25 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -954,7 +963,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1059,7 +1069,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 30 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1164,7 +1175,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1269,7 +1281,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1374,7 +1387,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1479,7 +1493,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1584,7 +1599,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1689,7 +1705,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 30 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1794,7 +1811,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -1899,7 +1917,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2004,7 +2023,8 @@ bridge_flow_ratio = 0.95 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MultiMaterial" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2109,7 +2129,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2214,7 +2235,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 30 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2319,7 +2341,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2424,7 +2447,8 @@ bridge_flow_ratio = 0.8 bridge_speed = 20 brim_width = 0 clip_multipart_objects = 1 -compatible_printers = "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle" +compatible_printers = +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1 complete_objects = 0 default_acceleration = 1000 dont_support_bridges = 1 @@ -2523,7 +2547,8 @@ xy_size_compensation = 0 [filament:ColorFabb Brass Bronze 1.75mm] bed_temperature = 60 bridge_fan_speed = 100 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = nozzle_diameter[0]>0.35 cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2545,13 +2570,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 210 [filament:ColorFabb HT 1.75mm] bed_temperature = 105 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2573,13 +2599,14 @@ max_fan_speed = 20 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 270 [filament:ColorFabb PLA-PHA] bed_temperature = 60 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2601,13 +2628,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 210 [filament:ColorFabb Woodfil 1.75mm] bed_temperature = 60 bridge_fan_speed = 100 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = nozzle_diameter[0]>0.35 cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2629,13 +2657,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 200 [filament:ColorFabb XT 1.75mm] bed_temperature = 65 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2657,13 +2686,14 @@ max_fan_speed = 50 min_fan_speed = 30 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 240 [filament:ColorFabb XT-CF20 1.75mm] bed_temperature = 90 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2685,13 +2715,14 @@ max_fan_speed = 50 min_fan_speed = 30 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 260 [filament:ColorFabb nGen 1.75mm] bed_temperature = 85 bridge_fan_speed = 40 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2713,13 +2744,14 @@ max_fan_speed = 35 min_fan_speed = 20 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 240 [filament:ColorFabb nGen flex] bed_temperature = 85 bridge_fan_speed = 40 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2741,13 +2773,14 @@ max_fan_speed = 35 min_fan_speed = 20 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 260 [filament:E3D Edge] bed_temperature = 90 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2769,13 +2802,14 @@ max_fan_speed = 50 min_fan_speed = 30 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 240 [filament:E3D PC-ABS 1.75mm] bed_temperature = 100 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2797,13 +2831,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 270 [filament:Fillamentum ABS 1.75mm] bed_temperature = 100 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2825,13 +2860,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 240 [filament:Fillamentum ASA 1.75mm] bed_temperature = 100 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2853,13 +2889,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 265 [filament:Fillamentum CPE HG100 HM100] bed_temperature = 90 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2881,13 +2918,14 @@ max_fan_speed = 80 min_fan_speed = 80 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 260 [filament:Fillamentum Timberfil] bed_temperature = 60 bridge_fan_speed = 100 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK2 MultiMaterial";"Original Prusa i3 MK2 MultiMaterial 0.6 nozzle";"Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = nozzle_diameter[0]>0.35 cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2909,13 +2947,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 190 [filament:Generic ABS 1.75mm] bed_temperature = 100 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2937,13 +2976,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 255 [filament:Generic PET 1.75mm] bed_temperature = 90 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -2965,13 +3005,14 @@ max_fan_speed = 50 min_fan_speed = 30 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 240 [filament:Generic PLA 1.75mm] bed_temperature = 60 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -2993,13 +3034,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 210 [filament:Polymaker PC-Max] bed_temperature = 120 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3021,13 +3063,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 270 [filament:Primavalue PVA] bed_temperature = 60 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -3049,13 +3092,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 195 [filament:Prusa ABS 1.75mm] bed_temperature = 100 bridge_fan_speed = 30 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3077,13 +3121,14 @@ max_fan_speed = 30 min_fan_speed = 10 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 255 [filament:Prusa HIPS 1.75mm] bed_temperature = 100 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3105,13 +3150,14 @@ max_fan_speed = 20 min_fan_speed = 20 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 [filament:Prusa PET 1.75mm] bed_temperature = 90 bridge_fan_speed = 50 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3133,13 +3179,14 @@ max_fan_speed = 50 min_fan_speed = 30 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 240 [filament:Prusa PLA 1.75mm] bed_temperature = 60 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -3161,13 +3208,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 210 [filament:SemiFlex or Flexfill 98A] bed_temperature = 50 bridge_fan_speed = 100 -compatible_printers = "Original Prusa i3 MK2";"Original Prusa i3 MK2 0.6 nozzle";"Original Prusa i3 MK2 MM Single Mode";"Original Prusa i3 MK2 MM Single Mode 0.6 nozzle";"Original Prusa i3 MK3" +compatible_printers = +compatible_printers_condition = nozzle_diameter[0]>0.35 and num_extruders==1 cooling = 0 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -3189,13 +3237,14 @@ max_fan_speed = 90 min_fan_speed = 70 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 230 [filament:Taulman Bridge 1.75mm] bed_temperature = 50 bridge_fan_speed = 40 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3217,13 +3266,14 @@ max_fan_speed = 5 min_fan_speed = 0 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 250 [filament:Taulman T-Glase 1.75mm] bed_temperature = 90 bridge_fan_speed = 40 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode" @@ -3245,13 +3295,14 @@ max_fan_speed = 5 min_fan_speed = 0 min_print_speed = 5 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 240 [filament:Verbatim BVOH] bed_temperature = 60 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 0 disable_fan_first_layers = 1 end_filament_gcode = "; Filament-specific end gcode" @@ -3273,13 +3324,14 @@ max_fan_speed = 100 min_fan_speed = 85 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 210 [filament:Verbatim PP] bed_temperature = 100 bridge_fan_speed = 100 compatible_printers = +compatible_printers_condition = cooling = 1 disable_fan_first_layers = 2 end_filament_gcode = "; Filament-specific end gcode" @@ -3301,7 +3353,7 @@ max_fan_speed = 100 min_fan_speed = 100 min_print_speed = 15 slowdown_below_layer_time = 10 -start_filament_gcode = "M900 K{if printer_preset==\"Original Prusa i3 MK2 MultiMaterial\"}200{elsif printer_preset==\"Original Prusa i3 MK2 MM Single Mode\"}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 [printer:Original Prusa i3 MK2] @@ -3319,15 +3371,15 @@ min_layer_height = 0.07 nozzle_diameter = 0.4 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\n printer_settings_id = retract_before_travel = 1 retract_before_wipe = 0% retract_layer_change = 1 retract_length = 0.8 retract_length_toolchange = 3 -retract_lift = 0.5 -retract_lift_above = 1 +retract_lift = 0.6 +retract_lift_above = 0 retract_lift_below = 199 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 @@ -3359,15 +3411,15 @@ min_layer_height = 0.05 nozzle_diameter = 0.25 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\n printer_settings_id = retract_before_travel = 1 retract_before_wipe = 0% retract_layer_change = 1 retract_length = 1 retract_length_toolchange = 3 -retract_lift = 0.5 -retract_lift_above = 1 +retract_lift = 0.6 +retract_lift_above = 0 retract_lift_below = 199 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 @@ -3399,15 +3451,15 @@ min_layer_height = 0.1 nozzle_diameter = 0.6 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\n printer_settings_id = retract_before_travel = 1 retract_before_wipe = 0% retract_layer_change = 1 retract_length = 0.8 retract_length_toolchange = 3 -retract_lift = 0.5 -retract_lift_above = 1 +retract_lift = 0.6 +retract_lift_above = 0 retract_lift_below = 199 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 @@ -3439,14 +3491,14 @@ min_layer_height = 0.07 nozzle_diameter = 0.4 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_settings_id = retract_before_travel = 3 retract_before_wipe = 0% retract_layer_change = 0 retract_length = 4 retract_length_toolchange = 6 -retract_lift = 0.5 +retract_lift = 0.6 retract_lift_above = 0 retract_lift_below = 199 retract_restart_extra = 0 @@ -3479,14 +3531,14 @@ min_layer_height = 0.07 nozzle_diameter = 0.6 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_settings_id = retract_before_travel = 3 retract_before_wipe = 0% retract_layer_change = 0 retract_length = 4 retract_length_toolchange = 6 -retract_lift = 0.5 +retract_lift = 0.6 retract_lift_above = 0 retract_lift_below = 199 retract_restart_extra = 0 @@ -3519,14 +3571,14 @@ min_layer_height = 0.07,0.07,0.07,0.07 nozzle_diameter = 0.4,0.4,0.4,0.4 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_settings_id = retract_before_travel = 3,3,3,3 retract_before_wipe = 60%,60%,60%,60% retract_layer_change = 0,0,0,0 retract_length = 4,4,4,4 retract_length_toolchange = 4,4,4,4 -retract_lift = 0.5,0.5,0.5,0.5 +retract_lift = 0.6,0.6,0.6,0.6 retract_lift_above = 0,0,0,0 retract_lift_below = 199,199,199,199 retract_restart_extra = 0,0,0,0 @@ -3559,14 +3611,14 @@ min_layer_height = 0.07,0.07,0.07,0.07 nozzle_diameter = 0.6,0.6,0.6,0.6 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_settings_id = retract_before_travel = 3,3,3,3 retract_before_wipe = 60%,60%,60%,60% retract_layer_change = 0,0,0,0 retract_length = 4,4,4,4 retract_length_toolchange = 4,4,4,4 -retract_lift = 0.5,0.5,0.5,0.5 +retract_lift = 0.6,0.6,0.6,0.6 retract_lift_above = 0,0,0,0 retract_lift_below = 199,199,199,199 retract_restart_extra = 0,0,0,0 @@ -3599,22 +3651,22 @@ min_layer_height = 0.07 nozzle_diameter = 0.4 octoprint_apikey = octoprint_host = -printer_notes = +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_before_travel = 1 retract_before_wipe = 0% retract_layer_change = 1 retract_length = 0.8 retract_length_toolchange = 3 -retract_lift = 0.5 -retract_lift_above = 1 -retract_lift_below = 199 +retract_lift = 0.6 +retract_lift_above = 0 +retract_lift_below = 209 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 retract_speed = 35 serial_port = serial_speed = 250000 single_extruder_multi_material = 0 -start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside pritn area\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line +start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 toolchange_gcode = use_firmware_retraction = 0 use_relative_e_distances = 1 From 0b6bd3cbdedaf52e95716d34294630ff22d4356c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 19:51:22 +0100 Subject: [PATCH 58/69] Implemented a "Reset user profile" on the first page of the configuration wizard if the wizard is opened from the menu. This allows one to reinstall the bundled printer profile cleanly. Fixed a bug when loading a config bundle as a config: The config bundle should not be unpacked into the user profile directory. --- lib/Slic3r/GUI.pm | 3 ++- lib/Slic3r/GUI/ConfigWizard.pm | 30 +++++++++++++++++++++--------- lib/Slic3r/GUI/MainFrame.pm | 20 ++++++++++++-------- xs/src/slic3r/GUI/Preset.cpp | 23 ++++++++++++++++++++--- xs/src/slic3r/GUI/Preset.hpp | 2 ++ xs/src/slic3r/GUI/PresetBundle.cpp | 22 +++++++++++++++++++--- xs/src/slic3r/GUI/PresetBundle.hpp | 13 ++++++++++++- xs/xsp/GUI_Preset.xsp | 4 +++- 8 files changed, 91 insertions(+), 26 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 6e5279727..5d6d8e4a6 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -128,7 +128,8 @@ sub OnInit { # On OSX the UI was not initialized correctly if the wizard was called # before the UI was up and running. $self->CallAfter(sub { - $self->{mainframe}->config_wizard; + # Run the config wizard, don't offer the "reset user profile" checkbox. + $self->{mainframe}->config_wizard(1); }); } diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm index be6fb2575..a32d345ed 100644 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ b/lib/Slic3r/GUI/ConfigWizard.pm @@ -14,13 +14,13 @@ our $wizard = 'Wizard'; $wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK; sub new { - my ($class, $parent, $presets) = @_; + my ($class, $parent, $presets, $fresh_start) = @_; my $self = $class->SUPER::new($parent, -1, "Configuration $wizard"); # initialize an empty repository $self->{config} = Slic3r::Config->new; - my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self); + my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self, $fresh_start); $self->add_page($welcome_page); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); @@ -50,9 +50,13 @@ sub add_page { sub run { my ($self) = @_; - my $result = undef; + my $result; if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) { my $preset_name = $self->{pages}[0]->{preset_name}; + $result = { + preset_name => $preset_name, + reset_user_profile => $self->{pages}[0]->{reset_user_profile} + }; if ($preset_name eq 'Other') { # it would be cleaner to have these defined inside each page class, # in some event getting called before leaving the page @@ -67,9 +71,7 @@ sub run { # set first_layer_bed_temperature to temperature + 5 $self->{config}->set('first_layer_bed_temperature', [ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]); - $result = $self->{config}; - } else { - $result = $preset_name; + $result->{config} = $self->{config}; } } $self->Destroy; @@ -266,13 +268,13 @@ sub config { package Slic3r::GUI::ConfigWizard::Page::Welcome; use base 'Slic3r::GUI::ConfigWizard::Page'; use Wx qw(:misc :sizer wxID_FORWARD); -use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE); +use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE EVT_CHECKBOX); sub new { - my $class = shift; - my ($parent) = @_; + my ($class, $parent, $fresh_start) = @_; my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); $self->{full_wizard_workflow} = 1; + $self->{reset_user_profile} = 0; # Test for the existence of the old config path. my $message_has_legacy; @@ -300,6 +302,10 @@ sub new { $self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); $self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); + if (! $fresh_start) { + $self->{reset_checkbox} = Wx::CheckBox->new($self, -1, "Reset user profile, install from scratch"); + $self->{vsizer}->Add($self->{reset_checkbox}, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); + } EVT_CHOICE($parent, $choice, sub { my $sel = $self->{choice}->GetStringSelection; @@ -307,6 +313,12 @@ sub new { $self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq '')); }); + if (! $fresh_start) { + EVT_CHECKBOX($self, $self->{reset_checkbox}, sub { + $self->{reset_user_profile} = $self->{reset_checkbox}->GetValue(); + }); + } + EVT_ACTIVATE($parent, sub { $self->set_full_wizard_workflow($self->{preset_name} eq 'Other'); }); diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index eae598a09..952b24aa2 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -299,7 +299,8 @@ sub _init_menubar { my $helpMenu = Wx::Menu->new; { $self->_append_menu_item($helpMenu, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…", "Run Configuration $Slic3r::GUI::ConfigWizard::wizard", sub { - $self->config_wizard; + # Run the config wizard, offer the "reset user profile" checkbox. + $self->config_wizard(0); }); $helpMenu->AppendSeparator(); $self->_append_menu_item($helpMenu, "Prusa 3D Drivers", 'Open the Prusa3D drivers download page in your browser', sub { @@ -580,7 +581,7 @@ sub export_configbundle { # to auto-install a config bundle on a fresh user account, # but that behavior was not documented and likely buggy. sub load_configbundle { - my ($self, $file) = @_; + my ($self, $file, $reset_user_profile) = @_; return unless $self->check_unsaved_changes; if (!$file) { my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', @@ -595,7 +596,7 @@ sub load_configbundle { wxTheApp->{app_config}->update_config_dir(dirname($file)); my $presets_imported = 0; - eval { $presets_imported = wxTheApp->{preset_bundle}->load_configbundle($file); }; + eval { $presets_imported = wxTheApp->{preset_bundle}->load_configbundle($file, $reset_user_profile ? 1 : 0); }; Slic3r::GUI::catch_error($self) and return; # Load the currently selected preset into the GUI, update the preset selection box. @@ -616,7 +617,7 @@ sub load_config { } sub config_wizard { - my ($self) = @_; + my ($self, $fresh_start) = @_; # Exit wizard if there are unsaved changes and the user cancels the action. return unless $self->check_unsaved_changes; # Enumerate the profiles bundled with the Slic3r installation under resources/profiles. @@ -632,22 +633,25 @@ sub config_wizard { closedir(DIR); } # Open the wizard. - if (my $config = Slic3r::GUI::ConfigWizard->new($self, \@profiles)->run) { - if (ref($config)) { + if (my $result = Slic3r::GUI::ConfigWizard->new($self, \@profiles, $fresh_start)->run) { + if ($result->{reset_user_profile}) { + eval { wxTheApp->{preset_bundle}->reset(1) }; + } + if (defined $result->{config}) { # Wizard returned a config. Add the config to each of the preset types. for my $tab (values %{$self->{options_tabs}}) { # Select the first visible preset, force. $tab->select_preset(undef, 1); } # Load the config over the previously selected defaults. - $self->load_config($config); + $self->load_config($result->{config}); for my $tab (values %{$self->{options_tabs}}) { # Save the settings under a new name, select the name. $tab->save_preset('My Settings'); } } else { # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. - eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $config . '.ini'); }; + eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini'); }; Slic3r::GUI::catch_error($self) and return; # Load the currently selected preset into the GUI, update the preset selection box. foreach my $tab (values %{$self->{options_tabs}}) { diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index adc996030..49c999737 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -263,6 +263,21 @@ PresetCollection::~PresetCollection() m_bitmap_main_frame = nullptr; } +void PresetCollection::reset(bool delete_files) +{ + if (m_presets.size() > 1) { + if (delete_files) { + // Erase the preset files. + for (Preset &preset : m_presets) + if (! preset.is_default && ! preset.is_external) + boost::nowide::remove(preset.file.c_str()); + } + // Don't use m_presets.resize() here as it requires a default constructor for Preset. + m_presets.erase(m_presets.begin() + 1, m_presets.end()); + this->select_preset(0); + } +} + // Load all presets found in dir_path. // Throws an exception on error. void PresetCollection::load_presets(const std::string &dir_path, const std::string &subdir) @@ -501,9 +516,11 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) std::string preset_name = Preset::remove_suffix_modified(old_label); const Preset *preset = this->find_preset(preset_name, false); assert(preset != nullptr); - std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name; - if (old_label != new_label) - ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str())); + if (preset != nullptr) { + std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name; + if (old_label != new_label) + ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str())); + } } return was_dirty != is_dirty; } diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index bfb7d6e20..b37982017 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -116,6 +116,8 @@ public: PresetCollection(Preset::Type type, const std::vector &keys); ~PresetCollection(); + void reset(bool delete_files); + Preset::Type type() const { return m_type; } std::string name() const; const std::deque& operator()() const { return m_presets; } diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 4dc2e56ce..645477541 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -69,6 +69,16 @@ PresetBundle::~PresetBundle() delete bitmap.second; } +void PresetBundle::reset(bool delete_files) +{ + // Clear the existing presets, delete their respective files. + this->prints .reset(delete_files); + this->filaments.reset(delete_files); + this->printers .reset(delete_files); + this->filament_presets.clear(); + this->filament_presets.emplace_back(this->filaments.get_selected_preset().name); +} + void PresetBundle::setup_directories() { boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir()); @@ -376,7 +386,8 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const { // 1) Load the config bundle into a temp data. PresetBundle tmp_bundle; - tmp_bundle.load_configbundle(path); + // Load the config bundle, don't save the loaded presets to user profile directory. + tmp_bundle.load_configbundle(path, 0); std::string bundle_name = std::string(" - ") + boost::filesystem::path(path).filename().string(); // 2) Extract active configs from the config bundle, copy them and activate them in this bundle. @@ -430,8 +441,11 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const // Load a config bundle file, into presets and store the loaded presets into separate files // of the local configuration directory. -size_t PresetBundle::load_configbundle(const std::string &path) +size_t PresetBundle::load_configbundle(const std::string &path, unsigned int flags) { + if (flags & LOAD_CFGBNDLE_RESET_USER_PROFILE) + this->reset(flags & LOAD_CFGBNDLE_SAVE); + // 1) Read the complete config file into a boost::property_tree. namespace pt = boost::property_tree; pt::ptree tree; @@ -504,7 +518,9 @@ size_t PresetBundle::load_configbundle(const std::string &path) #endif / presets->name() / file_name).make_preferred(); // Load the preset into the list of presets, save it to disk. - presets->load_preset(file_path.string(), preset_name, std::move(config), false).save(); + Preset &loaded = presets->load_preset(file_path.string(), preset_name, std::move(config), false); + if (flags & LOAD_CFGBNDLE_SAVE) + loaded.save(); ++ presets_loaded; } } diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 238e7c802..308785fda 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -15,6 +15,10 @@ public: PresetBundle(); ~PresetBundle(); + // Remove all the presets but the "-- default --". + // Optionally remove all the files referenced by the presets from the user profile directory. + void reset(bool delete_files); + void setup_directories(); // Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets. @@ -51,7 +55,14 @@ public: // Load settings into the provided settings instance. // Activate the presets stored in the config bundle. // Returns the number of presets loaded successfully. - size_t load_configbundle(const std::string &path); + enum { + // Save the profiles, which have been loaded. + LOAD_CFGBNDLE_SAVE = 1, + // Delete all old config profiles before loading. + LOAD_CFGBNDLE_RESET_USER_PROFILE = 2 + }; + // Load the config bundle, store it to the user profile directory by default. + size_t load_configbundle(const std::string &path, unsigned int flags = LOAD_CFGBNDLE_SAVE); // Export a config bundle file containing all the presets and the names of the active presets. void export_configbundle(const std::string &path); // , const DynamicPrintConfig &settings); diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 905ff4ecd..ed5db01e9 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -100,6 +100,8 @@ PresetCollection::arrayref() PresetBundle(); ~PresetBundle(); + void reset(bool delete_files); + void setup_directories() %code%{ try { @@ -128,7 +130,7 @@ PresetCollection::arrayref() size_t load_configbundle(const char *path) %code%{ try { - RETVAL = THIS->load_configbundle(path); + RETVAL = THIS->load_configbundle(path, PresetBundle::LOAD_CFGBNDLE_SAVE); } catch (std::exception& e) { croak("Loading of a config bundle %s failed:\n%s\n", path, e.what()); } From c3468f2ad90244288ca93083ba644a466f5143cb Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 20:58:16 +0100 Subject: [PATCH 59/69] Fix of preset selection. --- lib/Slic3r/GUI/MainFrame.pm | 6 ++++-- lib/Slic3r/GUI/Tab.pm | 19 ++++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 952b24aa2..bf58ebcaf 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -610,6 +610,8 @@ sub load_configbundle { # Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. # Also update the platter with the new presets. +# This method is used to update the configuration from mainpulations in the 3D scene (for example moving the wipe tower), +# and to load the configuration from the config wizard. sub load_config { my ($self, $config) = @_; $_->load_config($config) foreach values %{$self->{options_tabs}}; @@ -639,8 +641,8 @@ sub config_wizard { } if (defined $result->{config}) { # Wizard returned a config. Add the config to each of the preset types. - for my $tab (values %{$self->{options_tabs}}) { - # Select the first visible preset, force. + # Select and load the "-- default --" preset. + foreach my $tab (values %{$self->{options_tabs}}) { $tab->select_preset(undef, 1); } # Load the config over the previously selected defaults. diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index f7ea01a6f..e01c0a107 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -272,6 +272,8 @@ sub select_preset { my ($self, $name, $force) = @_; $force //= 0; my $presets = $self->{presets}; + # If no name is provided, select the "-- default --" preset. + $name //= $presets->default_preset->name; my $current_dirty = $presets->current_is_dirty; my $canceled = 0; my $printer_tab = $presets->name eq 'printer'; @@ -283,19 +285,18 @@ sub select_preset { # are compatible with the new printer. # If they are not compatible and the the current print or filament are dirty, let user decide # whether to discard the changes or keep the current printer selection. - my $new_printer_name = $name // ''; - my $new_printer_preset = $presets->find_preset($new_printer_name, 1); + my $new_printer_preset = $presets->find_preset($name, 1); my $print_presets = wxTheApp->{preset_bundle}->print; my $print_preset_dirty = $print_presets->current_is_dirty; my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); - $canceled = $print_preset_dirty && ! $print_preset_compatible && - ! $self->may_discard_current_dirty_preset($print_presets, $new_printer_name); + $canceled = ! $force && $print_preset_dirty && ! $print_preset_compatible && + ! $self->may_discard_current_dirty_preset($print_presets, $name); my $filament_presets = wxTheApp->{preset_bundle}->filament; my $filament_preset_dirty = $filament_presets->current_is_dirty; my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); - if (! $canceled) { + if (! $canceled && ! $force) { $canceled = $filament_preset_dirty && ! $filament_preset_compatible && - ! $self->may_discard_current_dirty_preset($filament_presets, $new_printer_name); + ! $self->may_discard_current_dirty_preset($filament_presets, $name); } if (! $canceled) { if (! $print_preset_compatible) { @@ -317,11 +318,7 @@ sub select_preset { $self->_on_presets_changed; } else { $presets->discard_current_changes if $current_dirty; - if (defined $name) { - $presets->select_preset_by_name($name); - } else { - $presets->select_preset(0); - } + $presets->select_preset_by_name($name); # Mark the print & filament enabled if they are compatible with the currently selected preset. # The following method should not discard changes of current print or filament presets on change of a printer profile, # if they are compatible with the current printer. From 67c6823ddee5fa097fc1c294a3e94447d8a95a3f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 21:12:24 +0100 Subject: [PATCH 60/69] Fixed a regression bug in the display of a filament name on the print controller tab. --- lib/Slic3r/GUI/Plater.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index f22e6237d..91905b2b6 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1443,8 +1443,8 @@ sub do_print { my $printer_panel = $controller->add_printer($printer_preset->name, $printer_preset->config); my $filament_stats = $self->{print}->filament_stats; - my @filament_names = wxTheApp->{preset_bundle}->filament_presets; - $filament_stats = { map { $filament_names[$_] => $filament_stats->{$_} } keys %$filament_stats }; + my $filament_names = wxTheApp->{preset_bundle}->filament_presets; + $filament_stats = { map { $filament_names->[$_] => $filament_stats->{$_} } keys %$filament_stats }; $printer_panel->load_print_job($self->{print_file}, $filament_stats); $self->GetFrame->select_tab(1); From c49d6a3ec781e6100ddeace0388502ba840665c7 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 19 Dec 2017 21:43:24 +0100 Subject: [PATCH 61/69] Try to fix the config wizard initialization on OSX. There is an issue when the config wizard is started from the help menu and the "other" workflow is followed without clearing the user profile directory. --- lib/Slic3r/GUI/MainFrame.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index bf58ebcaf..f18a1881e 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -641,9 +641,11 @@ sub config_wizard { } if (defined $result->{config}) { # Wizard returned a config. Add the config to each of the preset types. - # Select and load the "-- default --" preset. - foreach my $tab (values %{$self->{options_tabs}}) { - $tab->select_preset(undef, 1); + # Select and load the "-- default --" preset, start with the printer tab as it may revert + # the print and filament profile to the first visible one, which may have some + # printer compatibility configuration set, which we don't want to inherit. + foreach my $tab (qw(printer print filament)) { + $self->{options_tabs}->$tab->select_preset(undef, 1); } # Load the config over the previously selected defaults. $self->load_config($result->{config}); From 558a0753c1a541a68e2cac7e61ed58e641bce8f8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 11:28:16 +0100 Subject: [PATCH 62/69] Improved loading of the config wizard results. Fixed some updates of the "compatible with printer" flags at the print and filament presets. --- lib/Slic3r/GUI/MainFrame.pm | 39 ++++++++++---------------- xs/src/slic3r/GUI/Preset.cpp | 12 +++++--- xs/src/slic3r/GUI/Preset.hpp | 3 ++ xs/src/slic3r/GUI/PresetBundle.cpp | 45 +++++++++++++++++++++++------- xs/src/slic3r/GUI/PresetBundle.hpp | 10 ++++++- xs/xsp/GUI_Preset.xsp | 8 ++++++ 6 files changed, 77 insertions(+), 40 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index f18a1881e..6b07d761d 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -610,8 +610,6 @@ sub load_configbundle { # Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. # Also update the platter with the new presets. -# This method is used to update the configuration from mainpulations in the 3D scene (for example moving the wipe tower), -# and to load the configuration from the config wizard. sub load_config { my ($self, $config) = @_; $_->load_config($config) foreach values %{$self->{options_tabs}}; @@ -636,31 +634,22 @@ sub config_wizard { } # Open the wizard. if (my $result = Slic3r::GUI::ConfigWizard->new($self, \@profiles, $fresh_start)->run) { - if ($result->{reset_user_profile}) { - eval { wxTheApp->{preset_bundle}->reset(1) }; - } - if (defined $result->{config}) { - # Wizard returned a config. Add the config to each of the preset types. - # Select and load the "-- default --" preset, start with the printer tab as it may revert - # the print and filament profile to the first visible one, which may have some - # printer compatibility configuration set, which we don't want to inherit. - foreach my $tab (qw(printer print filament)) { - $self->{options_tabs}->$tab->select_preset(undef, 1); + eval { + if ($result->{reset_user_profile}) { + wxTheApp->{preset_bundle}->reset(1); } - # Load the config over the previously selected defaults. - $self->load_config($result->{config}); - for my $tab (values %{$self->{options_tabs}}) { - # Save the settings under a new name, select the name. - $tab->save_preset('My Settings'); - } - } else { - # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. - eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini'); }; - Slic3r::GUI::catch_error($self) and return; - # Load the currently selected preset into the GUI, update the preset selection box. - foreach my $tab (values %{$self->{options_tabs}}) { - $tab->load_current_preset; + if (defined $result->{config}) { + # Load and save the settings into print, filament and printer presets. + wxTheApp->{preset_bundle}->load_config('My Settings', $result->{config}); + } else { + # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. + wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini'); } + }; + Slic3r::GUI::catch_error($self) and return; + # Load the currently selected preset into the GUI, update the preset selection box. + foreach my $tab (values %{$self->{options_tabs}}) { + $tab->load_current_preset; } } } diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 49c999737..6af5982a3 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -350,11 +350,8 @@ void PresetCollection::save_current_preset(const std::string &new_name) } else { // Creating a new preset. Preset &preset = *m_presets.insert(it, m_edited_preset); - std::string file_name = new_name; - if (! boost::iends_with(file_name, ".ini")) - file_name += ".ini"; preset.name = new_name; - preset.file = (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); + preset.file = this->path_from_name(new_name); } // 2) Activate the saved preset. this->select_preset_by_name(new_name, true); @@ -591,4 +588,11 @@ std::string PresetCollection::name() const } } +// Generate a file path from a profile name. Add the ".ini" suffix if it is missing. +std::string PresetCollection::path_from_name(const std::string &new_name) const +{ + std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini"); + return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); +} + } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index b37982017..1f6a90595 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -211,6 +211,9 @@ public: // With force, the changes are reverted if the new index is the same as the old index. bool select_preset_by_name(const std::string &name, bool force); + // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. + std::string path_from_name(const std::string &new_name) const; + private: PresetCollection(); PresetCollection(const PresetCollection &other); diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 645477541..decc5d00b 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -133,6 +133,7 @@ void PresetBundle::load_presets() errors_cummulative += err.what(); } this->update_multi_material_filament_presets(); + this->update_compatible_with_printer(false); if (! errors_cummulative.empty()) throw std::runtime_error(errors_cummulative); } @@ -163,8 +164,10 @@ void PresetBundle::load_selections(const AppConfig &config) this->set_filament_preset(i, remove_ini_suffix(config.get("presets", name))); } // Update visibility of presets based on their compatibility with the active printer. - // This will switch the print or filament presets to compatible if the active presets are incompatible. - this->update_compatible_with_printer(false); + // Always try to select a compatible print and filament preset to the current printer preset, + // as the application may have been closed with an active "external" preset, which does not + // exist. + this->update_compatible_with_printer(true); } // Export selections (current print, current filaments, current printer) into config.ini @@ -279,7 +282,7 @@ void PresetBundle::load_config_file(const std::string &path) config.apply(FullPrintConfig::defaults()); config.load_from_gcode(path); Preset::normalize(config); - load_config_file_config(path, std::move(config)); + load_config_file_config(path, true, std::move(config)); return; } @@ -308,7 +311,7 @@ void PresetBundle::load_config_file(const std::string &path) config.apply(FullPrintConfig::defaults()); config.load(tree); Preset::normalize(config); - load_config_file_config(path, std::move(config)); + load_config_file_config(path, true, std::move(config)); break; } case CONFIG_FILE_TYPE_CONFIG_BUNDLE: @@ -318,7 +321,7 @@ void PresetBundle::load_config_file(const std::string &path) } // Load a config file from a boost property_tree. This is a private method called from load_config_file. -void PresetBundle::load_config_file_config(const std::string &path, DynamicPrintConfig &&config) +void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config) { // The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway, // but some of the alpha versions of Slic3r did. @@ -333,13 +336,17 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint // 1) Create a name from the file name. // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles. - std::string name = boost::filesystem::path(path).filename().string(); + std::string name = is_external ? boost::filesystem::path(name_or_path).filename().string() : name_or_path; // 2) If the loading succeeded, split and load the config into print / filament / printer settings. // First load the print and printer presets. for (size_t i_group = 0; i_group < 2; ++ i_group) { PresetCollection &presets = (i_group == 0) ? this->prints : this->printers; - presets.load_preset(path, name, config).is_external = true; + Preset &preset = presets.load_preset(is_external ? name_or_path : presets.path_from_name(name), name, config); + if (is_external) + preset.is_external = true; + else + preset.save(); } // 3) Now load the filaments. If there are multiple filament presets, split them and load them. @@ -347,7 +354,12 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint auto *filament_diameter = dynamic_cast(config.option("filament_diameter")); size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size()); if (num_extruders <= 1) { - this->filaments.load_preset(path, name, config).is_external = true; + Preset &preset = this->filaments.load_preset( + is_external ? name_or_path : this->filaments.path_from_name(name), name, config); + if (is_external) + preset.is_external = true; + else + preset.save(); this->filament_presets.clear(); this->filament_presets.emplace_back(name); } else { @@ -374,11 +386,20 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint suffix[0] = 0; else sprintf(suffix, " (%d)", i); + std::string new_name = name + suffix; // Load all filament presets, but only select the first one in the preset dialog. - this->filaments.load_preset(path, name + suffix, std::move(configs[i]), i == 0).is_external = true; - this->filament_presets.emplace_back(name + suffix); + Preset &preset = this->filaments.load_preset( + is_external ? name_or_path : this->filaments.path_from_name(new_name), + new_name, std::move(configs[i]), i == 0); + if (is_external) + preset.is_external = true; + else + preset.save(); + this->filament_presets.emplace_back(new_name); } } + + this->update_compatible_with_printer(false); } // Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file. @@ -437,6 +458,8 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const this->update_multi_material_filament_presets(); for (size_t i = 1; i < std::min(tmp_bundle.filament_presets.size(), this->filament_presets.size()); ++ i) this->filament_presets[i] = load_one(this->filaments, tmp_bundle.filaments, tmp_bundle.filament_presets[i], false); + + this->update_compatible_with_printer(false); } // Load a config bundle file, into presets and store the loaded presets into separate files @@ -537,6 +560,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla this->update_multi_material_filament_presets(); for (size_t i = 0; i < std::min(this->filament_presets.size(), active_filaments.size()); ++ i) this->filament_presets[i] = filaments.find_preset(active_filaments[i], true)->name; + + this->update_compatible_with_printer(false); return presets_loaded; } diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 308785fda..df04efd73 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -44,6 +44,11 @@ public: DynamicPrintConfig full_config() const; + // Load user configuration and store it into the user profiles. + // This method is called by the configuration wizard. + void load_config(const std::string &name, DynamicPrintConfig config) + { this->load_config_file_config(name, false, std::move(config)); } + // Load an external config file containing the print, filament and printer presets. // Instead of a config file, a G-code may be loaded containing the full set of parameters. // In the future the configuration will likely be read from an AMF file as well. @@ -89,7 +94,10 @@ public: void update_compatible_with_printer(bool select_other_if_incompatible); private: - void load_config_file_config(const std::string &path, DynamicPrintConfig &&config); + // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. + // and the external config is just referenced, not stored into user profile directory. + // If it is not an external config, then the config will be stored into the user profile directory. + void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config); void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree); bool load_compatible_bitmaps(); diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index ed5db01e9..0e6b1504b 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -119,6 +119,14 @@ PresetCollection::arrayref() Slic3r::data_dir().c_str(), e.what()); } %}; + void load_config(const char *name, DynamicPrintConfig *config) + %code%{ + try { + THIS->load_config(name, *config); + } catch (std::exception& e) { + croak("Loading a configuration %s failed:\n%s\n", name, e.what()); + } + %}; void load_config_file(const char *path) %code%{ try { From c8d14fb6178f4feea906f1509e9988fceceb0e26 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 12:03:54 +0100 Subject: [PATCH 63/69] The wipe tower generator does not call start_filament_gcode when returning from a wipe tower and the particular wipe tower layer is only sparsely filled without a tool change. https://github.com/prusa3d/Slic3r/issues/642 --- xs/src/libslic3r/GCode.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 25fbc0139..47695a230 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -180,16 +180,16 @@ 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", start_filament_gcode, new_extruder_id); - check_add_eol(gcode); - } + // Always append the filament start G-code even if the extruder did not switch, + // because the wipe tower resets the linear advance and we want it to be re-enabled. + 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", 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)); From 7142126609fbd01102a5d9ccb45e475cb721fb66 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 13:32:02 +0100 Subject: [PATCH 64/69] Grey out the compatible_printers_condition edit field in case the compatible_printers list is non empty. Changed the precendence of compatible_printers_condition over compatible_printers. Now compatible_printers has precedence. --- lib/Slic3r/GUI/Tab.pm | 3 +++ xs/src/slic3r/GUI/Preset.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index e01c0a107..9253cee09 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -495,6 +495,7 @@ sub _compatible_printers_widget { $btn->$method; # All printers have been made compatible with this preset. $self->_load_key_value('compatible_printers', []) if $checkbox->GetValue; + $self->get_field('compatible_printers_condition')->toggle($checkbox->GetValue); }); EVT_BUTTON($self, $btn, sub { @@ -516,6 +517,7 @@ sub _compatible_printers_widget { my $value = [ @presets[$dlg->GetSelections] ]; if (!@$value) { $checkbox->SetValue(1); + $self->get_field('compatible_printers_condition')->toggle(1); $btn->Disable; } # All printers have been made compatible with this preset. @@ -533,6 +535,7 @@ sub _reload_compatible_printers_widget { my $method = $has_any ? 'Enable' : 'Disable'; $self->{compatible_printers_checkbox}->SetValue(! $has_any); $self->{compatible_printers_btn}->$method; + $self->get_field('compatible_printers_condition')->toggle(! $has_any); } sub update_ui_from_settings { diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 6af5982a3..2720654bf 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -144,8 +144,10 @@ std::string Preset::label() const bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const { - auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); - if (condition != nullptr && ! condition->value.empty()) { + auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); + auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); + bool has_compatible_printers = compatible_printers != nullptr && ! compatible_printers->values.empty(); + if (! has_compatible_printers && condition != nullptr && ! condition->value.empty()) { try { return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config, extra_config); } catch (const std::runtime_error &err) { @@ -154,9 +156,7 @@ bool Preset::is_compatible_with_printer(const Preset &active_printer, const Dyna return true; } } - auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); - return this->is_default || active_printer.name.empty() || - compatible_printers == nullptr || compatible_printers->values.empty() || + return this->is_default || active_printer.name.empty() || ! has_compatible_printers || std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != compatible_printers->values.end(); } From 4572fe69dec14f2958b1457c23cd617836d888f2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 13:46:43 +0100 Subject: [PATCH 65/69] Fix of a regression update issue of the "modified" flag at the active profile, specific to OSX. https://github.com/prusa3d/Slic3r/issues/632 --- xs/src/slic3r/GUI/Preset.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 2720654bf..c28c989fb 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -519,6 +519,11 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str())); } } +#ifdef __APPLE__ + // wxWidgets on OSX do not upload the text of the combo box line automatically. + // Force it to update by re-selecting. + ui->SetSelection(ui->GetSelection()); +#endif /* __APPLE __ */ return was_dirty != is_dirty; } From b2ba4ee34c5ccd7d8278939f33e51d1db3bfa9ef Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 14:51:18 +0100 Subject: [PATCH 66/69] Fixes volumetric speed "Hint-Text" ignores "First Layer Speed" and "Extrusion multiplier" #641 Implements first layer speed adjustments. --- xs/src/slic3r/GUI/PresetHints.cpp | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/xs/src/slic3r/GUI/PresetHints.cpp b/xs/src/slic3r/GUI/PresetHints.cpp index 13478f980..8e23a5c49 100644 --- a/xs/src/slic3r/GUI/PresetHints.cpp +++ b/xs/src/slic3r/GUI/PresetHints.cpp @@ -55,11 +55,6 @@ static const ConfigOptionFloatOrPercent& first_positive(const ConfigOptionFloatO return (v1 != nullptr && v1->value > 0) ? *v1 : ((v2.value > 0) ? v2 : v3); } -static double first_positive(double v1, double v2) -{ - return (v1 > 0.) ? v1 : v2; -} - std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle &preset_bundle) { // Find out, to which nozzle index is the current filament profile assigned. @@ -106,6 +101,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle const auto &solid_infill_extrusion_width = *print_config.option("solid_infill_extrusion_width"); const auto &support_material_extrusion_width = *print_config.option("support_material_extrusion_width"); const auto &top_infill_extrusion_width = *print_config.option("top_infill_extrusion_width"); + const auto &first_layer_speed = *print_config.option("first_layer_speed"); // Index of an extruder assigned to a feature. If set to 0, an active extruder will be used for a multi-material print. // If different from idx_extruder, it will not be taken into account for this hint. @@ -136,12 +132,18 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle const float bfr = bridging ? bridge_flow_ratio : 0.f; double max_flow = 0.; std::string max_flow_extrusion_type; + auto limit_by_first_layer_speed = [&first_layer_speed, first_layer](double speed_normal, double speed_max) { + if (first_layer && first_layer_speed.value > 0) + // Apply the first layer limit. + speed_normal = first_layer_speed.get_abs_value(speed_normal); + return (speed_normal > 0.) ? speed_normal : speed_max; + }; if (perimeter_extruder_active) { double external_perimeter_rate = Flow::new_from_config_width(frExternalPerimeter, first_positive(first_layer_extrusion_width_ptr, external_perimeter_extrusion_width, extrusion_width), nozzle_diameter, lh, bfr).mm3_per_mm() * (bridging ? bridge_speed : - first_positive(std::max(external_perimeter_speed, small_perimeter_speed), max_print_speed)); + limit_by_first_layer_speed(std::max(external_perimeter_speed, small_perimeter_speed), max_print_speed)); if (max_flow < external_perimeter_rate) { max_flow = external_perimeter_rate; max_flow_extrusion_type = "external perimeters"; @@ -150,7 +152,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle first_positive(first_layer_extrusion_width_ptr, perimeter_extrusion_width, extrusion_width), nozzle_diameter, lh, bfr).mm3_per_mm() * (bridging ? bridge_speed : - first_positive(std::max(perimeter_speed, small_perimeter_speed), max_print_speed)); + limit_by_first_layer_speed(std::max(perimeter_speed, small_perimeter_speed), max_print_speed)); if (max_flow < perimeter_rate) { max_flow = perimeter_rate; max_flow_extrusion_type = "perimeters"; @@ -159,7 +161,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (! bridging && infill_extruder_active) { double infill_rate = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, infill_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr).mm3_per_mm() * first_positive(infill_speed, max_print_speed); + nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(infill_speed, max_print_speed); if (max_flow < infill_rate) { max_flow = infill_rate; max_flow_extrusion_type = "infill"; @@ -169,7 +171,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle double solid_infill_rate = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, solid_infill_extrusion_width, extrusion_width), nozzle_diameter, lh, 0).mm3_per_mm() * - (bridging ? bridge_speed : first_positive(solid_infill_speed, max_print_speed)); + (bridging ? bridge_speed : limit_by_first_layer_speed(solid_infill_speed, max_print_speed)); if (max_flow < solid_infill_rate) { max_flow = solid_infill_rate; max_flow_extrusion_type = "solid infill"; @@ -177,7 +179,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (! bridging) { double top_solid_infill_rate = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, top_infill_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr).mm3_per_mm() * first_positive(top_solid_infill_speed, max_print_speed); + nozzle_diameter, lh, bfr).mm3_per_mm() * limit_by_first_layer_speed(top_solid_infill_speed, max_print_speed); if (max_flow < top_solid_infill_rate) { max_flow = top_solid_infill_rate; max_flow_extrusion_type = "top solid infill"; @@ -188,7 +190,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle double support_material_rate = Flow::new_from_config_width(frSupportMaterial, first_positive(first_layer_extrusion_width_ptr, support_material_extrusion_width, extrusion_width), nozzle_diameter, lh, bfr).mm3_per_mm() * - (bridging ? bridge_speed : first_positive(support_material_speed, max_print_speed)); + (bridging ? bridge_speed : limit_by_first_layer_speed(support_material_speed, max_print_speed)); if (max_flow < support_material_rate) { max_flow = support_material_rate; max_flow_extrusion_type = "support"; @@ -198,23 +200,23 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle double support_material_interface_rate = Flow::new_from_config_width(frSupportMaterialInterface, first_positive(first_layer_extrusion_width_ptr, support_material_extrusion_width, extrusion_width), nozzle_diameter, lh, bfr).mm3_per_mm() * - (bridging ? bridge_speed : first_positive(support_material_interface_speed, max_print_speed)); + (bridging ? bridge_speed : limit_by_first_layer_speed(support_material_interface_speed, max_print_speed)); if (max_flow < support_material_interface_rate) { max_flow = support_material_interface_rate; max_flow_extrusion_type = "support interface"; } } - //FIXME handle gap_fill_speed if (! out.empty()) out += "\n"; out += (first_layer ? "First layer volumetric" : (bridging ? "Bridging volumetric" : "Volumetric")); out += " flow rate is maximized "; - out += ((max_volumetric_speed > 0 && max_volumetric_speed < max_flow) ? + bool limited_by_max_volumetric_speed = max_volumetric_speed > 0 && max_volumetric_speed < max_flow; + out += (limited_by_max_volumetric_speed ? "by the print profile maximum" : - ("when printing " + max_flow_extrusion_type)) + ("when printing " + max_flow_extrusion_type)) + " with a volumetric rate "; - if (max_volumetric_speed > 0 && max_volumetric_speed < max_flow) + if (limited_by_max_volumetric_speed) max_flow = max_volumetric_speed; char buf[2048]; sprintf(buf, "%3.2f mm³/s", max_flow); From 8acd51fc6246cc12523521e3b621db43a0dcbbd2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 18:25:53 +0100 Subject: [PATCH 67/69] Replaced boost::regex with std::regex. --- xs/src/libslic3r/PlaceholderParser.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 027ef4310..58ee09eea 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #ifdef _MSC_VER #include // provides **_environ @@ -22,9 +23,6 @@ #endif #include -#include -// Unicode iterator to iterate over utf8. -#include // Spirit v2.5 allows you to suppress automatic generation // of predefined terminals to speed up complation. With @@ -426,13 +424,13 @@ namespace client } try { std::string pattern(++ rhs.begin(), -- rhs.end()); - bool result = boost::regex_match(*subject, boost::regex(pattern)); + bool result = std::regex_match(*subject, std::regex(pattern)); if (op == '!') result = ! result; lhs.reset(); lhs.type = TYPE_BOOL; lhs.data.b = result; - } catch (boost::regex_error &ex) { + } catch (std::regex_error &ex) { // Syntax error in the regular expression boost::throw_exception(qi::expectation_failure( rhs.begin(), rhs.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what()))); From fed5128b7f55e947b3bb38905283dfba81da06a2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 21:54:47 +0100 Subject: [PATCH 68/69] Reverted regex to boost::regex as the C++11 regex seems to be broken on Linux/gcc 4.9. --- xs/src/libslic3r/PlaceholderParser.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 58ee09eea..bcd011da2 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #ifdef _MSC_VER #include // provides **_environ @@ -51,6 +50,15 @@ #include #include +// #define USE_CPP11_REGEX +#ifdef USE_CPP11_REGEX + #include + #define SLIC3R_REGEX_NAMESPACE std +#else /* USE_CPP11_REGEX */ + #include + #define SLIC3R_REGEX_NAMESPACE boost +#endif /* USE_CPP11_REGEX */ + namespace Slic3r { PlaceholderParser::PlaceholderParser() @@ -424,13 +432,13 @@ namespace client } try { std::string pattern(++ rhs.begin(), -- rhs.end()); - bool result = std::regex_match(*subject, std::regex(pattern)); + bool result = SLIC3R_REGEX_NAMESPACE::regex_match(*subject, SLIC3R_REGEX_NAMESPACE::regex(pattern)); if (op == '!') result = ! result; lhs.reset(); lhs.type = TYPE_BOOL; lhs.data.b = result; - } catch (std::regex_error &ex) { + } catch (SLIC3R_REGEX_NAMESPACE::regex_error &ex) { // Syntax error in the regular expression boost::throw_exception(qi::expectation_failure( rhs.begin(), rhs.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what()))); From 1bf67b4b62c09d06eefab368b8698c291f05afde Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Dec 2017 22:13:19 +0100 Subject: [PATCH 69/69] Added boost::regex to cmakelists. --- xs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 07442f248..2f8eb14c5 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -440,7 +440,7 @@ if(SLIC3R_STATIC) # Use boost libraries linked statically to the C++ runtime. # set(Boost_USE_STATIC_RUNTIME ON) endif() -find_package(Boost REQUIRED COMPONENTS system filesystem thread log locale) +find_package(Boost REQUIRED COMPONENTS system filesystem thread log locale regex) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) target_link_libraries(XS ${Boost_LIBRARIES})