ENH: [STUDIO-4034] add functions for custom printer/filament
Change-Id: I0fc2738392970b19c0ae8263ea7d968cc8f23c2f JIRA: STUDIO-4034 (cherry picked from commit 30e5b3f61f2f5aae308d5e454f71d69939104ebb)
This commit is contained in:
parent
f4ffe8621b
commit
0db3fd9f81
|
@ -1427,7 +1427,7 @@ void PresetCollection::set_sync_info_and_save(std::string name, std::string sett
|
|||
else
|
||||
preset->sync_info = syncinfo;
|
||||
if (get_preset_base(*preset) == preset) {
|
||||
for (auto preset2 : m_presets)
|
||||
for (auto & preset2 : m_presets)
|
||||
if (preset2.inherits() == preset->name) {
|
||||
preset2.base_id = setting_id;
|
||||
preset2.save_info();
|
||||
|
@ -1436,7 +1436,7 @@ void PresetCollection::set_sync_info_and_save(std::string name, std::string sett
|
|||
preset->setting_id = setting_id;
|
||||
if (update_time > 0)
|
||||
preset->updated_time = update_time;
|
||||
preset->save_info();
|
||||
preset->sync_info == "update" ? preset->save(nullptr) : preset->save_info();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2065,6 +2065,84 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string
|
|||
return preset;
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::function<void(Preset &)> modifier)
|
||||
{
|
||||
std::vector<Preset> new_presets;
|
||||
for (auto curr_preset : presets) {
|
||||
new_presets.push_back(*curr_preset);
|
||||
auto &preset = new_presets.back();
|
||||
preset.vendor = nullptr;
|
||||
preset.renamed_from.clear();
|
||||
preset.setting_id.clear();
|
||||
preset.inherits().clear();
|
||||
preset.is_default = false;
|
||||
preset.is_system = false;
|
||||
preset.is_external = false;
|
||||
preset.is_visible = true;
|
||||
preset.is_project_embedded = false;
|
||||
modifier(preset);
|
||||
if (find_preset(preset.name)) {
|
||||
failures.push_back(preset.name);
|
||||
continue;
|
||||
}
|
||||
preset.file = this->path_for_preset(preset);
|
||||
preset.alias.clear();
|
||||
if (m_type == Preset::TYPE_PRINT)
|
||||
preset.config.option<ConfigOptionString>("print_settings_id", true)->value = preset.name;
|
||||
else if (m_type == Preset::TYPE_FILAMENT)
|
||||
preset.config.option<ConfigOptionStrings>("filament_settings_id", true)->values[0] = preset.name;
|
||||
else if (m_type == Preset::TYPE_PRINTER)
|
||||
preset.config.option<ConfigOptionString>("printer_settings_id", true)->value = preset.name;
|
||||
preset.updated_time = (long long) Slic3r::Utils::get_current_time_utc();
|
||||
}
|
||||
if (!failures.empty())
|
||||
return false;
|
||||
lock();
|
||||
for (auto preset : new_presets) {
|
||||
auto it = this->find_preset_internal(preset.name);
|
||||
assert(it == m_presets.end() || it->name != preset.name);
|
||||
Preset & new_preset = *m_presets.insert(it, preset);
|
||||
new_preset.save(nullptr);
|
||||
}
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets_for_printer(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::string const &printer)
|
||||
{
|
||||
return clone_presets(presets, failures, [printer](Preset &preset) {
|
||||
preset.name = preset.alias + " @ " + printer;
|
||||
auto *compatible_printers = dynamic_cast<ConfigOptionStrings*>(preset.config.option("compatible_printers"));
|
||||
compatible_printers->values = std::vector<std::string>{ printer };
|
||||
});
|
||||
}
|
||||
|
||||
bool PresetCollection::create_presets_from_template_for_printer(std::vector<std::string> const &templates, std::vector<std::string> &failures, std::string const &printer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets_for_filament(std::vector<Preset const *> const &presets,
|
||||
std::vector<std::string> & failures,
|
||||
std::string const & filament_name,
|
||||
std::string const & filament_id)
|
||||
{
|
||||
return clone_presets(presets, failures, [filament_name, filament_id](Preset &preset) {
|
||||
preset.name = filament_name + " " + preset.name.substr(preset.name.find_last_of('@'));
|
||||
preset.alias = filament_name;
|
||||
preset.filament_id = filament_id;
|
||||
});
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<Preset const *>> PresetCollection::get_filament_presets() const
|
||||
{
|
||||
std::map<std::string, std::vector<Preset const *>> filament_presets;
|
||||
for (auto &preset : m_presets) {
|
||||
if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); }
|
||||
}
|
||||
return filament_presets;
|
||||
}
|
||||
|
||||
//BBS: add project embedded preset logic
|
||||
void PresetCollection::save_current_preset(const std::string &new_name, bool detach, bool save_to_project, Preset* _curr_preset)
|
||||
{
|
||||
|
|
|
@ -449,6 +449,13 @@ public:
|
|||
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
|
||||
bool clone_presets(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::function<void(Preset &)> modifier);
|
||||
bool clone_presets_for_printer(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::string const &printer);
|
||||
bool create_presets_from_template_for_printer(std::vector<std::string> const &templates, std::vector<std::string> &failures, std::string const &printer);
|
||||
bool clone_presets_for_filament(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::string const &filament_name, std::string const &filament_id);
|
||||
|
||||
std::map<std::string, std::vector<Preset const *>> get_filament_presets() const;
|
||||
|
||||
// Returns a loaded preset, returns true if an existing preset was selected AND modified from config.
|
||||
// In that case the successive filament loaded for a multi material printer should not be modified, but
|
||||
// an external preset should be created instead.
|
||||
|
|
|
@ -1100,6 +1100,112 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_models_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%") % compatibility_rule;
|
||||
if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)
|
||||
// Loading system presets, don't log substitutions.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::EnableSilent;
|
||||
else if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem)
|
||||
// Loading system presets, throw on unknown option value.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
|
||||
// Here the vendor specific read only Config Bundles are stored.
|
||||
boost::filesystem::path dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
|
||||
std::string vendor_file = dir_entry.path().string();
|
||||
if (Slic3r::is_json_file(vendor_file)) {
|
||||
std::string vendor_name = dir_entry.path().filename().string();
|
||||
// Remove the .json suffix.
|
||||
vendor_name.erase(vendor_name.size() - 5);
|
||||
try {
|
||||
// Load the config bundle, flatten it.
|
||||
append(substitutions, load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadVendorOnly, compatibility_rule).first);
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" finished, errors_cummulative %1%") % errors_cummulative;
|
||||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_filaments_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%") % compatibility_rule;
|
||||
if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)
|
||||
// Loading system presets, don't log substitutions.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::EnableSilent;
|
||||
else if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem)
|
||||
// Loading system presets, throw on unknown option value.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
|
||||
// Here the vendor specific read only Config Bundles are stored.
|
||||
boost::filesystem::path dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
bool first = true;
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
|
||||
std::string vendor_file = dir_entry.path().string();
|
||||
if (Slic3r::is_json_file(vendor_file)) {
|
||||
std::string vendor_name = dir_entry.path().filename().string();
|
||||
// Remove the .json suffix.
|
||||
vendor_name.erase(vendor_name.size() - 5);
|
||||
try {
|
||||
if (first) {
|
||||
// Reset this PresetBundle and load the first vendor config.
|
||||
append(substitutions, this->load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
|
||||
first = false;
|
||||
} else {
|
||||
// Load the other vendor configs, merge them with this PresetBundle.
|
||||
// Report duplicate profiles.
|
||||
PresetBundle other;
|
||||
append(substitutions, other.load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
|
||||
std::vector<std::string> duplicates = this->merge_presets(std::move(other));
|
||||
if (!duplicates.empty()) {
|
||||
errors_cummulative += "Found duplicated settings in vendor " + vendor_name + "'s json file lists: ";
|
||||
for (size_t i = 0; i < duplicates.size(); ++i) {
|
||||
if (i > 0) errors_cummulative += ", ";
|
||||
errors_cummulative += duplicates[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" finished, errors_cummulative %1%") % errors_cummulative;
|
||||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
VendorProfile PresetBundle::get_custom_vendor_models() const
|
||||
{
|
||||
VendorProfile vendor;
|
||||
vendor.name = "Custom";
|
||||
vendor.id = "Custom";
|
||||
for (auto &preset : printers.get_presets()) {
|
||||
if (preset.is_system) continue;
|
||||
if (printers.get_preset_base(preset) != &preset) continue;
|
||||
auto model = preset.config.opt_string("printer_model");
|
||||
auto variant = preset.config.opt_string("printer_variant");
|
||||
auto iter_model = std::find_if(vendor.models.begin(), vendor.models.end(), [model](VendorProfile::PrinterModel &m) {
|
||||
return m.name == model;
|
||||
});
|
||||
if (iter_model == vendor.models.end()) {
|
||||
iter_model = vendor.models.emplace(vendor.models.end(), VendorProfile::PrinterModel{});
|
||||
iter_model->name = model;
|
||||
}
|
||||
iter_model->variants.push_back(variant);
|
||||
}
|
||||
return vendor;
|
||||
}
|
||||
|
||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||
std::vector<std::string> PresetBundle::merge_presets(PresetBundle &&other)
|
||||
|
@ -2742,7 +2848,6 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
||||
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string vendor_system_path = data_dir() + "/" + PRESET_SYSTEM_DIR;
|
||||
|
||||
//BBS: add config related logs
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, path %1%, compatibility_rule %2%")%path.c_str()%compatibility_rule;
|
||||
|
@ -2796,7 +2901,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
auto config_version = Semver::parse(version_str);
|
||||
if (! config_version) {
|
||||
throw ConfigurationError((boost::format("vendor %1%'s config version: %2% invalid\nSuggest cleaning the directory %3% firstly")
|
||||
% vendor_name % version_str %vendor_system_path).str());
|
||||
% vendor_name % version_str % path).str());
|
||||
} else {
|
||||
vendor_profile.config_version = std::move(*config_version);
|
||||
}
|
||||
|
@ -2834,10 +2939,16 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
catch(nlohmann::detail::parse_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<root_file<<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%: %2%\nSuggest cleaning the directory %3% firstly")
|
||||
%root_file %err.what() %vendor_system_path).str());
|
||||
%root_file %err.what() % path).str());
|
||||
//goto __error_process;
|
||||
}
|
||||
|
||||
if (flags.has(LoadConfigBundleAttribute::LoadFilamentOnly)) {
|
||||
machine_model_subfiles.clear();
|
||||
machine_subfiles.clear();
|
||||
process_subfiles.clear();
|
||||
}
|
||||
|
||||
//2) paste the machine model
|
||||
for (auto& machine_model : machine_model_subfiles)
|
||||
{
|
||||
|
@ -2916,7 +3027,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
catch(nlohmann::detail::parse_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<< subfile <<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%: %2%\nSuggest cleaning the directory %3% firstly")
|
||||
%subfile %err.what() %vendor_system_path).str());
|
||||
%subfile %err.what() % path).str());
|
||||
}
|
||||
|
||||
if (! model.id.empty() && ! model.variants.empty())
|
||||
|
@ -3132,7 +3243,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse process setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3147,7 +3258,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse filament setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3162,7 +3273,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse printer setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ public:
|
|||
// Load a system config bundle.
|
||||
LoadSystem,
|
||||
LoadVendorOnly,
|
||||
LoadFilamentOnly,
|
||||
};
|
||||
using LoadConfigBundleAttributes = enum_bitmask<LoadConfigBundleAttribute>;
|
||||
// Load the config bundle based on the flags.
|
||||
|
@ -209,6 +210,10 @@ public:
|
|||
//BBS: add project embedded preset logic
|
||||
void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector<std::string>& unselected_options, bool save_to_project = false);
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_models_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_filaments_json(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
VendorProfile get_custom_vendor_models() const;
|
||||
|
||||
//BBS: add BBL as default
|
||||
static const char *BBL_BUNDLE;
|
||||
static const char *BBL_DEFAULT_PRINTER_MODEL;
|
||||
|
|
Loading…
Reference in New Issue