diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index a1d5f576cb..f230a11087 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1388,7 +1388,7 @@ void PresetCollection::load_presets( } if (presets_loaded.size() > 0) m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end())); - std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); + sort_presets(); //BBS: add config related logs BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": loaded %1% presets from %2%, type %3%")%presets_loaded.size() %dir %Preset::get_type_string(m_type); //this->select_preset(first_visible_idx()); @@ -1583,7 +1583,7 @@ void PresetCollection::load_project_embedded_presets(std::vector& proje } m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end())); - std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); + sort_presets(); //don't select it here //this->select_preset(first_visible_idx()); unlock(); @@ -1976,7 +1976,7 @@ void PresetCollection::update_after_user_presets_loaded() lock(); std::string selected_name = get_selected_preset_name(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", before sort, type %1%, selected_idx %2%, selected_name %3%") %m_type %m_idx_selected %selected_name; - std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); + sort_presets(); this->select_preset_by_name(selected_name, false); unlock(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", after sort, type %1%, selected_idx %2%") %m_type %m_idx_selected; @@ -3129,7 +3129,9 @@ std::vector PresetCollection::merge_presets(PresetCollection &&othe if (preset.is_default || preset.is_external) continue; Preset key(m_type, preset.name); - auto it = std::lower_bound(m_presets.begin() + m_num_default_presets, m_presets.end(), key); + auto it = (m_type == Preset::TYPE_FILAMENT) + ? std::lower_bound(m_presets.begin() + m_num_default_presets, m_presets.end(), key, filament_preset_less) + : std::lower_bound(m_presets.begin() + m_num_default_presets, m_presets.end(), key); if (it == m_presets.end() || it->name != preset.name) { if (preset.vendor != nullptr) { // Re-assign a pointer to the vendor structure in the new PresetBundle. diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 6afda07426..e1c3f57f33 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,8 @@ #define ORCA_JSON_KEY_RENAMED_FROM "renamed_from" +static constexpr const char* GENERIC_PREFIX = "Generic "; + namespace Slic3r { class AppConfig; @@ -764,13 +767,39 @@ protected: void set_custom_preset_alias(Preset &preset); private: + // Comparator that sorts "Generic " prefixed presets before others, then alphabetically within each group. + static bool filament_preset_less(const Preset &a, const Preset &b) { + bool a_generic = boost::starts_with(a.name, GENERIC_PREFIX); + bool b_generic = boost::starts_with(b.name, GENERIC_PREFIX); + if (a_generic != b_generic) + return a_generic; // generics first + return a.name < b.name; + } + + // Sort presets: filament presets use generic-first ordering, others sort alphabetically. + void sort_presets() { + if (m_type == Preset::TYPE_FILAMENT) + std::sort(m_presets.begin() + m_num_default_presets, m_presets.end(), filament_preset_less); + else + std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); + } + // Find a preset position in the sorted list of presets. // The "-- default -- " preset is always the first, so it needs // to be handled differently. // If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name. std::deque::iterator find_preset_internal(const std::string &name, bool from_orca_lib_only = false) { - auto it = Slic3r::lower_bound_by_predicate(m_presets.begin() + m_num_default_presets, m_presets.end(), [&name](const auto& l) { return l.name < name; }); + auto it = Slic3r::lower_bound_by_predicate(m_presets.begin() + m_num_default_presets, m_presets.end(), + [&name, this](const auto& l) { + if (m_type == Preset::TYPE_FILAMENT) { + bool l_generic = boost::starts_with(l.name, GENERIC_PREFIX); + bool name_generic = boost::starts_with(name, GENERIC_PREFIX); + if (l_generic && !name_generic) return true; + if (!l_generic && name_generic) return false; + } + return l.name < name; + }); if (it == m_presets.end() || it->name != name) { // Preset has not been not found in the sorted list of non-default presets. Try the defaults. for (size_t i = 0; i < m_num_default_presets; ++ i)