fix(preset): don't truncate child variant vectors to parent size on load (#13316)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Clifford
2026-05-08 15:03:39 -04:00
committed by GitHub
parent 1411f95434
commit 7aed2dc8bd
2 changed files with 57 additions and 0 deletions

View File

@@ -9641,6 +9641,13 @@ void DynamicPrintConfig::update_non_diff_values_to_base_config(DynamicPrintConfi
//nothing to do, keep the original one //nothing to do, keep the original one
} }
else { else {
// Guard: set_with_restore is parent-shaped and would truncate the child's
// vector when the child has more extruders than the parent (e.g. an IDEX
// preset inheriting from a single-nozzle base). The child's saved value is
// authoritative for its own extruder count, so skip the merge for this key.
if (cur_variant_count > target_variant_count)
continue;
int stride = 1; int stride = 1;
if (key_set2.find(opt) != key_set2.end()) if (key_set2.find(opt) != key_set2.end())
stride = 2; stride = 2;

View File

@@ -265,6 +265,56 @@ SCENARIO("DynamicPrintConfig serialization", "[Config]") {
} }
} }
SCENARIO("update_non_diff_values_to_base_config preserves child vectors when child has more extruders than parent",
"[Config][Variant]") {
GIVEN("A 2-extruder child printer config inheriting from a 1-extruder parent") {
Slic3r::DynamicPrintConfig child;
Slic3r::DynamicPrintConfig parent;
child.set_key_value("nozzle_diameter", new Slic3r::ConfigOptionFloats({0.4, 0.4}));
child.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1, 2}));
child.set_key_value("printer_extruder_variant", new Slic3r::ConfigOptionStrings({"Direct Drive Standard", "Direct Drive Standard"}));
child.set_key_value("retraction_length", new Slic3r::ConfigOptionFloats({1.5, 1.5}));
parent.set_key_value("nozzle_diameter", new Slic3r::ConfigOptionFloats({0.4}));
parent.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1}));
parent.set_key_value("printer_extruder_variant", new Slic3r::ConfigOptionStrings({"Direct Drive Standard"}));
parent.set_key_value("retraction_length", new Slic3r::ConfigOptionFloats({0.8}));
const Slic3r::t_config_option_keys keys = {
"retraction_length", "printer_extruder_id", "printer_extruder_variant"
};
const std::set<std::string> different_keys = {
"retraction_length", "printer_extruder_id", "printer_extruder_variant"
};
WHEN("update_non_diff_values_to_base_config is called") {
std::string id_name = "printer_extruder_id";
std::string var_name = "printer_extruder_variant";
child.update_non_diff_values_to_base_config(
parent, keys, different_keys, id_name, var_name,
Slic3r::printer_options_with_variant_1,
Slic3r::printer_options_with_variant_2);
THEN("printer_extruder_id retains size 2") {
REQUIRE(child.option<Slic3r::ConfigOptionInts>("printer_extruder_id")->values.size() == 2);
}
THEN("printer_extruder_variant retains size 2") {
REQUIRE(child.option<Slic3r::ConfigOptionStrings>("printer_extruder_variant")->values.size() == 2);
}
THEN("retraction_length retains size 2") {
REQUIRE(child.option<Slic3r::ConfigOptionFloats>("retraction_length")->values.size() == 2);
}
THEN("printer_extruder_id values are preserved for both extruders") {
auto* pe_id = child.option<Slic3r::ConfigOptionInts>("printer_extruder_id");
REQUIRE(pe_id->values.size() == 2);
REQUIRE(pe_id->values[0] == 1);
REQUIRE(pe_id->values[1] == 2);
}
}
}
}
// SCENARIO("DynamicPrintConfig JSON serialization", "[Config]") { // SCENARIO("DynamicPrintConfig JSON serialization", "[Config]") {
// WHEN("DynamicPrintConfig is serialized and deserialized") { // WHEN("DynamicPrintConfig is serialized and deserialized") {
// auto now = std::chrono::high_resolution_clock::now(); // auto now = std::chrono::high_resolution_clock::now();