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.
This commit is contained in:
grant0013
2026-05-19 15:05:03 +00:00
parent 5631637efa
commit c4804e0d80
2 changed files with 19 additions and 55 deletions

View File

@@ -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<int, DynamicPrintConfig> 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<int, std::string> 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);

View File

@@ -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;
});