diff --git a/doc/How to build - Windows.md b/doc/How to build - Windows.md index ea17523c00a..5a2acb140e8 100644 --- a/doc/How to build - Windows.md +++ b/doc/How to build - Windows.md @@ -69,6 +69,8 @@ cmake .. -G "Visual Studio 16 2019" -DDESTDIR="c:\src\REPO_NAME-deps" msbuild /m ALL_BUILD.vcxproj // This took 13.5 minutes on my machine: core I7-7700K @ 4.2Ghz with 32GB main memory and 20min on a average laptop ``` +note: if you have visual studio 2022 installed alongside 2017/2019, you may have to comment/remove the lines 20->31 in `dep_Boost-prefix/src/dep_Boosttools/build/src/engine/vswhere_usability_wrapper.cmd` (after first failing to compile) to force it to ignore vs2022. + ### Generate Visual Studio project file for Slic3r, referencing the precompiled dependencies. Go to the Windows Start Menu and Click on "Visual Studio 2019" folder, then select the ->"x64 Native Tools Command Prompt" to open a command window and run the following: ``` diff --git a/resources/ui_layout/default/filament.ui b/resources/ui_layout/default/filament.ui index 60f105f24c6..845f5e3773b 100644 --- a/resources/ui_layout/default/filament.ui +++ b/resources/ui_layout/default/filament.ui @@ -36,24 +36,23 @@ group:Fan speed - default end_line setting:min_fan_speed line:Perimeter fan speed - setting:label$:perimeter_fan_speed + setting:label_width$12:label$Internal:perimeter_fan_speed setting:label_width$12:label$External:external_perimeter_fan_speed - end_line - setting:overhang_perimeter_fan_speed - setting:infill_fan_speed + line:Internal Infill fan speed + setting:label_width$12:label$Sparse:infill_fan_speed line:Solid Infill fan speed - setting:label$:solid_infill_fan_speed - setting:label_width$12:label$Top:top_fan_speed - end_line + setting:label_width$12:label$Solid:solid_infill_fan_speed + setting:label_width$12:label$Top solid:top_fan_speed line:Support Material fan speed - setting:label$:support_material_fan_speed - setting:label_width$12:label$Support Interface:support_material_interface_fan_speed - end_line + setting:label_width$12:label$Default:support_material_fan_speed + setting:label_width$12:label$Interface:support_material_interface_fan_speed line:Bridges fan speed - setting:label$:bridge_fan_speed - setting:label_width$12:label$Infill bridges:bridge_internal_fan_speed - end_line - setting:gap_fill_fan_speed + setting:label_width$12:label$Bridges:bridge_fan_speed + setting:label_width$12:label$Internal bridges:bridge_internal_fan_speed + line:Overhangs Perimeter fan speed + setting:label_width$12:label$Overhangs:overhangs_fan_speed + line:Gap fill fan speed + setting:label_width$12:label$Gap fill:gap_fill_fan_speed group:Short layer time - began to increase base fan speed setting:fan_below_layer_time setting:label$Max fan speed:max_fan_speed diff --git a/resources/ui_layout/example/filament.ui b/resources/ui_layout/example/filament.ui index 60f105f24c6..845f5e3773b 100644 --- a/resources/ui_layout/example/filament.ui +++ b/resources/ui_layout/example/filament.ui @@ -36,24 +36,23 @@ group:Fan speed - default end_line setting:min_fan_speed line:Perimeter fan speed - setting:label$:perimeter_fan_speed + setting:label_width$12:label$Internal:perimeter_fan_speed setting:label_width$12:label$External:external_perimeter_fan_speed - end_line - setting:overhang_perimeter_fan_speed - setting:infill_fan_speed + line:Internal Infill fan speed + setting:label_width$12:label$Sparse:infill_fan_speed line:Solid Infill fan speed - setting:label$:solid_infill_fan_speed - setting:label_width$12:label$Top:top_fan_speed - end_line + setting:label_width$12:label$Solid:solid_infill_fan_speed + setting:label_width$12:label$Top solid:top_fan_speed line:Support Material fan speed - setting:label$:support_material_fan_speed - setting:label_width$12:label$Support Interface:support_material_interface_fan_speed - end_line + setting:label_width$12:label$Default:support_material_fan_speed + setting:label_width$12:label$Interface:support_material_interface_fan_speed line:Bridges fan speed - setting:label$:bridge_fan_speed - setting:label_width$12:label$Infill bridges:bridge_internal_fan_speed - end_line - setting:gap_fill_fan_speed + setting:label_width$12:label$Bridges:bridge_fan_speed + setting:label_width$12:label$Internal bridges:bridge_internal_fan_speed + line:Overhangs Perimeter fan speed + setting:label_width$12:label$Overhangs:overhangs_fan_speed + line:Gap fill fan speed + setting:label_width$12:label$Gap fill:gap_fill_fan_speed group:Short layer time - began to increase base fan speed setting:fan_below_layer_time setting:label$Max fan speed:max_fan_speed diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index fc917dcea0b..da610ef95b0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -553,7 +553,7 @@ constexpr float SMALL_PERIMETER_SPEED_RATIO_OFFSET = (-10); // Collect pairs of object_layer + support_layer sorted by print_z. // object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON. -std::vector GCode::collect_layers_to_print(const PrintObject& object) +std::vector GCode::collect_layers_to_print(const PrintObject &object, Print::StatusMonitor &status_monitor) { std::vector layers_to_print; layers_to_print.reserve(object.layers().size() + object.support_layers().size()); @@ -676,7 +676,7 @@ std::vector GCode::collect_layers_to_print(const PrintObjec + _(L("Make sure the object is printable. This is usually caused by negligibly small extrusions or by a faulty model. " "Try to repair the model or change its orientation on the bed.")); - const_cast(object.print())->active_step_add_warning( + status_monitor.active_step_add_warning( PrintStateBase::WarningLevel::CRITICAL, warning); } @@ -686,7 +686,7 @@ std::vector GCode::collect_layers_to_print(const PrintObjec // Prepare for non-sequential printing of multiple objects: Support resp. object layers with nearly identical print_z // will be printed for all objects at once. // Return a list of items. -std::vector>> GCode::collect_layers_to_print(const Print& print) +std::vector>> GCode::collect_layers_to_print(const Print &print, Print::StatusMonitor &status_monitor) { struct OrderingItem { coordf_t print_z; @@ -697,7 +697,7 @@ std::vector>> GCode::collec std::vector> per_object(print.objects().size(), std::vector()); std::vector ordering; for (size_t i = 0; i < print.objects().size(); ++i) { - per_object[i] = collect_layers_to_print(*print.objects()[i]); + per_object[i] = collect_layers_to_print(*print.objects()[i], status_monitor); OrderingItem ordering_item; ordering_item.object_idx = i; ordering.reserve(ordering.size() + per_object[i].size()); @@ -812,8 +812,8 @@ namespace DoExport { if (ret.size() < MAX_TAGS_COUNT) check(_(L("Extrusion type change G-code")), config.feature_gcode.value); if (ret.size() < MAX_TAGS_COUNT) check(_(L("Tool change G-code")), config.toolchange_gcode.value); if (ret.size() < MAX_TAGS_COUNT) check(_(L("Between objects G-code (for sequential printing)")), config.between_objects_gcode.value); - if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), config.color_change_gcode.value); - if (ret.size() < MAX_TAGS_COUNT) check(_(L("Pause Print G-code")), config.pause_print_gcode.value); + if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), GCodeWriter::get_default_color_change_gcode(config)); + if (ret.size() < MAX_TAGS_COUNT) check(_(L("Pause Print G-code")), GCodeWriter::get_default_pause_gcode(config)); if (ret.size() < MAX_TAGS_COUNT) check(_(L("Template Custom G-code")), config.template_custom_gcode.value); if (ret.size() < MAX_TAGS_COUNT) { for (const std::string& value : config.start_filament_gcode.values) { @@ -866,7 +866,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu if (print->is_step_done(psGCodeExport) && boost::filesystem::exists(boost::filesystem::path(path))) return; - print->set_started(psGCodeExport); + Print::StatusMonitor monitor{ *print }; + monitor.set_started(psGCodeExport); // check if any custom gcode contains keywords used by the gcode processor to // produce time estimation and gcode toolpaths @@ -876,7 +877,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu for (const auto& [source, keyword] : validation_res) { reports += source + ": \"" + keyword + "\"\n"; } - print->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, + monitor.active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, _(L("In the custom G-code were found reserved keywords:")) + "\n" + reports + _(L("This may cause problems in g-code visualization and printing time estimation."))); @@ -933,7 +934,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu // Post-process the G-code to update time stamps. m_processor.finalize(true); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); - DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->config() ,print->m_print_statistics); + DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->config(), monitor.stats()); if (result != nullptr) { *result = std::move(m_processor.extract_result()); // set the filename to the correct value @@ -948,7 +949,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu } BOOST_LOG_TRIVIAL(info) << "Exporting G-code finished" << log_memory_info(); - print->set_done(psGCodeExport); + monitor.set_done(psGCodeExport); //notify gui that the gcode is ready to be drawed print->set_status(100, "", PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE); print->set_status(100, L("Gcode done"), PrintBase::SlicingStatus::FlagBits::GCODE_ENDED); @@ -1265,7 +1266,7 @@ std::vector sort_object_instances_by_model_order(const Pri // set standby temp for extruders // Parse the custom G-code, try to find T, and add it if not present -void GCode::_init_multiextruders(Print& print, GCodeOutputStream& file, GCodeWriter & writer, ToolOrdering &tool_ordering, const std::string &custom_gcode ) +void GCode::_init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter & writer, const ToolOrdering &tool_ordering, const std::string &custom_gcode ) { //set standby temp for reprap @@ -1283,10 +1284,13 @@ void GCode::_init_multiextruders(Print& print, GCodeOutputStream& file, GCodeWri } } -void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) +void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) { PROFILE_FUNC(); + const Print &print = print_mod; + Print::StatusMonitor status_monitor{print_mod}; + //apply print config to m_config and m_writer, so we don't have to use print.config() instead // (and mostly to make m_writer.preamble() works) this->apply_print_config(print.config()); @@ -1315,8 +1319,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING m_fan_mover.release(); - print.m_print_statistics.color_extruderid_to_used_filament.clear(); - print.m_print_statistics.color_extruderid_to_used_weight.clear(); + status_monitor.stats().color_extruderid_to_used_filament.clear(); + status_monitor.stats().color_extruderid_to_used_weight.clear(); // How many times will be change_layer() called? // change_layer() in turn increments the progress bar status. @@ -1859,7 +1863,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Process all layers of a single object instance (sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. - this->process_layers(print, print.m_print_statistics, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file); + this->process_layers(print, status_monitor, tool_ordering, collect_layers_to_print(object, status_monitor), + *print_object_instance_sequential_active - object.instances().data(), file); ++finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. // Reset it when starting another object from 1st layer. @@ -1883,22 +1888,23 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato print_object_instance_sequential_active = print_object_instances_ordering.begin(); for (size_t i = 0; i < print.objects().size(); ++i, ++print_object_instance_sequential_active) { - std::vector object_layers = collect_layers_to_print(*print.objects()[i]); std::vector>> layers_to_print_range; - - int layer_num = 0; - for (const LayerToPrint& ltp : object_layers) { - layer_num++; - if (!first_layer && layer_num == 1) - continue; - - if (ltp.print_z() >= Rstart && ltp.print_z() < Rend) { - std::pair> merged; - merged.first = ltp.print_z(); - merged.second.emplace_back(ltp); - layers_to_print_range.emplace_back(merged); - if (first_layer) - break; + { + std::vector object_layers = collect_layers_to_print(*print.objects()[i], status_monitor); + int layer_num = 0; + for (LayerToPrint& ltp : object_layers) { + layer_num++; + if (!first_layer && layer_num == 1) + continue; + + if (ltp.print_z() >= Rstart && ltp.print_z() < Rend) { + std::pair> merged; + merged.first = ltp.print_z(); + merged.second.push_back(std::move(ltp)); + layers_to_print_range.emplace_back(merged); + if (first_layer) + break; + } } } @@ -1912,7 +1918,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato this->write_travel_to(gcode, polyline, "move to origin position for next object"); file.write(gcode); } - this->process_layers(print, print.m_print_statistics, tool_ordering, print_object_instances_ordering, layers_to_print_range, file); + this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, + layers_to_print_range, file); prev_object = print_object_instance_sequential_active; is_layers = true; } @@ -1929,7 +1936,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato } else { // Sort layers by Z. // All extrusion moves with the same top layer height are extruded uninterrupted. - std::vector>> layers_to_print = collect_layers_to_print(print); + std::vector>> layers_to_print = collect_layers_to_print(print, status_monitor); // Prusa Multi-Material wipe tower. if (has_wipe_tower && !layers_to_print.empty()) { m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get())); @@ -1961,7 +1968,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // This is not Marlin, M1 command is probably not supported. // (See https://github.com/prusa3d/PrusaSlicer/issues/5441.) if (overlap) { - print.active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, + status_monitor.active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, _(L("Your print is very close to the priming regions. " "Make sure there is no collision."))); } else { @@ -1975,7 +1982,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Process all layers of all objects (non-sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. - this->process_layers(print, print.m_print_statistics, tool_ordering, print_object_instances_ordering, layers_to_print, file); + this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, layers_to_print, file); if (m_wipe_tower) // Purge the extruder, pull out the active filament. file.write(m_wipe_tower->finalize(*this)); @@ -2041,12 +2048,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_writer.extruders(), initial_extruder_id, // Modifies - print.m_print_statistics)); + status_monitor.stats())); file.write("\n"); - file.write_format("; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight); - file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); - if (print.m_print_statistics.total_toolchanges > 0) - file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); + file.write_format("; total filament used [g] = %.2lf\n", status_monitor.stats().total_weight); + file.write_format("; total filament cost = %.2lf\n", status_monitor.stats().total_cost); + if (status_monitor.stats().total_toolchanges > 0) + file.write_format("; total toolchanges = %i\n", status_monitor.stats().total_toolchanges); file.write_format("; total layers count = %i\n", m_layer_count); file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); @@ -2110,7 +2117,7 @@ class TBBLocalesSetter : public tbb::task_scheduler_observer // and export G-code into file. void GCode::process_layers( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, const std::vector &print_object_instances_ordering, const std::vector>> &layers_to_print, @@ -2119,7 +2126,7 @@ void GCode::process_layers( // The pipeline is variable: The vase mode filter is optional. size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [this, &print, &print_stat, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> LayerResult { + [this, &print, &status_monitor, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> LayerResult { CNumericLocalesSetter locales_setter; if (layer_to_print_idx >= layers_to_print.size()) { if ((!m_pressure_equalizer && layer_to_print_idx == layers_to_print.size()) || (m_pressure_equalizer && layer_to_print_idx == (layers_to_print.size() + 1))) { @@ -2137,7 +2144,8 @@ void GCode::process_layers( if (m_wipe_tower && layer_tools.has_wipe_tower) m_wipe_tower->next_layer(); print.throw_if_canceled(); - return this->process_layer(print, print_stat, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1)); + return this->process_layer(print, status_monitor, layer.second, layer_tools, &layer == &layers_to_print.back(), + &print_object_instances_ordering, size_t(-1)); } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -2216,7 +2224,7 @@ void GCode::process_layers( // and export G-code into file. void GCode::process_layers( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, std::vector layers_to_print, const size_t single_object_idx, @@ -2225,7 +2233,7 @@ void GCode::process_layers( // The pipeline is variable: The vase mode filter is optional. size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [this, &print, &print_stat, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> LayerResult { + [this, &print, &status_monitor, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> LayerResult { if (layer_to_print_idx >= layers_to_print.size()) { if ((!m_pressure_equalizer && layer_to_print_idx == layers_to_print.size()) || (m_pressure_equalizer && layer_to_print_idx == (layers_to_print.size() + 1))) { fc.stop(); @@ -2239,7 +2247,7 @@ void GCode::process_layers( } else { LayerToPrint &layer = layers_to_print[layer_to_print_idx ++]; print.throw_if_canceled(); - return this->process_layer(print, print_stat, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx); + return this->process_layer(print, status_monitor, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx); } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -2415,7 +2423,7 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc // Print the machine envelope G-code for the Marlin firmware based on the "machine_max_xxx" parameters. // Do not process this piece of G-code by the time estimator, it already knows the values through another sources. -void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print) +void GCode::print_machine_envelope(GCodeOutputStream &file, const Print &print) { // gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinLegacy, gcfMarlinFirmware, gcfKlipper, gcfSailfish, gcfSprinter, gcfMach3, gcfMachinekit, /// gcfSmoothie, gcfNoExtrusion, gcfLerdge, @@ -2493,7 +2501,7 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print) // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // M140 - Set Bed Temperature // M190 - Set Bed Temperature and Wait -void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) { // Initial bed temperature based on the first extruder. int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id); @@ -2516,7 +2524,7 @@ void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &p // M104 - Set Extruder Temperature // M109 - Set Extruder Temperature and Wait // RepRapFirmware: G10 Sxx -void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait) { // Is the bed temperature set by the provided custom G-code? int temp_by_gcode = -1; @@ -2634,7 +2642,7 @@ std::string emit_custom_gcode_per_print_z( // ID of the first extruder printing this layer. uint16_t first_extruder_id, const Print &print, - PrintStatistics &stats) + Print::StatusMonitor &status_emitter) { std::string gcode; bool single_extruder_printer = print.config().nozzle_diameter.size() == 1; @@ -2659,10 +2667,10 @@ std::string emit_custom_gcode_per_print_z( if (color_change) { //update stats : length double previously_extruded = 0; - for (const auto& tuple : stats.color_extruderid_to_used_filament) + for (const auto &tuple : status_emitter.stats().color_extruderid_to_used_filament) if (tuple.first == m600_extruder_before_layer) previously_extruded += tuple.second; - stats.color_extruderid_to_used_filament.emplace_back(m600_extruder_before_layer, gcodegen.writer().get_tool(m600_extruder_before_layer)->used_filament() - previously_extruded); + status_emitter.stats().color_extruderid_to_used_filament.emplace_back(m600_extruder_before_layer, gcodegen.writer().get_tool(m600_extruder_before_layer)->used_filament() - previously_extruded); } // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count @@ -2680,13 +2688,19 @@ std::string emit_custom_gcode_per_print_z( ) { //! FIXME_in_fw show message during print pause cfg.set_key_value("color_change_extruder", new ConfigOptionInt(m600_extruder_before_layer)); - gcode += gcodegen.placeholder_parser_process("pause_print_gcode", print.config().pause_print_gcode, current_extruder_id, &cfg); + gcode += gcodegen.placeholder_parser_process("pause_print_gcode", GCodeWriter::get_default_pause_gcode(print.config()), current_extruder_id, &cfg); gcode += "\n"; gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; } else { + if (GCodeWriter::get_default_color_change_gcode(print.config()).empty()) { + status_emitter.active_step_add_warning( + PrintStateBase::WarningLevel::NON_CRITICAL, + _(L("Using a color change gcode, but there isn't one for this printer." + "\nThe printer won't stop for the filament change, unless you set it manually in the custom gcode section."))); + } cfg.set_key_value("color_change_extruder", new ConfigOptionInt(current_extruder_id)); // placeholder to avoid 'crashs' - gcode += gcodegen.placeholder_parser_process("color_change_gcode", print.config().color_change_gcode, current_extruder_id, &cfg); + gcode += gcodegen.placeholder_parser_process("color_change_gcode", GCodeWriter::get_default_color_change_gcode(print.config()), current_extruder_id, &cfg); gcode += "\n"; //FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after // return from M600. Thus the G-code generated by the following line is ignored. @@ -2697,13 +2711,19 @@ std::string emit_custom_gcode_per_print_z( } else { if (gcode_type == CustomGCode::PausePrint) // Pause print - { + { + if (GCodeWriter::get_default_pause_gcode(print.config()).empty()) { + status_emitter.active_step_add_warning( + PrintStateBase::WarningLevel::NON_CRITICAL, + _(L("Using a pause gcode, but there isn't one for this printer." + "\nThe printer won't pause, unless you set it manually in the custom gcode section."))); + } // add tag for processor gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n"; //! FIXME_in_fw show message during print pause if (!pause_print_msg.empty()) gcode += "M117 " + pause_print_msg + "\n"; - gcode += gcodegen.placeholder_parser_process("pause_print_gcode", print.config().pause_print_gcode, current_extruder_id); + gcode += gcodegen.placeholder_parser_process("pause_print_gcode", GCodeWriter::get_default_pause_gcode(print.config()), current_extruder_id); } else { // add tag for processor gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Custom_Code) + "\n"; @@ -2805,7 +2825,7 @@ boost::regex regex_g92e0_gcode{ "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t // and performing the extruder specific extrusions together. LayerResult GCode::process_layer( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, const LayerTools &layer_tools, @@ -2971,7 +2991,7 @@ LayerResult GCode::process_layer( if (single_object_instance_idx == size_t(-1)) { // Normal (non-sequential) print. - gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.tool()->id(), first_extruder_id, print, print_stat); + gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.tool()->id(), first_extruder_id, print, status_monitor); } // Extrude skirt at the print_z of the raft layers and normal object layers // not at the print_z of the interlaced support material layers. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index f3f9d1f5392..c2632d846ac 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -246,14 +246,14 @@ class GCode : ExtrusionVisitorConst { }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); - void _init_multiextruders(Print& print, GCodeOutputStream& file, GCodeWriter& writer, ToolOrdering& tool_ordering, const std::string& custom_gcode); + void _init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter& writer, const ToolOrdering& tool_ordering, const std::string& custom_gcode); - static std::vector collect_layers_to_print(const PrintObject &object); - static std::vector>> collect_layers_to_print(const Print &print); + static std::vector collect_layers_to_print(const PrintObject &object, Print::StatusMonitor &status_monitor); + static std::vector>> collect_layers_to_print(const Print &print, Print::StatusMonitor &status_monitor); LayerResult process_layer( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, const LayerTools &layer_tools, @@ -269,7 +269,7 @@ class GCode : ExtrusionVisitorConst { // and export G-code into file. void process_layers( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, const std::vector &print_object_instances_ordering, const std::vector>> &layers_to_print, @@ -279,7 +279,7 @@ class GCode : ExtrusionVisitorConst { // and export G-code into file. void process_layers( const Print &print, - PrintStatistics &print_stat, + Print::StatusMonitor &status_monitor, const ToolOrdering &tool_ordering, std::vector layers_to_print, const size_t single_object_idx, @@ -506,9 +506,9 @@ class GCode : ExtrusionVisitorConst { std::string _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1); double_t _compute_speed_mm_per_sec(const ExtrusionPath& path, double speed = -1); std::string _after_extrude(const ExtrusionPath &path); - void print_machine_envelope(GCodeOutputStream &file, Print &print); - void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); - void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); + void print_machine_envelope(GCodeOutputStream &file, const Print &print); + void _print_first_layer_bed_temperature(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); + void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, const Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } // To control print speed of 1st object layer over raft interface. diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index d9f261ffa31..c6f6a9a8d8b 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -29,8 +29,36 @@ #define E_NUM(val) PRECISION(val, this->config.gcode_precision_e.value) namespace Slic3r { +std::string GCodeWriter::get_default_pause_gcode(const GCodeConfig &config) +{ + if (config.pause_print_gcode.value.empty()) { + if (config.gcode_flavor.value == GCodeFlavor::gcfKlipper) { + return "PAUSE"; + } else if (config.gcode_flavor.value == GCodeFlavor::gcfRepRap || config.gcode_flavor.value == GCodeFlavor::gcfMarlinLegacy /*prusa only*/) { + return "M601"; + } else { + // no pause command for other firmware, for what i am aware. Please submit a pullrequest or issue if they change. + return ""; + } + } else { + return config.pause_print_gcode.value; + } +} -std::string GCodeWriter::PausePrintCode = "M601"; +std::string GCodeWriter::get_default_color_change_gcode(const GCodeConfig &config) +{ + if (config.color_change_gcode.value.empty()) { + if (config.gcode_flavor.value == GCodeFlavor::gcfRepRap || config.gcode_flavor.value == GCodeFlavor::gcfMarlinLegacy || + config.gcode_flavor.value == GCodeFlavor::gcfMarlinFirmware || config.gcode_flavor.value == GCodeFlavor::gcfSmoothie) { + return "M600"; + } else { + // no pause command for other firmware, for what i am aware. Please submit a pullrequest or issue if they change. + return ""; + } + } else { + return config.color_change_gcode.value; + } +} void GCodeWriter::apply_print_config(const PrintConfig &print_config) { diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index cb764840979..b0d3769843e 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -12,7 +12,6 @@ namespace Slic3r { class GCodeWriter { public: - static std::string PausePrintCode; GCodeConfig config; bool multiple_extruders; // override from region @@ -90,6 +89,9 @@ class GCodeWriter { std::string set_fan(uint8_t speed, uint16_t default_tool = 0); uint8_t get_fan() { return m_last_fan_speed; } + static std::string get_default_pause_gcode(const GCodeConfig &config); + static std::string get_default_color_change_gcode(const GCodeConfig &config); + private: // Extruders are sorted by their ID, so that binary search is possible. std::vector m_extruders; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 16094dfe17b..6eec0dc90d4 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -669,6 +669,28 @@ class Print : public PrintBaseWithState // Invalidates the step, and its depending steps in Print. //in public to invalidate gcode when the physical printer change. It's needed if we allow the gcode macro to read these values. bool invalidate_step(PrintStep step); + + // just a little wrapper to let the user know that this print can only be modified to emit warnings & update advancement status, change stats. + // TODO: have the status out of the printbase class and into another one, so we can have a const print & a mutable statusmonitor + class StatusMonitor + { + private: + Print& print; + + public: + StatusMonitor(Print &print_mutable) : print(print_mutable) {} + + // need this extra method because active_step_add_warning is protected and so need the friend status, and Gcode has it. + void active_step_add_warning(PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id = 0) + { + print.active_step_add_warning(warning_level, message, message_id); + } + PrintStatistics &stats() { return print.m_print_statistics; } + bool set_started(PrintStep step) { return print.set_started(step); } + PrintStateBase::TimeStamp set_done(PrintStep step) { return print.set_done(step); } + + }; + protected: private: @@ -708,8 +730,6 @@ class Print : public PrintBaseWithState // tiem of last change, to see if the gui need to be updated std::time_t m_timestamp_last_change; - // To allow GCode to set the Print's GCodeExport step status. - friend class GCode; // Allow PrintObject to access m_mutex and m_cancel_callback. friend class PrintObject; }; diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 16a8c2f8471..e37ab0b3d72 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -505,6 +505,10 @@ class PrintBase : public ObjectBase // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. //public to ebablet ot call it from brim code. void throw_if_canceled() const { if (m_cancel_status.load(std::memory_order_acquire)) throw CanceledException(); } + + // Update "scale", "input_filename", "input_filename_base" placeholders from the current printable ModelObjects. + void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const; + protected: friend class PrintObjectBase; friend class BackgroundSlicingProcess; @@ -522,8 +526,6 @@ class PrintBase : public ObjectBase // To be called by this->output_filename() with the format string pulled from the configuration layer. std::string output_filename(const std::string &format, const std::string &default_ext, const std::string &filename_base, const DynamicConfig *config_override = nullptr) const; - // Update "scale", "input_filename", "input_filename_base" placeholders from the current printable ModelObjects. - void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const; Model m_model; DynamicPrintConfig m_full_print_config; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index fdb04d64eab..36124b424d7 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2664,7 +2664,7 @@ void PrintConfigDef::init_fff_params() def = this->add("gap_fill_extension", coFloatOrPercent); def->label = L("Extension"); - def->full_label = L("Gapfill: extra extension"); + def->full_label = L("Gap fill: extra extension"); def->category = OptionCategory::perimeter; def->tooltip = L("Increase the length of all gapfills by this amount (may overextrude a little bit)\nCan be a % of the perimeter width"); def->ratio_over = "perimeter_width"; @@ -2675,7 +2675,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent{ 0, false }); def = this->add("gap_fill_fan_speed", coInts); - def->label = L("Gap Fill fan speed"); + def->label = L("Gap fill fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during all gap fill Perimeter moves" "\nSet to 1 to disable fan." @@ -2684,7 +2684,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->min = -1; def->max = 100; - def->mode = comAdvancedE | comSuSi; + def->mode = comExpert | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ -1 }); @@ -3133,7 +3133,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->min = -1; def->max = 100; - def->mode = comAdvancedE | comSuSi; + def->mode = comExpert | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ -1 }); @@ -3879,7 +3879,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(0,false)); def = this->add("overhangs_fan_speed", coInts); - def->label = L("Overhang Perimeter fan speed"); + def->label = L("Overhangs Perimeter fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during all Overhang Perimeter moves" "\nSet to 1 to disable fan." @@ -4107,7 +4107,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->min = -1; def->max = 100; - def->mode = comAdvancedE | comSuSi; + def->mode = comExpert | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ -1 }); @@ -4938,7 +4938,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->min = -1; def->max = 100; - def->mode = comAdvancedE | comSuSi; + def->mode = comExpert | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ -1 }); @@ -5044,21 +5044,23 @@ void PrintConfigDef::init_fff_params() def = this->add("color_change_gcode", coString); def->label = L("Color change G-code"); - def->tooltip = L("This G-code will be used as a code for the color change"); + def->tooltip = L("This G-code will be used as a code for the color change" + " If empty, the default color change print command for the selected G-code flavor will be used (if any)."); def->multiline = true; def->full_width = true; def->height = 12; def->mode = comExpert | comPrusa; - def->set_default_value(new ConfigOptionString("M600")); + def->set_default_value(new ConfigOptionString("")); def = this->add("pause_print_gcode", coString); def->label = L("Pause Print G-code"); - def->tooltip = L("This G-code will be used as a code for the pause print"); + def->tooltip = L("This G-code will be used as a code for the pause print." + " If empty, the default pause print command for the selected G-code flavor will be used (if any)."); def->multiline = true; def->full_width = true; def->height = 12; def->mode = comExpert | comPrusa; - def->set_default_value(new ConfigOptionString("M601")); + def->set_default_value(new ConfigOptionString("")); def = this->add("template_custom_gcode", coString); def->label = L("Custom G-code"); @@ -5315,7 +5317,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("%"); def->min = -1; def->max = 100; - def->mode = comAdvancedE | comSuSi; + def->mode = comExpert | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ -1 }); @@ -5967,7 +5969,7 @@ void PrintConfigDef::init_fff_params() def->category = OptionCategory::extruders; def->tooltip = L("This flag will wipe the nozzle a bit inward after extruding an external perimeter." " The wipe_extra_perimeter is executed first, then this move inward before the retraction wipe." - " Note that the retraction wipe will follow the exact external perimeter (center) line if this parameter is disabled, and will follow the inner side of the external periemter line if enabled"); + " Note that the retraction wipe will follow the exact external perimeter (center) line if this parameter is disabled, and will follow the inner side of the external perimeter line if enabled"); def->mode = comAdvancedE | comSuSi; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionBools{ true }); diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 942433f759d..93d071a9370 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -1,13 +1,14 @@ #include "libslic3r/libslic3r.h" #include "DoubleSlider.hpp" -#include "libslic3r/GCode.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "Plater.hpp" #include "I18N.hpp" #include "ExtruderSequenceDialog.hpp" -#include "libslic3r/Print.hpp" #include "libslic3r/AppConfig.hpp" +#include "libslic3r/GCode.hpp" +#include "libslic3r/GCodeWriter.hpp" +#include "libslic3r/Print.hpp" #include "GUI_Utils.hpp" #include "MsgDialog.hpp" #include "Tab.hpp" @@ -51,10 +52,11 @@ wxDEFINE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); static std::string gcode(Type type) { - const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config(); + const Print& print = GUI::wxGetApp().plater()->fff_print(); + const PrintConfig &config = print.config(); switch (type) { - case ColorChange: return config.color_change_gcode; - case PausePrint: return config.pause_print_gcode; + case ColorChange: return Slic3r::GCodeWriter::get_default_color_change_gcode(config); + case PausePrint: return Slic3r::GCodeWriter::get_default_pause_gcode(config); case Template: return config.template_custom_gcode; default: return ""; } @@ -2014,7 +2016,7 @@ void Control::show_add_context_menu() { wxMenu menu; - if (m_mode == SingleExtruder) { + if (m_mode == SingleExtruder && !gcode(ColorChange).empty()) { append_menu_item(&menu, wxID_ANY, _L("Add color change") + " (" + gcode(ColorChange) + ")", "", [this](wxCommandEvent&) { add_code_as_tick(ColorChange); }, "colorchange_add_m", &menu); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 74ff54055f6..9da3eefced9 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -41,7 +41,6 @@ #include "PresetComboBoxes.hpp" #include -#include #include #include "GUI_App.hpp" @@ -3363,11 +3362,6 @@ void TabPrinter::toggle_options() field = get_field("silent_mode"); if (field) field->toggle(is_marlin_flavor); - if (m_config->option>("gcode_flavor")->value == gcfKlipper) - GCodeWriter::PausePrintCode = "PAUSE"; - else - GCodeWriter::PausePrintCode = "M601"; - if (m_last_gcode_flavor != uint8_t(m_config->option>("gcode_flavor")->value)) { m_last_gcode_flavor = uint8_t(m_config->option>("gcode_flavor")->value); m_rebuild_kinematics_page = true;