From ef6d4a71def3c194574c4dfbc7daca932e99c49d Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Wed, 7 Oct 2026 05:24:58 -0500 Subject: [PATCH 1/2] Tests: qualify Polyline in the belt overhang test for Windows Windows headers declare a global Polyline, so the unqualified name in test_print.cpp is ambiguous there (both Windows builds of belt-printer fail at tests/fff_print/test_print.cpp:1336), as Polygon was in #16196. Co-Authored-By: Claude Fable 5.1 --- tests/fff_print/test_print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index 0f1d33c67f..32c37882f5 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -1395,7 +1395,7 @@ TEST_CASE("Belt supports reach the belt under a leading overhang", "[Print][belt REQUIRE(lowest != nullptr); double floor_under_lowest = std::numeric_limits::max(); for (const ExtrusionEntity *entity : lowest->support_fills.flatten().entities) - for (const Polyline &pl : entity->as_polylines()) + for (const Slic3r::Polyline &pl : entity->as_polylines()) for (const Point &pt : pl.points) floor_under_lowest = std::min(floor_under_lowest, floor.floor_print_z(pt)); // The object's lowest geometry. The slicing frame starts at the lowest From 006a9377c32764cb15e1a8b17bd4c4a27df55907 Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Wed, 7 Oct 2026 05:30:08 -0500 Subject: [PATCH 2/2] Profile validator: slice belt printers with two cubes along the belt The slice check (-s) prints one 10 mm cube per printer with a height range on filament 2 and expects the filament change to fire. Since #16236 a belt object's slicing Z starts at the belt below its leading end, well below the part's first printed layer, so the range 4-10 falls into the empty lead-in and filament 2 is never used: every belt printer reported "the filament change never fired" and the Slice check job on belt-printer went red. A height range in slicing Z does not map onto a part on a belt in any case. Slice belt printers with two cubes one behind the other along the belt, the second on filament 2, which gives the one plain T1 the check looks for. Other printers are unchanged. Co-Authored-By: Claude Fable 5.1 --- .../OrcaSlicer_profile_validator.cpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/dev-utils/OrcaSlicer_profile_validator.cpp b/src/dev-utils/OrcaSlicer_profile_validator.cpp index 7b80a3bbb1..208b950cfb 100644 --- a/src/dev-utils/OrcaSlicer_profile_validator.cpp +++ b/src/dev-utils/OrcaSlicer_profile_validator.cpp @@ -202,6 +202,7 @@ Vec2d place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er) std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl, bool by_object) { const Vec2d center = printable_area_center(cfg); + const bool belt = cfg.opt_bool("belt_printer"); std::vector cube_mins; if (by_object) { // By-object printing fires the hook only without a wipe tower, and rules out clumping detection and @@ -212,6 +213,12 @@ std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl, cfg.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); cfg.set_key_value("skirt_loops", new ConfigOptionInt(0)); cube_mins = {center + Vec2d(-20., -5.), center + Vec2d(10., -5.)}; + } else if (belt) { + // A belt object's slicing Z starts at the belt below its leading end, well below its first + // printed layer, so a height range in slicing Z does not map onto the part. Two cubes one + // behind the other along the belt, the second on filament 2, give the one filament change + // instead (the purge prism is an object the GUI adds, so there is no tower to place). + cube_mins = {center - Vec2d(5., 15.), center + Vec2d(-5., 5.)}; } else { // Clumping detection changes the tower footprint, so turn it on before placing the tower. if (!cfg.opt_string("wrapping_detection_gcode").empty()) @@ -229,14 +236,20 @@ std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl, obj->name = "cube"; // populates [input_filename_base] the way a loaded model does obj->add_volume(m); obj->add_instance(); - // Filament 2 is used only above z=4, so the upper layers carry a single filament change. - DynamicPrintConfig range_config; - range_config.set_key_value("extruder", new ConfigOptionInt(2)); - // Every range must carry a layer_height; use the process's own so a fine nozzle (e.g. 0.15 mm - // printing ~0.1 mm layers) isn't forced to a height its extrusion width can't support - that - // trips Flow::with_spacing. - range_config.set_key_value("layer_height", new ConfigOptionFloat(cfg.opt_float("layer_height"))); - obj->layer_config_ranges[{4.0, 10.0}].assign_config(std::move(range_config)); + if (belt && !by_object) { + // The second cube along the belt is on filament 2 (see cube_mins above). + if (&cube_min == &cube_mins.back()) + obj->config.set_key_value("extruder", new ConfigOptionInt(2)); + } else { + // Filament 2 is used only above z=4, so the upper layers carry a single filament change. + DynamicPrintConfig range_config; + range_config.set_key_value("extruder", new ConfigOptionInt(2)); + // Every range must carry a layer_height; use the process's own so a fine nozzle (e.g. 0.15 mm + // printing ~0.1 mm layers) isn't forced to a height its extrusion width can't support - that + // trips Flow::with_spacing. + range_config.set_key_value("layer_height", new ConfigOptionFloat(cfg.opt_float("layer_height"))); + obj->layer_config_ranges[{4.0, 10.0}].assign_config(std::move(range_config)); + } obj->ensure_on_bed(); print.auto_assign_extruders(obj); }