Storing and recovering the "compatible_printers_condition"

and "inherits" fields from / to the AMF/3MF/Config files.
The "compatible_printers_condition" are collected over all active profiles
(one print, possibly multiple filament, and one printer profile)
into a single vector.
This commit is contained in:
bubnikv 2018-06-26 10:50:50 +02:00
parent 082ed95a94
commit 1175dc95f6
6 changed files with 128 additions and 41 deletions

View file

@ -52,26 +52,40 @@ PresetBundle::PresetBundle() :
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
wxImage::AddHandler(new wxPNGHandler);
// Create the ID config keys, as they are not part of the Static print config classes.
this->prints.default_preset().config.opt_string("print_settings_id", true);
this->filaments.default_preset().config.option<ConfigOptionStrings>("filament_settings_id", true)->values.assign(1, std::string());
this->printers.default_preset().config.opt_string("printer_settings_id", true);
// "compatible printers" are not mandatory yet.
// The following keys are handled by the UI, they do not have a counterpart in any StaticPrintConfig derived classes,
// therefore they need to be handled differently. As they have no counterpart in StaticPrintConfig, they are not being
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
//
// "compatible_printers", "compatible_printers_condition", "inherits",
// "print_settings_id", "filament_settings_id", "printer_settings_id",
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
//
//FIXME Rename "compatible_printers" and "compatible_printers_condition", as they are defined in both print and filament profiles,
// therefore they are clashing when generating a a config file, G-code or AMF/3MF.
// this->filaments.default_preset().config.optptr("compatible_printers", true);
// this->filaments.default_preset().config.optptr("compatible_printers_condition", true);
// this->prints.default_preset().config.optptr("compatible_printers", true);
// this->prints.default_preset().config.optptr("compatible_printers_condition", true);
// Create the "printer_vendor", "printer_model" and "printer_variant" keys.
// Create the ID config keys, as they are not part of the Static print config classes.
this->prints.default_preset().config.optptr("print_settings_id", true);
this->prints.default_preset().config.option<ConfigOptionStrings>("compatible_printers_condition", true)->values = { "" };
this->prints.default_preset().config.option<ConfigOptionStrings>("inherits", true)->values = { "" };
this->filaments.default_preset().config.option<ConfigOptionStrings>("filament_settings_id", true)->values = { "" };
this->filaments.default_preset().config.option<ConfigOptionStrings>("compatible_printers_condition", true)->values = { "" };
this->filaments.default_preset().config.option<ConfigOptionStrings>("inherits", true)->values = { "" };
this->printers.default_preset().config.optptr("printer_settings_id", true);
this->printers.default_preset().config.optptr("printer_vendor", true);
this->printers.default_preset().config.optptr("printer_model", true);
this->printers.default_preset().config.optptr("printer_variant", true);
// Load the default preset bitmaps.
this->printers.default_preset().config.optptr("default_print_profile", true);
this->printers.default_preset().config.optptr("default_filament_profile", true);
this->printers.default_preset().config.option<ConfigOptionStrings>("inherits", true)->values = { "" };
// Load the default preset bitmaps.
this->prints .load_bitmap_default("cog.png");
this->filaments.load_bitmap_default("spool.png");
this->printers .load_bitmap_default("printer_empty.png");
this->load_compatible_bitmaps();
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
this->prints .select_preset(0);
this->filaments.select_preset(0);
@ -370,9 +384,20 @@ DynamicPrintConfig PresetBundle::full_config() const
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(out.option("nozzle_diameter"));
size_t num_extruders = nozzle_diameter->values.size();
// Collect the "compatible_printers_condition" and "inherits" values over all presets (print, filaments, printers) into a single vector.
std::vector<std::string> compatible_printers_condition;
std::vector<std::string> inherits;
auto append_config_string = [](const DynamicConfig &cfg, const std::string &key, std::vector<std::string> &dst) {
const ConfigOptionStrings *opt = cfg.opt<ConfigOptionStrings>(key);
dst.emplace_back((opt == nullptr || opt->values.empty()) ? "" : opt->values.front());
};
append_config_string(this->prints.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition);
append_config_string(this->prints.get_edited_preset().config, "inherits", inherits);
if (num_extruders <= 1) {
out.apply(this->filaments.get_edited_preset().config);
append_config_string(this->filaments.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition);
append_config_string(this->filaments.get_edited_preset().config, "inherits", inherits);
} else {
// Retrieve filament presets and build a single config object for them.
// First collect the filament configurations based on the user selection of this->filament_presets.
@ -382,11 +407,15 @@ DynamicPrintConfig PresetBundle::full_config() const
filament_configs.emplace_back(&this->filaments.find_preset(filament_preset_name, true)->config);
while (filament_configs.size() < num_extruders)
filament_configs.emplace_back(&this->filaments.first_visible().config);
for (const DynamicPrintConfig *cfg : filament_configs) {
append_config_string(*cfg, "compatible_printers_condition", compatible_printers_condition);
append_config_string(*cfg, "inherits", inherits);
}
// Option values to set a ConfigOptionVector from.
std::vector<const ConfigOption*> filament_opts(num_extruders, nullptr);
// loop through options and apply them to the resulting config.
for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) {
if (key == "compatible_printers" || key == "compatible_printers_condition")
if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits")
continue;
// Get a destination option.
ConfigOption *opt_dst = out.option(key, false);
@ -404,9 +433,13 @@ DynamicPrintConfig PresetBundle::full_config() const
}
}
//FIXME These two value types clash between the print and filament profiles. They should be renamed.
// Don't store the "compatible_printers_condition" for the printer profile, there is none.
append_config_string(this->printers.get_edited_preset().config, "inherits", inherits);
// These two value types clash between the print and filament profiles. They should be renamed.
out.erase("compatible_printers");
out.erase("compatible_printers_condition");
out.erase("inherits");
static const char *keys[] = { "perimeter", "infill", "solid_infill", "support_material", "support_material_interface" };
for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++ i) {
@ -419,6 +452,22 @@ DynamicPrintConfig PresetBundle::full_config() const
out.option<ConfigOptionString >("print_settings_id", true)->value = this->prints.get_selected_preset().name;
out.option<ConfigOptionStrings>("filament_settings_id", true)->values = this->filament_presets;
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset().name;
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
// The vector will not be stored if all fields are empty strings.
auto add_if_some_non_empty = [&out](std::vector<std::string> &&values, const std::string &key) {
bool nonempty = false;
for (const std::string &v : values)
if (! v.empty()) {
nonempty = true;
break;
}
if (nonempty)
out.set_key_value(key, new ConfigOptionStrings(std::move(values)));
};
add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition");
add_if_some_non_empty(std::move(inherits), "inherits");
return out;
}
@ -497,6 +546,20 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
}
}
size_t num_extruders = std::min(config.option<ConfigOptionFloats>("nozzle_diameter" )->values.size(),
config.option<ConfigOptionFloats>("filament_diameter")->values.size());
// Make a copy of the "compatible_printers_condition" and "inherits" vectors, which
// accumulate values over all presets (print, filaments, printers).
// These values will be distributed into their particular presets when loading.
auto *compatible_printers_condition = config.option<ConfigOptionStrings>("compatible_printers_condition", true);
auto *inherits = config.option<ConfigOptionStrings>("inherits", true);
std::vector<std::string> compatible_printers_condition_values = std::move(compatible_printers_condition->values);
std::vector<std::string> inherits_values = std::move(inherits->values);
if (compatible_printers_condition_values.empty())
compatible_printers_condition_values.emplace_back(std::string());
if (inherits_values.empty())
inherits_values.emplace_back(std::string());
// 1) Create a name from the file name.
// Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
std::string name = is_external ? boost::filesystem::path(name_or_path).filename().string() : name_or_path;
@ -505,6 +568,11 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// First load the print and printer presets.
for (size_t i_group = 0; i_group < 2; ++ i_group) {
PresetCollection &presets = (i_group == 0) ? this->prints : this->printers;
// Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles.
size_t idx = (i_group == 0) ? 0 : num_extruders + 1;
inherits->values = { (idx < inherits_values.size()) ? inherits_values[idx] : "" };
if (i_group == 0)
compatible_printers_condition->values = { compatible_printers_condition_values.front() };
if (is_external)
presets.load_external_preset(name_or_path, name,
config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id"),
@ -513,10 +581,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
presets.load_preset(presets.path_from_name(name), name, config).save();
}
// Update the "compatible_printers_condition" and "inherits" vectors, so their number matches the number of extruders.
compatible_printers_condition_values.erase(compatible_printers_condition_values.begin());
inherits_values.erase(inherits_values.begin());
compatible_printers_condition_values.resize(num_extruders, std::string());
inherits_values.resize(num_extruders, std::string());
compatible_printers_condition->values = std::move(compatible_printers_condition_values);
inherits->values = std::move(inherits_values);
// 3) Now load the filaments. If there are multiple filament presets, split them and load them.
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter"));
auto *filament_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("filament_diameter"));
size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size());
const ConfigOptionStrings *old_filament_profile_names = config.option<ConfigOptionStrings>("filament_settings_id", false);
assert(old_filament_profile_names != nullptr);
if (num_extruders <= 1) {