From f5acac102231d998fb540dbdfd9f6f94d2125230 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 8 Apr 2024 12:23:13 +0200 Subject: [PATCH] Material Settings: Added tilt parameters + "area_fill" is moved to Material Settings + "Tilt times" group is removed from SLA Printer Settings + Processed disabling/enabling of some parameters in respect to "use_tilt" + Implemented configuration option for vector of Enums --- src/libslic3r/Config.cpp | 10 +- src/libslic3r/Config.hpp | 240 ++++++++++++++++++ src/libslic3r/Preset.cpp | 9 +- src/libslic3r/PrintConfig.cpp | 321 ++++++++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 42 +++- src/libslic3r/SLAPrint.cpp | 19 ++ src/libslic3r/SLAPrintSteps.cpp | 2 +- src/slic3r/GUI/Field.cpp | 9 +- src/slic3r/GUI/GUI.cpp | 4 + src/slic3r/GUI/OptionsGroup.cpp | 6 +- src/slic3r/GUI/Search.cpp | 11 +- src/slic3r/GUI/Tab.cpp | 165 +++++++++--- src/slic3r/GUI/Tab.hpp | 2 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 10 +- 14 files changed, 807 insertions(+), 43 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 454906ec3f..871da6fcdb 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -294,6 +294,7 @@ ConfigOption* ConfigOptionDef::create_empty_option() const case coBool: return new ConfigOptionBool(); case coBools: return new ConfigOptionBools(); case coEnum: return new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map); + case coEnums: return new ConfigOptionEnumsGeneric(this->enum_def->m_enum_keys_map); default: throw ConfigurationError(std::string("Unknown option type for option ") + this->label); } } @@ -304,7 +305,10 @@ ConfigOption* ConfigOptionDef::create_default_option() const if (this->default_value) return (this->default_value->type() == coEnum) ? // Special case: For a DynamicConfig, convert a templated enum to a generic enum. - new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map, this->default_value->getInt()) : + new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map, this->default_value->getInt()) : + (this->default_value->type() == coEnums) ? + // Special case: For a DynamicConfig, convert a templated enums to a generic enums. + new ConfigOptionEnumsGeneric(this->enum_def->m_enum_keys_map, this->default_value->getInts()) : this->default_value->clone(); return this->create_empty_option(); } @@ -333,7 +337,7 @@ void ConfigDef::finalize() // Validate & finalize open & closed enums. for (std::pair &kvp : options) { ConfigOptionDef& def = kvp.second; - if (def.type == coEnum) { + if (def.type == coEnum || def.type == coEnums) { assert(def.enum_def); assert(def.enum_def->is_valid_closed_enum()); assert(! def.is_gui_type_enum_open()); @@ -1467,6 +1471,7 @@ CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBool) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBools) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumsGeneric) CEREAL_REGISTER_TYPE(Slic3r::ConfigBase) CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig) @@ -1508,4 +1513,5 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::C CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionBools) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInts, Slic3r::ConfigOptionEnumsGeneric) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 24bbe7a5b1..6cfe39c381 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -214,6 +214,8 @@ enum ConfigOptionType { coBools = coBool + coVectorType, // a generic enum coEnum = 9, + // vector of enum values + coEnums = coEnum + coVectorType, }; enum ConfigOptionMode { @@ -290,6 +292,7 @@ public: // Set a value from a ConfigOption. The two options should be compatible. virtual void set(const ConfigOption *option) = 0; virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); } + virtual std::vector getInts() const { throw BadOptionTypeException("Calling ConfigOption::getInts on a non-ints ConfigOption"); } virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); } virtual bool getBool() const { throw BadOptionTypeException("Calling ConfigOption::getBool on a non-boolean ConfigOption"); } virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); } @@ -1741,6 +1744,113 @@ public: } }; +template +class ConfigOptionEnums : public ConfigOptionVector +{ +public: + // by default, use the first value (0) of the T enum type + ConfigOptionEnums() : ConfigOptionVector() {} + explicit ConfigOptionEnums(size_t n, const T& value) : ConfigOptionVector(n, value) {} + explicit ConfigOptionEnums(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} + explicit ConfigOptionEnums(const std::vector& values) : ConfigOptionVector(values) {} + + static ConfigOptionType static_type() { return coEnums; } + ConfigOptionType type() const override { return static_type(); } + ConfigOption* clone() const override { return new ConfigOptionEnums(*this); } + ConfigOptionEnums& operator=(const ConfigOption *opt) { this->set(opt); return *this; } + bool operator==(const ConfigOptionEnums &rhs) const throw() { return this->values == rhs.values; } + bool operator< (const ConfigOptionEnums &rhs) const throw() { return this->values < rhs.values; } + bool is_nil(size_t) const override { return false; } + + std::vector getInts() const override { + std::vector ret; + ret.reserve(this->values.size()); + for (const auto& v : this->values) + ret.push_back(int(v)); + return ret; + } + + bool operator==(const ConfigOption& rhs) const override + { + if (rhs.type() != this->type()) + throw ConfigurationError("ConfigOptionEnums: Comparing incompatible types"); + // rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums + return this->getInts() == rhs.getInts(); + } + + void set(const ConfigOption* rhs) override { + if (rhs->type() != this->type()) + throw ConfigurationError("ConfigOptionEnums: Assigning an incompatible type"); + // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum + std::vector ret; + std::vector rhs_vals = rhs->getInts(); + ret.reserve(rhs_vals.size()); + for (const int& v : rhs_vals) + ret.push_back(T(v)); + this->values = ret; + } + + std::string serialize() const override + { + const t_config_enum_names& names = ConfigOptionEnum::get_enum_names(); + std::ostringstream ss; + for (const T& v : this->values) { + assert(static_cast(v) < int(names.size())); + if (&v != &this->values.front()) + ss << "," << names[static_cast(v)]; + } + return ss.str(); + } + + std::vector vserialize() const override + { + std::vector vv; + vv.reserve(this->values.size()); + for (const T v : this->values) { + std::ostringstream ss; + serialize_single_value(ss, int(v)); + vv.push_back(ss.str()); + } + return vv; + } + + bool deserialize(const std::string& str, bool append = false) override + { + if (!append) + this->values.clear(); + std::istringstream is(str); + std::string item_str; + while (std::getline(is, item_str, ',')) { + boost::trim(item_str); + if (item_str == "nil") { + throw ConfigurationError("Deserializing nil into a non-nullable object"); + } + else { + std::istringstream iss(item_str); + int value; + iss >> value; + this->values.push_back(static_cast(value)); + } + } + return true; + } + + static bool from_string(const std::string &str, T &value) + { + const t_config_enum_values &enum_keys_map = ConfigOptionEnum::get_enum_values(); + auto it = enum_keys_map.find(str); + if (it == enum_keys_map.end()) + return false; + value = static_cast(it->second); + return true; + } + +private: + void serialize_single_value(std::ostringstream& ss, const int v) const { + ss << v; + } +}; + // Generic enum configuration value. // We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum. // In the StaticConfig, it is better to use the specialized ConfigOptionEnum containers. @@ -1797,6 +1907,132 @@ private: template void serialize(Archive& ar) { ar(cereal::base_class(this)); } }; +template +class ConfigOptionEnumsGenericTempl : public ConfigOptionIntsTempl +{ +public: + ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map = nullptr) : keys_map(keys_map) {} + explicit ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map, std::vector values) : keys_map(keys_map) { this->values = values; } + + const t_config_enum_values* keys_map; + + ConfigOptionEnumsGenericTempl() : ConfigOptionIntsTempl() {} + explicit ConfigOptionEnumsGenericTempl(size_t n, int value) : ConfigOptionIntsTempl(n, value) {} + explicit ConfigOptionEnumsGenericTempl(std::initializer_list il) : ConfigOptionIntsTempl(std::move(il)) {} + explicit ConfigOptionEnumsGenericTempl(const std::vector& v) : ConfigOptionIntsTempl(v) {} + explicit ConfigOptionEnumsGenericTempl(std::vector&& v) : ConfigOptionIntsTempl(std::move(v)) {} + + static ConfigOptionType static_type() { return coEnums; } + ConfigOptionType type() const override { return static_type(); } + ConfigOption* clone() const override { return new ConfigOptionEnumsGenericTempl(*this); } + ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; } + bool operator==(const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values == rhs.values; } + bool operator< (const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values < rhs.values; } + std::vector getInts() const override { return this->values; } + + bool operator==(const ConfigOption& rhs) const override + { + if (rhs.type() != this->type()) + throw ConfigurationError("ConfigOptionEnumsGeneric: Comparing incompatible types"); + // rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums + return this->values == rhs.getInts(); + } + + void set(const ConfigOption* rhs) override { + if (rhs->type() != this->type()) + throw ConfigurationError("ConfigOptionEnumsGeneric: Assigning an incompatible type"); + // rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums + this->values = rhs->getInts(); + } + + // Could a special "nil" value be stored inside the vector, indicating undefined value? + bool nullable() const override { return NULLABLE; } + // Special "nil" value to be stored into the vector if this->supports_nil(). + static int nil_value() { return std::numeric_limits::max(); } + // A scalar is nil, or all values of a vector are nil. + bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; } + bool is_nil(size_t idx) const override { return this->values[idx < this->values.size() ? idx : 0] == nil_value(); } + + int& get_at(size_t i) { + assert(!this->values.empty()); + return *reinterpret_cast(&((i < this->values.size()) ? this->values[i] : this->values.front())); + } + + int get_at(size_t i) const { return i < this->values.size() ? this->values[i] : this->values.front(); } + + std::string serialize() const override + { + std::ostringstream ss; + for (const int& v : this->values) { + if (&v != &this->values.front()) + ss << ","; + serialize_single_value(ss, v); + } + return ss.str(); + } + + std::vector vserialize() const override + { + std::vector vv; + vv.reserve(this->values.size()); + for (const int v : this->values) { + std::ostringstream ss; + serialize_single_value(ss, v); + vv.push_back(ss.str()); + } + return vv; + } + + bool deserialize(const std::string& str, bool append = false) override + { + if (!append) + this->values.clear(); + std::istringstream is(str); + std::string item_str; + while (std::getline(is, item_str, ',')) { + boost::trim(item_str); + if (item_str == "nil") { + if (NULLABLE) + this->values.push_back(nil_value()); + else + throw ConfigurationError("Deserializing nil into a non-nullable object"); + } + else { + auto it = this->keys_map->find(item_str); + if (it == this->keys_map->end()) + return false; + this->values.push_back(it->second); + } + } + return true; + } + +private: + void serialize_single_value(std::ostringstream& ss, const int v) const { + if (v == nil_value()) { + if (NULLABLE) + ss << "nil"; + else + throw ConfigurationError("Serializing NaN"); + } + else { + for (const auto& kvp : *this->keys_map) + if (kvp.second == v) { + ss << kvp.first; + return; + } + ss << std::string(); + } + } + + friend class cereal::access; + template void serialize(Archive& ar) { ar(cereal::base_class>(this)); } +}; + +using ConfigOptionEnumsGeneric = ConfigOptionEnumsGenericTempl; +using ConfigOptionEnumsGenericNullable = ConfigOptionEnumsGenericTempl; + + // Definition of values / labels for a combo box. // Mostly used for closed enums (when type == coEnum), but may be used for // open enums with ints resp. floats, if gui_type is set to GUIType::i_enum_open" resp. GUIType::f_enum_open. @@ -2041,6 +2277,7 @@ public: case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; } case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map); archive(*opt); return opt; } + case coEnums: { auto opt = new ConfigOptionEnumsGeneric(this->enum_def->m_enum_keys_map); archive(*opt); return opt; } default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key); } } @@ -2075,6 +2312,7 @@ public: case coBool: archive(*static_cast(opt)); break; case coBools: archive(*static_cast(opt)); break; case coEnum: archive(*static_cast(opt)); break; + case coEnums: archive(*static_cast(opt)); break; default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key); } } @@ -2482,6 +2720,8 @@ public: // Thus the virtual method getInt() is used to retrieve the enum value. template ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast(this->option(opt_key)->getInt()); } + template + ENUM opt_enum(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast*>(this->option(opt_key))->get_at(idx);} bool opt_bool(const t_config_option_key &opt_key) const { return this->option(opt_key)->value != 0; } bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option(opt_key)->get_at(idx) != 0; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 4aecc7fc6a..df6260c5e0 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -604,6 +605,7 @@ static std::vector s_Preset_sla_material_options { "material_notes", "material_vendor", "material_print_speed", + "area_fill", "default_sla_material_profile", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits", @@ -627,13 +629,15 @@ static std::vector s_Preset_sla_material_options { "material_ow_elefant_foot_compensation" }; +static std::vector s_Preset_sla_material_options_all = boost::copy_range>(boost::join(s_Preset_sla_material_options, tilt_options())); + static std::vector s_Preset_sla_printer_options { "printer_technology", "bed_shape", "bed_custom_texture", "bed_custom_model", "max_print_height", "display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_mirror_x", "display_mirror_y", "display_orientation", - "fast_tilt_time", "slow_tilt_time", "high_viscosity_tilt_time", "area_fill", + "fast_tilt_time", "slow_tilt_time", "high_viscosity_tilt_time", //"area_fill", "relative_correction", "relative_correction_x", "relative_correction_y", @@ -657,7 +661,7 @@ const std::vector& Preset::machine_limits_options() { return s_Pres // of the nozzle_diameter vector. const std::vector& Preset::nozzle_options() { return print_config_def.extruder_option_keys(); } const std::vector& Preset::sla_print_options() { return s_Preset_sla_print_options; } -const std::vector& Preset::sla_material_options() { return s_Preset_sla_material_options; } +const std::vector& Preset::sla_material_options() { return s_Preset_sla_material_options_all; } const std::vector& Preset::sla_printer_options() { return s_Preset_sla_printer_options; } const std::vector& Preset::printer_options() @@ -1370,6 +1374,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi case coPercents:add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; case coPoints: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; case coFloatsOrPercents: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; + case coEnums: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; default: diff.emplace_back(opt_key); break; } // "nozzle_diameter" is a vector option which contain info about diameter for each nozzle diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7a8e3097c9..4e266ef026 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -255,6 +255,21 @@ static t_config_enum_values s_keys_map_PerimeterGeneratorType { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType) +static const t_config_enum_values s_keys_map_TiltProfiles{ + { "homingFast", tpHomingFast, }, + { "homingSlow", tpHomingSlow, }, + { "moveFast", tpMoveFast, }, + { "moveSlow", tpMoveSlow, }, + { "layer", tpLayer, }, + { "layerMove", tpLayerMove, }, + { "superSlow", tpSuperSlow, }, + { "resinSensor", tpResinSensor, }, + { "layerMoveSlow", tpLayerMoveSlow,}, + { "layerRelease", tpLayerRelease, }, + { "layerMoveFast", tpLayerMoveFast } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TiltProfiles) + static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology) { for (std::pair &kvp : options) @@ -275,6 +290,7 @@ PrintConfigDef::PrintConfigDef() this->init_extruder_option_keys(); assign_printer_technology_to_unknown(this->options, ptFFF); this->init_sla_params(); + this->init_sla_tilt_params(); assign_printer_technology_to_unknown(this->options, ptSLA); this->finalize(); } @@ -4385,6 +4401,207 @@ void PrintConfigDef::init_sla_params() } } +// SLA Materials "sub-presets" settings +void PrintConfigDef::init_sla_tilt_params() +{ + ConfigOptionDef* def; + + def = this->add("delay_before_exposure_ms", coFloats); + def->full_label = L("Delay before exposure"); + def->tooltip = L("Delay time before exposure"); + def->sidetext = L("s"); + def->min = 0; + def->max = 30; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 3., 3.})); + + def = this->add("delay_after_exposure_ms", coFloats); + def->full_label = L("Delay after exposure"); + def->tooltip = L("Delay time after exposure"); + def->sidetext = L("s"); + def->min = 0; + def->max = 30; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 0., 0.})); + + def = this->add("tower_hop_height_nm", coInts); + def->full_label = L("Tower hop height"); + def->tooltip = L("Tower hop height"); + def->sidetext = L("mm"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts({ 0, 0})); + + //ysFIXME + def = this->add("tower_profile", coEnums); + def->full_label = L("Tower profile"); + def->tooltip = L("Tower profile"); + def->mode = comExpert; + def->set_enum({ + { "homingFast", L("Homing Fast"), }, + { "homingSlow", L("Homing Slow"), }, + { "moveFast", L("Move Fast"), }, + { "moveSlow", L("Move Slow"), }, + { "layer", L("Layer"), }, + { "layerMove", L("Layer Move"), }, + { "superSlow", L("Super Slow"), }, + { "resinSensor", L("Resin Sensor"), }, + }); + def->set_default_value(new ConfigOptionEnums({ tpLayer, tpLayer })); + + def = this->add("tilt_down_initial_profile", coEnums); + def->full_label = L("Tilt down initial profile"); + def->tooltip = L("Tilt down initial profile"); + def->mode = comExpert; + def->set_enum({ + { "homingFast", L("Homing Fast"), }, + { "homingSlow", L("Homing Slow"), }, + { "moveFast", L("Move Fast"), }, + { "moveSlow", L("Move Slow"), }, + { "layerMoveSlow", L("Layer Move Slow"),}, + { "layerRelease", L("Layer Release"), }, + { "layerMoveFast", L("Layer Move Fast") }, + { "superSlow", L("Super Slow"), }, + }); + def->set_default_value(new ConfigOptionEnums({ tpLayerMoveFast, tpLayerMoveFast })); + + def = this->add("tilt_down_finish_profile", coEnums); + def->full_label = L("Tilt down finish profile"); + def->tooltip = L("Tilt down finish profile"); + def->mode = comExpert; + def->set_enum({ + { "homingFast", L("Homing Fast"), }, + { "homingSlow", L("Homing Slow"), }, + { "moveFast", L("Move Fast"), }, + { "moveSlow", L("Move Slow"), }, + { "layerMoveSlow", L("Layer Move Slow"),}, + { "layerRelease", L("Layer Release"), }, + { "layerMoveFast", L("Layer Move Fast") }, + { "superSlow", L("Super Slow"), }, + }); + def->set_default_value(new ConfigOptionEnums({ tpLayerMoveSlow, tpLayerMoveSlow })); + + def = this->add("tilt_up_initial_profile", coEnums); + def->full_label = L("Tilt up initial profile"); + def->tooltip = L("Tilt up initial profile"); + def->mode = comExpert; + def->set_enum({ + { "homingFast", L("Homing Fast"), }, + { "homingSlow", L("Homing Slow"), }, + { "moveFast", L("Move Fast"), }, + { "moveSlow", L("Move Slow"), }, + { "layerMoveSlow", L("Layer Move Slow"),}, + { "layerRelease", L("Layer Release"), }, + { "layerMoveFast", L("Layer Move Fast") }, + { "superSlow", L("Super Slow"), }, + }); + def->set_default_value(new ConfigOptionEnums({ tpMoveFast, tpMoveFast })); + + def = this->add("tilt_up_finish_profile", coEnums); + def->full_label = L("Tilt up finish profile"); + def->tooltip = L("Tilt up finish profile"); + def->mode = comExpert; + def->set_enum({ + { "homingFast", L("Homing Fast"), }, + { "homingSlow", L("Homing Slow"), }, + { "moveFast", L("Move Fast"), }, + { "moveSlow", L("Move Slow"), }, + { "layerMoveSlow", L("Layer Move Slow"),}, + { "layerRelease", L("Layer Release"), }, + { "layerMoveFast", L("Layer Move Fast") }, + { "superSlow", L("Super Slow"), }, + }); + def->set_default_value(new ConfigOptionEnums({ tpLayerMoveFast, tpLayerMoveFast })); + + def = this->add("use_tilt", coBools); + def->full_label = L("Use tilt"); + def->tooltip = L("Use tilt"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBools({ true, true })); + + def = this->add("tilt_down_offset_steps", coInts); + def->full_label = L("Tilt down offset steps"); + def->tooltip = L("Tilt down offset steps"); + def->sidetext = L("μ-steps"); + def->min = 0; + def->max = 10000; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts({ 0, 0 })); + + def = this->add("tilt_down_offset_delay_ms", coFloats); + def->full_label = L("Tilt down offset delay"); + def->tooltip = L("Tilt down offset delay"); + def->sidetext = L("s"); + def->min = 0; + def->max = 20; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 0., 0. })); + + def = this->add("tilt_down_cycles", coInts); + def->full_label = L("Tilt down cycles"); + def->tooltip = L("Tilt down cycles"); + def->min = 0; + def->max = 10; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts({ 1, 1 })); + + def = this->add("tilt_down_delay_ms", coFloats); + def->full_label = L("Tilt down delay"); + def->tooltip = L("Tilt down delay"); + def->sidetext = L("s"); + def->min = 0; + def->max = 20; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 0., 0. })); + + def = this->add("tilt_up_offset_steps", coInts); + def->full_label = L("Tilt up offset steps"); + def->tooltip = L("Tilt up offset steps"); + def->sidetext = L("μ-steps"); + def->min = 0; + def->max = 10000; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts({ 1200, 1200 })); + + def = this->add("tilt_up_offset_delay_ms", coFloats); + def->full_label = L("Tilt up offset delay"); + def->tooltip = L("Tilt up offset delay"); + def->sidetext = L("s"); + def->min = 0; + def->max = 20; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 0., 0. })); + + def = this->add("tilt_up_cycles", coInts); + def->full_label = L("Tilt up cycles"); + def->tooltip = L("Tilt up cycles"); + def->min = 0; + def->max = 10; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts({ 1, 1 })); + + def = this->add("tilt_up_delay_ms", coFloats); + def->full_label = L("Tilt up delay"); + def->tooltip = L("Tilt up delay"); + def->sidetext = L("s"); + def->min = 0; + def->max = 20; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 0., 0. })); + + def = this->add("moves_time_ms", coFloats); + def->full_label = L("Moves time"); + def->tooltip = L("Moves time"); + def->sidetext = L("s"); + def->min = 0; + def->max = 60; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats({ 4.5, 4.5 })); + +} + + // Ignore the following obsolete configuration keys: static std::set PrintConfigDef_ignore = { "clip_multipart_objects", @@ -4659,6 +4876,66 @@ void DynamicPrintConfig::normalize_fdm() opt_wall_transition_length->value = std::max(opt_wall_transition_length->value, 0.001); } +static std::vector s_Preset_sla_tilt_options{ + "delay_before_exposure_ms" + ,"delay_after_exposure_ms" + ,"tower_hop_height_nm" + ,"tower_profile" + ,"use_tilt" + ,"tilt_down_initial_profile" + ,"tilt_down_offset_steps" + ,"tilt_down_offset_delay_ms" + ,"tilt_down_finish_profile" + ,"tilt_down_cycles" + ,"tilt_down_delay_ms" + ,"tilt_up_initial_profile" + ,"tilt_up_offset_steps" + ,"tilt_up_offset_delay_ms" + ,"tilt_up_finish_profile" + ,"tilt_up_cycles" + ,"tilt_up_delay_ms" + ,"moves_time_ms" +}; + +const std::vector& tilt_options() { return s_Preset_sla_tilt_options; } + +// Default values containe option pair of values (Below and Above) for each titl modes +// (Slow, Fast, HighViscosity and NoTilt) + +const std::map tilt_options_floats_defs = +{ + {"delay_before_exposure_ms", ConfigOptionFloats({ 3., 3., 0., 1., 3.5, 3.5, 0., 0. }) } , + {"delay_after_exposure_ms", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } , + {"tilt_down_offset_delay_ms", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } , + {"tilt_down_delay_ms", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } , + {"tilt_up_offset_delay_ms", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } , + {"tilt_up_delay_ms", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } , + {"moves_time_ms", ConfigOptionFloats({ 4.5, 4.5, 2.1, 4.3, 14.25, 14.25, 0., 0. }) } , +}; + +const std::map tilt_options_ints_defs = +{ + {"tower_hop_height_nm", ConfigOptionInts({ 0, 0, 0, 0, 5, 5, 0, 0 }) } , + {"tilt_down_offset_steps", ConfigOptionInts({ 0, 0, 0, 0, 2200, 2200, 0, 0 }) } , + {"tilt_down_cycles", ConfigOptionInts({ 1, 1, 1, 1, 1, 1, 0, 0 }) } , + {"tilt_up_offset_steps", ConfigOptionInts({ 1200, 1200, 600, 600, 2200, 2200, 0, 0 }) } , + {"tilt_up_cycles", ConfigOptionInts({ 1, 1, 1, 1, 1, 1, 0, 0 }) } , +}; + +const std::map tilt_options_bools_defs = +{ + {"use_tilt", ConfigOptionBools({ true, true, true, true, true, true, false, false })} , +}; + +const std::map> tilt_options_enums_defs = +{ + {"tower_profile", ConfigOptionEnums({ tpLayer, tpLayer, tpLayer, tpLayer, tpSuperSlow, tpSuperSlow, tpLayer, tpLayer })} , + {"tilt_down_initial_profile", ConfigOptionEnums({ tpLayerMoveFast, tpLayerMoveFast, tpLayerMoveFast, tpLayerMoveFast, tpSuperSlow, tpSuperSlow, tpHomingSlow, tpHomingSlow }) } , + {"tilt_down_finish_profile", ConfigOptionEnums({ tpLayerMoveSlow, tpLayerMoveSlow, tpMoveFast, tpLayerMoveSlow, tpLayerMoveSlow, tpLayerMoveSlow, tpHomingSlow, tpHomingSlow }) } , + {"tilt_up_initial_profile", ConfigOptionEnums({ tpMoveFast, tpMoveFast, tpMoveFast, tpMoveFast, tpLayerMoveSlow, tpLayerMoveSlow, tpHomingSlow, tpHomingSlow }) } , + {"tilt_up_finish_profile", ConfigOptionEnums({ tpLayerMoveFast, tpLayerMoveFast, tpLayerMoveFast, tpLayerMoveFast, tpSuperSlow, tpSuperSlow, tpHomingSlow, tpHomingSlow }) } , +}; + void handle_legacy_sla(DynamicPrintConfig &config) { for (std::string corr : {"relative_correction", "material_correction"}) { @@ -4679,6 +4956,50 @@ void handle_legacy_sla(DynamicPrintConfig &config) } } } + + // Load default tilt options in config in respect to the print speed, if config is loaded from old PS + + if (config.has("material_print_speed") && + !config.has("tilt_down_offset_delay_ms") // Config from old PS doesn't contain any of tilt options, so check it + ) { + int tilt_mode = config.option("material_print_speed")->getInt(); + + for (const std::string& opt_key : s_Preset_sla_tilt_options) { + switch (config.def()->get(opt_key)->type) { + case coFloats: { + ConfigOptionFloats values = tilt_options_floats_defs.at(opt_key); + double val1 = values.get_at(2 * tilt_mode); + double val2 = values.get_at(2 * tilt_mode + 1); + config.set_key_value(opt_key, new ConfigOptionFloats({ val1, val2 })); + } + break; + case coInts: { + auto values = tilt_options_ints_defs.at(opt_key); + int val1 = values.get_at(2 * tilt_mode); + int val2 = values.get_at(2 * tilt_mode + 1); + config.set_key_value(opt_key, new ConfigOptionInts({ val1, val2 })); + } + break; + case coBools: { + auto values = tilt_options_bools_defs.at(opt_key); + bool val1 = values.get_at(2 * tilt_mode); + bool val2 = values.get_at(2 * tilt_mode + 1); + config.set_key_value(opt_key, new ConfigOptionBools({ val1, val2 })); + } + break; + case coEnums: { + auto values = tilt_options_enums_defs.at(opt_key); + int val1 = values.get_at(2 * tilt_mode); + int val2 = values.get_at(2 * tilt_mode + 1); + config.set_key_value(opt_key, new ConfigOptionEnumsGeneric({ val1, val2 })); + } + break; + case coNone: + default: + break; + } + } + } } void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 09e6612d3b..385e9f869a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -163,6 +163,20 @@ enum class GCodeThumbnailsFormat { PNG, JPG, QOI }; +enum TiltProfiles : int { + tpHomingFast, + tpHomingSlow, + tpMoveFast, + tpMoveSlow, + tpLayer, + tpLayerMove, + tpSuperSlow, + tpResinSensor, + tpLayerMoveSlow, + tpLayerRelease, + tpLayerMoveFast, +}; + #define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \ template<> const t_config_enum_names& ConfigOptionEnum::get_enum_names(); \ template<> const t_config_enum_values& ConfigOptionEnum::get_enum_values(); @@ -218,6 +232,7 @@ private: void init_fff_params(); void init_extruder_option_keys(); void init_sla_params(); + void init_sla_tilt_params(); void init_sla_support_params(const std::string &method_prefix); std::vector m_extruder_option_keys; @@ -297,6 +312,9 @@ public: { PrintConfigDef::handle_legacy_composite(*this); } }; +// This vector containes list of parameters for preview of tilt profiles +const std::vector& tilt_options(); + void handle_legacy_sla(DynamicPrintConfig &config); class StaticPrintConfig : public StaticConfig @@ -1132,11 +1150,31 @@ PRINT_CONFIG_CLASS_DEFINE( ((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)) + ((ConfigOptionFloat, area_fill)) + + //tilt params + ((ConfigOptionFloats, delay_before_exposure_ms)) + ((ConfigOptionFloats, delay_after_exposure_ms)) + ((ConfigOptionInts, tower_hop_height_nm)) + ((ConfigOptionEnums, tower_profile)) + ((ConfigOptionBools, use_tilt)) + ((ConfigOptionEnums, tilt_down_initial_profile)) + ((ConfigOptionInts, tilt_down_offset_steps)) + ((ConfigOptionFloats, tilt_down_offset_delay_ms)) + ((ConfigOptionEnums, tilt_down_finish_profile)) + ((ConfigOptionInts, tilt_down_cycles)) + ((ConfigOptionFloats, tilt_down_delay_ms)) + ((ConfigOptionEnums, tilt_up_initial_profile)) + ((ConfigOptionInts, tilt_up_offset_steps)) + ((ConfigOptionFloats, tilt_up_offset_delay_ms)) + ((ConfigOptionEnums, tilt_up_finish_profile)) + ((ConfigOptionInts, tilt_up_cycles)) + ((ConfigOptionFloats, tilt_up_delay_ms)) + ((ConfigOptionFloats, moves_time_ms)) ) PRINT_CONFIG_CLASS_DEFINE( @@ -1163,7 +1201,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, fast_tilt_time)) ((ConfigOptionFloat, slow_tilt_time)) ((ConfigOptionFloat, high_viscosity_tilt_time)) - ((ConfigOptionFloat, area_fill)) +// ((ConfigOptionFloat, area_fill)) ((ConfigOptionFloat, min_exposure_time)) ((ConfigOptionFloat, max_exposure_time)) ((ConfigOptionFloat, min_initial_exposure_time)) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 5dfb224482..3d79933255 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -839,6 +839,24 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector steps; diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 56da543fc8..4b67975a87 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -924,7 +924,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() { print_statistics.clear(); - const double area_fill = printer_config.area_fill.getFloat()*0.01;// 0.5 (50%); + const double area_fill = /*printer_config*/material_config.area_fill.getFloat()*0.01;// 0.5 (50%); const double fast_tilt = printer_config.fast_tilt_time.getFloat();// 5.0; const double slow_tilt = printer_config.slow_tilt_time.getFloat();// 8.0; const double hv_tilt = printer_config.high_viscosity_tilt_time.getFloat();// 10.0; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index ef966ce874..e6d6efb079 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1156,6 +1156,10 @@ void Choice::set_selection() field->SetSelection(m_opt.default_value->getInt()); break; } + case coEnums:{ + field->SetSelection(m_opt.default_value->getInts()[m_opt_idx]); + break; + } case coFloat: case coPercent: { double val = m_opt.default_value->getFloat(); @@ -1243,7 +1247,8 @@ void Choice::set_value(const boost::any& value, bool change_event) break; } - case coEnum: { + case coEnum: + case coEnums: { auto val = m_opt.enum_def->enum_to_index(boost::any_cast(value)); assert(val.has_value()); field->SetSelection(val.has_value() ? *val : 0); @@ -1308,7 +1313,7 @@ boost::any& Choice::get_value() if (m_opt_id == rp_option) return m_value = boost::any(ret_str); - if (m_opt.type == coEnum) + if (m_opt.type == coEnum || m_opt.type == coEnums) // Closed enum: The combo box item index returned by the field must be convertible to an enum value. m_value = m_opt.enum_def->index_to_enum(field->GetSelection()); else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) { diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 7c71ea4548..74a9f409ab 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -211,6 +211,10 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, opt); } break; + case coEnums: { + ConfigOptionEnumsGeneric* vec_new = new ConfigOptionEnumsGeneric(1, boost::any_cast(value));; + config.option(opt_key)->set_at(vec_new, opt_index, 0); + break; } case coPoints:{ if (opt_key == "bed_shape") { config.option(opt_key)->values = boost::any_cast>(value); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index eb5860b451..c2e428d1e5 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -83,7 +83,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co m_fields.emplace(id, SpinCtrl::Create(this->ctrl_parent(), opt, id)); break; case coEnum: - m_fields.emplace(id, Choice::Create(this->ctrl_parent(), opt, id)); + case coEnums: + m_fields.emplace(id, Choice::Create(this->ctrl_parent(), opt, id)); break; case coPoints: m_fields.emplace(id, PointCtrl::Create(this->ctrl_parent(), opt, id)); @@ -975,6 +976,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config case coEnum: ret = config.option(opt_key)->getInt(); break; + case coEnums: + ret = config.option(opt_key)->getInts()[idx]; + break; case coPoints: if (opt_key == "bed_shape") ret = config.option(opt_key)->values; diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 3febe895f6..937f4bb37f 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -97,8 +97,11 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty wxString suffix; wxString suffix_local; - if (gc.category == "Machine limits") { - suffix = id == 1 ? L("Stealth") : L("Normal"); + if (gc.category == "Machine limits" || gc.category == "Material printing profile") { + if (gc.category == "Machine limits") + suffix = id == 1 ? L("Stealth") : L("Normal"); + else + suffix = id == 1 ? L("Above") : L("Below"); suffix_local = " " + _(suffix); suffix = " " + suffix; } @@ -122,7 +125,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty int cnt = 0; - if ( type != Preset::TYPE_FILAMENT && type != Preset::TYPE_SLA_MATERIAL && !PresetCollection::is_independent_from_extruder_number_option(opt_key) ) + if ( type != Preset::TYPE_FILAMENT && !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; @@ -132,6 +135,8 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty case coPercents:change_opt_key(opt_key, config, cnt); break; case coPoints: change_opt_key(opt_key, config, cnt); break; case coFloatsOrPercents: change_opt_key(opt_key, config, cnt); break; + case coEnums: change_opt_key(opt_key, config, cnt); break; + default: break; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 70a45aa9e7..a4df3bc66d 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 && m_type != Preset::TYPE_SLA_MATERIAL && !PresetCollection::is_independent_from_extruder_number_option(opt_key)); + emplace_option(opt_key, m_type != Preset::TYPE_FILAMENT && !PresetCollection::is_independent_from_extruder_number_option(opt_key)); } template @@ -710,6 +710,7 @@ void Tab::emplace_option(const std::string& opt_key, bool respect_vec_values/* = case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; case coFloatsOrPercents: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coEnums: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; default: m_options_list.emplace(opt_key, m_opt_status_value); break; } } @@ -2946,7 +2947,7 @@ void TabPrinter::build_sla() // FIXME: This should be on one line in the UI optgroup->append_single_option_line("display_mirror_x"); optgroup->append_single_option_line("display_mirror_y"); - +/* optgroup = page->new_optgroup(L("Tilt")); line = { L("Tilt time"), "" }; line.append_option(optgroup->get_option("fast_tilt_time")); @@ -2954,7 +2955,7 @@ void TabPrinter::build_sla() line.append_option(optgroup->get_option("high_viscosity_tilt_time")); optgroup->append_line(line); optgroup->append_single_option_line("area_fill"); - +*/ optgroup = page->new_optgroup(L("Corrections")); line = Line{ m_config->def()->get("relative_correction")->full_label, "" }; for (auto& axis : { "X", "Y", "Z" }) { @@ -3038,6 +3039,29 @@ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::s optgroup->append_line(line); } +// Legend for OptionsGroups column's name tooltip +static void create_legend(Slic3r::GUI::PageShp page, const std::vector>& columns, ConfigOptionMode mode, bool is_wider = false) +{ + auto optgroup = page->new_optgroup(""); + auto line = Line{ "", "" }; + + ConfigOptionDef def; + def.type = coString; + def.width = is_wider ? Field::def_width_wider() : Field::def_width(); + def.gui_type = ConfigOptionDef::GUIType::legend; + def.mode = mode; + + for (auto& [name, tooltip] : columns) { + def.tooltip = tooltip; + def.set_default_value(new ConfigOptionString{ into_u8(_(name)) }); + + auto option = Option(def, name + "_legend"); + line.append_option(option); + } + + optgroup->append_line(line); +} + PageShp TabPrinter::build_kinematics_page() { auto page = add_options_page(L("Machine limits"), "cog", true); @@ -3075,27 +3099,12 @@ PageShp TabPrinter::build_kinematics_page() }; if (m_use_silent_mode) { - // Legend for OptionsGroups - auto optgroup = page->new_optgroup(""); - auto line = Line{ "", "" }; + std::vector> legend_columns = { + {L("Normal"), L("Values in this column are for Normal mode")}, + {L("Stealth"), L("Values in this column are for Stealth mode")} + }; - ConfigOptionDef def; - def.type = coString; - def.width = Field::def_width(); - def.gui_type = ConfigOptionDef::GUIType::legend; - def.mode = comAdvanced; - def.tooltip = L("Values in this column are for Normal mode"); - def.set_default_value(new ConfigOptionString{ _(L("Normal")).ToUTF8().data() }); - - auto option = Option(def, "full_power_legend"); - line.append_option(option); - - def.tooltip = L("Values in this column are for Stealth mode"); - def.set_default_value(new ConfigOptionString{ _(L("Stealth")).ToUTF8().data() }); - option = Option(def, "silent_legend"); - line.append_option(option); - - optgroup->append_line(line); + create_legend(page, legend_columns, comAdvanced); } const std::vector axes{ "x", "y", "z", "e" }; @@ -5390,16 +5399,114 @@ void TabSLAMaterial::build() page = add_options_page(L("Material printing profile"), "note"); optgroup = page->new_optgroup(L("Material printing profile")); - option = optgroup->get_option("material_print_speed"); - optgroup->append_single_option_line(option); +// option = optgroup->get_option("material_print_speed"); +// optgroup->append_single_option_line(option); + optgroup->append_single_option_line("area_fill"); + + build_tilt_group(page); +} + +static void append_tilt_options_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) +{ + auto option = optgroup->get_option(opt_key, 0); + auto line = Line{ option.opt.full_label, "" }; + option.opt.width = Field::def_width_wider(); + line.append_option(option); + + option = optgroup->get_option(opt_key, 1); + option.opt.width = Field::def_width_wider(); + line.append_option(option); + + optgroup->append_line(line); +} + +void TabSLAMaterial::build_tilt_group(Slic3r::GUI::PageShp page) +{ + // Legend + std::vector> legend_columns = { + {L("Below"), L("Values in this column are for ???")}, + {L("Above"), L("Values in this column are for ???")}, + }; + create_legend(page, legend_columns, comExpert, true); + + auto optgroup = page->new_optgroup(L("Tilt profiles")); + optgroup->on_change = [this, optgroup](const t_config_option_key& key, boost::any value) + { + if (key.find_first_of("use_tilt") == 0) + toggle_tilt_options(key == "use_tilt#0"); + + update_dirty(); + update(); + }; + + for (const std::string& opt_key : tilt_options()) + append_tilt_options_line(optgroup, opt_key); +} + +static boost::any get_def_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int idx) +{ + boost::any ret; + + const ConfigOptionDef* opt = config.def()->get(opt_key); + auto def_values = opt->default_value; + if (def_values) { + switch (def_values->type()) { + case coFloats: { + double val = static_cast(def_values.get())->get_at(idx); + ret = double_to_string(val); + } + break; + case coInts: + ret = static_cast(def_values.get())->get_at(idx); + break; + case coBools: + ret = static_cast(def_values.get())->get_at(idx); + break; + case coEnums: + ret = static_cast(def_values.get())->get_at(idx); + break; + case coNone: + default: + break; + } + } + return ret; +} + +std::vector disable_tilt_options = { + "tilt_down_initial_profile" + ,"tilt_down_offset_steps" + ,"tilt_down_offset_delay_ms" + ,"tilt_down_finish_profile" + ,"tilt_down_cycles" + ,"tilt_down_delay_ms" + ,"tilt_up_initial_profile" + ,"tilt_up_offset_steps" + ,"tilt_up_offset_delay_ms" + ,"tilt_up_finish_profile" + ,"tilt_up_cycles" + ,"tilt_up_delay_ms" + ,"moves_time_ms" +}; + +void TabSLAMaterial::toggle_tilt_options(bool is_above) +{ + if (m_active_page && m_active_page->title() == "Material printing profile") + { + int column_id = is_above ? 0 : 1; + auto optgroup = m_active_page->get_optgroup("Tilt profiles"); + bool use_tilt = boost::any_cast(optgroup->get_config_value(*m_config, "use_tilt", column_id)); + + for (const std::string& opt_key : disable_tilt_options) { + auto field = optgroup->get_fieldc(opt_key, column_id); + if (field != nullptr) + field->toggle(use_tilt); + } + } } 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(); } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 505c47b199..faf4e2b86d 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -578,6 +578,8 @@ public: ~TabSLAMaterial() {} void build() override; + void build_tilt_group(Slic3r::GUI::PageShp page); + void toggle_tilt_options(bool is_above); void toggle_options() override; void update() override; bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptSLA; } diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 2e75869599..9a5b0229ab 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -1199,6 +1199,14 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& auto opt = config.option_def(opt_key)->enum_def->enum_to_label(config.option(opt_key)->getInt()); return opt.has_value() ? _(from_u8(*opt)) : _L("Undef"); } + case coEnums: { + auto values = config.option(opt_key)->getInts(); + if (opt_idx < values.size()) { + auto opt = config.option_def(opt_key)->enum_def->enum_to_label(values[opt_idx]); + return opt.has_value() ? _(from_u8(*opt)) : _L("Undef"); + } + return _L("Undef"); + } case coPoints: { if (opt_key == "bed_shape") { BedShape shape(*config.option(opt_key)); @@ -1289,7 +1297,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 && type != Preset::TYPE_SLA_MATERIAL; + const bool deep_compare = type != Preset::TYPE_FILAMENT; auto dirty_options = presets->current_dirty_options(deep_compare); // process changes of extruders count