diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 51032b052..0971efb57 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1748,6 +1748,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) { @@ -1758,6 +1760,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; @@ -1804,6 +1811,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 9835bcffe..fb708ea98 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -456,10 +456,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; @@ -482,7 +482,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; } @@ -1258,6 +1261,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) { @@ -1355,23 +1376,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 599938c42..3636378c9 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); @@ -234,8 +267,9 @@ private: const PrintObject* m_print_object_ptr = nullptr; Print* m_print; - 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 9a44dd3b9..f81ef5c44 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -64,6 +64,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(). @@ -1809,17 +1810,13 @@ void Print::process(std::unordered_map* slice_time, bool 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); } @@ -2413,12 +2410,6 @@ void Print::_make_wipe_tower() // BBS: priming logic is removed, so don't consider it in tool ordering m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, 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 b5c6e92dc..93358285b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -697,12 +697,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(); } }; @@ -929,7 +931,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 1ccee3360..6768f708f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4641,10 +4641,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;