From 86421c637874b7b15b9d03cace067efac676ad16 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 1 Feb 2026 23:53:29 +0800 Subject: [PATCH] Use visible preset lookup for AMS filament fallback to ensure persistence across restarts --- src/libslic3r/Preset.cpp | 42 +++++++++++++++++++++- src/libslic3r/Preset.hpp | 5 +++ src/slic3r/Utils/MoonrakerPrinterAgent.cpp | 7 ++-- src/slic3r/Utils/QidiPrinterAgent.cpp | 30 +++++++++++++++- src/slic3r/Utils/SnapmakerPrinterAgent.cpp | 7 +++- 5 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index d711cdd010..d0353e2ed1 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -2764,7 +2764,7 @@ size_t PresetCollection::first_visible_idx() const size_t first_visible = -1; size_t idx = m_default_suppressed ? m_num_default_presets : 0; for (; idx < m_presets.size(); ++ idx) - if (m_presets[idx].is_visible && m_presets[idx].get_printer_id() == "BBL") { + if (m_presets[idx].is_visible && m_presets[idx].get_printer_id() == PresetBundle::ORCA_FILAMENT_LIBRARY) { if (first_visible == -1) first_visible = idx; if (m_type != Preset::TYPE_FILAMENT) @@ -2785,6 +2785,46 @@ size_t PresetCollection::first_visible_idx() const return first_visible; } +size_t PresetCollection::first_visible_idx_by_type(const std::string& filament_type) const +{ + size_t start = m_default_suppressed ? m_num_default_presets : 0; + + // Find the first visible, compatible, system base preset whose filament_type matches target. + auto find_by_type = [&](const std::string& target) -> size_t { + for (size_t i = start; i < m_presets.size(); ++i) { + const auto& p = m_presets[i]; + if (p.is_visible && p.is_compatible && p.is_system + && get_preset_base(p) == &p + && p.config.opt_string("filament_type", 0u) == target) + return i; + } + return size_t(-1); + }; + + // 1. Exact filament_type match + size_t idx = find_by_type(filament_type); + if (idx != size_t(-1)) + return idx; + + // 2. Base type fallback: strip modifier after first space + // e.g. "PLA High Speed" -> "PLA" + // Dash-separated types like "PA-CF", "PET-CF" are distinct materials, not modifiers. + auto sep = filament_type.find(' '); + if (sep != std::string::npos) { + idx = find_by_type(filament_type.substr(0, sep)); + if (idx != size_t(-1)) + return idx; + } + + // 3. Any visible preset + return first_visible_idx(); +} + +std::string PresetCollection::filament_id_by_type(const std::string& filament_type) const +{ + return preset(first_visible_idx_by_type(filament_type)).filament_id; +} + std::vector PresetCollection::diameters_of_selected_printer() { std::set diameters; diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index f2c6b889ad..d76f2b93c2 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -638,6 +638,11 @@ public: return const_cast(this)->find_preset2(name, auto_match); } size_t first_visible_idx() const; + // Return the index of the first visible, compatible, system base preset + // matching the given filament_type. Falls back to base type, then any visible. + size_t first_visible_idx_by_type(const std::string& filament_type) const; + // Return the filament_id of the best-matching visible preset for the given filament type. + std::string filament_id_by_type(const std::string& filament_type) const; // Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible. // If one of the prefered_alternates is compatible, select it. template size_t first_compatible_idx(PreferedCondition prefered_condition) const diff --git a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp index a49c69fc10..6a86224bf9 100644 --- a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp +++ b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp @@ -704,7 +704,10 @@ bool MoonrakerPrinterAgent::fetch_filament_info(std::string dev_id) tray.bed_temp = safe_int(lane_obj, "bed_temp"); tray.nozzle_temp = safe_int(lane_obj, "nozzle_temp"); tray.has_filament = !tray.tray_type.empty(); - tray.tray_info_idx = map_filament_type_to_generic_id(tray.tray_type); + auto* bundle = GUI::wxGetApp().preset_bundle; + tray.tray_info_idx = bundle + ? bundle->filaments.filament_id_by_type(tray.tray_type) + : map_filament_type_to_generic_id(tray.tray_type); max_lane_index = std::max(max_lane_index, lane_index); trays.push_back(tray); @@ -780,7 +783,7 @@ std::string MoonrakerPrinterAgent::map_filament_type_to_generic_id(const std::st if (upper == "COPE") return "OGFLC99"; if (upper == "SBS") return "OFLSBS99"; - // Unknown material + // Unknown material return UNKNOWN_FILAMENT_ID; } diff --git a/src/slic3r/Utils/QidiPrinterAgent.cpp b/src/slic3r/Utils/QidiPrinterAgent.cpp index e34dbe855a..8a440b6c29 100644 --- a/src/slic3r/Utils/QidiPrinterAgent.cpp +++ b/src/slic3r/Utils/QidiPrinterAgent.cpp @@ -1,5 +1,7 @@ #include "QidiPrinterAgent.hpp" #include "Http.hpp" +#include "libslic3r/PresetBundle.hpp" +#include "slic3r/GUI/GUI_App.hpp" #include "nlohmann/json.hpp" #include @@ -9,6 +11,22 @@ namespace Slic3r { +namespace { + +// Check whether any visible, compatible base preset in the collection has the given filament_id. +bool has_visible_base_preset(const PresetCollection& filaments, const std::string& filament_id) +{ + for (const auto& p : filaments.get_presets()) { + if (p.is_visible && p.is_compatible + && filaments.get_preset_base(p) == &p + && p.filament_id == filament_id) + return true; + } + return false; +} + +} // anonymous namespace + const std::string QidiPrinterAgent_VERSION = "0.0.1"; QidiPrinterAgent::QidiPrinterAgent(std::string log_dir) : MoonrakerPrinterAgent(std::move(log_dir)) @@ -157,7 +175,17 @@ bool QidiPrinterAgent::fetch_slot_info(const std::string& base_url, filament_name = filament_it->second; } tray.tray_type = normalize_filament_type(filament_name); - tray.tray_info_idx = build_setting_id(filament_type, vendor_type, tray.tray_type); + + // Try Qidi-specific setting ID first; fall back to visible preset by type + std::string setting_id = build_setting_id(filament_type, vendor_type, tray.tray_type); + auto* bundle = GUI::wxGetApp().preset_bundle; + if (!bundle) { + tray.tray_info_idx = setting_id; + } else if (!setting_id.empty() && has_visible_base_preset(bundle->filaments, setting_id)) { + tray.tray_info_idx = setting_id; + } else { + tray.tray_info_idx = bundle->filaments.filament_id_by_type(tray.tray_type); + } // Look up color from dictionary auto color_it = dict.colors.find(color_index); diff --git a/src/slic3r/Utils/SnapmakerPrinterAgent.cpp b/src/slic3r/Utils/SnapmakerPrinterAgent.cpp index a352ee889a..a7dda3fcd6 100644 --- a/src/slic3r/Utils/SnapmakerPrinterAgent.cpp +++ b/src/slic3r/Utils/SnapmakerPrinterAgent.cpp @@ -1,5 +1,7 @@ #include "SnapmakerPrinterAgent.hpp" #include "Http.hpp" +#include "libslic3r/PresetBundle.hpp" +#include "slic3r/GUI/GUI_App.hpp" #include "nlohmann/json.hpp" #include @@ -133,7 +135,10 @@ bool SnapmakerPrinterAgent::fetch_filament_info(std::string dev_id) if (tray.has_filament) { tray.tray_type = combine_filament_type(safe_at(filament_type, i, empty_str), safe_at(filament_sub_type, i, empty_str)); - tray.tray_info_idx = map_filament_type_to_generic_id(tray.tray_type); + auto* bundle = GUI::wxGetApp().preset_bundle; + tray.tray_info_idx = bundle + ? bundle->filaments.filament_id_by_type(tray.tray_type) + : map_filament_type_to_generic_id(tray.tray_type); tray.tray_color = safe_at(filament_color, i, default_color); // Extract NFC temperature data if available