mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 15:05:55 +08:00
Merge branch 'ys_sla_overrides' into master_27x
This commit is contained in:
commit
91323230e6
@ -266,6 +266,8 @@ ConfigOption* ConfigOptionDef::create_empty_option() const
|
||||
{
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloat: return new ConfigOptionFloatNullable();
|
||||
case coInt: return new ConfigOptionIntNullable();
|
||||
case coFloats: return new ConfigOptionFloatsNullable();
|
||||
case coInts: return new ConfigOptionIntsNullable();
|
||||
case coPercents: return new ConfigOptionPercentsNullable();
|
||||
@ -1433,6 +1435,9 @@ 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::ConfigOptionSingleNullable<double>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingleNullable<int>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingleNullable<bool>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVectorBase)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<double>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<int>)
|
||||
@ -1440,9 +1445,11 @@ 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::ConfigOptionFloatNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionIntNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionIntsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionString)
|
||||
@ -1469,6 +1476,9 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionS
|
||||
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::ConfigOptionSingleNullable<double>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingleNullable<int>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingleNullable<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>)
|
||||
@ -1476,9 +1486,11 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::Con
|
||||
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::ConfigOptionSingleNullable<double>, Slic3r::ConfigOptionFloatNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<double>, Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<double>, Slic3r::ConfigOptionFloatsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<int>, Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingleNullable<int>, Slic3r::ConfigOptionIntNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<int>, Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<int>, Slic3r::ConfigOptionIntsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<std::string>, Slic3r::ConfigOptionString)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
@ -60,9 +61,9 @@ namespace Slic3r {
|
||||
template<class Archive> void serialize(Archive& ar) { ar(this->value); ar(this->percent); }
|
||||
};
|
||||
|
||||
inline bool operator==(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return l.value == r.value && l.percent == r.percent; }
|
||||
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return !(l == r); }
|
||||
inline bool operator< (const FloatOrPercent& l, const FloatOrPercent& r) throw() { return l.value < r.value || (l.value == r.value && int(l.percent) < int(r.percent)); }
|
||||
inline bool operator==(const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return l.value == r.value && l.percent == r.percent; }
|
||||
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return !(l == r); }
|
||||
inline bool operator< (const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return l.value < r.value || (l.value == r.value && int(l.percent) < int(r.percent)); }
|
||||
}
|
||||
|
||||
namespace std {
|
||||
@ -319,8 +320,56 @@ public:
|
||||
typedef ConfigOption* ConfigOptionPtr;
|
||||
typedef const ConfigOption* ConfigOptionConstPtr;
|
||||
|
||||
// Nill value will be defined in specializations
|
||||
template<class T, class En = void> struct NilValueTempl
|
||||
{
|
||||
using NilType = T;
|
||||
static_assert(always_false<T>::value, "Type has no well defined nil value");
|
||||
};
|
||||
|
||||
template<class T> struct NilValueTempl<T, std::enable_if_t<std::is_integral_v<T>, void>> {
|
||||
using NilType = T;
|
||||
static constexpr auto value = std::numeric_limits<T>::max();
|
||||
};
|
||||
|
||||
template<> struct NilValueTempl<bool> : public NilValueTempl<int>{};
|
||||
|
||||
// For enums the nil is the max value of the underlying type.
|
||||
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());
|
||||
};
|
||||
|
||||
template<class T> struct NilValueTempl<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
|
||||
using NilType = T;
|
||||
static constexpr auto value = std::numeric_limits<T>::quiet_NaN();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct NilValueTempl<FloatOrPercent> : public NilValueTempl<double> {};
|
||||
|
||||
template<> struct NilValueTempl<std::string> {
|
||||
using NilType = const char *;
|
||||
|
||||
static constexpr const char* value = "";
|
||||
};
|
||||
|
||||
template<int N, class T> struct NilValueTempl<Vec<N, T>> {
|
||||
using NilType = Vec<N, T>;
|
||||
// No constexpr for Vec<N, T>
|
||||
static inline const Vec<N, T> value = Vec<N, T>::Ones() * NilValueTempl<remove_cvref_t<T>>::value;
|
||||
};
|
||||
|
||||
template<class T> using NilType = typename NilValueTempl<remove_cvref_t<T>>::NilType;
|
||||
|
||||
// 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>
|
||||
template <class T, bool NULLABLE = false>
|
||||
class ConfigOptionSingle : public ConfigOption {
|
||||
public:
|
||||
T value;
|
||||
@ -331,16 +380,18 @@ public:
|
||||
{
|
||||
if (rhs->type() != this->type())
|
||||
throw ConfigurationError("ConfigOptionSingle: Assigning an incompatible type");
|
||||
assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs));
|
||||
this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
|
||||
assert(dynamic_cast<const ConfigOptionSingle*>(rhs));
|
||||
this->value = static_cast<const ConfigOptionSingle*>(rhs)->value;
|
||||
}
|
||||
|
||||
bool operator==(const ConfigOption &rhs) const override
|
||||
{
|
||||
if (rhs.type() != this->type())
|
||||
throw ConfigurationError("ConfigOptionSingle: Comparing incompatible types");
|
||||
assert(dynamic_cast<const ConfigOptionSingle<T>*>(&rhs));
|
||||
return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value;
|
||||
assert(dynamic_cast<const ConfigOptionSingle*>(&rhs));
|
||||
if (this->is_nil() && rhs.is_nil())
|
||||
return true;
|
||||
return this->value == static_cast<const ConfigOptionSingle*>(&rhs)->value;
|
||||
}
|
||||
|
||||
bool operator==(const T &rhs) const throw() { return this->value == rhs; }
|
||||
@ -349,11 +400,67 @@ public:
|
||||
|
||||
size_t hash() const throw() override { return std::hash<T>{}(this->value); }
|
||||
|
||||
// Is this option overridden by another option?
|
||||
// An option overrides another option if it is not nil and not equal.
|
||||
bool overriden_by(const ConfigOption *rhs) const override {
|
||||
if (this->nullable())
|
||||
throw ConfigurationError("Cannot override a nullable ConfigOption.");
|
||||
if (rhs->type() != this->type())
|
||||
throw ConfigurationError("ConfigOptionVector.overriden_by() applied to different types.");
|
||||
auto rhs_co = static_cast<const ConfigOptionSingle*>(rhs);
|
||||
if (! rhs->nullable())
|
||||
// Overridding a non-nullable object with another non-nullable object.
|
||||
return this->value != rhs_co->value;
|
||||
|
||||
return !rhs_co->is_nil() && rhs_co->value != this->value;
|
||||
}
|
||||
// Apply an override option, possibly a nullable one.
|
||||
bool apply_override(const ConfigOption *rhs) override {
|
||||
if (this->nullable())
|
||||
throw ConfigurationError("Cannot override a nullable ConfigOption.");
|
||||
if (rhs->type() != this->type())
|
||||
throw ConfigurationError("ConfigOptionVector.apply_override() applied to different types.");
|
||||
auto rhs_co = static_cast<const ConfigOptionSingle*>(rhs);
|
||||
if (! rhs->nullable()) {
|
||||
// Overridding a non-nullable object with another non-nullable object.
|
||||
if (this->value != rhs_co->value) {
|
||||
this->value = rhs_co->value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rhs_co->is_nil() && rhs_co->value != this->value) {
|
||||
this->value = rhs_co->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nullable() const override { return NULLABLE; }
|
||||
|
||||
static constexpr NilType<T> nil_value() { return NilValue<T>(); }
|
||||
|
||||
// A scalar is nil, or all values of a vector are nil.
|
||||
bool is_nil() const override
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if constexpr (NULLABLE)
|
||||
ret = this->value == nil_value();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive & ar) { ar(this->value); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using ConfigOptionSingleNullable = ConfigOptionSingle<T, true>;
|
||||
|
||||
// Value of a vector valued option (bools, ints, floats, strings, points)
|
||||
class ConfigOptionVectorBase : public ConfigOption {
|
||||
public:
|
||||
@ -572,23 +679,35 @@ private:
|
||||
template<class Archive> void serialize(Archive & ar) { ar(this->values); }
|
||||
};
|
||||
|
||||
class ConfigOptionFloat : public ConfigOptionSingle<double>
|
||||
template<bool NULLABLE = false>
|
||||
class ConfigOptionFloatTempl : public ConfigOptionSingle<double, NULLABLE>
|
||||
{
|
||||
public:
|
||||
ConfigOptionFloat() : ConfigOptionSingle<double>(0) {}
|
||||
explicit ConfigOptionFloat(double _value) : ConfigOptionSingle<double>(_value) {}
|
||||
ConfigOptionFloatTempl() : ConfigOptionSingle<double, NULLABLE>(0) {}
|
||||
explicit ConfigOptionFloatTempl(double _value) : ConfigOptionSingle<double, NULLABLE>(_value) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coFloat; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
double getFloat() const override { return this->value; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionFloat(*this); }
|
||||
bool operator==(const ConfigOptionFloat &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionFloat &rhs) const throw() { return this->value < rhs.value; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionFloatTempl(*this); }
|
||||
bool operator==(const ConfigOptionFloatTempl &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionFloatTempl &rhs) const throw() { return this->value < rhs.value; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << this->value;
|
||||
double v = this->value;
|
||||
|
||||
if (std::isfinite(v))
|
||||
ss << v;
|
||||
else if (std::isnan(v)) {
|
||||
if (NULLABLE)
|
||||
ss << "nil";
|
||||
else
|
||||
throw ConfigurationError("Serializing NaN");
|
||||
} else
|
||||
throw ConfigurationError("Serializing invalid number");
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -596,19 +715,33 @@ public:
|
||||
{
|
||||
UNUSED(append);
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
|
||||
if (str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->value = this->nil_value();
|
||||
else
|
||||
throw ConfigurationError("Deserializing nil into a non-nullable object");
|
||||
} else {
|
||||
iss >> this->value;
|
||||
}
|
||||
|
||||
return !iss.fail();
|
||||
}
|
||||
|
||||
ConfigOptionFloat& operator=(const ConfigOption *opt)
|
||||
ConfigOptionFloatTempl& operator=(const ConfigOption *opt)
|
||||
{
|
||||
this->set(opt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_nil() const override
|
||||
{
|
||||
return std::isnan(this->value);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double>>(this)); }
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double, NULLABLE>>(this)); }
|
||||
};
|
||||
|
||||
template<bool NULLABLE>
|
||||
@ -734,27 +867,37 @@ private:
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<double>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionFloat = ConfigOptionFloatTempl<false>;
|
||||
using ConfigOptionFloatNullable = ConfigOptionFloatTempl<true>;
|
||||
using ConfigOptionFloats = ConfigOptionFloatsTempl<false>;
|
||||
using ConfigOptionFloatsNullable = ConfigOptionFloatsTempl<true>;
|
||||
|
||||
class ConfigOptionInt : public ConfigOptionSingle<int>
|
||||
template<bool NULLABLE = false>
|
||||
class ConfigOptionIntTempl : public ConfigOptionSingle<int, NULLABLE>
|
||||
{
|
||||
public:
|
||||
ConfigOptionInt() : ConfigOptionSingle<int>(0) {}
|
||||
explicit ConfigOptionInt(int value) : ConfigOptionSingle<int>(value) {}
|
||||
explicit ConfigOptionInt(double _value) : ConfigOptionSingle<int>(int(floor(_value + 0.5))) {}
|
||||
ConfigOptionIntTempl() : ConfigOptionSingle<int, NULLABLE>(0) {}
|
||||
explicit ConfigOptionIntTempl(int value) : ConfigOptionSingle<int, NULLABLE>(value) {}
|
||||
explicit ConfigOptionIntTempl(double _value) : ConfigOptionSingle<int, NULLABLE>(int(floor(_value + 0.5))) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coInt; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
int getInt() const override { return this->value; }
|
||||
void setInt(int val) override { this->value = val; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
|
||||
bool operator==(const ConfigOptionInt &rhs) const throw() { return this->value == rhs.value; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionIntTempl(*this); }
|
||||
bool operator==(const ConfigOptionIntTempl &rhs) const throw() { return this->value == rhs.value; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << this->value;
|
||||
if (this->value == this->nil_value()) {
|
||||
if (NULLABLE)
|
||||
ss << "nil";
|
||||
else
|
||||
throw ConfigurationError("Serializing NaN");
|
||||
} else
|
||||
ss << this->value;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -762,11 +905,20 @@ public:
|
||||
{
|
||||
UNUSED(append);
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
|
||||
if (str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->value = this->nil_value();
|
||||
else
|
||||
throw ConfigurationError("Deserializing nil into a non-nullable object");
|
||||
} else {
|
||||
iss >> this->value;
|
||||
}
|
||||
|
||||
return !iss.fail();
|
||||
}
|
||||
|
||||
ConfigOptionInt& operator=(const ConfigOption *opt)
|
||||
ConfigOptionIntTempl& operator=(const ConfigOption *opt)
|
||||
{
|
||||
this->set(opt);
|
||||
return *this;
|
||||
@ -774,9 +926,12 @@ public:
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<int>>(this)); }
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<int, NULLABLE>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionInt = ConfigOptionIntTempl<false>;
|
||||
using ConfigOptionIntNullable = ConfigOptionIntTempl<true>;
|
||||
|
||||
template<bool NULLABLE>
|
||||
class ConfigOptionIntsTempl : public ConfigOptionVector<int>
|
||||
{
|
||||
@ -1860,6 +2015,8 @@ public:
|
||||
template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloat: { auto opt = new ConfigOptionFloatNullable(); archive(*opt); return opt; }
|
||||
case coInt: { auto opt = new ConfigOptionIntNullable(); archive(*opt); return opt; }
|
||||
case coFloats: { auto opt = new ConfigOptionFloatsNullable(); archive(*opt); return opt; }
|
||||
case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; }
|
||||
case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); return opt; }
|
||||
@ -1892,6 +2049,8 @@ public:
|
||||
template<class Archive> ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const {
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloat: archive(*static_cast<const ConfigOptionFloatNullable*>(opt)); break;
|
||||
case coInt: archive(*static_cast<const ConfigOptionIntNullable*>(opt)); break;
|
||||
case coFloats: archive(*static_cast<const ConfigOptionFloatsNullable*>(opt)); break;
|
||||
case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break;
|
||||
case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(opt));break;
|
||||
|
@ -45,8 +45,9 @@ namespace {
|
||||
std::string to_ini(const ConfMap &m)
|
||||
{
|
||||
std::string ret;
|
||||
for (auto ¶m : m) ret += param.first + " = " + param.second + "\n";
|
||||
|
||||
for (auto ¶m : m)
|
||||
ret += param.first + " = " + param.second + "\n";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ std::pair<DynamicPrintConfig, ConfigSubstitutions> extract_profile(
|
||||
// as output argument then replace it with the readed profile to report
|
||||
// that it was empty.
|
||||
profile_use = profile_in.empty() ? profile_out : profile_in;
|
||||
profile_out = profile_in;
|
||||
profile_out += std::move(profile_in);
|
||||
|
||||
return {profile_use, std::move(config_substitutions)};
|
||||
}
|
||||
|
@ -606,7 +606,25 @@ static std::vector<std::string> s_Preset_sla_material_options {
|
||||
"material_print_speed",
|
||||
"default_sla_material_profile",
|
||||
"compatible_prints", "compatible_prints_condition",
|
||||
"compatible_printers", "compatible_printers_condition", "inherits"
|
||||
"compatible_printers", "compatible_printers_condition", "inherits",
|
||||
|
||||
// overriden options
|
||||
"material_ow_support_head_front_diameter",
|
||||
"material_ow_support_head_penetration",
|
||||
"material_ow_support_head_width",
|
||||
"material_ow_support_pillar_diameter",
|
||||
|
||||
"material_ow_branchingsupport_head_front_diameter",
|
||||
"material_ow_branchingsupport_head_penetration",
|
||||
"material_ow_branchingsupport_head_width",
|
||||
"material_ow_branchingsupport_pillar_diameter",
|
||||
|
||||
"material_ow_support_points_density_relative",
|
||||
|
||||
"material_ow_relative_correction_x",
|
||||
"material_ow_relative_correction_y",
|
||||
"material_ow_relative_correction_z",
|
||||
"material_ow_elefant_foot_compensation"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_sla_printer_options {
|
||||
|
@ -74,6 +74,8 @@ PresetBundle::PresetBundle() :
|
||||
this->sla_materials.default_preset().config.optptr("sla_material_settings_id", true);
|
||||
this->sla_materials.default_preset().compatible_printers_condition();
|
||||
this->sla_materials.default_preset().inherits();
|
||||
// Set all the nullable values to nils.
|
||||
this->sla_materials.default_preset().config.null_nullables();
|
||||
|
||||
this->sla_prints.default_preset().config.optptr("sla_print_settings_id", true);
|
||||
this->sla_prints.default_preset().config.opt_string("output_filename_format", true) = "[input_filename_base].sl1";
|
||||
@ -693,7 +695,8 @@ void PresetBundle::export_selections(AppConfig &config)
|
||||
//assert(this->printers.get_edited_preset().printer_technology() != ptFFF || extruders_filaments.size() > 1 || filaments.get_selected_preset().alias == extruders_filaments.front().get_selected_preset()->alias);
|
||||
config.clear_section("presets");
|
||||
config.set("presets", "print", prints.get_selected_preset_name());
|
||||
config.set("presets", "filament", extruders_filaments.front().get_selected_preset_name());
|
||||
if (!extruders_filaments.empty()) // Tomas: To prevent crash with SLA overrides
|
||||
config.set("presets", "filament", extruders_filaments.front().get_selected_preset_name());
|
||||
for (unsigned i = 1; i < extruders_filaments.size(); ++i) {
|
||||
char name[64];
|
||||
sprintf(name, "filament_%u", i);
|
||||
|
@ -4301,6 +4301,35 @@ void PrintConfigDef::init_sla_params()
|
||||
def->min = float(SCALING_FACTOR);
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.001));
|
||||
|
||||
// Declare retract values for material profile, overriding the print and printer profiles.
|
||||
for (const char* opt_key : {
|
||||
// float
|
||||
"support_head_front_diameter", "branchingsupport_head_front_diameter",
|
||||
"support_head_penetration", "branchingsupport_head_penetration",
|
||||
"support_head_width", "branchingsupport_head_width",
|
||||
"support_pillar_diameter", "branchingsupport_pillar_diameter",
|
||||
"relative_correction_x", "relative_correction_y", "relative_correction_z",
|
||||
"elefant_foot_compensation",
|
||||
// int
|
||||
"support_points_density_relative"
|
||||
}) {
|
||||
auto it_opt = options.find(opt_key);
|
||||
assert(it_opt != options.end());
|
||||
def = this->add_nullable(std::string("material_ow_") + opt_key, it_opt->second.type);
|
||||
def->label = it_opt->second.label;
|
||||
def->full_label = it_opt->second.full_label;
|
||||
def->tooltip = it_opt->second.tooltip;
|
||||
def->sidetext = it_opt->second.sidetext;
|
||||
def->min = it_opt->second.min;
|
||||
def->max = it_opt->second.max;
|
||||
def->mode = it_opt->second.mode;
|
||||
switch (def->type) {
|
||||
case coFloat: def->set_default_value(new ConfigOptionFloatNullable{ it_opt->second.default_value->getFloat() }); break;
|
||||
case coInt: def->set_default_value(new ConfigOptionIntNullable{ it_opt->second.default_value->getInt() }); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
|
@ -1117,6 +1117,20 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, material_correction_y))
|
||||
((ConfigOptionFloat, material_correction_z))
|
||||
((ConfigOptionEnum<SLAMaterialSpeed>, material_print_speed))
|
||||
((ConfigOptionFloatNullable, material_ow_support_pillar_diameter))
|
||||
((ConfigOptionFloatNullable, material_ow_branchingsupport_pillar_diameter))
|
||||
((ConfigOptionFloatNullable, material_ow_support_head_front_diameter))
|
||||
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_front_diameter))
|
||||
((ConfigOptionFloatNullable, material_ow_support_head_penetration))
|
||||
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_penetration))
|
||||
((ConfigOptionFloatNullable, material_ow_support_head_width))
|
||||
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_width))
|
||||
((ConfigOptionIntNullable, material_ow_support_points_density_relative))
|
||||
|
||||
((ConfigOptionFloatNullable, material_ow_elefant_foot_compensation))
|
||||
((ConfigOptionFloatNullable, material_ow_relative_correction_x))
|
||||
((ConfigOptionFloatNullable, material_ow_relative_correction_y))
|
||||
((ConfigOptionFloatNullable, material_ow_relative_correction_z))
|
||||
)
|
||||
|
||||
PRINT_CONFIG_CLASS_DEFINE(
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "CSGMesh/CSGMeshCopy.hpp"
|
||||
#include "CSGMesh/PerformCSGMeshBooleans.hpp"
|
||||
#include "format.hpp"
|
||||
#include "StaticMap.hpp"
|
||||
|
||||
#include "Format/SLAArchiveFormatRegistry.hpp"
|
||||
|
||||
@ -202,6 +203,63 @@ std::vector<ObjectID> SLAPrint::print_object_ids() const
|
||||
return out;
|
||||
}
|
||||
|
||||
static t_config_option_keys print_config_diffs(const StaticPrintConfig ¤t_config,
|
||||
const DynamicPrintConfig &new_full_config,
|
||||
DynamicPrintConfig &material_overrides)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
static const constexpr StaticSet overriden_keys = {
|
||||
"support_head_front_diameter"sv,
|
||||
"support_head_penetration"sv,
|
||||
"support_head_width"sv,
|
||||
"support_pillar_diameter"sv,
|
||||
"branchingsupport_head_front_diameter"sv,
|
||||
"branchingsupport_head_penetration"sv,
|
||||
"branchingsupport_head_width"sv,
|
||||
"branchingsupport_pillar_diameter"sv,
|
||||
"support_points_density_relative"sv,
|
||||
"relative_correction_x"sv,
|
||||
"relative_correction_y"sv,
|
||||
"relative_correction_z"sv,
|
||||
"elefant_foot_compensation"sv,
|
||||
};
|
||||
|
||||
static constexpr auto material_ow_prefix = "material_ow_";
|
||||
|
||||
t_config_option_keys print_diff;
|
||||
for (const t_config_option_key &opt_key : current_config.keys()) {
|
||||
const ConfigOption *opt_old = current_config.option(opt_key);
|
||||
assert(opt_old != nullptr);
|
||||
const ConfigOption *opt_new = new_full_config.option(opt_key);
|
||||
// assert(opt_new != nullptr);
|
||||
if (opt_new == nullptr)
|
||||
//FIXME This may happen when executing some test cases.
|
||||
continue;
|
||||
const ConfigOption *opt_new_override = std::binary_search(overriden_keys.begin(), overriden_keys.end(), opt_key) ? new_full_config.option(material_ow_prefix + opt_key) : nullptr;
|
||||
if (opt_new_override != nullptr && ! opt_new_override->is_nil()) {
|
||||
// An override is available at some of the material presets.
|
||||
bool overriden = opt_new->overriden_by(opt_new_override);
|
||||
if (overriden || *opt_old != *opt_new) {
|
||||
auto opt_copy = opt_new->clone();
|
||||
opt_copy->apply_override(opt_new_override);
|
||||
bool changed = *opt_old != *opt_copy;
|
||||
if (changed)
|
||||
print_diff.emplace_back(opt_key);
|
||||
if (changed || overriden) {
|
||||
// overrides will be applied to the placeholder parser, which layers these parameters over full_print_config.
|
||||
material_overrides.set_key_value(opt_key, opt_copy);
|
||||
} else
|
||||
delete opt_copy;
|
||||
}
|
||||
} else if (*opt_new != *opt_old)
|
||||
print_diff.emplace_back(opt_key);
|
||||
}
|
||||
|
||||
return print_diff;
|
||||
}
|
||||
|
||||
|
||||
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig config)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@ -214,12 +272,15 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
||||
config.option("printer_settings_id", true);
|
||||
config.option("physical_printer_settings_id", true);
|
||||
// Collect changes to print config.
|
||||
DynamicPrintConfig mat_overrides;
|
||||
t_config_option_keys print_diff = m_print_config.diff(config);
|
||||
t_config_option_keys printer_diff = m_printer_config.diff(config);
|
||||
t_config_option_keys printer_diff = print_config_diffs(m_printer_config, config, mat_overrides);
|
||||
t_config_option_keys material_diff = m_material_config.diff(config);
|
||||
t_config_option_keys object_diff = m_default_object_config.diff(config);
|
||||
t_config_option_keys object_diff = print_config_diffs(m_default_object_config, config, mat_overrides);
|
||||
t_config_option_keys placeholder_parser_diff = m_placeholder_parser.config_diff(config);
|
||||
|
||||
config.apply(mat_overrides, true);
|
||||
|
||||
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
|
||||
unsigned int apply_status = APPLY_STATUS_UNCHANGED;
|
||||
auto update_apply_status = [&apply_status](bool invalidated)
|
||||
@ -603,6 +664,27 @@ std::string SLAPrint::validate(std::vector<std::string>*) const
|
||||
if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max)
|
||||
return _u8L("Initial exposition time is out of printer profile bounds.");
|
||||
|
||||
for (const std::string& prefix : { "", "branching" }) {
|
||||
|
||||
double head_penetration = m_full_print_config.opt_float(prefix + "support_head_penetration");
|
||||
double head_width = m_full_print_config.opt_float(prefix + "support_head_width");
|
||||
|
||||
if (head_penetration > head_width) {
|
||||
return _u8L("Invalid Head penetration") + "\n" +
|
||||
_u8L("Head penetration should not be greater than the head width.") + "\n" +
|
||||
_u8L("Please check value of head penetration in print settings or material overrides.");
|
||||
}
|
||||
|
||||
double pinhead_d = m_full_print_config.opt_float(prefix + "support_head_front_diameter");
|
||||
double pillar_d = m_full_print_config.opt_float(prefix + "support_pillar_diameter");
|
||||
|
||||
if (pinhead_d > pillar_d) {
|
||||
return _u8L("Invalid pinhead diameter") + "\n" +
|
||||
_u8L("Pinhead front diameter should be smaller than the pillar diameter.") +
|
||||
_u8L("Please check value of pinhead front diameter in print settings or material overrides.");
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -737,66 +819,81 @@ void SLAPrint::process()
|
||||
|
||||
bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys, bool &invalidate_all_model_objects)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (opt_keys.empty())
|
||||
return false;
|
||||
|
||||
static std::unordered_set<std::string> steps_full = {
|
||||
"initial_layer_height",
|
||||
"material_correction",
|
||||
"material_correction_x",
|
||||
"material_correction_y",
|
||||
"material_correction_z",
|
||||
"material_print_speed",
|
||||
"relative_correction",
|
||||
"relative_correction_x",
|
||||
"relative_correction_y",
|
||||
"relative_correction_z",
|
||||
"absolute_correction",
|
||||
"elefant_foot_compensation",
|
||||
"elefant_foot_min_width",
|
||||
"gamma_correction"
|
||||
static constexpr StaticSet steps_full = {
|
||||
"initial_layer_height"sv,
|
||||
"material_correction"sv,
|
||||
"material_correction_x"sv,
|
||||
"material_correction_y"sv,
|
||||
"material_correction_z"sv,
|
||||
"material_print_speed"sv,
|
||||
"relative_correction"sv,
|
||||
"relative_correction_x"sv,
|
||||
"relative_correction_y"sv,
|
||||
"relative_correction_z"sv,
|
||||
"absolute_correction"sv,
|
||||
"elefant_foot_compensation"sv,
|
||||
"elefant_foot_min_width"sv,
|
||||
"gamma_correction"sv,
|
||||
};
|
||||
|
||||
// Cache the plenty of parameters, which influence the final rasterization only,
|
||||
// or they are only notes not influencing the rasterization step.
|
||||
static std::unordered_set<std::string> steps_rasterize = {
|
||||
"min_exposure_time",
|
||||
"max_exposure_time",
|
||||
"exposure_time",
|
||||
"min_initial_exposure_time",
|
||||
"max_initial_exposure_time",
|
||||
"initial_exposure_time",
|
||||
"display_width",
|
||||
"display_height",
|
||||
"display_pixels_x",
|
||||
"display_pixels_y",
|
||||
"display_mirror_x",
|
||||
"display_mirror_y",
|
||||
"display_orientation",
|
||||
"sla_archive_format",
|
||||
"sla_output_precision"
|
||||
static constexpr StaticSet steps_rasterize = {
|
||||
"min_exposure_time"sv,
|
||||
"max_exposure_time"sv,
|
||||
"exposure_time"sv,
|
||||
"min_initial_exposure_time"sv,
|
||||
"max_initial_exposure_time"sv,
|
||||
"initial_exposure_time"sv,
|
||||
"display_width"sv,
|
||||
"display_height"sv,
|
||||
"display_pixels_x"sv,
|
||||
"display_pixels_y"sv,
|
||||
"display_mirror_x"sv,
|
||||
"display_mirror_y"sv,
|
||||
"display_orientation"sv,
|
||||
"sla_archive_format"sv,
|
||||
"sla_output_precision"sv
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore = {
|
||||
"bed_shape",
|
||||
"max_print_height",
|
||||
"printer_technology",
|
||||
"output_filename_format",
|
||||
"fast_tilt_time",
|
||||
"slow_tilt_time",
|
||||
"high_viscosity_tilt_time",
|
||||
"area_fill",
|
||||
"bottle_cost",
|
||||
"bottle_volume",
|
||||
"bottle_weight",
|
||||
"material_density"
|
||||
static StaticSet steps_ignore = {
|
||||
"bed_shape"sv,
|
||||
"max_print_height"sv,
|
||||
"printer_technology"sv,
|
||||
"output_filename_format"sv,
|
||||
"fast_tilt_time"sv,
|
||||
"slow_tilt_time"sv,
|
||||
"high_viscosity_tilt_time"sv,
|
||||
"area_fill"sv,
|
||||
"bottle_cost"sv,
|
||||
"bottle_volume"sv,
|
||||
"bottle_weight"sv,
|
||||
"material_density"sv,
|
||||
"material_ow_support_pillar_diameter"sv,
|
||||
"material_ow_support_head_front_diameter"sv,
|
||||
"material_ow_support_head_penetration"sv,
|
||||
"material_ow_support_head_width"sv,
|
||||
"material_ow_branchingsupport_pillar_diameter"sv,
|
||||
"material_ow_branchingsupport_head_front_diameter"sv,
|
||||
"material_ow_branchingsupport_head_penetration"sv,
|
||||
"material_ow_branchingsupport_head_width"sv,
|
||||
"material_ow_elefant_foot_compensation"sv,
|
||||
"material_ow_support_points_density_relative"sv,
|
||||
"material_ow_relative_correction_x"sv,
|
||||
"material_ow_relative_correction_y"sv,
|
||||
"material_ow_relative_correction_z"sv
|
||||
};
|
||||
|
||||
std::vector<SLAPrintStep> steps;
|
||||
std::vector<SLAPrintObjectStep> osteps;
|
||||
bool invalidated = false;
|
||||
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
for (std::string_view opt_key : opt_keys) {
|
||||
if (steps_rasterize.find(opt_key) != steps_rasterize.end()) {
|
||||
// These options only affect the final rasterization, or they are just notes without influence on the output,
|
||||
// so there is nothing to invalidate.
|
||||
@ -874,7 +971,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
} else if (
|
||||
opt_key == "support_points_density_relative"
|
||||
|| opt_key == "support_enforcers_only"
|
||||
|| opt_key == "support_points_minimal_distance") {
|
||||
|| opt_key == "support_points_minimal_distance"
|
||||
) {
|
||||
steps.emplace_back(slaposSupportPoints);
|
||||
} else if (
|
||||
opt_key == "support_head_front_diameter"
|
||||
@ -893,7 +991,6 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
|| opt_key == "support_max_bridge_length"
|
||||
|| opt_key == "support_max_pillar_link_distance"
|
||||
|| opt_key == "support_base_safety_distance"
|
||||
|
||||
|| opt_key == "branchingsupport_head_front_diameter"
|
||||
|| opt_key == "branchingsupport_head_penetration"
|
||||
|| opt_key == "branchingsupport_head_width"
|
||||
@ -910,7 +1007,6 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
|| opt_key == "branchingsupport_max_bridge_length"
|
||||
|| opt_key == "branchingsupport_max_pillar_link_distance"
|
||||
|| opt_key == "branchingsupport_base_safety_distance"
|
||||
|
||||
|| opt_key == "pad_object_gap"
|
||||
) {
|
||||
steps.emplace_back(slaposSupportTree);
|
||||
|
@ -614,7 +614,15 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
|
||||
// the density config value is in percents:
|
||||
config.density_relative = float(cfg.support_points_density_relative / 100.f);
|
||||
config.minimal_distance = float(cfg.support_points_minimal_distance);
|
||||
config.head_diameter = float(cfg.support_head_front_diameter);
|
||||
switch (cfg.support_tree_type) {
|
||||
case sla::SupportTreeType::Default:
|
||||
case sla::SupportTreeType::Organic:
|
||||
config.head_diameter = float(cfg.support_head_front_diameter);
|
||||
break;
|
||||
case sla::SupportTreeType::Branching:
|
||||
config.head_diameter = float(cfg.branchingsupport_head_front_diameter);
|
||||
break;
|
||||
}
|
||||
|
||||
// scaling for the sub operations
|
||||
double d = objectstep_scale * OBJ_STEP_LEVELS[slaposSupportPoints] / 100.0;
|
||||
|
@ -347,36 +347,6 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
toggle_field("thin_walls", !have_arachne);
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||
{
|
||||
double head_penetration = config->opt_float("support_head_penetration");
|
||||
double head_width = config->opt_float("support_head_width");
|
||||
if (head_penetration > head_width) {
|
||||
wxString msg_text = _(L("Head penetration should not be greater than the head width."));
|
||||
|
||||
MessageDialog dialog(m_msg_dlg_parent, msg_text, _(L("Invalid Head penetration")), wxICON_WARNING | wxOK);
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
if (dialog.ShowModal() == wxID_OK) {
|
||||
new_conf.set_key_value("support_head_penetration", new ConfigOptionFloat(head_width));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
}
|
||||
|
||||
double pinhead_d = config->opt_float("support_head_front_diameter");
|
||||
double pillar_d = config->opt_float("support_pillar_diameter");
|
||||
if (pinhead_d > pillar_d) {
|
||||
wxString msg_text = _(L("Pinhead diameter should be smaller than the pillar diameter."));
|
||||
|
||||
MessageDialog dialog(m_msg_dlg_parent, msg_text, _(L("Invalid pinhead diameter")), wxICON_WARNING | wxOK);
|
||||
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
if (dialog.ShowModal() == wxID_OK) {
|
||||
new_conf.set_key_value("support_head_front_diameter", new ConfigOptionFloat(pillar_d / 2.0));
|
||||
apply(config, &new_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManipulation::toggle_print_sla_options(DynamicPrintConfig* config)
|
||||
{
|
||||
bool supports_en = config->opt_bool("supports_enable");
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
void toggle_print_fff_options(DynamicPrintConfig* config);
|
||||
|
||||
// SLA print
|
||||
void update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config = false);
|
||||
void toggle_print_sla_options(DynamicPrintConfig* config);
|
||||
|
||||
bool is_initialized_support_material_overhangs_queried() { return m_is_initialized_support_material_overhangs_queried; }
|
||||
|
@ -856,6 +856,7 @@ void SpinCtrl::BUILD() {
|
||||
switch (m_opt.type) {
|
||||
case coInt:
|
||||
default_value = m_opt.default_value->getInt();
|
||||
m_last_meaningful_value = default_value;
|
||||
break;
|
||||
case coInts:
|
||||
{
|
||||
|
@ -194,8 +194,11 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
||||
ConfigOptionBools* vec_new = new ConfigOptionBools{ boost::any_cast<unsigned char>(value) != 0 };
|
||||
config.option<ConfigOptionBools>(opt_key)->set_at(vec_new, opt_index, 0);
|
||||
break;}
|
||||
case coInt:
|
||||
config.set_key_value(opt_key, new ConfigOptionInt(boost::any_cast<int>(value)));
|
||||
case coInt: {
|
||||
//config.set_key_value(opt_key, new ConfigOptionInt(boost::any_cast<int>(value)));
|
||||
int& val_new = config.opt_int(opt_key);
|
||||
val_new = boost::any_cast<int>(value);
|
||||
}
|
||||
break;
|
||||
case coInts:{
|
||||
ConfigOptionInts* vec_new = new ConfigOptionInts{ boost::any_cast<int>(value) };
|
||||
|
@ -261,8 +261,8 @@ void ObjectSettings::update_config_values(ModelConfig* config)
|
||||
}
|
||||
|
||||
main_config.apply(config->get(), true);
|
||||
printer_technology == ptFFF ? config_manipulation.update_print_fff_config(&main_config) :
|
||||
config_manipulation.update_print_sla_config(&main_config) ;
|
||||
if (printer_technology == ptFFF)
|
||||
config_manipulation.update_print_fff_config(&main_config);
|
||||
|
||||
printer_technology == ptFFF ? config_manipulation.toggle_print_fff_options(&main_config) :
|
||||
config_manipulation.toggle_print_sla_options(&main_config) ;
|
||||
|
@ -867,6 +867,16 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
{
|
||||
switch (opt->type)
|
||||
{
|
||||
case coFloat:
|
||||
if (config.option(opt_key)->is_nil())
|
||||
ret = _L("N/A");
|
||||
else
|
||||
ret = double_to_string(config.option<ConfigOptionFloatNullable>(opt_key)->value);
|
||||
|
||||
break;
|
||||
case coInt:
|
||||
ret = config.option<ConfigOptionIntNullable>(opt_key)->value;
|
||||
break;
|
||||
case coPercents:
|
||||
case coFloats: {
|
||||
if (config.option(opt_key)->is_nil())
|
||||
|
@ -206,6 +206,7 @@ public:
|
||||
|
||||
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
|
||||
const std::vector<Line>& get_lines() { return m_lines; }
|
||||
Line* get_last_line() { return m_lines.empty() ? nullptr : &m_lines[m_lines.size()-1]; }
|
||||
bool is_legend_line();
|
||||
// if we have to set the same control alignment for different option groups,
|
||||
// we have to set same max contrtol width to all of them
|
||||
|
@ -2640,6 +2640,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
config.apply(loaded_printer_technology == ptFFF ?
|
||||
static_cast<const ConfigBase&>(FullPrintConfig::defaults()) :
|
||||
static_cast<const ConfigBase&>(SLAFullPrintConfig::defaults()));
|
||||
// Set all the nullable values in defaults to nils.
|
||||
config.null_nullables();
|
||||
// and place the loaded config over the base.
|
||||
config += std::move(config_loaded);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
|
||||
|
||||
int cnt = 0;
|
||||
|
||||
if ( type != Preset::TYPE_FILAMENT && !PresetCollection::is_independent_from_extruder_number_option(opt_key) )
|
||||
if ( type != Preset::TYPE_FILAMENT && type != Preset::TYPE_SLA_MATERIAL && !PresetCollection::is_independent_from_extruder_number_option(opt_key) )
|
||||
switch (config->option(opt_key)->type())
|
||||
{
|
||||
case coInts: change_opt_key<ConfigOptionInts >(opt_key, config, cnt); break;
|
||||
|
@ -687,7 +687,7 @@ void Tab::init_options_list()
|
||||
m_options_list.clear();
|
||||
|
||||
for (const std::string& opt_key : m_config->keys())
|
||||
emplace_option(opt_key, m_type != Preset::TYPE_FILAMENT && !PresetCollection::is_independent_from_extruder_number_option(opt_key));
|
||||
emplace_option(opt_key, m_type != Preset::TYPE_FILAMENT && m_type != Preset::TYPE_SLA_MATERIAL && !PresetCollection::is_independent_from_extruder_number_option(opt_key));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -1960,7 +1960,7 @@ void TabFilament::update_line_with_near_label_widget(ConfigOptionsGroupShp optgr
|
||||
field->toggle(is_checked);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> option_keys {
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> filament_overrides_option_keys {
|
||||
{"Travel lift", {
|
||||
"filament_retract_lift",
|
||||
"filament_travel_ramping_lift",
|
||||
@ -1992,7 +1992,7 @@ void TabFilament::add_filament_overrides_page()
|
||||
|
||||
const int extruder_idx = 0; // #ys_FIXME
|
||||
|
||||
for (const auto&[title, keys] : option_keys) {
|
||||
for (const auto&[title, keys] : filament_overrides_option_keys) {
|
||||
ConfigOptionsGroupShp optgroup = page->new_optgroup(L(title));
|
||||
for (const std::string& opt_key : keys) {
|
||||
create_line_with_near_label_widget(optgroup, opt_key, extruder_idx);
|
||||
@ -2038,7 +2038,7 @@ void TabFilament::update_filament_overrides_page()
|
||||
|| m_config->opt_float("filament_retract_lift", extruder_idx) > 0
|
||||
);
|
||||
|
||||
for (const auto&[title, keys] : option_keys) {
|
||||
for (const auto&[title, keys] : filament_overrides_option_keys) {
|
||||
std::optional<ConfigOptionsGroupShp> optgroup{get_option_group(page, title)};
|
||||
if (!optgroup) {
|
||||
continue;
|
||||
@ -5351,6 +5351,8 @@ void TabSLAMaterial::build()
|
||||
|
||||
optgroup->append_line(line);
|
||||
|
||||
add_material_overrides_page();
|
||||
|
||||
page = add_options_page(L("Notes"), "note");
|
||||
optgroup = page->new_optgroup(L("Notes"), 0);
|
||||
optgroup->label_width = 0;
|
||||
@ -5391,6 +5393,9 @@ void TabSLAMaterial::toggle_options()
|
||||
const Preset ¤t_printer = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
std::string model = current_printer.config.opt_string("printer_model");
|
||||
m_config_manipulation.toggle_field("material_print_speed", model != "SL1");
|
||||
|
||||
if (m_active_page->title() == "Material Overrides")
|
||||
update_material_overrides_page();
|
||||
}
|
||||
|
||||
void TabSLAMaterial::update()
|
||||
@ -5398,6 +5403,8 @@ void TabSLAMaterial::update()
|
||||
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF)
|
||||
return;
|
||||
|
||||
toggle_options();
|
||||
|
||||
update_description_lines();
|
||||
Layout();
|
||||
|
||||
@ -5412,13 +5419,14 @@ void TabSLAMaterial::update()
|
||||
|
||||
static void add_options_into_line(ConfigOptionsGroupShp &optgroup,
|
||||
const std::vector<SamePair<std::string>> &prefixes,
|
||||
const std::string &optkey)
|
||||
const std::string &optkey,
|
||||
const std::string &preprefix = std::string())
|
||||
{
|
||||
auto opt = optgroup->get_option(prefixes.front().first + optkey);
|
||||
auto opt = optgroup->get_option(preprefix + prefixes.front().first + optkey);
|
||||
Line line{ opt.opt.label, "" };
|
||||
line.full_width = 1;
|
||||
for (auto &prefix : prefixes) {
|
||||
opt = optgroup->get_option(prefix.first + optkey);
|
||||
opt = optgroup->get_option(preprefix + prefix.first + optkey);
|
||||
opt.opt.label = prefix.second;
|
||||
opt.opt.width = 12; // TODO
|
||||
line.append_option(opt);
|
||||
@ -5464,6 +5472,163 @@ void TabSLAPrint::build_sla_support_params(const std::vector<SamePair<std::strin
|
||||
add_options_into_line(optgroup, prefixes, "support_max_pillar_link_distance");
|
||||
}
|
||||
|
||||
static std::vector<std::string> get_override_opt_kyes_for_line(const std::string& title, const std::string& key)
|
||||
{
|
||||
const std::string preprefix = "material_ow_";
|
||||
|
||||
std::vector<std::string> opt_keys;
|
||||
opt_keys.reserve(3);
|
||||
|
||||
if (title == "Support head" || title == "Support pillar") {
|
||||
for (auto& prefix : { "", "branching" })
|
||||
opt_keys.push_back(preprefix + prefix + key);
|
||||
}
|
||||
else if (key == "relative_correction") {
|
||||
for (auto& axis : { "x", "y", "z" })
|
||||
opt_keys.push_back(preprefix + key + "_" + char(axis[0]));
|
||||
}
|
||||
else
|
||||
opt_keys.push_back(preprefix + key);
|
||||
|
||||
return opt_keys;
|
||||
}
|
||||
|
||||
void TabSLAMaterial::create_line_with_near_label_widget(ConfigOptionsGroupShp optgroup, const std::string& key)
|
||||
{
|
||||
if (optgroup->title == "Support head" || optgroup->title == "Support pillar")
|
||||
add_options_into_line(optgroup, { {"", L("Default")}, {"branching", L("Branching")} }, key, "material_ow_");
|
||||
else {
|
||||
const std::string opt_key = std::string("material_ow_") + key;
|
||||
if (key == "relative_correction") {
|
||||
Line line = Line{ m_preset_bundle->printers.get_edited_preset().config.def()->get("relative_correction")->full_label, "" };
|
||||
for (auto& axis : { "X", "Y", "Z" }) {
|
||||
auto opt = optgroup->get_option(opt_key + "_" + char(std::tolower(axis[0])));
|
||||
opt.opt.label = axis;
|
||||
line.append_option(opt);
|
||||
}
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
else
|
||||
optgroup->append_single_option_line(opt_key);
|
||||
}
|
||||
|
||||
Line* line = optgroup->get_last_line();
|
||||
if (!line)
|
||||
return;
|
||||
|
||||
line->near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), key](wxWindow* parent) {
|
||||
wxWindow* check_box = CheckBox::GetNewWin(parent);
|
||||
wxGetApp().UpdateDarkUI(check_box);
|
||||
|
||||
check_box->Bind(wxEVT_CHECKBOX, [this, optgroup_wk, key](wxCommandEvent& evt) {
|
||||
const bool is_checked = evt.IsChecked();
|
||||
if (auto optgroup_sh = optgroup_wk.lock(); optgroup_sh) {
|
||||
auto opt_keys = get_override_opt_kyes_for_line(optgroup_sh->title.ToStdString(), key);
|
||||
for (const std::string& opt_key : opt_keys)
|
||||
if (Field* field = optgroup_sh->get_fieldc(opt_key, 0); field != nullptr) {
|
||||
field->toggle(is_checked);
|
||||
if (is_checked)
|
||||
field->set_last_meaningful_value();
|
||||
else
|
||||
field->set_na_value();
|
||||
}
|
||||
}
|
||||
|
||||
toggle_options();
|
||||
});
|
||||
|
||||
m_overrides_options[key] = check_box;
|
||||
return check_box;
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> material_overrides_option_keys{
|
||||
{"Support head", {
|
||||
"support_head_front_diameter",
|
||||
"support_head_penetration",
|
||||
"support_head_width"
|
||||
}},
|
||||
{"Support pillar", {
|
||||
"support_pillar_diameter",
|
||||
}},
|
||||
{"Automatic generation", {
|
||||
"support_points_density_relative"
|
||||
}},
|
||||
{"Corrections", {
|
||||
"relative_correction",
|
||||
"elefant_foot_compensation"
|
||||
}}
|
||||
};
|
||||
|
||||
void TabSLAMaterial::add_material_overrides_page()
|
||||
{
|
||||
PageShp page = add_options_page(L("Material Overrides"), "wrench");
|
||||
|
||||
for (const auto& [title, keys] : material_overrides_option_keys) {
|
||||
ConfigOptionsGroupShp optgroup = page->new_optgroup(L(title));
|
||||
for (const std::string& opt_key : keys) {
|
||||
create_line_with_near_label_widget(optgroup, opt_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TabSLAMaterial::update_line_with_near_label_widget(ConfigOptionsGroupShp optgroup, const std::string& key, bool is_checked/* = true*/)
|
||||
{
|
||||
if (!m_overrides_options[key])
|
||||
return;
|
||||
|
||||
const std::string preprefix = "material_ow_";
|
||||
|
||||
std::vector<std::string> opt_keys;
|
||||
opt_keys.reserve(3);
|
||||
|
||||
if (optgroup->title == "Support head" || optgroup->title == "Support pillar") {
|
||||
for (auto& prefix : { "", "branching" }) {
|
||||
std::string opt_key = preprefix + prefix + key;
|
||||
is_checked = !m_config->option(opt_key)->is_nil();
|
||||
opt_keys.push_back(opt_key);
|
||||
}
|
||||
}
|
||||
else if (key == "relative_correction") {
|
||||
for (auto& axis : { "x", "y", "z" }) {
|
||||
std::string opt_key = preprefix + key + "_" + char(axis[0]);
|
||||
is_checked = !m_config->option(opt_key)->is_nil();
|
||||
opt_keys.push_back(opt_key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string opt_key = preprefix + key;
|
||||
is_checked = !m_config->option(opt_key)->is_nil();
|
||||
opt_keys.push_back(opt_key);
|
||||
}
|
||||
|
||||
CheckBox::SetValue(m_overrides_options[key], is_checked);
|
||||
|
||||
for (const std::string& opt_key : opt_keys) {
|
||||
Field* field = optgroup->get_field(opt_key);
|
||||
if (field != nullptr)
|
||||
field->toggle(is_checked);
|
||||
}
|
||||
}
|
||||
|
||||
void TabSLAMaterial::update_material_overrides_page()
|
||||
{
|
||||
if (!m_active_page || m_active_page->title() != "Material Overrides")
|
||||
return;
|
||||
Page* page = m_active_page;
|
||||
|
||||
for (const auto& [title, keys] : material_overrides_option_keys) {
|
||||
std::optional<ConfigOptionsGroupShp> optgroup{ get_option_group(page, title) };
|
||||
if (!optgroup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const std::string& key : keys) {
|
||||
update_line_with_near_label_widget(*optgroup, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TabSLAPrint::build()
|
||||
{
|
||||
m_presets = &m_preset_bundle->sla_prints;
|
||||
@ -5573,8 +5738,6 @@ void TabSLAPrint::update()
|
||||
|
||||
m_update_cnt++;
|
||||
|
||||
m_config_manipulation.update_print_sla_config(m_config, true);
|
||||
|
||||
update_description_lines();
|
||||
Layout();
|
||||
|
||||
|
@ -566,6 +566,12 @@ public:
|
||||
|
||||
class TabSLAMaterial : public Tab
|
||||
{
|
||||
void create_line_with_near_label_widget(ConfigOptionsGroupShp optgroup, const std::string& opt_key);
|
||||
void update_line_with_near_label_widget(ConfigOptionsGroupShp optgroup, const std::string& opt_key, bool is_checked = true);
|
||||
void add_material_overrides_page();
|
||||
void update_material_overrides_page();
|
||||
|
||||
std::map<std::string, wxWindow*> m_overrides_options;
|
||||
public:
|
||||
TabSLAMaterial(wxBookCtrlBase* parent) :
|
||||
Tab(parent, _(L("Material Settings")), Slic3r::Preset::TYPE_SLA_MATERIAL) {}
|
||||
|
@ -1095,7 +1095,7 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
||||
|
||||
switch (opt->type) {
|
||||
case coInt:
|
||||
return from_u8((boost::format("%1%") % config.opt_int(opt_key)).str());
|
||||
return from_u8((boost::format("%1%") % config.option(opt_key)->getInt()).str());
|
||||
case coInts: {
|
||||
if (is_nullable) {
|
||||
auto values = config.opt<ConfigOptionIntsNullable>(opt_key);
|
||||
@ -1140,7 +1140,7 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
||||
return _L("Undef");
|
||||
}
|
||||
case coFloat:
|
||||
return double_to_string(config.opt_float(opt_key));
|
||||
return double_to_string(config.option(opt_key)->getFloat());
|
||||
case coFloats: {
|
||||
if (is_nullable) {
|
||||
auto values = config.opt<ConfigOptionFloatsNullable>(opt_key);
|
||||
@ -1289,7 +1289,7 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
|
||||
m_tree->model->AddPreset(type, from_u8(presets->get_edited_preset().name), old_pt, from_u8(new_selected_preset));
|
||||
|
||||
// Collect dirty options.
|
||||
const bool deep_compare = type != Preset::TYPE_FILAMENT;
|
||||
const bool deep_compare = type != Preset::TYPE_FILAMENT && type != Preset::TYPE_SLA_MATERIAL;
|
||||
auto dirty_options = presets->current_dirty_options(deep_compare);
|
||||
|
||||
// process changes of extruders count
|
||||
|
Loading…
x
Reference in New Issue
Block a user