diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 1283d0ac1a..61ae78b5eb 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1385,12 +1385,16 @@ const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConf return this->default_preset((opt_printer_technology == nullptr || opt_printer_technology->value == ptFFF) ? 0 : 1); } -const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model_id) const +const Preset* PrinterPresetCollection::find_system_preset_by_model_and_variant(const std::string &model_id, const std::string& variant) const { if (model_id.empty()) { return nullptr; } const auto it = std::find_if(cbegin(), cend(), [&](const Preset &preset) { - return preset.config.opt_string("printer_model") == model_id; + if (!preset.is_system || preset.config.opt_string("printer_model") != model_id) + return false; + if (variant.empty()) + return true; + return preset.config.opt_string("printer_variant") == variant; }); return it != cend() ? &*it : nullptr; diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 9d5597cac1..4897f504c7 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -592,7 +592,7 @@ public: const Preset& default_preset_for(const DynamicPrintConfig &config) const override; - const Preset* find_by_model_id(const std::string &model_id) const; + const Preset* find_system_preset_by_model_and_variant(const std::string &model_id, const std::string &variant) const; private: PrinterPresetCollection() = default; diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index adb84df67c..95d93b1c2a 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -188,7 +188,8 @@ void PresetBundle::setup_directories() } } -PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule substitution_rule, const std::string &preferred_model_id) +PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule substitution_rule, + const PresetPreferences& preferred_selection/* = PresetPreferences()*/) { // First load the vendor specific system presets. PresetsConfigSubstitutions substitutions; @@ -239,7 +240,8 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward if (! errors_cummulative.empty()) throw Slic3r::RuntimeError(errors_cummulative); - this->load_selections(config, preferred_model_id); + // ysToDo : set prefered filament or sla_material (relates to print technology) and force o use of preffered printer model if it was added + this->load_selections(config, preferred_selection); return substitutions; } @@ -441,7 +443,7 @@ void PresetBundle::load_installed_sla_materials(AppConfig &config) // Load selections (current print, current filaments, current printer) from config.ini // This is done on application start up or after updates are applied. -void PresetBundle::load_selections(AppConfig &config, const std::string &preferred_model_id) +void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& preferred_selection/* = PresetPreferences()*/) { // Update visibility of presets based on application vendor / model / variant configuration. this->load_installed_printers(config); @@ -464,13 +466,21 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr // will be selected by the following call of this->update_compatible(PresetSelectCompatibleType::Always). const Preset *initial_printer = printers.find_preset(initial_printer_profile_name); - const Preset *preferred_printer = printers.find_by_model_id(preferred_model_id); + const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant); printers.select_preset_by_name( - (preferred_printer != nullptr && (initial_printer == nullptr || !initial_printer->is_visible)) ? + (preferred_printer != nullptr /*&& (initial_printer == nullptr || !initial_printer->is_visible)*/) ? preferred_printer->name : initial_printer_profile_name, true); + // select preferred filament/sla_material profile if any exists and is visible + if (!preferred_selection.filament.empty()) + if (auto it = filaments.find_preset_internal(preferred_selection.filament); it != filaments.end() && it->is_visible) + initial_filament_profile_name = it->name; + if (!preferred_selection.sla_material.empty()) + if (auto it = sla_materials.find_preset_internal(preferred_selection.sla_material); it != sla_materials.end() && it->is_visible) + initial_sla_material_profile_name = it->name; + // Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found. prints.select_preset_by_name_strict(initial_print_profile_name); filaments.select_preset_by_name_strict(initial_filament_profile_name); diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index 3c7349668a..c22599e388 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -25,9 +25,18 @@ public: void setup_directories(); + struct PresetPreferences { + std::string printer_model_id;// name of a preferred printer model + std::string printer_variant; // name of a preferred printer variant + std::string filament; // name of a preferred filament preset + std::string sla_material; // name of a preferred sla_material preset + }; + // Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets. // Load selections (current print, current filaments, current printer) from config.ini - PresetsConfigSubstitutions load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule rule, const std::string &preferred_model_id = std::string()); + // select preferred presets, if any exist + PresetsConfigSubstitutions load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule rule, + const PresetPreferences& preferred_selection = PresetPreferences()); // Export selections (current print, current filaments, current printer) into config.ini void export_selections(AppConfig &config); @@ -153,7 +162,7 @@ private: // Load selections (current print, current filaments, current printer) from config.ini // This is done just once on application start up. - void load_selections(AppConfig &config, const std::string &preferred_model_id = ""); + void load_selections(AppConfig &config, const PresetPreferences& preferred_selection = PresetPreferences()); // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. // and the external config is just referenced, not stored into user profile directory. diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index c31bc02873..f64bdecbaa 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -2453,6 +2453,34 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo return true; } +static std::set get_new_added_presets(const std::map& old_data, const std::map& new_data) +{ + auto get_aliases = [](const std::map& data) { + std::set old_aliases; + for (auto item : data) { + const std::string& name = item.first; + size_t pos = name.find("@"); + old_aliases.emplace(pos == std::string::npos ? name : name.substr(0, pos-1)); + } + return old_aliases; + }; + + std::set old_aliases = get_aliases(old_data); + std::set new_aliases = get_aliases(new_data); + std::set diff; + std::set_difference(new_aliases.begin(), new_aliases.end(), old_aliases.begin(), old_aliases.end(), std::inserter(diff, diff.begin())); + + return diff; +} + +static std::string get_first_added_preset(const std::map& old_data, const std::map& new_data) +{ + std::set diff = get_new_added_presets(old_data, new_data); + if (diff.empty()) + return std::string(); + return *diff.begin(); +} + bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater) { const auto enabled_vendors = appconfig_new.vendors(); @@ -2525,13 +2553,61 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese preset_bundle->reset(true); } + std::string preferred_model; + std::string preferred_variant; + const auto enabled_vendors_old = app_config->vendors(); + auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old](const std::string& bundle_name, const Bundle& bundle, std::string& variant) { + const auto config = enabled_vendors.find(bundle_name); + if (config == enabled_vendors.end()) + return std::string(); + for (const auto& model : bundle.vendor_profile->models) { + if (const auto model_it = config->second.find(model.id); + model_it != config->second.end() && model_it->second.size() > 0) { + variant = *model_it->second.begin(); + const auto config_old = enabled_vendors_old.find(bundle_name); + if (config_old == enabled_vendors_old.end()) + return model.id; + const auto model_it_old = config_old->second.find(model.id); + if (model_it_old == config_old->second.end()) + return model.id; + else if (model_it_old->second != model_it->second) { + for (const auto& var : model_it->second) + if (model_it_old->second.find(var) == model_it_old->second.end()) { + variant = var; + return model.id; + } + } + } + } + if (!variant.empty()) + variant.clear(); + return std::string(); + }; + // Prusa printers are considered first, then 3rd party. + if (preferred_model = get_preferred_printer_model("PrusaResearch", bundles.prusa_bundle(), preferred_variant); + preferred_model.empty()) { + for (const auto& bundle : bundles) { + if (bundle.second.is_prusa_bundle) { continue; } + if (preferred_model = get_preferred_printer_model(bundle.first, bundle.second, preferred_variant); + !preferred_model.empty()) + break; + } + } + + std::string first_added_filament, first_added_sla_material; + auto apply_section = [this, app_config](const std::string& section_name, std::string& first_added_preset) { + if (appconfig_new.has_section(section_name)) { + // get first of new added preset names + const std::map& old_presets = app_config->has_section(section_name) ? app_config->get_section(section_name) : std::map(); + first_added_preset = get_first_added_preset(old_presets, appconfig_new.get_section(section_name)); + app_config->set_section(section_name, appconfig_new.get_section(section_name)); + } + }; + apply_section(AppConfig::SECTION_FILAMENTS, first_added_filament); + apply_section(AppConfig::SECTION_MATERIALS, first_added_sla_material); + app_config->set_vendors(appconfig_new); - if (appconfig_new.has_section(AppConfig::SECTION_FILAMENTS)) { - app_config->set_section(AppConfig::SECTION_FILAMENTS, appconfig_new.get_section(AppConfig::SECTION_FILAMENTS)); - } - if (appconfig_new.has_section(AppConfig::SECTION_MATERIALS)) { - app_config->set_section(AppConfig::SECTION_MATERIALS, appconfig_new.get_section(AppConfig::SECTION_MATERIALS)); - } + app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); app_config->set("export_sources_full_pathnames", page_reload_from_disk->full_pathnames ? "1" : "0"); @@ -2556,44 +2632,8 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese page_mode->serialize_mode(app_config); - std::string preferred_model; - - // Figure out the default pre-selected printer based on the selections in the pickers. - // The default is the first selected printer model (one with at least 1 variant selected). - // The default is only applied by load_presets() if the user doesn't have a (visible) printer - // selected already. - // Prusa printers are considered first, then 3rd party. - const auto config_prusa = enabled_vendors.find("PrusaResearch"); - if (config_prusa != enabled_vendors.end()) { - for (const auto &model : bundles.prusa_bundle().vendor_profile->models) { - const auto model_it = config_prusa->second.find(model.id); - if (model_it != config_prusa->second.end() && model_it->second.size() > 0) { - preferred_model = model.id; - break; - } - } - } - if (preferred_model.empty()) { - for (const auto &bundle : bundles) { - if (bundle.second.is_prusa_bundle) { continue; } - - const auto config = enabled_vendors.find(bundle.first); - if (config == enabled_vendors.end()) { continue; } - for (const auto &model : bundle.second.vendor_profile->models) { - const auto model_it = config->second.find(model.id); - if (model_it != config->second.end() && model_it->second.size() > 0) { - preferred_model = model.id; - break; - } - } - } - } - - // Reloading the configs after some modifications were done to PrusaSlicer.ini. - // Just perform the substitutions silently, as the substitutions were already presented to the user on application start-up - // and the Wizard shall not create any new values that would require substitution. - // Throw on substitutions in system profiles, as the system profiles provided over the air should be compatible with this PrusaSlicer version. - preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem, preferred_model); + preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem, + {preferred_model, preferred_variant, first_added_filament, first_added_sla_material}); if (page_custom->custom_wanted()) { page_firmware->apply_custom_config(*custom_config); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index aab8c28292..b8d4ead509 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -634,6 +634,12 @@ PlaterPresetComboBox::~PlaterPresetComboBox() edit_btn->Destroy(); } +static void run_wizard(ConfigWizard::StartPage sp) +{ + if (wxGetApp().check_and_save_current_preset_changes()) + wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); +} + void PlaterPresetComboBox::OnSelect(wxCommandEvent &evt) { auto selected_item = evt.GetSelection(); @@ -653,7 +659,7 @@ void PlaterPresetComboBox::OnSelect(wxCommandEvent &evt) case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break; default: break; } - wxTheApp->CallAfter([sp]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); }); + wxTheApp->CallAfter([sp]() { run_wizard(sp); }); } return; } @@ -685,7 +691,7 @@ void PlaterPresetComboBox::show_add_menu() append_menu_item(menu, wxID_ANY, _L("Add/Remove presets"), "", [](wxCommandEvent&) { - wxTheApp->CallAfter([]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS); }); + wxTheApp->CallAfter([]() { run_wizard(ConfigWizard::SP_PRINTERS); }); }, "edit_uni", menu, []() { return true; }, wxGetApp().plater()); append_menu_item(menu, wxID_ANY, _L("Add physical printer"), "", @@ -715,7 +721,7 @@ void PlaterPresetComboBox::show_edit_menu() else append_menu_item(menu, wxID_ANY, _L("Add/Remove presets"), "", [](wxCommandEvent&) { - wxTheApp->CallAfter([]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS); }); + wxTheApp->CallAfter([]() { run_wizard(ConfigWizard::SP_PRINTERS); }); }, "edit_uni", menu, []() { return true; }, wxGetApp().plater()); append_menu_item(menu, wxID_ANY, _L("Add physical printer"), "", @@ -918,7 +924,7 @@ void TabPresetComboBox::OnSelect(wxCommandEvent &evt) this->SetSelection(m_last_selected); if (marker == LABEL_ITEM_WIZARD_PRINTERS) wxTheApp->CallAfter([this]() { - wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS); + run_wizard(ConfigWizard::SP_PRINTERS); // update combobox if its parent is a PhysicalPrinterDialog PhysicalPrinterDialog* parent = dynamic_cast(this->GetParent());