From f7164db68e760c9df9a937b5b3674c9f8bcd3be8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 17 Jul 2020 08:27:23 +0200 Subject: [PATCH] GCodeViewer -> Added estimated printing times for move types --- src/libslic3r/GCode.cpp | 28 +---- src/libslic3r/GCode/GCodeProcessor.cpp | 51 ++++++++- src/libslic3r/GCode/GCodeProcessor.hpp | 36 +++--- src/libslic3r/Print.hpp | 19 +++- src/slic3r/GUI/GCodeViewer.cpp | 148 ++++++++++++++++++------- 5 files changed, 195 insertions(+), 87 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 47448954c..9e365f955 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -705,27 +705,6 @@ namespace Slic3r { } #if ENABLE_GCODE_VIEWER -// free functions called by GCode::do_export() -namespace DoExport { - static void update_print_stats_estimated_times( - const GCodeProcessor& processor, - const bool silent_time_estimator_enabled, - PrintStatistics& print_statistics) - { - print_statistics.estimated_normal_print_time = processor.get_time_dhm(GCodeProcessor::ETimeMode::Normal); - print_statistics.estimated_normal_custom_gcode_print_times = processor.get_custom_gcode_times(GCodeProcessor::ETimeMode::Normal, true); - if (silent_time_estimator_enabled) { - print_statistics.estimated_silent_print_time = processor.get_time_dhm(GCodeProcessor::ETimeMode::Stealth); - print_statistics.estimated_silent_custom_gcode_print_times = processor.get_custom_gcode_times(GCodeProcessor::ETimeMode::Stealth, true); - } - else { - print_statistics.estimated_silent_print_time = "N/A"; - print_statistics.estimated_silent_custom_gcode_print_times.clear(); - } - } - -} // namespace DoExport - void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb) #else void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb) @@ -787,11 +766,12 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_ } #if ENABLE_GCODE_VIEWER + print->m_print_statistics.clear_time_estimates(); m_processor.process_file(path_tmp); - if (result != nullptr) + if (result != nullptr) { *result = std::move(m_processor.extract_result()); - - DoExport::update_print_stats_estimated_times(m_processor, m_silent_time_estimator_enabled, print->m_print_statistics); + m_processor.update_print_stats_estimated_times(print->m_print_statistics); + } #endif // ENABLE_GCODE_VIEWER GCodeTimeEstimator::PostProcessData normal_data = m_normal_time_estimator.get_post_process_data(); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 7174e5e36..7f8efc53f 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1,5 +1,6 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" +#include "libslic3r/Print.hpp" #include "GCodeProcessor.hpp" #include @@ -161,6 +162,7 @@ void GCodeProcessor::TimeMachine::reset() prev.reset(); gcode_time.reset(); blocks = std::vector(); + std::fill(moves_time.begin(), moves_time.end(), 0.0f); } void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time) @@ -264,9 +266,11 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks) size_t n_blocks_process = blocks.size() - keep_last_n_blocks; // m_g1_times.reserve(m_g1_times.size() + n_blocks_process); for (size_t i = 0; i < n_blocks_process; ++i) { - float block_time = blocks[i].time(); + const TimeBlock& block = blocks[i]; + float block_time = block.time(); time += block_time; gcode_time.cache += block_time; + moves_time[static_cast(block.move_type)] += block_time; // if (block.g1_line_id >= 0) // m_g1_times.emplace_back(block.g1_line_id, time); @@ -388,12 +392,31 @@ void GCodeProcessor::process_file(const std::string& filename) #endif // ENABLE_GCODE_VIEWER_STATISTICS } +void GCodeProcessor::update_print_stats_estimated_times(PrintStatistics& print_statistics) +{ + print_statistics.estimated_normal_print_time = get_time(GCodeProcessor::ETimeMode::Normal); + print_statistics.estimated_normal_custom_gcode_print_times = get_custom_gcode_times(GCodeProcessor::ETimeMode::Normal, true); + print_statistics.estimated_normal_moves_times = get_moves_time(GCodeProcessor::ETimeMode::Normal); + if (m_time_processor.machines[static_cast(GCodeProcessor::ETimeMode::Stealth)].enabled) { + print_statistics.estimated_silent_print_time = get_time(GCodeProcessor::ETimeMode::Stealth); + print_statistics.estimated_silent_custom_gcode_print_times = get_custom_gcode_times(GCodeProcessor::ETimeMode::Stealth, true); + print_statistics.estimated_silent_moves_times = get_moves_time(GCodeProcessor::ETimeMode::Stealth); + } + else { + print_statistics.estimated_silent_print_time = 0.0f; + print_statistics.estimated_silent_custom_gcode_print_times.clear(); + print_statistics.estimated_silent_moves_times.clear(); + } +} + +float GCodeProcessor::get_time(ETimeMode mode) const +{ + return (mode < ETimeMode::Count) ? m_time_processor.machines[static_cast(mode)].time : 0.0f; +} + std::string GCodeProcessor::get_time_dhm(ETimeMode mode) const { - std::string ret = "N/A"; - if (mode < ETimeMode::Count) - ret = short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].time)); - return ret; + return (mode < ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].time)) : std::string("N/A"); } std::vector>> GCodeProcessor::get_custom_gcode_times(ETimeMode mode, bool include_remaining) const @@ -411,6 +434,19 @@ std::vector>> GCodeProcesso return ret; } +std::vector> GCodeProcessor::get_moves_time(ETimeMode mode) const +{ + std::vector> ret; + if (mode < ETimeMode::Count) { + for (size_t i = 0; i < m_time_processor.machines[static_cast(mode)].moves_time.size(); ++i) { + float time = m_time_processor.machines[static_cast(mode)].moves_time[i]; + if (time > 0.0f) + ret.push_back({ static_cast(i), time }); + } + } + return ret; +} + void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) { /* std::cout << line.raw() << std::endl; */ @@ -668,6 +704,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (max_abs_delta == 0.0f) return; + EMoveType type = move_type(delta_pos); + // time estimate section auto move_length = [](const AxisCoords& delta_pos) { float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]); @@ -696,6 +734,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) minimum_feedrate(static_cast(i), m_feedrate); TimeBlock block; + block.move_type = type; block.distance = distance; // calculates block cruise feedrate @@ -827,7 +866,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) } // store move - store_move_vertex(move_type(delta_pos)); + store_move_vertex(type); } void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 9878eea9d..214ed3d91 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -13,6 +13,8 @@ namespace Slic3r { + struct PrintStatistics; + class GCodeProcessor { public: @@ -57,6 +59,20 @@ namespace Slic3r { }; public: + enum class EMoveType : unsigned char + { + Noop, + Retract, + Unretract, + Tool_change, + Color_change, + Pause_Print, + Custom_GCode, + Travel, + Extrude, + Count + }; + struct FeedrateProfile { float entry{ 0.0f }; // mm/s @@ -84,6 +100,7 @@ namespace Slic3r { bool nominal_length{ false }; }; + EMoveType move_type{ EMoveType::Noop }; float distance{ 0.0f }; // mm float acceleration{ 0.0f }; // mm/s^2 float max_entry_speed{ 0.0f }; // mm/s @@ -135,6 +152,7 @@ namespace Slic3r { State prev; CustomGCodeTime gcode_time; std::vector blocks; + std::array(EMoveType::Count)> moves_time; void reset(); @@ -169,20 +187,6 @@ namespace Slic3r { }; public: - enum class EMoveType : unsigned char - { - Noop, - Retract, - Unretract, - Tool_change, - Color_change, - Pause_Print, - Custom_GCode, - Travel, - Extrude, - Count - }; - struct MoveVertex { EMoveType type{ EMoveType::Noop }; @@ -255,9 +259,13 @@ namespace Slic3r { // Process the gcode contained in the file with the given filename void process_file(const std::string& filename); + void update_print_stats_estimated_times(PrintStatistics& print_statistics); + float get_time(ETimeMode mode) const; std::string get_time_dhm(ETimeMode mode) const; std::vector>> get_custom_gcode_times(ETimeMode mode, bool include_remaining) const; + std::vector> get_moves_time(ETimeMode mode) const; + private: void process_gcode_line(const GCodeReader::GCodeLine& line); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 4a0657061..748411cd7 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -304,14 +304,16 @@ struct PrintStatistics { PrintStatistics() { clear(); } #if ENABLE_GCODE_VIEWER - std::string estimated_normal_print_time; - std::string estimated_silent_print_time; + float estimated_normal_print_time; + float estimated_silent_print_time; std::string estimated_normal_print_time_str; std::string estimated_silent_print_time_str; std::vector>> estimated_normal_custom_gcode_print_times; std::vector>> estimated_silent_custom_gcode_print_times; std::vector>> estimated_normal_custom_gcode_print_times_str; std::vector>> estimated_silent_custom_gcode_print_times_str; + std::vector> estimated_normal_moves_times; + std::vector> estimated_silent_moves_times; #else std::string estimated_normal_print_time; std::string estimated_silent_print_time; @@ -336,6 +338,8 @@ struct PrintStatistics void clear() { #if ENABLE_GCODE_VIEWER + estimated_normal_print_time_str.clear(); + estimated_silent_print_time_str.clear(); estimated_normal_custom_gcode_print_times_str.clear(); estimated_silent_custom_gcode_print_times_str.clear(); #else @@ -353,6 +357,17 @@ struct PrintStatistics total_wipe_tower_filament = 0.; filament_stats.clear(); } + +#if ENABLE_GCODE_VIEWER + void clear_time_estimates() { + estimated_normal_print_time = 0.0f; + estimated_silent_print_time = 0.0f; + estimated_normal_custom_gcode_print_times.clear(); + estimated_silent_custom_gcode_print_times.clear(); + estimated_normal_moves_times.clear(); + estimated_silent_moves_times.clear(); + } +#endif //ENABLE_GCODE_VIEWER }; typedef std::vector PrintObjectPtrs; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 27b0db83f..db95c2b22 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1717,19 +1717,16 @@ void GCodeViewer::render_time_estimate() const return; const PrintStatistics& ps = wxGetApp().plater()->fff_print().print_statistics(); - if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A") - return; - - if (ps.estimated_normal_print_time.empty() && ps.estimated_silent_print_time.empty()) + if (ps.estimated_normal_print_time <= 0.0f && ps.estimated_silent_print_time <= 0.0f) return; ImGuiWrapper& imgui = *wxGetApp().imgui(); - using Time = std::pair; - using TimesList = std::vector>; + using Times = std::pair; + using TimesList = std::vector>; - // helper structure containig the data needed to render the items - struct Item + // helper structure containig the data needed to render the time items + struct PartialTime { enum class EType : unsigned char { @@ -1741,12 +1738,13 @@ void GCodeViewer::render_time_estimate() const int extruder_id; Color color1; Color color2; - Time time; + Times times; }; - using Items = std::vector; + using PartialTimes = std::vector; - auto append_mode = [this, &imgui](const std::string& time_str, const Items& items) { - auto append_partial_times = [this, &imgui](const Items& items) { + auto append_mode = [this, &imgui](float total_time, const PartialTimes& items, + const std::vector>& moves_time) { + auto append_partial_times = [this, &imgui](const PartialTimes& items) { using Headers = std::vector; const Headers headers = { _u8L("Event"), @@ -1754,19 +1752,19 @@ void GCodeViewer::render_time_estimate() const _u8L("Duration") }; using Offsets = std::array; - auto calc_offsets = [this, &headers](const Items& items) { + auto calc_offsets = [this, &headers](const PartialTimes& items) { Offsets ret = { ImGui::CalcTextSize(headers[0].c_str()).x, ImGui::CalcTextSize(headers[1].c_str()).x }; - for (const Item& item : items) { + for (const PartialTime& item : items) { std::string label; switch (item.type) { - case Item::EType::Print: { label = _u8L("Print"); break; } - case Item::EType::Pause: { label = _u8L("Pause"); break; } - case Item::EType::ColorChange: { label = _u8L("Color change"); break; } + case PartialTime::EType::Print: { label = _u8L("Print"); break; } + case PartialTime::EType::Pause: { label = _u8L("Pause"); break; } + case PartialTime::EType::ColorChange: { label = _u8L("Color change"); break; } } ret[0] = std::max(ret[0], ImGui::CalcTextSize(label.c_str()).x); - ret[1] = std::max(ret[1], ImGui::CalcTextSize(short_time(get_time_dhms(item.time.second)).c_str()).x); + ret[1] = std::max(ret[1], ImGui::CalcTextSize(short_time(get_time_dhms(item.times.second)).c_str()).x); } const ImGuiStyle& style = ImGui::GetStyle(); @@ -1774,7 +1772,7 @@ void GCodeViewer::render_time_estimate() const ret[1] += ret[0] + style.ItemSpacing.x; return ret; }; - auto append_color = [this, &imgui](const Color& color1, const Color& color2, Offsets& offsets, const Time& time) { + auto append_color = [this, &imgui](const Color& color1, const Color& color2, Offsets& offsets, const Times& times) { ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); imgui.text(_u8L("Color change")); ImGui::PopStyleColor(); @@ -1797,7 +1795,7 @@ void GCodeViewer::render_time_estimate() const ImGui::GetColorU32({ color2[0], color2[1], color2[2], 1.0f })); #endif // USE_ICON_HEXAGON ImGui::SameLine(offsets[0]); - imgui.text(short_time(get_time_dhms(time.second - time.first))); + imgui.text(short_time(get_time_dhms(times.second - times.first))); }; if (items.empty()) @@ -1815,48 +1813,116 @@ void GCodeViewer::render_time_estimate() const ImGui::PopStyleColor(); ImGui::Separator(); - for (const Item& item : items) { + for (const PartialTime& item : items) { switch (item.type) { - case Item::EType::Print: + case PartialTime::EType::Print: { ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); imgui.text(_u8L("Print")); ImGui::PopStyleColor(); ImGui::SameLine(offsets[0]); - imgui.text(short_time(get_time_dhms(item.time.second))); + imgui.text(short_time(get_time_dhms(item.times.second))); ImGui::SameLine(offsets[1]); - imgui.text(short_time(get_time_dhms(item.time.first))); + imgui.text(short_time(get_time_dhms(item.times.first))); break; } - case Item::EType::Pause: + case PartialTime::EType::Pause: { ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); imgui.text(_u8L("Pause")); ImGui::PopStyleColor(); ImGui::SameLine(offsets[0]); - imgui.text(short_time(get_time_dhms(item.time.second - item.time.first))); + imgui.text(short_time(get_time_dhms(item.times.second - item.times.first))); break; } - case Item::EType::ColorChange: + case PartialTime::EType::ColorChange: { - append_color(item.color1, item.color2, offsets, item.time); + append_color(item.color1, item.color2, offsets, item.times); break; } } } }; + auto append_move_times = [this, &imgui](float total_time, const std::vector>& moves_time) { + using Headers = std::vector; + const Headers headers = { + _u8L("Type"), + _u8L("Time"), + _u8L("Percentage") + }; + auto move_type_label = [](GCodeProcessor::EMoveType type) { + switch (type) + { + case GCodeProcessor::EMoveType::Noop: { return _u8L("Noop"); } + case GCodeProcessor::EMoveType::Retract: { return _u8L("Retraction"); } + case GCodeProcessor::EMoveType::Unretract: { return _u8L("Unretraction"); } + case GCodeProcessor::EMoveType::Tool_change: { return _u8L("Tool change"); } + case GCodeProcessor::EMoveType::Color_change: { return _u8L("Color change"); } + case GCodeProcessor::EMoveType::Pause_Print: { return _u8L("Pause print"); } + case GCodeProcessor::EMoveType::Custom_GCode: { return _u8L("Custom GCode"); } + case GCodeProcessor::EMoveType::Travel: { return _u8L("Travel"); } + case GCodeProcessor::EMoveType::Extrude: { return _u8L("Extrusion"); } + default: { return _u8L("Unknown"); } + } + }; + using Offsets = std::array; + auto calc_offsets = [this, &headers, move_type_label](const std::vector>& moves_time) { + Offsets ret = { ImGui::CalcTextSize(headers[0].c_str()).x, ImGui::CalcTextSize(headers[1].c_str()).x }; + for (const auto& [type, time] : moves_time) { + ret[0] = std::max(ret[0], ImGui::CalcTextSize(move_type_label(type).c_str()).x); + ret[1] = std::max(ret[1], ImGui::CalcTextSize(short_time(get_time_dhms(time)).c_str()).x); + } + + const ImGuiStyle& style = ImGui::GetStyle(); + ret[0] += 2.0f * style.ItemSpacing.x; + ret[1] += ret[0] + style.ItemSpacing.x; + return ret; + }; + + + if (moves_time.empty()) + return; + + if (!ImGui::CollapsingHeader(_u8L("Moves Time").c_str())) + return; + + Offsets offsets = calc_offsets(moves_time); + + ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); + imgui.text(headers[0]); + ImGui::SameLine(offsets[0]); + imgui.text(headers[1]); + ImGui::SameLine(offsets[1]); + imgui.text(headers[2]); + ImGui::PopStyleColor(); + ImGui::Separator(); + + for (const auto& [type, time] : moves_time) { + ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); + imgui.text(move_type_label(type)); + ImGui::PopStyleColor(); + ImGui::SameLine(offsets[0]); + imgui.text(short_time(get_time_dhms(time))); + ImGui::SameLine(offsets[1]); + char buf[64]; + ::sprintf(buf, "%.2f%%", 100.0f * time / total_time); + ImGui::TextUnformatted(buf); + } + }; + ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); imgui.text(_u8L("Time") + ":"); ImGui::PopStyleColor(); ImGui::SameLine(); - imgui.text(time_str); + imgui.text(short_time(get_time_dhms(total_time))); append_partial_times(items); + append_move_times(total_time, moves_time); }; - auto generate_items = [this](const TimesList& times) { - std::vector items; + auto generate_partial_times = [this](const TimesList& times) { + PartialTimes items; std::vector custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; int extruders_count = wxGetApp().extruders_edited_cnt(); @@ -1872,8 +1938,8 @@ void GCodeViewer::render_time_estimate() const { auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; }); if (it != custom_gcode_per_print_z.end()) { - items.push_back({ Item::EType::Print, it->extruder, Color(), Color(), time_rec.second }); - items.push_back({ Item::EType::Pause, it->extruder, Color(), Color(), time_rec.second }); + items.push_back({ PartialTime::EType::Print, it->extruder, Color(), Color(), time_rec.second }); + items.push_back({ PartialTime::EType::Pause, it->extruder, Color(), Color(), time_rec.second }); custom_gcode_per_print_z.erase(it); } break; @@ -1882,14 +1948,14 @@ void GCodeViewer::render_time_estimate() const { auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; }); if (it != custom_gcode_per_print_z.end()) { - items.push_back({ Item::EType::Print, it->extruder, Color(), Color(), time_rec.second }); - items.push_back({ Item::EType::ColorChange, it->extruder, last_color[it->extruder - 1], decode_color(it->color), time_rec.second }); + items.push_back({ PartialTime::EType::Print, it->extruder, Color(), Color(), time_rec.second }); + items.push_back({ PartialTime::EType::ColorChange, it->extruder, last_color[it->extruder - 1], decode_color(it->color), time_rec.second }); last_color[it->extruder - 1] = decode_color(it->color); last_extruder_id = it->extruder; custom_gcode_per_print_z.erase(it); } else - items.push_back({ Item::EType::Print, last_extruder_id, Color(), Color(), time_rec.second }); + items.push_back({ PartialTime::EType::Print, last_extruder_id, Color(), Color(), time_rec.second }); break; } @@ -1905,22 +1971,22 @@ void GCodeViewer::render_time_estimate() const ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(-1.0f, 0.5f * static_cast(cnv_size.get_height()))); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::SetNextWindowBgAlpha(0.6f); - imgui.begin(std::string("Time_estimate_2"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove); + imgui.begin(std::string("Time_estimate"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove); // title imgui.title(_u8L("Estimated printing time")); // mode tabs ImGui::BeginTabBar("mode_tabs"); - if (ps.estimated_normal_print_time != "N/A") { + if (ps.estimated_normal_print_time > 0.0f) { if (ImGui::BeginTabItem(_u8L("Normal").c_str())) { - append_mode(ps.estimated_normal_print_time, generate_items(ps.estimated_normal_custom_gcode_print_times)); + append_mode(ps.estimated_normal_print_time, generate_partial_times(ps.estimated_normal_custom_gcode_print_times), ps.estimated_normal_moves_times); ImGui::EndTabItem(); } } - if (ps.estimated_silent_print_time != "N/A") { + if (ps.estimated_silent_print_time > 0.0f) { if (ImGui::BeginTabItem(_u8L("Stealth").c_str())) { - append_mode(ps.estimated_silent_print_time, generate_items(ps.estimated_silent_custom_gcode_print_times)); + append_mode(ps.estimated_silent_print_time, generate_partial_times(ps.estimated_silent_custom_gcode_print_times), ps.estimated_silent_moves_times); ImGui::EndTabItem(); } }