Bug fix for perfect name matching

This commit is contained in:
Lam Wei Lun
2026-08-19 16:57:45 +08:00
parent 2e0ef11b0f
commit aeaa3c5d66
6 changed files with 242 additions and 16 deletions
+28 -10
View File
@@ -4894,11 +4894,19 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// Mirror first_visible_idx()'s start index so suppressed default presets are
// never picked as a slot material.
const size_t first_candidate = this->filaments.is_default_suppressed() ? this->filaments.num_default_presets() : 0;
// Candidate preference for a published entry: exact setting_id (variant-level,
// since "Generic PLA" and "Generic PLA Matte" share filament_id), then exact
// filament_id, then vendor+type, then type only (a type-only pick may surface an
// unrelated preset, e.g. a different vendor's PLA).
// Candidate preference for a published entry: exact preset name (unambiguous
// even when ids are shared between variants or missing from older files), then
// exact setting_id (variant-level, since "Generic PLA" and "Generic PLA Matte"
// share filament_id), then exact filament_id, then vendor+type, then type only
// (a type-only pick may surface an unrelated preset, e.g. a different vendor's
// PLA).
auto candidate_score = [](const Preset &candidate, const PublishedMaterialEntry &entry) -> int {
if (!entry.preset_name.empty()) {
const std::string bare_name = entry.preset_name.substr(0, entry.preset_name.find('@'));
if (candidate.name == entry.preset_name || candidate.alias == entry.preset_name ||
candidate.name == bare_name || candidate.alias == bare_name)
return 4;
}
if (!entry.setting_id.empty() && candidate.setting_id == entry.setting_id)
return 3;
const ConfigOptionStrings *types = candidate.config.opt<ConfigOptionStrings>("filament_type");
@@ -4926,10 +4934,13 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
int best_score = -1;
for (size_t i = first_candidate; i < this->filaments.size(); ++i) {
const Preset &candidate = this->filaments.preset(i);
if (!candidate.is_visible || used_preset_names.count(candidate.name) != 0)
continue;
const int score = candidate_score(candidate, entry);
if (score > best_score) {
// Exact identity tiers (name / setting_id) win even when the
// preset is hidden or already referenced by another slot; the
// alias re-pointing pass below still de-aliases afterwards.
if (score < 3 && (!candidate.is_visible || used_preset_names.count(candidate.name) != 0))
continue;
best_score = score;
initial_preset = candidate.name;
}
@@ -4979,9 +4990,13 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
continue;
for (size_t i = first_candidate; i < this->filaments.size(); ++i) {
const Preset &candidate = this->filaments.preset(i);
if (!candidate.is_visible || referenced_elsewhere(candidate.name, size_t(-1)))
continue;
const int score = candidate_score(candidate, entry);
// Exact identity tiers (name / setting_id) may use a hidden preset;
// the referenced check stays: re-pointing exists to de-alias.
if (score < 3 && !candidate.is_visible)
continue;
if (referenced_elsewhere(candidate.name, size_t(-1)))
continue;
if (score > best_score) {
best_score = score;
replacement = candidate.name;
@@ -5106,11 +5121,14 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
std::string best_name;
for (size_t i = first_candidate; i < this->filaments.size(); ++i) {
const Preset &candidate = this->filaments.preset(i);
if (!candidate.is_visible)
continue;
const int score = candidate_score(candidate, entry);
if (score <= best_score)
continue;
// Lower tiers (vendor+type, type only) need a visible preset;
// an exact identity match (name / setting_id) wins even when
// the preset is hidden in the library.
if (score < 3 && !candidate.is_visible)
continue;
if (unreferenced_only) {
bool used = false;
for (size_t s = 0; s < this->filament_presets.size(); ++s)
+4
View File
@@ -40,6 +40,10 @@ struct PublishedMaterialEntry {
// used on load to match the exact published variant, which filament_id alone cannot
// distinguish ("Generic PLA" and "Generic PLA Matte" share their inherited id).
std::string setting_id;
// Canonical name of the author's slot preset (e.g. "Generic PLA @System"). The receiver
// prefers an exact name/alias match over id matching: ids can be shared across variants
// or missing from older files, the name is what the author actually selected.
std::string preset_name;
// 0-based author filament slot; -1 (hand-crafted files) is skipped.
int slot{-1};
std::vector<std::string> keys;
+3 -1
View File
@@ -7252,6 +7252,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
entry.filament_id = mat["filament_id"].get<std::string>();
if (mat.contains("setting_id") && mat["setting_id"].is_string())
entry.setting_id = mat["setting_id"].get<std::string>();
if (mat.contains("name") && mat["name"].is_string())
entry.preset_name = mat["name"].get<std::string>();
}
if (m.contains("slot") && m["slot"].is_number_integer())
entry.slot = m["slot"].get<int>();
@@ -16251,7 +16253,7 @@ int Plater::export_published_3mf(const std::vector<std::string>& published_keys,
j.push_back(key);
nlohmann::json jm = nlohmann::json::array();
for (const Slic3r::PublishedMaterialEntry& e : material_keys)
jm.push_back({ {"material", {{"filament_type", e.filament_type}, {"filament_vendor", e.filament_vendor}, {"filament_id", e.filament_id}, {"setting_id", e.setting_id}}}, {"slot", e.slot}, {"keys", e.keys},
jm.push_back({ {"material", {{"filament_type", e.filament_type}, {"filament_vendor", e.filament_vendor}, {"filament_id", e.filament_id}, {"setting_id", e.setting_id}, {"name", e.preset_name}}}, {"slot", e.slot}, {"keys", e.keys},
{"full", e.full}, {"full_keys", e.full_keys},
{"publish_type", e.publish_type}, {"type", e.publish_type_value},
{"publish_color", e.publish_color}, {"color", e.color} });
+6 -3
View File
@@ -924,11 +924,14 @@ std::vector<Slic3r::PublishedMaterialEntry> PublishSettingsDialog::GetPublishedM
entry.filament_id = cat.filament_id;
entry.slot = static_cast<int>(cat.filament_slot);
// The author's preset id distinguishes exact variants that share filament_id
// ("Generic PLA" vs "Generic PLA Matte"), so the receiver can match precisely.
// ("Generic PLA" vs "Generic PLA Matte"), so the receiver can match precisely; the
// preset name is the most direct identity and is matched first on load.
PresetBundle *bundle = wxGetApp().preset_bundle;
if (bundle != nullptr && cat.filament_slot < bundle->filament_presets.size()) {
if (const Preset *preset = bundle->filaments.find_preset(bundle->filament_presets[cat.filament_slot], false, true))
entry.setting_id = preset->setting_id;
if (const Preset *preset = bundle->filaments.find_preset(bundle->filament_presets[cat.filament_slot], false, true)) {
entry.setting_id = preset->setting_id;
entry.preset_name = preset->name;
}
}
// "Full Publish": the whole filament preset is embedded; type and colour are implicitly
// published, and the per-key rows are disabled / their state ignored.