diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 172a535e3..b90c50c49 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -620,6 +620,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role) case erWipeTower : return L("Prime tower"); case erCustom : return L("Custom"); case erMixed : return L("Multiple"); + case erFlush : return L("Flush"); default : assert(false); } return ""; @@ -663,6 +664,8 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role) return erCustom; else if (role == L("Multiple")) return erMixed; + else if (role == L("Flush")) + return erFlush; else return erNone; } diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index e32c6d3c0..d64feb701 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -36,6 +36,7 @@ enum ExtrusionRole : uint8_t { erSupportTransition, erWipeTower, erCustom, + erFlush, // Extrusion role for a collection with multiple extrusion roles. erMixed, erCount diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 36a8df11b..04bdc8875 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -224,12 +224,12 @@ void GCodeProcessor::TimeMachine::reset() prepare_time = 0.0f; } -void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time) +void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time, ExtrusionRole target_role) { if (!enabled) return; - calculate_time(0, additional_time); + calculate_time(0, additional_time,target_role); } static void planner_forward_pass_kernel(GCodeProcessor::TimeBlock& prev, GCodeProcessor::TimeBlock& curr) @@ -302,7 +302,7 @@ static void recalculate_trapezoids(std::vector& block } } -void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, float additional_time) +void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, float additional_time, ExtrusionRole target_role) { if (!enabled || blocks.size() < 2) return; @@ -321,11 +321,16 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa recalculate_trapezoids(blocks); size_t n_blocks_process = blocks.size() - keep_last_n_blocks; + bool found_target_block = false; for (size_t i = 0; i < n_blocks_process; ++i) { const TimeBlock& block = blocks[i]; float block_time = block.time(); - if (i == 0) + + bool is_valid_block = target_role == ExtrusionRole::erNone || target_role == block.role || i == n_blocks_process - 1; + if (!found_target_block && is_valid_block) { block_time += additional_time; + found_target_block = true; + } time += block_time; gcode_time.cache += block_time; @@ -344,7 +349,11 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa //BBS if (block.flags.prepare_stage) prepare_time += block_time; - g1_times_cache.push_back({ block.g1_line_id, time }); + + if(!g1_times_cache.empty() && g1_times_cache.back().id == block.g1_line_id) + g1_times_cache.back().elapsed_time = time; + else + 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, [](const StopTime& t, unsigned int value) { return t.g1_line_id < value; }); @@ -865,6 +874,7 @@ void GCodeProcessor::UsedFilaments::process_support_cache(GCodeProcessor* proces void GCodeProcessor::UsedFilaments::update_flush_per_filament(size_t extrude_id, float flush_volume) { if (flush_volume != 0.f) { + role_cache += flush_volume; if (flush_per_filament.find(extrude_id) != flush_per_filament.end()) flush_per_filament[extrude_id] += flush_volume; else @@ -1603,7 +1613,7 @@ void GCodeProcessor::finalize(bool post_process) for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { TimeMachine& machine = m_time_processor.machines[i]; TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time; - machine.calculate_time(); + machine.calculate_time(0, 0, ExtrusionRole::erNone); if (gcode_time.needed && gcode_time.cache != 0.0f) gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache }); } @@ -2184,6 +2194,7 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double& void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled) { + static ExtrusionRole prev_role; // producers tags if (producers_enabled && process_producers_tags(comment)) return; @@ -2222,12 +2233,15 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers //BBS: flush start tag if (boost::starts_with(comment, GCodeProcessor::Flush_Start_Tag)) { + prev_role = m_extrusion_role; + set_extrusion_role(erFlush); m_flushing = true; return; } //BBS: flush end tag if (boost::starts_with(comment, GCodeProcessor::Flush_End_Tag)) { + set_extrusion_role(prev_role); m_flushing = false; return; } @@ -3201,8 +3215,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) blocks.push_back(block); - if (blocks.size() > TimeProcessor::Planner::refresh_threshold) - machine.calculate_time(TimeProcessor::Planner::queue_size); + if (blocks.size() > TimeProcessor::Planner::refresh_threshold) { + machine.calculate_time(TimeProcessor::Planner::queue_size, 0, erNone); + } } if (m_seams_detector.is_active()) { @@ -3636,8 +3651,9 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line) blocks.push_back(block); - if (blocks.size() > TimeProcessor::Planner::refresh_threshold) - machine.calculate_time(TimeProcessor::Planner::queue_size); + if (blocks.size() > TimeProcessor::Planner::refresh_threshold) { + machine.calculate_time(TimeProcessor::Planner::queue_size, 0, erNone); + } } //BBS: seam detector @@ -4239,11 +4255,29 @@ void GCodeProcessor::process_T(const std::string_view command) float extra_time = get_filament_unload_time(static_cast(m_last_extruder_id)); m_time_processor.extruder_unloaded = false; extra_time += get_filament_load_time(static_cast(m_extruder_id)); - simulate_st_synchronize(extra_time); - } + // store tool change move + store_move_vertex(EMoveType::Tool_change); + // construct a new time block to handle filament change + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + TimeMachine& machine = m_time_processor.machines[i]; + if (!machine.enabled) + continue; + TimeBlock block; + block.role = erFlush; + block.move_type = EMoveType::Tool_change; + block.layer_id = std::max(1, m_layer_id); + block.g1_line_id = m_g1_line_id; + block.flags.prepare_stage = m_processing_start_custom_gcode; + block.distance = 0; + block.calculate_trapezoid(); - // store tool change move - store_move_vertex(EMoveType::Tool_change); + // when do st_sync, we will clear all of the blocks without keeping last n blocks, so we can directly add the new block into the blocks + machine.blocks.push_back(block); + } + + simulate_st_synchronize(extra_time, erFlush); + + } } } } @@ -4450,7 +4484,7 @@ void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code) gcode_time.needed = true; //FIXME this simulates st_synchronize! is it correct? // The estimated time may be longer than the real print time. - machine.simulate_st_synchronize(); + machine.simulate_st_synchronize(0, erNone); if (gcode_time.cache != 0.0f) { gcode_time.times.push_back({ code, gcode_time.cache }); gcode_time.cache = 0.0f; @@ -4472,10 +4506,14 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code) } } -void GCodeProcessor::simulate_st_synchronize(float additional_time) +void GCodeProcessor::simulate_st_synchronize(float additional_time, ExtrusionRole target_role) { for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { - m_time_processor.machines[i].simulate_st_synchronize(additional_time); + TimeMachine& machine = m_time_processor.machines[i]; + if (!machine.enabled) + continue; + + machine.simulate_st_synchronize(additional_time, target_role); } } diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 791e7e373..e33bd4c95 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -459,9 +459,26 @@ namespace Slic3r { void reset(); - // Simulates firmware st_synchronize() call - void simulate_st_synchronize(float additional_time = 0.0f); - void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f); + /** + * @brief Simulates firmware st_synchronize() call + * + * Adding additional time to the specified extrusion role's time block. + * + * @param additional_time Addtional time to calculate + * @param target_role Target extrusion role for addtional time.Default is none,means any role is ok. + */ + void simulate_st_synchronize(float additional_time = 0.0f, ExtrusionRole target_role = ExtrusionRole::erNone); + + /** + * @brief Calculates the time for all blocks + * + * Computes the time for all blocks. + * + * @param keep_last_n_blocks The number of last blocks to retain during calculation (default is 0). + * @param additional_time Additional time to calculate. + * @param target_role Target extrusion role for addtional time.Default is none, means any role is ok. + */ + void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f, ExtrusionRole target_role = ExtrusionRole::erNone); }; struct UsedFilaments // filaments per ColorChange @@ -964,7 +981,7 @@ namespace Slic3r { void process_filaments(CustomGCode::Type code); // Simulates firmware st_synchronize() call - void simulate_st_synchronize(float additional_time = 0.0f); + void simulate_st_synchronize(float additional_time = 0.0f, ExtrusionRole target_role =ExtrusionRole::erNone); void update_estimated_times_stats(); //BBS: diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 90ab44d05..389b7d7e2 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -751,7 +751,8 @@ const std::vector GCodeViewer::Extrusion_Role_Colors {{ { 0.00f, 0.50f, 0.00f, 1.0f }, // erSupportMaterialInterface { 0.00f, 0.25f, 0.00f, 1.0f }, // erSupportTransition { 0.70f, 0.89f, 0.67f, 1.0f }, // erWipeTower - { 0.37f, 0.82f, 0.58f, 1.0f } // erCustom + { 0.37f, 0.82f, 0.58f, 1.0f }, // erCustom + { 0.85f, 0.65f, 0.95f, 1.0f } // erFlush }}; const std::vector GCodeViewer::Options_Colors {{ @@ -3096,6 +3097,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const last_travel_s_id = move_id; } + else if (move.type == EMoveType::Unretract && move.extrusion_role == ExtrusionRole::erFlush) { + m_roles.emplace_back(move.extrusion_role); + } } // roles -> remove duplicates