mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-10 14:02:47 +00:00
Fix user preset load crash from inconsistent per-variant vector sizes (#14106)
* Fix user preset load crash from inconsistent per-variant vector sizes
This commit is contained in:
@@ -10256,7 +10256,19 @@ void DynamicPrintConfig::update_diff_values_to_child_config(DynamicPrintConfig&
|
||||
int stride = 1;
|
||||
if (key_set2.find(opt) != key_set2.end())
|
||||
stride = 2;
|
||||
opt_vec_src->set_only_diff(opt_vec_dest, variant_index, stride);
|
||||
// set_only_diff() requires the base vector length to equal variant_index.size()*stride, where
|
||||
// variant_index is sized from the parent's printer_extruder_variant list (or 1 when it has none).
|
||||
// Legacy / multi-extruder / multi-variant presets can violate this in either direction when a key's
|
||||
// stored length and the variant-list length were sized inconsistently - e.g. a Snapmaker U1 base
|
||||
// (4 nozzles) whose stride-2 machine limits were length-extended to nozzles*2 while its
|
||||
// printer_extruder_variant list is empty (variant_index == 1), so base length != variant_index*stride.
|
||||
// Rather than throw (which is caught upstream and DELETES the user preset file), fall back to the
|
||||
// child's explicit value, which is authoritative for its own extruder/variant layout.
|
||||
if (opt_vec_src->size() != variant_index.size() * size_t(stride)) {
|
||||
opt_src->set(opt_target);
|
||||
}
|
||||
else
|
||||
opt_vec_src->set_only_diff(opt_vec_dest, variant_index, stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,6 +315,54 @@ SCENARIO("update_non_diff_values_to_base_config preserves child vectors when chi
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("update_diff_values_to_child_config tolerates legacy machine-limit vector sizes",
|
||||
"[Config][Variant]") {
|
||||
// Regression: loading a user printer preset that inherits a non-BBL multi-extruder base and
|
||||
// overrides stride-2 machine limits used to throw in ConfigOptionVector::set_only_diff
|
||||
// ("invalid diff_index size"). The base's machine-limit vectors get length-extended by the
|
||||
// nozzle count while it carries no printer_extruder_variant, so the base length (nozzles*2)
|
||||
// no longer matches variant_index.size()*2. The throw was caught upstream and DELETED the
|
||||
// user's preset file. The merge must instead degrade gracefully.
|
||||
GIVEN("A 4-nozzle parent with stride-2 limits extended to nozzles*2 but no printer_extruder_variant") {
|
||||
Slic3r::DynamicPrintConfig parent;
|
||||
Slic3r::DynamicPrintConfig child;
|
||||
|
||||
parent.set_key_value("nozzle_diameter",
|
||||
new Slic3r::ConfigOptionFloats({0.4, 0.4, 0.4, 0.4}));
|
||||
parent.set_key_value("machine_max_acceleration_x",
|
||||
new Slic3r::ConfigOptionFloats({25000, 25000, 25000, 25000, 25000, 25000, 25000, 25000}));
|
||||
|
||||
// Child user preset declares 4 extruder variants and overrides the machine limit.
|
||||
child.set_key_value("printer_extruder_id",
|
||||
new Slic3r::ConfigOptionInts({1, 2, 3, 4}));
|
||||
child.set_key_value("printer_extruder_variant",
|
||||
new Slic3r::ConfigOptionStrings({"Direct Drive Standard", "Direct Drive Standard",
|
||||
"Direct Drive Standard", "Direct Drive Standard"}));
|
||||
child.set_key_value("machine_max_acceleration_x",
|
||||
new Slic3r::ConfigOptionFloats({8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000}));
|
||||
|
||||
WHEN("update_diff_values_to_child_config merges the child overrides") {
|
||||
std::string id_name = "printer_extruder_id";
|
||||
std::string var_name = "printer_extruder_variant";
|
||||
|
||||
THEN("it does not throw on the legacy size mismatch") {
|
||||
REQUIRE_NOTHROW(parent.update_diff_values_to_child_config(
|
||||
child, id_name, var_name,
|
||||
Slic3r::printer_options_with_variant_1,
|
||||
Slic3r::printer_options_with_variant_2));
|
||||
|
||||
AND_THEN("the child's overridden machine limit is preserved") {
|
||||
auto* mx = parent.option<Slic3r::ConfigOptionFloats>("machine_max_acceleration_x");
|
||||
REQUIRE(mx != nullptr);
|
||||
REQUIRE(mx->values.size() >= 2);
|
||||
REQUIRE_THAT(mx->values[0], Catch::Matchers::WithinAbs(8000.0, 1e-6));
|
||||
REQUIRE_THAT(mx->values[1], Catch::Matchers::WithinAbs(8000.0, 1e-6));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SCENARIO("DynamicPrintConfig JSON serialization", "[Config]") {
|
||||
// WHEN("DynamicPrintConfig is serialized and deserialized") {
|
||||
// auto now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
Reference in New Issue
Block a user