From b246239b39bb57ffae677d09428776a1209b75ba Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Wed, 7 Oct 2026 16:56:13 +0800 Subject: [PATCH] Size a Project's Mixed-Colour Metadata to the Filaments in the CLI The mixed-colour metadata options are parallel per-slot arrays in the project config. A project saved before they were sized per slot stores a single value for the gradient ones, and one saved before they existed stores none. The GUI sizes all seven to the filament count when it opens a project; the CLI kept the stored arrays and exported one-element defaults for absent ones, so a project it exported carried one-element arrays where the GUI writes one entry per filament. Slicing is unaffected, every reader treats a missing entry as not mixed / no gradient, but the GUI-vs-CLI comparison reported the four gradient keys on every mixed-filament project. The resize helper moves from PresetBundle.cpp, where it was file-local, to PrintConfig.cpp next to set_filament_dev_options(). It creates an option the config lacks before sizing it, a no-op for the bundle's project config where all seven always exist. The CLI calls it with its filament count once the project and loaded filaments are merged, after the check that every mixed slot has a filament of its own. --- src/OrcaSlicer.cpp | 2 ++ src/libslic3r/PresetBundle.cpp | 18 ----------------- src/libslic3r/PrintConfig.cpp | 15 ++++++++++++++ src/libslic3r/PrintConfig.hpp | 4 ++++ .../test_config_variant_expansion.cpp | 20 +++++++++++++++++++ 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index 7104d1bbcb..b895c25e89 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -4094,6 +4094,8 @@ int CLI::run(int argc, char **argv) flush_and_exit(CLI_MIXED_FILAMENT_INVALID); } } + if (filament_count > 0) + resize_mixed_filament_metadata(m_print_config, size_t(filament_count), size_t(filament_count)); m_print_config.option>("printer_technology", true)->value = printer_technology; diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index b1fad347f1..46f8b1d789 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -3601,24 +3601,6 @@ void PresetBundle::export_selections(AppConfig &config) BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": printer %1%, print %2%, filaments[0] %3% ")%printers.get_selected_preset_name() % prints.get_selected_preset_name() %filament_presets[0]; } -// Preserve metadata only for existing colour slots; new slots get false/empty defaults. -static void resize_mixed_filament_metadata(DynamicPrintConfig &config, size_t old_slot_count, size_t new_slot_count) -{ - auto resize = [old_slot_count, new_slot_count](auto *opt) { - if (opt) { - opt->values.resize(std::min(old_slot_count, opt->values.size())); - opt->values.resize(new_slot_count); - } - }; - resize(config.option("filament_is_mixed")); - resize(config.option("filament_mixed_components")); - resize(config.option("filament_mixed_sublayer_ratios")); - resize(config.option("filament_mixed_gradient")); - resize(config.option("filament_mixed_gradient_range")); - resize(config.option("filament_mixed_gradient_curve")); - resize(config.option("filament_mixed_gradient_per_part")); -} - void PresetBundle::set_num_filaments(unsigned int n, std::string new_color) { unsigned old_filament_count = this->filament_presets.size(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 59a01bc5ff..e2b795a8d1 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -10838,6 +10838,21 @@ void set_filament_dev_options(DynamicPrintConfig &config, const std::vectorvalues.resize(std::min(old_slot_count, opt->values.size())); + opt->values.resize(new_slot_count); + }; + resize(config.option("filament_is_mixed", true)); + resize(config.option("filament_mixed_components", true)); + resize(config.option("filament_mixed_sublayer_ratios", true)); + resize(config.option("filament_mixed_gradient", true)); + resize(config.option("filament_mixed_gradient_range", true)); + resize(config.option("filament_mixed_gradient_curve", true)); + resize(config.option("filament_mixed_gradient_per_part", true)); +} + //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 beff23933a..0bad9eea86 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -933,6 +933,10 @@ extern std::set filament_dev_options; // 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); +// Orca: sizes the per-slot mixed-colour metadata options to new_slot_count, keeping the first +// old_slot_count values; an option the config lacks is created. +void resize_mixed_filament_metadata(DynamicPrintConfig &config, size_t old_slot_count, size_t new_slot_count); + 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 0df6eb976f..3f90a70bae 100644 --- a/tests/libslic3r/test_config_variant_expansion.cpp +++ b/tests/libslic3r/test_config_variant_expansion.cpp @@ -826,3 +826,23 @@ TEST_CASE("The device drying options are rebuilt as each filament's values in sl set_filament_dev_options(config, {&two_values, &no_value}); REQUIRE(config.option("filament_dev_ams_drying_ams_limitations")->values == std::vector({"1", "0", ""})); } + +TEST_CASE("The mixed filament metadata is sized to the filament count", "[Config]") +{ + DynamicPrintConfig config; + config.option("filament_is_mixed", true)->values = {false, false, true}; + config.option("filament_mixed_components", true)->values = {"", "", "1,2"}; + config.option("filament_mixed_gradient", true)->values = {false}; + config.option("filament_mixed_gradient_range", true)->values = {""}; + + resize_mixed_filament_metadata(config, 3, 3); + REQUIRE(config.option("filament_is_mixed")->values == std::vector({false, false, true})); + REQUIRE(config.option("filament_mixed_components")->values == std::vector({"", "", "1,2"})); + REQUIRE(config.option("filament_mixed_gradient")->values == std::vector({false, false, false})); + REQUIRE(config.option("filament_mixed_gradient_range")->values == std::vector({"", "", ""})); + REQUIRE(config.option("filament_mixed_gradient_curve")->values == std::vector({"", "", ""})); + + resize_mixed_filament_metadata(config, 2, 4); + REQUIRE(config.option("filament_is_mixed")->values == std::vector({false, false, false, false})); + REQUIRE(config.option("filament_mixed_components")->values == std::vector({"", "", "", ""})); +}