From 45932dd95697c76031b5ce43016697533a4a622f Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Thu, 8 Oct 2026 19:07:56 -0400 Subject: [PATCH] Leave the AFC lane sync out of the IMEX work MoonrakerPrinterAgent filled physical_extruder_map from AFC's per-lane extruder_index whenever the printer's filaments were synced. IMEX does not need it: printers carry their map in the printer profile, and IMEX reads it from there. The sync also wrote device state into the edited printer preset, so a sync could mark the preset modified or replace a hand-tuned map. The two Moonraker agent files go back to upstream's version. The sync can return separately, writing the map somewhere other than the printer preset. Co-Authored-By: Claude Opus 5.5 --- src/libslic3r/PresetBundle.cpp | 4 +- src/slic3r/Utils/MoonrakerPrinterAgent.cpp | 79 ---------------------- src/slic3r/Utils/MoonrakerPrinterAgent.hpp | 1 - 3 files changed, 1 insertion(+), 83 deletions(-) diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index eaedc5405c..beaa5a6a42 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -119,9 +119,7 @@ static std::vector s_project_options { // project_config's default [0] to clobber the preset's authored value // (e.g. AFC-shaped [0,1,1,1,1]) during full_fff_config() merge, and the // clobbered value then rode into saved 3mfs and back into the edited - // preset on reload. MoonrakerPrinterAgent's runtime set_key_value still - // works — it creates the option on project_config on demand without - // needing it pre-initialized here. + // preset on reload. // Per-filament nozzle-volume choice; project-level like filament_map so the per-filament // slot resolution survives preset switches. "filament_volume_map", diff --git a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp index a23c1cde2e..96570b656b 100644 --- a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp +++ b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,6 @@ #include #include #include -#include namespace { @@ -572,79 +570,6 @@ bool MoonrakerPrinterAgent::fetch_filament_info(std::string dev_id, FilamentSync << (max_lane_index + 1) << " lanes"; int ams_count = (max_lane_index + 4) / 4; build_ams_payload(ams_count, max_lane_index, trays); - - // If every tray reported extruder_index, auto-populate physical_extruder_map on an - // IMEX printer so IMEX PA and temperature emission use the correct physical extruder - // qualifier. AFC publishes extruder_index=0 for all AFC lanes (they share one carriage) - // and extruder_index=N for independent direct-drive tools on separate carriages. - // The write itself is gated below, on the GUI thread, where the preset can be read. - bool all_have_extruder_index = std::all_of(trays.begin(), trays.end(), - [](const AmsTrayData& t) { return t.extruder_index >= 0; }); - if (all_have_extruder_index) { - std::vector pem(max_lane_index + 1, 0); - for (const auto& tray : trays) - if (tray.slot_index >= 0 && tray.slot_index <= max_lane_index) - pem[tray.slot_index] = tray.extruder_index; - // Record which device this map came from. The write below targets whichever - // printer preset is being edited when the callback runs, and nothing else here - // establishes the two are the same machine: two IMEX printers of different models - // with the same logical extruder count would both pass every check below. - const std::string src_dev_id = device_info.dev_id; - wxTheApp->CallAfter([pem, src_dev_id]() { - auto* bundle = GUI::wxGetApp().preset_bundle; - if (!bundle) return; - auto& preset = bundle->printers.get_edited_preset(); - auto& config = preset.config; - - // Pair device to preset at callback time, on the predicate update_sync_status() - // uses. Matching against an identity captured when the device was selected would - // instead ask whether the edited preset had changed since then, and would reject - // the user who selects a machine and only then switches to its matching preset. - auto* dev_manager = GUI::wxGetApp().getDeviceManager(); - MachineObject* obj = dev_manager ? dev_manager->get_selected_machine() : nullptr; - if (!obj || obj->get_dev_id() != src_dev_id) return; - - const std::string preset_model = preset.get_printer_type(bundle); - if (preset_model != obj->get_show_printer_type()) { - BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent: skipping physical_extruder_map sync, the device is a " - << obj->get_show_printer_type() << " but the edited printer preset is a " - << preset_model; - return; - } - - // Only IMEX profiles read physical_extruder_map as logical -> physical extruder. - // Elsewhere in the tree the key carries the BBL extruder-id reading, or is unused - // entirely (a single-nozzle Klipper machine), so writing the device's lane data - // there would silently mutate an unrelated setting -- and dirty the preset with - // no user action -- for every AFC user who is not running IMEX. - const auto* is_imex = config.option("is_imex"); - if (!is_imex || !is_imex->value) return; - - // The map has one entry per LOGICAL extruder, i.e. the nozzle_diameter index - // space (see effective_physical_extruder_map() in IMEXHelpers.cpp). The device - // reports one entry per lane, which is the same index space only when the counts - // match; when they differ the lane -> logical extruder correspondence is not - // knowable here, and a wrong-length map is discarded by PrintApply anyway, so - // leave whatever the profile authored alone rather than writing a map that - // nothing will honour. - const auto* nozzles = config.option("nozzle_diameter"); - if (!nozzles || nozzles->values.size() != pem.size()) { - BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent: skipping physical_extruder_map sync, device reports " - << pem.size() << " lanes but the printer profile has " - << (nozzles ? nozzles->values.size() : 0) << " logical extruders"; - return; - } - - // Write only on a real change: an unconditional set_key_value() marks the printer - // preset dirty on every device poll, so the user sees unsaved changes they never made. - const auto* current = config.option("physical_extruder_map"); - if (current && current->values == pem) return; - - config.set_key_value("physical_extruder_map", new ConfigOptionInts(pem)); - BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent: auto-populated physical_extruder_map from AFC extruder_index"; - }); - } - return true; } @@ -888,10 +813,6 @@ bool MoonrakerPrinterAgent::fetch_moonraker_filament_data(std::vector(); tray.has_filament = !tray.tray_type.empty(); auto* bundle = GUI::wxGetApp().preset_bundle; tray.tray_info_idx = bundle diff --git a/src/slic3r/Utils/MoonrakerPrinterAgent.hpp b/src/slic3r/Utils/MoonrakerPrinterAgent.hpp index bb70e3f453..141574b84d 100644 --- a/src/slic3r/Utils/MoonrakerPrinterAgent.hpp +++ b/src/slic3r/Utils/MoonrakerPrinterAgent.hpp @@ -88,7 +88,6 @@ protected: // Tray data for AMS payload building struct AmsTrayData { int slot_index = 0; // 0-based slot index - int extruder_index = -1; // Physical extruder index from AFC extruder_index field (-1 = not provided) bool has_filament = false; std::string tray_type; // Material type (e.g., "PLA", "ASA") std::string tray_color; // Raw color (#RRGGBB, 0xRRGGBB, or RRGGBBAA)