diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a0afca3..632bc12 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -276,7 +276,6 @@ namespace Slic3r { deretraction_str = gcodegen.unretract(); } - // Insert the toolchange and deretraction gcode into the generated gcode. @@ -1487,6 +1486,15 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Write end commands to file. file.write(this->retract()); + + //B38 + { + std::string gcode; + m_writer.add_object_change_labels(gcode); + file.write(gcode); + } + + file.write(m_writer.set_fan(0)); // adds tag for processor @@ -2215,6 +2223,9 @@ LayerResult GCode::process_layer( bool first_layer = layer.id() == 0; unsigned int first_extruder_id = layer_tools.extruders.front(); + //B36 + m_writer.set_is_first_layer(first_layer); + // Initialize config with the 1st object to be printed at this layer. m_config.apply(layer.object()->config(), true); @@ -2452,7 +2463,13 @@ void GCode::process_layer_single_object( break; else ++ object_id; - gcode += std::string("; printing object ") + print_object.model_object()->name + " id:" + std::to_string(object_id) + " copy " + std::to_string(print_instance.instance_id) + "\n"; + //B38 + if (this->config().gcode_flavor == gcfKlipper) { + m_writer.set_object_start_str(std::string("EXCLUDE_OBJECT_START NAME=") + print_object.model_object()->name + "\n"); + } else { + gcode += std::string("; printing object ") + print_object.model_object()->name + " id:" + std::to_string(object_id) + + " copy " + std::to_string(print_instance.instance_id) + "\n"; + } } } }; @@ -2625,8 +2642,21 @@ void GCode::process_layer_single_object( } } } - if (! first && this->config().gcode_label_objects) - gcode += std::string("; stop printing object ") + print_object.model_object()->name + " id:" + std::to_string(object_id) + " copy " + std::to_string(print_instance.instance_id) + "\n"; + + if (!first && this->config().gcode_label_objects) { + //B38 + if (this->config().gcode_flavor == gcfKlipper) { + if (!m_writer.is_object_start_str_empty()) { + m_writer.set_object_start_str(""); + } else { + m_writer.set_object_end_str(std::string("EXCLUDE_OBJECT_END NAME=") + print_object.model_object()->name + "\n"); + } + } else { + gcode += std::string("; stop printing object ") + print_object.model_object()->name + " id:" + std::to_string(object_id) + + " copy " + std::to_string(print_instance.instance_id) + "\n"; + } + } + } void GCode::apply_print_config(const PrintConfig &print_config) @@ -2703,8 +2733,13 @@ std::string GCode::change_layer(coordf_t print_z) // Increment a progress bar indicator. gcode += m_writer.update_progress(++ m_layer_index, m_layer_count); coordf_t z = print_z + m_config.z_offset.value; // in unscaled coordinates - if (EXTRUDER_CONFIG(retract_layer_change) && m_writer.will_move_z(z)) + if (EXTRUDER_CONFIG(retract_layer_change) && m_writer.will_move_z(z)) { gcode += this->retract(); + } + + //B38 + m_writer.add_object_change_labels(gcode); + { std::ostringstream comment; @@ -2998,6 +3033,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de gcode += this->travel_to(path.first_point(), path.role(), comment); } + //B38 + m_writer.add_object_change_labels(gcode); + // compensate retraction gcode += this->unretract(); @@ -3057,8 +3095,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de } if (m_volumetric_speed != 0. && speed == 0) speed = m_volumetric_speed / path.mm3_per_mm; + //B37 if (this->on_first_layer()) - speed = m_config.get_abs_value("first_layer_speed", speed); + speed = path.role() == ExtrusionRole::ExternalPerimeter ? m_config.get_abs_value("first_layer_external_perimeter_speed") : m_config.get_abs_value("first_layer_speed", speed); else if (this->object_layer_over_raft()) speed = m_config.get_abs_value("first_layer_speed_over_raft", speed); if (m_config.max_volumetric_speed.value > 0) { @@ -3296,6 +3335,10 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string // Reset the wipe path when traveling, so one would not wipe along an old path. m_wipe.reset_path(); + //B38 + m_writer.add_object_change_labels(gcode); + + // use G1 because we rely on paths being straight (G0 may make round paths) if (travel.size() >= 2) { diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 9ed53c0..52080c7 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -320,7 +320,10 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com GCodeG1Formatter w; w.emit_xy(point); - w.emit_f(this->config.travel_speed.value * 60.0); + //B36 + auto speed = m_is_first_layer ? this->config.get_abs_value("first_layer_travel_speed") : + this->config.travel_speed.value; + w.emit_f(speed * 60.0); w.emit_comment(this->config.gcode_comments, comment); return w.string(); } @@ -596,6 +599,31 @@ std::string GCodeWriter::set_fan(unsigned int speed) const return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed); } + +//B38 +void GCodeWriter::add_object_start_labels(std::string &gcode) +{ + if (!m_gcode_label_objects_start.empty()) { + gcode += m_gcode_label_objects_start; + m_gcode_label_objects_start = ""; + } +} + +void GCodeWriter::add_object_end_labels(std::string &gcode) +{ + if (!m_gcode_label_objects_end.empty()) { + gcode += m_gcode_label_objects_end; + m_gcode_label_objects_end = ""; + } +} + +void GCodeWriter::add_object_change_labels(std::string &gcode) +{ + add_object_end_labels(gcode); + add_object_start_labels(gcode); +} + + void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) { assert(digits <= 9); static constexpr const std::array pow_10{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 638f09c..4420007 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -24,6 +24,8 @@ public: //B24 m_last_volume_temperature(0), m_last_volume_temperature_reached(true), m_lifted(0) + //B36 + , m_is_first_layer(true) {} Extruder* extruder() { return m_extruder; } const Extruder* extruder() const { return m_extruder; } @@ -96,6 +98,19 @@ public: // Keeping the state is left to the CoolingBuffer, which runs asynchronously on another thread. std::string set_fan(unsigned int speed) const; + //B36 + void set_is_first_layer(bool bval) { m_is_first_layer = bval; } + + //B38 + void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; } + bool is_object_start_str_empty() { return m_gcode_label_objects_start.empty(); } + void set_object_end_str(std::string end_string) { m_gcode_label_objects_end = end_string; } + bool is_object_end_str_empty() { return m_gcode_label_objects_end.empty(); } + void add_object_start_labels(std::string &gcode); + void add_object_end_labels(std::string &gcode); + void add_object_change_labels(std::string &gcode); + + private: // Extruders are sorted by their ID, so that binary search is possible. std::vector m_extruders; @@ -117,6 +132,13 @@ private: double m_lifted; Vec3d m_pos = Vec3d::Zero(); + //B36 + bool m_is_first_layer = true; + + //B38 + std::string m_gcode_label_objects_start; + std::string m_gcode_label_objects_end; + enum class Acceleration { Travel, Print diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f0f7425..020659d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -484,8 +484,10 @@ static std::vector s_Preset_print_options { "mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "wall_distribution_count", "min_feature_size", "min_bead_width" - //B15 - // "enable_auxiliary_fan" + //B36 + ,"first_layer_travel_speed" + //B37 + ,"first_layer_external_perimeter_speed" }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index abe2f58..1c8780a 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -222,6 +222,10 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "travel_speed" || opt_key == "travel_speed_z" || opt_key == "first_layer_speed" + //B36 + || opt_key == "first_layer_travel_speed" + //B37 + || opt_key == "first_layer_external_perimeter_speed" || opt_key == "z_offset") { steps.emplace_back(psWipeTower); steps.emplace_back(psSkirtBrim); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b13184c..a794e4a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1366,16 +1366,24 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); //B36 - // def = this->add("first_layer_travel_speed", coFloatOrPercent); - // def->label = L("First layer travel speed"); - // def->tooltip = L("If expressed as absolute value in mm/s, this speed will be applied to all the print moves " - // "of the first layer, regardless of their type. If expressed as a percentage " - // "(for example: 40%) it will scale the default speeds."); - // def->sidetext = L("mm/s or %"); - // def->min = 0; - // def->max_literal = 20; - // def->mode = comAdvanced; - // def->set_default_value(new ConfigOptionFloatOrPercent(200, false)); + def = this->add("first_layer_travel_speed", coFloat); + def->label = L("First layer travel"); + def->tooltip = L("Speed for travel moves (jumps between distant extrusion points)."); + def->sidetext = L("mm/s"); + def->aliases = {"travel_feed_rate"}; + def->min = 1; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(130)); + + //B37 + def = this->add("first_layer_external_perimeter_speed", coFloat); + def->label = L("First layer external perimeters"); + def->tooltip = L("Speed for travel moves (jumps between distant extrusion points)."); + def->sidetext = L("mm/s"); + def->aliases = {"travel_feed_rate"}; + def->min = 1; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(130)); def = this->add("first_layer_speed_over_raft", coFloatOrPercent); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 561db7c..74ec0c8 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -731,6 +731,12 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, wipe_tower_no_sparse_layers)) ((ConfigOptionString, toolchange_gcode)) ((ConfigOptionFloat, travel_speed)) + + //B36 + ((ConfigOptionFloat, first_layer_travel_speed)) + //B37 + ((ConfigOptionFloat, first_layer_external_perimeter_speed)) + ((ConfigOptionFloat, travel_speed_z)) ((ConfigOptionBool, use_firmware_retraction)) ((ConfigOptionBool, use_relative_e_distances)) @@ -800,8 +806,6 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloatOrPercent, first_layer_extrusion_width)) ((ConfigOptionFloatOrPercent, first_layer_height)) ((ConfigOptionFloatOrPercent, first_layer_speed)) - //B36 - // ((ConfigOptionFloatOrPercent, first_layer_travel_speed)) ((ConfigOptionInts, first_layer_temperature)) ((ConfigOptionIntsNullable, idle_temperature)) //B26 diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bd10dd3..b397889 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1574,6 +1574,10 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Modifiers")); optgroup->append_single_option_line("first_layer_speed"); optgroup->append_single_option_line("first_layer_speed_over_raft"); + //B36 + optgroup->append_single_option_line("first_layer_travel_speed"); + //B37 + optgroup->append_single_option_line("first_layer_external_perimeter_speed"); optgroup = page->new_optgroup(L("Acceleration control (advanced)")); optgroup->append_single_option_line("external_perimeter_acceleration");