update libslic3r

This commit is contained in:
QIDI TECH
2024-11-11 14:57:19 +08:00
parent a42b7a0880
commit 87d9e1e953
432 changed files with 13838 additions and 6269 deletions

View File

@@ -2,6 +2,17 @@
#define slic3r_Config_hpp_
#include <assert.h>
#include <float.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format/format_fwd.hpp>
#include <boost/functional/hash.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
#include <cereal/access.hpp>
#include <cereal/types/base_class.hpp>
#include <ctype.h>
#include <boost/container_hash/hash.hpp>
#include <cereal/cereal.hpp>
#include <map>
#include <climits>
#include <limits>
@@ -14,20 +25,22 @@
#include <string_view>
#include <type_traits>
#include <vector>
#include <float.h>
#include <algorithm>
#include <cmath>
#include <initializer_list>
#include <memory>
#include <optional>
#include <utility>
#include <variant>
#include <cassert>
#include <cctype>
#include <cfloat>
#include "libslic3r.h"
#include "clonable_ptr.hpp"
#include "Exception.hpp"
#include "Point.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format/format_fwd.hpp>
#include <boost/functional/hash.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
#include <cereal/access.hpp>
#include <cereal/types/base_class.hpp>
#include "LocalesUtils.hpp"
namespace Slic3r {
struct FloatOrPercent
@@ -193,6 +206,8 @@ enum ConfigOptionType {
coBools = coBool + coVectorType,
// a generic enum
coEnum = 9,
// vector of enum values
coEnums = coEnum + coVectorType,
};
enum ConfigOptionMode {
@@ -231,6 +246,7 @@ enum ForwardCompatibilitySubstitutionRule
class ConfigDef;
class ConfigOption;
class ConfigOptionDef;
// For forward definition of ConfigOption in ConfigOptionUniquePtr, we have to define a custom deleter.
struct ConfigOptionDeleter { void operator()(ConfigOption* p); };
using ConfigOptionUniquePtr = std::unique_ptr<ConfigOption, ConfigOptionDeleter>;
@@ -269,6 +285,7 @@ public:
// Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0;
virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
virtual std::vector<int> getInts() const { throw BadOptionTypeException("Calling ConfigOption::getInts on a non-ints ConfigOption"); }
virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
virtual bool getBool() const { throw BadOptionTypeException("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
@@ -318,7 +335,7 @@ template<class T>
struct NilValueTempl<T, std::enable_if_t<std::is_enum_v<T>, void>>
{
using NilType = T;
static constexpr auto value = static_cast<T>(std::numeric_limits<std::underlying_type_t<T>>::max());
static constexpr auto value = static_cast<std::underlying_type_t<T>>(std::numeric_limits<std::underlying_type_t<T>>::max());
};
template<class T> struct NilValueTempl<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
@@ -346,6 +363,7 @@ template<class T> using NilType = typename NilValueTempl<remove_cvref_t<T>>::Nil
// Define shortcut as a function instead of a static const var so that it can be constexpr
// even if the NilValueTempl::value is not constexpr.
template<class T> static constexpr NilType<T> NilValue() noexcept { return NilValueTempl<remove_cvref_t<T>>::value; }
// Value of a single valued option (bool, int, float, string, point, enum)
template <class T, bool NULLABLE = false>
class ConfigOptionSingle : public ConfigOption {
@@ -430,6 +448,7 @@ public:
return ret;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) { ar(this->value); }
@@ -437,6 +456,7 @@ private:
template<class T>
using ConfigOptionSingleNullable = ConfigOptionSingle<T, true>;
// Value of a vector valued option (bools, ints, floats, strings, points)
class ConfigOptionVectorBase : public ConfigOption {
public:
@@ -683,6 +703,7 @@ public:
throw ConfigurationError("Serializing NaN");
} else
throw ConfigurationError("Serializing invalid number");
return ss.str();
}
@@ -690,14 +711,16 @@ public:
{
UNUSED(append);
std::istringstream iss(str);
if (str == "nil") {
if (NULLABLE)
this->value = this->nil_value();
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
} else {
iss >> this->value;
iss >> this->value;
}
return !iss.fail();
}
@@ -711,6 +734,7 @@ public:
{
return std::isnan(this->value);
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double, NULLABLE>>(this)); }
@@ -868,7 +892,8 @@ public:
else
throw ConfigurationError("Serializing NaN");
} else
ss << this->value;
ss << this->value;
return ss.str();
}
@@ -876,14 +901,16 @@ public:
{
UNUSED(append);
std::istringstream iss(str);
if (str == "nil") {
if (NULLABLE)
this->value = this->nil_value();
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
} else {
iss >> this->value;
iss >> this->value;
}
return !iss.fail();
}
@@ -900,6 +927,7 @@ private:
using ConfigOptionInt = ConfigOptionIntTempl<false>;
using ConfigOptionIntNullable = ConfigOptionIntTempl<true>;
template<bool NULLABLE>
class ConfigOptionIntsTempl : public ConfigOptionVector<int>
{
@@ -1709,6 +1737,113 @@ public:
}
};
template <class T>
class ConfigOptionEnums : public ConfigOptionVector<T>
{
public:
// by default, use the first value (0) of the T enum type
ConfigOptionEnums() : ConfigOptionVector<T>() {}
explicit ConfigOptionEnums(size_t n, const T& value) : ConfigOptionVector<T>(n, value) {}
explicit ConfigOptionEnums(std::initializer_list<T> il) : ConfigOptionVector<T>(std::move(il)) {}
explicit ConfigOptionEnums(const std::vector<T>& values) : ConfigOptionVector<T>(values) {}
static ConfigOptionType static_type() { return coEnums; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnums<T>(*this); }
ConfigOptionEnums<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnums<T> &rhs) const throw() { return this->values == rhs.values; }
bool operator< (const ConfigOptionEnums<T> &rhs) const throw() { return this->values < rhs.values; }
bool is_nil(size_t) const override { return false; }
std::vector<int> getInts() const override {
std::vector<int> ret;
ret.reserve(this->values.size());
for (const auto& v : this->values)
ret.push_back(int(v));
return ret;
}
bool operator==(const ConfigOption& rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnums<T>: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
return this->getInts() == rhs.getInts();
}
void set(const ConfigOption* rhs) override {
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionEnums<T>: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
std::vector<T> ret;
std::vector<int> rhs_vals = rhs->getInts();
ret.reserve(rhs_vals.size());
for (const int& v : rhs_vals)
ret.push_back(T(v));
this->values = ret;
}
std::string serialize() const override
{
const t_config_enum_names& names = ConfigOptionEnum<T>::get_enum_names();
std::ostringstream ss;
for (const T& v : this->values) {
assert(static_cast<int>(v) < int(names.size()));
if (&v != &this->values.front())
ss << "," << names[static_cast<int>(v)];
}
return ss.str();
}
std::vector<std::string> vserialize() const override
{
std::vector<std::string> vv;
vv.reserve(this->values.size());
for (const T v : this->values) {
std::ostringstream ss;
serialize_single_value(ss, int(v));
vv.push_back(ss.str());
}
return vv;
}
bool deserialize(const std::string& str, bool append = false) override
{
if (!append)
this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
boost::trim(item_str);
if (item_str == "nil") {
throw ConfigurationError("Deserializing nil into a non-nullable object");
}
else {
std::istringstream iss(item_str);
int value;
iss >> value;
this->values.push_back(static_cast<T>(value));
}
}
return true;
}
static bool from_string(const std::string &str, T &value)
{
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
auto it = enum_keys_map.find(str);
if (it == enum_keys_map.end())
return false;
value = static_cast<T>(it->second);
return true;
}
private:
void serialize_single_value(std::ostringstream& ss, const int v) const {
ss << v;
}
};
// Generic enum configuration value.
// We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum.
// In the StaticConfig, it is better to use the specialized ConfigOptionEnum<T> containers.
@@ -1765,6 +1900,132 @@ private:
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); }
};
template<bool NULLABLE>
class ConfigOptionEnumsGenericTempl : public ConfigOptionIntsTempl<NULLABLE>
{
public:
ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map = nullptr) : keys_map(keys_map) {}
explicit ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map, std::vector<int> values) : keys_map(keys_map) { this->values = values; }
const t_config_enum_values* keys_map;
ConfigOptionEnumsGenericTempl() : ConfigOptionIntsTempl<NULLABLE>() {}
explicit ConfigOptionEnumsGenericTempl(size_t n, int value) : ConfigOptionIntsTempl<NULLABLE>(n, value) {}
explicit ConfigOptionEnumsGenericTempl(std::initializer_list<int> il) : ConfigOptionIntsTempl<NULLABLE>(std::move(il)) {}
explicit ConfigOptionEnumsGenericTempl(const std::vector<int>& v) : ConfigOptionIntsTempl<NULLABLE>(v) {}
explicit ConfigOptionEnumsGenericTempl(std::vector<int>&& v) : ConfigOptionIntsTempl<NULLABLE>(std::move(v)) {}
static ConfigOptionType static_type() { return coEnums; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnumsGenericTempl(*this); }
ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values == rhs.values; }
bool operator< (const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values < rhs.values; }
std::vector<int> getInts() const override { return this->values; }
bool operator==(const ConfigOption& rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
return this->values == rhs.getInts();
}
void set(const ConfigOption* rhs) override {
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
this->values = rhs->getInts();
}
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
static int nil_value() { return std::numeric_limits<int>::max(); }
// A scalar is nil, or all values of a vector are nil.
bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
bool is_nil(size_t idx) const override { return this->values[idx < this->values.size() ? idx : 0] == nil_value(); }
int& get_at(size_t i) {
assert(!this->values.empty());
return *reinterpret_cast<int*>(&((i < this->values.size()) ? this->values[i] : this->values.front()));
}
int get_at(size_t i) const { return i < this->values.size() ? this->values[i] : this->values.front(); }
std::string serialize() const override
{
std::ostringstream ss;
for (const int& v : this->values) {
if (&v != &this->values.front())
ss << ",";
serialize_single_value(ss, v);
}
return ss.str();
}
std::vector<std::string> vserialize() const override
{
std::vector<std::string> vv;
vv.reserve(this->values.size());
for (const int v : this->values) {
std::ostringstream ss;
serialize_single_value(ss, v);
vv.push_back(ss.str());
}
return vv;
}
bool deserialize(const std::string& str, bool append = false) override
{
if (!append)
this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
boost::trim(item_str);
if (item_str == "nil") {
if (NULLABLE)
this->values.push_back(nil_value());
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
}
else {
auto it = this->keys_map->find(item_str);
if (it == this->keys_map->end())
return false;
this->values.push_back(it->second);
}
}
return true;
}
private:
void serialize_single_value(std::ostringstream& ss, const int v) const {
if (v == nil_value()) {
if (NULLABLE)
ss << "nil";
else
throw ConfigurationError("Serializing NaN");
}
else {
for (const auto& kvp : *this->keys_map)
if (kvp.second == v) {
ss << kvp.first;
return;
}
ss << std::string();
}
}
friend class cereal::access;
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionVector<int>>(this)); }
};
using ConfigOptionEnumsGeneric = ConfigOptionEnumsGenericTempl<false>;
using ConfigOptionEnumsGenericNullable = ConfigOptionEnumsGenericTempl<true>;
// Definition of values / labels for a combo box.
// Mostly used for closed enums (when type == coEnum), but may be used for
// open enums with ints resp. floats, if gui_type is set to GUIType::i_enum_open" resp. GUIType::f_enum_open.
@@ -1958,6 +2219,8 @@ public:
one_string,
// Close parameter, string value could be one of the list values.
select_close,
// Password, string vaule is hidden by asterisk.
password,
};
static bool is_gui_type_enum_open(const GUIType gui_type)
{ return gui_type == ConfigOptionDef::GUIType::i_enum_open || gui_type == ConfigOptionDef::GUIType::f_enum_open || gui_type == ConfigOptionDef::GUIType::select_open; }
@@ -1979,6 +2242,7 @@ public:
ConfigOption* create_default_option() const;
bool is_scalar() const { return (int(this->type) & int(coVectorType)) == 0; }
template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
if (this->nullable) {
switch (this->type) {
@@ -2008,6 +2272,7 @@ public:
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_def->m_enum_keys_map); archive(*opt); return opt; }
case coEnums: { auto opt = new ConfigOptionEnumsGeneric(this->enum_def->m_enum_keys_map); archive(*opt); return opt; }
default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
}
}
@@ -2042,6 +2307,7 @@ public:
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;
case coEnums: archive(*static_cast<const ConfigOptionEnumsGeneric*>(opt)); break;
default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
}
}
@@ -2449,6 +2715,8 @@ public:
// Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionEnums<ENUM>*>(this->option(opt_key))->get_at(idx);}
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }