WIP: Undo / Redo stack.
Integration of the "cereal" serialization library. Serialization / deserialization of the DynamicConfig / DynamicPrintConfig. DynamicPrintConfig serializes ordinal identifiers instead of the option key strings to conserve space.
This commit is contained in:
parent
27cc66eb54
commit
a710e7e7e4
@ -344,6 +344,10 @@ if (NOT GLEW_FOUND)
|
||||
endif ()
|
||||
include_directories(${GLEW_INCLUDE_DIRS})
|
||||
|
||||
# Find the Cereal serialization library
|
||||
add_library(cereal INTERFACE)
|
||||
target_include_directories(cereal INTERFACE include)
|
||||
|
||||
# l10n
|
||||
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
||||
add_custom_target(pot
|
||||
|
2
deps/CMakeLists.txt
vendored
2
deps/CMakeLists.txt
vendored
@ -88,6 +88,7 @@ if (MSVC)
|
||||
dep_libcurl
|
||||
dep_wxwidgets
|
||||
dep_gtest
|
||||
dep_cereal
|
||||
dep_nlopt
|
||||
# dep_qhull # Experimental
|
||||
dep_zlib # on Windows we still need zlib
|
||||
@ -102,6 +103,7 @@ else()
|
||||
dep_libcurl
|
||||
dep_wxwidgets
|
||||
dep_gtest
|
||||
dep_cereal
|
||||
dep_nlopt
|
||||
dep_qhull
|
||||
dep_libigl
|
||||
|
10
deps/deps-unix-common.cmake
vendored
10
deps/deps-unix-common.cmake
vendored
@ -19,6 +19,16 @@ ExternalProject_Add(dep_gtest
|
||||
CMAKE_ARGS -DBUILD_GMOCK=OFF ${DEP_CMAKE_OPTS} -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||
)
|
||||
|
||||
ExternalProject_Add(dep_cereal
|
||||
EXCLUDE_FROM_ALL 1
|
||||
URL "https://github.com/USCiLab/cereal/archive/v1.2.2.tar.gz"
|
||||
# URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae
|
||||
CMAKE_ARGS
|
||||
-DJUST_INSTALL_CEREAL=on
|
||||
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||
${DEP_CMAKE_OPTS}
|
||||
)
|
||||
|
||||
ExternalProject_Add(dep_nlopt
|
||||
EXCLUDE_FROM_ALL 1
|
||||
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
|
||||
|
14
deps/deps-windows.cmake
vendored
14
deps/deps-windows.cmake
vendored
@ -115,6 +115,20 @@ if (${DEP_DEBUG})
|
||||
endif ()
|
||||
|
||||
|
||||
ExternalProject_Add(dep_cereal
|
||||
EXCLUDE_FROM_ALL 1
|
||||
URL "https://github.com/USCiLab/cereal/archive/v1.2.2.tar.gz"
|
||||
# URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae
|
||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||
CMAKE_ARGS
|
||||
-DJUST_INSTALL_CEREAL=on
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
|
||||
|
||||
ExternalProject_Add(dep_nlopt
|
||||
EXCLUDE_FROM_ALL 1
|
||||
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
|
||||
|
@ -189,6 +189,7 @@ target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNE
|
||||
target_link_libraries(libslic3r
|
||||
libnest2d
|
||||
admesh
|
||||
cereal
|
||||
libigl
|
||||
miniz
|
||||
boost_libs
|
||||
|
@ -209,6 +209,51 @@ std::vector<std::string> ConfigOptionDef::cli_args(const std::string &key) const
|
||||
return args;
|
||||
}
|
||||
|
||||
ConfigOption* ConfigOptionDef::create_empty_option() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case coFloat: return new ConfigOptionFloat();
|
||||
case coFloats: return new ConfigOptionFloats();
|
||||
case coInt: return new ConfigOptionInt();
|
||||
case coInts: return new ConfigOptionInts();
|
||||
case coString: return new ConfigOptionString();
|
||||
case coStrings: return new ConfigOptionStrings();
|
||||
case coPercent: return new ConfigOptionPercent();
|
||||
case coPercents: return new ConfigOptionPercents();
|
||||
case coFloatOrPercent: return new ConfigOptionFloatOrPercent();
|
||||
case coPoint: return new ConfigOptionPoint();
|
||||
case coPoints: return new ConfigOptionPoints();
|
||||
case coPoint3: return new ConfigOptionPoint3();
|
||||
// case coPoint3s: return new ConfigOptionPoint3s();
|
||||
case coBool: return new ConfigOptionBool();
|
||||
case coBools: return new ConfigOptionBools();
|
||||
case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map);
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigOption* ConfigOptionDef::create_default_option() const
|
||||
{
|
||||
if (this->default_value)
|
||||
return (this->default_value->type() == coEnum) ?
|
||||
// Special case: For a DynamicConfig, convert a templated enum to a generic enum.
|
||||
new ConfigOptionEnumGeneric(this->enum_keys_map, this->default_value->getInt()) :
|
||||
this->default_value->clone();
|
||||
return this->create_empty_option();
|
||||
}
|
||||
|
||||
// Assignment of the serialization IDs is not thread safe. The Defs shall be initialized from the main thread!
|
||||
ConfigOptionDef* ConfigDef::add(const t_config_option_key &opt_key, ConfigOptionType type)
|
||||
{
|
||||
static size_t serialization_key_ordinal_last = 0;
|
||||
ConfigOptionDef *opt = &this->options[opt_key];
|
||||
opt->opt_key = opt_key;
|
||||
opt->type = type;
|
||||
opt->serialization_key_ordinal = ++ serialization_key_ordinal_last;
|
||||
this->by_serialization_key_ordinal[opt->serialization_key_ordinal] = opt;
|
||||
return opt;
|
||||
}
|
||||
|
||||
std::string ConfigOptionDef::nocli = "~~~noCLI";
|
||||
|
||||
std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const
|
||||
@ -358,7 +403,7 @@ t_config_option_keys ConfigBase::equal(const ConfigBase &other) const
|
||||
return equal;
|
||||
}
|
||||
|
||||
std::string ConfigBase::serialize(const t_config_option_key &opt_key) const
|
||||
std::string ConfigBase::opt_serialize(const t_config_option_key &opt_key) const
|
||||
{
|
||||
const ConfigOption* opt = this->option(opt_key);
|
||||
assert(opt != nullptr);
|
||||
@ -469,7 +514,7 @@ void ConfigBase::setenv_() const
|
||||
for (size_t i = 0; i < envname.size(); ++i)
|
||||
envname[i] = (envname[i] <= 'z' && envname[i] >= 'a') ? envname[i]-('a'-'A') : envname[i];
|
||||
|
||||
boost::nowide::setenv(envname.c_str(), this->serialize(*it).c_str(), 1);
|
||||
boost::nowide::setenv(envname.c_str(), this->opt_serialize(*it).c_str(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,16 +638,16 @@ void ConfigBase::save(const std::string &file) const
|
||||
c.open(file, std::ios::out | std::ios::trunc);
|
||||
c << "# " << Slic3r::header_slic3r_generated() << std::endl;
|
||||
for (const std::string &opt_key : this->keys())
|
||||
c << opt_key << " = " << this->serialize(opt_key) << std::endl;
|
||||
c << opt_key << " = " << this->opt_serialize(opt_key) << std::endl;
|
||||
c.close();
|
||||
}
|
||||
|
||||
bool DynamicConfig::operator==(const DynamicConfig &rhs) const
|
||||
{
|
||||
t_options_map::const_iterator it1 = this->options.begin();
|
||||
t_options_map::const_iterator it1_end = this->options.end();
|
||||
t_options_map::const_iterator it2 = rhs.options.begin();
|
||||
t_options_map::const_iterator it2_end = rhs.options.end();
|
||||
auto it1 = this->options.begin();
|
||||
auto it1_end = this->options.end();
|
||||
auto it2 = rhs.options.begin();
|
||||
auto it2_end = rhs.options.end();
|
||||
for (; it1 != it1_end && it2 != it2_end; ++ it1, ++ it2)
|
||||
if (it1->first != it2->first || *it1->second != *it2->second)
|
||||
// key or value differ
|
||||
@ -612,10 +657,10 @@ bool DynamicConfig::operator==(const DynamicConfig &rhs) const
|
||||
|
||||
ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create)
|
||||
{
|
||||
t_options_map::iterator it = options.find(opt_key);
|
||||
auto it = options.find(opt_key);
|
||||
if (it != options.end())
|
||||
// Option was found.
|
||||
return it->second;
|
||||
return it->second.get();
|
||||
if (! create)
|
||||
// Option was not found and a new option shall not be created.
|
||||
return nullptr;
|
||||
@ -628,34 +673,8 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre
|
||||
// throw std::runtime_error(std::string("Invalid option name: ") + opt_key);
|
||||
// Let the parent decide what to do if the opt_key is not defined by this->def().
|
||||
return nullptr;
|
||||
ConfigOption *opt = nullptr;
|
||||
if (optdef->default_value) {
|
||||
opt = (optdef->default_value->type() == coEnum) ?
|
||||
// Special case: For a DynamicConfig, convert a templated enum to a generic enum.
|
||||
new ConfigOptionEnumGeneric(optdef->enum_keys_map, optdef->default_value->getInt()) :
|
||||
optdef->default_value->clone();
|
||||
} else {
|
||||
switch (optdef->type) {
|
||||
case coFloat: opt = new ConfigOptionFloat(); break;
|
||||
case coFloats: opt = new ConfigOptionFloats(); break;
|
||||
case coInt: opt = new ConfigOptionInt(); break;
|
||||
case coInts: opt = new ConfigOptionInts(); break;
|
||||
case coString: opt = new ConfigOptionString(); break;
|
||||
case coStrings: opt = new ConfigOptionStrings(); break;
|
||||
case coPercent: opt = new ConfigOptionPercent(); break;
|
||||
case coPercents: opt = new ConfigOptionPercents(); break;
|
||||
case coFloatOrPercent: opt = new ConfigOptionFloatOrPercent(); break;
|
||||
case coPoint: opt = new ConfigOptionPoint(); break;
|
||||
case coPoints: opt = new ConfigOptionPoints(); break;
|
||||
case coPoint3: opt = new ConfigOptionPoint3(); break;
|
||||
// case coPoint3s: opt = new ConfigOptionPoint3s(); break;
|
||||
case coBool: opt = new ConfigOptionBool(); break;
|
||||
case coBools: opt = new ConfigOptionBools(); break;
|
||||
case coEnum: opt = new ConfigOptionEnumGeneric(optdef->enum_keys_map); break;
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + opt_key);
|
||||
}
|
||||
}
|
||||
this->options[opt_key] = opt;
|
||||
ConfigOption *opt = optdef->create_default_option();
|
||||
this->options.insert(it, std::make_pair(opt_key, opt));
|
||||
return opt;
|
||||
}
|
||||
|
||||
@ -802,3 +821,63 @@ t_config_option_keys StaticConfig::keys() const
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOption)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<double>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<int>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<std::string>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<Slic3r::Vec2d>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<Slic3r::Vec3d>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle<bool>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVectorBase)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<double>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<int>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<std::string>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<Slic3r::Vec2d>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<unsigned char>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloat)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionString)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionStrings)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercent)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercents)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatOrPercent)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoints)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint3)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBool)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBools)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigBase)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig)
|
||||
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<double>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<int>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<std::string>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<Slic3r::Vec2d>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<Slic3r::Vec3d>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle<bool>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionVectorBase)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<double>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<int>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<std::string>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<Slic3r::Vec2d>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<unsigned char>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<double>, Slic3r::ConfigOptionFloat)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<double>, Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<int>, Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<int>, Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<std::string>, Slic3r::ConfigOptionString)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<std::string>, Slic3r::ConfigOptionStrings)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloat, Slic3r::ConfigOptionPercent)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloats, Slic3r::ConfigOptionPercents)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionPercent, Slic3r::ConfigOptionFloatOrPercent)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<Slic3r::Vec2d>, Slic3r::ConfigOptionPoint)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<Slic3r::Vec2d>, Slic3r::ConfigOptionPoints)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<Slic3r::Vec3d>, Slic3r::ConfigOptionPoint3)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<bool>, Slic3r::ConfigOptionBool)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBools)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig)
|
||||
|
@ -18,6 +18,12 @@
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include <cereal/types/polymorphic.hpp>
|
||||
#include <cereal/types/map.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
#include <cereal/archives/binary.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Name of the configuration option.
|
||||
@ -152,6 +158,10 @@ public:
|
||||
|
||||
bool operator==(const T &rhs) const { return this->value == rhs; }
|
||||
bool operator!=(const T &rhs) const { return this->value != rhs; }
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive & ar) { ar(this->value); }
|
||||
};
|
||||
|
||||
// Value of a vector valued option (bools, ints, floats, strings, points)
|
||||
@ -290,6 +300,10 @@ public:
|
||||
|
||||
bool operator==(const std::vector<T> &rhs) const { return this->values == rhs; }
|
||||
bool operator!=(const std::vector<T> &rhs) const { return this->values != rhs; }
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive & ar) { ar(this->values); }
|
||||
};
|
||||
|
||||
class ConfigOptionFloat : public ConfigOptionSingle<double>
|
||||
@ -324,6 +338,10 @@ public:
|
||||
this->set(opt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionFloats : public ConfigOptionVector<double>
|
||||
@ -382,6 +400,10 @@ public:
|
||||
this->set(opt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<double>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionInt : public ConfigOptionSingle<int>
|
||||
@ -418,6 +440,10 @@ public:
|
||||
this->set(opt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<int>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionInts : public ConfigOptionVector<int>
|
||||
@ -468,6 +494,10 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<int>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionString : public ConfigOptionSingle<std::string>
|
||||
@ -492,6 +522,10 @@ public:
|
||||
UNUSED(append);
|
||||
return unescape_string_cstyle(str, this->value);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<std::string>>(this)); }
|
||||
};
|
||||
|
||||
// semicolon-separated strings
|
||||
@ -526,6 +560,10 @@ public:
|
||||
this->values.clear();
|
||||
return unescape_strings_cstyle(str, this->values);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<std::string>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionPercent : public ConfigOptionFloat
|
||||
@ -558,6 +596,10 @@ public:
|
||||
iss >> this->value;
|
||||
return !iss.fail();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloat>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionPercents : public ConfigOptionFloats
|
||||
@ -612,6 +654,10 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloats>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionFloatOrPercent : public ConfigOptionPercent
|
||||
@ -661,6 +707,10 @@ public:
|
||||
iss >> this->value;
|
||||
return !iss.fail();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionPercent>(this), percent); }
|
||||
};
|
||||
|
||||
class ConfigOptionPoint : public ConfigOptionSingle<Vec2d>
|
||||
@ -691,6 +741,10 @@ public:
|
||||
return sscanf(str.data(), " %lf , %lf %c", &this->value(0), &this->value(1), &dummy) == 2 ||
|
||||
sscanf(str.data(), " %lf x %lf %c", &this->value(0), &this->value(1), &dummy) == 2;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(this->value.x(), this->value.y()); }
|
||||
};
|
||||
|
||||
class ConfigOptionPoints : public ConfigOptionVector<Vec2d>
|
||||
@ -750,8 +804,21 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void save(Archive& archive) const {
|
||||
size_t cnt = this->values.size();
|
||||
archive(cnt);
|
||||
archive.saveBinary((const char*)this->values.data(), sizeof(Vec2d) * cnt);
|
||||
}
|
||||
template<class Archive> void load(Archive& archive) {
|
||||
size_t cnt;
|
||||
archive(cnt);
|
||||
this->values.assign(cnt, Vec2d());
|
||||
archive.loadBinary((char*)this->values.data(), sizeof(Vec2d) * cnt);
|
||||
}
|
||||
};
|
||||
|
||||
class ConfigOptionPoint3 : public ConfigOptionSingle<Vec3d>
|
||||
{
|
||||
@ -783,6 +850,10 @@ public:
|
||||
return sscanf(str.data(), " %lf , %lf , %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 2 ||
|
||||
sscanf(str.data(), " %lf x %lf x %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 2;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(this->value.x(), this->value.y(), this->value.z()); }
|
||||
};
|
||||
|
||||
class ConfigOptionBool : public ConfigOptionSingle<bool>
|
||||
@ -809,6 +880,10 @@ public:
|
||||
this->value = (str.compare("1") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<bool>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionBools : public ConfigOptionVector<unsigned char>
|
||||
@ -864,6 +939,10 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<unsigned char>>(this)); }
|
||||
};
|
||||
|
||||
// Map from an enum integer value to an enum name.
|
||||
@ -1002,19 +1081,73 @@ public:
|
||||
this->value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); }
|
||||
};
|
||||
|
||||
// Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling.
|
||||
class ConfigOptionDef
|
||||
{
|
||||
public:
|
||||
// Identifier of this option. It is stored here so that it is accessible through the by_serialization_key_ordinal map.
|
||||
t_config_option_key opt_key;
|
||||
// What type? bool, int, string etc.
|
||||
ConfigOptionType type = coNone;
|
||||
// Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
|
||||
Slic3r::clonable_ptr<const ConfigOption> default_value;
|
||||
void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr<const ConfigOption>(ptr); }
|
||||
template<typename T>
|
||||
const T* get_default_value() const { return static_cast<const T*>(this->default_value.get()); }
|
||||
void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr<const ConfigOption>(ptr); }
|
||||
template<typename T> const T* get_default_value() const { return static_cast<const T*>(this->default_value.get()); }
|
||||
|
||||
// Create an empty option to be used as a base for deserialization of DynamicConfig.
|
||||
ConfigOption* create_empty_option() const;
|
||||
// Create a default option to be inserted into a DynamicConfig.
|
||||
ConfigOption* create_default_option() const;
|
||||
|
||||
template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
|
||||
switch (this->type) {
|
||||
case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; }
|
||||
case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); return opt; }
|
||||
case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; }
|
||||
case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); return opt; }
|
||||
case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; }
|
||||
case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); return opt; }
|
||||
case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; }
|
||||
case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; }
|
||||
case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; }
|
||||
case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; }
|
||||
case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; }
|
||||
case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; }
|
||||
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
|
||||
case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; }
|
||||
case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; }
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive> ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const {
|
||||
switch (this->type) {
|
||||
case coFloat: archive(*static_cast<const ConfigOptionFloat*>(opt)); break;
|
||||
case coFloats: archive(*static_cast<const ConfigOptionFloats*>(opt)); break;
|
||||
case coInt: archive(*static_cast<const ConfigOptionInt*>(opt)); break;
|
||||
case coInts: archive(*static_cast<const ConfigOptionInts*>(opt)); break;
|
||||
case coString: archive(*static_cast<const ConfigOptionString*>(opt)); break;
|
||||
case coStrings: archive(*static_cast<const ConfigOptionStrings*>(opt)); break;
|
||||
case coPercent: archive(*static_cast<const ConfigOptionPercent*>(opt)); break;
|
||||
case coPercents: archive(*static_cast<const ConfigOptionPercents*>(opt)); break;
|
||||
case coFloatOrPercent: archive(*static_cast<const ConfigOptionFloatOrPercent*>(opt)); break;
|
||||
case coPoint: archive(*static_cast<const ConfigOptionPoint*>(opt)); break;
|
||||
case coPoints: archive(*static_cast<const ConfigOptionPoints*>(opt)); break;
|
||||
case coPoint3: archive(*static_cast<const ConfigOptionPoint3*>(opt)); break;
|
||||
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
|
||||
case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
|
||||
case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
// Make the compiler happy, shut up the warnings.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Usually empty.
|
||||
// Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection,
|
||||
@ -1084,6 +1217,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// 0 is an invalid key.
|
||||
size_t serialization_key_ordinal = 0;
|
||||
|
||||
// Returns the alternative CLI arguments for the given option.
|
||||
// If there are no cli arguments defined, use the key and replace underscores with dashes.
|
||||
std::vector<std::string> cli_args(const std::string &key) const;
|
||||
@ -1103,7 +1239,8 @@ typedef std::map<t_config_option_key, ConfigOptionDef> t_optiondef_map;
|
||||
class ConfigDef
|
||||
{
|
||||
public:
|
||||
t_optiondef_map options;
|
||||
t_optiondef_map options;
|
||||
std::map<size_t, const ConfigOptionDef*> by_serialization_key_ordinal;
|
||||
|
||||
bool has(const t_config_option_key &opt_key) const { return this->options.count(opt_key) > 0; }
|
||||
const ConfigOptionDef* get(const t_config_option_key &opt_key) const {
|
||||
@ -1124,11 +1261,7 @@ public:
|
||||
std::function<bool(const ConfigOptionDef &)> filter = [](const ConfigOptionDef &){ return true; }) const;
|
||||
|
||||
protected:
|
||||
ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type) {
|
||||
ConfigOptionDef* opt = &this->options[opt_key];
|
||||
opt->type = type;
|
||||
return opt;
|
||||
}
|
||||
ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type);
|
||||
};
|
||||
|
||||
// An abstract configuration store.
|
||||
@ -1197,7 +1330,7 @@ public:
|
||||
bool equals(const ConfigBase &other) const { return this->diff(other).empty(); }
|
||||
t_config_option_keys diff(const ConfigBase &other) const;
|
||||
t_config_option_keys equal(const ConfigBase &other) const;
|
||||
std::string serialize(const t_config_option_key &opt_key) const;
|
||||
std::string opt_serialize(const t_config_option_key &opt_key) const;
|
||||
// Set a configuration value from a string, it will call an overridable handle_legacy()
|
||||
// to resolve renamed and removed configuration keys.
|
||||
bool set_deserialize(const t_config_option_key &opt_key, const std::string &str, bool append = false);
|
||||
@ -1235,7 +1368,7 @@ public:
|
||||
assert(this->def() == nullptr || this->def() == rhs.def());
|
||||
this->clear();
|
||||
for (const auto &kvp : rhs.options)
|
||||
this->options[kvp.first] = kvp.second->clone();
|
||||
this->options[kvp.first].reset(kvp.second->clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1258,15 +1391,13 @@ public:
|
||||
for (const auto &kvp : rhs.options) {
|
||||
auto it = this->options.find(kvp.first);
|
||||
if (it == this->options.end())
|
||||
this->options[kvp.first] = kvp.second->clone();
|
||||
this->options[kvp.first].reset(kvp.second->clone());
|
||||
else {
|
||||
assert(it->second->type() == kvp.second->type());
|
||||
if (it->second->type() == kvp.second->type())
|
||||
*it->second = *kvp.second;
|
||||
else {
|
||||
delete it->second;
|
||||
it->second = kvp.second->clone();
|
||||
}
|
||||
else
|
||||
it->second.reset(kvp.second->clone());
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@ -1277,14 +1408,13 @@ public:
|
||||
DynamicConfig& operator+=(DynamicConfig &&rhs)
|
||||
{
|
||||
assert(this->def() == nullptr || this->def() == rhs.def());
|
||||
for (const auto &kvp : rhs.options) {
|
||||
for (auto &kvp : rhs.options) {
|
||||
auto it = this->options.find(kvp.first);
|
||||
if (it == this->options.end()) {
|
||||
this->options[kvp.first] = kvp.second;
|
||||
this->options.insert(std::make_pair(kvp.first, std::move(kvp.second)));
|
||||
} else {
|
||||
assert(it->second->type() == kvp.second->type());
|
||||
delete it->second;
|
||||
it->second = kvp.second;
|
||||
it->second = std::move(kvp.second);
|
||||
}
|
||||
}
|
||||
rhs.options.clear();
|
||||
@ -1301,8 +1431,6 @@ public:
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (auto &opt : this->options)
|
||||
delete opt.second;
|
||||
this->options.clear();
|
||||
}
|
||||
|
||||
@ -1311,7 +1439,6 @@ public:
|
||||
auto it = this->options.find(opt_key);
|
||||
if (it == this->options.end())
|
||||
return false;
|
||||
delete it->second;
|
||||
this->options.erase(it);
|
||||
return true;
|
||||
}
|
||||
@ -1336,11 +1463,10 @@ public:
|
||||
{
|
||||
auto it = this->options.find(opt_key);
|
||||
if (it == this->options.end()) {
|
||||
this->options[opt_key] = opt;
|
||||
this->options[opt_key].reset(opt);
|
||||
return true;
|
||||
} else {
|
||||
delete it->second;
|
||||
it->second = opt;
|
||||
it->second.reset(opt);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1370,12 +1496,15 @@ public:
|
||||
void read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
|
||||
bool read_cli(int argc, char** argv, t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
|
||||
|
||||
typedef std::map<t_config_option_key,ConfigOption*> t_options_map;
|
||||
t_options_map::const_iterator cbegin() const { return options.cbegin(); }
|
||||
t_options_map::const_iterator cend() const { return options.cend(); }
|
||||
std::map<t_config_option_key, std::unique_ptr<ConfigOption>>::const_iterator cbegin() const { return options.cbegin(); }
|
||||
std::map<t_config_option_key, std::unique_ptr<ConfigOption>>::const_iterator cend() const { return options.cend(); }
|
||||
size_t size() const { return options.size(); }
|
||||
|
||||
private:
|
||||
t_options_map options;
|
||||
std::map<t_config_option_key, std::unique_ptr<ConfigOption>> options;
|
||||
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(options); }
|
||||
};
|
||||
|
||||
/// Configuration store with a static definition of configuration values.
|
||||
|
@ -2060,7 +2060,7 @@ namespace Slic3r {
|
||||
|
||||
for (const std::string &key : config.keys())
|
||||
if (key != "compatible_printers")
|
||||
out += "; " + key + " = " + config.serialize(key) + "\n";
|
||||
out += "; " + key + " = " + config.opt_serialize(key) + "\n";
|
||||
|
||||
if (!out.empty())
|
||||
{
|
||||
@ -2094,7 +2094,7 @@ namespace Slic3r {
|
||||
// stores object's config data
|
||||
for (const std::string& key : obj->config.keys())
|
||||
{
|
||||
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << obj->config.serialize(key) << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << obj->config.opt_serialize(key) << "\"/>\n";
|
||||
}
|
||||
|
||||
for (const ModelVolume* volume : obj_metadata.second.object->volumes)
|
||||
@ -2124,7 +2124,7 @@ namespace Slic3r {
|
||||
// stores volume's config data
|
||||
for (const std::string& key : volume->config.keys())
|
||||
{
|
||||
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.serialize(key) << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n";
|
||||
}
|
||||
|
||||
stream << " </" << VOLUME_TAG << ">\n";
|
||||
|
@ -873,7 +873,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
std::string str_config = "\n";
|
||||
for (const std::string &key : config->keys())
|
||||
if (key != "compatible_printers")
|
||||
str_config += "; " + key + " = " + config->serialize(key) + "\n";
|
||||
str_config += "; " + key + " = " + config->opt_serialize(key) + "\n";
|
||||
stream << "<metadata type=\"" << SLIC3R_CONFIG_TYPE << "\">" << xml_escape(str_config) << "</metadata>\n";
|
||||
}
|
||||
|
||||
@ -885,7 +885,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
for (const auto &attr : material.second->attributes)
|
||||
stream << " <metadata type=\"" << attr.first << "\">" << attr.second << "</metadata>\n";
|
||||
for (const std::string &key : material.second->config.keys())
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << material.second->config.serialize(key) << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << material.second->config.opt_serialize(key) << "</metadata>\n";
|
||||
stream << " </material>\n";
|
||||
}
|
||||
std::string instances;
|
||||
@ -893,7 +893,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
ModelObject *object = model->objects[object_id];
|
||||
stream << " <object id=\"" << object_id << "\">\n";
|
||||
for (const std::string &key : object->config.keys())
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << object->config.serialize(key) << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << object->config.opt_serialize(key) << "</metadata>\n";
|
||||
if (!object->name.empty())
|
||||
stream << " <metadata type=\"name\">" << xml_escape(object->name) << "</metadata>\n";
|
||||
const std::vector<double> &layer_height_profile = object->layer_height_profile;
|
||||
@ -952,7 +952,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
else
|
||||
stream << " <volume materialid=\"" << volume->material_id() << "\">\n";
|
||||
for (const std::string &key : volume->config.keys())
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << volume->config.serialize(key) << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r." << key << "\">" << volume->config.opt_serialize(key) << "</metadata>\n";
|
||||
if (!volume->name.empty())
|
||||
stream << " <metadata type=\"name\">" << xml_escape(volume->name) << "</metadata>\n";
|
||||
if (volume->is_modifier())
|
||||
|
@ -1749,7 +1749,7 @@ void GCode::append_full_config(const Print& print, std::string& str)
|
||||
const StaticPrintConfig *cfg = configs[i];
|
||||
for (const std::string &key : cfg->keys())
|
||||
if (key != "compatible_printers")
|
||||
str += "; " + key + " = " + cfg->serialize(key) + "\n";
|
||||
str += "; " + key + " = " + cfg->opt_serialize(key) + "\n";
|
||||
}
|
||||
const DynamicConfig &full_config = print.placeholder_parser().config();
|
||||
for (const char *key : {
|
||||
|
@ -128,7 +128,7 @@ void Layer::make_perimeters()
|
||||
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
||||
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||
&& config.overhangs == other_config.overhangs
|
||||
&& config.serialize("perimeter_extrusion_width").compare(other_config.serialize("perimeter_extrusion_width")) == 0
|
||||
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
|
||||
&& config.thin_walls == other_config.thin_walls
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||
layerms.push_back(other_layerm);
|
||||
|
@ -406,10 +406,13 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
|
||||
def = this->add("bottom_fill_pattern", coEnum);
|
||||
*def = *def_top_fill_pattern;
|
||||
def->label = L("Bottom fill pattern");
|
||||
def->category = L("Infill");
|
||||
def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells.");
|
||||
def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern";
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values = def_top_fill_pattern->enum_values;
|
||||
def->aliases = def_top_fill_pattern->aliases;
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
|
||||
def = this->add("external_perimeter_extrusion_width", coFloatOrPercent);
|
||||
@ -3194,3 +3197,6 @@ void DynamicPrintAndCLIConfig::handle_legacy(t_config_option_key &opt_key, std::
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CEREAL_REGISTER_TYPE(Slic3r::DynamicPrintConfig)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::DynamicConfig, Slic3r::DynamicPrintConfig)
|
||||
|
@ -1190,6 +1190,8 @@ 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());
|
||||
for (const auto &kvp : this->options)
|
||||
this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second;
|
||||
}
|
||||
// Do not release the default values, they are handled by print_config_def & cli_actions_config_def / cli_transform_config_def / cli_misc_config_def.
|
||||
~PrintAndCLIConfigDef() { this->options.clear(); }
|
||||
@ -1199,4 +1201,38 @@ private:
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
// Serialization through the Cereal library
|
||||
namespace cereal {
|
||||
// Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig.
|
||||
template <class Archive> struct specialize<Archive, Slic3r::DynamicPrintConfig, cereal::specialization::non_member_load_save> {};
|
||||
|
||||
template<class Archive> void load(Archive& archive, Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt;
|
||||
archive(cnt);
|
||||
config.clear();
|
||||
for (size_t i = 0; i < cnt; ++ i) {
|
||||
size_t serialization_key_ordinal;
|
||||
archive(serialization_key_ordinal);
|
||||
assert(serialization_key_ordinal > 0);
|
||||
auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal);
|
||||
assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end());
|
||||
config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive));
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive> void save(Archive& archive, const Slic3r::DynamicPrintConfig &config)
|
||||
{
|
||||
size_t cnt = config.size();
|
||||
archive(cnt);
|
||||
for (auto it = config.cbegin(); it != config.cend(); ++it) {
|
||||
const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first);
|
||||
assert(optdef != nullptr);
|
||||
assert(optdef->serialization_key_ordinal > 0);
|
||||
archive(optdef->serialization_key_ordinal);
|
||||
optdef->save_option_to_archive(archive, it->second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -159,7 +159,7 @@ endif ()
|
||||
|
||||
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
|
||||
|
||||
target_link_libraries(libslic3r_gui libslic3r avrdude imgui ${GLEW_LIBRARIES})
|
||||
target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui ${GLEW_LIBRARIES})
|
||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
||||
endif ()
|
||||
|
@ -1366,7 +1366,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
|
||||
continue;
|
||||
c << std::endl << "[" << presets->section_name() << ":" << preset.name << "]" << std::endl;
|
||||
for (const std::string &opt_key : preset.config.keys())
|
||||
c << opt_key << " = " << preset.config.serialize(opt_key) << std::endl;
|
||||
c << opt_key << " = " << preset.config.opt_serialize(opt_key) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user