diff --git a/resources/icons/export_prusa_config.svg b/resources/icons/export_prusa_config.svg
new file mode 100644
index 000000000..f3225e29a
--- /dev/null
+++ b/resources/icons/export_prusa_config.svg
@@ -0,0 +1,24 @@
+
+
+
diff --git a/resources/icons/import_prusa_config.svg b/resources/icons/import_prusa_config.svg
new file mode 100644
index 000000000..567ffaf53
--- /dev/null
+++ b/resources/icons/import_prusa_config.svg
@@ -0,0 +1,29 @@
+
+
+
diff --git a/resources/icons/import_prusa_config_bundle.svg b/resources/icons/import_prusa_config_bundle.svg
new file mode 100644
index 000000000..14224e96a
--- /dev/null
+++ b/resources/icons/import_prusa_config_bundle.svg
@@ -0,0 +1,66 @@
+
+
+
diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp
index 105db05c9..bd7296a29 100644
--- a/src/libslic3r/Format/3mf.cpp
+++ b/src/libslic3r/Format/3mf.cpp
@@ -5,6 +5,7 @@
#include "../GCode.hpp"
#include "../Geometry.hpp"
#include "../GCode/ThumbnailData.hpp"
+#include "../PrintConfig.hpp"
#include "../Time.hpp"
#include "../I18N.hpp"
@@ -592,34 +593,6 @@ namespace Slic3r {
XML_StopParser(m_xml_parser, false);
}
- template
- void convert_from_prusa(CONFIG_CLASS& conf, const DynamicPrintConfig& global_config) {
- //void convert_from_prusa(DynamicPrintConfig& conf, const DynamicPrintConfig & global_config) {
- //void convert_from_prusa(ModelConfigObject& conf, const DynamicPrintConfig& global_config) {
- for (const t_config_option_key& opt_key : conf.keys()) {
- const ConfigOption* opt = conf.option(opt_key);
- std::string serialized = opt->serialize();
- std::string key = opt_key;
- std::map result = PrintConfigDef::from_prusa(key, serialized, global_config);
- if (key != opt_key) {
- conf.erase(opt_key);
- }
- if (!key.empty() && serialized != opt->serialize()) {
- ConfigOption* opt_new = opt->clone();
- opt_new->deserialize(serialized);
- conf.set_key_value(key, opt_new);
- }
- for (auto entry : result) {
- const ConfigOptionDef* def = print_config_def.get(entry.first);
- if (def) {
- ConfigOption* opt_new = def->default_value.get()->clone();
- opt_new->deserialize(entry.second);
- conf.set_key_value(entry.first, opt_new);
- }
- }
- }
- }
-
bool _3MF_Importer::_load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions)
{
mz_zip_archive archive;
@@ -761,7 +734,7 @@ namespace Slic3r {
return false;
else {
use_prusa_config = true;
- convert_from_prusa(config, config);
+ config.convert_from_prusa();
}
close_zip_reader(&archive);
@@ -841,11 +814,11 @@ namespace Slic3r {
return false;
if (use_prusa_config) {
- convert_from_prusa(model_object->config, config);
+ model_object->config.convert_from_prusa(config);
for (ModelVolume* volume : model_object->volumes)
- convert_from_prusa(volume->config, config);
+ volume->config.convert_from_prusa(config);
for (auto entry : model_object->layer_config_ranges)
- convert_from_prusa(entry.second, config);
+ entry.second.convert_from_prusa(config);
}
}
diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp
index 61788dbe1..8cd6e164e 100644
--- a/src/libslic3r/PresetBundle.cpp
+++ b/src/libslic3r/PresetBundle.cpp
@@ -5,6 +5,7 @@
#include "Utils.hpp"
#include "Model.hpp"
#include "format.hpp"
+#include "PrintConfig.hpp"
#include
#include
@@ -679,13 +680,15 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
// Instead of a config file, a G-code may be loaded containing the full set of parameters.
// In the future the configuration will likely be read from an AMF file as well.
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
-ConfigSubstitutions PresetBundle::load_config_file(const std::string &path, ForwardCompatibilitySubstitutionRule compatibility_rule)
+ConfigSubstitutions PresetBundle::load_config_file(const std::string &path, ForwardCompatibilitySubstitutionRule compatibility_rule, bool from_prusa)
{
if (is_gcode_file(path)) {
DynamicPrintConfig config;
config.apply(FullPrintConfig::defaults());
ConfigSubstitutions config_substitutions = config.load_from_gcode_file(path, compatibility_rule);
Preset::normalize(config);
+ if(from_prusa)
+ config.convert_from_prusa();
load_config_file_config(path, true, std::move(config));
return config_substitutions;
}
@@ -720,11 +723,13 @@ ConfigSubstitutions PresetBundle::load_config_file(const std::string &path, Forw
config.apply(FullPrintConfig::defaults());
config_substitutions = config.load(tree, compatibility_rule);
Preset::normalize(config);
+ if (from_prusa)
+ config.convert_from_prusa();
load_config_file_config(path, true, std::move(config));
return config_substitutions;
}
case CONFIG_FILE_TYPE_CONFIG_BUNDLE:
- return load_config_file_config_bundle(path, tree, compatibility_rule);
+ return load_config_file_config_bundle(path, tree, compatibility_rule, from_prusa);
}
} catch (const ConfigurationError &e) {
throw Slic3r::RuntimeError(format("Invalid configuration file %1%: %2%", path, e.what()));
@@ -906,11 +911,11 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.
// Note: only called when using --load from cli. Will load the bundle like with the menu but wihtout saving it.
ConfigSubstitutions PresetBundle::load_config_file_config_bundle(
- const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule)
+ const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule, bool from_prusa)
{
// Load the config bundle, but don't save the loaded presets to user profile directory
// [PresetsConfigSubstitutions, size_t]
- auto [presets_substitutions, presets_imported] = this->load_configbundle(path, { }, compatibility_rule);
+ auto [presets_substitutions, presets_imported] = this->load_configbundle(path, (from_prusa ? LoadConfigBundleAttributes{ LoadConfigBundleAttribute::ConvertFromPrusa } : LoadConfigBundleAttribute{ }), compatibility_rule);
ConfigSubstitutions config_substitutions;
this->update_compatible(PresetSelectCompatibleType::Never);
for (PresetConfigSubstitutions &sub : presets_substitutions)
@@ -1205,7 +1210,7 @@ std::pair PresetBundle::load_configbundle(
std::string alias_name;
std::vector renamed_from;
try {
- auto parse_config_section = [§ion, &alias_name, &renamed_from, &substitution_context, &path](DynamicPrintConfig &config) {
+ auto parse_config_section = [§ion, &alias_name, &renamed_from, &substitution_context, &path, &flags](DynamicPrintConfig &config) {
substitution_context.substitutions.clear();
for (auto &kvp : section.second) {
if (kvp.first == "alias")
@@ -1219,6 +1224,8 @@ std::pair PresetBundle::load_configbundle(
// Throws on parsing error. For system presets, no substituion is being done, but an exception is thrown.
config.set_deserialize(kvp.first, kvp.second.data(), substitution_context);
}
+ if (flags.has(LoadConfigBundleAttribute::ConvertFromPrusa))
+ config.convert_from_prusa();
};
if (presets == &this->printers) {
// Select the default config based on the printer_technology field extracted from kvp.
diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp
index d54cec73a..a974f6ed2 100644
--- a/src/libslic3r/PresetBundle.hpp
+++ b/src/libslic3r/PresetBundle.hpp
@@ -85,7 +85,7 @@ public:
// Instead of a config file, a G-code may be loaded containing the full set of parameters.
// In the future the configuration will likely be read from an AMF file as well.
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
- ConfigSubstitutions load_config_file(const std::string &path, ForwardCompatibilitySubstitutionRule compatibility_rule);
+ ConfigSubstitutions load_config_file(const std::string &path, ForwardCompatibilitySubstitutionRule compatibility_rule, bool from_prusa = false);
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
@@ -100,6 +100,8 @@ public:
// Load a system config bundle.
LoadSystem,
LoadVendorOnly,
+ //apply import rule from prusa
+ ConvertFromPrusa,
};
using LoadConfigBundleAttributes = enum_bitmask;
// Load the config bundle based on the flags.
@@ -162,7 +164,7 @@ private:
// If it is not an external config, then the config will be stored into the user profile directory.
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config);
ConfigSubstitutions load_config_file_config_bundle(
- const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule);
+ const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule, bool from_prusa = false);
DynamicPrintConfig full_fff_config() const;
DynamicPrintConfig full_sla_config() const;
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index dec20cb1b..53800ee86 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -5724,9 +5724,49 @@ std::map PrintConfigDef::from_prusa(t_config_option_key
if ("xy_size_compensation" == opt_key) {
output["xy_inner_size_compensation"] = value;
}
+ if ("infill_anchor_max" == opt_key) {
+ if(value == "0")
+ output["infill_connection"] = "notconnected";
+ }
return output;
}
+
+template
+void _convert_from_prusa(CONFIG_CLASS& conf, const DynamicPrintConfig& global_config) {
+ //void convert_from_prusa(DynamicPrintConfig& conf, const DynamicPrintConfig & global_config) {
+ //void convert_from_prusa(ModelConfigObject& conf, const DynamicPrintConfig& global_config) {
+ for (const t_config_option_key& opt_key : conf.keys()) {
+ const ConfigOption* opt = conf.option(opt_key);
+ std::string serialized = opt->serialize();
+ std::string key = opt_key;
+ std::map result = PrintConfigDef::from_prusa(key, serialized, global_config);
+ if (key != opt_key) {
+ conf.erase(opt_key);
+ }
+ if (!key.empty() && serialized != opt->serialize()) {
+ ConfigOption* opt_new = opt->clone();
+ opt_new->deserialize(serialized);
+ conf.set_key_value(key, opt_new);
+ }
+ for (auto entry : result) {
+ const ConfigOptionDef* def = print_config_def.get(entry.first);
+ if (def) {
+ ConfigOption* opt_new = def->default_value.get()->clone();
+ opt_new->deserialize(entry.second);
+ conf.set_key_value(entry.first, opt_new);
+ }
+ }
+ }
+}
+
+void DynamicPrintConfig::convert_from_prusa() {
+ _convert_from_prusa(*this, *this);
+}
+void ModelConfig::convert_from_prusa(const DynamicPrintConfig& global_config) {
+ _convert_from_prusa(*this, global_config);
+}
+
std::unordered_set prusa_export_to_remove_keys = {
"allow_empty_layers",
"avoid_crossing_not_first_layer",
@@ -5972,6 +6012,12 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
}
}
}
+ if ("infill_anchor_max" == opt_key) {
+ //it's infill_anchor == 0 that disable it for prusa
+ if (all_conf.opt_serialize("infill_connection") == "notconnected") {
+ value = "0";
+ }
+ }
}
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index a9690d221..592b576ab 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -425,6 +425,8 @@ private:
std::vector m_milling_option_keys;
};
+
+
// The one and only global definition of SLic3r configuration options.
// This definition is constant.
extern const PrintConfigDef print_config_def;
@@ -477,6 +479,8 @@ public:
void to_prusa(t_config_option_key& opt_key, std::string& value) const override
{ PrintConfigDef::to_prusa(opt_key, value, *this); }
+ // utilities to help convert from prusa config.
+ void convert_from_prusa();
///
/// callback to changed other settings that are linked (like width & spacing)
@@ -1986,6 +1990,10 @@ public:
// Not thread safe! Should not be called from other than the main thread!
void touch() { m_timestamp = ++ s_last_timestamp; }
+
+ // utilities to help convert from prusa config.
+ void convert_from_prusa(const DynamicPrintConfig& global_config);
+
private:
friend class cereal::access;
template void serialize(Archive& ar) { ar(m_timestamp); ar(m_data); }
@@ -1996,6 +2004,8 @@ private:
static uint64_t s_last_timestamp;
};
+
+
} // namespace Slic3r
// Serialization through the Cereal library
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index f4373eb54..e862a385d 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -388,7 +388,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder", "infill_anchor_max" })
toggle_field(el, have_infill);
// Only allow configuration of open anchors if the anchoring is enabled.
- bool has_infill_anchors = have_infill && config->option("infill_anchor_max")->value > 0;
+ bool has_infill_anchors = have_infill && config->option>("infill_connection")->value != InfillConnection::icNotConnected;
+ toggle_field("infill_anchor_max", has_infill_anchors);
+ has_infill_anchors = has_infill_anchors && config->option("infill_anchor_max")->value > 0;
toggle_field("infill_anchor", has_infill_anchors);
bool can_have_infill_dense = config->option("fill_density")->value < 50;
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index c7aceb01b..60b46ce5f 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -1277,6 +1277,9 @@ void MainFrame::init_menubar_as_editor()
append_menu_item(import_menu, wxID_ANY, _L("Import &Config") + dots + "\tCtrl+L", _L("Load exported configuration file"),
[this](wxCommandEvent&) { load_config_file(); }, "import_config", nullptr,
[]() {return true; }, this);
+ append_menu_item(import_menu, wxID_ANY, _L("Import Prusa Config") + dots, _L("Load configuration file exported from PrusaSlicer"),
+ [this](wxCommandEvent&) { load_config_file(true); }, "import_prusa_config", nullptr,
+ []() {return true; }, this);
append_menu_item(import_menu, wxID_ANY, _L("Import Config from &project") + dots +"\tCtrl+Alt+L", _L("Load configuration from project file"),
[this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "import_config", nullptr,
[]() {return true; }, this);
@@ -1284,6 +1287,9 @@ void MainFrame::init_menubar_as_editor()
append_menu_item(import_menu, wxID_ANY, _L("Import Config &Bundle") + dots, _L("Load presets from a bundle"),
[this](wxCommandEvent&) { load_configbundle(); }, "import_config_bundle", nullptr,
[]() {return true; }, this);
+ append_menu_item(import_menu, wxID_ANY, _L("Import Prusa Config Bundle") + dots, _L("Load presets from a PrusaSlicer bundle"),
+ [this](wxCommandEvent&) { load_configbundle(wxEmptyString, true); }, "import_prusa_config_bundle", nullptr,
+ []() {return true; }, this);
append_submenu(fileMenu, import_menu, wxID_ANY, _L("&Import"), "");
wxMenu* export_menu = new wxMenu();
@@ -1324,7 +1330,7 @@ void MainFrame::init_menubar_as_editor()
[]() {return true; }, this);
export_menu->AppendSeparator();
append_menu_item(export_menu, wxID_ANY, _L("Export to &Prusa Config") + dots, _L("Export current configuration to file, with only settings compatible with PrusaSlicer"),
- [this](wxCommandEvent&) { export_config(true); }, "export_config", nullptr,
+ [this](wxCommandEvent&) { export_config(true); }, "export_prusa_config", nullptr,
[]() {return true; }, this);
append_submenu(fileMenu, export_menu, wxID_ANY, _L("&Export"), "");
@@ -1812,7 +1818,7 @@ void MainFrame::export_config(bool to_prusa)
}
// Load a config file containing a Print, Filament & Printer preset.
-void MainFrame::load_config_file()
+void MainFrame::load_config_file(bool from_prusa)
{
if (!wxGetApp().check_unsaved_changes())
return;
@@ -1822,17 +1828,17 @@ void MainFrame::load_config_file()
wxString file;
if (dlg.ShowModal() == wxID_OK)
file = dlg.GetPath();
- if (! file.IsEmpty() && this->load_config_file(file.ToUTF8().data())) {
+ if (! file.IsEmpty() && this->load_config_file(file.ToUTF8().data(), from_prusa)) {
wxGetApp().app_config->update_config_dir(get_dir_name(file));
m_last_config = file;
}
}
// Load a config file containing a Print, Filament & Printer preset from command line.
-bool MainFrame::load_config_file(const std::string &path)
+bool MainFrame::load_config_file(const std::string &path, bool from_prusa)
{
try {
- ConfigSubstitutions config_substitutions = wxGetApp().preset_bundle->load_config_file(path, ForwardCompatibilitySubstitutionRule::Enable);
+ ConfigSubstitutions config_substitutions = wxGetApp().preset_bundle->load_config_file(path, ForwardCompatibilitySubstitutionRule::Enable, from_prusa);
if (!config_substitutions.empty())
show_substitutions_info(config_substitutions, path);
} catch (const std::exception& ex) {
@@ -1875,7 +1881,7 @@ void MainFrame::export_configbundle(bool export_physical_printers /*= false*/)
// Loading a config bundle with an external file name used to be used
// to auto - install a config bundle on a fresh user account,
// but that behavior was not documented and likely buggy.
-void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/)
+void MainFrame::load_configbundle(wxString file/* = wxEmptyString*/, bool from_prusa/* = false*/)
{
if (!wxGetApp().check_unsaved_changes())
return;
@@ -1893,9 +1899,12 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re
size_t presets_imported = 0;
PresetsConfigSubstitutions config_substitutions;
try {
+ PresetBundle::LoadConfigBundleAttributes lcba{ PresetBundle::LoadConfigBundleAttribute::SaveImported };
// Report all substitutions.
std::tie(config_substitutions, presets_imported) = wxGetApp().preset_bundle->load_configbundle(
- file.ToUTF8().data(), PresetBundle::LoadConfigBundleAttribute::SaveImported, ForwardCompatibilitySubstitutionRule::Enable);
+ file.ToUTF8().data(),
+ (from_prusa ? lcba | PresetBundle::LoadConfigBundleAttribute::ConvertFromPrusa : lcba),
+ ForwardCompatibilitySubstitutionRule::Enable);
} catch (const std::exception &ex) {
show_error(this, ex.what());
return;
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 167f86d72..2fab1c6db 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -192,11 +192,11 @@ public:
void repair_stl();
void export_config(bool to_prusa = false);
// Query user for the config file and open it.
- void load_config_file();
+ void load_config_file(bool from_prusa = false);
// Open a config file. Return true if loaded.
- bool load_config_file(const std::string &path);
+ bool load_config_file(const std::string &path, bool from_prusa = false);
void export_configbundle(bool export_physical_printers = false);
- void load_configbundle(wxString file = wxEmptyString);
+ void load_configbundle(wxString file = wxEmptyString, bool from_prusa = false);
void load_config(const DynamicPrintConfig& config);
// Select tab in m_tabpanel
// When tab == -1, will be selected last selected tab