diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 76d0037289..e79f15cb3d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2046,6 +2046,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato unsigned int initial_non_support_extruder_id; unsigned int final_extruder_id = (unsigned int)-1; bool has_wipe_tower = false; + print.m_statistics_by_extruder_count.clear(); + std::vector print_object_instances_ordering; std::vector::const_iterator print_object_instance_sequential_active; if (print.config().print_sequence == PrintSequence::ByObject) { @@ -2056,6 +2058,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato print_object_instance_sequential_active = print_object_instances_ordering.begin(); for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) { tool_ordering = ToolOrdering(*(*print_object_instance_sequential_active)->print_object, initial_extruder_id); + { //save the flush statitics stored in tool ordering by object + print.m_statistics_by_extruder_count.stats_by_single_extruder += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::SingleExt); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_auto += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtAuto); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_manual += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtManual); + } if ((initial_extruder_id = tool_ordering.first_extruder()) != static_cast(-1)) { //BBS: try to find the non-support filament extruder if is multi color and initial_extruder is support filament initial_non_support_extruder_id = initial_extruder_id; @@ -2096,6 +2103,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Find tool ordering for all the objects at once, and the initial extruder ID. // If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it. tool_ordering = print.tool_ordering(); + { //save the flush statitics stored in tool ordering + print.m_statistics_by_extruder_count.stats_by_single_extruder = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::SingleExt); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_auto = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtAuto); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_manual = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtManual); + } tool_ordering.assign_custom_gcodes(print); if (tool_ordering.all_extruders().empty()) // No object to print was found, cancel the G-code export. diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 5971ee1005..01648ade73 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -464,10 +464,10 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object } //calculate the flush weight (first value) and filament change count(second value) -static std::pair calc_filament_change_info_by_toolorder(const PrintConfig* config,const std::vector&filament_map,const std::vector&flush_matrix,const std::vector>&layer_sequences) +static FilamentChangeStats calc_filament_change_info_by_toolorder(const PrintConfig* config,const std::vector&filament_map,const std::vector&flush_matrix,const std::vector>&layer_sequences) { + FilamentChangeStats ret; std::map flush_volume_per_filament; - std::vectorlast_filament_per_extruder(2, -1); int total_filament_change_count = 0; @@ -490,7 +490,10 @@ static std::pair calc_filament_change_info_by_toolorder(const PrintConf total_filament_flush_weight += weight; } - return { total_filament_flush_weight,total_filament_change_count }; + ret.filament_change_count = total_filament_change_count; + ret.filament_flush_weight = total_filament_flush_weight; + + return ret; } @@ -1259,6 +1262,22 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vectorfilament_maps(number_of_extruders, 0); + FilamentMapMode map_mode = FilamentMapMode::fmmAuto; if (nozzle_nums > 1) { filament_maps = m_print->get_filament_maps(); - if (m_print->get_filament_map_mode() == FilamentMapMode::fmmAuto + map_mode = m_print->get_filament_map_mode(); + if (map_mode == FilamentMapMode::fmmAuto && (print_config->print_sequence != PrintSequence::ByObject || m_print->objects().size() == 1)) { const PrintConfig* print_config = m_print_config_ptr; if (!print_config && m_print_object_ptr) { @@ -1361,23 +1382,46 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first ); auto curr_flush_info = calc_filament_change_info_by_toolorder(print_config, filament_maps, nozzle_flush_mtx, filament_sequences); - m_curr_flush_info = curr_flush_info; + if (nozzle_nums <= 1) + m_stats_by_single_extruder = curr_flush_info; + else if (map_mode == fmmAuto) + m_stats_by_multi_extruder_auto = curr_flush_info; + else if (map_mode == fmmManual) + m_stats_by_multi_extruder_manual = curr_flush_info; + // in multi extruder mode if (nozzle_nums > 1) { - std::vector>filament_sequences_one_extruder; - auto maps_without_group = filament_maps; - for (auto& item : maps_without_group) - item = 0; - reorder_filaments_for_minimum_flush_volume( - filament_lists, - maps_without_group, - layer_filaments, - nozzle_flush_mtx, - get_custom_seq, - &filament_sequences_one_extruder + // always calculate the info by one extruder + { + std::vector>filament_sequences_one_extruder; + auto maps_without_group = filament_maps; + for (auto& item : maps_without_group) + item = 0; + reorder_filaments_for_minimum_flush_volume( + filament_lists, + maps_without_group, + layer_filaments, + nozzle_flush_mtx, + get_custom_seq, + &filament_sequences_one_extruder ); - auto one_extruder_flush_info = calc_filament_change_info_by_toolorder(print_config, maps_without_group, nozzle_flush_mtx, filament_sequences_one_extruder); - m_one_extruder_flush_info = one_extruder_flush_info; + m_stats_by_single_extruder = calc_filament_change_info_by_toolorder(print_config, maps_without_group, nozzle_flush_mtx, filament_sequences_one_extruder); + } + // if in manual mode,also calculate the info by auto mode + if (map_mode == fmmManual) + { + std::vector>filament_sequences_one_extruder; + std::vectorfilament_maps_auto = get_recommended_filament_maps(layer_filaments, print_config); + reorder_filaments_for_minimum_flush_volume( + filament_lists, + filament_maps_auto, + layer_filaments, + nozzle_flush_mtx, + get_custom_seq, + &filament_sequences_one_extruder + ); + m_stats_by_multi_extruder_auto = calc_filament_change_info_by_toolorder(print_config, filament_maps_auto, nozzle_flush_mtx, filament_sequences_one_extruder); + } } for (size_t i = 0; i < filament_sequences.size(); ++i) diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index f790ac2a47..16aefb2e77 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -101,6 +101,37 @@ private: const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to }; + +struct FilamentChangeStats +{ + int filament_flush_weight{0}; + int filament_change_count{0}; + int extruder_change_count{0}; + + void clear(){ + filament_flush_weight = 0; + filament_change_count = 0; + extruder_change_count = 0; + } + + FilamentChangeStats& operator+=(const FilamentChangeStats& other) { + this->filament_flush_weight += other.filament_flush_weight; + this->filament_change_count += other.filament_change_count; + this->extruder_change_count += other.extruder_change_count; + return *this; + } + + FilamentChangeStats operator+(const FilamentChangeStats& other){ + FilamentChangeStats ret; + ret.filament_flush_weight = this->filament_flush_weight + other.filament_flush_weight; + ret.filament_change_count = this->filament_change_count + other.filament_change_count; + ret.extruder_change_count = this->extruder_change_count + other.extruder_change_count; + return ret; + } + +}; + + class LayerTools { public: @@ -156,9 +187,10 @@ private: class ToolOrdering { public: - enum FlushCalcMode { - Normal=0, - OneExtruder + enum FilamentChangeMode { + SingleExt, + MultiExtAuto, + MultiExtManual }; ToolOrdering() = default; @@ -172,8 +204,9 @@ public: void clear() { m_layer_tools.clear(); - m_curr_flush_info = { 0,0 }; - m_one_extruder_flush_info = { 0,0 }; + m_stats_by_single_extruder.clear(); + m_stats_by_multi_extruder_auto.clear(); + m_stats_by_multi_extruder_manual.clear(); } // Only valid for non-sequential print: @@ -205,8 +238,8 @@ public: static std::vector get_recommended_filament_maps(const std::vector>& layer_filaments, const PrintConfig *print_config); - // first val: flush weight second val: change count - std::pair get_flush_info(int mode) const { return mode == FlushCalcMode::OneExtruder ? m_one_extruder_flush_info : m_curr_flush_info; } + // should be called after doing reorder + FilamentChangeStats get_filament_change_stats(FilamentChangeMode mode); private: void initialize_layers(std::vector &zs); @@ -236,8 +269,9 @@ private: Print* m_print; bool m_is_BBL_printer = false; - std::pair m_curr_flush_info{ 0,0 }; - std::pair m_one_extruder_flush_info{ 0,0 }; + FilamentChangeStats m_stats_by_single_extruder; + FilamentChangeStats m_stats_by_multi_extruder_manual; + FilamentChangeStats m_stats_by_multi_extruder_auto; }; } // namespace SLic3r diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 89f1cfb62e..9f4d31048b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -66,6 +66,7 @@ void Print::clear() m_objects.clear(); m_print_regions.clear(); m_model.clear_objects(); + m_statistics_by_extruder_count.clear(); } // Called by Print::apply(). @@ -2064,17 +2065,13 @@ void Print::process(long long *time_cost_with_cache, bool use_cache) m_tool_ordering.clear(); if (this->has_wipe_tower()) { this->_make_wipe_tower(); - } else if (this->config().print_sequence != PrintSequence::ByObject) { - // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches. - m_tool_ordering = ToolOrdering(*this, -1, false); + } + else if (this->config().print_sequence != PrintSequence::ByObject) { + // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches. + m_tool_ordering = ToolOrdering(*this, -1, false); if (m_tool_ordering.empty() || m_tool_ordering.last_extruder() == unsigned(-1)) throw Slic3r::SlicingError("The print is empty. The model is not printable with current print settings."); - std::pair curr_info = m_tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal); - std::pair single_extruder_info = m_tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::OneExtruder); - - this->m_statistics_by_extruder_count.filament_flush_weight = { curr_info.first,single_extruder_info.first }; - this->m_statistics_by_extruder_count.filament_change_count = { curr_info.second,single_extruder_info.second }; } this->set_done(psWipeTower); } @@ -2709,12 +2706,6 @@ void Print::_make_wipe_tower() // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print. m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int) -1, bUseWipeTower2 ? true : false); - std::pair curr_info = m_wipe_tower_data.tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal); - std::pair single_extruder_info = m_wipe_tower_data.tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::OneExtruder); - - this->m_statistics_by_extruder_count.filament_flush_weight = { curr_info.first,single_extruder_info.first }; - this->m_statistics_by_extruder_count.filament_change_count = { curr_info.second,single_extruder_info.second }; - if (!m_wipe_tower_data.tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index d26cf61861..af87031724 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -826,12 +826,14 @@ class ConstPrintRegionPtrsAdaptor : public ConstVectorOfPtrsAdaptor struct StatisticsByExtruderCount { - // multi extruder always comes first - std::vector filament_flush_weight{ 0,0 }; - std::vector filament_change_count{ 0,0 }; + // flush weight comes first,then comes filament change time + FilamentChangeStats stats_by_single_extruder; + FilamentChangeStats stats_by_multi_extruder_auto; + FilamentChangeStats stats_by_multi_extruder_manual; void clear() { - filament_flush_weight.clear(); - filament_change_count.clear(); + stats_by_single_extruder.clear(); + stats_by_multi_extruder_auto.clear(); + stats_by_multi_extruder_manual.clear(); } }; @@ -1074,7 +1076,7 @@ private: // Estimated print time, filament consumed. PrintStatistics m_print_statistics; bool m_support_used {false}; - StatisticsByExtruderCount m_statistics_by_extruder_count; + StatisticsByExtruderCount m_statistics_by_extruder_count; //BBS: plate's origin Vec3d m_origin; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 2394036481..93035f494a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4424,10 +4424,18 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding) link_text(_u8L("(change)")); ImGui::SameLine(); imgui.text(_u8L(",this arrangement would be optimal.")); - int delta_filament_weight = stats_by_extruder.filament_flush_weight[1] - stats_by_extruder.filament_flush_weight[0]; - int delta_filament_change = stats_by_extruder.filament_change_count[1] - stats_by_extruder.filament_change_count[0]; - imgui.text(from_u8((boost::format(_u8L("Info by single extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.filament_flush_weight[1] % stats_by_extruder.filament_change_count[1]).str())); - imgui.text(from_u8((boost::format(_u8L("Info by multi extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.filament_flush_weight[0] % stats_by_extruder.filament_change_count[0]).str())); + auto config = wxGetApp().plater()->get_partplate_list().get_current_fff_print().config(); + auto filament_map_mode = config.filament_map_mode.value; + + if (filament_map_mode == fmmAuto) { + imgui.text(from_u8((boost::format(_u8L("Info by multi extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_auto.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_auto.filament_change_count).str())); + imgui.text(from_u8((boost::format(_u8L("Info by single extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_single_extruder.filament_flush_weight % stats_by_extruder.stats_by_single_extruder.filament_change_count).str())); + } + else if (filament_map_mode == fmmManual) { + imgui.text(from_u8((boost::format(_u8L("Info by manual mode : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_manual.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_manual.filament_change_count).str())); + imgui.text(from_u8((boost::format(_u8L("Info by auto mode : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_auto.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_auto.filament_change_count).str())); + } + float available_width = ImGui::GetContentRegionAvail().x; float available_height = ImGui::GetContentRegionAvail().y; float half_width = available_width * 0.5f;