diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 8746c2a30ae..6036ec01789 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1152,6 +1152,8 @@ void GCode::_do_export(Print &print, FILE *file) m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm; m_last_width = GCodeAnalyzer::Default_Width; m_last_height = GCodeAnalyzer::Default_Height; + print.m_print_statistics.color_extruderid_to_used_filament.clear(); + print.m_print_statistics.color_extruderid_to_used_weight.clear(); // How many times will be change_layer() called? // change_layer() in turn increments the progress bar status. @@ -1440,7 +1442,7 @@ void GCode::_do_export(Print &print, FILE *file) for (const LayerToPrint <p : layers_to_print) { std::vector lrs; lrs.emplace_back(std::move(ltp)); - this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), nullptr, *print_object_instance_sequential_active - object.instances().data()); + this->process_layer(file, print, print.m_print_statistics, lrs, tool_ordering.tools_for_layer(ltp.print_z()), nullptr, *print_object_instance_sequential_active - object.instances().data()); print.throw_if_canceled(); } #ifdef HAS_PRESSURE_EQUALIZER @@ -1493,7 +1495,7 @@ void GCode::_do_export(Print &print, FILE *file) const LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first); if (m_wipe_tower && layer_tools.has_wipe_tower) m_wipe_tower->next_layer(); - this->process_layer(file, print, layer.second, layer_tools, &print_object_instances_ordering, size_t(-1)); + this->process_layer(file, print, print.m_print_statistics, layer.second, layer_tools, &print_object_instances_ordering, size_t(-1)); print.throw_if_canceled(); } #ifdef HAS_PRESSURE_EQUALIZER @@ -1809,81 +1811,97 @@ std::vector GCode::sort_print_object_instances( return out; } -namespace ProcessLayer +std::string GCode::emit_custom_gcode_per_print_z( + const CustomGCode::Item *custom_gcode, + // ID of the first extruder printing this layer. + unsigned int first_extruder_id, + const Print &print, + PrintStatistics &stats) { - - static std::string emit_custom_gcode_per_print_z( - const CustomGCode::Item *custom_gcode, - // ID of the first extruder printing this layer. - unsigned int first_extruder_id, - bool single_extruder_printer) - { - std::string gcode; + bool single_extruder_printer = print.config().nozzle_diameter.size() == 1; + std::string gcode; - if (custom_gcode != nullptr) { - // Extruder switches are processed by LayerTools, they should be filtered out. - assert(custom_gcode->gcode != ToolChangeCode); - - const std::string &custom_code = custom_gcode->gcode; - bool color_change = custom_code == ColorChangeCode; - bool tool_change = custom_code == ToolChangeCode; - // Tool Change is applied as Color Change for a single extruder printer only. - assert(! tool_change || single_extruder_printer); - - std::string pause_print_msg; - int m600_extruder_before_layer = -1; - if (color_change && custom_gcode->extruder > 0) - m600_extruder_before_layer = custom_gcode->extruder - 1; - else if (custom_code == PausePrintCode) - pause_print_msg = custom_gcode->color; - - // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count - if (color_change || tool_change) - { - // Color Change or Tool Change as Color Change. - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n"; - // add tag for time estimator - gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n"; - - if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != m600_extruder_before_layer - // && !MMU1 - ) { - //! FIXME_in_fw show message during print pause - gcode += "M601\n"; // pause print - gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; - } - else { - gcode += ColorChangeCode; - gcode += "\n"; - } - } - else - { - if (custom_code == PausePrintCode) // Pause print - { - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n"; - //! FIXME_in_fw show message during print pause - if (!pause_print_msg.empty()) - gcode += "M117 " + pause_print_msg + "\n"; - // add tag for time estimator - gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; - } - else // custom Gcode - { - // add tag for analyzer - gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n"; - // add tag for time estimator - //gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n"; - } - gcode += custom_code + "\n"; - } - } + if (custom_gcode != nullptr) { + // Extruder switches are processed by LayerTools, they should be filtered out. + assert(custom_gcode->gcode != ToolChangeCode); + + const std::string &custom_code = custom_gcode->gcode; + bool color_change = custom_code == ColorChangeCode; + bool tool_change = custom_code == ToolChangeCode; + // Tool Change is applied as Color Change for a single extruder printer only. + assert(! tool_change || single_extruder_printer); + + std::string pause_print_msg; + int m600_extruder_before_layer = -1; + if (color_change && custom_gcode->extruder > 0) + m600_extruder_before_layer = custom_gcode->extruder - 1; + else if (custom_code == PausePrintCode) + pause_print_msg = custom_gcode->color; + + if (color_change) { + //update stats : weight + double previously_extruded = 0; + for (const auto& tuple : stats.color_extruderid_to_used_weight) + if (tuple.first == this->m_writer.extruder()->id()) + previously_extruded += tuple.second; + double extruded = this->m_writer.extruder()->filament_density() * this->m_writer.extruder()->extruded_volume(); + stats.color_extruderid_to_used_weight.emplace_back(this->m_writer.extruder()->id(), extruded - previously_extruded); + + //update stats : length + previously_extruded = 0; + for (const auto& tuple : stats.color_extruderid_to_used_filament) + if (tuple.first == this->m_writer.extruder()->id()) + previously_extruded += tuple.second; + stats.color_extruderid_to_used_filament.emplace_back(this->m_writer.extruder()->id(), this->m_writer.extruder()->used_filament() - previously_extruded); + } + + // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count + if (color_change || tool_change) + { - return gcode; - } -} // namespace ProcessLayer + // Color Change or Tool Change as Color Change. + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n"; + // add tag for time estimator + gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n"; + + if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != m600_extruder_before_layer + // && !MMU1 + ) { + //! FIXME_in_fw show message during print pause + gcode += "M601\n"; // pause print + gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; + } + else { + gcode += ColorChangeCode; + gcode += "\n"; + } + } + else + { + if (custom_code == PausePrintCode) // Pause print + { + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n"; + //! FIXME_in_fw show message during print pause + if (!pause_print_msg.empty()) + gcode += "M117 " + pause_print_msg + "\n"; + // add tag for time estimator + gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; + } + else // custom Gcode + { + // add tag for analyzer + gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n"; + // add tag for time estimator + //gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n"; + } + gcode += custom_code + "\n"; + } + } + + return gcode; +} namespace Skirt { static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) @@ -1956,11 +1974,12 @@ namespace Skirt { // and performing the extruder specific extrusions together. void GCode::process_layer( // Write into the output file. - FILE *file, - const Print &print, + FILE *file, + const Print &print, + PrintStatistics &print_stat, // Set of object & print layers of the same PrintObject and with the same print_z. - const std::vector &layers, - const LayerTools &layer_tools, + const std::vector &layers, + const LayerTools &layer_tools, // Pairs of PrintObject index and its instance index. const std::vector *ordering, // If set to size_t(-1), then print all copies of all objects. @@ -2054,7 +2073,7 @@ void GCode::process_layer( if (single_object_instance_idx == size_t(-1)) { // Normal (non-sequential) print. - gcode += ProcessLayer::emit_custom_gcode_per_print_z(layer_tools.custom_gcode, first_extruder_id, print.config().nozzle_diameter.size() == 1); + gcode += this->emit_custom_gcode_per_print_z(layer_tools.custom_gcode, first_extruder_id, print, print_stat); } // 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 580f0477dbf..45b4e848738 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -200,6 +200,9 @@ class GCode : ExtrusionVisitorConst { // append full config to the given string static void append_full_config(const Print& print, std::string& str); + // called by porcess_layer, do the color change / custom gcode + std::string emit_custom_gcode_per_print_z(const CustomGCode::Item* custom_gcode, unsigned int first_extruder_id, const Print& print, PrintStatistics& stats); + // Object and support extrusions of the same PrintObject at the same print_z. // public, so that it could be accessed by free helper functions from GCode.cpp struct LayerToPrint @@ -225,6 +228,7 @@ class GCode : ExtrusionVisitorConst { // Write into the output file. FILE *file, const Print &print, + PrintStatistics &print_stat, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, const LayerTools &layer_tools, diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp index 9ba6cc3971f..ba481e17c6d 100644 --- a/src/libslic3r/GCodeTimeEstimator.cpp +++ b/src/libslic3r/GCodeTimeEstimator.cpp @@ -772,7 +772,7 @@ namespace Slic3r { std::vector> ret; float total_time = 0.0f; - for (auto t : m_custom_gcode_times) + for (const std::pair &t : m_custom_gcode_times) { std::string time = _get_time_dhm(t.second); if (include_remaining) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 154f974fd6f..fdef4075981 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -321,10 +321,12 @@ struct PrintStatistics std::vector> estimated_normal_custom_gcode_print_times; std::vector> estimated_silent_custom_gcode_print_times; double total_used_filament; + std::vector> color_extruderid_to_used_filament; double total_extruded_volume; double total_cost; int total_toolchanges; double total_weight; + std::vector> color_extruderid_to_used_weight; double total_wipe_tower_cost; double total_wipe_tower_filament; std::map filament_stats; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index eff186f9850..b5cdcca4efa 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1241,10 +1241,36 @@ void Sidebar::update_sliced_info_sizer() (ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, ps.total_wipe_tower_filament / 1000) : wxString::Format("%.2f", ps.total_used_filament / 1000); - p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); + if (ps.color_extruderid_to_used_filament.size() > 0) { + double total_length = 0; + for (int i = 0; i < ps.color_extruderid_to_used_filament.size(); i++) { + new_label+= from_u8((boost::format("\n - %1% %2%") % _utf8(L("Color")) % i ).str()); + total_length += ps.color_extruderid_to_used_filament[i].second; + info_text += wxString::Format("\n%.2f (%.2f)", ps.color_extruderid_to_used_filament[i].second / 1000, total_length / 1000); + } + new_label += from_u8((boost::format("\n - %1% %2%") % _utf8(L("Color")) % ps.color_extruderid_to_used_filament.size()).str()); + info_text += wxString::Format("\n%.2f (%.2f)", (ps.total_used_filament - total_length) / 1000, ps.total_used_filament / 1000); + } + p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume)); - p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight)); + + if (ps.color_extruderid_to_used_weight.size() > 0 && ps.total_weight != 0) { + new_label = _(L("Used Filament (g)")); + info_text = wxString::Format("%.2f", ps.total_weight); + double total_weight = 0; + for (int i = 0; i < ps.color_extruderid_to_used_weight.size(); i++) { + new_label += from_u8((boost::format("\n - %1% %2%") % _utf8(L("Color")) % i).str()); + total_weight += ps.color_extruderid_to_used_weight[i].second; + info_text += (ps.color_extruderid_to_used_weight[i].second == 0 ? "\nN/A": wxString::Format("\n%.2f", ps.color_extruderid_to_used_weight[i].second / 1000)) + + (total_weight == 0 ? " (N/A)" : wxString::Format(" (%.2f)", total_weight / 1000)); + } + new_label += from_u8((boost::format("\n - %1% %2%") % _utf8(L("Color")) % ps.color_extruderid_to_used_weight.size()).str()); + info_text += ((ps.total_weight - total_weight / 1000) == 0 ? "\nN/A" : wxString::Format("\n%.2f", (ps.total_weight - total_weight / 1000))) + + wxString::Format(" (%.2f)", ps.total_weight); + p->sliced_info->SetTextAndShow(siFilament_g, info_text, new_label); + }else + p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight), _(L("Used Filament (g)"))); new_label = _(L("Cost")); if (is_wipe_tower)