mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	GCodeViewer -> Added estimated printing times for extrusion roles
This commit is contained in:
		
							parent
							
								
									5d845c7a25
								
							
						
					
					
						commit
						b03ae392c5
					
				
					 4 changed files with 144 additions and 54 deletions
				
			
		|  | @ -163,6 +163,7 @@ void GCodeProcessor::TimeMachine::reset() | |||
|     gcode_time.reset(); | ||||
|     blocks = std::vector<TimeBlock>(); | ||||
|     std::fill(moves_time.begin(), moves_time.end(), 0.0f); | ||||
|     std::fill(roles_time.begin(), roles_time.end(), 0.0f); | ||||
| } | ||||
| 
 | ||||
| void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time) | ||||
|  | @ -271,6 +272,7 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks) | |||
|         time += block_time; | ||||
|         gcode_time.cache += block_time; | ||||
|         moves_time[static_cast<size_t>(block.move_type)] += block_time; | ||||
|         roles_time[static_cast<size_t>(block.role)] += block_time; | ||||
| 
 | ||||
| //        if (block.g1_line_id >= 0)
 | ||||
| //            m_g1_times.emplace_back(block.g1_line_id, time);
 | ||||
|  | @ -397,15 +399,18 @@ void GCodeProcessor::update_print_stats_estimated_times(PrintStatistics& print_s | |||
|     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); | ||||
|     print_statistics.estimated_normal_roles_times = get_roles_time(GCodeProcessor::ETimeMode::Normal); | ||||
|     if (m_time_processor.machines[static_cast<size_t>(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); | ||||
|         print_statistics.estimated_silent_roles_times = get_roles_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(); | ||||
|         print_statistics.estimated_silent_roles_times.clear(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -447,6 +452,19 @@ std::vector<std::pair<GCodeProcessor::EMoveType, float>> GCodeProcessor::get_mov | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(ETimeMode mode) const | ||||
| { | ||||
|     std::vector<std::pair<ExtrusionRole, float>> ret; | ||||
|     if (mode < ETimeMode::Count) { | ||||
|         for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) { | ||||
|             float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i]; | ||||
|             if (time > 0.0f) | ||||
|                 ret.push_back({ static_cast<ExtrusionRole>(i), time }); | ||||
|         } | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) | ||||
| { | ||||
| /* std::cout << line.raw() << std::endl; */ | ||||
|  | @ -735,6 +753,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) | |||
| 
 | ||||
|         TimeBlock block; | ||||
|         block.move_type = type; | ||||
|         block.role = m_extrusion_role; | ||||
|         block.distance = distance; | ||||
| 
 | ||||
|         // calculates block cruise feedrate
 | ||||
|  |  | |||
|  | @ -101,6 +101,7 @@ namespace Slic3r { | |||
|             }; | ||||
| 
 | ||||
|             EMoveType move_type{ EMoveType::Noop }; | ||||
|             ExtrusionRole role{ erNone }; | ||||
|             float distance{ 0.0f }; // mm
 | ||||
|             float acceleration{ 0.0f }; // mm/s^2
 | ||||
|             float max_entry_speed{ 0.0f }; // mm/s
 | ||||
|  | @ -153,6 +154,7 @@ namespace Slic3r { | |||
|             CustomGCodeTime gcode_time; | ||||
|             std::vector<TimeBlock> blocks; | ||||
|             std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time; | ||||
|             std::array<float, static_cast<size_t>(ExtrusionRole::erCount)> roles_time; | ||||
| 
 | ||||
|             void reset(); | ||||
| 
 | ||||
|  | @ -265,6 +267,7 @@ namespace Slic3r { | |||
|         std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(ETimeMode mode, bool include_remaining) const; | ||||
| 
 | ||||
|         std::vector<std::pair<EMoveType, float>> get_moves_time(ETimeMode mode) const; | ||||
|         std::vector<std::pair<ExtrusionRole, float>> get_roles_time(ETimeMode mode) const; | ||||
| 
 | ||||
|     private: | ||||
|         void process_gcode_line(const GCodeReader::GCodeLine& line); | ||||
|  |  | |||
|  | @ -314,6 +314,8 @@ struct PrintStatistics | |||
|     std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> estimated_silent_custom_gcode_print_times_str; | ||||
|     std::vector<std::pair<GCodeProcessor::EMoveType, float>> estimated_normal_moves_times; | ||||
|     std::vector<std::pair<GCodeProcessor::EMoveType, float>> estimated_silent_moves_times; | ||||
|     std::vector<std::pair<ExtrusionRole, float>> estimated_normal_roles_times; | ||||
|     std::vector<std::pair<ExtrusionRole, float>> estimated_silent_roles_times; | ||||
| #else | ||||
|     std::string                     estimated_normal_print_time; | ||||
|     std::string                     estimated_silent_print_time; | ||||
|  | @ -366,6 +368,8 @@ struct PrintStatistics | |||
|         estimated_silent_custom_gcode_print_times.clear(); | ||||
|         estimated_normal_moves_times.clear(); | ||||
|         estimated_silent_moves_times.clear(); | ||||
|         estimated_normal_roles_times.clear(); | ||||
|         estimated_silent_roles_times.clear(); | ||||
|     } | ||||
| #endif //ENABLE_GCODE_VIEWER
 | ||||
| }; | ||||
|  |  | |||
|  | @ -1724,6 +1724,8 @@ void GCodeViewer::render_time_estimate() const | |||
| 
 | ||||
|     using Times = std::pair<float, float>; | ||||
|     using TimesList = std::vector<std::pair<CustomGCode::Type, Times>>; | ||||
|     using Headers = std::vector<std::string>; | ||||
|     using ColumnOffsets = std::array<float, 2>; | ||||
| 
 | ||||
|     // helper structure containig the data needed to render the time items
 | ||||
|     struct PartialTime | ||||
|  | @ -1743,17 +1745,14 @@ void GCodeViewer::render_time_estimate() const | |||
|     using PartialTimes = std::vector<PartialTime>; | ||||
| 
 | ||||
|     auto append_mode = [this, &imgui](float total_time, const PartialTimes& items, | ||||
|         const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& moves_time) { | ||||
|         auto append_partial_times = [this, &imgui](const PartialTimes& items) { | ||||
|             using Headers = std::vector<std::string>; | ||||
|             const Headers headers = { | ||||
|                 _u8L("Event"), | ||||
|                 _u8L("Remaining"), | ||||
|                 _u8L("Duration") | ||||
|             }; | ||||
|             using Offsets = std::array<float, 2>; | ||||
|         const Headers& partial_times_headers, | ||||
|         const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& moves_time, | ||||
|         const Headers& moves_headers, | ||||
|         const std::vector<std::pair<ExtrusionRole, float>>& roles_time, | ||||
|         const Headers& roles_headers) { | ||||
|         auto append_partial_times = [this, &imgui](const PartialTimes& items, const Headers& headers) { | ||||
|             auto calc_offsets = [this, &headers](const PartialTimes& items) { | ||||
|                 Offsets ret = { ImGui::CalcTextSize(headers[0].c_str()).x, ImGui::CalcTextSize(headers[1].c_str()).x }; | ||||
|                 ColumnOffsets ret = { ImGui::CalcTextSize(headers[0].c_str()).x, ImGui::CalcTextSize(headers[1].c_str()).x }; | ||||
|                 for (const PartialTime& item : items) { | ||||
|                     std::string label; | ||||
|                     switch (item.type) | ||||
|  | @ -1772,7 +1771,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 Times& times) { | ||||
|             auto append_color = [this, &imgui](const Color& color1, const Color& color2, ColumnOffsets& offsets, const Times& times) { | ||||
|                 ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); | ||||
|                 imgui.text(_u8L("Color change")); | ||||
|                 ImGui::PopStyleColor(); | ||||
|  | @ -1801,7 +1800,7 @@ void GCodeViewer::render_time_estimate() const | |||
|             if (items.empty()) | ||||
|                 return; | ||||
| 
 | ||||
|             Offsets offsets = calc_offsets(items); | ||||
|             ColumnOffsets offsets = calc_offsets(items); | ||||
| 
 | ||||
|             ImGui::Spacing(); | ||||
|             ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); | ||||
|  | @ -1845,42 +1844,25 @@ void GCodeViewer::render_time_estimate() const | |||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         auto append_move_times = [this, &imgui](float total_time, const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& moves_time) { | ||||
|             using Headers = std::vector<std::string>; | ||||
|             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<float, 2>; | ||||
|             auto calc_offsets = [this, &headers, move_type_label](const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& 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; | ||||
|             }; | ||||
|         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"); } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         auto append_move_times = [this, &imgui, move_type_label](float total_time, | ||||
|             const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& moves_time, | ||||
|             const Headers& headers, const ColumnOffsets& offsets) { | ||||
| 
 | ||||
|             if (moves_time.empty()) | ||||
|                 return; | ||||
|  | @ -1888,8 +1870,6 @@ void GCodeViewer::render_time_estimate() const | |||
|             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]); | ||||
|  | @ -1899,7 +1879,10 @@ void GCodeViewer::render_time_estimate() const | |||
|             ImGui::PopStyleColor(); | ||||
|             ImGui::Separator(); | ||||
| 
 | ||||
|             for (const auto& [type, time] : moves_time) { | ||||
|             std::vector<std::pair<GCodeProcessor::EMoveType, float>> sorted_moves_time(moves_time); | ||||
|             std::sort(sorted_moves_time.begin(), sorted_moves_time.end(), [](const auto& p1, const auto& p2) { return p2.second < p1.second; }); | ||||
| 
 | ||||
|             for (const auto& [type, time] : sorted_moves_time) { | ||||
|                 ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); | ||||
|                 imgui.text(move_type_label(type)); | ||||
|                 ImGui::PopStyleColor(); | ||||
|  | @ -1912,13 +1895,72 @@ void GCodeViewer::render_time_estimate() const | |||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         auto append_role_times = [this, &imgui](float total_time,  | ||||
|             const std::vector<std::pair<ExtrusionRole, float>>& roles_time, | ||||
|             const Headers& headers, const ColumnOffsets& offsets) { | ||||
| 
 | ||||
|             if (roles_time.empty()) | ||||
|                 return; | ||||
| 
 | ||||
|             if (!ImGui::CollapsingHeader(_u8L("Features Time").c_str())) | ||||
|                 return; | ||||
| 
 | ||||
|             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(); | ||||
| 
 | ||||
|             std::vector<std::pair<ExtrusionRole, float>> sorted_roles_time(roles_time); | ||||
|             std::sort(sorted_roles_time.begin(), sorted_roles_time.end(), [](const auto& p1, const auto& p2) { return p2.second < p1.second; }); | ||||
| 
 | ||||
|             for (const auto& [role, time] : sorted_roles_time) { | ||||
|                 ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); | ||||
|                 imgui.text(_u8L(ExtrusionEntity::role_to_string(role))); | ||||
|                 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); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         auto calc_common_offsets = [move_type_label]( | ||||
|             const std::vector<std::pair<GCodeProcessor::EMoveType, float>>& moves_time, const Headers& moves_headers, | ||||
|             const std::vector<std::pair<ExtrusionRole, float>>& roles_time, const Headers& roles_headers) { | ||||
|                 ColumnOffsets ret = { std::max(ImGui::CalcTextSize(moves_headers[0].c_str()).x, ImGui::CalcTextSize(roles_headers[0].c_str()).x), | ||||
|                     std::max(ImGui::CalcTextSize(moves_headers[1].c_str()).x, ImGui::CalcTextSize(roles_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); | ||||
|                 } | ||||
| 
 | ||||
|                 for (const auto& [role, time] : roles_time) { | ||||
|                     ret[0] = std::max(ret[0], ImGui::CalcTextSize(_u8L(ExtrusionEntity::role_to_string(role)).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; | ||||
|         }; | ||||
| 
 | ||||
|         ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT); | ||||
|         imgui.text(_u8L("Time") + ":"); | ||||
|         ImGui::PopStyleColor(); | ||||
|         ImGui::SameLine(); | ||||
|         imgui.text(short_time(get_time_dhms(total_time))); | ||||
|         append_partial_times(items); | ||||
|         append_move_times(total_time, moves_time); | ||||
|         append_partial_times(items, partial_times_headers); | ||||
|         ColumnOffsets common_offsets = calc_common_offsets(moves_time, moves_headers, roles_time, roles_headers); | ||||
|         append_move_times(total_time, moves_time, moves_headers, common_offsets); | ||||
|         append_role_times(total_time, roles_time, roles_headers, common_offsets); | ||||
|     }; | ||||
| 
 | ||||
|     auto generate_partial_times = [this](const TimesList& times) { | ||||
|  | @ -1966,6 +2008,22 @@ void GCodeViewer::render_time_estimate() const | |||
|         return items; | ||||
|     }; | ||||
| 
 | ||||
|     const Headers partial_times_headers = { | ||||
|         _u8L("Event"), | ||||
|         _u8L("Remaining"), | ||||
|         _u8L("Duration") | ||||
|     }; | ||||
|     const Headers moves_headers = { | ||||
|         _u8L("Type"), | ||||
|         _u8L("Time"), | ||||
|         _u8L("Percentage") | ||||
|     }; | ||||
|     const Headers roles_headers = { | ||||
|         _u8L("Feature"), | ||||
|         _u8L("Time"), | ||||
|         _u8L("Percentage") | ||||
|     }; | ||||
| 
 | ||||
|     Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); | ||||
|     imgui.set_next_window_pos(static_cast<float>(cnv_size.get_width()), static_cast<float>(cnv_size.get_height()), ImGuiCond_Always, 1.0f, 1.0f); | ||||
|     ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(-1.0f, 0.5f * static_cast<float>(cnv_size.get_height()))); | ||||
|  | @ -1980,13 +2038,19 @@ void GCodeViewer::render_time_estimate() const | |||
|     ImGui::BeginTabBar("mode_tabs"); | ||||
|     if (ps.estimated_normal_print_time > 0.0f) { | ||||
|         if (ImGui::BeginTabItem(_u8L("Normal").c_str())) { | ||||
|             append_mode(ps.estimated_normal_print_time, generate_partial_times(ps.estimated_normal_custom_gcode_print_times), ps.estimated_normal_moves_times); | ||||
|             append_mode(ps.estimated_normal_print_time,  | ||||
|                 generate_partial_times(ps.estimated_normal_custom_gcode_print_times), partial_times_headers, | ||||
|                 ps.estimated_normal_moves_times, moves_headers,  | ||||
|                 ps.estimated_normal_roles_times, roles_headers); | ||||
|             ImGui::EndTabItem(); | ||||
|         } | ||||
|     } | ||||
|     if (ps.estimated_silent_print_time > 0.0f) { | ||||
|         if (ImGui::BeginTabItem(_u8L("Stealth").c_str())) { | ||||
|             append_mode(ps.estimated_silent_print_time, generate_partial_times(ps.estimated_silent_custom_gcode_print_times), ps.estimated_silent_moves_times); | ||||
|             append_mode(ps.estimated_silent_print_time, | ||||
|                 generate_partial_times(ps.estimated_silent_custom_gcode_print_times), partial_times_headers, | ||||
|                 ps.estimated_silent_moves_times, moves_headers, | ||||
|                 ps.estimated_silent_roles_times, roles_headers); | ||||
|             ImGui::EndTabItem(); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 enricoturri1966
						enricoturri1966