ENH: add timelapse gcode for multi_extruder

and add most used_extruder for print by object
jira:none

Change-Id: I021069e865992828b098d73c0d704ba7edbd55d8
This commit is contained in:
zhimin.zeng 2024-12-31 09:30:46 +08:00 committed by lane.wei
parent 1ae969d08f
commit ae62f7b8e4
5 changed files with 59 additions and 44 deletions

View File

@ -1864,7 +1864,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
std::vector<int> first_non_support_filaments;
std::vector<const PrintInstance*> print_object_instances_ordering;
std::vector<const PrintInstance*>::const_iterator print_object_instance_sequential_active;
std::vector<int> extruder_count;
std::vector<const PrintInstance *>::const_iterator first_has_extrude_print_object;
//resize
first_non_support_filaments.resize(print.config().nozzle_diameter.size(), -1);
@ -1880,13 +1879,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
bool find_fist_non_support_filament = false;
for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) {
tool_ordering = ToolOrdering(*(*print_object_instance_sequential_active)->print_object, initial_extruder_id);
//get extruder count
std::vector<int> object_extruder_count = tool_ordering.cal_most_used_extruder(print.config());
if (extruder_count.empty())
extruder_count = object_extruder_count;
else
for (size_t extruder_id = 0; extruder_id < object_extruder_count.size(); extruder_id++)
extruder_count[extruder_id] += object_extruder_count[extruder_id];
tool_ordering.sort_and_build_data(*(*print_object_instance_sequential_active)->print_object,initial_extruder_id);
if (!find_fist_non_support_filament && tool_ordering.first_extruder() != (unsigned int) -1) {
@ -1911,7 +1903,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// Find tool ordering for all the objects at once, and the initial extruder ID.
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
tool_ordering = print.tool_ordering();
extruder_count = tool_ordering.cal_most_used_extruder(print.config());
tool_ordering.cal_most_used_extruder(print.config());
tool_ordering.assign_custom_gcodes(print);
if (tool_ordering.all_extruders().empty())
// No object to print was found, cancel the G-code export.
@ -1967,15 +1959,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
file.write(m_writer.set_additional_fan(0));
}
//set key for most used extruder
//count most used extruder
int max_count_extruder = 0;
for (int extruder_id = 1; extruder_id < extruder_count.size(); extruder_id++) {
if (extruder_count[extruder_id] >= extruder_count[max_count_extruder])
max_count_extruder = extruder_id;
}
m_placeholder_parser.set("most_used_physical_extruder_id", print.config().physical_extruder_map.values[max_count_extruder]);
// Let the start-up script prime the 1st printing tool.
auto match_physical_extruder_for_each_filament = [](std::vector<int> &filaments, const FullPrintConfig &config) {
@ -2288,6 +2271,7 @@ 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.
tool_ordering.cal_most_used_extruder(print.config());
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file,
prime_extruder);
{
@ -2602,7 +2586,7 @@ void GCode::process_layers(
//BBS
check_placeholder_parser_failed();
print.throw_if_canceled();
GCode::LayerResult res = this->process_layer(print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1));
GCode::LayerResult res = this->process_layer(print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, tool_ordering.get_most_used_extruder(), size_t(-1));
res.gcode_store_pos = layer_to_print_idx - 1;
return std::move(res);
}
@ -2740,7 +2724,7 @@ void GCode::process_layers(
//BBS
check_placeholder_parser_failed();
print.throw_if_canceled();
GCode::LayerResult res = this->process_layer(print, {std::move(layer)}, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx, prime_extruder);
GCode::LayerResult res = this->process_layer(print, {std::move(layer)}, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, tool_ordering.get_most_used_extruder(), single_object_idx, prime_extruder);
res.gcode_store_pos = layer_to_print_idx - 1;
return std::move(res);
}
@ -3302,6 +3286,7 @@ GCode::LayerResult GCode::process_layer(
const bool last_layer,
// Pairs of PrintObject index and its instance index.
const std::vector<const PrintInstance*> *ordering,
const int most_used_extruder,
// If set to size_t(-1), then print all copies of all objects.
// Otherwise print a single copy of a single object.
const size_t single_object_instance_idx,
@ -3399,7 +3384,7 @@ GCode::LayerResult GCode::process_layer(
PrinterStructure printer_structure = m_config.printer_structure.value;
bool need_insert_timelapse_gcode_for_traditional = false;
if (printer_structure == PrinterStructure::psI3 &&
if ((printer_structure == PrinterStructure::psI3 || m_config.nozzle_diameter.values.size() == 2)&&
!m_spiral_vase &&
(!m_wipe_tower || !m_wipe_tower->enable_timelapse_print()) &&
print.config().print_sequence == PrintSequence::ByLayer) {
@ -3408,10 +3393,13 @@ GCode::LayerResult GCode::process_layer(
bool has_insert_timelapse_gcode = false;
bool has_wipe_tower = (layer_tools.has_wipe_tower && m_wipe_tower);
auto insert_timelapse_gcode = [this, print_z, &print]() -> std::string {
int physical_extruder_id = print.config().physical_extruder_map.get_at(most_used_extruder);
auto insert_timelapse_gcode = [this, print_z, &print, &physical_extruder_id]() -> std::string {
std::string gcode_res;
if (!print.config().time_lapse_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
@ -3424,7 +3412,9 @@ GCode::LayerResult GCode::process_layer(
gcode += this->change_layer(print_z); // this will increase m_layer_index
m_layer = &layer;
m_object_layer_over_raft = false;
if (printer_structure == PrinterStructure::psI3 && !need_insert_timelapse_gcode_for_traditional && !m_spiral_vase && print.config().print_sequence == PrintSequence::ByLayer) {
if ((printer_structure == PrinterStructure::psI3 || m_config.nozzle_diameter.values.size() == 2)
&& !need_insert_timelapse_gcode_for_traditional && !m_spiral_vase
&& print.config().print_sequence == PrintSequence::ByLayer) {
std::string timepals_gcode = insert_timelapse_gcode();
gcode += timepals_gcode;
m_writer.set_current_position_clear(false);
@ -3438,6 +3428,7 @@ GCode::LayerResult GCode::process_layer(
}
if (! print.config().layer_change_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += this->placeholder_parser_process("layer_change_gcode",
@ -3785,20 +3776,29 @@ GCode::LayerResult GCode::process_layer(
if (has_wipe_tower) {
if (!m_wipe_tower->is_empty_wipe_tower_gcode(*this, extruder_id, extruder_id == layer_tools.extruders.back())) {
if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
gcode += this->retract(false, false, LiftType::NormalLift);
m_writer.add_object_change_labels(gcode);
std::string timepals_gcode = insert_timelapse_gcode();
gcode += timepals_gcode;
m_writer.set_current_position_clear(false);
//BBS: check whether custom gcode changes the z position. Update if changed
double temp_z_after_timepals_gcode;
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
Vec3d pos = m_writer.get_position();
pos(2) = temp_z_after_timepals_gcode;
m_writer.set_position(pos);
bool should_insert = true;
if (m_config.nozzle_diameter.values.size() == 2){
if (!writer().filament() || get_extruder_id(writer().filament()->id()) != most_used_extruder) {
should_insert = false;
}
}
if (should_insert) {
gcode += this->retract(false, false, LiftType::NormalLift);
m_writer.add_object_change_labels(gcode);
std::string timepals_gcode = insert_timelapse_gcode();
gcode += timepals_gcode;
m_writer.set_current_position_clear(false);
// BBS: check whether custom gcode changes the z position. Update if changed
double temp_z_after_timepals_gcode;
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
Vec3d pos = m_writer.get_position();
pos(2) = temp_z_after_timepals_gcode;
m_writer.set_position(pos);
}
has_insert_timelapse_gcode = true;
}
has_insert_timelapse_gcode = true;
}
gcode += m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
}
@ -4011,7 +4011,8 @@ GCode::LayerResult GCode::process_layer(
//BBS: for first layer, we always print wall firstly to get better bed adhesive force
//This behaviour is same with cura
if (is_infill_first && !first_layer) {
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure == PrinterStructure::psI3
&& !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
gcode += this->retract(false, false, LiftType::NormalLift);
if (!temp_start_str.empty() && m_writer.empty_object_start_str()) {
std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
@ -4040,7 +4041,8 @@ GCode::LayerResult GCode::process_layer(
gcode += this->extrude_perimeters(print, by_region_specific);
} else {
gcode += this->extrude_perimeters(print, by_region_specific);
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure == PrinterStructure::psI3
&& !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
gcode += this->retract(false, false, LiftType::NormalLift);
if (!temp_start_str.empty() && m_writer.empty_object_start_str()) {
std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
@ -4126,8 +4128,8 @@ GCode::LayerResult GCode::process_layer(
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
log_memory_info();
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
if (m_support_traditional_timelapse)
if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
if (m_support_traditional_timelapse && printer_structure == PrinterStructure::psI3)
m_support_traditional_timelapse = false;
gcode += this->retract(false, false, LiftType::NormalLift);

View File

@ -340,6 +340,8 @@ private:
const bool last_layer,
// Pairs of PrintObject index and its instance index.
const std::vector<const PrintInstance*> *ordering,
// idientiy timelapse pos
const int most_used_extruder,
// If set to size_t(-1), then print all copies of all objects.
// Otherwise print a single copy of a single object.
const size_t single_object_idx = size_t(-1),

View File

@ -801,7 +801,7 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
}
}
std::vector<int> ToolOrdering::cal_most_used_extruder(const PrintConfig &config)
void ToolOrdering::cal_most_used_extruder(const PrintConfig &config)
{
// record
std::vector<int> extruder_count;
@ -819,7 +819,14 @@ std::vector<int> ToolOrdering::cal_most_used_extruder(const PrintConfig &config)
extruder_count[extruder_id]++;
}
}
return extruder_count;
// set key for most used extruder
// count most used extruder
most_used_extruder = 0;
for (int extruder_id = 1; extruder_id < extruder_count.size(); extruder_id++) {
if (extruder_count[extruder_id] >= extruder_count[most_used_extruder])
most_used_extruder = extruder_id;
}
}
//BBS: find first non support filament

View File

@ -235,6 +235,7 @@ public:
std::vector<LayerTools>& layer_tools() { return m_layer_tools; }
bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().has_wipe_tower; }
int get_most_used_extruder() const { return most_used_extruder; }
/*
* called in single extruder mode, the value in map are all 0
* called in dual extruder mode, the value in map will be 0 or 1
@ -246,7 +247,7 @@ public:
// should be called after doing reorder
FilamentChangeStats get_filament_change_stats(FilamentChangeMode mode);
std::vector<int> cal_most_used_extruder(const PrintConfig &config);
void cal_most_used_extruder(const PrintConfig &config);
bool cal_non_support_filaments(const PrintConfig &config,
unsigned int & first_non_support_filament,
std::vector<int> & initial_non_support_filaments,
@ -281,6 +282,8 @@ private:
FilamentChangeStats m_stats_by_single_extruder;
FilamentChangeStats m_stats_by_multi_extruder_curr;
FilamentChangeStats m_stats_by_multi_extruder_best;
int most_used_extruder;
};
} // namespace SLic3r

View File

@ -4350,7 +4350,8 @@ void TabPrinter::toggle_options()
}
if (m_active_page->title() == "Machine gcode") {
toggle_line("time_lapse_gcode", m_preset_bundle->printers.get_edited_preset().config.opt_enum<PrinterStructure>("printer_structure") == PrinterStructure::psI3);
toggle_line("time_lapse_gcode",
m_preset_bundle->printers.get_edited_preset().config.opt_enum<PrinterStructure>("printer_structure") == PrinterStructure::psI3 || m_preset_bundle->get_printer_extruder_count() == 2);
}
wxString extruder_number;
long val = 1;