mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 06:45:56 +08:00
Merge branch 'lm_ys_nx_console' (SPE-2028, SPE-2164)
This commit is contained in:
commit
de1e8b8953
@ -32,6 +32,9 @@
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/filesystem.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/dll/runtime_symbol_info.hpp>
|
||||
|
||||
#include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in
|
||||
@ -58,6 +61,8 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
#include "libslic3r/BlacklistedLibraryCheck.hpp"
|
||||
#include "libslic3r/ProfilesSharingUtils.hpp"
|
||||
#include "libslic3r/Utils/DirectoriesUtils.hpp"
|
||||
|
||||
#include "PrusaSlicer.hpp"
|
||||
|
||||
@ -168,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<ConfigOptionStrings>("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<int, int> opengl_version = { 0, 0 };
|
||||
@ -259,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);
|
||||
@ -280,6 +295,13 @@ 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);
|
||||
}
|
||||
|
||||
// If model for slicing is loaded from 3mf file, then its geometry has to be used and arrange couldn't be apply for this model.
|
||||
if ((boost::algorithm::iends_with(file, ".3mf") || boost::algorithm::iends_with(file, ".zip")) && !m_config.opt_bool("dont_arrange")) {
|
||||
//So, check a state of "dont_arrange" parameter and set it to true, if its value is false.
|
||||
m_config.set_key_value("dont_arrange", new ConfigOptionBool(true));
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
boost::nowide::cerr << file << ": " << e.what() << std::endl;
|
||||
@ -693,6 +715,8 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (processed_profiles_sharing())
|
||||
return 1;
|
||||
|
||||
if (start_gui) {
|
||||
#ifdef SLIC3R_GUI
|
||||
@ -815,6 +839,8 @@ bool CLI::setup(int argc, char **argv)
|
||||
m_actions.emplace_back(opt_key);
|
||||
else if (cli_transform_config_def.has(opt_key))
|
||||
m_transforms.emplace_back(opt_key);
|
||||
else if (cli_profiles_sharing_config_def.has(opt_key))
|
||||
m_profiles_sharing.emplace_back(opt_key);
|
||||
}
|
||||
|
||||
{
|
||||
@ -833,11 +859,17 @@ bool CLI::setup(int argc, char **argv)
|
||||
std::string validity = m_config.validate();
|
||||
|
||||
// Initialize with defaults.
|
||||
for (const t_optiondef_map *options : { &cli_actions_config_def.options, &cli_transform_config_def.options, &cli_misc_config_def.options })
|
||||
for (const t_optiondef_map *options : { &cli_actions_config_def.options
|
||||
, &cli_transform_config_def.options
|
||||
, &cli_profiles_sharing_config_def.options
|
||||
, &cli_misc_config_def.options })
|
||||
for (const t_optiondef_map::value_type &optdef : *options)
|
||||
m_config.option(optdef.first, true);
|
||||
|
||||
set_data_dir(m_config.opt_string("datadir"));
|
||||
if (std::string provided_datadir = m_config.opt_string("datadir"); provided_datadir.empty()) {
|
||||
set_data_dir(get_default_datadir());
|
||||
} else
|
||||
set_data_dir(provided_datadir);
|
||||
|
||||
//FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
|
||||
if (!validity.empty()) {
|
||||
@ -863,6 +895,7 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn
|
||||
<< std::endl
|
||||
<< "Actions:" << std::endl;
|
||||
cli_actions_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
cli_profiles_sharing_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
boost::nowide::cout
|
||||
<< std::endl
|
||||
@ -874,6 +907,11 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn
|
||||
<< "Other options:" << std::endl;
|
||||
cli_misc_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
//boost::nowide::cout
|
||||
// << std::endl
|
||||
// << "Profiles sharing options:" << std::endl;
|
||||
// cli_profiles_sharing_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
boost::nowide::cout
|
||||
<< std::endl
|
||||
<< "Print options are processed in the following order:" << std::endl
|
||||
@ -939,6 +977,121 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co
|
||||
return proposed_path.string();
|
||||
}
|
||||
|
||||
std::set<std::string> query_options = {
|
||||
"printer-profile"
|
||||
};
|
||||
|
||||
bool CLI::processed_profiles_sharing()
|
||||
{
|
||||
if (m_profiles_sharing.empty()) {
|
||||
#if 0 // fsFIXME !!! just for the test
|
||||
Slic3r::DynamicPrintConfig config = {};
|
||||
bool was_loaded = Slic3r::load_full_print_config("0.20mm QUALITY @MINI", "Prusament PLA", "Original Prusa MINI & MINI+", config);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
for (auto const& opt_key : m_profiles_sharing) {
|
||||
if (query_options.find(opt_key) != query_options.end())
|
||||
continue;
|
||||
if (opt_key == "query-printer-models") {
|
||||
ret = Slic3r::get_json_printer_models(get_printer_technology(m_config));
|
||||
}
|
||||
/*
|
||||
else if (opt_key == "query-printer-profiles") {
|
||||
if (!m_config.has("printer_model") || !m_config.has("printer_variant")) {
|
||||
boost::nowide::cerr << "error in '" << opt_key << "' : this action requires set 'printer-model' and 'printer-variant' options" << std::endl;
|
||||
break;
|
||||
}
|
||||
ret = Slic3r::get_json_printer_profiles(m_config.opt_string("printer_model"), m_config.opt_string("printer_variant"));
|
||||
|
||||
if (ret.empty())
|
||||
boost::nowide::cerr << "Printer_model '" << m_config.opt_string("printer_model") <<
|
||||
"' with printer_variant '" << m_config.opt_string("printer_variant") <<
|
||||
"' wasn't found among installed printers." << std::endl <<
|
||||
"Or the request can be wrong." << std::endl;
|
||||
}
|
||||
*/
|
||||
else if (opt_key == "query-print-filament-profiles") {
|
||||
if (!m_config.has("printer-profile")) {
|
||||
boost::nowide::cerr << "error: this action requires set printer-preset option" << opt_key << std::endl;
|
||||
break;
|
||||
}
|
||||
ret = Slic3r::get_json_print_filament_profiles(m_config.opt_string("printer-profile"));
|
||||
|
||||
if (ret.empty())
|
||||
boost::nowide::cerr << "Printer profile '" << m_config.opt_string("printer-profile") <<
|
||||
"' wasn't found among installed printers." << std::endl <<
|
||||
"Or the request can be wrong." << std::endl;
|
||||
}
|
||||
else {
|
||||
boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// use --output when available
|
||||
|
||||
std::string cmdline_param = m_config.opt_string("output");
|
||||
if (cmdline_param.empty()) {
|
||||
if (ret.empty())
|
||||
boost::nowide::cerr << "Wrong request" << std::endl;
|
||||
else
|
||||
printf("%s", ret.c_str());
|
||||
}
|
||||
else {
|
||||
// if we were supplied a directory, use it and append our automatically generated filename
|
||||
boost::filesystem::path cmdline_path(cmdline_param);
|
||||
boost::filesystem::path proposed_path = boost::filesystem::path(Slic3r::resources_dir()) / "out.json";
|
||||
if (boost::filesystem::is_directory(cmdline_path))
|
||||
proposed_path = (cmdline_path / proposed_path.filename());
|
||||
else if (cmdline_path.extension().empty())
|
||||
proposed_path = cmdline_path.replace_extension("json");
|
||||
else
|
||||
proposed_path = cmdline_path;
|
||||
const std::string file = proposed_path.string();
|
||||
|
||||
boost::nowide::ofstream c;
|
||||
c.open(file, std::ios::out | std::ios::trunc);
|
||||
c << ret << std::endl;
|
||||
c.close();
|
||||
|
||||
boost::nowide::cout << "Output for your request is written into " << file << std::endl;
|
||||
}
|
||||
|
||||
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<ConfigOptionStrings>("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
|
||||
|
@ -28,6 +28,7 @@ private:
|
||||
std::vector<std::string> m_input_files;
|
||||
std::vector<std::string> m_actions;
|
||||
std::vector<std::string> m_transforms;
|
||||
std::vector<std::string> m_profiles_sharing;
|
||||
std::vector<Model> m_models;
|
||||
|
||||
bool setup(int argc, char **argv);
|
||||
@ -39,6 +40,10 @@ private:
|
||||
bool export_models(IO::ExportFormat format);
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -508,8 +508,20 @@ set(SLIC3R_SOURCES
|
||||
Arachne/WallToolPaths.hpp
|
||||
Arachne/WallToolPaths.cpp
|
||||
StaticMap.hpp
|
||||
ProfilesSharingUtils.hpp
|
||||
ProfilesSharingUtils.cpp
|
||||
Utils/DirectoriesUtils.hpp
|
||||
Utils/DirectoriesUtils.cpp
|
||||
Utils/JsonUtils.hpp
|
||||
Utils/JsonUtils.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
list(APPEND SLIC3R_SOURCES
|
||||
MacUtils.mm
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_library(libslic3r STATIC ${SLIC3R_SOURCES})
|
||||
|
||||
if (WIN32)
|
||||
|
14
src/libslic3r/MacUtils.mm
Normal file
14
src/libslic3r/MacUtils.mm
Normal file
@ -0,0 +1,14 @@
|
||||
#import "Utils/DirectoriesUtils.hpp"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Utils/DirectoriesUtils.hpp
|
||||
std::string GetDataDir()
|
||||
{
|
||||
NSURL* url = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
|
||||
inDomain:NSUserDomainMask
|
||||
appropriateForURL:nil create:NO error:nil];
|
||||
|
||||
return std::string([(CFStringRef)url.path UTF8String]);
|
||||
}
|
||||
|
@ -2191,7 +2191,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Printer type");
|
||||
def->tooltip = L("Type of the printer.");
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
// def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
def = this->add("printer_notes", coString);
|
||||
def->label = L("Printer notes");
|
||||
@ -2212,7 +2212,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Printer variant");
|
||||
def->tooltip = L("Name of the printer variant. For example, the printer variants may be differentiated by a nozzle diameter.");
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
// def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
def = this->add("print_settings_id", coString);
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
@ -5119,17 +5119,67 @@ 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()
|
||||
{
|
||||
ConfigOptionDef* def;
|
||||
|
||||
// Information from this def will be used just for console output.
|
||||
// So, don't use L marker to label and tooltips values to avoid extract those phrases to translation.
|
||||
|
||||
def = this->add("query-printer-models", coBool);
|
||||
def->label = ("Get list of printer models");
|
||||
def->tooltip = ("Get list of installed printer models into JSON.\n"
|
||||
"Note:\n"
|
||||
"To print printer models for required technology use 'printer-technology' option with value FFF or SLA. By default printer_technology is FFF.\n"
|
||||
"To print out JSON into file use 'output' option.\n"
|
||||
"To specify configuration folder use 'datadir' option.");
|
||||
|
||||
/*
|
||||
def = this->add("query-printer-profiles", coBool);
|
||||
def->label = ("Get list of printer profiles for the selected printer model and printer variant");
|
||||
def->tooltip = ("Get list of printer profiles for the selected 'printer-model' and 'printer-variant' into JSON.\n"
|
||||
"Note:\n"
|
||||
"To print out JSON into file use 'output' option.\n"
|
||||
"To specify configuration folder use 'datadir' option.");
|
||||
*/
|
||||
|
||||
def = this->add("query-print-filament-profiles", coBool);
|
||||
def->label = ("Get list of print profiles and filament profiles for the selected printer profile");
|
||||
def->tooltip = ("Get list of print profiles and filament profiles for the selected 'printer-profile' into JSON.\n"
|
||||
"Note:\n"
|
||||
"To print out JSON into file use 'output' option.\n"
|
||||
"To specify configuration folder use 'datadir' option.");
|
||||
}
|
||||
|
||||
const CLIActionsConfigDef cli_actions_config_def;
|
||||
const CLITransformConfigDef cli_transform_config_def;
|
||||
const CLIMiscConfigDef cli_misc_config_def;
|
||||
const CLIProfilesSharingConfigDef cli_profiles_sharing_config_def;
|
||||
|
||||
DynamicPrintAndCLIConfig::PrintAndCLIConfigDef DynamicPrintAndCLIConfig::s_def;
|
||||
|
||||
void DynamicPrintAndCLIConfig::handle_legacy(t_config_option_key &opt_key, std::string &value) const
|
||||
{
|
||||
if (cli_actions_config_def .options.find(opt_key) == cli_actions_config_def .options.end() &&
|
||||
cli_profiles_sharing_config_def.options.find(opt_key) == cli_profiles_sharing_config_def.options.end() &&
|
||||
cli_transform_config_def.options.find(opt_key) == cli_transform_config_def.options.end() &&
|
||||
cli_misc_config_def .options.find(opt_key) == cli_misc_config_def .options.end()) {
|
||||
PrintConfigDef::handle_legacy(opt_key, value);
|
||||
|
@ -1211,6 +1211,12 @@ public:
|
||||
CLIMiscConfigDef();
|
||||
};
|
||||
|
||||
class CLIProfilesSharingConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
CLIProfilesSharingConfigDef();
|
||||
};
|
||||
|
||||
typedef std::string t_custom_gcode_key;
|
||||
// This map containes list of specific placeholders for each custom G-code, if any exist
|
||||
const std::map<t_custom_gcode_key, t_config_option_keys>& custom_gcode_specific_placeholders();
|
||||
@ -1282,6 +1288,9 @@ extern const CLITransformConfigDef cli_transform_config_def;
|
||||
// This class defines all command line options that are not actions or transforms.
|
||||
extern const CLIMiscConfigDef cli_misc_config_def;
|
||||
|
||||
// This class defines the command line options representing profiles sharing commands.
|
||||
extern const CLIProfilesSharingConfigDef cli_profiles_sharing_config_def;
|
||||
|
||||
class DynamicPrintAndCLIConfig : public DynamicPrintConfig
|
||||
{
|
||||
public:
|
||||
@ -1306,6 +1315,7 @@ private:
|
||||
this->options.insert(cli_actions_config_def.options.begin(), cli_actions_config_def.options.end());
|
||||
this->options.insert(cli_transform_config_def.options.begin(), cli_transform_config_def.options.end());
|
||||
this->options.insert(cli_misc_config_def.options.begin(), cli_misc_config_def.options.end());
|
||||
this->options.insert(cli_profiles_sharing_config_def.options.begin(), cli_profiles_sharing_config_def.options.end());
|
||||
for (const auto &kvp : this->options)
|
||||
this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second;
|
||||
}
|
||||
|
559
src/libslic3r/ProfilesSharingUtils.cpp
Normal file
559
src/libslic3r/ProfilesSharingUtils.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
///|/ Copyright (c) Prusa Research 2021 - 2023 Oleksandra Iushchenko @YuSanka
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "ProfilesSharingUtils.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "format.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "Utils/DirectoriesUtils.hpp"
|
||||
#include "Utils/JsonUtils.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static bool load_preset_bundle_from_datadir(PresetBundle& preset_bundle)
|
||||
{
|
||||
AppConfig app_config = AppConfig(AppConfig::EAppMode::Editor);
|
||||
if (!app_config.exists()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Configuration wasn't found. Check your 'datadir' value.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::string error = app_config.load(); !error.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << Slic3r::format("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||
"Try to manually delete the file to recover from the error. Your user profiles will not be affected."
|
||||
"\n%1%\n%2%", app_config.config_path(), error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
|
||||
// supplied as argument to --datadir; in that case we should still run the wizard
|
||||
preset_bundle.setup_directories();
|
||||
|
||||
std::string delayed_error_load_presets;
|
||||
// Suppress the '- default -' presets.
|
||||
preset_bundle.set_default_suppressed(app_config.get_bool("no_defaults"));
|
||||
try {
|
||||
auto preset_substitutions = preset_bundle.load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent);
|
||||
if (!preset_substitutions.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Some substitutions are found during loading presets.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Post-process vendor map to delete non-installed models/varians
|
||||
|
||||
VendorMap& vendors = preset_bundle.vendors;
|
||||
for (auto& [vendor_id, vendor_profile] : vendors) {
|
||||
std::vector<VendorProfile::PrinterModel> models;
|
||||
|
||||
for (auto& printer_model : vendor_profile.models) {
|
||||
std::vector<VendorProfile::PrinterVariant> variants;
|
||||
|
||||
for (const auto& variant : printer_model.variants) {
|
||||
// check if printer model with variant is intalled
|
||||
if (app_config.get_variant(vendor_id, printer_model.id, variant.name))
|
||||
variants.push_back(variant);
|
||||
}
|
||||
|
||||
if (!variants.empty()) {
|
||||
if (printer_model.variants.size() != variants.size())
|
||||
printer_model.variants = variants;
|
||||
models.push_back(printer_model);
|
||||
}
|
||||
}
|
||||
|
||||
if (!models.empty()) {
|
||||
if (vendor_profile.models.size() != models.size())
|
||||
vendor_profile.models = models;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
BOOST_LOG_TRIVIAL(error) << ex.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
/*
|
||||
struct PrinterAttr_
|
||||
{
|
||||
std::string model_name;
|
||||
std::string variant;
|
||||
};
|
||||
|
||||
static std::string get_printer_profiles(const VendorProfile* vendor_profile,
|
||||
const PresetBundle* preset_bundle,
|
||||
const PrinterAttr_& printer_attr)
|
||||
{
|
||||
for (const auto& printer_model : vendor_profile->models) {
|
||||
if (printer_model.name != printer_attr.model_name)
|
||||
continue;
|
||||
|
||||
for (const auto& variant : printer_model.variants)
|
||||
if (variant.name == printer_attr.variant)
|
||||
{
|
||||
pt::ptree data_node;
|
||||
data_node.put("printer_model", printer_model.name);
|
||||
data_node.put("printer_variant", printer_attr.variant);
|
||||
|
||||
pt::ptree printer_profiles_node;
|
||||
for (const Preset& printer_preset : preset_bundle->printers) {
|
||||
if (printer_preset.vendor->id == vendor_profile->id &&
|
||||
printer_preset.is_visible && // ???
|
||||
printer_preset.config.opt_string("printer_model") == printer_model.id &&
|
||||
printer_preset.config.opt_string("printer_variant") == printer_attr.variant) {
|
||||
pt::ptree profile_node;
|
||||
profile_node.put("", printer_preset.name);
|
||||
printer_profiles_node.push_back(std::make_pair("", profile_node));
|
||||
}
|
||||
}
|
||||
data_node.add_child("printer_profiles", printer_profiles_node);
|
||||
|
||||
// Serialize the tree into JSON and return it.
|
||||
return write_json_with_post_process(data_node);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string get_json_printer_profiles(const std::string& printer_model_name, const std::string& printer_variant)
|
||||
{
|
||||
if (!is_datadir())
|
||||
return "";
|
||||
|
||||
PrinterAttr_ printer_attr({printer_model_name, printer_variant});
|
||||
|
||||
PresetBundle preset_bundle;
|
||||
if (!load_preset_bundle_from_datadir(preset_bundle))
|
||||
return "";
|
||||
|
||||
const VendorMap& vendors = preset_bundle.vendors;
|
||||
for (const auto& [vendor_id, vendor] : vendors) {
|
||||
std::string out = get_printer_profiles(&vendor, &preset_bundle, printer_attr);
|
||||
if (!out.empty())
|
||||
return out;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
*/
|
||||
|
||||
struct PrinterAttr
|
||||
{
|
||||
std::string vendor_id;
|
||||
std::string model_id;
|
||||
std::string variant_name;
|
||||
};
|
||||
|
||||
static bool is_compatible_preset(const Preset& printer_preset, const PrinterAttr& attr)
|
||||
{
|
||||
return printer_preset.vendor->id == attr.vendor_id &&
|
||||
printer_preset.config.opt_string("printer_model") == attr.model_id &&
|
||||
printer_preset.config.opt_string("printer_variant") == attr.variant_name;
|
||||
}
|
||||
|
||||
static void add_profile_node(pt::ptree& printer_profiles_node, const std::string& preset_name, const int extruders_cnt)
|
||||
{
|
||||
pt::ptree profile_node;
|
||||
|
||||
profile_node.put("name", preset_name);
|
||||
if (extruders_cnt > 0)
|
||||
profile_node.put("extruders_cnt", extruders_cnt);
|
||||
|
||||
printer_profiles_node.push_back(std::make_pair("", profile_node));
|
||||
}
|
||||
|
||||
static void get_printer_profiles_node(pt::ptree& printer_profiles_node,
|
||||
pt::ptree& user_printer_profiles_node,
|
||||
const PrinterPresetCollection& printer_presets,
|
||||
const PrinterAttr& attr)
|
||||
{
|
||||
printer_profiles_node.clear();
|
||||
user_printer_profiles_node.clear();
|
||||
|
||||
for (const Preset& printer_preset : printer_presets) {
|
||||
if (!printer_preset.is_visible)
|
||||
continue;
|
||||
int extruders_cnt = printer_preset.printer_technology() == ptSLA ? 0 :
|
||||
printer_preset.config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
|
||||
if (printer_preset.is_user()) {
|
||||
const Preset* parent_preset = printer_presets.get_preset_parent(printer_preset);
|
||||
if (parent_preset && is_compatible_preset(*parent_preset, attr))
|
||||
add_profile_node(user_printer_profiles_node, printer_preset.name, extruders_cnt);
|
||||
}
|
||||
else if (is_compatible_preset(printer_preset, attr))
|
||||
add_profile_node(printer_profiles_node, printer_preset.name, extruders_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_printer_models(pt::ptree& vendor_node,
|
||||
const VendorProfile* vendor_profile,
|
||||
PrinterTechnology printer_technology,
|
||||
const PrinterPresetCollection& printer_presets)
|
||||
{
|
||||
for (const auto& printer_model : vendor_profile->models) {
|
||||
if (printer_technology != ptUnknown && printer_model.technology != printer_technology)
|
||||
continue;
|
||||
|
||||
pt::ptree variants_node;
|
||||
pt::ptree printer_profiles_node;
|
||||
pt::ptree user_printer_profiles_node;
|
||||
|
||||
if (printer_model.technology == ptSLA) {
|
||||
PrinterAttr attr({ vendor_profile->id, printer_model.id, "default" });
|
||||
|
||||
get_printer_profiles_node(printer_profiles_node, user_printer_profiles_node, printer_presets, attr);
|
||||
if (printer_profiles_node.empty() && user_printer_profiles_node.empty())
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
for (const auto& variant : printer_model.variants) {
|
||||
|
||||
PrinterAttr attr({ vendor_profile->id, printer_model.id, variant.name });
|
||||
|
||||
get_printer_profiles_node(printer_profiles_node, user_printer_profiles_node, printer_presets, attr);
|
||||
if (printer_profiles_node.empty() && user_printer_profiles_node.empty())
|
||||
continue;
|
||||
|
||||
pt::ptree variant_node;
|
||||
variant_node.put("name", variant.name);
|
||||
variant_node.add_child("printer_profiles", printer_profiles_node);
|
||||
if (!user_printer_profiles_node.empty())
|
||||
variant_node.add_child("user_printer_profiles", user_printer_profiles_node);
|
||||
|
||||
variants_node.push_back(std::make_pair("", variant_node));
|
||||
}
|
||||
|
||||
if (variants_node.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
pt::ptree data_node;
|
||||
data_node.put("id", printer_model.id);
|
||||
data_node.put("name", printer_model.name);
|
||||
data_node.put("technology", printer_model.technology == ptFFF ? "FFF" : "SLA");
|
||||
|
||||
if (!variants_node.empty())
|
||||
data_node.add_child("variants", variants_node);
|
||||
else {
|
||||
data_node.add_child("printer_profiles", printer_profiles_node);
|
||||
if (!user_printer_profiles_node.empty())
|
||||
data_node.add_child("user_printer_profiles", user_printer_profiles_node);
|
||||
}
|
||||
|
||||
data_node.put("vendor_name", vendor_profile->name);
|
||||
data_node.put("vendor_id", vendor_profile->id);
|
||||
|
||||
vendor_node.push_back(std::make_pair("", data_node));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_undef_printer_models(pt::ptree& vendor_node,
|
||||
PrinterTechnology printer_technology,
|
||||
const PrinterPresetCollection& printer_presets)
|
||||
{
|
||||
for (auto pt : { ptFFF, ptSLA }) {
|
||||
if (printer_technology != ptUnknown && printer_technology != pt)
|
||||
continue;
|
||||
|
||||
pt::ptree printer_profiles_node;
|
||||
for (const Preset& preset : printer_presets) {
|
||||
if (!preset.is_visible || preset.printer_technology() != pt ||
|
||||
preset.vendor || printer_presets.get_preset_parent(preset))
|
||||
continue;
|
||||
|
||||
int extruders_cnt = preset.printer_technology() == ptSLA ? 0 :
|
||||
preset.config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
add_profile_node(printer_profiles_node, preset.name, extruders_cnt);
|
||||
}
|
||||
|
||||
if (!printer_profiles_node.empty()) {
|
||||
pt::ptree data_node;
|
||||
data_node.put("id", "");
|
||||
data_node.put("technology", pt == ptFFF ? "FFF" : "SLA");
|
||||
data_node.add_child("printer_profiles", printer_profiles_node);
|
||||
data_node.put("vendor_name", "");
|
||||
data_node.put("vendor_id", "");
|
||||
|
||||
vendor_node.push_back(std::make_pair("", data_node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_json_printer_models(PrinterTechnology printer_technology)
|
||||
{
|
||||
PresetBundle preset_bundle;
|
||||
if (!load_preset_bundle_from_datadir(preset_bundle))
|
||||
return "";
|
||||
|
||||
pt::ptree vendor_node;
|
||||
|
||||
const VendorMap& vendors_map = preset_bundle.vendors;
|
||||
for (const auto& [vendor_id, vendor] : vendors_map)
|
||||
add_printer_models(vendor_node, &vendor, printer_technology, preset_bundle.printers);
|
||||
|
||||
// add printers with no vendor information
|
||||
add_undef_printer_models(vendor_node, printer_technology, preset_bundle.printers);
|
||||
|
||||
pt::ptree root;
|
||||
root.add_child("printer_models", vendor_node);
|
||||
|
||||
// Serialize the tree into JSON and return it.
|
||||
return write_json_with_post_process(root);
|
||||
}
|
||||
|
||||
static std::string get_installed_print_and_filament_profiles(const PresetBundle* preset_bundle, const Preset* printer_preset)
|
||||
{
|
||||
PrinterTechnology printer_technology = printer_preset->printer_technology();
|
||||
|
||||
pt::ptree print_profiles;
|
||||
pt::ptree user_print_profiles;
|
||||
|
||||
const PresetWithVendorProfile printer_preset_with_vendor_profile = preset_bundle->printers.get_preset_with_vendor_profile(*printer_preset);
|
||||
|
||||
const PresetCollection& print_presets = printer_technology == ptFFF ? preset_bundle->prints : preset_bundle->sla_prints;
|
||||
const PresetCollection& material_presets = printer_technology == ptFFF ? preset_bundle->filaments : preset_bundle->sla_materials;
|
||||
const std::string material_node_name = printer_technology == ptFFF ? "filament_profiles" : "sla_material_profiles";
|
||||
|
||||
for (auto print_preset : print_presets) {
|
||||
|
||||
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))
|
||||
{
|
||||
pt::ptree materials_profile_node;
|
||||
pt::ptree user_materials_profile_node;
|
||||
|
||||
for (auto material_preset : material_presets) {
|
||||
|
||||
// ?! check visible and no-template presets only
|
||||
if (!material_preset.is_visible || (material_preset.vendor && material_preset.vendor->templates_profile))
|
||||
continue;
|
||||
|
||||
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) &&
|
||||
is_compatible_with_print(material_preset_with_vendor_profile, print_preset_with_vendor_profile, printer_preset_with_vendor_profile)) {
|
||||
pt::ptree material_node;
|
||||
material_node.put("", material_preset.name);
|
||||
if (material_preset.is_user())
|
||||
user_materials_profile_node.push_back(std::make_pair("", material_node));
|
||||
else
|
||||
materials_profile_node.push_back(std::make_pair("", material_node));
|
||||
}
|
||||
}
|
||||
|
||||
pt::ptree print_profile_node;
|
||||
print_profile_node.put("name", print_preset.name);
|
||||
print_profile_node.add_child(material_node_name, materials_profile_node);
|
||||
if (!user_materials_profile_node.empty())
|
||||
print_profile_node.add_child("user_" + material_node_name, user_materials_profile_node);
|
||||
|
||||
if (print_preset.is_user())
|
||||
user_print_profiles.push_back(std::make_pair("", print_profile_node));
|
||||
else
|
||||
print_profiles.push_back(std::make_pair("", print_profile_node));
|
||||
}
|
||||
}
|
||||
|
||||
if (print_profiles.empty() && user_print_profiles.empty())
|
||||
return "";
|
||||
|
||||
pt::ptree tree;
|
||||
tree.put("printer_profile", printer_preset->name);
|
||||
tree.add_child("print_profiles", print_profiles);
|
||||
if (!user_print_profiles.empty())
|
||||
tree.add_child("user_print_profiles", user_print_profiles);
|
||||
|
||||
// Serialize the tree into JSON and return it.
|
||||
return write_json_with_post_process(tree);
|
||||
}
|
||||
|
||||
std::string get_json_print_filament_profiles(const std::string& printer_profile)
|
||||
{
|
||||
PresetBundle preset_bundle;
|
||||
if (load_preset_bundle_from_datadir(preset_bundle)) {
|
||||
const Preset* preset = preset_bundle.printers.find_preset(printer_profile, false, false);
|
||||
if (preset)
|
||||
return get_installed_print_and_filament_profiles(&preset_bundle, preset);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// Helper function for FS
|
||||
bool load_full_print_config(const std::string& print_preset_name, const std::string& filament_preset_name, const std::string& printer_preset_name, DynamicPrintConfig& config)
|
||||
{
|
||||
PresetBundle preset_bundle;
|
||||
if (!load_preset_bundle_from_datadir(preset_bundle)){
|
||||
BOOST_LOG_TRIVIAL(error) << Slic3r::format("Failed to load data from the datadir '%1%'.", data_dir());
|
||||
return false;
|
||||
}
|
||||
|
||||
config = {};
|
||||
config.apply(FullPrintConfig::defaults());
|
||||
|
||||
bool is_failed{ false };
|
||||
|
||||
if (const Preset* print_preset = preset_bundle.prints.find_preset(print_preset_name))
|
||||
config.apply_only(print_preset->config, print_preset->config.keys());
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Print profile '%1%' wasn't found.", print_preset_name);
|
||||
is_failed |= true;
|
||||
}
|
||||
|
||||
if (const Preset* filament_preset = preset_bundle.filaments.find_preset(filament_preset_name))
|
||||
config.apply_only(filament_preset->config, filament_preset->config.keys());
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Filament profile '%1%' wasn't found.", filament_preset_name);
|
||||
is_failed |= true;
|
||||
}
|
||||
|
||||
if (const Preset* printer_preset = preset_bundle.printers.find_preset(printer_preset_name))
|
||||
config.apply_only(printer_preset->config, printer_preset->config.keys());
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Printer profile '%1%' wasn't found.", printer_preset_name);
|
||||
is_failed |= true;
|
||||
}
|
||||
|
||||
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<std::string>& 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<std::string> 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<const ConfigOptionFloats*>(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
|
28
src/libslic3r/ProfilesSharingUtils.hpp
Normal file
28
src/libslic3r/ProfilesSharingUtils.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
///|/ Copyright (c) Prusa Research 2021 Oleksandra Iushchenko @YuSanka
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#ifndef slic3r_ProfilesSharingUtils_hpp_
|
||||
#define slic3r_ProfilesSharingUtils_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
std::string get_json_printer_models(PrinterTechnology printer_technology);
|
||||
//std::string get_json_printer_profiles(const std::string& printer_model, const std::string& printer_variant);
|
||||
std::string get_json_print_filament_profiles(const std::string& printer_profile);
|
||||
|
||||
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<std::string>& material_preset_names,
|
||||
const std::string& printer_preset_name,
|
||||
DynamicPrintConfig& config,
|
||||
PrinterTechnology printer_technology);
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_ProfilesSharingUtils_hpp_
|
94
src/libslic3r/Utils/DirectoriesUtils.cpp
Normal file
94
src/libslic3r/Utils/DirectoriesUtils.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "DirectoriesUtils.hpp"
|
||||
#include "../libslic3r.h"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
static std::string GetDataDir()
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
std::wstring buffer;
|
||||
buffer.resize(MAX_PATH);
|
||||
|
||||
hr = ::SHGetFolderPathW
|
||||
(
|
||||
NULL, // parent window, not used
|
||||
CSIDL_APPDATA,
|
||||
NULL, // access token (current user)
|
||||
SHGFP_TYPE_CURRENT, // current path, not just default value
|
||||
(LPWSTR)buffer.data()
|
||||
);
|
||||
|
||||
if (hr == E_FAIL)
|
||||
{
|
||||
// directory doesn't exist, maybe we can get its default value?
|
||||
hr = ::SHGetFolderPathW
|
||||
(
|
||||
NULL,
|
||||
CSIDL_APPDATA,
|
||||
NULL,
|
||||
SHGFP_TYPE_DEFAULT,
|
||||
(LPWSTR)buffer.data()
|
||||
);
|
||||
}
|
||||
|
||||
for (int i=0; i< MAX_PATH; i++)
|
||||
if (buffer.data()[i] == '\0') {
|
||||
buffer.resize(i);
|
||||
break;
|
||||
}
|
||||
|
||||
return boost::nowide::narrow(buffer);
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
|
||||
static std::string GetDataDir()
|
||||
{
|
||||
std::string dir;
|
||||
|
||||
char* ptr;
|
||||
if ((ptr = getenv("XDG_CONFIG_HOME")))
|
||||
dir = std::string(ptr);
|
||||
else {
|
||||
if ((ptr = getenv("HOME")))
|
||||
dir = std::string(ptr);
|
||||
else {
|
||||
struct passwd* who = (struct passwd*)NULL;
|
||||
if ((ptr = getenv("USER")) || (ptr = getenv("LOGNAME")))
|
||||
who = getpwnam(ptr);
|
||||
// make sure the user exists!
|
||||
if (!who)
|
||||
who = getpwuid(getuid());
|
||||
|
||||
dir = std::string(who ? who->pw_dir : 0);
|
||||
}
|
||||
if (! dir.empty())
|
||||
dir += "/.config";
|
||||
}
|
||||
|
||||
if (dir.empty())
|
||||
BOOST_LOG_TRIVIAL(error) << "GetDataDir() > unsupported file layout";
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
std::string get_default_datadir()
|
||||
{
|
||||
const std::string config_dir = GetDataDir();
|
||||
const std::string data_dir = (boost::filesystem::path(config_dir) / SLIC3R_APP_FULL_NAME).make_preferred().string();
|
||||
return data_dir;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
17
src/libslic3r/Utils/DirectoriesUtils.hpp
Normal file
17
src/libslic3r/Utils/DirectoriesUtils.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef slic3r_DirectoriesUtils_hpp_
|
||||
#define slic3r_DirectoriesUtils_hpp_
|
||||
|
||||
#include <string>
|
||||
|
||||
#if __APPLE__
|
||||
//implemented at MacUtils.mm
|
||||
std::string GetDataDir();
|
||||
#endif //__APPLE__
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
std::string get_default_datadir();
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_DirectoriesUtils_hpp_
|
22
src/libslic3r/Utils/JsonUtils.cpp
Normal file
22
src/libslic3r/Utils/JsonUtils.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "JsonUtils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
std::string write_json_with_post_process(const pt::ptree& ptree)
|
||||
{
|
||||
std::stringstream oss;
|
||||
pt::write_json(oss, ptree);
|
||||
|
||||
// fix json-out to show node values as a string just for string nodes
|
||||
std::regex reg("\\\"([0-9]+\\.{0,1}[0-9]*)\\\""); // code is borrowed from https://stackoverflow.com/questions/2855741/why-does-boost-property-tree-write-json-save-everything-as-string-is-it-possibl
|
||||
std::string result = std::regex_replace(oss.str(), reg, "$1");
|
||||
|
||||
boost::replace_all(result, "\"true\"", "true");
|
||||
boost::replace_all(result, "\"false\"", "false");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
12
src/libslic3r/Utils/JsonUtils.hpp
Normal file
12
src/libslic3r/Utils/JsonUtils.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef slic3r_JsonUtils_hpp_
|
||||
#define slic3r_JsonUtils_hpp_
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
std::string write_json_with_post_process(const boost::property_tree::ptree& ptree);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_jsonUtils_hpp_
|
@ -15,6 +15,14 @@
|
||||
#define _libslic3r_h_
|
||||
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY
|
||||
#define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY "-alpha"
|
||||
//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY "-beta"
|
||||
|
||||
|
||||
|
||||
#define GCODEVIEWER_APP_NAME "PrusaSlicer G-code Viewer"
|
||||
#define GCODEVIEWER_APP_KEY "PrusaSlicerGcodeViewer"
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveFormatRegistry.hpp"
|
||||
#include "libslic3r/Utils/DirectoriesUtils.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
@ -412,20 +413,14 @@ bool static check_old_linux_datadir(const wxString& app_name) {
|
||||
// To be precise, the datadir should exist, it is created when single instance
|
||||
// lock happens. Instead of checking for existence, check the contents.
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
std::string new_path = Slic3r::data_dir();
|
||||
|
||||
wxString dir;
|
||||
if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() )
|
||||
dir = wxFileName::GetHomeDir() + wxS("/.config");
|
||||
std::string default_path = (dir + "/" + app_name).ToUTF8().data();
|
||||
|
||||
if (new_path != default_path) {
|
||||
// This happens when the user specifies a custom --datadir.
|
||||
// Do not show anything in that case.
|
||||
// If the config folder is redefined - do not check
|
||||
// This happens when the user specifies a custom --datadir.
|
||||
if (new_path != get_default_datadir())
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
fs::path data_dir = fs::path(new_path);
|
||||
if (! fs::is_directory(data_dir))
|
||||
@ -922,34 +917,7 @@ static boost::optional<Semver> parse_semver_from_ini(std::string path)
|
||||
|
||||
void GUI_App::init_app_config()
|
||||
{
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
|
||||
// SetAppName(SLIC3R_APP_KEY);
|
||||
SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
// SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
|
||||
|
||||
// SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
|
||||
// Set the Slic3r data directory at the Slic3r XS module.
|
||||
// Unix: ~/ .Slic3rP
|
||||
// Windows : "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
|
||||
// Mac : "~/Library/Application Support/Slic3r"
|
||||
|
||||
if (data_dir().empty()) {
|
||||
#ifndef __linux__
|
||||
set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data());
|
||||
#else
|
||||
// Since version 2.3, config dir on Linux is in ${XDG_CONFIG_HOME}.
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/2911
|
||||
wxString dir;
|
||||
if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() )
|
||||
dir = wxFileName::GetHomeDir() + wxS("/.config");
|
||||
set_data_dir((dir + "/" + GetAppName()).ToUTF8().data());
|
||||
#endif
|
||||
} else {
|
||||
m_datadir_redefined = true;
|
||||
}
|
||||
SetAppName(SLIC3R_APP_FULL_NAME);
|
||||
|
||||
if (!app_config)
|
||||
app_config = new AppConfig(is_editor() ? AppConfig::EAppMode::Editor : AppConfig::EAppMode::GCodeViewer);
|
||||
@ -981,7 +949,7 @@ std::string GUI_App::check_older_app_config(Semver current_version, bool backup)
|
||||
std::string older_data_dir_path;
|
||||
|
||||
// If the config folder is redefined - do not check
|
||||
if (m_datadir_redefined)
|
||||
if (data_dir() != get_default_datadir())
|
||||
return {};
|
||||
|
||||
// find other version app config (alpha / beta / release)
|
||||
|
@ -418,7 +418,6 @@ private:
|
||||
// inititate read of version file online in separate thread
|
||||
void app_version_check(bool from_user);
|
||||
|
||||
bool m_datadir_redefined { false };
|
||||
bool m_wifi_config_dialog_shown { false };
|
||||
};
|
||||
|
||||
|
@ -15,4 +15,5 @@ std::string get_downloads_path_mac()
|
||||
//[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"]];
|
||||
//return std::string();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user