mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 13:32:44 +00:00
Merge main + clean up code + fix missing include
This commit is contained in:
@@ -599,6 +599,143 @@ TEST_CASE("A printer specific filament supersedes the generic library filament w
|
||||
CHECK(is_compatible_with_printer(generic_lib, PresetWithVendorProfile(*printer_c, nullptr)));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const char *kMixedKeys[] = {
|
||||
"filament_is_mixed",
|
||||
"filament_mixed_components",
|
||||
"filament_mixed_sublayer_ratios",
|
||||
"filament_mixed_gradient",
|
||||
"filament_mixed_gradient_range",
|
||||
"filament_mixed_gradient_curve",
|
||||
"filament_mixed_gradient_per_part",
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Mixed-color filament metadata lives in project_config as parallel per-filament arrays.
|
||||
// set_num_filaments() is the single place that grows them alongside filament_colour; if it
|
||||
// misses them, creating a mixed slot writes past the end of the short arrays.
|
||||
TEST_CASE("set_num_filaments keeps mixed-color arrays in step with the filament count", "[Preset][Bundle][FilamentMixer]")
|
||||
{
|
||||
auto mixed_array_size = [](const DynamicPrintConfig &cfg, const std::string &key) -> size_t {
|
||||
if (const auto *b = cfg.option<ConfigOptionBools>(key))
|
||||
return b->values.size();
|
||||
if (const auto *s = cfg.option<ConfigOptionStrings>(key))
|
||||
return s->values.size();
|
||||
return size_t(-1); // key missing entirely
|
||||
};
|
||||
|
||||
PresetBundle bundle;
|
||||
|
||||
const unsigned int n = GENERATE(2u, 4u, 8u);
|
||||
bundle.set_num_filaments(n, std::string("#FF0000"));
|
||||
|
||||
REQUIRE(bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values.size() == n);
|
||||
for (const char *key : kMixedKeys) {
|
||||
DYNAMIC_SECTION("grown: " << key) {
|
||||
CHECK(mixed_array_size(bundle.project_config, key) == n);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("shrinking keeps them in step too") {
|
||||
bundle.set_num_filaments(1, std::string("#00FF00"));
|
||||
REQUIRE(bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values.size() == 1);
|
||||
for (const char *key : kMixedKeys)
|
||||
CHECK(mixed_array_size(bundle.project_config, key) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
// A mix is described by 1-based indices into the project's filament list, which Orca rebuilds
|
||||
// from the selected printer's snapshot (filament_%02u / filament_colors) at startup and on every
|
||||
// printer selection. Held anywhere but that same per-printer snapshot, the mixed arrays end up
|
||||
// indexing a filament list they were never saved against.
|
||||
TEST_CASE("Mixed-color filament metadata is snapshotted per printer, with its filament list", "[Preset][Bundle][FilamentMixer]")
|
||||
{
|
||||
PresetBundle bundle;
|
||||
// export_selections skips the built-in "Default Printer" placeholder entirely.
|
||||
add_inmemory_preset(bundle.printers, "Test Printer");
|
||||
bundle.printers.select_preset_by_name("Test Printer", true);
|
||||
bundle.set_num_filaments(2u, std::string("#FF0000"));
|
||||
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values = { false, true };
|
||||
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values = { "", "1,2" };
|
||||
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios")->values = { "", "0.5,0.5" };
|
||||
|
||||
AppConfig app_config;
|
||||
bundle.export_selections(app_config);
|
||||
|
||||
const std::string printer_name = bundle.printers.get_selected_preset_name();
|
||||
for (const char *key : kMixedKeys) {
|
||||
DYNAMIC_SECTION("per printer, not global: " << key) {
|
||||
CHECK(app_config.has_printer_setting(printer_name, key));
|
||||
CHECK_FALSE(app_config.has("presets", key));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("with the encoding load_selections reads back") {
|
||||
CHECK(app_config.get_printer_setting(printer_name, "filament_is_mixed") == "0,1");
|
||||
CHECK(app_config.get_printer_setting(printer_name, "filament_mixed_components") == "|1,2");
|
||||
CHECK(app_config.get_printer_setting(printer_name, "filament_mixed_sublayer_ratios") == "|0.5,0.5");
|
||||
}
|
||||
}
|
||||
|
||||
// The gradient curve is the one mixed array whose values contain '|' themselves — it separates the
|
||||
// control points — so it cannot be '|'-joined into the app config like its siblings without a
|
||||
// multi-point curve being split across filament slots on the way back in.
|
||||
TEST_CASE("A multi-point gradient curve survives the app-config snapshot", "[Preset][Bundle][FilamentMixer]")
|
||||
{
|
||||
const std::vector<std::string> curves = { "", "", "0,0|0.5,0.3|1,1" };
|
||||
|
||||
PresetBundle bundle;
|
||||
add_inmemory_preset(bundle.printers, "Test Printer");
|
||||
bundle.printers.select_preset_by_name("Test Printer", true);
|
||||
bundle.set_num_filaments(3u, std::string("#FF0000"));
|
||||
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_gradient_curve")->values = curves;
|
||||
|
||||
AppConfig app_config;
|
||||
bundle.export_selections(app_config);
|
||||
|
||||
// Decoding the stored form returns the three slots intact, curve delimiters and all. A plain
|
||||
// '|' join would decode as five slots here instead of three.
|
||||
std::vector<std::string> decoded;
|
||||
REQUIRE(unescape_strings_cstyle(
|
||||
app_config.get_printer_setting(bundle.printers.get_selected_preset_name(), "filament_mixed_gradient_curve"), decoded));
|
||||
CHECK(decoded == curves);
|
||||
}
|
||||
|
||||
// A multi-tool printer sizes the filament list from its nozzle count. Mixed-color slots are extra
|
||||
// virtual filaments at the tail of that list with no nozzle of their own, so the count has to
|
||||
// allow for them: sizing to the nozzle count alone drops the project's mixes and strips every
|
||||
// painted facet above the new count.
|
||||
TEST_CASE("Sizing the filament list to a multi-tool nozzle count keeps mixed slots", "[Preset][Bundle][FilamentMixer]")
|
||||
{
|
||||
// The 5-slot layout of a 4-tool project carrying one mix of filaments 2 and 3.
|
||||
const size_t nozzle_count = 4;
|
||||
PresetBundle bundle;
|
||||
bundle.set_num_filaments(5u, std::string("#FF0000"));
|
||||
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values =
|
||||
{ false, false, false, false, true };
|
||||
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values =
|
||||
{ "", "", "", "", "2,3" };
|
||||
|
||||
REQUIRE(bundle.num_mixed_filaments() == 1);
|
||||
|
||||
SECTION("nozzle count plus the mixed slots preserves the mix") {
|
||||
bundle.set_num_filaments(nozzle_count + bundle.num_mixed_filaments(), std::string("#00FF00"));
|
||||
|
||||
CHECK(bundle.filament_presets.size() == 5);
|
||||
CHECK(bundle.num_mixed_filaments() == 1);
|
||||
CHECK(bundle.is_mixed_filament(4));
|
||||
CHECK(bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values[4] == "2,3");
|
||||
}
|
||||
|
||||
SECTION("the nozzle count alone is what truncated it away") {
|
||||
bundle.set_num_filaments(nozzle_count, std::string("#00FF00"));
|
||||
|
||||
CHECK(bundle.filament_presets.size() == nozzle_count);
|
||||
CHECK(bundle.num_mixed_filaments() == 0);
|
||||
}
|
||||
}
|
||||
// A "published" 3MF keeps the user's currently-selected presets and overlays only the
|
||||
// author-selected process keys onto the edited preset (mirrors the GUI load path: normalize
|
||||
// before load_config_model, then the overlay in load_config_file_config).
|
||||
|
||||
Reference in New Issue
Block a user