diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 52a04721bd..454906ec3f 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -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) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingle) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingleNullable) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingleNullable) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionSingleNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVectorBase) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) @@ -1440,9 +1445,11 @@ CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) 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) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingle) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingleNullable) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingleNullable) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionSingleNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOption, Slic3r::ConfigOptionVectorBase) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector) @@ -1476,9 +1486,11 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::Con CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionFloat) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingleNullable, Slic3r::ConfigOptionFloatNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionFloats) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionFloatsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionInt) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingleNullable, Slic3r::ConfigOptionIntNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionInts) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionIntsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionString) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 09d283a327..24bbe7a5b1 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -60,9 +61,9 @@ namespace Slic3r { template 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 struct NilValueTempl +{ + using NilType = T; + static_assert(always_false::value, "Type has no well defined nil value"); +}; + +template struct NilValueTempl, void>> { + using NilType = T; + static constexpr auto value = std::numeric_limits::max(); +}; + +template<> struct NilValueTempl : public NilValueTempl{}; + +// For enums the nil is the max value of the underlying type. +template +struct NilValueTempl, void>> +{ + using NilType = T; + static constexpr auto value = static_cast(std::numeric_limits>::max()); +}; + +template struct NilValueTempl, void>> { + using NilType = T; + static constexpr auto value = std::numeric_limits::quiet_NaN(); +}; + +template<> +struct NilValueTempl : public NilValueTempl {}; + +template<> struct NilValueTempl { + using NilType = const char *; + + static constexpr const char* value = ""; +}; + +template struct NilValueTempl> { + using NilType = Vec; + // No constexpr for Vec + static inline const Vec value = Vec::Ones() * NilValueTempl>::value; +}; + +template using NilType = typename NilValueTempl>::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 static constexpr NilType NilValue() noexcept { return NilValueTempl>::value; } + // Value of a single valued option (bool, int, float, string, point, enum) -template +template 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*>(rhs)); - this->value = static_cast*>(rhs)->value; + assert(dynamic_cast(rhs)); + this->value = static_cast(rhs)->value; } bool operator==(const ConfigOption &rhs) const override { if (rhs.type() != this->type()) throw ConfigurationError("ConfigOptionSingle: Comparing incompatible types"); - assert(dynamic_cast*>(&rhs)); - return this->value == static_cast*>(&rhs)->value; + assert(dynamic_cast(&rhs)); + if (this->is_nil() && rhs.is_nil()) + return true; + return this->value == static_cast(&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{}(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(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(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 nil_value() { return NilValue(); } + + // 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 void serialize(Archive & ar) { ar(this->value); } }; +template +using ConfigOptionSingleNullable = ConfigOptionSingle; + // Value of a vector valued option (bools, ints, floats, strings, points) class ConfigOptionVectorBase : public ConfigOption { public: @@ -572,23 +679,35 @@ private: template void serialize(Archive & ar) { ar(this->values); } }; -class ConfigOptionFloat : public ConfigOptionSingle +template +class ConfigOptionFloatTempl : public ConfigOptionSingle { public: - ConfigOptionFloat() : ConfigOptionSingle(0) {} - explicit ConfigOptionFloat(double _value) : ConfigOptionSingle(_value) {} + ConfigOptionFloatTempl() : ConfigOptionSingle(0) {} + explicit ConfigOptionFloatTempl(double _value) : ConfigOptionSingle(_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 void serialize(Archive &ar) { ar(cereal::base_class>(this)); } + template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; template @@ -734,27 +867,37 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionFloat = ConfigOptionFloatTempl; +using ConfigOptionFloatNullable = ConfigOptionFloatTempl; using ConfigOptionFloats = ConfigOptionFloatsTempl; using ConfigOptionFloatsNullable = ConfigOptionFloatsTempl; -class ConfigOptionInt : public ConfigOptionSingle +template +class ConfigOptionIntTempl : public ConfigOptionSingle { public: - ConfigOptionInt() : ConfigOptionSingle(0) {} - explicit ConfigOptionInt(int value) : ConfigOptionSingle(value) {} - explicit ConfigOptionInt(double _value) : ConfigOptionSingle(int(floor(_value + 0.5))) {} + ConfigOptionIntTempl() : ConfigOptionSingle(0) {} + explicit ConfigOptionIntTempl(int value) : ConfigOptionSingle(value) {} + explicit ConfigOptionIntTempl(double _value) : ConfigOptionSingle(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 void serialize(Archive &ar) { ar(cereal::base_class>(this)); } + template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionInt = ConfigOptionIntTempl; +using ConfigOptionIntNullable = ConfigOptionIntTempl; + template class ConfigOptionIntsTempl : public ConfigOptionVector { @@ -1860,6 +2015,8 @@ public: template 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 ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const { if (this->nullable) { switch (this->type) { + case coFloat: archive(*static_cast(opt)); break; + case coInt: archive(*static_cast(opt)); break; case coFloats: archive(*static_cast(opt)); break; case coInts: archive(*static_cast(opt)); break; case coPercents: archive(*static_cast(opt));break; diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index 2ed898441b..f298cdf395 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -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; } diff --git a/src/libslic3r/Format/ZipperArchiveImport.cpp b/src/libslic3r/Format/ZipperArchiveImport.cpp index 426e0d3252..c366821257 100644 --- a/src/libslic3r/Format/ZipperArchiveImport.cpp +++ b/src/libslic3r/Format/ZipperArchiveImport.cpp @@ -139,7 +139,7 @@ std::pair 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)}; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 75dda312ef..f5e1aa7036 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -606,7 +606,25 @@ static std::vector 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 s_Preset_sla_printer_options { diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 943e5e9f63..7547030b68 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -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); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 34e513f571..f7ead0b0da 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -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: diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5c9bd4ee3c..f1dc6b96a4 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1117,6 +1117,20 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, material_correction_y)) ((ConfigOptionFloat, material_correction_z)) ((ConfigOptionEnum, 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( diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index f8fef6ac7b..f11ca9744f 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -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 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*) 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 &opt_keys, bool &invalidate_all_model_objects) { + using namespace std::string_view_literals; + if (opt_keys.empty()) return false; - static std::unordered_set 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 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 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 steps; std::vector 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::vectoropt_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"); diff --git a/src/slic3r/GUI/ConfigManipulation.hpp b/src/slic3r/GUI/ConfigManipulation.hpp index d9fc23351c..3e0947a21c 100644 --- a/src/slic3r/GUI/ConfigManipulation.hpp +++ b/src/slic3r/GUI/ConfigManipulation.hpp @@ -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; } diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 2470caa9b6..ef966ce874 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -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: { diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index d0c8aa5733..7c71ea4548 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -194,8 +194,11 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt ConfigOptionBools* vec_new = new ConfigOptionBools{ boost::any_cast(value) != 0 }; config.option(opt_key)->set_at(vec_new, opt_index, 0); break;} - case coInt: - config.set_key_value(opt_key, new ConfigOptionInt(boost::any_cast(value))); + case coInt: { + //config.set_key_value(opt_key, new ConfigOptionInt(boost::any_cast(value))); + int& val_new = config.opt_int(opt_key); + val_new = boost::any_cast(value); + } break; case coInts:{ ConfigOptionInts* vec_new = new ConfigOptionInts{ boost::any_cast(value) }; diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 5a1b1e0ceb..1de08c58c1 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -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) ; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index be5755974a..eb5860b451 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -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(opt_key)->value); + + break; + case coInt: + ret = config.option(opt_key)->value; + break; case coPercents: case coFloats: { if (config.option(opt_key)->is_nil()) diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index ae500c5d32..683182ec9a 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -206,6 +206,7 @@ public: wxGridSizer* get_grid_sizer() { return m_grid_sizer; } const std::vector& 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 diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e3a184639f..dcb5a52491 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2640,6 +2640,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ config.apply(loaded_printer_technology == ptFFF ? static_cast(FullPrintConfig::defaults()) : static_cast(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); } diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 35dec1f481..3febe895f6 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -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(opt_key, config, cnt); break; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 3dbab1cd1d..cb26498f42 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -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 @@ -1960,7 +1960,7 @@ void TabFilament::update_line_with_near_label_widget(ConfigOptionsGroupShp optgr field->toggle(is_checked); } -std::vector>> option_keys { +std::vector>> 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 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> &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 get_override_opt_kyes_for_line(const std::string& title, const std::string& key) +{ + const std::string preprefix = "material_ow_"; + + std::vector 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>> 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 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 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(); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 1ee13905a1..505c47b199 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -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 m_overrides_options; public: TabSLAMaterial(wxBookCtrlBase* parent) : Tab(parent, _(L("Material Settings")), Slic3r::Preset::TYPE_SLA_MATERIAL) {} diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 43239561c3..2e75869599 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -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(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(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