mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-26 04:12:07 +00:00
feat(engine): wire the per-filament volume-map producer pipeline
- Print::update_filament_maps_to_config takes filament/volume/nozzle maps, backfills an empty volume map from extruder types, rebuilds filament_map_2, re-expands the per-filament variant arrays, and recomputes retract overrides keyed by resolved slots - grouping writes its result back in every non-sequential mode; manual multi-nozzle grouping validates the user mapping and raises a translatable error on deviation; the engine's concrete volume assignment is deliberately not merged yet (per-filament arrays are already consumed by filament id, so materializing High Flow now would change motion before the layer-aware resolvers land) - Print::apply treats the three map keys as engine outputs in auto modes (erased from the diff and adopted), compares them against used filaments in manual mode, and keeps the pre-expansion snapshot in sync with the late normalization pass so rebuilt headers reflect the sliced state instead of resurrecting stale values - volume/nozzle maps and extruder_nozzle_stats join the invalidation group of filament_map (wipe tower + skirt/brim) - PresetBundle composes full configs with an optional per-filament volume map (plate map, else defaults derived from each extruder's flow type); project config keeps the map sized across filament count changes - PartPlate stores per-plate volume/nozzle maps; Plater injects them at every slice-composition site (incl. g-code reload and wipe-tower estimation); BackgroundSlicingProcess reads engine results back to the plate in auto modes - per-filament map trust guards relaxed to size-match everywhere now that every producer sizes the map; single-filament explicit flow assignments are honored - tests: grouping volume maps stay concrete, merge semantics of update_used_filament_values, single-filament override honoring Motion g-code is byte-identical fleet-wide including Hybrid projects (19-fixture gate + repro determinism double-slice). Header deltas: the map keys now dump real values, and stale pre-normalization values (e.g. enable_prime_tower on single-used-filament prints) no longer leak into the config block.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include "libslic3r/FilamentGroupUtils.hpp"
|
||||
#include "libslic3r/MultiNozzleUtils.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/GCode/ToolOrdering.hpp"
|
||||
@@ -348,3 +349,45 @@ TEST_CASE("NozzleStatusRecorder tracks nozzle/extruder occupancy", "[MultiNozzle
|
||||
// Clearing a nozzle leaves the extruder->nozzle association intact.
|
||||
REQUIRE(rec.get_nozzle_in_extruder(1) == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Hybrid nozzle stats resolve to concrete volume types", "[ToolOrdering][H2C]")
|
||||
{
|
||||
// Extruder 0 is Standard-only; extruder 1 carries a mixed Standard + High Flow inventory
|
||||
// (the "Hybrid" flow selection). The write-back pipeline persists get_volume_map(), so the
|
||||
// result must always carry concrete per-filament volume types, never the Hybrid seed.
|
||||
auto stats = get_extruder_nozzle_stats({"Standard#1", "Standard#1|High Flow#1"});
|
||||
REQUIRE(stats.size() == 2);
|
||||
REQUIRE(stats[1].size() == 2);
|
||||
|
||||
std::vector<unsigned int> used_filaments = {0, 1, 2};
|
||||
std::vector<int> filament_map = {0, 1, 1}; // 0-based extruder ids
|
||||
std::vector<int> volume_requests = {(int) nvtStandard, (int) nvtHighFlow, (int) nvtStandard};
|
||||
std::vector<int> nozzle_requests = {0, 1, 2}; // distinct logical nozzles
|
||||
|
||||
auto group = LayeredNozzleGroupResult::create(used_filaments, filament_map, volume_requests, nozzle_requests, stats, 0.4f);
|
||||
REQUIRE(group.has_value());
|
||||
|
||||
auto volume_map = group->get_volume_map();
|
||||
REQUIRE(volume_map == volume_requests);
|
||||
for (auto fid : used_filaments)
|
||||
REQUIRE(volume_map[fid] != (int) nvtHybrid);
|
||||
|
||||
// The Hybrid seed itself matches no physical nozzle: such a request is unsatisfiable.
|
||||
std::vector<int> hybrid_requests = {(int) nvtStandard, (int) nvtHybrid, (int) nvtStandard};
|
||||
REQUIRE_FALSE(LayeredNozzleGroupResult::create(used_filaments, filament_map, hybrid_requests, nozzle_requests, stats, 0.4f).has_value());
|
||||
}
|
||||
|
||||
TEST_CASE("update_used_filament_values merges only used filaments", "[ToolOrdering][H2C]")
|
||||
{
|
||||
// The config write-back merges the engine's per-filament values over the config baseline:
|
||||
// used filaments adopt the engine value, unused filaments keep their config assignment.
|
||||
std::vector<int> old_values = {1, 1, 2, 1};
|
||||
std::vector<int> new_values = {2, 2, 1, 2};
|
||||
std::vector<unsigned int> used = {0, 2};
|
||||
|
||||
auto merged = FilamentGroupUtils::update_used_filament_values(old_values, new_values, used);
|
||||
REQUIRE(merged == std::vector<int>{2, 1, 1, 1});
|
||||
|
||||
// No used filaments => the config baseline is returned untouched.
|
||||
REQUIRE(FilamentGroupUtils::update_used_filament_values(old_values, new_values, {}) == old_values);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user