From 8965b0be210bf4c92844fe99efdd36c1a15017fd Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 22 Aug 2026 21:22:25 +0800 Subject: [PATCH] Skip mixed slots in flush volume auto-calculation Mixed-colour slots are virtual and never flushed. Guard auto_calc_flushing_volumes_internal against them as BambuStudio does, and make the flushing dialog's default matrix and the sidebar 'modified' comparison physical-only so the untouched mixed rows no longer count as a user edit and the Re-calculate result matches the physical-only table. --- src/slic3r/GUI/Plater.cpp | 6 +++ src/slic3r/GUI/WipeTowerDialog.cpp | 71 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4676ff3c4b..479b91e098 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6477,6 +6477,10 @@ void Sidebar::auto_calc_flushing_volumes(const int filament_idx, const int extru void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int extruder_id) { auto& preset_bundle = wxGetApp().preset_bundle; + // A mixed-colour slot is virtual and is never flushed to or from: leave its row and column + // alone (the flushing dialog hides them and only compares physical slots). + if (modify_id >= 0 && preset_bundle->is_mixed_filament((size_t)modify_id)) + return; auto& project_config = preset_bundle->project_config; const auto& full_config = wxGetApp().preset_bundle->full_config(); auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment; @@ -6515,6 +6519,8 @@ void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int if (modify_id >= 0 && modify_id < multi_colours.size()) { for (int i = 0; i < multi_colours.size(); ++i) { + if (preset_bundle->is_mixed_filament((size_t)i)) + continue; // from to modify int from_idx = i; if (from_idx != modify_id) { diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp index f1d0946bf5..70aba0404e 100644 --- a/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/src/slic3r/GUI/WipeTowerDialog.cpp @@ -204,6 +204,10 @@ bool is_flush_config_modified() const auto &project_config = wxGetApp().preset_bundle->project_config; const std::vector &config_matrix = (project_config.option("flush_volumes_matrix"))->values; const std::vector &config_multiplier = (project_config.option("flush_multiplier"))->values; + // The config matrix is N x N per nozzle over every slot, while CalcFlushingVolumes is p x p + // over the physical slots (mixed slots never flush): map each default cell to its config index. + const auto physical_indices = wxGetApp().preset_bundle->physical_filament_config_indices(); + const size_t full_n = project_config.option("filament_colour")->values.size(); bool has_modify = false; for (int i = 0; i < config_multiplier.size(); i++) { @@ -212,11 +216,12 @@ bool is_flush_config_modified() break; } std::vector> default_matrix = WipingDialog::CalcFlushingVolumes(i); - int len = default_matrix.size(); - for (int m = 0; m < len; m++) { - for (int n = 0; n < len; n++) { - int idx = i * len * len + m * len + n; - if (config_matrix[idx] != default_matrix[m][n] * config_multiplier[i]) { + size_t p_len = default_matrix.size(); + size_t nozzle_offset = i * full_n * full_n; + for (size_t m = 0; m < p_len; m++) { + for (size_t n = 0; n < p_len; n++) { + size_t cfg_idx = nozzle_offset + physical_indices[m] * full_n + physical_indices[n]; + if (cfg_idx < config_matrix.size() && config_matrix[cfg_idx] != default_matrix[m][n] * config_multiplier[i]) { has_modify = true; break; } @@ -571,55 +576,51 @@ WipingDialog::VolumeMatrix WipingDialog::CalcFlushingVolumes(int extruder_id) auto& preset_bundle = wxGetApp().preset_bundle; auto full_config = preset_bundle->full_config(); auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment; + // Mixed-colour slots are virtual and never flushed: compute a p x p matrix over the physical + // slots only, laid out like the table; row/column k belongs to config slot physical_indices[k]. + auto physical_indices = preset_bundle->physical_filament_config_indices(); - std::vector filament_color_strs = full_config.option("filament_colour")->values; - std::vector> multi_colors; - std::vector filament_colors; - for (auto color_str : filament_color_strs) - filament_colors.emplace_back(color_str); - + std::vector all_color_strs = full_config.option("filament_colour")->values; int flush_dataset_value = full_config.option("nozzle_flush_dataset")->values[extruder_id]; + const std::vector min_flush_volumes = get_min_flush_volumes(full_config, extruder_id); + // Support for multi-color filament - for (int i = 0; i < filament_colors.size(); ++i) { + std::vector> multi_colors; + for (size_t cfg_idx : physical_indices) { std::vector single_filament; - if (i < ams_multi_color_filament.size()) { - if (!ams_multi_color_filament[i].empty()) { - std::vector colors = ams_multi_color_filament[i]; - for (int j = 0; j < colors.size(); ++j) { - single_filament.push_back(wxColour(colors[j])); - } - multi_colors.push_back(single_filament); - continue; - } + if (cfg_idx < ams_multi_color_filament.size() && !ams_multi_color_filament[cfg_idx].empty()) { + for (const auto& c : ams_multi_color_filament[cfg_idx]) + single_filament.push_back(wxColour(c)); + } else if (cfg_idx < all_color_strs.size()) { + single_filament.push_back(wxColour(all_color_strs[cfg_idx])); } - single_filament.push_back(wxColour(filament_colors[i])); multi_colors.push_back(single_filament); } VolumeMatrix matrix; - const std::vector min_flush_volumes = get_min_flush_volumes(full_config, extruder_id); - - for (int from_idx = 0; from_idx < multi_colors.size(); ++from_idx) { - bool is_from_support = is_support_filament(from_idx); + for (size_t pi = 0; pi < physical_indices.size(); ++pi) { + int from_cfg = (int)physical_indices[pi]; + bool is_from_support = is_support_filament(from_cfg); matrix.emplace_back(); - for (int to_idx = 0; to_idx < multi_colors.size(); ++to_idx) { - if (from_idx == to_idx) { + for (size_t pj = 0; pj < physical_indices.size(); ++pj) { + int to_cfg = (int)physical_indices[pj]; + if (from_cfg == to_cfg) { matrix.back().emplace_back(0); continue; } - bool is_to_support = is_support_filament(to_idx); - + bool is_to_support = is_support_filament(to_cfg); int flushing_volume = 0; if (is_to_support) { flushing_volume = Slic3r::g_flush_volume_to_support; } else { - for (int i = 0; i < multi_colors[from_idx].size(); ++i) { - const wxColour& from = multi_colors[from_idx][i]; - for (int j = 0; j < multi_colors[to_idx].size(); ++j) { - const wxColour& to = multi_colors[to_idx][j]; - int volume = CalcFlushingVolume(from, to, min_flush_volumes[from_idx], flush_dataset_value); + int min_flush_from = (from_cfg < (int)min_flush_volumes.size()) ? min_flush_volumes[from_cfg] : 0; + for (size_t i = 0; i < multi_colors[pi].size(); ++i) { + const wxColour& from = multi_colors[pi][i]; + for (size_t j = 0; j < multi_colors[pj].size(); ++j) { + const wxColour& to = multi_colors[pj][j]; + int volume = CalcFlushingVolume(from, to, min_flush_from, flush_dataset_value); flushing_volume = std::max(flushing_volume, volume); } }