diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index 33411e2f0d..1939988261 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -3476,6 +3476,14 @@ int CLI::run(int argc, char **argv) } new_variant_counts = old_variant_counts; //filament_variant_count = old_variant_counts; + //ORCA: lay the per-variant options out one value per variant of the current filaments before each + // loaded filament replaces its own variants, including an option only a loaded filament + // defines, which otherwise starts as a single default value and never reaches the others. + for (const DynamicPrintConfig &config : load_filaments_config) + for (const std::string &opt_key : filament_options_with_variant) + if (opt_key != "filament_extruder_variant" && config.has(opt_key)) + m_print_config.option(opt_key, true); + normalize_filament_values_to_variants(m_print_config); for (int index = 0; index < load_filaments_config.size(); index++) { DynamicPrintConfig& config = load_filaments_config[index]; int filament_index = load_filaments_index[index]; @@ -3647,6 +3655,25 @@ int CLI::run(int argc, char **argv) } } + //ORCA: a per-variant option the loaded filament does not define keeps the values of the + // variants the filament already had, and a variant new to it takes its first one's. + const int old_start = old_start_indice[filament_index - 1]; + std::vector kept_variant_indice = new_variant_indice; + for (int &i : kept_variant_indice) + if (i < 0) + i = old_start; + for (const std::string &opt_key : filament_options_with_variant) { + if (config.has(opt_key)) + continue; + auto *opt_vec_dst = dynamic_cast(m_print_config.option(opt_key)); + if (opt_vec_dst == nullptr || opt_vec_dst->size() < size_t(old_start + old_variant_count)) + continue; + // set_with_restore_2() pads its source in place + std::unique_ptr old_values(opt_vec_dst->clone()); + opt_vec_dst->set_with_restore_2(static_cast(old_values.get()), kept_variant_indice, old_start, + old_variant_count, true); + } + //update the old index if (old_variant_count != new_variant_count) { @@ -4081,6 +4108,9 @@ int CLI::run(int argc, char **argv) if (printer_technology == ptFFF) { fff_print_config.apply(m_print_config, true); m_print_config.apply(fff_print_config, true); + //ORCA: an option no preset or project defines has just come in as its single default value, and a + // command line override may hold one value per filament. + normalize_filament_values_to_variants(m_print_config); } else { boost::nowide::cerr << "invalid printer_technology " << std::endl; record_exit_reson(outfile_dir, CLI_INVALID_PRINTER_TECH, 0, cli_errors[CLI_INVALID_PRINTER_TECH], sliced_info); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 1202477b6a..16a913a85f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -9405,20 +9405,8 @@ void PrintConfigDef::handle_legacy_composite(DynamicPrintConfig &config) } // Orca: a config saved before a key joined filament_options_with_variant stores it once per filament - // rather than once per filament variant. Give every variant of a filament that filament's value. - if (auto *self_index = config.option("filament_self_index"); self_index && !self_index->empty()) { - const int filament_count = *std::max_element(self_index->values.begin(), self_index->values.end()); - if (filament_count > 0 && size_t(filament_count) < self_index->size()) { - for (const std::string &key : filament_options_with_variant) { - auto *opt = dynamic_cast(config.option(key)); - if (!opt || opt->size() != size_t(filament_count)) - continue; - std::unique_ptr per_filament(opt->clone()); - for (size_t variant = 0; variant < self_index->size(); ++variant) - opt->set_at(per_filament.get(), variant, self_index->values[variant] - 1); - } - } - } + // rather than once per filament variant, and one exported by an older CLI may store a single value. + normalize_filament_values_to_variants(config); } const PrintConfigDef print_config_def; @@ -10735,6 +10723,25 @@ void set_variant_override(ConfigOptionVectorBase &target, const ConfigOptionVect target.set_to_index(&source, indices, stride); } +void normalize_filament_values_to_variants(DynamicPrintConfig &config) +{ + const auto *self_index = config.option("filament_self_index"); + if (self_index == nullptr || self_index->empty()) + return; + const int filament_count = *std::max_element(self_index->values.begin(), self_index->values.end()); + if (filament_count <= 0 || size_t(filament_count) >= self_index->size()) + return; + for (const std::string &key : filament_options_with_variant) { + auto *opt = dynamic_cast(config.option(key)); + if (opt == nullptr || (opt->size() != size_t(filament_count) && opt->size() != 1)) + continue; + std::unique_ptr per_filament(opt->clone()); + // set_at() takes the first value for a filament past the end of a single-value vector + for (size_t variant = 0; variant < self_index->size(); ++variant) + opt->set_at(per_filament.get(), variant, self_index->values[variant] - 1); + } +} + //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 8b61280979..1e91f2e451 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -884,6 +884,11 @@ extern std::set empty_options; void set_variant_override(ConfigOptionVectorBase &target, const ConfigOptionVectorBase &source, const std::vector &variant_index, int stride = 1); +// Orca: lays every filament_options_with_variant option out one value per filament variant, as +// filament_self_index maps the variants to filaments. An option holding one value per filament, or a +// single value, gives every variant of a filament that filament's value; other lengths are left alone. +void normalize_filament_values_to_variants(DynamicPrintConfig &config); + extern std::set filament_dev_options; 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); diff --git a/tests/libslic3r/test_config_variant_expansion.cpp b/tests/libslic3r/test_config_variant_expansion.cpp index e603808b54..de19e8219c 100644 --- a/tests/libslic3r/test_config_variant_expansion.cpp +++ b/tests/libslic3r/test_config_variant_expansion.cpp @@ -717,3 +717,15 @@ TEST_CASE("get_index_for_extruder scales the variant column by the requested str REQUIRE(col0_stride2 == 0); REQUIRE(col1_stride2 == 2); } + +// A per-variant filament option read with a single value gives it to every filament variant. A project +// exported by an older CLI holds a single value for an option no loaded preset defined, such as +// filament_ironing_flow. +TEST_CASE("A per-variant filament option read with a single value gives it to every filament variant", "[Config]") +{ + // filament 1 defines Standard and High Flow, filament 2 Standard + DynamicPrintConfig config; + config.option("filament_self_index", true)->values = {1, 1, 2}; + 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})); +}