6572{
6573 assert(! layers.empty());
6574
6575 assert(single_object_instance_idx == size_t(-1) || layers.size() == 1);
6576
6577
6578 const Layer *object_layer = nullptr;
6579 const SupportLayer *support_layer = nullptr;
6580 const SupportLayer *raft_layer = nullptr;
6582 if (l.object_layer && ! object_layer)
6583 object_layer = l.object_layer;
6584 if (l.support_layer) {
6585 if (! support_layer)
6586 support_layer = l.support_layer;
6587 if (! raft_layer && support_layer->id() < support_layer->object()->slicing_parameters().raft_layers())
6588 raft_layer = support_layer;
6589 }
6590 }
6591
6592
6593
6594 if (object_layer == nullptr && support_layer == nullptr &&
6595 std::any_of(layers.begin(), layers.end(),
6596 [](
const LayerToPrint &l) { return l.belt_brim_band != nullptr; }))
6597 return this->
process_belt_brim_layer(print, layers, layer_tools, last_layer, single_object_instance_idx, most_used_extruder);
6598
6599 const Layer* layer_ptr = nullptr;
6600 if (object_layer != nullptr)
6601 layer_ptr = object_layer;
6602 else if (support_layer != nullptr)
6603 layer_ptr = support_layer;
6604 const Layer&
layer = *layer_ptr;
6606
6607
6610 LayerResult result { {},
layer.id(),
false, last_layer };
6611 if (layer_tools.extruders.empty())
6612
6613 return result;
6614
6615
6617
6618
6619
6621 m_writer.set_is_first_layer(first_layer);
6622 unsigned int first_extruder_id = layer_tools.extruders.front();
6623
6624
6626
6627
6628
6630 if (
m_spiral_vase && layers.size() == 1 && support_layer ==
nullptr) {
6631 bool enable = (
layer.id() > 0 || !print.has_brim()) && (
layer.id() >= (
size_t)print.config().skirt_height.value && ! print.has_infinite_skirt());
6632 if (enable) {
6633 for (
const LayerRegion *layer_region :
layer.regions())
6634 if (
size_t(layer_region->region().config().bottom_shell_layers.value) >
layer.id() ||
6635 layer_region->perimeters.items_count() > 1u ||
6636 layer_region->fills.items_count() > 0) {
6637 enable = false;
6638 break;
6639 }
6640 }
6641 result.spiral_vase_enable = enable;
6642
6644 }
6645
6648
6649
6651
6652 char buf[80];
6653 sprintf(buf, print.is_BBL_printer() ? "; Z_HEIGHT: %g\n" : ";Z:%g\n", print_z);
6655
6656 float height = first_layer ?
static_cast<float>(print_z) : static_cast<float>(print_z) -
m_last_layer_z;
6659
6663
6664
6665 if (!
m_config.before_layer_change_gcode.value.empty()) {
6671 print.config().before_layer_change_gcode.value,
m_writer.filament()->id(), &
config)
6672 + "\n";
6673 }
6674
6677 bool is_multi_extruder =
m_config.nozzle_diameter.size() > 1;
6678
6679
6680
6681
6682
6688
6689 bool need_insert_timelapse_gcode_for_traditional = false;
6691 need_insert_timelapse_gcode_for_traditional = ((is_i3_printer && !
m_spiral_vase) || is_multi_extruder);
6692 }
6693
6694 bool has_insert_timelapse_gcode = false;
6695 bool has_wipe_tower = (layer_tools.has_wipe_tower &&
m_wipe_tower);
6696
6697
6702
6703
6709
6710 if (!need_insert_timelapse_gcode_for_traditional && !
m_config.time_lapse_gcode.value.empty() && !
is_BBL_Printer()) {
6713 print.config().time_lapse_gcode.value,
m_writer.filament()->id(), &
config)
6714 + "\n";
6715 }
6716
6717 if (!
m_config.layer_change_gcode.value.empty())
6719
6720
6721 gcode +=
";_SET_FAN_SPEED_CHANGING_LAYER\n";
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737 double calib_z = print_z;
6739
6740 for (
const Layer* l :
layer.object()->layers())
6741 if (!l->lslices.empty()) {
6742 calib_z = print_z - (l->print_z - l->height);
6743 break;
6744 }
6745 }
6746 switch (print.calib_mode()) {
6749 static_cast<float>(print.calib_params().end),
6750 static_cast<float>(print.calib_params().step)));
6751 break;
6752 }
6754
6755
6756
6757
6758 int sectioned_temp = 0;
6760 sscanf(
layer.object()->model_object()->name.c_str(),
"temp_%d", §ioned_temp) == 1 &&
6761 sectioned_temp > 0) {
6763 } else {
6765 }
6766 break;
6767 }
6769
6770
6771
6773 static_cast<float>(print.calib_params().end),
6774 static_cast<float>(print.calib_params().step));
6776 break;
6777 }
6779 auto _speed = print.calib_params().start + std::max(0.0, calib_z) * print.calib_params().step;
6781 break;
6782 }
6784 auto _length = print.calib_params().start + std::floor(std::max(0.0,calib_z-0.4)) * print.calib_params().step;
6785 DynamicConfig _cfg;
6788 sprintf(buf, "; Calib_Retraction_tower: Z_HEIGHT: %g, length:%g\n", calib_z, _length);
6790 break;
6791 }
6795 } else {
6796 if (print.calib_params().freqStartX == print.calib_params().freqStartY && print.calib_params().freqEndX == print.calib_params().freqEndY) {
6798 } else {
6801 }
6802 }
6803 break;
6804 }
6809 } else {
6811 }
6812 break;
6813 }
6816 !
m_config.machine_max_junction_deviation.values.empty() &&
6817 m_config.machine_max_junction_deviation.values.front() > 0) {
6819 } else {
6821 }
6822 break;
6823 }
6824 }
6825
6826
6827 if (first_layer) {
6828
6831 }
6832
6835 }
6836
6839 }
6840 }
6841
6842
6843
6844
6845
6846 bool past_first_layer_band = !first_layer;
6848 past_first_layer_band = past > 0;
6849
6851
6852 const auto plr_mode = print.config().enable_power_loss_recovery.value;
6854
6855 if (print.is_BBL_printer()) {
6856
6857 if (print.config().scan_first_layer.value) {
6858
6860 gcode +=
"M976 S1 P1 ; scan model before printing 2nd layer\n";
6861 gcode +=
"M400 P100\n";
6863 }
6864 }
6865
6866
6869 }
6870
6873 }
6874
6875
6876
6877
6878
6879
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891 const int num_filament_slots = (int) print.config().filament_diameter.values.size();
6892
6893
6894
6895 const int initial_physical =
6896 ((int) first_extruder_id >= 0 &&
6897 (int) first_extruder_id < (int)
m_config.physical_extruder_map.values.size())
6898 ?
m_config.physical_extruder_map.values[(int) first_extruder_id]
6899 : -1;
6901 const int logical = (tool_idx == initial_physical)
6902 ? (int)first_extruder_id
6905 if (logical < 0 || logical >= num_filament_slots) continue;
6906
6908 if (temperature > 0)
6910 tool_idx, "set IMEX tool temperature");
6911 }
6912 } else {
6913
6914
6916 if ((print.config().single_extruder_multi_material.value ||
m_ooze_prevention.enable) &&
6917 extruder.id() !=
m_writer.filament()->id())
6918
6919 continue;
6921 int temperature = print.config().nozzle_temperature.get_at(fi);
6922 if (temperature > 0 && temperature != print.config().nozzle_temperature_initial_layer.get_at(fi))
6923 gcode +=
m_writer.set_temperature(temperature,
false, extruder.id());
6924 }
6925 }
6926
6927
6928 int bed_temp = 0;
6931 else
6934
6936 }
6937
6938 if (single_object_instance_idx == size_t(-1)) {
6939
6941 }
6942
6943
6944 auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
6946 const unsigned int number_of_extruders = (
unsigned int)(sqrt(flush_matrix.size()) +
EPSILON);
6947
6948 std::vector<std::vector<float>> wipe_volumes;
6949 for (unsigned int i = 0; i < number_of_extruders; ++i)
6950 wipe_volumes.push_back(std::vector<float>(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders));
6951 unsigned int next_extruder = current_extruder;
6952 float min_flush = std::numeric_limits<float>::max();
6953 for (auto extruder_id : extruders) {
6954 if (print.config().filament_soluble.get_at(extruder_id) || extruder_id == current_extruder)
6955 continue;
6956 if (wipe_volumes[current_extruder][extruder_id] < min_flush) {
6957 next_extruder = extruder_id;
6958 min_flush = wipe_volumes[current_extruder][extruder_id];
6959 }
6960 }
6961 return next_extruder;
6962 };
6963
6965 auto overhang_speed = [this](const LayerRegion ®ion) {
6967 };
6968 for (const auto &layer_to_print : layers)
6971
6972
6973 std::map<unsigned int, std::vector<ObjectByExtruder>> by_extruder;
6974
6975
6976
6977 std::map<std::pair<const SupportLayer *, ExtrusionRole>, unsigned int> support_filaments;
6978 std::vector<std::unique_ptr<ExtrusionEntityCollection>> split_perimeter_storage;
6979 bool is_anything_overridden = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden();
6981 if (layer_to_print.support_layer != nullptr) {
6982 const SupportLayer &support_layer = *layer_to_print.support_layer;
6983 const PrintObject& object = *layer_to_print.original_object;
6984 if (! support_layer.support_fills.entities.empty()) {
6988
6989 unsigned int support_extruder = object.config().support_filament.value - 1;
6990
6991 bool support_dontcare = object.config().support_filament.value == 0;
6992
6993 unsigned int interface_extruder = object.config().support_interface_filament.value - 1;
6994
6995 bool interface_dontcare = object.config().support_interface_filament.value == 0;
6996
6997
6998 WipingExtrusions& wiping_extrusions = const_cast<LayerTools&>(layer_tools).wiping_extrusions();
6999 if (support_dontcare) {
7000 int extruder_override = wiping_extrusions.get_support_extruder_overrides(&object);
7001 if (extruder_override >= 0) {
7002 support_extruder = extruder_override;
7003 support_dontcare = false;
7004 }
7005 }
7006
7007 if (interface_dontcare) {
7008 int extruder_override = wiping_extrusions.get_support_interface_extruder_overrides(&object);
7009 if (extruder_override >= 0) {
7010 interface_extruder = extruder_override;
7011 interface_dontcare = false;
7012 }
7013 }
7014
7015
7016 if (support_dontcare && !interface_dontcare) {
7017 unsigned int dontcare_extruder = first_extruder_id;
7018 for (unsigned int extruder_id : layer_tools.extruders) {
7019 if (print.config().filament_soluble.get_at(extruder_id))
7020 continue;
7021
7022
7023 if (extruder_id == interface_extruder)
7024 continue;
7025
7026 dontcare_extruder = extruder_id;
7027 break;
7028 }
7029 #if 0
7030
7031 if (dontcare_extruder == interface_extruder && (
object.
config().support_interface_not_for_body &&
object.
config().support_interface_filament.value!=0)) {
7032
7033 auto all_extruders = print.extruders();
7034 dontcare_extruder = get_next_extruder(dontcare_extruder, all_extruders);
7035 }
7036 #endif
7037
7038 if (support_dontcare)
7039 support_extruder = dontcare_extruder;
7040 }
7041 else if (support_dontcare || interface_dontcare) {
7042
7043
7044 unsigned int dontcare_extruder = first_extruder_id;
7045 if (print.config().filament_soluble.get_at(dontcare_extruder)) {
7046
7047
7048 for (unsigned int extruder_id : layer_tools.extruders)
7049 if (! print.config().filament_soluble.get_at(extruder_id)) {
7050 dontcare_extruder = extruder_id;
7051 break;
7052 }
7053 }
7054 if (print.config().filament_is_support.get_at(dontcare_extruder)) {
7055
7056
7057 for (unsigned int extruder_id : layer_tools.extruders)
7058 if (!print.config().filament_is_support.get_at(extruder_id)) {
7059 dontcare_extruder = extruder_id;
7060 break;
7061 }
7062 }
7063 if (support_dontcare)
7064 support_extruder = dontcare_extruder;
7065 if (interface_dontcare)
7066 interface_extruder = dontcare_extruder;
7067 }
7068
7069
7070 bool single_extruder = ! has_support || support_extruder == interface_extruder;
7071
7072
7073 if (has_support) {
7076 }
7077 if (has_interface) {
7079 single_extruder ? (has_support ? support_extruder : interface_extruder) : interface_extruder;
7080 }
7081
7083 obj.support = &support_layer.support_fills;
7085 if (! single_extruder && has_interface) {
7087 obj_interface.support = &support_layer.support_fills;
7089 }
7090 }
7091 }
7092
7093 if (layer_to_print.object_layer != nullptr) {
7094 const Layer &
layer = *layer_to_print.object_layer;
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104 size_t n_slices =
layer.lslices.size();
7105 const std::vector<BoundingBox> &layer_surface_bboxes =
layer.lslices_bboxes;
7106
7107
7108 std::vector<size_t> slices_test_order;
7109 slices_test_order.reserve(n_slices);
7110 for (size_t i = 0; i < n_slices; ++ i)
7111 slices_test_order.emplace_back(i);
7112 std::sort(slices_test_order.begin(), slices_test_order.end(), [&layer_surface_bboxes](size_t i, size_t j) {
7113 const Vec2d s1 = layer_surface_bboxes[i].size().cast<double>();
7114 const Vec2d s2 = layer_surface_bboxes[j].size().cast<double>();
7115 return s1.x() * s1.y() < s2.x() * s2.y();
7116 });
7117 auto point_inside_surface = [&
layer, &layer_surface_bboxes](
const size_t i,
const Point &point) {
7118 const BoundingBox &bbox = layer_surface_bboxes[i];
7119 return point(0) >= bbox.min(0) && point(0) < bbox.max(0) &&
7120 point(1) >= bbox.min(1) && point(1) < bbox.max(1) &&
7121 layer.lslices[i].contour.contains(point);
7122 };
7123
7124 for (
size_t region_id = 0; region_id <
layer.regions().size(); ++ region_id) {
7125 const LayerRegion *layerm =
layer.regions()[region_id];
7126 if (layerm == nullptr)
7127 continue;
7128
7129
7130 const PrintRegion ®ion = print.get_print_region(layerm->region().print_region_id());
7131
7132
7133
7134
7135 std::vector<unsigned int> printing_extruders;
7138
7139 assert(dynamic_cast<const ExtrusionEntityCollection*>(ee) != nullptr);
7140 const auto *extrusions = static_cast<const ExtrusionEntityCollection*>(ee);
7141 if (extrusions->entities.empty())
7142 continue;
7143
7144 auto process_extrusions = [&](const ExtrusionEntityCollection *current_extrusions,
7145 const ExtrusionEntityCollection *overrides_key,
7146 bool use_overrides) {
7147
7148 int correct_extruder_id = layer_tools.extruder(*current_extrusions, region);
7149
7151 if (! layer_tools.has_extruder(correct_extruder_id)) {
7152
7153
7154
7155
7156
7157 if (!layer_tools.is_mixed_slot(correct_extruder_id)) {
7158
7159
7160 correct_extruder_id = layer_tools.extruders.back();
7161 }
7162 }
7163 printing_extruders.clear();
7164 if (is_anything_overridden && use_overrides) {
7165 entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(overrides_key, layer_to_print.original_object, correct_extruder_id, layer_to_print.object()->instances().size());
7166 if (entity_overrides == nullptr) {
7167 printing_extruders.emplace_back(correct_extruder_id);
7168 } else {
7169 printing_extruders.reserve(entity_overrides->size());
7170 for (int extruder : *entity_overrides)
7171 printing_extruders.emplace_back(extruder >= 0 ?
7172
7173 extruder :
7174
7175 static_cast<unsigned int>(- extruder - 1));
7177 }
7178 } else {
7179 printing_extruders.emplace_back(correct_extruder_id);
7180 }
7181
7182
7183 for (unsigned int extruder : printing_extruders) {
7185 by_extruder,
7186 extruder,
7187 &layer_to_print - layers.data(),
7188 layers.size(), n_slices + 1);
7189 for (size_t i = 0; i <= n_slices; ++i) {
7190 bool last = i == n_slices;
7191 size_t island_idx = last ? n_slices : slices_test_order[i];
7192 if (last || point_inside_surface(island_idx, current_extrusions->first_point())) {
7193 if (islands[island_idx].by_region.empty())
7195 islands[island_idx].by_region[region.print_region_id()].append(entity_type, current_extrusions, entity_overrides);
7196 break;
7197 }
7198 }
7199 }
7200 };
7201
7202 const auto is_inner = [](
const ExtrusionEntity *entity) {
return is_inner_wall(*entity); };
7204 std::count_if(extrusions->entities.begin(), extrusions->entities.end(), is_inner) : 0;
7205 bool split_mixed_perimeters =
7206 region.config().outer_wall_filament_id.value != region.config().inner_wall_filament_id.value &&
7207 inner_count > 0 && inner_count < extrusions->entities.size();
7208
7209 if (split_mixed_perimeters) {
7210 auto outer_perimeters = std::make_unique<ExtrusionEntityCollection>();
7211 auto inner_perimeters = std::make_unique<ExtrusionEntityCollection>();
7212 for (const ExtrusionEntity *entity : extrusions->entities)
7213 (is_inner(entity) ? inner_perimeters : outer_perimeters)->
append(*entity);
7214
7215 split_perimeter_storage.emplace_back(std::move(outer_perimeters));
7216 process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
7217 split_perimeter_storage.emplace_back(std::move(inner_perimeters));
7218 process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
7219 } else {
7220 process_extrusions(extrusions, extrusions, true);
7221 }
7222 }
7223 }
7224 }
7225 }
7226 }
7227
7228
7229
7232
7233
7234
7235 std::map<unsigned int, std::pair<std::vector<InstanceToPrint>, std::vector<InstanceVisit>>> filament_to_print_instances;
7236 {
7237
7238
7240 single_object_instance_idx == size_t(-1) &&
7242
7243
7244
7245
7246 std::vector<unsigned int> plan_filaments = layer_tools.extruders;
7247 for (const auto &grp : layer_tools.mixed_sub_layer_groups)
7248 if (std::find(plan_filaments.begin(), plan_filaments.end(), grp.mixed_slot_0based) == plan_filaments.end())
7249 plan_filaments.push_back(grp.mixed_slot_0based);
7250
7251 for (unsigned int filament_id : plan_filaments) {
7252 auto objects_by_extruder_it = by_extruder.find(filament_id);
7253 if (objects_by_extruder_it == by_extruder.end()) continue;
7254
7255 auto &filament_plan = filament_to_print_instances[filament_id];
7256
7257 if (!island_level_ordering) {
7258
7260 filament_plan.second.reserve(filament_plan.first.size());
7261 for (size_t i = 0; i < filament_plan.first.size(); ++i)
7262 filament_plan.second.push_back({i, {}, true});
7263 continue;
7264 }
7265
7266 int plate_idx = print.get_plate_index();
7267 Point wt_pos(print.config().wipe_tower_x.get_at(plate_idx), print.config().wipe_tower_y.get_at(plate_idx));
7268
7269
7270
7271
7272 std::vector<GCode::ObjectByExtruder> &objects_by_extruder = objects_by_extruder_it->second;
7273 std::vector<InstanceToPrint> &instances = filament_plan.first;
7274 std::vector<IslandOrderNode> nodes;
7275 std::vector<std::pair<size_t, bool>> layout;
7276 std::vector<size_t> node_instances;
7277 auto quantize_to_mm = [](
const Point &pt) -> Point {
7279
7280
7283 };
7284 return Point(q(pt.x()), q(pt.y()));
7285 };
7288
7290 const PrintObject *print_object = layers[
layer_id].original_object;
7291 if (print_object == nullptr)
7292 continue;
7293 const Layer *obj_layer = layers[
layer_id].object_layer;
7295 const bool islands_chainable = obj_layer != nullptr && islands.size() == obj_layer->lslices.size() + 1;
7296 for (size_t instance_id = 0; instance_id < print_object->instances().size(); ++instance_id) {
7297 const size_t instance_idx = instances.size();
7299 print_object->instances()[instance_id].model_instance->get_labeled_id());
7300 layout.emplace_back(islands.size(), ! islands.empty() && ! islands.back().by_region.empty());
7301 const Point &shift = print_object->instances()[instance_id].shift;
7302 const size_t first_node = nodes.size();
7303 if (islands_chainable)
7304 for (size_t i = 0; i + 1 < islands.size(); ++i)
7305 if (!islands[i].by_region.empty()) {
7306 nodes.push_back({print_object->id(), instance_id, i,
7307 quantize_to_mm(obj_layer->lslices[i].contour.centroid() + shift)});
7308 node_instances.emplace_back(instance_idx);
7309 }
7310 if (nodes.size() == first_node) {
7311
7312 nodes.push_back({print_object->id(), instance_id, size_t(-1), quantize_to_mm(shift)});
7313 node_instances.emplace_back(instance_idx);
7314 }
7315 }
7316 }
7317
7318
7320 if (! (cache_entry.nodes == nodes && cache_entry.layout == layout)) {
7321 cache_entry.nodes = nodes;
7322 cache_entry.layout = layout;
7324 node_points.reserve(nodes.size());
7326 node_points.emplace_back(node.pos);
7328
7329 std::reverse(tour.begin(), tour.end());
7330
7331
7332 std::vector<InstanceVisit> visits;
7333 std::vector<bool> instance_seen(instances.size(), false);
7334 std::vector<int> last_visit_of_instance(instances.size(), -1);
7335 for (size_t node_idx : tour) {
7336 const size_t instance_idx = node_instances[node_idx];
7337 if (visits.empty() || visits.back().instance_idx != instance_idx) {
7338 visits.push_back({instance_idx, {}, !instance_seen[instance_idx]});
7339 instance_seen[instance_idx] = true;
7340 }
7341 if (nodes[node_idx].island_idx != size_t(-1))
7342 visits.back().islands.emplace_back(nodes[node_idx].island_idx);
7343 last_visit_of_instance[instance_idx] = int(visits.size()) - 1;
7344 }
7345
7346
7347 for (size_t i = 0; i < instances.size(); ++i) {
7348 if (last_visit_of_instance[i] < 0)
7349 continue;
7350 InstanceVisit &last_visit = visits[size_t(last_visit_of_instance[i])];
7351 if (last_visit.islands.empty())
7352
7353 continue;
7354 std::vector<ObjectByExtruder::Island> &islands = instances[i].object_by_extruder.islands;
7355 if (! islands.empty() && ! islands.back().by_region.empty())
7356 last_visit.islands.emplace_back(islands.size() - 1);
7357 }
7358 cache_entry.visits = std::move(visits);
7359 }
7360 filament_plan.second = cache_entry.visits;
7361 }
7362 }
7363
7364 std::set<size_t> layer_object_label_ids;
7365 for (auto iter = filament_to_print_instances.begin(); iter != filament_to_print_instances.end(); ++iter) {
7367 layer_object_label_ids.insert(instance.label_object_id);
7368 }
7369 }
7370
7372
7373
7374
7375
7376 auto insert_timelapse_gcode = [
this, print_z, &print, &most_used_extruder, &layer_object_label_ids,&printed_objects = std::as_const(
m_printed_objects)](
bool skip_pos_pick =
false) -> std::string {
7377 return generate_timelapse_gcode(print, print_z, most_used_extruder, &layer_object_label_ids, &printed_objects, skip_pos_pick);
7378 };
7379
7380
7381
7382
7383 if (!need_insert_timelapse_gcode_for_traditional &&
is_BBL_Printer()
7386 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7387 }
7388 gcode += insert_timelapse_gcode();
7389 }
7390
7393
7394 auto insert_wrapping_detection_gcode = [this, &print, &print_z, &most_used_extruder]() -> std::string {
7395 std::string wrapping_gcode;
7396 if (print.config().enable_wrapping_detection && !print.config().wrapping_detection_gcode.value.empty()) {
7401 config.set_key_value(
"most_used_physical_extruder_id",
new ConfigOptionInt(
m_config.physical_extruder_map.get_at(most_used_extruder)));
7402 config.set_key_value(
"curr_physical_extruder_id",
new ConfigOptionInt(
m_config.physical_extruder_map.get_at(
m_writer.filament()->extruder_id())));
7404 }
7405 m_writer.set_current_position_clear(
false);
7406
7407 double temp_z_after_tool_change;
7410 pos(2) = temp_z_after_tool_change;
7412 }
7413 return wrapping_gcode;
7414 };
7415
7416 bool has_insert_wrapping_detection_gcode = false;
7417
7418
7420
7421
7422
7423
7424
7425 std::set<std::pair<size_t, size_t>> belt_brim_emitted;
7426
7427
7428
7429
7430
7431 auto emit_belt_brim_for_extruder = [this, &print, &layers, single_object_instance_idx](unsigned int extruder_id) -> std::string {
7433 };
7434
7435 for (unsigned int extruder_id : layer_tools.extruders)
7436 {
7437 if (print.config().skirt_type ==
stCombined && !print.skirt_brim_groups().empty()) {
7438 for (size_t group_idx = 0; group_idx < print.skirt_brim_groups().size(); ++group_idx) {
7439 const Print::SkirtBrimGroup& group = print.skirt_brim_groups()[group_idx];
7440 if (group.skirt.empty())
7441 continue;
7442
7443 std::string skirt_gcode =
generate_skirt(print, group.skirt,
Point(0, 0),
layer.object()->config().skirt_start_angle,
7445 gcode += std::move(skirt_gcode);
7446 }
7447 }
7448
7450 std::set<size_t> all_label_ids;
7451 for (
InstanceToPrint &instance : filament_to_print_instances[extruder_id].first)
7452 all_label_ids.insert(instance.label_object_id);
7453
7454
7455
7456 for (const auto &grp : layer_tools.mixed_sub_layer_groups)
7457 for (unsigned int comp : grp.components_0based)
7458 if (comp == extruder_id) {
7459 auto mit = filament_to_print_instances.find(grp.mixed_slot_0based);
7460 if (mit != filament_to_print_instances.end())
7462 all_label_ids.insert(inst.label_object_id);
7463 break;
7464 }
7465
7466
7468 if (!all_label_ids.empty()) {
7469 std::vector<size_t> filament_instances_id(all_label_ids.begin(), all_label_ids.end());
7471 }
7472 }
7473
7474
7475
7477
7478 std::string gcode_toolchange;
7479 if (has_wipe_tower) {
7480 if (!
m_wipe_tower->is_empty_wipe_tower_gcode(*
this, extruder_id, extruder_id == layer_tools.extruders.back())) {
7481 if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode
7483 bool should_insert = true;
7484 if (
m_config.nozzle_diameter.values.size() == 2){
7487
7488
7489
7491 should_insert = is_case_b ? !curr_is_photo_head : curr_is_photo_head;
7492 }
7493
7494 if (should_insert) {
7495 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7496 m_writer.add_object_change_labels(gcode);
7497
7498 gcode += insert_timelapse_gcode();
7499 has_insert_timelapse_gcode = true;
7500 }
7501 }
7502
7503 if (print.config().enable_wrapping_detection && !has_insert_wrapping_detection_gcode) {
7504 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7505 gcode += insert_wrapping_detection_gcode();
7506 has_insert_wrapping_detection_gcode = true;
7507 }
7508 gcode_toolchange =
m_wipe_tower->tool_change(*
this, extruder_id, extruder_id == layer_tools.extruders.back());
7509 }
7510 } else {
7511
7512
7513 if (need_insert_timelapse_gcode_for_traditional &&
7514 !has_insert_timelapse_gcode &&
7516 m_writer.need_toolchange(extruder_id) &&
7517 m_config.nozzle_diameter.values.size() == 2 &&
7521 bool should_insert = is_case_b ? !curr_is_photo_head : curr_is_photo_head;
7522 if (should_insert) {
7523 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7524 m_writer.add_object_change_labels(gcode);
7525
7526 gcode += insert_timelapse_gcode();
7527 has_insert_timelapse_gcode = true;
7528 }
7529 }
7530
7531 if (print.config().enable_wrapping_detection && !has_insert_wrapping_detection_gcode) {
7532 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7533 gcode += insert_wrapping_detection_gcode();
7534 has_insert_wrapping_detection_gcode = true;
7535 }
7536
7537 gcode_toolchange = this->
set_extruder(extruder_id, print_z);
7538 }
7539
7540 if (!gcode_toolchange.empty()) {
7541
7542 result.spiral_vase_enable = false;
7543 }
7544
7545 gcode += std::move(gcode_toolchange);
7546
7547
7550
7551
7552
7553
7554
7555 if (print.has_belt_brim()) {
7557 gcode += emit_belt_brim_for_extruder(extruder_id);
7559 }
7560
7561 auto &filament_plan = filament_to_print_instances[extruder_id];
7562 std::vector<InstanceToPrint> &instances_to_print = filament_plan.first;
7563 const std::vector<InstanceVisit> &instance_visits = filament_plan.second;
7564
7565
7566 std::vector<ObjectByExtruder::Island::Region> by_region_per_copy_cache;
7567 for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) {
7568 if (is_anything_overridden && print_wipe_extrusions == 0)
7569 gcode+=
"; PURGING FINISHED\n";
7570
7572 InstanceToPrint &instance_to_print = instances_to_print[visit.instance_idx];
7573 const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id];
7574 const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
7575 if (visit.first_visit && print_wipe_extrusions == (is_anything_overridden ? 1 : 0)) {
7577 const PrintObject &vobj = instance_to_print.print_object;
7578 if (vobj.has_belt_brim()) {
7579
7580
7581
7582
7583 if (extruder_id == (unsigned int)(vobj.belt_brim_filament() - 1) &&
7584 belt_brim_emitted.insert({ instance_to_print.layer_id, instance_to_print.instance_id }).second)
7586 layer_to_print.object_layer);
7587 } else {
7589 layer_to_print.object_layer);
7590 }
7591 }
7592
7593
7595 instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id();
7596 m_config.apply(print.default_region_config());
7597 m_config.apply(instance_to_print.print_object.config(),
true);
7598 m_layer = layer_to_print.layer();
7602
7604 gcode += std::string(
"; printing object ") + instance_to_print.print_object.model_object()->name +
7605 " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " +
7606 std::to_string(inst.id) + "\n";
7607 }
7608
7612 std::string("; start printing object, unique label id: ") +
7613 std::to_string(instance_to_print.label_object_id) + "\n" + "M624 " +
7615 } else {
7616 const auto gflavor = print.config().gcode_flavor.value;
7618 m_writer.set_object_start_str(std::string(
"EXCLUDE_OBJECT_START NAME=") +
7620 }
7622 std::string str = std::string("M486 S") + std::to_string(inst.unique_id) + "\n";
7623 m_writer.set_object_start_str(str);
7624 }
7625 }
7626 }
7627
7628
7629
7630
7631
7633
7634
7635 const Point &
offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
7636 std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object,
offset);
7642 if (visit.first_visit && instance_to_print.object_by_extruder.support != nullptr) {
7643 m_layer = layers[instance_to_print.layer_id].support_layer;
7645
7646
7647 const Point&
offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
7648 std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object,
offset);
7654 ExtrusionEntityCollection support_eec;
7655
7656
7657 WipingExtrusions& wiping_extrusions = const_cast<LayerTools&>(layer_tools).wiping_extrusions();
7658 bool support_overridden = wiping_extrusions.is_support_overridden(layer_to_print.original_object);
7659 bool support_intf_overridden = wiping_extrusions.is_support_interface_overridden(layer_to_print.original_object);
7660
7661 ExtrusionRole support_extrusion_role = instance_to_print.object_by_extruder.support_extrusion_role;
7663 if (is_overridden == (print_wipe_extrusions != 0)) {
7665
7666 *instance_to_print.object_by_extruder.support, support_extrusion_role);
7667
7668
7671 }
7672 }
7673
7674 m_layer = layer_to_print.layer();
7676 }
7677
7678
7679
7680
7681
7682 std::vector<ObjectByExtruder::Island> &islands = instance_to_print.object_by_extruder.islands;
7683 std::vector<size_t> island_order;
7684 island_order.reserve(visit.islands.size());
7685 for (size_t idx : visit.islands)
7686 if (idx < islands.size())
7687 island_order.emplace_back(idx);
7688 else
7689 BOOST_LOG_TRIVIAL(error) << "island tour refers to island " << idx << " of " << islands.size() << ", skipped";
7690 if (island_order.empty()) {
7691 island_order.reserve(islands.size());
7692 if (layer_to_print.object_layer != nullptr && islands.size() == layer_to_print.object_layer->lslices.size() + 1) {
7693 for (size_t i = 0; i + 1 < islands.size(); ++i)
7694 if (!islands[i].by_region.empty())
7695 island_order.emplace_back(i);
7696 if (island_order.size() > 1) {
7698 island_centroids.reserve(island_order.size());
7699 for (size_t i : island_order)
7700 island_centroids.emplace_back(layer_to_print.object_layer->lslices[i].contour.centroid());
7703 std::vector<size_t> ordered;
7704 ordered.reserve(island_order.size());
7705 for (size_t k : chain)
7706 ordered.emplace_back(island_order[k]);
7707 island_order = std::move(ordered);
7708 }
7709 if (!islands.back().by_region.empty())
7710 island_order.emplace_back(islands.size() - 1);
7711 } else {
7712
7713 for (size_t i = 0; i < islands.size(); ++i)
7714 island_order.emplace_back(i);
7715 }
7716 }
7717 for (size_t island_idx : island_order) {
7719 const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast<unsigned int>(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region;
7720
7721 const Point&
offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
7722 std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object,
offset);
7728
7729
7730 auto has_infill = [](const std::vector<ObjectByExtruder::Island::Region> &by_region) {
7731 for (auto region : by_region) {
7732 if (!region.infills.empty())
7733 return true;
7734 }
7735 return false;
7736 };
7737 {
7738
7740 if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure ==
PrinterStructure::psI3
7741 && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
7742 gcode += this->
retract(
false,
false, auto_lift_type,
true);
7743
7744 gcode += insert_timelapse_gcode();
7745 has_insert_timelapse_gcode = true;
7746 }
7747
7749
7751
7753 }
7754
7756 }
7757
7759 gcode += std::string(
"; stop printing object ") +
7760 instance_to_print.print_object.model_object()->name +
7761 " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " +
7762 std::to_string(inst.id) + "\n";
7763 }
7764
7765
7766 if (!
m_writer.is_object_start_str_empty()) {
7770 m_writer.set_object_end_str(std::string(
"; stop printing object, unique label id: ") +
7771 std::to_string(instance_to_print.label_object_id) + "\n" +
7772 "M625\n");
7773 } else {
7774 const auto gflavor = print.config().gcode_flavor.value;
7776 m_writer.set_object_end_str(std::string(
"EXCLUDE_OBJECT_END NAME=") +
7779 m_writer.set_object_end_str(std::string(
"M486 S-1\n"));
7780 }
7781 }
7782 }
7783 }
7784 }
7785
7786
7787
7788
7789
7790 for (const auto &grp : layer_tools.mixed_sub_layer_groups) {
7791 int sub_idx = -1;
7792 for (size_t k = 0; k < grp.components_0based.size(); ++k) {
7793 if (grp.components_0based[k] == extruder_id) {
7794 sub_idx = static_cast<int>(k);
7795 break;
7796 }
7797 }
7798 if (sub_idx < 0)
7799 continue;
7800
7801 auto mixed_instances_it = filament_to_print_instances.find(grp.mixed_slot_0based);
7802 if (mixed_instances_it == filament_to_print_instances.end() || mixed_instances_it->second.first.empty())
7803 continue;
7804
7805 double lh = grp.layer_height > 0. ? grp.layer_height :
static_cast<double>(
height);
7806 double cumulative_h = 0.0;
7807 for (int i = 0; i < sub_idx; ++i)
7808 cumulative_h += grp.sub_heights[i];
7809 double default_sub_h = grp.sub_heights[sub_idx];
7810 double default_sub_z = print_z - lh + cumulative_h + default_sub_h;
7811
7815
7817
7818 for (
InstanceToPrint &instance_to_print : mixed_instances_it->second.first) {
7819 const bool use_per_volume = grp.is_gradient
7820 && !grp.per_volume_gradient.empty()
7821 && std::any_of(grp.per_volume_gradient.begin(), grp.per_volume_gradient.end(),
7822 [&](const auto &kv) { return kv.first.obj == &instance_to_print.print_object; });
7823
7824
7825 const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
7826 const auto &inst = instance_to_print.print_object.instances()[instance_to_print.instance_id];
7827
7829 instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id();
7830 m_config.apply(print.default_region_config());
7831 m_config.apply(instance_to_print.print_object.config(),
true);
7832 m_layer = layer_to_print.layer();
7836
7838 gcode += std::string(
"; printing object ") + instance_to_print.print_object.model_object()->name +
7839 " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " +
7840 std::to_string(inst.id) + "\n";
7841 }
7845 std::string("; start printing object, unique label id: ") +
7846 std::to_string(instance_to_print.label_object_id) + "\n" + "M624 " +
7848 } else {
7849 const auto gflavor = print.config().gcode_flavor.value;
7851 m_writer.set_object_start_str(std::string(
"EXCLUDE_OBJECT_START NAME=") +
7854 m_writer.set_object_start_str(std::string(
"M486 S") + std::to_string(inst.unique_id) +
"\n");
7855 }
7856 }
7857 }
7858
7860
7862 std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object,
offset);
7867
7868
7870
7871
7872
7873
7874
7875 struct SubLayerEmitEntry {
7876 double sub_h;
7877 double sub_z;
7878 std::function<bool(size_t region_idx)> region_filter;
7879 bool skip = false;
7880 };
7881 std::vector<SubLayerEmitEntry> emit_plan;
7882
7883 auto compute_sub_zh = [&](double r1, double r2, double &out_sub_h, double &out_sub_z) {
7884 std::vector<double> sub_heights_local(grp.components_0based.size());
7885 for (size_t ci = 0; ci < grp.components_0based.size(); ++ci)
7886 sub_heights_local[ci] = (static_cast<int>(ci) == grp.gradient_first_sorted_idx) ? r1 * lh : r2 * lh;
7887 double cum = 0.0;
7888 for (int ci = 0; ci < sub_idx; ++ci)
7889 cum += sub_heights_local[ci];
7890 out_sub_h = sub_heights_local[sub_idx];
7891 out_sub_z = print_z - lh + cum + out_sub_h;
7892 };
7893
7894 auto gradient_ratios = [](const auto &g) -> std::pair<double, double> {
7895 double t = (g.total_layers > 0) ? (2.0 * g.current_idx + 1.0) / (2.0 * g.total_layers) : 0.5;
7896
7897 double r1 = g.curve.empty()
7898 ? (g.gradient_start + (g.gradient_end - g.gradient_start) * t)
7900 return {r1, 1.0 - r1};
7901 };
7902
7903
7904
7905 auto region_uses_slot = [](
const PrintRegionConfig &rcfg,
unsigned int slot_1b) {
7906 return (unsigned int)rcfg.outer_wall_filament_id.value == slot_1b
7907 || (unsigned int)rcfg.inner_wall_filament_id.value == slot_1b
7908 || (unsigned int)rcfg.sparse_infill_filament_id.value == slot_1b
7909 || (unsigned int)rcfg.internal_solid_filament_id.value == slot_1b
7910 || (unsigned int)rcfg.top_surface_filament_id.value == slot_1b
7911 || (unsigned int)rcfg.bottom_surface_filament_id.value == slot_1b;
7912 };
7913
7914 double obj_sub_z = default_sub_z;
7915
7916 if (use_per_volume) {
7917 const PrintObject *po = &instance_to_print.print_object;
7918 const unsigned int slot_1b = grp.mixed_slot_0based + 1;
7919
7920
7921 std::set<ObjectID> tagged_volumes_present;
7922 bool has_untagged_for_slot = false;
7924 for (size_t r = 0; r < island.by_region.size(); ++r) {
7925 const auto ®ion = island.by_region[r];
7926 if (region.perimeters.empty() && region.infills.empty())
7927 continue;
7928 const PrintRegion &pr = print.get_print_region(r);
7929 if (!region_uses_slot(pr.config(), slot_1b))
7930 continue;
7931 ObjectID vid = pr.gradient_volume_id();
7932 if (vid.valid())
7933 tagged_volumes_present.insert(vid);
7934 else
7935 has_untagged_for_slot = true;
7936 }
7937 }
7938
7939
7940 for (const ObjectID &target_vid : tagged_volumes_present) {
7941 auto vg_it = grp.per_volume_gradient.find({po, target_vid});
7942 if (vg_it == grp.per_volume_gradient.end())
7943 continue;
7944 const auto &vg = vg_it->second;
7945 auto [r1, r2] = gradient_ratios(vg);
7946
7947 bool vol_no_split = false;
7948 bool skip_entry = false;
7949 const size_t n = grp.components_0based.size();
7950 if (n == 2 && vg.current_idx + 1 == vg.total_layers) {
7951 const size_t dom_idx = (r1 >= r2) ? 0 : 1;
7952 const unsigned int first_sorted_comp = grp.components_0based[grp.gradient_first_sorted_idx];
7953 const unsigned int other_comp = grp.components_0based[1 - grp.gradient_first_sorted_idx];
7954 const unsigned int dom_0b = (dom_idx == 0) ? first_sorted_comp : other_comp;
7955 const unsigned int oth_0b = (dom_idx == 0) ? other_comp : first_sorted_comp;
7956 if (dom_0b < oth_0b) {
7957 vol_no_split = true;
7958 if (extruder_id != dom_0b)
7959 skip_entry = true;
7960 }
7961 }
7962
7963 double vol_sub_h = default_sub_h;
7964 double vol_sub_z = default_sub_z;
7965 if (vol_no_split) {
7966 vol_sub_h = lh;
7967 vol_sub_z = print_z;
7968 } else {
7969 compute_sub_zh(r1, r2, vol_sub_h, vol_sub_z);
7970 }
7971
7972 emit_plan.push_back({vol_sub_h, vol_sub_z,
7973 [target_vid, &print](size_t r) {
7974 return print.get_print_region(r).gradient_volume_id() == target_vid;
7975 },
7976 skip_entry});
7977 }
7978
7979
7980 if (has_untagged_for_slot) {
7981 double obj_sub_h = default_sub_h;
7982 auto og_it = grp.per_object_gradient.find(po);
7983 if (og_it != grp.per_object_gradient.end()) {
7984 auto [r1, r2] = gradient_ratios(og_it->second);
7985 compute_sub_zh(r1, r2, obj_sub_h, obj_sub_z);
7986 }
7987 emit_plan.push_back({obj_sub_h, obj_sub_z,
7988 [&print](size_t r) {
7989 return !print.get_print_region(r).gradient_volume_id().valid();
7990 },
7991 false});
7992 }
7993 } else {
7994
7995 double legacy_sub_h = default_sub_h;
7996 obj_sub_z = default_sub_z;
7997 if (grp.is_gradient) {
7998 auto og_it = grp.per_object_gradient.find(&instance_to_print.print_object);
7999 if (og_it != grp.per_object_gradient.end()) {
8000 auto [r1, r2] = gradient_ratios(og_it->second);
8001 compute_sub_zh(r1, r2, legacy_sub_h, obj_sub_z);
8002 }
8003 }
8004 emit_plan.push_back({legacy_sub_h, obj_sub_z, nullptr, false});
8005 }
8006
8007
8008 auto plan_has_infill = [](const std::vector<ObjectByExtruder::Island::Region> &by_region) {
8009 for (const auto &r : by_region)
8010 if (!r.infills.empty())
8011 return true;
8012 return false;
8013 };
8014
8015 for (auto &entry : emit_plan) {
8016 if (entry.skip)
8017 continue;
8021
8022
8023
8025
8027 const auto &src = island.by_region;
8028 std::vector<ObjectByExtruder::Island::Region> subset_storage;
8029 if (entry.region_filter) {
8030 subset_storage.resize(src.size());
8031 for (size_t r = 0; r < src.size(); ++r)
8032 if (entry.region_filter(r))
8033 subset_storage[r] = src[r];
8034 }
8035 const auto &by_region_specific = entry.region_filter ? subset_storage : src;
8036
8037
8038
8039
8041 if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional
8043 && !has_insert_timelapse_gcode && plan_has_infill(by_region_specific)) {
8044 gcode += this->
retract(
false,
false, auto_lift_type,
true);
8045 gcode += insert_timelapse_gcode();
8046 has_insert_timelapse_gcode = true;
8047 }
8051
8053 }
8054 }
8055
8056
8057 if (instance_to_print.object_by_extruder.support && !instance_to_print.object_by_extruder.support->empty()) {
8058 if (use_per_volume) {
8061 }
8062 ExtrusionRole support_role = instance_to_print.object_by_extruder.support_extrusion_role;
8064
8067 }
8068
8069
8070 if (!
m_writer.is_object_start_str_empty()) {
8074 m_writer.set_object_end_str(std::string(
"; stop printing object, unique label id: ") +
8075 std::to_string(instance_to_print.label_object_id) + "\n" +
8076 "M625\n");
8077 } else {
8078 const auto gflavor = print.config().gcode_flavor.value;
8080 m_writer.set_object_end_str(std::string(
"EXCLUDE_OBJECT_END NAME=") +
8083 m_writer.set_object_end_str(std::string(
"M486 S-1\n"));
8084 }
8085 }
8086 }
8087 }
8088
8091 }
8092
8093
8094
8095 if (!layer_tools.mixed_sub_layer_groups.empty()) {
8096 m_writer.add_object_end_labels(gcode);
8099 }
8100
8101 }
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111 if (print.has_belt_brim()) {
8114 const PrintObject *obj = ltp.original_object;
8115 if (obj == nullptr || ! obj->has_belt_brim() || ltp.object_layer == nullptr)
8116 continue;
8117 const size_t ltp_idx = size_t(<p - layers.data());
8118 const unsigned int brim0 = (unsigned int)(obj->belt_brim_filament() - 1);
8119 const size_t i_begin = single_object_instance_idx == size_t(-1) ? 0 : single_object_instance_idx;
8120 const size_t i_end = single_object_instance_idx == size_t(-1) ? obj->instances().size()
8121 : single_object_instance_idx + 1;
8122 for (size_t instance_id = i_begin; instance_id < i_end && instance_id < obj->instances().size(); ++ instance_id) {
8123 if (! belt_brim_emitted.insert({ ltp_idx, instance_id }).second)
8124 continue;
8128 }
8129 }
8131 }
8132
8133 if (first_layer) {
8134 for (auto iter = by_extruder.begin(); iter != by_extruder.end(); ++iter) {
8135 if (!iter->second.empty())
8137 }
8138 }
8139
8140#if 0
8141
8142
8143
8144
8145
8148
8149
8152
8153 object_layer || last_layer);
8154
8155 file.write(gcode);
8156#endif
8157
8158 BOOST_LOG_TRIVIAL(
trace) <<
"Exported layer " <<
layer.id() <<
" print_z " << print_z <<
8160
8161
8163
8164
8165
8166
8167
8170 gcode += this->
retract(
false,
false, auto_lift_type,
true);
8171 }
8172 m_writer.add_object_change_labels(gcode);
8173 gcode += insert_timelapse_gcode();
8174 has_insert_timelapse_gcode = true;
8175 }
8176
8177 if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
8178
8183
8184
8185 if (
m_config.nozzle_diameter.values.size() == 2
8190 }
8192 gcode += this->
retract(
false,
false, auto_lift_type,
true);
8193 }
8194 m_writer.add_object_change_labels(gcode);
8195
8196 gcode += insert_timelapse_gcode();
8197 }
8198
8199 result.gcode = std::move(gcode);
8200 result.cooling_buffer_flush = object_layer || raft_layer || last_layer;
8201 return result;
8202}
std::string set_input_shaping(char axis, float damp, float freq, std::string type) const
Definition GCodeWriter.cpp:641
GCodeConfig config
Definition GCodeWriter.hpp:28
std::string set_jerk_xy(double jerk)
Definition GCodeWriter.cpp:483
std::string set_pressure_advance(double pa, int tool=-1) const
Definition GCodeWriter.cpp:599
static std::string set_temperature(unsigned int temperature, GCodeFlavor flavor, bool wait=false, int tool=-1, std::string comment=std::string())
Definition GCodeWriter.cpp:317
Extruder * filament(size_t extruder_id)
Definition GCodeWriter.hpp:46
std::string set_junction_deviation(double junction_deviation)
Definition GCodeWriter.cpp:581
void compute_farthest_point(const std::vector< LayerToPrint > &layers, int most_used_extruder, const std::map< std::pair< const SupportLayer *, ExtrusionRole >, unsigned int > &support_filaments)
Definition GCode.cpp:6304
bool last_pos_defined() const
Definition GCode.hpp:554
const std::string & instance_name(const PrintInstance &instance)
Definition GCode.cpp:5880
friend std::vector< ObjectByExtruder::Island > & object_islands_by_extruder(std::map< unsigned int, std::vector< ObjectByExtruder > > &by_extruder, unsigned int extruder_id, size_t object_idx, size_t num_objects, size_t num_islands)
Definition GCode.cpp:5600
float interpolate_value_across_layers(float start_value, float end_value, float step=0.0f) const
Definition GCode.cpp:10221
friend ObjectByExtruder & object_by_extruder(std::map< unsigned int, std::vector< ObjectByExtruder > > &by_extruder, unsigned int extruder_id, size_t object_idx, size_t num_objects)
Definition GCode.cpp:5588
std::string extrude_infill(const Print &print, const std::vector< ObjectByExtruder::Island::Region > &by_region, bool ironing)
Definition GCode.cpp:8933
int belt_layer_past_first_layer_band(const Layer *object_layer) const
Definition GCode.cpp:11425
LayerResult process_belt_brim_layer(const Print &print, const std::vector< LayerToPrint > &layers, const LayerTools &layer_tools, const bool last_layer, const size_t single_object_instance_idx, const int most_used_extruder)
Definition GCode.cpp:6127
std::string extrude_perimeters(const Print &print, const std::vector< ObjectByExtruder::Island::Region > &by_region, bool is_first_layer, bool is_infill_first, bool unsupported_loops_only=false)
Definition GCode.cpp:8886
std::pair< const PrintObject *, Point > m_last_obj_copy
Definition GCode.hpp:905
std::vector< InstanceToPrint > sort_print_object_instances(std::vector< ObjectByExtruder > &objects_by_extruder, const std::vector< LayerToPrint > &layers, const std::vector< const PrintInstance * > *ordering, const size_t single_object_instance_idx)
Definition GCode.cpp:5613
std::string generate_object_brim(const Print &print, const PrintObject &object, size_t instance_id, bool first_layer, unsigned int extruder_id, const Layer *object_layer)
Definition GCode.cpp:5991
std::string generate_object_skirt_group(const Print &print, const PrintObject &object, size_t instance_id, const LayerTools &layer_tools, const Layer &layer, unsigned int extruder_id)
Definition GCode.cpp:5969
boost::container::small_vector< int32_t, 3 > ExtruderPerCopy
Definition ToolOrdering.hpp:49
static std::string emit_custom_gcode_per_print_z(GCode &gcodegen, const CustomGCode::Item *custom_gcode, unsigned int current_extruder_id, unsigned int first_extruder_id, const PrintConfig &config)
Definition GCode.cpp:5669
void trace(unsigned int level, const char *message)
Definition utils.cpp:247
@ Calib_Vol_speed_Tower
Definition calib.hpp:31
@ Calib_Input_shaping_freq
Definition calib.hpp:34
@ Calib_Temp_Tower
Definition calib.hpp:30
@ Calib_Cornering
Definition calib.hpp:36
@ Calib_Input_shaping_damp
Definition calib.hpp:35
@ Calib_VFA_Tower
Definition calib.hpp:32
@ stCombined
Definition PrintConfig.hpp:474
@ zhtSlope
Definition PrintConfig.hpp:585
@ zhtSpiral
Definition PrintConfig.hpp:586
bool is_inner_wall(const ExtrusionEntity &entity)
Definition ExtrusionEntity.hpp:167
static bool prepares_overhang_estimator(const Layer &layer, bool overhang_fan, OverhangSpeed overhang_speed)
Definition GCode.cpp:5074
@ NormalLift
Definition PrintConfig.hpp:430
std::vector< size_t > order_points_with_strategy(const Points &points, PrintOrder print_order, const Point *start_near)
Definition OrderingStrategies.cpp:501
static std::vector< T > get_flush_volumes_matrix(const std::vector< T > &fv_matrix, size_t extruder_id=-1, size_t nozzle_nums=1)
Definition PrintConfig.hpp:2685
@ tlTraditional
Definition PrintConfig.hpp:469
std::vector< ArithmeticOnly< T > > grid(const T &start, const T &stop, const T &stride)
A set of equidistant values starting from 'start' (inclusive), ending in the closest multiple of 'str...
Definition MTUtils.hpp:127
@ ByLayer
Definition PrintConfig.hpp:311
std::vector< size_t > chain_points(const Points &points, const Point *start_near)
Definition ShortestPath.cpp:1565
static bool overhang_fan_enabled(const PrintConfig &config, bool cooling_markers)
Definition GCode.cpp:5123
@ AsObjectList
Definition PrintConfig.hpp:320
void sort_remove_duplicates(std::vector< T > &vec)
Definition libslic3r.h:231
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
double sample_gradient_curve(const GradientCurve &c, double t)
Definition FilamentMixer.cpp:357
PrinterStructure
Definition PrintConfig.hpp:557
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157
zaa_minimize_perimeter_height gcode_label_objects((ConfigOptionBool, exclude_object))((ConfigOptionFloat
Type
Definition GCode.hpp:616
@ PERIMETERS
Definition GCode.hpp:617
@ INFILL
Definition GCode.hpp:618