From ffc8a3e307ec44d1ed14dbb36aa75752d257ec7f Mon Sep 17 00:00:00 2001 From: Argo <52103738+Argolein@users.noreply.github.com> Date: Tue, 10 Feb 2026 02:12:30 +0100 Subject: [PATCH] Adds (AMS) filament sync options: Only sync color / sync all (#12169) This PR adds a new filament sync mode setting for device-based filament synchronization. Users can now choose between syncing both filament preset + color (current behavior) or syncing color only, so calibrated local filament profiles are preserved while still updating slot colors from the printer. It also includes small UI improvements for the new preference entry and sync status messaging. image --- src/libslic3r/AppConfig.cpp | 2 + src/libslic3r/PresetBundle.cpp | 68 +++++++++++++++++++++++++++- src/libslic3r/PresetBundle.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 36 ++++++++++----- src/slic3r/GUI/Preferences.cpp | 10 ++++ src/slic3r/GUI/SyncAmsInfoDialog.cpp | 4 +- 6 files changed, 106 insertions(+), 16 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index a9f04aae19..64d4bbc89e 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -220,6 +220,8 @@ void AppConfig::set_defaults() set_bool("enable_merge_color_by_sync_ams", false); if (get("ams_sync_match_full_use_color_dist").empty()) set_bool("ams_sync_match_full_use_color_dist", false); + if (get("sync_ams_filament_mode").empty()) + set("sync_ams_filament_mode", "0"); // 0: filament+color, 1: color only if (get("camera_orbit_mult").empty()) set("camera_orbit_mult", "1.0"); diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 576080f51e..d5244b6bc0 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -2338,7 +2338,7 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info) } } -unsigned int PresetBundle::sync_ams_list(std::vector> &unknowns, bool use_map, std::map &maps,bool enable_append, MergeFilamentInfo &merge_info) +unsigned int PresetBundle::sync_ams_list(std::vector> &unknowns, bool use_map, std::map &maps, bool enable_append, MergeFilamentInfo &merge_info, bool color_only) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "use_map:" << use_map << " enable_append:" << enable_append; std::vector ams_filament_presets; @@ -2489,7 +2489,71 @@ unsigned int PresetBundle::sync_ams_list(std::vector("filament_colour"); ConfigOptionStrings *filament_color_type = project_config.option("filament_colour_type"); ConfigOptionInts * filament_map = project_config.option("filament_map"); - if (use_map) { + if (color_only) { + auto get_map_index = [&ams_infos](const std::vector &infos, const AMSMapInfo &temp) { + for (int i = 0; i < infos.size(); i++) { + if (infos[i].slot_id == temp.slot_id && infos[i].ams_id == temp.ams_id) { + ams_infos[i].is_map = true; + return i; + } + } + return -1; + }; + + auto exist_colors = filament_color->values; + std::vector> exist_multi_color_filment(exist_colors.size()); + for (size_t i = 0; i < exist_colors.size(); i++) { + exist_multi_color_filment[i] = {exist_colors[i]}; + } + + ConfigOptionStrings *project_multi_color = project_config.option("filament_multi_colour"); + if (project_multi_color) { + for (size_t i = 0; i < std::min(exist_multi_color_filment.size(), project_multi_color->values.size()); i++) { + std::vector colors = split_string(project_multi_color->values[i], ' '); + if (!colors.empty()) { + exist_multi_color_filment[i] = colors; + } + } + } + + bool mapped_any = false; + if (use_map && !maps.empty()) { + for (size_t i = 0; i < exist_colors.size(); i++) { + if (maps.find(i) == maps.end()) { + continue; + } + int valid_index = get_map_index(ams_array_maps, maps[i]); + if (valid_index >= 0 && valid_index < int(ams_filament_colors.size()) && !ams_filament_colors[valid_index].empty()) { + exist_colors[i] = ams_filament_colors[valid_index]; + mapped_any = true; + if (valid_index < int(ams_multi_color_filment.size()) && !ams_multi_color_filment[valid_index].empty()) { + exist_multi_color_filment[i] = ams_multi_color_filment[valid_index]; + } else { + exist_multi_color_filment[i] = {ams_filament_colors[valid_index]}; + } + } + } + } + // Fallback to index-based color sync if no mapping was applied. + if (!use_map || maps.empty() || !mapped_any) { + size_t sync_count = std::min(exist_colors.size(), ams_filament_colors.size()); + for (size_t i = 0; i < sync_count; i++) { + if (ams_filament_colors[i].empty()) { + continue; + } + exist_colors[i] = ams_filament_colors[i]; + if (i < ams_multi_color_filment.size() && !ams_multi_color_filment[i].empty()) { + exist_multi_color_filment[i] = ams_multi_color_filment[i]; + } else { + exist_multi_color_filment[i] = {ams_filament_colors[i]}; + } + } + } + + filament_color->values = exist_colors; + ams_multi_color_filment = exist_multi_color_filment; + merge_info.merges.clear(); + } else if (use_map) { auto check_has_merge_info = [](std::map &maps, MergeFilamentInfo &merge_info, int exist_colors_size) { std::set done; for (auto it_i = maps.begin(); it_i != maps.end(); ++it_i) { diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index 3c6aa9e6e6..51eed5646f 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -173,7 +173,7 @@ public: void update_num_filaments(unsigned int to_del_flament_id); void get_ams_cobox_infos(AMSComboInfo &combox_info); - unsigned int sync_ams_list(std::vector> &unknowns, bool use_map, std::map &maps,bool enable_append, MergeFilamentInfo& merge_info); + unsigned int sync_ams_list(std::vector> &unknowns, bool use_map, std::map &maps, bool enable_append, MergeFilamentInfo &merge_info, bool color_only = false); //BBS: check whether this is the only edited filament bool is_the_only_edited_filament(unsigned int filament_index); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7aa9a24cd3..2b955dc412 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3464,8 +3464,9 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) } MergeFilamentInfo merge_info; std::vector> unknowns; - auto enable_append = wxGetApp().app_config->get_bool("enable_append_color_by_sync_ams"); - auto n = wxGetApp().preset_bundle->sync_ams_list(unknowns, !sync_result.direct_sync, sync_result.sync_maps, enable_append, merge_info); + auto enable_append = wxGetApp().app_config->get_bool("enable_append_color_by_sync_ams"); + auto sync_color_only = wxGetApp().app_config->get("sync_ams_filament_mode") == "1"; + auto n = wxGetApp().preset_bundle->sync_ams_list(unknowns, !sync_result.direct_sync, sync_result.sync_maps, enable_append, merge_info, sync_color_only); wxString detail; for (auto & uk : unknowns) { auto tray_name = uk.first->opt_string("tray_name", 0u); @@ -3497,9 +3498,11 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) _L("Sync filaments with AMS"), wxOK); dlg.ShowModal(); } - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "on_filament_count_change"; - wxGetApp().plater()->on_filament_count_change(n); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish on_filament_count_change"; + if (!sync_color_only) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "on_filament_count_change"; + wxGetApp().plater()->on_filament_count_change(n); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish on_filament_count_change"; + } for (auto& c : p->combos_filament) c->update(); // Expand filament list @@ -3523,14 +3526,23 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) } Layout(); - // Perform preset selection and list update first — these may rebuild combo widgets, - // which clears any badge state. Badges must be set AFTER these calls to persist. - wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); - wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); - update_dynamic_filament_list(); + // For full sync, preset selection/list update may rebuild combo widgets. + // For color-only, keep current presets untouched and refresh colors only. + if (!sync_color_only) { + wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); + wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); + update_dynamic_filament_list(); + } else { + wxGetApp().plater()->update_filament_colors_in_full_config(); + for (auto &c : p->combos_filament) + c->update(); + obj_list()->update_filament_colors(); + update_dynamic_filament_list(); + } - auto badge_combox_filament = [](PlaterPresetComboBox *c) { - auto tip = _L("Filament type and color information have been synchronized, but slot information is not included."); + auto badge_combox_filament = [sync_color_only](PlaterPresetComboBox *c) { + auto tip = sync_color_only ? _L("Only filament color information has been synchronized from printer.") : + _L("Filament type and color information have been synchronized, but slot information is not included."); c->SetToolTip(tip); c->ShowBadge(true); }; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 28868d3ac5..98ec6e0707 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1492,6 +1492,16 @@ void PreferencesDialog::create_items() SETTING_USE_ENCRYPTED_TOKEN_FILE); g_sizer->Add(item_token_storage); + //// ONLINE > Filament Sync Options + g_sizer->Add(create_item_title(_L("Filament Sync Options")), 1, wxEXPAND); + + auto item_filament_sync_mode = create_item_combobox( + _L("Filament sync mode"), + _L("Choose whether sync updates both filament preset and color, or only color."), + "sync_ams_filament_mode", + {_L("Filament & Color"), _L("Color only")}); + g_sizer->Add(item_filament_sync_mode); + //// ONLINE > Network plugin g_sizer->Add(create_item_title(_L("Network plugin")), 1, wxEXPAND); diff --git a/src/slic3r/GUI/SyncAmsInfoDialog.cpp b/src/slic3r/GUI/SyncAmsInfoDialog.cpp index 49f75d23d1..1e6f2256fe 100644 --- a/src/slic3r/GUI/SyncAmsInfoDialog.cpp +++ b/src/slic3r/GUI/SyncAmsInfoDialog.cpp @@ -3337,7 +3337,9 @@ FinishSyncAmsDialog::FinishSyncAmsDialog(InputInfo &input_info) 310, input_info.dialog_pos, 68, - _L("Successfully synchronized color and type of filament from printer."), + wxGetApp().app_config->get("sync_ams_filament_mode") == "1" ? + _L("Successfully synchronized filament color from printer.") : + _L("Successfully synchronized color and type of filament from printer."), _CTX(L_CONTEXT("OK", "FinishSyncAms"), "FinishSyncAms"), "", DisappearanceMode::TimedDisappearance)