From bf97ae0536b604810f9553f82511b8778795febc Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Mon, 5 Oct 2026 19:00:24 +0800 Subject: [PATCH] Keep Each Filament's Device Drying Values When the CLI Merges Filaments The device drying options hold several values per filament, as many as the filament preset gives, and a project stores them as the filaments' values one after another. The CLI filament merge wrote them like an option with one value per filament, putting each preset's first value at the filament's own index, so a project with three filaments whose preset gives "1", "0" was exported with 1;1;1;0;1;0 where the GUI writes 1;0;1;0;1;0. The merge now leaves these options out of the per-filament pass and rebuilds them afterwards from every filament's values in slot order. Without a fixed number of values per filament one slot cannot be replaced in place, so the stored values are kept when any slot has no config to rebuild from. --- src/OrcaSlicer.cpp | 11 ++++++++ src/libslic3r/PrintConfig.cpp | 16 +++++++++++ src/libslic3r/PrintConfig.hpp | 5 ++++ .../test_config_variant_expansion.cpp | 27 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index 62ccfb7675..ac2978a098 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -3618,6 +3618,9 @@ int CLI::run(int argc, char **argv) { if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "dev_model_name" || opt_key == "filament_settings_id") continue; + // rebuilt from every filament after this loop + if (filament_dev_options.find(opt_key) != filament_dev_options.end()) + continue; ConfigOption *opt = m_print_config.option(opt_key, true); if (opt == nullptr) { // opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def(). @@ -3681,6 +3684,14 @@ int CLI::run(int argc, char **argv) } } + // The stored values cannot be told apart per filament, so they are kept as they are unless every slot has a config. + std::vector filament_configs(filament_count, nullptr); + for (size_t index = 0; index < load_filaments_config.size(); index++) + if (load_filaments_index[index] >= 1 && load_filaments_index[index] <= filament_count) + filament_configs[load_filaments_index[index] - 1] = &load_filaments_config[index]; + if (std::find(filament_configs.begin(), filament_configs.end(), nullptr) == filament_configs.end()) + set_filament_dev_options(m_print_config, filament_configs); + if (m_print_config.option("filament_extruder_variant")) { std::vector& filament_self_indice = m_print_config.option("filament_self_index", true)->values; int index_size = m_print_config.option("filament_extruder_variant")->size(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 76073b4981..d2717a11c1 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -10815,6 +10815,22 @@ void normalize_filament_values_to_variants(DynamicPrintConfig &config) } } +void set_filament_dev_options(DynamicPrintConfig &config, const std::vector &filament_configs) +{ + for (const std::string &key : filament_dev_options) { + if (std::none_of(filament_configs.begin(), filament_configs.end(), [&key](const DynamicPrintConfig *filament) { return filament->has(key); })) + continue; + const ConfigOption *default_value = print_config_def.get(key)->default_value.get(); + auto *dst = static_cast(config.option(key, true)); + dst->clear(); + for (const DynamicPrintConfig *filament : filament_configs) { + const auto *src = static_cast(filament->has(key) ? filament->option(key) : default_value); + if (!src->empty()) + dst->append(src); + } + } +} + //used for object/region config //use the smallest of multiple to single diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 68e35db40d..6e86d6347a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -928,6 +928,11 @@ void normalize_filament_values_to_variants(DynamicPrintConfig &config); extern std::set filament_dev_options; +// Orca: a filament_dev_options option holds several values per filament, and how many is up to the +// filament preset, so one filament's values cannot be replaced in place. This rebuilds each option from +// filament_configs, one config per filament in slot order, as the filaments' values one after another. +void set_filament_dev_options(DynamicPrintConfig &config, const std::vector &filament_configs); + extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector variant_index, std::set& key_set1, int stride = 1); extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config, t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector& f_map_indices); diff --git a/tests/libslic3r/test_config_variant_expansion.cpp b/tests/libslic3r/test_config_variant_expansion.cpp index 240a6e25fa..0df6eb976f 100644 --- a/tests/libslic3r/test_config_variant_expansion.cpp +++ b/tests/libslic3r/test_config_variant_expansion.cpp @@ -799,3 +799,30 @@ TEST_CASE("A per-variant filament option read with a single value gives it to ev config.load_from_ini_string("pressure_advance = 0.021", ForwardCompatibilitySubstitutionRule::Disable); REQUIRE(config.option("pressure_advance")->values == std::vector({0.021, 0.021, 0.021})); } + +// The device drying options hold several values per filament, as many as each filament preset gives. +TEST_CASE("The device drying options are rebuilt as each filament's values in slot order", "[Config]") +{ + DynamicPrintConfig two_values, one_value, no_value; + two_values.option("filament_dev_ams_drying_ams_limitations", true)->values = {"1", "0"}; + two_values.option("filament_dev_ams_drying_temperature", true)->values = {45., 45., 55., 55.}; + one_value.option("filament_dev_ams_drying_ams_limitations", true)->values = {"1"}; + one_value.option("filament_dev_ams_drying_temperature", true)->values = {65., 65., 75., 75.}; + + // values a project stored for three other filaments + DynamicPrintConfig config; + config.option("filament_dev_ams_drying_ams_limitations", true)->values = {"0", "0", "0"}; + config.option("filament_dev_chamber_drying_time", true)->values = {12., 8., 12.}; + + set_filament_dev_options(config, {&two_values, &one_value, &two_values}); + REQUIRE(config.option("filament_dev_ams_drying_ams_limitations")->values == + std::vector({"1", "0", "1", "1", "0"})); + REQUIRE(config.option("filament_dev_ams_drying_temperature")->values == + std::vector({45., 45., 55., 55., 65., 65., 75., 75., 45., 45., 55., 55.})); + // an option no filament defines keeps the stored values + REQUIRE(config.option("filament_dev_chamber_drying_time")->values == std::vector({12., 8., 12.})); + + // a filament without the option takes the option's default + set_filament_dev_options(config, {&two_values, &no_value}); + REQUIRE(config.option("filament_dev_ams_drying_ams_limitations")->values == std::vector({"1", "0", ""})); +}