Merge branch 'ys_sla_overrides' into master_27x

This commit is contained in:
YuSanka 2024-02-05 17:00:08 +01:00
commit 91323230e6
22 changed files with 627 additions and 132 deletions

View File

@ -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)

View File

@ -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;
// Value of a single valued option (bool, int, float, string, point, enum)
// 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, 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);
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;
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);
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;

View File

@ -45,7 +45,8 @@ namespace {
std::string to_ini(const ConfMap &m)
{
std::string ret;
for (auto &param : m) ret += param.first + " = " + param.second + "\n";
for (auto &param : m)
ret += param.first + " = " + param.second + "\n";
return ret;
}

View File

@ -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)};
}

View File

@ -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 {

View File

@ -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,6 +695,7 @@ 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());
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];

View File

@ -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:

View File

@ -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(

View File

@ -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 &current_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);

View File

@ -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);
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;

View File

@ -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");

View File

@ -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; }

View File

@ -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:
{

View File

@ -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) };

View File

@ -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) ;

View File

@ -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())

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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 &current_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();

View File

@ -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) {}

View File

@ -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