From 487ac0423e1dc254bd93ab34b133acf8d4036a88 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 20 Feb 2020 17:32:46 +0100 Subject: [PATCH] Implemented time estimation for PausePrint (#3544) DoubleSlider: fixed get_color_for_color_change_tick() --- src/libslic3r/CustomGCode.hpp | 6 ++ src/libslic3r/GCode.cpp | 6 +- src/libslic3r/GCodeTimeEstimator.cpp | 92 +++++++++++++++++++--------- src/libslic3r/GCodeTimeEstimator.hpp | 22 ++++--- src/libslic3r/Print.hpp | 8 +-- src/slic3r/GUI/DoubleSlider.cpp | 4 +- src/slic3r/GUI/GLCanvas3D.cpp | 7 ++- src/slic3r/GUI/Plater.cpp | 41 +++++++++---- 8 files changed, 127 insertions(+), 59 deletions(-) diff --git a/src/libslic3r/CustomGCode.hpp b/src/libslic3r/CustomGCode.hpp index e54599ca6..a5ef1cc2e 100644 --- a/src/libslic3r/CustomGCode.hpp +++ b/src/libslic3r/CustomGCode.hpp @@ -13,6 +13,12 @@ static constexpr char ColorChangeCode[] = "M600"; static constexpr char PausePrintCode[] = "M601"; static constexpr char ToolChangeCode[] = "tool_change"; +enum CustomGcodeType +{ + cgtColorChange, + cgtPausePrint, +}; + namespace CustomGCode { struct Item diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0b7ef4ff7..b7a7c18c4 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1033,9 +1033,9 @@ namespace DoExport { print_statistics.clear(); print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/(); print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A"; - print_statistics.estimated_normal_color_print_times = normal_time_estimator.get_color_times_dhms(true); + print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true); if (silent_time_estimator_enabled) - print_statistics.estimated_silent_color_print_times = silent_time_estimator.get_color_times_dhms(true); + print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true); print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges); if (! extruders.empty()) { std::pair out_filament_used_mm ("; filament used [mm] = ", 0); @@ -1823,7 +1823,7 @@ namespace ProcessLayer if (!pause_print_msg.empty()) gcode += "M117 " + pause_print_msg + "\n"; // add tag for time estimator - //gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; + gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; } else // custom Gcode { diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp index 3ef325aef..44b6a3d24 100644 --- a/src/libslic3r/GCodeTimeEstimator.cpp +++ b/src/libslic3r/GCodeTimeEstimator.cpp @@ -174,6 +174,7 @@ namespace Slic3r { const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER"; const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE"; + const std::string GCodeTimeEstimator::Pause_Print_Tag = "PRINT_PAUSE"; GCodeTimeEstimator::GCodeTimeEstimator(EMode mode) : m_mode(mode) @@ -212,8 +213,8 @@ namespace Slic3r { } _calculate_time(); - if (m_needs_color_times && (m_color_time_cache != 0.0f)) - m_color_times.push_back(m_color_time_cache); + if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f)) + m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache }); #if ENABLE_MOVE_STATS _log_moves_stats(); @@ -230,8 +231,8 @@ namespace Slic3r { _calculate_time(); - if (m_needs_color_times && (m_color_time_cache != 0.0f)) - m_color_times.push_back(m_color_time_cache); + if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f)) + m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache }); #if ENABLE_MOVE_STATS _log_moves_stats(); @@ -245,8 +246,8 @@ namespace Slic3r { m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2)); _calculate_time(); - if (m_needs_color_times && (m_color_time_cache != 0.0f)) - m_color_times.push_back(m_color_time_cache); + if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f)) + m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache }); #if ENABLE_MOVE_STATS _log_moves_stats(); @@ -263,8 +264,8 @@ namespace Slic3r { m_parser.parse_line(line, action); _calculate_time(); - if (m_needs_color_times && (m_color_time_cache != 0.0f)) - m_color_times.push_back(m_color_time_cache); + if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f)) + m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache}); #if ENABLE_MOVE_STATS _log_moves_stats(); @@ -351,8 +352,8 @@ namespace Slic3r { } // check tags - // remove color change tag - if (gcode_line == "; " + Color_Change_Tag) + // remove Color_Change_Tag and Pause_Print_Tag + if (gcode_line == "; " + Color_Change_Tag || gcode_line == "; " + Pause_Print_Tag) continue; // replaces placeholders for initial line M73 with the real lines @@ -717,25 +718,26 @@ namespace Slic3r { return _get_time_minutes(get_time()); } - std::vector GCodeTimeEstimator::get_color_times() const + std::vector> GCodeTimeEstimator::get_custom_gcode_times() const { - return m_color_times; + return m_custom_gcode_times; } std::vector GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const { std::vector ret; float total_time = 0.0f; - for (float t : m_color_times) +// for (float t : m_color_times) + for (auto t : m_custom_gcode_times) { - std::string time = _get_time_dhms(t); + std::string time = _get_time_dhms(t.second); if (include_remaining) { time += " ("; time += _get_time_dhms(m_time - total_time); time += ")"; } - total_time += t; + total_time += t.second; ret.push_back(time); } return ret; @@ -745,20 +747,42 @@ namespace Slic3r { { std::vector ret; float total_time = 0.0f; - for (float t : m_color_times) +// for (float t : m_color_times) + for (auto t : m_custom_gcode_times) { - std::string time = _get_time_minutes(t); + std::string time = _get_time_minutes(t.second); if (include_remaining) { time += " ("; time += _get_time_minutes(m_time - total_time); time += ")"; } - total_time += t; + total_time += t.second; } return ret; } + std::vector> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const + { + std::vector> ret; + + float total_time = 0.0f; + for (auto t : m_custom_gcode_times) + { + std::string time = _get_time_dhm(t.second); + if (include_remaining) + { + time += " ("; + time += _get_time_dhm(m_time - total_time); + time += ")"; + } + total_time += t.second; + ret.push_back({t.first, time}); + } + + return ret; + } + // Return an estimate of the memory consumed by the time estimator. size_t GCodeTimeEstimator::memory_used() const { @@ -791,9 +815,9 @@ namespace Slic3r { m_last_st_synchronized_block_id = -1; - m_needs_color_times = false; - m_color_times.clear(); - m_color_time_cache = 0.0f; + m_needs_custom_gcode_times = false; + m_custom_gcode_times.clear(); + m_custom_gcode_time_cache = 0.0f; } void GCodeTimeEstimator::_reset_time() @@ -814,7 +838,7 @@ namespace Slic3r { _recalculate_trapezoids(); m_time += get_additional_time(); - m_color_time_cache += get_additional_time(); + m_custom_gcode_time_cache += get_additional_time(); for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i) { @@ -835,7 +859,7 @@ namespace Slic3r { it->second.time += block_time; #endif // ENABLE_MOVE_STATS - m_color_time_cache += block_time; + m_custom_gcode_time_cache += block_time; } m_last_st_synchronized_block_id = (int)m_blocks.size() - 1; @@ -1466,26 +1490,34 @@ namespace Slic3r { { std::string comment = line.comment(); - // color change tag + // Color_Change_Tag size_t pos = comment.find(Color_Change_Tag); if (pos != comment.npos) { - _process_color_change_tag(); + _process_custom_gcode_tag(cgtColorChange); + return true; + } + + // Pause_Print_Tag + pos = comment.find(Pause_Print_Tag); + if (pos != comment.npos) + { + _process_custom_gcode_tag(cgtPausePrint); return true; } return false; } - void GCodeTimeEstimator::_process_color_change_tag() + void GCodeTimeEstimator::_process_custom_gcode_tag(CustomGcodeType code) { PROFILE_FUNC(); - m_needs_color_times = true; + m_needs_custom_gcode_times = true; _calculate_time(); - if (m_color_time_cache != 0.0f) + if (m_custom_gcode_time_cache != 0.0f) { - m_color_times.push_back(m_color_time_cache); - m_color_time_cache = 0.0f; + m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache}); + m_custom_gcode_time_cache = 0.0f; } } diff --git a/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp index 496b992d8..7c364d9eb 100644 --- a/src/libslic3r/GCodeTimeEstimator.hpp +++ b/src/libslic3r/GCodeTimeEstimator.hpp @@ -4,6 +4,7 @@ #include "libslic3r.h" #include "PrintConfig.hpp" #include "GCodeReader.hpp" +#include "CustomGCode.hpp" #define ENABLE_MOVE_STATS 0 @@ -23,6 +24,7 @@ namespace Slic3r { static const std::string Silent_Last_M73_Output_Placeholder_Tag; static const std::string Color_Change_Tag; + static const std::string Pause_Print_Tag; enum EMode : unsigned char { @@ -240,10 +242,10 @@ namespace Slic3r { int m_last_st_synchronized_block_id; float m_time; // s - // data to calculate color print times - bool m_needs_color_times; - std::vector m_color_times; - float m_color_time_cache; + // data to calculate custom code times + bool m_needs_custom_gcode_times; + std::vector> m_custom_gcode_times; + float m_custom_gcode_time_cache; #if ENABLE_MOVE_STATS MovesStatsMap _moves_stats; @@ -369,8 +371,8 @@ namespace Slic3r { // Returns the estimated time, in minutes (integer) std::string get_time_minutes() const; - // Returns the estimated time, in seconds, for each color - std::vector get_color_times() const; + // Returns the estimated time, in seconds, for each custom gcode + std::vector> get_custom_gcode_times() const; // Returns the estimated time, in format DDd HHh MMm SSs, for each color // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" @@ -380,6 +382,10 @@ namespace Slic3r { // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" std::vector get_color_times_minutes(bool include_remaining) const; + // Returns the estimated time, in format DDd HHh MMm, for each custom_gcode + // If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)" + std::vector> get_custom_gcode_times_dhm(bool include_remaining) const; + // Return an estimate of the memory consumed by the time estimator. size_t memory_used() const; @@ -460,8 +466,8 @@ namespace Slic3r { // Returns true if any tag has been processed bool _process_tags(const GCodeReader::GCodeLine& line); - // Processes color change tag - void _process_color_change_tag(); + // Processes ColorChangeTag and PausePrintTag + void _process_custom_gcode_tag(CustomGcodeType code); // Simulates firmware st_synchronize() call void _simulate_st_synchronize(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 7b326472e..4f9f9ad1e 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -302,8 +302,8 @@ struct PrintStatistics PrintStatistics() { clear(); } std::string estimated_normal_print_time; std::string estimated_silent_print_time; - std::vector estimated_normal_color_print_times; - std::vector estimated_silent_color_print_times; + std::vector> estimated_normal_custom_gcode_print_times; + std::vector> estimated_silent_custom_gcode_print_times; double total_used_filament; double total_extruded_volume; double total_cost; @@ -323,8 +323,8 @@ struct PrintStatistics void clear() { estimated_normal_print_time.clear(); estimated_silent_print_time.clear(); - estimated_normal_color_print_times.clear(); - estimated_silent_color_print_times.clear(); + estimated_normal_custom_gcode_print_times.clear(); + estimated_silent_custom_gcode_print_times.clear(); total_used_filament = 0.; total_extruded_volume = 0.; total_cost = 0.; diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 357c143c4..9afbb73ed 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -696,9 +696,11 @@ std::string Control::get_color_for_color_change_tick(std::set::const_i if (it_n->gcode == ToolChangeCode) { is_tool_change = true; if (it_n->extruder == it->extruder) - return m_extruder_colors[it->extruder-1]; // return a color for a specific extruder from the colors list + return it->color; break; } + if (it_n->gcode == ColorChangeCode && it_n->extruder == it->extruder) + return it->color; } if (!is_tool_change && it->extruder == def_extruder) return it->color; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b5319a2f1..496de1d54 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -982,12 +982,17 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code"))); int cnt = custom_gcode_per_print_z.size(); + int color_change_idx = color_cnt - extruders_cnt; for (int i = cnt-1; i >= 0; --i) if (custom_gcode_per_print_z[i].gcode == ColorChangeCode) { ::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float)); color_pos += 4; color_in_pos -= 4; - cp_legend_items.emplace_back((boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str()); + + // create label for color change item + std::string id_str = std::to_string(color_change_idx--) + ": "; + + cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str()); } } } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bc28b62e0..8296e15d5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1252,23 +1252,40 @@ void Sidebar::update_sliced_info_sizer() else { new_label = _(L("Estimated printing time")) +" :"; info_text = ""; - if (ps.estimated_normal_print_time != "N/A") { - new_label += wxString::Format("\n - %s", _(L("normal mode"))); - info_text += wxString::Format("\n%s", ps.estimated_normal_print_time); - for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i) + wxString str_color = _(L("Color")); + wxString str_pause = _(L("Pause")); + + auto fill_labels = [str_color, str_pause](const std::vector>& times, + wxString& new_label, wxString& info_text) + { + int color_change_count = 0; + for (auto time : times) + if (time.first == cgtColorChange) + color_change_count++; + + for (int i = (int)times.size() - 1; i >= 0; --i) { - new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1); - info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]); + if (i == 0 || times[i - 1].first == cgtPausePrint) + new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count); + else if (times[i - 1].first == cgtColorChange) + new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count--); + + if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint) + new_label += wxString::Format(" -> %s", str_pause); + + info_text += wxString::Format("\n%s", times[i].second); } + }; + + if (ps.estimated_normal_print_time != "N/A") { + new_label += wxString::Format("\n - %s", _(L("normal mode"))); + info_text += wxString::Format("\n%s", ps.estimated_normal_print_time); + fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text); } if (ps.estimated_silent_print_time != "N/A") { - new_label += wxString::Format("\n - %s", _(L("stealth mode"))); + new_label += wxString::Format("\n - %s", _(L("stealth mode"))); info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); - for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i) - { - new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1); - info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]); - } + fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text); } p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label); }