mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-31 13:57:07 +00:00
feat(config): keep per-(extruder x volume-type) slots in variant expansion
- get_extruder_nozzle_volume_count derives per-extruder volume-type slot lists from extruder_nozzle_stats (absent stats = one slot per extruder) - update_values_to_printer_extruders learns the slot layout: when any extruder mixes volume types, option arrays keep one slot per (extruder x volume type), extruder-ascending then volume-ascending; single-slot resolution takes the filament's volume type on mixed extruders - update_values_to_printer_extruders_for_multiple_filaments applies a per-filament nozzle_volume_type override from filament_volume_map (when sized to the filament count) and remaps filament_self_index through the same pipeline as every other filament key - get_config_index_base + is_auto_filament_map_mode helpers (consumers land with the per-filament config-index resolvers) - callers updated: PresetBundle composition paths, PrintApply (counts hoisted above the extruder_applied guard), Print write-back - new tests: slot counting, Hybrid slot expansion incl. stride 2, per-filament override, non-Hybrid degeneracy Non-Hybrid printers keep their variant layout and values (proven by a 19-fixture byte gate; the only header delta is filament_self_index now flowing through the same variant pipeline as its sibling filament keys). Hybrid slices grow the config-block variant arrays to one entry per sub-nozzle volume type; motion g-code is unchanged until the g-code writer consumes the new slots.
This commit is contained in:
@@ -120,17 +120,34 @@ DynamicPrintConfig PresetBundle::construct_full_config(
|
|||||||
inherits.emplace_back(print_inherits);
|
inherits.emplace_back(print_inherits);
|
||||||
|
|
||||||
// BBS: update printer config related with variants
|
// BBS: update printer config related with variants
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 1, extruder_volume_type_count = 1;
|
||||||
|
bool different_extruder = false;
|
||||||
if (apply_extruder) {
|
if (apply_extruder) {
|
||||||
out.update_values_to_printer_extruders(out, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
different_extruder = out.support_different_extruders(extruder_count);
|
||||||
out.update_values_to_printer_extruders(out, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
extruder_volume_type_count = out.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
// update print config related with variants
|
|
||||||
out.update_values_to_printer_extruders(out, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
if ((extruder_count > 1) || different_extruder) {
|
||||||
|
// Orca: keep processing variant_1 before variant_2 here; variant_2 slots are resolved
|
||||||
|
// against the printer id/variant lists as rewritten by the variant_1 pass, and the
|
||||||
|
// composed values depend on that order. Note the order is load-bearing, not correct
|
||||||
|
// in general: the variant_2 pass reads the original full-width arrays through indices
|
||||||
|
// resolved on the shrunk lists, which mis-reads presets whose variant_2 columns differ
|
||||||
|
// per variant (e.g. X2D machine_max_speed_e/machine_max_acceleration_e). The slicing
|
||||||
|
// path composes variant_2 first and is unaffected; changing the order here would alter
|
||||||
|
// long-standing composed values, so any fix must re-baseline them.
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
||||||
|
// update print config related with variants
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_filaments <= 1) {
|
if (num_filaments <= 1) {
|
||||||
// BBS: update filament config related with variants
|
// BBS: update filament config related with variants
|
||||||
DynamicPrintConfig filament_config = in_filament_presets[0].config;
|
DynamicPrintConfig filament_config = in_filament_presets[0].config;
|
||||||
if (apply_extruder) filament_config.update_values_to_printer_extruders(out, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[0]);
|
if (apply_extruder && ((extruder_count > 1) || different_extruder))
|
||||||
|
filament_config.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[0]);
|
||||||
out.apply(filament_config);
|
out.apply(filament_config);
|
||||||
compatible_printers_condition.emplace_back(in_filament_presets[0].compatible_printers_condition());
|
compatible_printers_condition.emplace_back(in_filament_presets[0].compatible_printers_condition());
|
||||||
compatible_prints_condition.emplace_back(in_filament_presets[0].compatible_prints_condition());
|
compatible_prints_condition.emplace_back(in_filament_presets[0].compatible_prints_condition());
|
||||||
@@ -153,8 +170,8 @@ DynamicPrintConfig PresetBundle::construct_full_config(
|
|||||||
filament_temp_configs.resize(num_filaments);
|
filament_temp_configs.resize(num_filaments);
|
||||||
for (size_t i = 0; i < num_filaments; ++i) {
|
for (size_t i = 0; i < num_filaments; ++i) {
|
||||||
filament_temp_configs[i] = *(filament_configs[i]);
|
filament_temp_configs[i] = *(filament_configs[i]);
|
||||||
if (apply_extruder)
|
if (apply_extruder && ((extruder_count > 1) || different_extruder))
|
||||||
filament_temp_configs[i].update_values_to_printer_extruders(out, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[i]);
|
filament_temp_configs[i].update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through options and apply them to the resulting config.
|
// loop through options and apply them to the resulting config.
|
||||||
@@ -3979,18 +3996,34 @@ DynamicPrintConfig PresetBundle::full_fff_config(bool apply_extruder, std::optio
|
|||||||
different_settings.emplace_back(different_print_settings);
|
different_settings.emplace_back(different_print_settings);
|
||||||
|
|
||||||
//BBS: update printer config related with variants
|
//BBS: update printer config related with variants
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 1, extruder_volume_type_count = 1;
|
||||||
|
bool different_extruder = false;
|
||||||
if (apply_extruder) {
|
if (apply_extruder) {
|
||||||
out.update_values_to_printer_extruders(out, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
different_extruder = out.support_different_extruders(extruder_count);
|
||||||
out.update_values_to_printer_extruders(out, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
extruder_volume_type_count = out.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
//update print config related with variants
|
|
||||||
out.update_values_to_printer_extruders(out, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
if ((extruder_count > 1) || different_extruder) {
|
||||||
|
// Orca: keep processing variant_1 before variant_2 here; variant_2 slots are resolved
|
||||||
|
// against the printer id/variant lists as rewritten by the variant_1 pass, and the
|
||||||
|
// composed values depend on that order. Note the order is load-bearing, not correct
|
||||||
|
// in general: the variant_2 pass reads the original full-width arrays through indices
|
||||||
|
// resolved on the shrunk lists, which mis-reads presets whose variant_2 columns differ
|
||||||
|
// per variant (e.g. X2D machine_max_speed_e/machine_max_acceleration_e). The slicing
|
||||||
|
// path composes variant_2 first and is unaffected; changing the order here would alter
|
||||||
|
// long-standing composed values, so any fix must re-baseline them.
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
||||||
|
//update print config related with variants
|
||||||
|
out.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_filaments <= 1) {
|
if (num_filaments <= 1) {
|
||||||
//BBS: update filament config related with variants
|
//BBS: update filament config related with variants
|
||||||
DynamicPrintConfig filament_config = this->filaments.get_edited_preset().config;
|
DynamicPrintConfig filament_config = this->filaments.get_edited_preset().config;
|
||||||
if (apply_extruder)
|
if (apply_extruder && ((extruder_count > 1) || different_extruder))
|
||||||
filament_config.update_values_to_printer_extruders(out, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[0]);
|
filament_config.update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[0]);
|
||||||
out.apply(filament_config);
|
out.apply(filament_config);
|
||||||
compatible_printers_condition.emplace_back(this->filaments.get_edited_preset().compatible_printers_condition());
|
compatible_printers_condition.emplace_back(this->filaments.get_edited_preset().compatible_printers_condition());
|
||||||
compatible_prints_condition .emplace_back(this->filaments.get_edited_preset().compatible_prints_condition());
|
compatible_prints_condition .emplace_back(this->filaments.get_edited_preset().compatible_prints_condition());
|
||||||
@@ -4083,8 +4116,8 @@ DynamicPrintConfig PresetBundle::full_fff_config(bool apply_extruder, std::optio
|
|||||||
filament_temp_configs.resize(num_filaments);
|
filament_temp_configs.resize(num_filaments);
|
||||||
for (size_t i = 0; i < num_filaments; ++i) {
|
for (size_t i = 0; i < num_filaments; ++i) {
|
||||||
filament_temp_configs[i] = *(filament_configs[i]);
|
filament_temp_configs[i] = *(filament_configs[i]);
|
||||||
if (apply_extruder)
|
if (apply_extruder && ((extruder_count > 1) || different_extruder))
|
||||||
filament_temp_configs[i].update_values_to_printer_extruders(out, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[i]);
|
filament_temp_configs[i].update_values_to_printer_extruders(out, extruder_count, extruder_volume_type_count, nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, filament_maps[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through options and apply them to the resulting config.
|
// loop through options and apply them to the resulting config.
|
||||||
|
|||||||
@@ -3206,8 +3206,16 @@ void Print::update_filament_maps_to_config(std::vector<int> f_maps)
|
|||||||
m_ori_full_print_config.option<ConfigOptionInts>("filament_map", true)->values = f_maps;
|
m_ori_full_print_config.option<ConfigOptionInts>("filament_map", true)->values = f_maps;
|
||||||
m_config.filament_map.values = f_maps;
|
m_config.filament_map.values = f_maps;
|
||||||
|
|
||||||
|
int extruder_count = 1, extruder_volume_type_count = 1;
|
||||||
|
bool support_multi = m_ori_full_print_config.support_different_extruders(extruder_count);
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
extruder_volume_type_count = m_ori_full_print_config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
m_full_print_config = m_ori_full_print_config;
|
m_full_print_config = m_ori_full_print_config;
|
||||||
m_full_print_config.update_values_to_printer_extruders_for_multiple_filaments(m_full_print_config, filament_options_with_variant, "filament_self_index", "filament_extruder_variant");
|
std::set<std::string> filament_keys = filament_options_with_variant;
|
||||||
|
filament_keys.insert("filament_self_index");
|
||||||
|
if ((extruder_count > 1) || support_multi)
|
||||||
|
m_full_print_config.update_values_to_printer_extruders_for_multiple_filaments(m_full_print_config, extruder_count, extruder_volume_type_count, filament_keys, "filament_self_index", "filament_extruder_variant");
|
||||||
|
|
||||||
const std::vector<std::string> &extruder_retract_keys = print_config_def.extruder_retract_keys();
|
const std::vector<std::string> &extruder_retract_keys = print_config_def.extruder_retract_keys();
|
||||||
const std::string filament_prefix = "filament_";
|
const std::string filament_prefix = "filament_";
|
||||||
|
|||||||
@@ -1162,15 +1162,28 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
}
|
}
|
||||||
|
|
||||||
//apply extruder related values
|
//apply extruder related values
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 1, extruder_volume_type_count = 1;
|
||||||
|
bool different_extruder = false;
|
||||||
|
|
||||||
|
different_extruder = new_full_config.support_different_extruders(extruder_count);
|
||||||
|
extruder_volume_type_count = new_full_config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
if (!extruder_applied) {
|
if (!extruder_applied) {
|
||||||
// variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly
|
if ((extruder_count > 1) || different_extruder) {
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
// variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
new_full_config.update_values_to_printer_extruders(new_full_config, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
||||||
//update print config related with variants
|
new_full_config.update_values_to_printer_extruders(new_full_config, extruder_count, extruder_volume_type_count, nozzle_volume_types, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
//update print config related with variants
|
||||||
|
new_full_config.update_values_to_printer_extruders(new_full_config, extruder_count, extruder_volume_type_count, nozzle_volume_types, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
}
|
||||||
|
|
||||||
m_ori_full_print_config = new_full_config;
|
m_ori_full_print_config = new_full_config;
|
||||||
new_full_config.update_values_to_printer_extruders_for_multiple_filaments(new_full_config, filament_options_with_variant, "filament_self_index", "filament_extruder_variant");
|
|
||||||
|
std::set<std::string> filament_keys = filament_options_with_variant;
|
||||||
|
filament_keys.insert("filament_self_index");
|
||||||
|
if ((extruder_count > 1) || different_extruder)
|
||||||
|
new_full_config.update_values_to_printer_extruders_for_multiple_filaments(m_ori_full_print_config, extruder_count, extruder_volume_type_count, filament_keys,
|
||||||
|
"filament_self_index", "filament_extruder_variant");
|
||||||
}
|
}
|
||||||
// else {
|
// else {
|
||||||
// int extruder_count;
|
// int extruder_count;
|
||||||
@@ -1199,7 +1212,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
if (print_diff_set.find("filament_map_mode") == print_diff_set.end())
|
if (print_diff_set.find("filament_map_mode") == print_diff_set.end())
|
||||||
{
|
{
|
||||||
FilamentMapMode map_mode = new_full_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode", true)->value;
|
FilamentMapMode map_mode = new_full_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode", true)->value;
|
||||||
if (map_mode < fmmManual) {
|
if (is_auto_filament_map_mode(map_mode)) {
|
||||||
if (print_diff_set.find("filament_map") != print_diff_set.end()) {
|
if (print_diff_set.find("filament_map") != print_diff_set.end()) {
|
||||||
print_diff_set.erase("filament_map");
|
print_diff_set.erase("filament_map");
|
||||||
//full_config_diff.erase("filament_map");
|
//full_config_diff.erase("filament_map");
|
||||||
|
|||||||
@@ -650,6 +650,16 @@ std::string get_extruder_variant_string(ExtruderType extruder_type, NozzleVolume
|
|||||||
return variant_string;
|
return variant_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_config_index_base(NozzleVolumeType volume_type, ExtruderType extruder_type, int variant_id_1based, const std::vector<std::string>& variant_list, const std::vector<int>& variant_ids_1based)
|
||||||
|
{
|
||||||
|
assert(variant_list.size() == variant_ids_1based.size());
|
||||||
|
std::string extruder_variant = get_extruder_variant_string(extruder_type, volume_type);
|
||||||
|
for (int index = 0; index < int(variant_list.size()); ++index) {
|
||||||
|
if (extruder_variant == variant_list[index] && variant_ids_1based[index] == variant_id_1based) { return index; }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string get_nozzle_volume_type_string(NozzleVolumeType nozzle_volume_type)
|
std::string get_nozzle_volume_type_string(NozzleVolumeType nozzle_volume_type)
|
||||||
{
|
{
|
||||||
if (nozzle_volume_type > nvtMaxNozzleVolumeType) {
|
if (nozzle_volume_type > nvtMaxNozzleVolumeType) {
|
||||||
@@ -10283,184 +10293,229 @@ DynamicPrintConfig::get_filament_type() const
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id)
|
int DynamicPrintConfig::get_extruder_nozzle_volume_count(int extruder_count, std::vector<std::vector<NozzleVolumeType>>& nozzle_volume_types) const
|
||||||
{
|
{
|
||||||
int extruder_count;
|
int count = extruder_count;
|
||||||
bool different_extruder = printer_config.support_different_extruders(extruder_count);
|
auto opt_extruder_nozzle_stats = dynamic_cast<const ConfigOptionStrings*>(this->option("extruder_nozzle_stats"));
|
||||||
if ((extruder_count > 1) || different_extruder)
|
nozzle_volume_types.resize(extruder_count, std::vector<NozzleVolumeType>{});
|
||||||
{
|
if (opt_extruder_nozzle_stats && (int(opt_extruder_nozzle_stats->values.size()) == extruder_count)) {
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: different extruders processing")%__LINE__;
|
std::vector<std::map<NozzleVolumeType, int>> extruder_nozzle_counts = get_extruder_nozzle_stats(opt_extruder_nozzle_stats->values);
|
||||||
//apply process settings
|
count = 0;
|
||||||
//auto opt_nozzle_diameters = this->option<ConfigOptionFloats>("nozzle_diameter");
|
for (int i = 0; i < extruder_count; i++)
|
||||||
//int extruder_count = opt_nozzle_diameters->size();
|
|
||||||
auto opt_extruder_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("extruder_type"));
|
|
||||||
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
|
||||||
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<int> variant_index;
|
|
||||||
|
|
||||||
if (extruder_id > 0 && extruder_id <= static_cast<unsigned> (extruder_count)) {
|
|
||||||
variant_index.resize(1);
|
|
||||||
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(extruder_id - 1));
|
|
||||||
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(extruder_id - 1));
|
|
||||||
|
|
||||||
//variant index
|
|
||||||
variant_index[0] = get_index_for_extruder(extruder_id, id_name, extruder_type, nozzle_volume_type, variant_name);
|
|
||||||
|
|
||||||
if (variant_index[0] < 0) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: could not found extruder_type %2%, nozzle_volume_type %3%, for filament")
|
|
||||||
% __LINE__ % s_keys_names_ExtruderType[extruder_type] % s_keys_names_NozzleVolumeType[nozzle_volume_type];
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
extruder_count = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
variant_index.resize(extruder_count);
|
|
||||||
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(e_index));
|
|
||||||
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index));
|
|
||||||
|
|
||||||
//variant index
|
|
||||||
variant_index[e_index] = get_index_for_extruder(e_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
|
||||||
if (variant_index[e_index] < 0) {
|
|
||||||
// Orca: This is expected during transient UI states (e.g. popup windows),
|
|
||||||
// fall back to 0 silently.
|
|
||||||
variant_index[e_index] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ConfigDef *config_def = this->def();
|
|
||||||
if (!config_def) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto& key: key_set)
|
|
||||||
{
|
{
|
||||||
const ConfigOptionDef *optdef = config_def->get(key);
|
count += extruder_nozzle_counts[i].size();
|
||||||
if (!optdef) {
|
// std::map iteration order gives the canonical slot order: ascending NozzleVolumeType
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key;
|
for (auto& iter : extruder_nozzle_counts[i])
|
||||||
continue;
|
nozzle_volume_types[i].push_back(iter.first);
|
||||||
}
|
|
||||||
switch (optdef->type) {
|
|
||||||
case coStrings:
|
|
||||||
{
|
|
||||||
ConfigOptionStrings * opt = this->option<ConfigOptionStrings>(key);
|
|
||||||
std::vector<std::string> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coInts:
|
|
||||||
{
|
|
||||||
ConfigOptionInts * opt = this->option<ConfigOptionInts>(key);
|
|
||||||
std::vector<int> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coFloats:
|
|
||||||
{
|
|
||||||
ConfigOptionFloats * opt = this->option<ConfigOptionFloats>(key);
|
|
||||||
std::vector<double> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coPercents:
|
|
||||||
{
|
|
||||||
ConfigOptionPercents * opt = this->option<ConfigOptionPercents>(key);
|
|
||||||
std::vector<double> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coFloatsOrPercents:
|
|
||||||
{
|
|
||||||
ConfigOptionFloatsOrPercents * opt = this->option<ConfigOptionFloatsOrPercents>(key);
|
|
||||||
std::vector<FloatOrPercent> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coBools:
|
|
||||||
{
|
|
||||||
ConfigOptionBools * opt = this->option<ConfigOptionBools>(key);
|
|
||||||
std::vector<unsigned char> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case coEnums:
|
|
||||||
{
|
|
||||||
ConfigOptionEnumsGeneric * opt = this->option<ConfigOptionEnumsGeneric>(key);
|
|
||||||
std::vector<int> new_values;
|
|
||||||
|
|
||||||
new_values.resize(extruder_count * stride);
|
|
||||||
for (int e_index = 0; e_index < extruder_count; e_index++)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < stride; i++)
|
|
||||||
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
|
||||||
}
|
|
||||||
opt->values = new_values;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%")%__LINE__%key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
|
std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, int extruder_count, int extruder_nozzle_volume_count, std::vector<std::vector<NozzleVolumeType>>& nv_types,
|
||||||
|
std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id, NozzleVolumeType filament_nvt)
|
||||||
{
|
{
|
||||||
int extruder_count;
|
std::vector<int> variant_index;
|
||||||
bool different_extruder = printer_config.support_different_extruders(extruder_count);
|
int variant_count = extruder_count;
|
||||||
if ((extruder_count > 1) || different_extruder)
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: extruder_count %2%, extruder_nozzle_volume_count %3%")%__LINE__ %extruder_count %extruder_nozzle_volume_count;
|
||||||
|
|
||||||
|
auto opt_extruder_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("extruder_type"));
|
||||||
|
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
||||||
|
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
||||||
|
return variant_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extruder_id > 0 && extruder_id <= static_cast<unsigned> (extruder_count)) {
|
||||||
|
variant_index.resize(1);
|
||||||
|
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(extruder_id - 1));
|
||||||
|
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(extruder_id - 1));
|
||||||
|
|
||||||
|
if (nozzle_volume_type == nvtHybrid) {
|
||||||
|
// a mixed-nozzle extruder has no preset column of its own: the filament's concrete
|
||||||
|
// volume type selects the slot
|
||||||
|
nozzle_volume_type = filament_nvt;
|
||||||
|
}
|
||||||
|
else if (nozzle_volume_type != filament_nvt) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__
|
||||||
|
<< boost::format(", Line %1%: nozzle_volume_type is %2%, not equal to filament_nvt %3%") % __LINE__ % nozzle_volume_type % filament_nvt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//variant index
|
||||||
|
variant_index[0] = get_index_for_extruder(extruder_id, id_name, extruder_type, nozzle_volume_type, variant_name);
|
||||||
|
|
||||||
|
if (variant_index[0] < 0) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: could not found extruder_type %2%, nozzle_volume_type %3%, for filament")
|
||||||
|
% __LINE__ % s_keys_names_ExtruderType[extruder_type] % s_keys_names_NozzleVolumeType[nozzle_volume_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
variant_count = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Orca: emit the slots first, then size variant_count from what was actually
|
||||||
|
// emitted. extruder_nozzle_volume_count only equals the emitted total when every
|
||||||
|
// extruder carries per-type stats; an extruder with an empty stats entry combined
|
||||||
|
// with a Hybrid extruder would otherwise overrun a table pre-sized from that count.
|
||||||
|
for (int e_index = 0; e_index < extruder_count; e_index++)
|
||||||
|
{
|
||||||
|
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(e_index));
|
||||||
|
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index));
|
||||||
|
|
||||||
|
// Orca: latch the decision before the inner loop reassigns nozzle_volume_type;
|
||||||
|
// re-testing the reassigned value would make every slot after the first reuse
|
||||||
|
// the first slot's volume type.
|
||||||
|
const bool per_type_slots = extruder_nozzle_volume_count > extruder_count || nozzle_volume_type == nvtHybrid;
|
||||||
|
const int nvt_count = per_type_slots ? int(nv_types[e_index].size()) : 1;
|
||||||
|
for (int nvt_index = 0; nvt_index < nvt_count; nvt_index++)
|
||||||
|
{
|
||||||
|
if (per_type_slots)
|
||||||
|
nozzle_volume_type = nv_types[e_index][nvt_index];
|
||||||
|
//variant index
|
||||||
|
int slot_index = get_index_for_extruder(e_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
||||||
|
if (slot_index < 0) {
|
||||||
|
// Orca: This is expected during transient UI states (e.g. popup windows),
|
||||||
|
// fall back to 0 silently.
|
||||||
|
slot_index = 0;
|
||||||
|
}
|
||||||
|
variant_index.push_back(slot_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
variant_count = int(variant_index.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfigDef *config_def = this->def();
|
||||||
|
if (!config_def) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
||||||
|
return variant_index;
|
||||||
|
}
|
||||||
|
for (auto& key: key_set)
|
||||||
|
{
|
||||||
|
const ConfigOptionDef *optdef = config_def->get(key);
|
||||||
|
if (!optdef) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (optdef->type) {
|
||||||
|
case coStrings:
|
||||||
|
{
|
||||||
|
ConfigOptionStrings * opt = this->option<ConfigOptionStrings>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<std::string> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coInts:
|
||||||
|
{
|
||||||
|
ConfigOptionInts * opt = this->option<ConfigOptionInts>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<int> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coFloats:
|
||||||
|
{
|
||||||
|
ConfigOptionFloats * opt = this->option<ConfigOptionFloats>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<double> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coPercents:
|
||||||
|
{
|
||||||
|
ConfigOptionPercents * opt = this->option<ConfigOptionPercents>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<double> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coFloatsOrPercents:
|
||||||
|
{
|
||||||
|
ConfigOptionFloatsOrPercents * opt = this->option<ConfigOptionFloatsOrPercents>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<FloatOrPercent> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coBools:
|
||||||
|
{
|
||||||
|
ConfigOptionBools * opt = this->option<ConfigOptionBools>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<unsigned char> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case coEnums:
|
||||||
|
{
|
||||||
|
ConfigOptionEnumsGeneric * opt = this->option<ConfigOptionEnumsGeneric>(key);
|
||||||
|
if (!opt) continue;
|
||||||
|
std::vector<int> new_values;
|
||||||
|
|
||||||
|
new_values.resize(variant_count * stride);
|
||||||
|
for (int e_index = 0; e_index < variant_count; e_index++)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < stride; i++)
|
||||||
|
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
|
||||||
|
}
|
||||||
|
opt->values = new_values;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%")%__LINE__%key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return variant_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, int extruder_count, int extruder_nozzle_volume_count, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: extruder_count %2%, extruder_nozzle_volume_count %3%")%__LINE__ %extruder_count %extruder_nozzle_volume_count;
|
||||||
|
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: extruder_count=%2%, different_extruder=%3%")%__LINE__ %extruder_count %different_extruder;
|
|
||||||
auto opt_filament_map = printer_config.option<ConfigOptionInts>("filament_map");
|
auto opt_filament_map = printer_config.option<ConfigOptionInts>("filament_map");
|
||||||
if (!opt_filament_map) {
|
if (!opt_filament_map) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: filament_map option not found, skipping")%__LINE__;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: filament_map option not found, skipping")%__LINE__;
|
||||||
@@ -10469,14 +10524,22 @@ void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filamen
|
|||||||
std::vector<int> filament_maps = opt_filament_map->values;
|
std::vector<int> filament_maps = opt_filament_map->values;
|
||||||
size_t filament_count = filament_maps.size();
|
size_t filament_count = filament_maps.size();
|
||||||
//apply process settings
|
//apply process settings
|
||||||
//auto opt_nozzle_diameters = this->option<ConfigOptionFloats>("nozzle_diameter");
|
|
||||||
//int extruder_count = opt_nozzle_diameters->size();
|
|
||||||
auto opt_extruder_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("extruder_type"));
|
auto opt_extruder_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("extruder_type"));
|
||||||
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
||||||
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto opt_filament_volume_maps = dynamic_cast<const ConfigOptionInts*>(printer_config.option("filament_volume_map"));
|
||||||
|
std::vector<int> filament_volume_maps;
|
||||||
|
// Orca: the per-filament volume map is only trustworthy when a producer explicitly
|
||||||
|
// sized it to the filament count; the registered default is a 1-element vector and
|
||||||
|
// stale project values may be mis-sized. A single-filament config cannot be told
|
||||||
|
// apart from that default by size, so it is ignored too until the pipeline that
|
||||||
|
// seeds the map lands; anything untrusted must not distort slot resolution.
|
||||||
|
if (opt_filament_volume_maps && filament_count > 1 && opt_filament_volume_maps->values.size() == filament_count)
|
||||||
|
filament_volume_maps = opt_filament_volume_maps->values;
|
||||||
auto opt_ids = id_name.empty()? nullptr: dynamic_cast<const ConfigOptionInts*>(this->option(id_name));
|
auto opt_ids = id_name.empty()? nullptr: dynamic_cast<const ConfigOptionInts*>(this->option(id_name));
|
||||||
std::vector<int> variant_index;
|
std::vector<int> variant_index;
|
||||||
|
|
||||||
@@ -10487,6 +10550,10 @@ void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filamen
|
|||||||
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(filament_maps[f_index] - 1));
|
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(filament_maps[f_index] - 1));
|
||||||
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(filament_maps[f_index] - 1));
|
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(filament_maps[f_index] - 1));
|
||||||
|
|
||||||
|
if ((extruder_nozzle_volume_count > extruder_count || nozzle_volume_type == nvtHybrid) && (!filament_volume_maps.empty())) {
|
||||||
|
nozzle_volume_type = (NozzleVolumeType)(filament_volume_maps[f_index]);
|
||||||
|
}
|
||||||
|
|
||||||
//variant index
|
//variant index
|
||||||
variant_index[f_index] = get_index_for_extruder(f_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
variant_index[f_index] = get_index_for_extruder(f_index+1, id_name, extruder_type, nozzle_volume_type, variant_name);
|
||||||
if (variant_index[f_index] < 0) {
|
if (variant_index[f_index] < 0) {
|
||||||
@@ -10511,8 +10578,11 @@ void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filamen
|
|||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool has_id_key = !id_name.empty() && key_set.count(id_name) > 0;
|
||||||
for (auto& key: key_set)
|
for (auto& key: key_set)
|
||||||
{
|
{
|
||||||
|
if (has_id_key && key == id_name)
|
||||||
|
continue;
|
||||||
const ConfigOptionDef *optdef = config_def->get(key);
|
const ConfigOptionDef *optdef = config_def->get(key);
|
||||||
if (!optdef) {
|
if (!optdef) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key;
|
||||||
@@ -10672,6 +10742,16 @@ void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filamen
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Orca: also require a non-empty id list; get_at on an empty vector is undefined.
|
||||||
|
if (has_id_key && opt_ids && !opt_ids->values.empty()) {
|
||||||
|
// remap the id list itself last: the lookups above still need the original ids
|
||||||
|
std::vector<int> new_values;
|
||||||
|
new_values.resize(filament_count);
|
||||||
|
for (int f_index = 0; f_index < filament_count; f_index++) {
|
||||||
|
new_values[f_index] = opt_ids->get_at(variant_index[f_index]);
|
||||||
|
}
|
||||||
|
const_cast<ConfigOptionInts*>(opt_ids)->values = new_values;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -468,6 +468,11 @@ enum FilamentMapMode {
|
|||||||
fmmDefault
|
fmmDefault
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// All auto modes are ordered before fmmManual (see the enum ordering note above).
|
||||||
|
inline bool is_auto_filament_map_mode(FilamentMapMode mode) {
|
||||||
|
return mode < fmmManual;
|
||||||
|
}
|
||||||
|
|
||||||
// Dual-extruder purge control. Default reproduces the current
|
// Dual-extruder purge control. Default reproduces the current
|
||||||
// per-extruder flush_multiplier + filament_prime_volume behaviour, so absent/default is inert.
|
// per-extruder flush_multiplier + filament_prime_volume behaviour, so absent/default is inert.
|
||||||
// Saving -> reduce prime volume to 15 mm3; Fast -> use flush_multiplier_fast + filament_flush_temp_fast.
|
// Saving -> reduce prime volume to 15 mm3; Fast -> use flush_multiplier_fast + filament_flush_temp_fast.
|
||||||
@@ -479,6 +484,10 @@ enum PrimeVolumeMode {
|
|||||||
|
|
||||||
extern std::string get_extruder_variant_string(ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type);
|
extern std::string get_extruder_variant_string(ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type);
|
||||||
|
|
||||||
|
// Base slot lookup: scans a variant list (paired with its 1-based extruder/filament ids) for the
|
||||||
|
// entry matching the given extruder/volume type and id. Returns 0 when no entry matches.
|
||||||
|
extern int get_config_index_base(NozzleVolumeType volume_type, ExtruderType extruder_type, int variant_id_1based, const std::vector<std::string>& variant_list, const std::vector<int>& variant_ids_1based);
|
||||||
|
|
||||||
static std::set<NozzleVolumeType> get_valid_nozzle_volume_type() {
|
static std::set<NozzleVolumeType> get_valid_nozzle_volume_type() {
|
||||||
std::set<NozzleVolumeType> type;
|
std::set<NozzleVolumeType> type;
|
||||||
for (int i = 0; i <= nvtMaxNozzleVolumeType; ++i) {
|
for (int i = 0; i <= nvtMaxNozzleVolumeType; ++i) {
|
||||||
@@ -731,9 +740,14 @@ public:
|
|||||||
//BBS
|
//BBS
|
||||||
bool is_using_different_extruders();
|
bool is_using_different_extruders();
|
||||||
bool support_different_extruders(int& extruder_count) const;
|
bool support_different_extruders(int& extruder_count) const;
|
||||||
|
// Counts the config slots of a printer: one per (extruder x nozzle volume type) as described by
|
||||||
|
// extruder_nozzle_stats, or simply one per extruder when the stats are absent/mismatched.
|
||||||
|
// Fills nozzle_volume_types with each extruder's volume types in ascending enum order.
|
||||||
|
int get_extruder_nozzle_volume_count(int extruder_count, std::vector<std::vector<NozzleVolumeType>>& nozzle_volume_types) const;
|
||||||
int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const;
|
int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const;
|
||||||
void update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0);
|
std::vector<int> update_values_to_printer_extruders(DynamicPrintConfig& printer_config, int extruder_count, int extruder_nozzle_volume_count, std::vector<std::vector<NozzleVolumeType>>& nv_types,
|
||||||
void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
|
std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0, NozzleVolumeType filament_nvt = nvtStandard);
|
||||||
|
void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, int extruder_count, int extruder_nozzle_volume_count, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
|
||||||
|
|
||||||
void update_non_diff_values_to_base_config(DynamicPrintConfig& new_config, const t_config_option_keys& keys, const std::set<std::string>& different_keys, std::string extruder_id_name, std::string extruder_variant_name,
|
void update_non_diff_values_to_base_config(DynamicPrintConfig& new_config, const t_config_option_keys& keys, const std::set<std::string>& different_keys, std::string extruder_id_name, std::string extruder_variant_name,
|
||||||
std::set<std::string>& key_set1, std::set<std::string>& key_set2);
|
std::set<std::string>& key_set1, std::set<std::string>& key_set2);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_clipper_offset.cpp
|
test_clipper_offset.cpp
|
||||||
test_clipper_utils.cpp
|
test_clipper_utils.cpp
|
||||||
test_config.cpp
|
test_config.cpp
|
||||||
|
test_config_variant_expansion.cpp
|
||||||
test_toolordering_nozzle_group.cpp
|
test_toolordering_nozzle_group.cpp
|
||||||
test_preset_bundle_loading.cpp
|
test_preset_bundle_loading.cpp
|
||||||
test_preset_setting_id.cpp
|
test_preset_setting_id.cpp
|
||||||
|
|||||||
285
tests/libslic3r/test_config_variant_expansion.cpp
Normal file
285
tests/libslic3r/test_config_variant_expansion.cpp
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// A 2-extruder printer whose second extruder holds both a Standard and a High Flow nozzle
|
||||||
|
// (nozzle_volume_type Hybrid), described by extruder_nozzle_stats. The variant lists carry one
|
||||||
|
// column per (extruder x volume type) as composed from the presets.
|
||||||
|
DynamicPrintConfig make_hybrid_printer_config()
|
||||||
|
{
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#1", "Standard#3|High Flow#2"};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("extruder_type", true)->values = {etDirectDrive, etDirectDrive};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type", true)->values = {nvtStandard, nvtHybrid};
|
||||||
|
config.option<ConfigOptionStrings>("extruder_variant_list", true)->values = {"Direct Drive Standard,Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard,Direct Drive High Flow"};
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_print_variant_columns(DynamicPrintConfig &config)
|
||||||
|
{
|
||||||
|
config.option<ConfigOptionInts>("print_extruder_id", true)->values = {1, 1, 2, 2};
|
||||||
|
config.option<ConfigOptionStrings>("print_extruder_variant", true)->values = {"Direct Drive Standard", "Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard", "Direct Drive High Flow"};
|
||||||
|
config.option<ConfigOptionFloats>("outer_wall_speed", true)->values = {30., 200., 50., 500.};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("get_extruder_nozzle_volume_count reads the per-extruder volume-type layout", "[Config]")
|
||||||
|
{
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
|
||||||
|
SECTION("absent stats fall back to one slot per extruder") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
REQUIRE(config.get_extruder_nozzle_volume_count(2, nozzle_volume_types) == 2);
|
||||||
|
REQUIRE(nozzle_volume_types.size() == 2);
|
||||||
|
REQUIRE(nozzle_volume_types[0].empty());
|
||||||
|
REQUIRE(nozzle_volume_types[1].empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("stats sized differently from the extruder count are ignored") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#1"};
|
||||||
|
REQUIRE(config.get_extruder_nozzle_volume_count(2, nozzle_volume_types) == 2);
|
||||||
|
REQUIRE(nozzle_volume_types[0].empty());
|
||||||
|
REQUIRE(nozzle_volume_types[1].empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("single volume type per extruder counts one slot each") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#1", "High Flow#1"};
|
||||||
|
REQUIRE(config.get_extruder_nozzle_volume_count(2, nozzle_volume_types) == 2);
|
||||||
|
REQUIRE(nozzle_volume_types[0] == std::vector<NozzleVolumeType>{nvtStandard});
|
||||||
|
REQUIRE(nozzle_volume_types[1] == std::vector<NozzleVolumeType>{nvtHighFlow});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a mixed-nozzle extruder contributes one slot per volume type, ascending enum order") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
// list High Flow first in the token string: parsing must still order Standard before High Flow
|
||||||
|
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#3", "High Flow#3|Standard#3"};
|
||||||
|
REQUIRE(config.get_extruder_nozzle_volume_count(2, nozzle_volume_types) == 3);
|
||||||
|
REQUIRE(nozzle_volume_types[0] == std::vector<NozzleVolumeType>{nvtStandard});
|
||||||
|
REQUIRE(nozzle_volume_types[1] == std::vector<NozzleVolumeType>({nvtStandard, nvtHighFlow}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("update_values_to_printer_extruders expands one slot per (extruder x volume type)", "[Config]")
|
||||||
|
{
|
||||||
|
SECTION("Hybrid extruder yields three slots, extruder-ascending then volume-ascending") {
|
||||||
|
DynamicPrintConfig config = make_hybrid_printer_config();
|
||||||
|
add_print_variant_columns(config);
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
|
std::vector<int> variant_index = config.update_values_to_printer_extruders(config, extruder_count, count, nozzle_volume_types,
|
||||||
|
print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
|
||||||
|
REQUIRE(variant_index == std::vector<int>({0, 2, 3}));
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("outer_wall_speed")->values == std::vector<double>({30., 50., 500.}));
|
||||||
|
REQUIRE(config.option<ConfigOptionInts>("print_extruder_id")->values == std::vector<int>({1, 2, 2}));
|
||||||
|
REQUIRE(config.option<ConfigOptionStrings>("print_extruder_variant")->values ==
|
||||||
|
std::vector<std::string>({"Direct Drive Standard", "Direct Drive Standard", "Direct Drive High Flow"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("stride-2 options keep (normal, silent) pairs together per slot") {
|
||||||
|
DynamicPrintConfig config = make_hybrid_printer_config();
|
||||||
|
config.option<ConfigOptionInts>("printer_extruder_id", true)->values = {1, 1, 2, 2};
|
||||||
|
config.option<ConfigOptionStrings>("printer_extruder_variant", true)->values = {"Direct Drive Standard", "Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard", "Direct Drive High Flow"};
|
||||||
|
config.option<ConfigOptionFloats>("machine_max_speed_x", true)->values = {100., 50., 110., 55., 120., 60., 130., 65.};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
|
std::vector<int> variant_index = config.update_values_to_printer_extruders(config, extruder_count, count, nozzle_volume_types,
|
||||||
|
printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
||||||
|
|
||||||
|
REQUIRE(variant_index == std::vector<int>({0, 2, 3}));
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("machine_max_speed_x")->values ==
|
||||||
|
std::vector<double>({100., 50., 120., 60., 130., 65.}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("single-slot expansion on a Hybrid extruder resolves via the filament volume type") {
|
||||||
|
DynamicPrintConfig printer_config = make_hybrid_printer_config();
|
||||||
|
|
||||||
|
DynamicPrintConfig filament_config;
|
||||||
|
filament_config.option<ConfigOptionStrings>("filament_extruder_variant", true)->values = {"Direct Drive Standard", "Direct Drive High Flow"};
|
||||||
|
filament_config.option<ConfigOptionFloats>("filament_max_volumetric_speed", true)->values = {12., 20.};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = printer_config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
|
SECTION("default filament volume type selects the Standard column") {
|
||||||
|
std::vector<int> variant_index = filament_config.update_values_to_printer_extruders(printer_config, extruder_count, count,
|
||||||
|
nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, 2);
|
||||||
|
REQUIRE(variant_index == std::vector<int>({0}));
|
||||||
|
REQUIRE(filament_config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({12.}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a High Flow filament volume type selects the High Flow column") {
|
||||||
|
std::vector<int> variant_index = filament_config.update_values_to_printer_extruders(printer_config, extruder_count, count,
|
||||||
|
nozzle_volume_types, filament_options_with_variant, "", "filament_extruder_variant", 1, 2, nvtHighFlow);
|
||||||
|
REQUIRE(variant_index == std::vector<int>({1}));
|
||||||
|
REQUIRE(filament_config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({20.}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("an extruder without per-type stats does not overrun the slot table when another is Hybrid") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
// e0 carries no per-type stats (empty entry), so the summed volume-type count (2) does
|
||||||
|
// not exceed the extruder count even though the Hybrid e1 emits one slot per volume type.
|
||||||
|
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"", "Standard#3|High Flow#3"};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("extruder_type", true)->values = {etDirectDrive, etDirectDrive};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type", true)->values = {nvtStandard, nvtHybrid};
|
||||||
|
config.option<ConfigOptionStrings>("extruder_variant_list", true)->values = {"Direct Drive Standard,Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard,Direct Drive High Flow"};
|
||||||
|
add_print_variant_columns(config);
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
REQUIRE(count == 2);
|
||||||
|
REQUIRE(nozzle_volume_types[0].empty());
|
||||||
|
|
||||||
|
std::vector<int> variant_index = config.update_values_to_printer_extruders(config, extruder_count, count, nozzle_volume_types,
|
||||||
|
print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
|
||||||
|
// e0 resolves by its configured type; the Hybrid e1 emits one slot per stats volume type
|
||||||
|
REQUIRE(variant_index == std::vector<int>({0, 2, 3}));
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("outer_wall_speed")->values == std::vector<double>({30., 50., 500.}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("without Hybrid or extra slots the expansion matches the per-extruder resolution") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("extruder_type", true)->values = {etDirectDrive, etDirectDrive};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type", true)->values = {nvtStandard, nvtHighFlow};
|
||||||
|
config.option<ConfigOptionStrings>("extruder_variant_list", true)->values = {"Direct Drive Standard,Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard,Direct Drive High Flow"};
|
||||||
|
add_print_variant_columns(config);
|
||||||
|
|
||||||
|
// compute what the per-extruder loop resolves directly, before the arrays are rewritten
|
||||||
|
std::vector<int> expected_index;
|
||||||
|
for (int e_index = 0; e_index < 2; e_index++)
|
||||||
|
expected_index.push_back(config.get_index_for_extruder(e_index + 1, "print_extruder_id", etDirectDrive,
|
||||||
|
e_index == 0 ? nvtStandard : nvtHighFlow, "print_extruder_variant"));
|
||||||
|
REQUIRE(expected_index == std::vector<int>({0, 3}));
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
REQUIRE(count == 2);
|
||||||
|
|
||||||
|
std::vector<int> variant_index = config.update_values_to_printer_extruders(config, extruder_count, count, nozzle_volume_types,
|
||||||
|
print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
|
||||||
|
REQUIRE(variant_index == expected_index);
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("outer_wall_speed")->values == std::vector<double>({30., 500.}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("update_values_to_printer_extruders_for_multiple_filaments resolves per-filament slots", "[Config]")
|
||||||
|
{
|
||||||
|
auto make_filament_arrays = [](DynamicPrintConfig &config) {
|
||||||
|
config.option<ConfigOptionInts>("filament_self_index", true)->values = {1, 1, 2, 2};
|
||||||
|
config.option<ConfigOptionStrings>("filament_extruder_variant", true)->values = {"Direct Drive Standard", "Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard", "Direct Drive High Flow"};
|
||||||
|
config.option<ConfigOptionFloats>("filament_max_volumetric_speed", true)->values = {12., 20., 13., 21.};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<std::string> filament_keys = filament_options_with_variant;
|
||||||
|
filament_keys.insert("filament_self_index");
|
||||||
|
|
||||||
|
SECTION("filament_volume_map picks the concrete volume type on a Hybrid extruder") {
|
||||||
|
DynamicPrintConfig config = make_hybrid_printer_config();
|
||||||
|
make_filament_arrays(config);
|
||||||
|
config.option<ConfigOptionInts>("filament_map", true)->values = {2, 2};
|
||||||
|
config.option<ConfigOptionInts>("filament_volume_map", true)->values = {nvtStandard, nvtHighFlow};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
|
config.update_values_to_printer_extruders_for_multiple_filaments(config, extruder_count, count, filament_keys,
|
||||||
|
"filament_self_index", "filament_extruder_variant");
|
||||||
|
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({12., 21.}));
|
||||||
|
REQUIRE(config.option<ConfigOptionStrings>("filament_extruder_variant")->values ==
|
||||||
|
std::vector<std::string>({"Direct Drive Standard", "Direct Drive High Flow"}));
|
||||||
|
REQUIRE(config.option<ConfigOptionInts>("filament_self_index")->values == std::vector<int>({1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a volume map not sized to the filament count is ignored") {
|
||||||
|
DynamicPrintConfig config = make_hybrid_printer_config();
|
||||||
|
make_filament_arrays(config);
|
||||||
|
config.option<ConfigOptionInts>("filament_map", true)->values = {2, 2};
|
||||||
|
// the registered default is a single-element vector; it must not override slot resolution
|
||||||
|
config.option<ConfigOptionInts>("filament_volume_map", true)->values = {nvtStandard};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
|
config.update_values_to_printer_extruders_for_multiple_filaments(config, extruder_count, count, filament_keys,
|
||||||
|
"filament_self_index", "filament_extruder_variant");
|
||||||
|
|
||||||
|
// Hybrid resolves as Standard when no usable per-filament map exists
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({12., 13.}));
|
||||||
|
REQUIRE(config.option<ConfigOptionInts>("filament_self_index")->values == std::vector<int>({1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a single-filament map matches the registered default's shape and is ignored") {
|
||||||
|
DynamicPrintConfig config = make_hybrid_printer_config();
|
||||||
|
config.option<ConfigOptionInts>("filament_self_index", true)->values = {1, 1};
|
||||||
|
config.option<ConfigOptionStrings>("filament_extruder_variant", true)->values = {"Direct Drive Standard", "Direct Drive High Flow"};
|
||||||
|
config.option<ConfigOptionFloats>("filament_max_volumetric_speed", true)->values = {12., 20.};
|
||||||
|
config.option<ConfigOptionInts>("filament_map", true)->values = {2};
|
||||||
|
// sized to the (single) filament count, but indistinguishable from the registered
|
||||||
|
// 1-element default, so it must not override slot resolution
|
||||||
|
config.option<ConfigOptionInts>("filament_volume_map", true)->values = {nvtHighFlow};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
|
||||||
|
config.update_values_to_printer_extruders_for_multiple_filaments(config, extruder_count, count, filament_keys,
|
||||||
|
"filament_self_index", "filament_extruder_variant");
|
||||||
|
|
||||||
|
// Hybrid resolves as Standard, exactly as if no map were present
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({12.}));
|
||||||
|
REQUIRE(config.option<ConfigOptionInts>("filament_self_index")->values == std::vector<int>({1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("without Hybrid or extra slots the volume map is not consulted") {
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("extruder_type", true)->values = {etDirectDrive, etDirectDrive};
|
||||||
|
config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type", true)->values = {nvtStandard, nvtHighFlow};
|
||||||
|
config.option<ConfigOptionStrings>("extruder_variant_list", true)->values = {"Direct Drive Standard,Direct Drive High Flow",
|
||||||
|
"Direct Drive Standard,Direct Drive High Flow"};
|
||||||
|
make_filament_arrays(config);
|
||||||
|
config.option<ConfigOptionInts>("filament_map", true)->values = {1, 2};
|
||||||
|
// sized to the filament count, but inert because no extruder exposes multiple volume types
|
||||||
|
config.option<ConfigOptionInts>("filament_volume_map", true)->values = {nvtHighFlow, nvtStandard};
|
||||||
|
|
||||||
|
std::vector<std::vector<NozzleVolumeType>> nozzle_volume_types;
|
||||||
|
int extruder_count = 2;
|
||||||
|
int count = config.get_extruder_nozzle_volume_count(extruder_count, nozzle_volume_types);
|
||||||
|
REQUIRE(count == 2);
|
||||||
|
|
||||||
|
config.update_values_to_printer_extruders_for_multiple_filaments(config, extruder_count, count, filament_keys,
|
||||||
|
"filament_self_index", "filament_extruder_variant");
|
||||||
|
|
||||||
|
// filament 1 keeps its extruder's Standard column, filament 2 its extruder's High Flow column
|
||||||
|
REQUIRE(config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->values == std::vector<double>({12., 21.}));
|
||||||
|
REQUIRE(config.option<ConfigOptionInts>("filament_self_index")->values == std::vector<int>({1, 2}));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user