From 6dbb5f3b0673a0b4f34c1f03c66cafe1e1861a99 Mon Sep 17 00:00:00 2001 From: Ian Chua Date: Mon, 5 Oct 2026 15:20:25 +0800 Subject: [PATCH] refactor: support generic virtual external spool slots --- src/slic3r/GUI/DeviceCore/DevDefs.h | 6 +-- src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp | 52 ++++++++++++++++++--- src/slic3r/GUI/DeviceCore/DevFilaSystem.h | 4 +- src/slic3r/GUI/DeviceManager.cpp | 25 ++++++---- tests/slic3rutils/test_dev_mapping.cpp | 9 ++++ 5 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/slic3r/GUI/DeviceCore/DevDefs.h b/src/slic3r/GUI/DeviceCore/DevDefs.h index 6332d6b109..34469c7d43 100644 --- a/src/slic3r/GUI/DeviceCore/DevDefs.h +++ b/src/slic3r/GUI/DeviceCore/DevDefs.h @@ -163,8 +163,8 @@ public: ~devPrinterUtil() = delete; public: - static bool IsVirtualSlot(int ams_id) { return (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID);} - static bool IsVirtualSlot(const std::string& ams_id) { return (ams_id == VIRTUAL_AMS_MAIN_ID_STR || ams_id == VIRTUAL_AMS_DEPUTY_ID_STR); } + static bool IsVirtualSlot(int ams_id); + static bool IsVirtualSlot(const std::string& ams_id); }; namespace GUI @@ -200,4 +200,4 @@ template<> struct std::hash }; // key(extruder_id) -> { key1(nozzle type info), val1( number of the nozzle type)} -using ExtruderNozzleInfos = std::unordered_map>; \ No newline at end of file +using ExtruderNozzleInfos = std::unordered_map>; diff --git a/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp b/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp index 0e8b1ea12b..b72b803c4e 100644 --- a/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp +++ b/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp @@ -33,6 +33,25 @@ using namespace nlohmann; namespace Slic3r { + +bool devPrinterUtil::IsVirtualSlot(int ams_id) +{ + if (wxTheApp == nullptr || GUI::wxGetApp().preset_bundle == nullptr || GUI::wxGetApp().preset_bundle->is_bbl_vendor()) + return ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID; + + const int extruder_count = GUI::wxGetApp().preset_bundle->get_printer_extruder_count(); + return ams_id >= VIRTUAL_TRAY_MAIN_ID - extruder_count + 1 && ams_id <= VIRTUAL_TRAY_MAIN_ID; +} + +bool devPrinterUtil::IsVirtualSlot(const std::string& ams_id) +{ + try { + return IsVirtualSlot(std::stoi(ams_id)); + } catch (...) { + return false; + } +} + static int _hex_digit_to_int(const char c) { return (c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1; } wxColour DevAmsTray::decode_color(const std::string &color) @@ -302,13 +321,21 @@ int DevFilaSystem::GetExtruderIdByAmsId(const std::string& ams_id) const { return it->second->GetExtruderId(); } - else if (stoi(ams_id) == VIRTUAL_TRAY_MAIN_ID) - { - return MAIN_EXTRUDER_ID; + + const bool is_bbl_vendor = wxTheApp != nullptr && GUI::wxGetApp().preset_bundle != nullptr && GUI::wxGetApp().preset_bundle->is_bbl_vendor(); + if (!is_bbl_vendor && GetOwner()) { + for (const auto& tray : GetOwner()->vt_slot) { + if (tray.id == ams_id) + return VIRTUAL_TRAY_MAIN_ID - std::stoi(ams_id); + } } - else if (stoi(ams_id) == VIRTUAL_TRAY_DEPUTY_ID) - { + + if (is_bbl_vendor && ams_id == VIRTUAL_AMS_MAIN_ID_STR) + return MAIN_EXTRUDER_ID; + if (is_bbl_vendor && ams_id == VIRTUAL_AMS_DEPUTY_ID_STR) return DEPUTY_EXTRUDER_ID; + if (!is_bbl_vendor && devPrinterUtil::IsVirtualSlot(ams_id)) { + return VIRTUAL_TRAY_MAIN_ID - std::stoi(ams_id); } assert(false && __FUNCTION__); @@ -325,8 +352,19 @@ std::string DevFilaSystem::GetNozzleFlowStringByAmsId(const std::string& ams_id) std::map DevFilaSystem::GetTrayIndexMap() { std::map tray_id_map; - tray_id_map[VIRTUAL_TRAY_MAIN_ID] = DevAmsSlotId{VIRTUAL_TRAY_MAIN_ID, 0}; - tray_id_map[VIRTUAL_TRAY_DEPUTY_ID] = DevAmsSlotId{VIRTUAL_TRAY_DEPUTY_ID, 0}; + if (wxTheApp != nullptr && GUI::wxGetApp().preset_bundle != nullptr && GUI::wxGetApp().preset_bundle->is_bbl_vendor()) { + tray_id_map[VIRTUAL_TRAY_MAIN_ID] = DevAmsSlotId{VIRTUAL_TRAY_MAIN_ID, 0}; + tray_id_map[VIRTUAL_TRAY_DEPUTY_ID] = DevAmsSlotId{VIRTUAL_TRAY_DEPUTY_ID, 0}; + } else if (GetOwner()) { + for (const auto& tray : GetOwner()->vt_slot) { + try { + const int tray_id = std::stoi(tray.id); + tray_id_map[tray_id] = DevAmsSlotId{tray_id, 0}; + } catch (...) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " invalid virtual tray id: " << tray.id; + } + } + } for (auto& [ams_id, ams_item] : GetAmsList()) { for (auto &[slot_id, slot_item] : ams_item->GetTrays()) { diff --git a/src/slic3r/GUI/DeviceCore/DevFilaSystem.h b/src/slic3r/GUI/DeviceCore/DevFilaSystem.h index 32edc06a32..ee9079a5c4 100644 --- a/src/slic3r/GUI/DeviceCore/DevFilaSystem.h +++ b/src/slic3r/GUI/DeviceCore/DevFilaSystem.h @@ -349,7 +349,7 @@ public: DevAmsTray* GetAmsTray(const std::string& ams_id, const std::string& tray_id) const; void CollectAmsColors(std::vector& ams_colors) const; - // Map a linear tray index -> {ams_id, slot_id}. Includes the two virtual (external-spool) trays, + // Map a linear tray index -> {ams_id, slot_id}. Includes virtual external-spool trays, // N3S single-slot units, and the A2L/N9 AMS-Lite-mixed layout (trays 24-27). std::map GetTrayIndexMap(); @@ -434,4 +434,4 @@ struct DevFilamentDryingPreset float filament_dev_ams_drying_heat_distortion_temperature = 0.0f; }; -}// namespace Slic3r \ No newline at end of file +}// namespace Slic3r diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 0656463a51..38b2b0bdd3 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -5266,16 +5266,17 @@ DevAmsTray MachineObject::parse_vt_tray(json vtray) bool MachineObject::contains_tray(const std::string &ams_id, const std::string &tray_id) const { - if (ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) { - + const bool is_bbl_vendor = wxTheApp != nullptr && GUI::wxGetApp().preset_bundle != nullptr && GUI::wxGetApp().preset_bundle->is_bbl_vendor(); + if (is_bbl_vendor && ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) return m_fila_system->GetAmsTray(ams_id, tray_id) != nullptr; - } else { + + if (!is_bbl_vendor || ams_id == VIRTUAL_AMS_MAIN_ID_STR || ams_id == VIRTUAL_AMS_DEPUTY_ID_STR) { for (const auto& tray : vt_slot) { - if (tray.id == ams_id) { return true; } + if (tray.id == ams_id) return true; } } - return false; + return !is_bbl_vendor && m_fila_system->GetAmsTray(ams_id, tray_id) != nullptr; } DevAmsTray MachineObject::get_tray(const std::string &ams_id, const std::string &tray_id) const @@ -5285,13 +5286,19 @@ DevAmsTray MachineObject::get_tray(const std::string &ams_id, const std::string return DevAmsTray(tray_id); } - if (ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) { + const bool is_bbl_vendor = wxTheApp != nullptr && GUI::wxGetApp().preset_bundle != nullptr && GUI::wxGetApp().preset_bundle->is_bbl_vendor(); + if (is_bbl_vendor && ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) { auto tray = m_fila_system->GetAmsTray(ams_id, tray_id); - if (tray) { return *tray;}; + if (tray) return *tray; } - else { + else if (!is_bbl_vendor || ams_id == VIRTUAL_AMS_MAIN_ID_STR || ams_id == VIRTUAL_AMS_DEPUTY_ID_STR) { for (const auto &tray : vt_slot) { - if (tray.id == ams_id) { return tray; } + if (tray.id == ams_id) return tray; + } + + if (!is_bbl_vendor) { + auto tray = m_fila_system->GetAmsTray(ams_id, tray_id); + if (tray) return *tray; } } diff --git a/tests/slic3rutils/test_dev_mapping.cpp b/tests/slic3rutils/test_dev_mapping.cpp index ce4727d68f..5869e08946 100644 --- a/tests/slic3rutils/test_dev_mapping.cpp +++ b/tests/slic3rutils/test_dev_mapping.cpp @@ -87,6 +87,15 @@ TEST_CASE("Agent external filament slots preserve every extruder", "[DevFilaSyst CHECK(obj.vt_slot[1].setting_id == "P1"); CHECK(obj.vt_slot[2].setting_id == "P2"); CHECK(obj.vt_slot[3].setting_id == "P3"); + + CHECK(obj.contains_tray("253", "0")); + CHECK(obj.get_tray("253", "0").setting_id == "P2"); + CHECK(obj.GetFilaSystem()->GetExtruderIdByAmsId("253") == 2); + + const auto tray_index_map = obj.GetFilaSystem()->GetTrayIndexMap(); + REQUIRE(tray_index_map.count(252) == 1); + CHECK(tray_index_map.at(252).first == 252); + CHECK(tray_index_map.at(252).second == 0); } TEST_CASE("Switch-bound AMS trays map to the left extruder", "[DevMapping]")