From c4804e0d802d528bd9406a0a0a56d0ae775ce14b Mon Sep 17 00:00:00 2001 From: grant0013 Date: Tue, 19 May 2026 15:05:03 +0000 Subject: [PATCH] CrealityPrintAgent: prefer system bases over user copies in CFS matcher The matcher tiebreaker previously preferred user-edited filament presets over system bases on a tied score. For a K2 owner who has a custom copy of Creality Generic PLA @K2-all called eg Creality Hyper PLA @K2 (mine), the matcher scored both that copy and the shipped brand-specific Hyper PLA @Creality K2 0.4 nozzle at 30, then tiebreak picked the user copy. User copies inherit filament_id from their parent -- in this case the generic PLA GFL99 -- so the returned id pointed at Generic PLA, not at Hyper PLA brand-specific id (01001). PresetBundle::sync_ams_list then resolved by id back to Creality Generic PLA @K2-all, visibly losing the brand on every sync. Flip the tiebreaker to prefer system over user. The shipped brand-specific preset always wins now and sync_ams_list lands on the right slot label. Drop the post-sync user-override step from the sidebar path that was layered on to compensate -- silently substituting the user local tuning is the wrong default for an upstream-shipped feature; users who want their local tuning on a synced slot still get to it via the existing combo dropdown. --- src/slic3r/GUI/Plater.cpp | 61 +++++-------------------- src/slic3r/Utils/CrealityPrintAgent.cpp | 13 ++++-- 2 files changed, 19 insertions(+), 55 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5325c4a1995..3e7dd4868d6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3743,12 +3743,13 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) // existing PresetBundle::sync_ams_list machinery so the filament combo widgets // get the same correct rebuild as BBL printers. // -// PresetBundle::sync_ams_list resolves each tray's filament_id only against -// system *base* presets (get_preset_base(f) == &f), so user-edited copies of -// system presets (the typical K-series workflow — copy "Creality Generic PLA -// @K2-all" and tune PA/temps for one's specific spool) are collapsed back to -// the system base. We replay the user-copy assignment after sync_ams_list -// returns to preserve the matcher's preference. +// PresetBundle::sync_ams_list resolves each tray's filament_id against system +// bases (get_preset_base(f) == &f). Combined with the matcher's system-over- +// user tiebreaker, this lands us on the brand-specific shipped preset for the +// loaded spool (e.g. "Hyper PLA @Creality K2 0.4 nozzle") rather than a +// generic-inheriting user copy. We do not override post-sync — local user +// customisations should be applied by the user via the dropdown, not silently +// substituted in. void Sidebar::sync_filaments_from_creality_cfs() { auto* preset_bundle = wxGetApp().preset_bundle; @@ -3826,32 +3827,11 @@ void Sidebar::sync_filaments_from_creality_cfs() constexpr int kMainExtruder = 0x10000; std::map new_filament_ams_list; - // Side table of user-copy preset names per filament index. PresetBundle::sync_ams_list - // collapses filament_id back to the SYSTEM base preset name; we replay the user copy - // assignment after it returns to preserve the matcher's preference. - std::map user_preset_overrides; - for (const auto& s : slots) { const std::string normalized_type = CrealityPrintAgent::normalize_filament_type(s.filament_type); const std::string matched_id = CrealityPrintAgent::match_filament_preset( filaments, s.vendor, s.brand_name, normalized_type); - // Find the best user copy with the matched filament_id, if any. The matcher - // already biases toward user copies for scoring; this re-finds the best user - // copy by filament_id so we can override after sync_ams_list. - const Preset* best_user = nullptr; - if (!matched_id.empty()) { - for (const auto& p : filaments.get_presets()) { - if (!p.is_visible || !p.is_compatible) continue; - if (p.filament_id != matched_id) continue; - if (p.is_system || p.is_default) continue; - if (!best_user) { - best_user = &p; - break; // first user copy wins; matcher's scoring tiebreak already ran - } - } - } - DynamicPrintConfig tray_config; tray_config.set_key_value("filament_id", new ConfigOptionStrings{matched_id}); tray_config.set_key_value("tag_uid", new ConfigOptionStrings{std::string()}); @@ -3871,20 +3851,10 @@ void Sidebar::sync_filaments_from_creality_cfs() const int map_key = kMainExtruder + slot_in_filament_array; new_filament_ams_list.emplace(map_key, std::move(tray_config)); - if (best_user) { - user_preset_overrides[slot_in_filament_array] = best_user->name; - BOOST_LOG_TRIVIAL(warning) - << "sync_filaments_from_creality_cfs: slot " << slot_in_filament_array - << " spool {" << s.vendor << " " << s.brand_name << " (" << normalized_type - << ")} -> filament_id=\"" << matched_id - << "\" user-override=\"" << best_user->name << "\""; - } else { - BOOST_LOG_TRIVIAL(warning) - << "sync_filaments_from_creality_cfs: slot " << slot_in_filament_array - << " spool {" << s.vendor << " " << s.brand_name << " (" << normalized_type - << ")} -> filament_id=\"" << matched_id - << "\" (no user copy; system base will be used)"; - } + BOOST_LOG_TRIVIAL(warning) + << "sync_filaments_from_creality_cfs: slot " << slot_in_filament_array + << " spool {" << s.vendor << " " << s.brand_name << " (" << normalized_type + << ")} -> filament_id=\"" << matched_id << "\""; } preset_bundle->filament_ams_list = new_filament_ams_list; @@ -3907,16 +3877,7 @@ void Sidebar::sync_filaments_from_creality_cfs() return; } - // Override system-base names with the user copies the matcher preferred. auto& filament_presets = preset_bundle->filament_presets; - for (const auto& [slot_idx, user_name] : user_preset_overrides) { - if (slot_idx >= 0 && slot_idx < int(filament_presets.size())) { - BOOST_LOG_TRIVIAL(warning) - << "sync_filaments_from_creality_cfs: overriding slot " << slot_idx - << " from \"" << filament_presets[slot_idx] << "\" to \"" << user_name << "\""; - filament_presets[slot_idx] = user_name; - } - } // Mirror the BBL post-sync refresh sequence. wxGetApp().plater()->on_filament_count_change(n); diff --git a/src/slic3r/Utils/CrealityPrintAgent.cpp b/src/slic3r/Utils/CrealityPrintAgent.cpp index f6f873832d8..fb5519de068 100644 --- a/src/slic3r/Utils/CrealityPrintAgent.cpp +++ b/src/slic3r/Utils/CrealityPrintAgent.cpp @@ -32,11 +32,14 @@ bool has_visible_base_preset(const PresetCollection& filaments, const std::strin // Score visible compatible filament presets against the CFS spool metadata and // return the best-matching filament_id. Scoring: // +20 preset name contains brand_name as a substring -// (e.g. "Hyper PLA" in "Creality Hyper PLA @K2 (Harky)") +// (e.g. "Hyper PLA" in "Hyper PLA @Creality K2 0.4 nozzle") // +10 preset name contains the vendor substring (e.g. "Creality") -// Tiebreak: prefer user-edited presets over system presets — the K2 owner -// typically copies the system base and tweaks PA / temps for their box, -// so their copy is the better fit than the pristine system entry. +// Tiebreak: prefer the SYSTEM (shipped) preset over user copies. Brand- +// specific system presets carry their own filament_id; user copies of +// generic presets inherit a generic filament_id from their parent, so +// preferring the user copy can collapse a brand-specific match back to +// "Generic PLA" via the inherited id. Plus: this code targets upstream +// OrcaSlicer where shipping the user's local tuning would be wrong. // Requires the preset's declared filament_type to equal the spool's base type // (PLA/PETG/ABS/...) so we never auto-pick a PETG preset for a PLA spool. // Falls back to filaments.filament_id_by_type(base_type) when nothing scores. @@ -101,7 +104,7 @@ std::string CrealityPrintAgent::match_filament_preset(const PresetCollection& fi std::sort(matches.begin(), matches.end(), [](const Match& a, const Match& b) { if (a.score != b.score) return a.score > b.score; - if (a.is_user != b.is_user) return a.is_user; + if (a.is_user != b.is_user) return !a.is_user; // prefer system over user return false; });