diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index dc9c157a8..de1079927 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -954,61 +954,84 @@ void ToolOrdering::mark_skirt_layers(const PrintConfig &config, coordf_t max_lay // BBS: replace model custom gcode with current plate custom gcode static CustomGCode::Info custom_gcode_per_print_z; -void ToolOrdering::assign_custom_gcodes(const Print &print) +void ToolOrdering::assign_custom_gcodes(const Print& print) { - // Only valid for non-sequential print. - assert(print.config().print_sequence == PrintSequence::ByLayer); + // Only valid for non-sequential print. + assert(print.config().print_sequence == PrintSequence::ByLayer); custom_gcode_per_print_z = print.model().get_curr_plate_custom_gcodes(); - if (custom_gcode_per_print_z.gcodes.empty()) - return; + if (custom_gcode_per_print_z.gcodes.empty()) + return; // BBS - auto num_filaments = unsigned(print.config().filament_diameter.size()); - CustomGCode::Mode mode = - (num_filaments == 1) ? CustomGCode::SingleExtruder : - print.object_extruders().size() == 1 ? CustomGCode::MultiAsSingle : CustomGCode::MultiExtruder; - CustomGCode::Mode model_mode = print.model().get_curr_plate_custom_gcodes().mode; - std::vector extruder_printing_above(num_filaments, false); - auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin(); - // Tool changes and color changes will be ignored, if the model's tool/color changes were entered in mm mode and the print is in non mm mode - // or vice versa. - bool ignore_tool_and_color_changes = (mode == CustomGCode::MultiExtruder) != (model_mode == CustomGCode::MultiExtruder); - // If printing on a single extruder machine, make the tool changes trigger color change (M600) events. - bool tool_changes_as_color_changes = mode == CustomGCode::SingleExtruder && model_mode == CustomGCode::MultiAsSingle; + auto num_filaments = unsigned(print.config().filament_diameter.size()); + CustomGCode::Mode mode = + (num_filaments == 1) ? CustomGCode::SingleExtruder : + print.object_extruders().size() == 1 ? CustomGCode::MultiAsSingle : CustomGCode::MultiExtruder; + CustomGCode::Mode model_mode = print.model().get_curr_plate_custom_gcodes().mode; + auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin(); + // Tool changes and color changes will be ignored, if the model's tool/color changes were entered in mm mode and the print is in non mm mode + // or vice versa. + bool ignore_tool_and_color_changes = (mode == CustomGCode::MultiExtruder) != (model_mode == CustomGCode::MultiExtruder); + // If printing on a single extruder machine, make the tool changes trigger color change (M600) events. + bool tool_changes_as_color_changes = mode == CustomGCode::SingleExtruder && model_mode == CustomGCode::MultiAsSingle; - // take the half of the minimum layer height gap as episilon - double layer_height_episilon = std::numeric_limits::max(); - for (auto it_prev = m_layer_tools.begin(), it_next = std::next(m_layer_tools.begin()); it_next != m_layer_tools.end(); it_prev = it_next, ++it_next) - layer_height_episilon = std::min(layer_height_episilon, it_next->print_z - it_prev->print_z); - layer_height_episilon *= 0.5; + auto apply_custom_gcode_to_layer = [mode, + ignore_tool_and_color_changes, + tool_changes_as_color_changes, + num_filaments](LayerTools& lt, const std::vector& extruder_printing_above, const CustomGCode::Item& item) + { + bool color_change = item.type == CustomGCode::ColorChange; + bool tool_change = item.type == CustomGCode::ToolChange; + bool pause_or_custom_gcode = !color_change && !tool_change; + bool apply_color_change = !ignore_tool_and_color_changes && + // If it is color change, it will actually be useful as the exturder above will print. + // BBS + (color_change ? + mode == CustomGCode::SingleExtruder || + (item.extruder <= int(num_filaments) && extruder_printing_above[unsigned(item.extruder - 1)]) : + tool_change && tool_changes_as_color_changes); + if (pause_or_custom_gcode || apply_color_change) + lt.custom_gcode = &item; + }; + + std::unordered_map> extruder_print_above_by_layer; + { + std::vector extruder_printing_above(num_filaments, false); + for (auto iter = m_layer_tools.rbegin(); iter != m_layer_tools.rend(); ++iter) { + for (unsigned int i : iter->extruders) + extruder_printing_above[i] = true; + int layer_idx = iter.base() - m_layer_tools.begin(); + extruder_print_above_by_layer.emplace(layer_idx, extruder_printing_above); + } + } - auto it_lt = m_layer_tools.rbegin(); for (auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin(); custom_gcode_it != custom_gcode_per_print_z.gcodes.rend(); ++custom_gcode_it) { if (custom_gcode_it->type == CustomGCode::ToolChange) continue; - for (; it_lt != m_layer_tools.rend(); ++it_lt) { - for (unsigned int i : it_lt->extruders) - extruder_printing_above[i] = true; - if (std::abs(it_lt->print_z - custom_gcode_it->print_z) < layer_height_episilon) { - const CustomGCode::Item &custom_gcode = *custom_gcode_it; - // The custom G-code applies to the current layer. - bool color_change = custom_gcode.type == CustomGCode::ColorChange; - bool tool_change = custom_gcode.type == CustomGCode::ToolChange; - bool pause_or_custom_gcode = ! color_change && ! tool_change; - bool apply_color_change = ! ignore_tool_and_color_changes && - // If it is color change, it will actually be useful as the exturder above will print. - // BBS - (color_change ? - mode == CustomGCode::SingleExtruder || - (custom_gcode.extruder <= int(num_filaments) && extruder_printing_above[unsigned(custom_gcode.extruder - 1)]) : - tool_change && tool_changes_as_color_changes); - if (pause_or_custom_gcode || apply_color_change) - it_lt->custom_gcode = &custom_gcode; - ++it_lt; - break; - } + auto layer_it_upper = std::upper_bound(m_layer_tools.begin(), m_layer_tools.end(), custom_gcode_it->print_z, [](double z,const LayerTools& lt) { + return z < lt.print_z; + }); + + int upper_layer_idx = layer_it_upper - m_layer_tools.begin(); + if (layer_it_upper == m_layer_tools.begin()) { + apply_custom_gcode_to_layer(*layer_it_upper, extruder_print_above_by_layer[0], *custom_gcode_it); + } + else if (layer_it_upper == m_layer_tools.end()) { + auto layer_it_lower = std::prev(layer_it_upper); + int lower_layer_idx = layer_it_lower - m_layer_tools.begin(); + apply_custom_gcode_to_layer(*layer_it_lower, extruder_print_above_by_layer[lower_layer_idx], *custom_gcode_it); + } + else { + auto layer_it_lower = std::prev(layer_it_upper); + int lower_layer_idx = layer_it_lower - m_layer_tools.begin(); + double gap_to_lower = std::fabs(custom_gcode_it->print_z - layer_it_lower->print_z); + double gap_to_upper = std::fabs(custom_gcode_it->print_z - layer_it_upper->print_z); + if (gap_to_lower < gap_to_upper) + apply_custom_gcode_to_layer(*layer_it_lower, extruder_print_above_by_layer[lower_layer_idx], *custom_gcode_it); + else + apply_custom_gcode_to_layer(*layer_it_upper, extruder_print_above_by_layer[upper_layer_idx], *custom_gcode_it); } } }