diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 5a4ab0dc10..a57663fa35 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -173,6 +173,13 @@ int CLI::run(int argc, char **argv) m_print_config.apply(config); } + bool has_config_from_profiles = m_profiles_sharing.empty() && + (!m_config.opt_string("print-profile").empty() || + !m_config.option("material-profile")->values.empty() || + !m_config.opt_string("printer-profile").empty() ); + if (has_config_from_profiles && !check_and_load_input_profiles(printer_technology)) + return 1; + #ifdef SLIC3R_GUI #if ENABLE_GL_CORE_PROFILE std::pair opengl_version = { 0, 0 }; @@ -264,6 +271,9 @@ int CLI::run(int argc, char **argv) } Model model; try { + if (has_config_from_profiles) + model = Model::read_from_file(file, nullptr, nullptr, Model::LoadAttribute::AddDefaultInstances); + else { // When loading an AMF or 3MF, config is imported as well, including the printer technology. DynamicPrintConfig config; ConfigSubstitutionContext config_substitutions(config_substitution_rule); @@ -285,6 +295,7 @@ int CLI::run(int argc, char **argv) // config is applied to m_print_config before the current m_config values. config += std::move(m_print_config); m_print_config = std::move(config); + } } catch (std::exception& e) { boost::nowide::cerr << file << ": " << e.what() << std::endl; @@ -1048,6 +1059,33 @@ bool CLI::processed_profiles_sharing() return true; } +bool CLI::check_and_load_input_profiles(PrinterTechnology& printer_technology) +{ + Slic3r::DynamicPrintConfig config = {}; + std::string ret = Slic3r::load_full_print_config(m_config.opt_string("print-profile"), + m_config.option("material-profile")->values, + m_config.opt_string("printer-profile"), + config, printer_technology); + if (!ret.empty()) { + boost::nowide::cerr << ret << std::endl; + return false; + } + + config.normalize_fdm(); + + PrinterTechnology other_printer_technology = get_printer_technology(config); + if (printer_technology == ptUnknown) + printer_technology = other_printer_technology; + else if (printer_technology != other_printer_technology && other_printer_technology != ptUnknown) { + boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl; + return false; + } + + m_print_config.apply(config); + + return true; +} + // __has_feature() is used later for Clang, this is for compatibility with other compilers (such as GCC and MSVC) #ifndef __has_feature # define __has_feature(x) 0 diff --git a/src/PrusaSlicer.hpp b/src/PrusaSlicer.hpp index 8910f56980..b11e1b5d30 100644 --- a/src/PrusaSlicer.hpp +++ b/src/PrusaSlicer.hpp @@ -42,6 +42,8 @@ private: bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); } bool processed_profiles_sharing(); + + bool check_and_load_input_profiles(PrinterTechnology& printer_technology); std::string output_filepath(const Model &model, IO::ExportFormat format) const; }; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 413e01b5ab..391db4309e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5119,6 +5119,22 @@ CLIMiscConfigDef::CLIMiscConfigDef() def->tooltip = L("Render with a software renderer. The bundled MESA software renderer is loaded instead of the default OpenGL driver."); def->min = 0; #endif /* _MSC_VER */ + + def = this->add("printer-profile", coString); + def->label = ("Printer preset name"); + def->tooltip = ("Name of the printer preset used for slicing."); + def->set_default_value(new ConfigOptionString()); + + def = this->add("print-profile", coString); + def->label = ("Print preset name"); + def->tooltip = ("Name of the print preset used for slicing."); + def->set_default_value(new ConfigOptionString()); + + def = this->add("material-profile", coStrings); + def->label = ("Material preset name(s)"); + def->tooltip = ("Name(s) of the material preset(s) used for slicing.\n" + "Could be filaments or sla_material preset name(s) depending on printer tochnology"); + def->set_default_value(new ConfigOptionStrings()); } CLIProfilesSharingConfigDef::CLIProfilesSharingConfigDef() @@ -5151,11 +5167,6 @@ CLIProfilesSharingConfigDef::CLIProfilesSharingConfigDef() "Note:\n" "To print out JSON into file use 'output' option.\n" "To specify configuration folder use 'datadir' option."); - - def = this->add("printer-profile", coString); - def->label = ("Printer preset name"); - def->tooltip = ("Name of the printer preset used for slicing."); - def->set_default_value(new ConfigOptionString()); } const CLIActionsConfigDef cli_actions_config_def; diff --git a/src/libslic3r/ProfilesSharingUtils.cpp b/src/libslic3r/ProfilesSharingUtils.cpp index 79d46e1e1a..97564120f9 100644 --- a/src/libslic3r/ProfilesSharingUtils.cpp +++ b/src/libslic3r/ProfilesSharingUtils.cpp @@ -391,4 +391,133 @@ bool load_full_print_config(const std::string& print_preset_name, const std::str return !is_failed; } +// Helper function for load full config from installed presets by profile names +std::string load_full_print_config(const std::string& print_preset_name, + const std::vector& material_preset_names_in, + const std::string& printer_preset_name, + DynamicPrintConfig& config, + PrinterTechnology printer_technology) +{ + // check entered profile names + + if (print_preset_name.empty() || + material_preset_names_in.empty() || + printer_preset_name.empty()) + return "Request is not completed. All of Print/Material/Printer profiles have to be entered"; + + // check preset bundle + + PresetBundle preset_bundle; + if (!load_preset_bundle_from_datadir(preset_bundle)) + return Slic3r::format("Failed to load data from the datadir '%1%'.", data_dir()); + + // check existance of required profiles + + std::string errors; + + const Preset* printer_preset = preset_bundle.printers.find_preset(printer_preset_name); + if (!printer_preset) + errors += "\n" + Slic3r::format("Printer profile '%1%' wasn't found.", printer_preset_name); + else if (printer_technology == ptUnknown) + printer_technology = printer_preset->printer_technology(); + else if (printer_technology != printer_preset->printer_technology()) + errors += "\n" + std::string("Printer technology of the selected printer preset is differs with required printer technology"); + + PresetCollection& print_presets = printer_technology == ptFFF ? preset_bundle.prints : preset_bundle.sla_prints; + + const Preset* print_preset = print_presets.find_preset(print_preset_name); + if (!print_preset) + errors += "\n" + Slic3r::format("Print profile '%1%' wasn't found.", print_preset_name); + + PresetCollection& material_presets = printer_technology == ptFFF ? preset_bundle.filaments : preset_bundle.sla_materials; + + auto check_material = [&material_presets] (const std::string& name, std::string& errors) -> void { + const Preset* material_preset = material_presets.find_preset(name); + if (!material_preset) + errors += "\n" + Slic3r::format("Material profile '%1%' wasn't found.", name); + }; + + check_material(material_preset_names_in.front(), errors); + if (material_preset_names_in.size() > 1) { + for (int idx = 1; idx < material_preset_names_in.size(); idx++) { + if (material_preset_names_in[idx] != material_preset_names_in.front()) + check_material(material_preset_names_in[idx], errors); + } + } + + if (!errors.empty()) + return errors; + + // check and update list of material presets + + std::vector material_preset_names = material_preset_names_in; + + if (printer_technology == ptSLA && material_preset_names.size() > 1) { + BOOST_LOG_TRIVIAL(warning) << "Note: More than one sla material profiles were entered. Extras material profiles will be ignored."; + material_preset_names.resize(1); + } + + if (printer_technology == ptFFF) { + const int extruders_count = static_cast(printer_preset->config.option("nozzle_diameter"))->values.size(); + if (extruders_count > material_preset_names.size()) { + BOOST_LOG_TRIVIAL(warning) << "Note: Less than needed filament profiles were entered. Missed filament profiles will be filled with first material."; + material_preset_names.reserve(extruders_count); + for (int i = extruders_count - material_preset_names.size(); i > 0; i--) + material_preset_names.push_back(material_preset_names.front()); + } + else if (extruders_count < material_preset_names.size()) { + BOOST_LOG_TRIVIAL(warning) << "Note: More than needed filament profiles were entered. Extras filament profiles will be ignored."; + material_preset_names.resize(extruders_count); + } + } + + // check profiles compatibility + + const PresetWithVendorProfile printer_preset_with_vendor_profile = preset_bundle.printers.get_preset_with_vendor_profile(*printer_preset); + const PresetWithVendorProfile print_preset_with_vendor_profile = print_presets.get_preset_with_vendor_profile(*print_preset); + + if (!is_compatible_with_printer(print_preset_with_vendor_profile, printer_preset_with_vendor_profile)) + errors += "\n" + Slic3r::format("Print profile '%1%' is not compatible with printer profile %2%.", print_preset_name, printer_preset_name); + + auto check_material_preset_compatibility = [&material_presets, printer_preset_name, print_preset_name, printer_preset_with_vendor_profile, print_preset_with_vendor_profile] + (const std::string& name, std::string& errors) -> void { + const Preset* material_preset = material_presets.find_preset(name); + const PresetWithVendorProfile material_preset_with_vendor_profile = material_presets.get_preset_with_vendor_profile(*material_preset); + + if (!is_compatible_with_printer(material_preset_with_vendor_profile, printer_preset_with_vendor_profile)) + errors += "\n" + Slic3r::format("Material profile '%1%' is not compatible with printer profile %2%.", name, printer_preset_name); + + if (!is_compatible_with_print(material_preset_with_vendor_profile, print_preset_with_vendor_profile, printer_preset_with_vendor_profile)) + errors += "\n" + Slic3r::format("Material profile '%1%' is not compatible with print profile %2%.", name, print_preset_name); + }; + + check_material_preset_compatibility(material_preset_names.front(), errors); + if (material_preset_names.size() > 1) { + for (int idx = 1; idx < material_preset_names.size(); idx++) { + if (material_preset_names[idx] != material_preset_names.front()) + check_material_preset_compatibility(material_preset_names[idx], errors); + } + } + + if (!errors.empty()) + return errors; + + // get full print configuration + + preset_bundle.printers.select_preset_by_name(printer_preset_name, true); + print_presets.select_preset_by_name(print_preset_name, true); + if (printer_technology == ptSLA) + material_presets.select_preset_by_name(material_preset_names.front(), true); + else if (printer_technology == ptFFF) { + auto& extruders_filaments = preset_bundle.extruders_filaments; + extruders_filaments.clear(); + for (size_t i = 0; i < material_preset_names.size(); ++i) + extruders_filaments.emplace_back(ExtruderFilaments(&preset_bundle.filaments, i, material_preset_names[i])); + } + + config = preset_bundle.full_config(); + + return ""; +} + } // namespace Slic3r diff --git a/src/libslic3r/ProfilesSharingUtils.hpp b/src/libslic3r/ProfilesSharingUtils.hpp index 4ea1539dbd..5eafe899e3 100644 --- a/src/libslic3r/ProfilesSharingUtils.hpp +++ b/src/libslic3r/ProfilesSharingUtils.hpp @@ -19,6 +19,15 @@ std::string GetDataDir(); class DynamicPrintConfig; bool load_full_print_config(const std::string& print_preset, const std::string& filament_preset, const std::string& printer_preset, DynamicPrintConfig& out_config); +// Load full print config into config +// Return error/warning string if any exists +std::string load_full_print_config( const std::string& print_preset_name, + const std::vector& material_preset_names, + const std::string& printer_preset_name, + DynamicPrintConfig& config, + PrinterTechnology printer_technology); + + } // namespace Slic3r #endif // slic3r_ProfilesSharingUtils_hpp_