diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index c866ae4067..40912dcc3e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -208,6 +208,7 @@ void GCodeProcessor::TimeMachine::reset() std::fill(moves_time.begin(), moves_time.end(), 0.0f); std::fill(roles_time.begin(), roles_time.end(), 0.0f); layers_time = std::vector(); + prepare_time = 0.0f; } void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time) @@ -315,7 +316,9 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa time += block_time; gcode_time.cache += block_time; - moves_time[static_cast(block.move_type)] += block_time; + //BBS: don't calculate travel of start gcode into travel time + if (!block.flags.prepare_stage || block.move_type != EMoveType::Travel) + moves_time[static_cast(block.move_type)] += block_time; roles_time[static_cast(block.role)] += block_time; if (block.layer_id >= layers_time.size()) { const size_t curr_size = layers_time.size(); @@ -325,6 +328,9 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa } } layers_time[block.layer_id - 1] += block_time; + //BBS + if (block.flags.prepare_stage) + prepare_time += block_time; g1_times_cache.push_back({ block.g1_line_id, time }); // update times for remaining time to printer stop placeholders auto it_stop_time = std::lower_bound(stop_times.begin(), stop_times.end(), block.g1_line_id, @@ -458,7 +464,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st // (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent", // get_time_dhms(machine.time).c_str()); sprintf(buf, "; model printing time: %s; total estimated time: %s\n", - get_time_dhms(machine.time - machine.roles_time[ExtrusionRole::erCustom]).c_str(), + get_time_dhms(machine.time - machine.prepare_time).c_str(), get_time_dhms(machine.time).c_str()); ret += buf; } @@ -1431,6 +1437,11 @@ float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast(mode)].time : 0.0f; } +float GCodeProcessor::get_prepare_time(PrintEstimatedStatistics::ETimeMode mode) const +{ + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast(mode)].prepare_time : 0.0f; +} + std::string GCodeProcessor::get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const { return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].time)) : std::string("N/A"); @@ -2663,10 +2674,12 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) TimeBlock block; block.move_type = type; - block.role = m_extrusion_role; + //BBS: don't calculate travel time into extrusion path, except travel inside start and end gcode. + block.role = (type != EMoveType::Travel || m_extrusion_role == erCustom) ? m_extrusion_role : erNone; block.distance = distance; block.g1_line_id = m_g1_line_id; block.layer_id = std::max(1, m_layer_id); + block.flags.prepare_stage = m_processing_start_custom_gcode; //BBS: limite the cruise according to centripetal acceleration //Only need to handle when both prev and curr segment has movement in x-y plane @@ -3085,10 +3098,12 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line) TimeBlock block; block.move_type = type; - block.role = m_extrusion_role; + //BBS: don't calculate travel time into extrusion path, except travel inside start and end gcode. + block.role = (type != EMoveType::Travel || m_extrusion_role == erCustom) ? m_extrusion_role : erNone; block.distance = delta_xyz; block.g1_line_id = m_g1_line_id; block.layer_id = std::max(1, m_layer_id); + block.flags.prepare_stage = m_processing_start_custom_gcode; // BBS: calculates block cruise feedrate // For arc move, we need to limite the cruise according to centripetal acceleration which is @@ -4015,6 +4030,7 @@ void GCodeProcessor::update_estimated_times_stats() auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) { PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast(mode)]; data.time = get_time(mode); + data.prepare_time = get_prepare_time(mode); data.custom_gcode_times = get_custom_gcode_times(mode, true); data.moves_times = get_moves_time(mode); data.roles_times = get_roles_time(mode); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index a0866eca93..e95527605b 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -49,6 +49,7 @@ namespace Slic3r { struct Mode { float time; + float prepare_time; std::vector>> custom_gcode_times; std::vector> moves_times; std::vector> roles_times; @@ -56,6 +57,7 @@ namespace Slic3r { void reset() { time = 0.0f; + prepare_time = 0.0f; custom_gcode_times.clear(); moves_times.clear(); roles_times.clear(); @@ -298,6 +300,7 @@ namespace Slic3r { { bool recalculate{ false }; bool nominal_length{ false }; + bool prepare_stage{ false }; }; EMoveType move_type{ EMoveType::Noop }; @@ -381,6 +384,8 @@ namespace Slic3r { std::array(EMoveType::Count)> moves_time; std::array(ExtrusionRole::erCount)> roles_time; std::vector layers_time; + //BBS: prepare stage time before print model, including start gcode time and mostly same with start gcode time + float prepare_time; void reset(); @@ -681,6 +686,7 @@ namespace Slic3r { void finalize(bool post_process); float get_time(PrintEstimatedStatistics::ETimeMode mode) const; + float get_prepare_time(PrintEstimatedStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; std::vector>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 57533af3fe..d8fc148c95 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -942,7 +942,6 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode) // BBS for first layer inspection view_type_items.push_back(EViewType::FilamentId); - options_items.push_back(EMoveType::Seam); options_items.push_back(EMoveType::Travel); options_items.push_back(EMoveType::Retract); options_items.push_back(EMoveType::Unretract); @@ -950,6 +949,8 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode) if (mode == ConfigOptionMode::comDevelop) { options_items.push_back(EMoveType::Tool_change); } + //BBS: seam is not real move and extrusion, put at last line + options_items.push_back(EMoveType::Seam); } std::vector GCodeViewer::get_plater_extruder() @@ -4365,6 +4366,11 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f); }; + auto move_time_and_percent = [time_mode](EMoveType move_type) { + auto it = std::find_if(time_mode.moves_times.begin(), time_mode.moves_times.end(), [move_type](const std::pair& item) { return move_type == item.first; }); + return (it != time_mode.moves_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f); + }; + auto used_filament_per_role = [this, imperial_units](ExtrusionRole role) { auto it = m_print_statistics.used_filaments_per_role.find(role); if (it == m_print_statistics.used_filaments_per_role.end()) @@ -4438,7 +4444,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv std::vector offsets; std::vector labels; std::vector times; + std::string travel_time; std::vector percents; + std::string travel_percent; std::vector model_used_filaments_m; std::vector model_used_filaments_g; double total_model_used_filament_m = 0, total_model_used_filament_g = 0; @@ -4485,6 +4493,17 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } } + //BBS: get travel time and percent + { + auto [time, percent] = move_time_and_percent(EMoveType::Travel); + travel_time = (time > 0.0f) ? short_time(get_time_dhms(time)) : ""; + if (percent == 0) + ::sprintf(buffer, "0%%"); + else + percent > 0.001 ? ::sprintf(buffer, "%.1f%%", percent * 100) : ::sprintf(buffer, "<0.1%%"); + travel_percent = buffer; + } + offsets = calculate_offsets({ {_u8L("Line Type"), labels}, {_u8L("Time"), times}, {_u8L("Percent"), percents}, {_u8L("Display"), {""}}}, icon_size); append_headers({{_u8L("Line Type"), offsets[0]}, {_u8L("Time"), offsets[1]}, {_u8L("Percent"), offsets[2]}, {_u8L("Display"), offsets[3]}}); break; @@ -4573,7 +4592,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv }; const bool visible = m_buffers[buffer_id(type)].visible; if (type == EMoveType::Travel) { - //TODO display travel time + //BBS: only display travel time in FeatureType view append_option_item_with_type(type, Travel_Colors[0], _u8L("Travel"), visible); } else if (type == EMoveType::Seam) @@ -4613,7 +4632,23 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } for(auto item : options_items) { - append_option_item(item, offsets); + if (item != EMoveType::Travel) { + append_option_item(item, offsets); + } else { + //BBS: show travel time in FeatureType view + const bool visible = m_buffers[buffer_id(item)].visible; + std::vector> columns_offsets; + columns_offsets.push_back({ _u8L("Travel"), offsets[0] }); + columns_offsets.push_back({ travel_time, offsets[1] }); + columns_offsets.push_back({ travel_percent, offsets[2] }); + append_item(EItemType::Rect, Travel_Colors[0], columns_offsets, true, visible, [this, item, visible]() { + m_buffers[buffer_id(item)].visible = !m_buffers[buffer_id(item)].visible; + // update buffers' render paths + refresh_render_paths(false, false); + update_moves_slider(); + wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); + }); + } } break; } @@ -5209,19 +5244,19 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv auto it = std::find_if(time_mode.roles_times.begin(), time_mode.roles_times.end(), [role](const std::pair& item) { return role == item.first; }); return (it != time_mode.roles_times.end()) ? it->second : 0.0f; }; - //BBS: start gcode is prepeare time - if (role_time(erCustom) != 0.0f) { + //BBS: start gcode is mostly same with prepeare time + if (time_mode.prepare_time != 0.0f) { ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.text(prepare_str + ":"); ImGui::SameLine(max_len); - imgui.text(short_time(get_time_dhms(role_time(erCustom)))); + imgui.text(short_time(get_time_dhms(time_mode.prepare_time))); } ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.text(print_str + ":"); ImGui::SameLine(max_len); - imgui.text(short_time(get_time_dhms(time_mode.time - role_time(erCustom)))); + imgui.text(short_time(get_time_dhms(time_mode.time - time_mode.prepare_time))); ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.text(total_str + ":");