diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 5713b25c8..dc6dd8e68 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -371,19 +371,28 @@ public: size_t i = m_default_suppressed ? m_num_default_presets : 0; size_t n = this->m_presets.size(); size_t i_compatible = n; + int match_quality = -1; for (; i < n; ++ i) // Since we use the filament selection from Wizard, it's needed to control the preset visibility too if (m_presets[i].is_compatible && m_presets[i].is_visible) { - if (prefered_condition(m_presets[i].name)) - return i; - if (i_compatible == n) - // Store the first compatible profile into i_compatible. + int this_match_quality = prefered_condition(m_presets[i]); + if (this_match_quality > match_quality) { + if (match_quality == std::numeric_limits::max()) + // Better match will not be found. + return i; + // Store the first compatible profile with highest match quality into i_compatible. i_compatible = i; + match_quality = this_match_quality; + } } - return (i_compatible == n) ? 0 : i_compatible; + return (i_compatible == n) ? + // No compatible preset found, return the default preset. + 0 : + // Compatible preset found. + i_compatible; } // Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible. - size_t first_compatible_idx() const { return this->first_compatible_idx([](const std::string&){return true;}); } + size_t first_compatible_idx() const { return this->first_compatible_idx([](const Preset&) -> int { return 0; }); } // Return index of the first visible preset. Certainly at least the '- default -' preset shall be visible. // Return the first visible preset. Certainly at least the '- default -' preset shall be visible. @@ -407,7 +416,7 @@ public: this->select_preset(this->first_compatible_idx(prefered_condition)); } void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType select_other_if_incompatible) - { this->update_compatible(active_printer, active_print, select_other_if_incompatible, [](const std::string&){return true;}); } + { this->update_compatible(active_printer, active_print, select_other_if_incompatible, [](const Preset&) -> int { return 0; }); } size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 4309f0732..4a986ec40 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1439,50 +1439,67 @@ void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_pri const Preset &printer_preset = this->printers.get_edited_preset(); const PresetWithVendorProfile printer_preset_with_vendor_profile = this->printers.get_preset_with_vendor_profile(printer_preset); + class PreferedProfileMatch + { + public: + PreferedProfileMatch(const std::string &prefered_alias, const std::string &prefered_name) : + m_prefered_alias(prefered_alias), m_prefered_name(prefered_name) {} + + int operator()(const Preset &preset) const + { + return (! m_prefered_alias.empty() && m_prefered_alias == preset.alias) ? + // Matching an alias, always take this preset with priority. + std::numeric_limits::max() : + // Otherwise take the prefered profile, or the first compatible. + preset.name == m_prefered_name; + } + + private: + const std::string m_prefered_alias; + const std::string &m_prefered_name; + }; + switch (printer_preset.printer_technology()) { case ptFFF: { assert(printer_preset.config.has("default_print_profile")); assert(printer_preset.config.has("default_filament_profile")); - const std::string &prefered_print_profile = printer_preset.config.opt_string("default_print_profile"); const std::vector &prefered_filament_profiles = printer_preset.config.option("default_filament_profile")->values; - prefered_print_profile.empty() ? - this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible) : - this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, - [&prefered_print_profile](const std::string& profile_name) { return profile_name == prefered_print_profile; }); + this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, + PreferedProfileMatch(this->prints.get_edited_preset().alias, printer_preset.config.opt_string("default_print_profile"))); const PresetWithVendorProfile print_preset_with_vendor_profile = this->prints.get_edited_preset_with_vendor_profile(); // Remember whether the filament profiles were compatible before updating the filament compatibility. std::vector filament_preset_was_compatible(this->filament_presets.size(), false); for (size_t idx = 0; idx < this->filament_presets.size(); ++ idx) { - std::string &filament_name = this->filament_presets[idx]; - Preset *preset = this->filaments.find_preset(filament_name, false); + Preset *preset = this->filaments.find_preset(this->filament_presets[idx], false); filament_preset_was_compatible[idx] = preset != nullptr && preset->is_compatible; } - prefered_filament_profiles.empty() ? - this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_filament_if_incompatible) : - this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_filament_if_incompatible, - [&prefered_filament_profiles](const std::string& profile_name) - { return std::find(prefered_filament_profiles.begin(), prefered_filament_profiles.end(), profile_name) != prefered_filament_profiles.end(); }); + // First select a first compatible profile for the preset editor. + std::string prev_filament_alias = this->filaments.get_edited_preset().alias; + this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_filament_if_incompatible, + [&prev_filament_alias, &prefered_filament_profiles](const Preset &preset) -> int { + return (! prev_filament_alias.empty() && prev_filament_alias == preset.alias) ? + // Matching an alias, always take this preset with priority. + std::numeric_limits::max() : + // Otherwise take the prefered profile, or the first compatible, any is good for the preset editor. + std::find(prefered_filament_profiles.begin(), prefered_filament_profiles.end(), preset.name) != prefered_filament_profiles.end(); + }); if (select_other_filament_if_incompatible != PresetSelectCompatibleType::Never) { // Verify validity of the current filament presets. + const std::string prefered_filament_profile = prefered_filament_profiles.empty() ? std::string() : prefered_filament_profiles.front(); if (this->filament_presets.size() == 1) { + // The compatible profile should have been already selected for the preset editor. Just use it. if (select_other_filament_if_incompatible == PresetSelectCompatibleType::Always || filament_preset_was_compatible.front()) this->filament_presets.front() = this->filaments.get_edited_preset().name; } else { for (size_t idx = 0; idx < this->filament_presets.size(); ++ idx) { std::string &filament_name = this->filament_presets[idx]; Preset *preset = this->filaments.find_preset(filament_name, false); - if (preset == nullptr || (! preset->is_compatible && (select_other_filament_if_incompatible == PresetSelectCompatibleType::Always || filament_preset_was_compatible[idx]))) { + if (preset == nullptr || (! preset->is_compatible && (select_other_filament_if_incompatible == PresetSelectCompatibleType::Always || filament_preset_was_compatible[idx]))) // Pick a compatible profile. If there are prefered_filament_profiles, use them. - if (prefered_filament_profiles.empty()) - filament_name = this->filaments.first_compatible().name; - else { - const std::string &preferred = (idx < prefered_filament_profiles.size()) ? - prefered_filament_profiles[idx] : prefered_filament_profiles.front(); - filament_name = this->filaments.first_compatible( - [&preferred](const std::string& profile_name) { return profile_name == preferred; }).name; - } - } + filament_name = this->filaments.first_compatible( + PreferedProfileMatch(preset ? preset->alias : std::string(), + (idx < prefered_filament_profiles.size()) ? prefered_filament_profiles[idx] : prefered_filament_profile)).name; } } } @@ -1492,17 +1509,11 @@ void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_pri { assert(printer_preset.config.has("default_sla_print_profile")); assert(printer_preset.config.has("default_sla_material_profile")); - const PresetWithVendorProfile sla_print_preset_with_vendor_profile = this->sla_prints.get_edited_preset_with_vendor_profile(); - const std::string &prefered_sla_print_profile = printer_preset.config.opt_string("default_sla_print_profile"); - (prefered_sla_print_profile.empty()) ? - this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible) : - this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, - [&prefered_sla_print_profile](const std::string& profile_name){ return profile_name == prefered_sla_print_profile; }); - const std::string &prefered_sla_material_profile = printer_preset.config.opt_string("default_sla_material_profile"); - prefered_sla_material_profile.empty() ? - this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_filament_if_incompatible) : - this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_filament_if_incompatible, - [&prefered_sla_material_profile](const std::string& profile_name){ return profile_name == prefered_sla_material_profile; }); + this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, + PreferedProfileMatch(this->sla_prints.get_edited_preset().alias, printer_preset.config.opt_string("default_sla_print_profile"))); + const PresetWithVendorProfile sla_print_preset_with_vendor_profile = this->sla_prints.get_edited_preset_with_vendor_profile(); + this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_filament_if_incompatible, + PreferedProfileMatch(this->sla_materials.get_edited_preset().alias, printer_preset.config.opt_string("default_sla_material_profile"))); break; } default: break;