Count layer slider tool changes in the parallel-mode checks

A tool change added from the layer slider switches heads mid-print like a
painted color, but the parallel-mode checks only looked at the filaments of the
plate's objects, support and prime tower. A one-filament plate with a slider
change to a copying head's filament passed them. They now include those tool
changes, as the plate's warning badge already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-10-03 00:33:57 -04:00
co-authored by Claude Opus 5.5
parent d4d79fa328
commit 3ae74ff952
2 changed files with 29 additions and 3 deletions
+6 -3
View File
@@ -1768,11 +1768,14 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
if (m_config.is_imex.value && !m_objects.empty()) {
const std::string& parallel_mode = m_objects.front()->config().imex_parallel_mode.value;
if (!parallel_mode.empty() && parallel_mode != kImexPrimaryMode) {
// Tool changes added from the layer slider switch heads mid-print as a painted color
// does, so they count here, as the plate's warning badge counts them.
const std::vector<unsigned int> imex_extruders = this->extruders(/*conside_custom_gcode=*/true);
std::vector<int> used_filaments_0b;
std::vector<int> used_slots_1b;
used_filaments_0b.reserve(extruders.size());
used_slots_1b.reserve(extruders.size());
for (unsigned int e : extruders) {
used_filaments_0b.reserve(imex_extruders.size());
used_slots_1b.reserve(imex_extruders.size());
for (unsigned int e : imex_extruders) {
used_filaments_0b.push_back((int)e);
used_slots_1b.push_back((int)e + 1);
}
+23
View File
@@ -1256,6 +1256,29 @@ TEST_CASE("A mixed filament outranks the multi-color rule on the same plate",
}
}
// A tool change added from the layer slider switches heads mid-print just as a painted color
// does, so a parallel mode has to judge it with the plate's other filaments. Before it counted,
// a one-filament plate with a slider change to a copying head's filament passed validate().
TEST_CASE("A layer slider tool change counts as a color in a parallel mode", "[MultiFilament][IMEX]")
{
DynamicPrintConfig config = multifilament_config(7);
imex_7x4_printer(config);
all_regions_on_filament(config, 1); // filament 1 => logical slot 0 => physical head 0
config.set_deserialize_strict({ { "imex_parallel_mode", "copy" } });
Slic3r::Model model;
Slic3r::Print print;
init_print({ cube(20) }, print, model, config);
std::vector<StringObjectException> warnings;
REQUIRE(print.validate(&warnings).string.empty());
// Filament 5 routes to head 1, which copies the primary in this mode.
model.plates_custom_gcodes[model.curr_plate_index].gcodes.push_back(
{ 5.0, CustomGCode::Type::ToolChange, 5, "", "" });
print.apply(model, print.full_print_config());
REQUIRE_FALSE(print.validate(&warnings).string.empty());
}
// Guard rail: the block must not fire on a well-formed plate. Filament 1 (slot 0) routes to
// head 0, which `copy` declares Primary, so the Primary tool has something to print with.
TEST_CASE("An IMEX plate whose filament routes to the Primary tool validates",