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:
parent
082ed95a94
commit
1175dc95f6
6 changed files with 128 additions and 41 deletions
|
@ -188,7 +188,10 @@ void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys
|
|||
throw UnknownOptionException(opt_key);
|
||||
}
|
||||
const ConfigOption *other_opt = other.option(opt_key);
|
||||
if (other_opt != nullptr)
|
||||
if (other_opt == nullptr) {
|
||||
// The key was not found in the source config, therefore it will not be initialized!
|
||||
// printf("Not found, therefore not initialized: %s\n", opt_key.c_str());
|
||||
} else
|
||||
my_opt->set(other_opt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1419,7 +1419,10 @@ void GCode::append_full_config(const Print& print, std::string& str)
|
|||
str += "; " + key + " = " + cfg->serialize(key) + "\n";
|
||||
}
|
||||
const DynamicConfig &full_config = print.placeholder_parser.config();
|
||||
for (const char *key : { "print_settings_id", "filament_settings_id", "printer_settings_id" })
|
||||
for (const char *key : {
|
||||
"print_settings_id", "filament_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant", "default_print_profile", "default_filament_profile",
|
||||
"compatible_printers_condition", "inherits" })
|
||||
str += std::string("; ") + key + " = " + full_config.serialize(key) + "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -147,12 +147,15 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->label = L("Compatible printers");
|
||||
def->default_value = new ConfigOptionStrings();
|
||||
|
||||
def = this->add("compatible_printers_condition", coString);
|
||||
// The following value is defined as a vector of strings, so it could
|
||||
// collect the "inherits" values over the print and filaments profiles
|
||||
// when storing into a project file (AMF, 3MF, Config ...)
|
||||
def = this->add("compatible_printers_condition", coStrings);
|
||||
def->label = L("Compatible printers condition");
|
||||
def->tooltip = L("A boolean expression using the configuration values of an active printer profile. "
|
||||
"If this expression evaluates to true, this profile is considered compatible "
|
||||
"with the active printer profile.");
|
||||
def->default_value = new ConfigOptionString();
|
||||
def->default_value = new ConfigOptionStrings { "" };
|
||||
|
||||
def = this->add("complete_objects", coBool);
|
||||
def->label = L("Complete individual objects");
|
||||
|
@ -819,12 +822,15 @@ PrintConfigDef::PrintConfigDef()
|
|||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(80);
|
||||
|
||||
def = this->add("inherits", coString);
|
||||
// The following value is defined as a vector of strings, so it could
|
||||
// collect the "inherits" values over the print and filaments profiles
|
||||
// when storing into a project file (AMF, 3MF, Config ...)
|
||||
def = this->add("inherits", coStrings);
|
||||
def->label = L("Inherits profile");
|
||||
def->tooltip = L("Name of the profile, from which this profile inherits.");
|
||||
def->full_width = true;
|
||||
def->height = 50;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
def->default_value = new ConfigOptionStrings { "" };
|
||||
|
||||
def = this->add("interface_shells", coBool);
|
||||
def->label = L("Interface shells");
|
||||
|
|
|
@ -180,7 +180,7 @@ void Preset::normalize(DynamicPrintConfig &config)
|
|||
size_t n = (nozzle_diameter == nullptr) ? 1 : nozzle_diameter->values.size();
|
||||
const auto &defaults = FullPrintConfig::defaults();
|
||||
for (const std::string &key : Preset::filament_options()) {
|
||||
if (key == "compatible_printers")
|
||||
if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits")
|
||||
continue;
|
||||
auto *opt = config.option(key, false);
|
||||
assert(opt != nullptr);
|
||||
|
@ -234,12 +234,12 @@ std::string Preset::label() const
|
|||
|
||||
bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const
|
||||
{
|
||||
auto *condition = dynamic_cast<const ConfigOptionString*>(this->config.option("compatible_printers_condition"));
|
||||
auto *condition = dynamic_cast<const ConfigOptionStrings*>(this->config.option("compatible_printers_condition"));
|
||||
auto *compatible_printers = dynamic_cast<const ConfigOptionStrings*>(this->config.option("compatible_printers"));
|
||||
bool has_compatible_printers = compatible_printers != nullptr && ! compatible_printers->values.empty();
|
||||
if (! has_compatible_printers && condition != nullptr && ! condition->value.empty()) {
|
||||
if (! has_compatible_printers && condition != nullptr && ! condition->values.empty() && ! condition->values.front().empty()) {
|
||||
try {
|
||||
return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config, extra_config);
|
||||
return PlaceholderParser::evaluate_boolean_expression(condition->values.front(), active_printer.config, extra_config);
|
||||
} catch (const std::runtime_error &err) {
|
||||
//FIXME in case of an error, return "compatible with everything".
|
||||
printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what());
|
||||
|
@ -449,9 +449,8 @@ Preset& PresetCollection::load_external_preset(
|
|||
std::deque<Preset>::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name);
|
||||
if (it != m_presets.end()) {
|
||||
t_config_option_keys diff = it->config.diff(cfg);
|
||||
//FIXME Following keys are either not updated in the preset (the *_settings_id),
|
||||
// or not stored into the AMF/3MF/Config file, therefore they will most likely not match.
|
||||
// Ignore these differences for now.
|
||||
// Following keys are used by the UI, not by the slicing core, therefore they are not important
|
||||
// when comparing profiles for equality. Ignore them.
|
||||
for (const char *key : { "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
"print_settings_id", "filament_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant", "default_print_profile", "default_filament_profile" })
|
||||
|
@ -503,7 +502,10 @@ void PresetCollection::save_current_preset(const std::string &new_name)
|
|||
} else {
|
||||
// Creating a new preset.
|
||||
Preset &preset = *m_presets.insert(it, m_edited_preset);
|
||||
std::string &inherits = preset.config.opt_string("inherits", true);
|
||||
ConfigOptionStrings *opt_inherits = preset.config.option<ConfigOptionStrings>("inherits", true);
|
||||
if (opt_inherits->values.empty())
|
||||
opt_inherits->values.emplace_back(std::string());
|
||||
std::string &inherits = opt_inherits->values.front();
|
||||
std::string old_name = preset.name;
|
||||
preset.name = new_name;
|
||||
preset.file = this->path_from_name(new_name);
|
||||
|
@ -556,20 +558,20 @@ bool PresetCollection::load_bitmap_default(const std::string &file_name)
|
|||
|
||||
const Preset* PresetCollection::get_selected_preset_parent() const
|
||||
{
|
||||
auto *inherits = dynamic_cast<const ConfigOptionString*>(this->get_edited_preset().config.option("inherits"));
|
||||
if (inherits == nullptr || inherits->value.empty())
|
||||
return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; // nullptr;
|
||||
const Preset* preset = this->find_preset(inherits->value, false);
|
||||
auto *inherits = dynamic_cast<const ConfigOptionStrings*>(this->get_edited_preset().config.option("inherits"));
|
||||
if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty())
|
||||
return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr;
|
||||
const Preset* preset = this->find_preset(inherits->values.front(), false);
|
||||
return (preset == nullptr || preset->is_default || preset->is_external) ? nullptr : preset;
|
||||
}
|
||||
|
||||
const Preset* PresetCollection::get_preset_parent(const Preset& child) const
|
||||
{
|
||||
auto *inherits = dynamic_cast<const ConfigOptionString*>(child.config.option("inherits"));
|
||||
if (inherits == nullptr || inherits->value.empty())
|
||||
auto *inherits = dynamic_cast<const ConfigOptionStrings*>(child.config.option("inherits"));
|
||||
if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty())
|
||||
// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr;
|
||||
return nullptr;
|
||||
const Preset* preset = this->find_preset(inherits->value, false);
|
||||
const Preset* preset = this->find_preset(inherits->values.front(), false);
|
||||
return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -803,7 +803,7 @@ void Tab::reload_compatible_printers_widget()
|
|||
bool has_any = !m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
|
||||
has_any ? m_compatible_printers_btn->Enable() : m_compatible_printers_btn->Disable();
|
||||
m_compatible_printers_checkbox->SetValue(!has_any);
|
||||
get_field("compatible_printers_condition")->toggle(!has_any);
|
||||
get_field("compatible_printers_condition", 0)->toggle(!has_any);
|
||||
}
|
||||
|
||||
void TabPrint::build()
|
||||
|
@ -1014,7 +1014,7 @@ void TabPrint::build()
|
|||
};
|
||||
optgroup->append_line(line, &m_colored_Label);
|
||||
|
||||
option = optgroup->get_option("compatible_printers_condition");
|
||||
option = optgroup->get_option("compatible_printers_condition", 0);
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
|
@ -1365,7 +1365,7 @@ void TabFilament::build()
|
|||
};
|
||||
optgroup->append_line(line, &m_colored_Label);
|
||||
|
||||
option = optgroup->get_option("compatible_printers_condition");
|
||||
option = optgroup->get_option("compatible_printers_condition", 0);
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
|
@ -2240,7 +2240,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox
|
|||
// All printers have been made compatible with this preset.
|
||||
if ((*checkbox)->GetValue())
|
||||
load_key_value("compatible_printers", std::vector<std::string> {});
|
||||
get_field("compatible_printers_condition")->toggle((*checkbox)->GetValue());
|
||||
get_field("compatible_printers_condition", 0)->toggle((*checkbox)->GetValue());
|
||||
update_changed_ui();
|
||||
}) );
|
||||
|
||||
|
|
Loading…
Reference in a new issue