Merge branch 'ys_spe1916'

This commit is contained in:
Lukas Matena 2024-06-06 13:36:25 +02:00
commit e1b33bacf2
25 changed files with 2308 additions and 1674 deletions

View File

@ -1,4 +1,10 @@
min_slic3r_version = 2.7.5-rc
1.14.0 Added new settings for SLA material profiles.
min_slic3r_version = 2.7.3-beta1 min_slic3r_version = 2.7.3-beta1
1.13.4 Updated FW version notification (6.0.1). Added ROSA3D filaments. Updated print profiles for 0.6 nozzle. Updated perimeter speeds in "0.10mm FAST DETAIL" profile (MK4/XL). Slightly increased nozzle temperature for Generic PETG/Prusa PETG/Prusament PETG (0.6n).
1.13.3 Updated FW version notification.
1.13.2 Added material profiles for Prusament Resin Flex Anatomic Red and Prusament Resin Flex Gingiva Mask.
1.13.1 Added material profile for Prusament Resin Model Transparent Clear. Enabled stealth mode support for MINI, XL, MK3.5, MK3.9, MK4 (this mode will be available in FW 6.0.0).
1.13.0 Updated version for PrusaSlicer 2.7.3 1.13.0 Updated version for PrusaSlicer 2.7.3
1.13.0-beta3 Reduced number of top/bottom layers (0.6). Updated cooling thresholds. 1.13.0-beta3 Reduced number of top/bottom layers (0.6). Updated cooling thresholds.
1.13.0-beta2 Disabled ramping lift for MK3.5. 1.13.0-beta2 Disabled ramping lift for MK3.5.

File diff suppressed because one or more lines are too long

View File

@ -153,8 +153,8 @@ namespace ImGui
const wchar_t PlugMarker = 0x1C; const wchar_t PlugMarker = 0x1C;
const wchar_t DowelMarker = 0x1D; const wchar_t DowelMarker = 0x1D;
const wchar_t SnapMarker = 0x1E; const wchar_t SnapMarker = 0x1E;
const wchar_t HorizontalHide = 0xB1; const wchar_t HorizontalHide = 0xB4;
const wchar_t HorizontalShow = 0xB2; const wchar_t HorizontalShow = 0xB6;
// Do not forget use following letters only in wstring // Do not forget use following letters only in wstring
const wchar_t DocumentationButton = 0x2600; const wchar_t DocumentationButton = 0x2600;
const wchar_t DocumentationHoverButton = 0x2601; const wchar_t DocumentationHoverButton = 0x2601;

View File

@ -294,6 +294,7 @@ ConfigOption* ConfigOptionDef::create_empty_option() const
case coBool: return new ConfigOptionBool(); case coBool: return new ConfigOptionBool();
case coBools: return new ConfigOptionBools(); case coBools: return new ConfigOptionBools();
case coEnum: return new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map); 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); 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) if (this->default_value)
return (this->default_value->type() == coEnum) ? return (this->default_value->type() == coEnum) ?
// Special case: For a DynamicConfig, convert a templated enum to a generic enum. // 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(); this->default_value->clone();
return this->create_empty_option(); return this->create_empty_option();
} }
@ -333,7 +337,7 @@ void ConfigDef::finalize()
// Validate & finalize open & closed enums. // Validate & finalize open & closed enums.
for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options) { for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options) {
ConfigOptionDef& def = kvp.second; ConfigOptionDef& def = kvp.second;
if (def.type == coEnum) { if (def.type == coEnum || def.type == coEnums) {
assert(def.enum_def); assert(def.enum_def);
assert(def.enum_def->is_valid_closed_enum()); assert(def.enum_def->is_valid_closed_enum());
assert(! def.is_gui_type_enum_open()); 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::ConfigOptionBools)
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBoolsNullable)
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric)
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumsGeneric)
CEREAL_REGISTER_TYPE(Slic3r::ConfigBase) CEREAL_REGISTER_TYPE(Slic3r::ConfigBase)
CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig) CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig)
@ -1508,4 +1513,5 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<bool>, Slic3r::C
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBools) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBools)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBoolsNullable)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInts, Slic3r::ConfigOptionEnumsGeneric)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig)

View File

@ -214,6 +214,8 @@ enum ConfigOptionType {
coBools = coBool + coVectorType, coBools = coBool + coVectorType,
// a generic enum // a generic enum
coEnum = 9, coEnum = 9,
// vector of enum values
coEnums = coEnum + coVectorType,
}; };
enum ConfigOptionMode { enum ConfigOptionMode {
@ -290,6 +292,7 @@ public:
// Set a value from a ConfigOption. The two options should be compatible. // Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0; virtual void set(const ConfigOption *option) = 0;
virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); } virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
virtual std::vector<int> getInts() const { throw BadOptionTypeException("Calling ConfigOption::getInts on a non-ints ConfigOption"); }
virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); } virtual 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 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"); } virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
@ -1741,6 +1744,113 @@ public:
} }
}; };
template <class T>
class ConfigOptionEnums : public ConfigOptionVector<T>
{
public:
// by default, use the first value (0) of the T enum type
ConfigOptionEnums() : ConfigOptionVector<T>() {}
explicit ConfigOptionEnums(size_t n, const T& value) : ConfigOptionVector<T>(n, value) {}
explicit ConfigOptionEnums(std::initializer_list<T> il) : ConfigOptionVector<T>(std::move(il)) {}
explicit ConfigOptionEnums(const std::vector<T>& values) : ConfigOptionVector<T>(values) {}
static ConfigOptionType static_type() { return coEnums; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnums<T>(*this); }
ConfigOptionEnums<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnums<T> &rhs) const throw() { return this->values == rhs.values; }
bool operator< (const ConfigOptionEnums<T> &rhs) const throw() { return this->values < rhs.values; }
bool is_nil(size_t) const override { return false; }
std::vector<int> getInts() const override {
std::vector<int> ret;
ret.reserve(this->values.size());
for (const auto& v : this->values)
ret.push_back(int(v));
return ret;
}
bool operator==(const ConfigOption& rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnums<T>: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
return this->getInts() == rhs.getInts();
}
void set(const ConfigOption* rhs) override {
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionEnums<T>: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
std::vector<T> ret;
std::vector<int> rhs_vals = rhs->getInts();
ret.reserve(rhs_vals.size());
for (const int& v : rhs_vals)
ret.push_back(T(v));
this->values = ret;
}
std::string serialize() const override
{
const t_config_enum_names& names = ConfigOptionEnum<T>::get_enum_names();
std::ostringstream ss;
for (const T& v : this->values) {
assert(static_cast<int>(v) < int(names.size()));
if (&v != &this->values.front())
ss << "," << names[static_cast<int>(v)];
}
return ss.str();
}
std::vector<std::string> vserialize() const override
{
std::vector<std::string> vv;
vv.reserve(this->values.size());
for (const T v : this->values) {
std::ostringstream ss;
serialize_single_value(ss, int(v));
vv.push_back(ss.str());
}
return vv;
}
bool deserialize(const std::string& str, bool append = false) override
{
if (!append)
this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
boost::trim(item_str);
if (item_str == "nil") {
throw ConfigurationError("Deserializing nil into a non-nullable object");
}
else {
std::istringstream iss(item_str);
int value;
iss >> value;
this->values.push_back(static_cast<T>(value));
}
}
return true;
}
static bool from_string(const std::string &str, T &value)
{
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
auto it = enum_keys_map.find(str);
if (it == enum_keys_map.end())
return false;
value = static_cast<T>(it->second);
return true;
}
private:
void serialize_single_value(std::ostringstream& ss, const int v) const {
ss << v;
}
};
// Generic enum configuration value. // Generic enum configuration value.
// We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum. // We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum.
// In the StaticConfig, it is better to use the specialized ConfigOptionEnum<T> containers. // In the StaticConfig, it is better to use the specialized ConfigOptionEnum<T> containers.
@ -1797,6 +1907,132 @@ private:
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); } template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); }
}; };
template<bool NULLABLE>
class ConfigOptionEnumsGenericTempl : public ConfigOptionIntsTempl<NULLABLE>
{
public:
ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map = nullptr) : keys_map(keys_map) {}
explicit ConfigOptionEnumsGenericTempl(const t_config_enum_values* keys_map, std::vector<int> values) : keys_map(keys_map) { this->values = values; }
const t_config_enum_values* keys_map;
ConfigOptionEnumsGenericTempl() : ConfigOptionIntsTempl<NULLABLE>() {}
explicit ConfigOptionEnumsGenericTempl(size_t n, int value) : ConfigOptionIntsTempl<NULLABLE>(n, value) {}
explicit ConfigOptionEnumsGenericTempl(std::initializer_list<int> il) : ConfigOptionIntsTempl<NULLABLE>(std::move(il)) {}
explicit ConfigOptionEnumsGenericTempl(const std::vector<int>& v) : ConfigOptionIntsTempl<NULLABLE>(v) {}
explicit ConfigOptionEnumsGenericTempl(std::vector<int>&& v) : ConfigOptionIntsTempl<NULLABLE>(std::move(v)) {}
static ConfigOptionType static_type() { return coEnums; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnumsGenericTempl(*this); }
ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values == rhs.values; }
bool operator< (const ConfigOptionEnumsGenericTempl& rhs) const throw() { return this->values < rhs.values; }
std::vector<int> getInts() const override { return this->values; }
bool operator==(const ConfigOption& rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
return this->values == rhs.getInts();
}
void set(const ConfigOption* rhs) override {
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumsGeneric or ConfigOptionEnums<T>
this->values = rhs->getInts();
}
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
static int nil_value() { return std::numeric_limits<int>::max(); }
// A scalar is nil, or all values of a vector are nil.
bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
bool is_nil(size_t idx) const override { return this->values[idx < this->values.size() ? idx : 0] == nil_value(); }
int& get_at(size_t i) {
assert(!this->values.empty());
return *reinterpret_cast<int*>(&((i < this->values.size()) ? this->values[i] : this->values.front()));
}
int get_at(size_t i) const { return i < this->values.size() ? this->values[i] : this->values.front(); }
std::string serialize() const override
{
std::ostringstream ss;
for (const int& v : this->values) {
if (&v != &this->values.front())
ss << ",";
serialize_single_value(ss, v);
}
return ss.str();
}
std::vector<std::string> vserialize() const override
{
std::vector<std::string> vv;
vv.reserve(this->values.size());
for (const int v : this->values) {
std::ostringstream ss;
serialize_single_value(ss, v);
vv.push_back(ss.str());
}
return vv;
}
bool deserialize(const std::string& str, bool append = false) override
{
if (!append)
this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
boost::trim(item_str);
if (item_str == "nil") {
if (NULLABLE)
this->values.push_back(nil_value());
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
}
else {
auto it = this->keys_map->find(item_str);
if (it == this->keys_map->end())
return false;
this->values.push_back(it->second);
}
}
return true;
}
private:
void serialize_single_value(std::ostringstream& ss, const int v) const {
if (v == nil_value()) {
if (NULLABLE)
ss << "nil";
else
throw ConfigurationError("Serializing NaN");
}
else {
for (const auto& kvp : *this->keys_map)
if (kvp.second == v) {
ss << kvp.first;
return;
}
ss << std::string();
}
}
friend class cereal::access;
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionVector<int>>(this)); }
};
using ConfigOptionEnumsGeneric = ConfigOptionEnumsGenericTempl<false>;
using ConfigOptionEnumsGenericNullable = ConfigOptionEnumsGenericTempl<true>;
// Definition of values / labels for a combo box. // Definition of values / labels for a combo box.
// Mostly used for closed enums (when type == coEnum), but may be used for // 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. // open enums with ints resp. floats, if gui_type is set to GUIType::i_enum_open" resp. GUIType::f_enum_open.
@ -2043,6 +2279,7 @@ public:
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
case coBools: { auto opt = new ConfigOptionBools(); 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 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); default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
} }
} }
@ -2077,6 +2314,7 @@ public:
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break; case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break; case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break; case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
case coEnums: archive(*static_cast<const ConfigOptionEnumsGeneric*>(opt)); break;
default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key); default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
} }
} }
@ -2484,6 +2722,8 @@ public:
// Thus the virtual method getInt() is used to retrieve the enum value. // Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM> template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); } ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionEnums<ENUM>*>(this->option(opt_key))->get_at(idx);}
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; } bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; } bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }

View File

@ -19,6 +19,7 @@
#include "libslic3r/miniz_extension.hpp" #include "libslic3r/miniz_extension.hpp"
#include "libslic3r/LocalesUtils.hpp" #include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/GCode/ThumbnailData.hpp" #include "libslic3r/GCode/ThumbnailData.hpp"
#include "libslic3r/Utils/JsonUtils.hpp"
#include "SLAArchiveReader.hpp" #include "SLAArchiveReader.hpp"
#include "SLAArchiveFormatRegistry.hpp" #include "SLAArchiveFormatRegistry.hpp"
@ -33,6 +34,7 @@
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -51,6 +53,110 @@ std::string to_ini(const ConfMap &m)
return ret; return ret;
} }
static std::string get_key(const std::string& opt_key)
{
static const std::set<std::string> ms_opts = {
"delay_before_exposure"
, "delay_after_exposure"
, "tilt_down_offset_delay"
, "tilt_up_offset_delay"
, "tilt_down_delay"
, "tilt_up_delay"
};
static const std::set<std::string> nm_opts = {
"tower_hop_height"
};
static const std::set<std::string> speed_opts = {
"tower_speed"
, "tilt_down_initial_speed"
, "tilt_down_finish_speed"
, "tilt_up_initial_speed"
, "tilt_up_finish_speed"
};
if (ms_opts.find(opt_key) != ms_opts.end())
return opt_key + "_ms";
if (nm_opts.find(opt_key) != nm_opts.end())
return opt_key + "_nm";
if (speed_opts.find(opt_key) != speed_opts.end())
return boost::replace_all_copy(opt_key, "_speed", "_profile");
return opt_key;
}
namespace pt = boost::property_tree;
std::string to_json(const SLAPrint& print, const ConfMap &m)
{
auto& cfg = print.full_print_config();
pt::ptree below_node;
pt::ptree above_node;
const t_config_enum_names& tilt_enum_names = ConfigOptionEnum< TiltSpeeds>::get_enum_names();
const t_config_enum_names& tower_enum_names = ConfigOptionEnum<TowerSpeeds>::get_enum_names();
for (const std::string& opt_key : tilt_options()) {
const ConfigOption* opt = cfg.option(opt_key);
assert(opt != nullptr);
switch (opt->type()) {
case coFloats: {
auto values = static_cast<const ConfigOptionFloats*>(opt);
// those options have to be exported in ms instead of s
below_node.put<double>(get_key(opt_key), int(1000 * values->get_at(0)));
above_node.put<double>(get_key(opt_key), int(1000 * values->get_at(1)));
}
break;
case coInts: {
auto values = static_cast<const ConfigOptionInts*>(opt);
int koef = opt_key == "tower_hop_height" ? 1000000 : 1;
below_node.put<int>(get_key(opt_key), koef * values->get_at(0));
above_node.put<int>(get_key(opt_key), koef * values->get_at(1));
}
break;
case coBools: {
auto values = static_cast<const ConfigOptionBools*>(opt);
below_node.put<bool>(get_key(opt_key), values->get_at(0));
above_node.put<bool>(get_key(opt_key), values->get_at(1));
}
break;
case coEnums: {
const t_config_enum_names& enum_names = opt_key == "tower_speed" ? tower_enum_names : tilt_enum_names;
auto values = static_cast<const ConfigOptionEnums<TiltSpeeds>*>(opt);
below_node.put(get_key(opt_key), enum_names[values->get_at(0)]);
above_node.put(get_key(opt_key), enum_names[values->get_at(1)]);
}
break;
case coNone:
default:
break;
}
}
pt::ptree profile_node;
profile_node.put("area_fill", cfg.option("area_fill")->serialize());
profile_node.add_child("below_area_fill", below_node);
profile_node.add_child("above_area_fill", above_node);
pt::ptree root;
// params from config.ini
for (auto& param : m)
root.put(param.first, param.second );
root.put("version", "1");
root.add_child("exposure_profile", profile_node);
// Boost confirms its implementation has no 100% conformance to JSON standard.
// In the boost libraries, boost will always serialize each value as string and parse all values to a string equivalent.
// so, post-prosess output
return write_json_with_post_process(root);
}
std::string get_cfg_value(const DynamicPrintConfig &cfg, const std::string &key) std::string get_cfg_value(const DynamicPrintConfig &cfg, const std::string &key)
{ {
std::string ret; std::string ret;
@ -123,10 +229,15 @@ void fill_slicerconf(ConfMap &m, const SLAPrint &print)
auto is_banned = [](const std::string &key) { auto is_banned = [](const std::string &key) {
return std::binary_search(banned_keys.begin(), banned_keys.end(), key); return std::binary_search(banned_keys.begin(), banned_keys.end(), key);
}; };
auto is_tilt_param = [](const std::string& key) -> bool {
const auto& keys = tilt_options();
return std::find(keys.begin(), keys.end(), key) != keys.end();
};
auto &cfg = print.full_print_config(); auto &cfg = print.full_print_config();
for (const std::string &key : cfg.keys()) for (const std::string &key : cfg.keys())
if (! is_banned(key) && ! cfg.option(key)->is_nil()) if (! is_banned(key) && !is_tilt_param(key) && ! cfg.option(key)->is_nil())
m[key] = cfg.opt_serialize(key); m[key] = cfg.opt_serialize(key);
} }
@ -212,6 +323,9 @@ void SL1Archive::export_print(Zipper &zipper,
zipper.add_entry("prusaslicer.ini"); zipper.add_entry("prusaslicer.ini");
zipper << to_ini(slicerconf); zipper << to_ini(slicerconf);
zipper.add_entry("config.json");
zipper << to_json(print, iniconf);
size_t i = 0; size_t i = 0;
for (const sla::EncodedRaster &rst : m_layers) { for (const sla::EncodedRaster &rst : m_layers) {

View File

@ -26,6 +26,7 @@
#include <fstream> #include <fstream>
#include <stdexcept> #include <stdexcept>
#include <unordered_map> #include <unordered_map>
#include <boost/range/join.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
@ -606,6 +607,7 @@ static std::vector<std::string> s_Preset_sla_material_options {
"material_notes", "material_notes",
"material_vendor", "material_vendor",
"material_print_speed", "material_print_speed",
"area_fill",
"default_sla_material_profile", "default_sla_material_profile",
"compatible_prints", "compatible_prints_condition", "compatible_prints", "compatible_prints_condition",
"compatible_printers", "compatible_printers_condition", "inherits", "compatible_printers", "compatible_printers_condition", "inherits",
@ -622,20 +624,40 @@ static std::vector<std::string> s_Preset_sla_material_options {
"material_ow_branchingsupport_pillar_diameter", "material_ow_branchingsupport_pillar_diameter",
"material_ow_support_points_density_relative", "material_ow_support_points_density_relative",
"material_ow_absolute_correction",
"material_ow_relative_correction_x",
"material_ow_relative_correction_y",
"material_ow_relative_correction_z",
"material_ow_elefant_foot_compensation" "material_ow_elefant_foot_compensation"
}; };
static std::vector<std::string> s_Preset_sla_tilt_options{
"delay_before_exposure"
,"delay_after_exposure"
,"tower_hop_height"
,"tower_speed"
,"use_tilt"
,"tilt_down_initial_speed"
,"tilt_down_offset_steps"
,"tilt_down_offset_delay"
,"tilt_down_finish_speed"
,"tilt_down_cycles"
,"tilt_down_delay"
,"tilt_up_initial_speed"
,"tilt_up_offset_steps"
,"tilt_up_offset_delay"
,"tilt_up_finish_speed"
,"tilt_up_cycles"
,"tilt_up_delay"
};
const std::vector<std::string>& tilt_options() { return s_Preset_sla_tilt_options; }
static std::vector<std::string> s_Preset_sla_material_options_all = boost::copy_range<std::vector<std::string>>(boost::join(s_Preset_sla_material_options, s_Preset_sla_tilt_options));
static std::vector<std::string> s_Preset_sla_printer_options { static std::vector<std::string> s_Preset_sla_printer_options {
"printer_technology", "printer_technology",
"bed_shape", "bed_custom_texture", "bed_custom_model", "max_print_height", "bed_shape", "bed_custom_texture", "bed_custom_model", "max_print_height",
"display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_width", "display_height", "display_pixels_x", "display_pixels_y",
"display_mirror_x", "display_mirror_y", "display_mirror_x", "display_mirror_y",
"display_orientation", "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",
"relative_correction_x", "relative_correction_x",
"relative_correction_y", "relative_correction_y",
@ -659,7 +681,7 @@ const std::vector<std::string>& Preset::machine_limits_options() { return s_Pres
// of the nozzle_diameter vector. // of the nozzle_diameter vector.
const std::vector<std::string>& Preset::nozzle_options() { return print_config_def.extruder_option_keys(); } const std::vector<std::string>& Preset::nozzle_options() { return print_config_def.extruder_option_keys(); }
const std::vector<std::string>& Preset::sla_print_options() { return s_Preset_sla_print_options; } const std::vector<std::string>& Preset::sla_print_options() { return s_Preset_sla_print_options; }
const std::vector<std::string>& Preset::sla_material_options() { return s_Preset_sla_material_options; } const std::vector<std::string>& Preset::sla_material_options() { return s_Preset_sla_material_options_all; }
const std::vector<std::string>& Preset::sla_printer_options() { return s_Preset_sla_printer_options; } const std::vector<std::string>& Preset::sla_printer_options() { return s_Preset_sla_printer_options; }
const std::vector<std::string>& Preset::printer_options() const std::vector<std::string>& Preset::printer_options()
@ -1378,6 +1400,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
case coPercents:add_correct_opts_to_diff<ConfigOptionPercents >(opt_key, diff, config_other, config_this); break; case coPercents:add_correct_opts_to_diff<ConfigOptionPercents >(opt_key, diff, config_other, config_this); break;
case coPoints: add_correct_opts_to_diff<ConfigOptionPoints >(opt_key, diff, config_other, config_this); break; case coPoints: add_correct_opts_to_diff<ConfigOptionPoints >(opt_key, diff, config_other, config_this); break;
case coFloatsOrPercents: add_correct_opts_to_diff<ConfigOptionFloatsOrPercents >(opt_key, diff, config_other, config_this); break; case coFloatsOrPercents: add_correct_opts_to_diff<ConfigOptionFloatsOrPercents >(opt_key, diff, config_other, config_this); break;
case coEnums: add_correct_opts_to_diff<ConfigOptionEnumsGeneric>(opt_key, diff, config_other, config_this); break;
default: diff.emplace_back(opt_key); break; default: diff.emplace_back(opt_key); break;
} }
// "nozzle_diameter" is a vector option which contain info about diameter for each nozzle // "nozzle_diameter" is a vector option which contain info about diameter for each nozzle

View File

@ -257,6 +257,7 @@ static t_config_enum_values s_keys_map_PerimeterGeneratorType {
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType)
static t_config_enum_values s_keys_map_TopOnePerimeterType { static t_config_enum_values s_keys_map_TopOnePerimeterType {
{ "none", int(TopOnePerimeterType::None) }, { "none", int(TopOnePerimeterType::None) },
{ "top", int(TopOnePerimeterType::TopSurfaces) }, { "top", int(TopOnePerimeterType::TopSurfaces) },
@ -264,6 +265,39 @@ static t_config_enum_values s_keys_map_TopOnePerimeterType {
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TopOnePerimeterType) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TopOnePerimeterType)
static const t_config_enum_values s_keys_map_TowerSpeeds{
{ "layer1", tsLayer1 },
{ "layer2", tsLayer2 },
{ "layer3", tsLayer3 },
{ "layer4", tsLayer4 },
{ "layer5", tsLayer5 },
{ "layer8", tsLayer8 },
{ "layer11", tsLayer11 },
{ "layer14", tsLayer14 },
{ "layer18", tsLayer18 },
{ "layer22", tsLayer22 },
{ "layer24", tsLayer24 },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TowerSpeeds)
static const t_config_enum_values s_keys_map_TiltSpeeds{
{ "move120", tsMove120 },
{ "layer200", tsLayer200 },
{ "move300", tsMove300 },
{ "layer400", tsLayer400 },
{ "layer600", tsLayer600 },
{ "layer800", tsLayer800 },
{ "layer1000", tsLayer1000 },
{ "layer1250", tsLayer1250 },
{ "layer1500", tsLayer1500 },
{ "layer1750", tsLayer1750 },
{ "layer2000", tsLayer2000 },
{ "layer2250", tsLayer2250 },
{ "move5120", tsMove5120 },
{ "move8000", tsMove8000 },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TiltSpeeds)
static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology) static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology)
{ {
for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options) for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options)
@ -284,6 +318,7 @@ PrintConfigDef::PrintConfigDef()
this->init_extruder_option_keys(); this->init_extruder_option_keys();
assign_printer_technology_to_unknown(this->options, ptFFF); assign_printer_technology_to_unknown(this->options, ptFFF);
this->init_sla_params(); this->init_sla_params();
this->init_sla_tilt_params();
assign_printer_technology_to_unknown(this->options, ptSLA); assign_printer_technology_to_unknown(this->options, ptSLA);
this->finalize(); this->finalize();
} }
@ -3949,12 +3984,14 @@ void PrintConfigDef::init_sla_params()
def->set_default_value(new ConfigOptionFloat(10.)); def->set_default_value(new ConfigOptionFloat(10.));
def = this->add("area_fill", coFloat); def = this->add("area_fill", coFloat);
def->label = L("Area fill"); def->label = L("Area fill threshold");
def->tooltip = L("The percentage of the bed area. \nIf the print area exceeds the specified value, \nthen a slow tilt will be used, otherwise - a fast tilt"); def->tooltip = L("The value is expressed as a percentage of the bed area. If the area of a particular layer "
"is smaller than 'area_fill', then 'Below area fill threshold' parameters are used to determine the "
"layer separation (tearing) procedure. Otherwise 'Above area fill threshold' parameters are used.");
def->sidetext = L("%"); def->sidetext = L("%");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(50.)); def->set_default_value(new ConfigOptionFloat(35.));
def = this->add("relative_correction", coFloats); def = this->add("relative_correction", coFloats);
def->label = L("Printer scaling correction"); def->label = L("Printer scaling correction");
@ -3993,6 +4030,7 @@ void PrintConfigDef::init_sla_params()
def->full_label = L("Printer absolute correction"); def->full_label = L("Printer absolute correction");
def->tooltip = L("Will inflate or deflate the sliced 2D polygons according " def->tooltip = L("Will inflate or deflate the sliced 2D polygons according "
"to the sign of the correction."); "to the sign of the correction.");
def->sidetext = L("mm");
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.0)); def->set_default_value(new ConfigOptionFloat(0.0));
@ -4444,8 +4482,7 @@ void PrintConfigDef::init_sla_params()
"support_head_penetration", "branchingsupport_head_penetration", "support_head_penetration", "branchingsupport_head_penetration",
"support_head_width", "branchingsupport_head_width", "support_head_width", "branchingsupport_head_width",
"support_pillar_diameter", "branchingsupport_pillar_diameter", "support_pillar_diameter", "branchingsupport_pillar_diameter",
"relative_correction_x", "relative_correction_y", "relative_correction_z", "elefant_foot_compensation", "absolute_correction",
"elefant_foot_compensation",
// int // int
"support_points_density_relative" "support_points_density_relative"
}) { }) {
@ -4467,6 +4504,186 @@ void PrintConfigDef::init_sla_params()
} }
} }
// SLA Materials "sub-presets" settings
void PrintConfigDef::init_sla_tilt_params()
{
ConfigOptionDef* def;
def = this->add("delay_before_exposure", coFloats);
def->full_label = L("Delay before exposure");
def->tooltip = L("Delay before exposure after previous layer separation.");
def->sidetext = L("s");
def->min = 0;
def->max = 30;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats({ 3., 3.}));
def = this->add("delay_after_exposure", coFloats);
def->full_label = L("Delay after exposure");
def->tooltip = L("Delay after exposure before layer separation.");
def->sidetext = L("s");
def->min = 0;
def->max = 30;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats({ 0., 0.}));
def = this->add("tower_hop_height", coInts);
def->full_label = L("Tower hop height");
def->tooltip = L("The height of the tower raise.");
def->sidetext = L("mm");
def->min = 0;
def->max = 100;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInts({ 0, 0}));
def = this->add("tower_speed", coEnums);
def->full_label = L("Tower speed");
def->tooltip = L("Tower speed used for tower raise.");
def->mode = comExpert;
def->sidetext = L("mm/s");
def->set_enum<TowerSpeeds>({
{ "layer1", "1" },
{ "layer2", "2" },
{ "layer3", "3" },
{ "layer4", "4" },
{ "layer5", "5" },
{ "layer8", "8" },
{ "layer11", "11" },
{ "layer14", "14" },
{ "layer18", "18" },
{ "layer22", "22" },
{ "layer24", "24" },
});
def->set_default_value(new ConfigOptionEnums<TowerSpeeds>({ tsLayer22, tsLayer22 }));
const std::initializer_list<std::pair<std::string_view, std::string_view>> tilt_speeds_il = {
{ "move120", "120" },
{ "layer200", "200" },
{ "move300", "300" },
{ "layer400", "400" },
{ "layer600", "600" },
{ "layer800", "800" },
{ "layer1000", "1000" },
{ "layer1250", "1250" },
{ "layer1500", "1500" },
{ "layer1750", "1750" },
{ "layer2000", "2000" },
{ "layer2250", "2250" },
{ "move5120", "5120" },
{ "move8000", "8000" },
};
def = this->add("tilt_down_initial_speed", coEnums);
def->full_label = L("Tilt down initial speed");
def->tooltip = L("Tilt speed used for an initial portion of tilt down move.");
def->mode = comExpert;
def->sidetext = L("μ-steps/s");
def->set_enum<TiltSpeeds>(tilt_speeds_il);
def->set_default_value(new ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750 }));
def = this->add("tilt_down_finish_speed", coEnums);
def->full_label = L("Tilt down finish speed");
def->tooltip = L("Tilt speed used for the rest of the tilt down move.");
def->mode = comExpert;
def->sidetext = L("μ-steps/s");
def->set_enum<TiltSpeeds>(tilt_speeds_il);
def->set_default_value(new ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750 }));
def = this->add("tilt_up_initial_speed", coEnums);
def->full_label = L("Tilt up initial speed");
def->tooltip = L("Tilt speed used for an initial portion of tilt up move.");
def->mode = comExpert;
def->sidetext = L("μ-steps/s");
def->set_enum<TiltSpeeds>(tilt_speeds_il);
def->set_default_value(new ConfigOptionEnums<TiltSpeeds>({ tsMove8000, tsMove8000 }));
def = this->add("tilt_up_finish_speed", coEnums);
def->full_label = L("Tilt up finish speed");
def->tooltip = L("Tilt speed used for the rest of the tilt-up.");
def->mode = comExpert;
def->sidetext = L("μ-steps/s");
def->set_enum<TiltSpeeds>(tilt_speeds_il);
def->set_default_value(new ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750 }));
def = this->add("use_tilt", coBools);
def->full_label = L("Use tilt");
def->tooltip = L("If enabled, tilt is used for layer separation. Otherwise, all the parameters below are ignored.");
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("Number of steps to move down from the calibrated (horizontal) position with 'tilt_down_initial_speed'.");
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", coFloats);
def->full_label = L("Tilt down offset delay");
def->tooltip = L("Delay after the tilt reaches 'tilt_down_offset_steps' position.");
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("Number of cycles to split the rest of the tilt down move.");
def->min = 0;
def->max = 10;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInts({ 1, 1 }));
def = this->add("tilt_down_delay", coFloats);
def->full_label = L("Tilt down delay");
def->tooltip = L("The delay between tilt-down cycles.");
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("Move tilt up to calibrated (horizontal) position minus this offset.");
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", coFloats);
def->full_label = L("Tilt up offset delay");
def->tooltip = L("Delay after the tilt reaches 'tilt_up_offset_steps' position.");
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("Number of cycles to split the rest of the tilt-up.");
def->min = 0;
def->max = 10;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInts({ 1, 1 }));
def = this->add("tilt_up_delay", coFloats);
def->full_label = L("Tilt up delay");
def->tooltip = L("The delay between tilt-up cycles.");
def->sidetext = L("s");
def->min = 0;
def->max = 20;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats({ 0., 0. }));
}
// Ignore the following obsolete configuration keys: // Ignore the following obsolete configuration keys:
static std::set<std::string> PrintConfigDef_ignore = { static std::set<std::string> PrintConfigDef_ignore = {
"clip_multipart_objects", "clip_multipart_objects",
@ -4741,6 +4958,87 @@ void DynamicPrintConfig::normalize_fdm()
opt_wall_transition_length->value = std::max(opt_wall_transition_length->value, 0.001); opt_wall_transition_length->value = std::max(opt_wall_transition_length->value, 0.001);
} }
// Default values containe option pair of values (Below and Above) for each titl modes
// (Slow, Fast, HighViscosity and NoTilt) -> used for SL1S and other vendors printers
const std::map<std::string, ConfigOptionFloats> tilt_options_floats_defs =
{
{"delay_before_exposure", ConfigOptionFloats({ 3., 3., 0., 1., 3.5, 3.5, 0., 0. }) } ,
{"delay_after_exposure", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_down_offset_delay", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_down_delay", ConfigOptionFloats({ 0., 0., 0., 0.5, 0., 0., 0., 0. }) } ,
{"tilt_up_offset_delay", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_up_delay", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
};
const std::map<std::string, ConfigOptionInts> tilt_options_ints_defs =
{
{"tower_hop_height", 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<std::string, ConfigOptionBools> tilt_options_bools_defs =
{
{"use_tilt", ConfigOptionBools({ true, true, true, true, true, true, false, false })} ,
};
const std::map<std::string, ConfigOptionEnums<TowerSpeeds>> tower_tilt_options_enums_defs =
{
{"tower_speed", ConfigOptionEnums<TowerSpeeds>({ tsLayer22, tsLayer22, tsLayer22, tsLayer22, tsLayer2, tsLayer2, tsLayer1, tsLayer1 })} ,
};
const std::map<std::string, ConfigOptionEnums<TiltSpeeds>> tilt_options_enums_defs =
{
{"tilt_down_initial_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750, tsLayer1750, tsLayer1750, tsLayer800, tsLayer800, tsMove120, tsMove120 }) } ,
{"tilt_down_finish_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750, tsMove8000, tsLayer1750, tsLayer1750, tsLayer1750, tsMove120, tsMove120 }) } ,
{"tilt_up_initial_speed", ConfigOptionEnums<TiltSpeeds>({ tsMove8000, tsMove8000, tsMove8000, tsMove8000, tsLayer1750, tsLayer1750, tsMove120, tsMove120 }) } ,
{"tilt_up_finish_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer1750, tsLayer1750, tsLayer1750, tsLayer1750, tsLayer800, tsLayer800, tsMove120, tsMove120 }) } ,
};
// Default values containe option pair of values (Below and Above) for each titl modes
// (Slow, Fast, HighViscosity and NoTilt) -> used for SL1 printer
const std::map<std::string, ConfigOptionFloats> tilt_options_floats_sl1_defs =
{
{"delay_before_exposure", ConfigOptionFloats({ 3., 3., 0., 1., 3.5, 3.5, 0., 0. }) } ,
{"delay_after_exposure", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_down_offset_delay", ConfigOptionFloats({ 1., 1., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_down_delay", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
{"tilt_up_offset_delay", ConfigOptionFloats({ 0., 0., 0., 0., 1., 1., 0., 0. }) } ,
{"tilt_up_delay", ConfigOptionFloats({ 0., 0., 0., 0., 0., 0., 0., 0. }) } ,
};
const std::map<std::string, ConfigOptionInts> tilt_options_ints_sl1_defs =
{
{"tower_hop_height", ConfigOptionInts({ 0, 0, 0, 0, 5, 5, 0, 0 }) } ,
{"tilt_down_offset_steps", ConfigOptionInts({ 650, 650, 0, 0, 2200, 2200, 0, 0 }) } ,
{"tilt_down_cycles", ConfigOptionInts({ 1, 1, 1, 1, 1, 1, 0, 0 }) } ,
{"tilt_up_offset_steps", ConfigOptionInts({ 400, 400, 400, 400, 2200, 2200, 0, 0 }) } ,
{"tilt_up_cycles", ConfigOptionInts({ 1, 1, 1, 1, 1, 1, 0, 0 }) } ,
};
const std::map<std::string, ConfigOptionBools> tilt_options_bools_sl1_defs =
{
{"use_tilt", ConfigOptionBools({ true, true, true, true, true, true, false, false })} ,
};
const std::map<std::string, ConfigOptionEnums<TowerSpeeds>> tower_tilt_options_enums_sl1_defs =
{
{"tower_speed", ConfigOptionEnums<TowerSpeeds>({ tsLayer22, tsLayer22, tsLayer22, tsLayer22, tsLayer2, tsLayer2, tsLayer1, tsLayer1 })} ,
};
const std::map<std::string, ConfigOptionEnums<TiltSpeeds>> tilt_options_enums_sl1_defs =
{
{"tilt_down_initial_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer400, tsLayer400, tsLayer400, tsLayer400, tsLayer600, tsLayer600, tsMove120, tsMove120 }) } ,
{"tilt_down_finish_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer1500, tsLayer1500, tsLayer1750, tsLayer1500, tsLayer1500, tsLayer1500, tsMove120, tsMove120 }) } ,
{"tilt_up_initial_speed", ConfigOptionEnums<TiltSpeeds>({ tsMove5120, tsMove5120, tsMove5120, tsMove5120, tsLayer1500, tsLayer1500, tsMove120, tsMove120 }) } ,
{"tilt_up_finish_speed", ConfigOptionEnums<TiltSpeeds>({ tsLayer400, tsLayer400, tsLayer400, tsLayer400, tsLayer600, tsLayer600, tsMove120, tsMove120 }) } ,
};
void handle_legacy_sla(DynamicPrintConfig &config) void handle_legacy_sla(DynamicPrintConfig &config)
{ {
for (std::string corr : {"relative_correction", "material_correction"}) { for (std::string corr : {"relative_correction", "material_correction"}) {
@ -4761,6 +5059,66 @@ 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") // Config from old PS doesn't contain any of tilt options, so check it
) {
int tilt_mode = config.option("material_print_speed")->getInt();
const bool is_sl1_model = config.opt_string("printer_model") == "SL1";
const std::map<std::string, ConfigOptionFloats> floats_defs = is_sl1_model ? tilt_options_floats_sl1_defs : tilt_options_floats_defs;
const std::map<std::string, ConfigOptionInts> ints_defs = is_sl1_model ? tilt_options_ints_sl1_defs : tilt_options_ints_defs;
const std::map<std::string, ConfigOptionBools> bools_defs = is_sl1_model ? tilt_options_bools_sl1_defs : tilt_options_bools_defs;
const std::map<std::string, ConfigOptionEnums<TowerSpeeds>> tower_enums_defs = is_sl1_model ? tower_tilt_options_enums_sl1_defs : tower_tilt_options_enums_defs;
const std::map<std::string, ConfigOptionEnums<TiltSpeeds>> tilt_enums_defs = is_sl1_model ? tilt_options_enums_sl1_defs : tilt_options_enums_defs;
for (const std::string& opt_key : tilt_options()) {
switch (config.def()->get(opt_key)->type) {
case coFloats: {
ConfigOptionFloats values = 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 = 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 = 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: {
int val1, val2;
if (opt_key == "tower_speed") {
auto values = tower_enums_defs.at(opt_key);
val1 = values.get_at(2 * tilt_mode);
val2 = values.get_at(2 * tilt_mode + 1);
}
else {
auto values = tilt_enums_defs.at(opt_key);
val1 = values.get_at(2 * tilt_mode);
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) void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)

View File

@ -171,6 +171,37 @@ enum class GCodeThumbnailsFormat {
PNG, JPG, QOI PNG, JPG, QOI
}; };
enum TowerSpeeds : int {
tsLayer1,
tsLayer2,
tsLayer3,
tsLayer4,
tsLayer5,
tsLayer8,
tsLayer11,
tsLayer14,
tsLayer18,
tsLayer22,
tsLayer24,
};
enum TiltSpeeds : int {
tsMove120,
tsLayer200,
tsMove300,
tsLayer400,
tsLayer600,
tsLayer800,
tsLayer1000,
tsLayer1250,
tsLayer1500,
tsLayer1750,
tsLayer2000,
tsLayer2250,
tsMove5120,
tsMove8000,
};
#define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \ #define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \
template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \ template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \
template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values(); template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values();
@ -226,6 +257,7 @@ private:
void init_fff_params(); void init_fff_params();
void init_extruder_option_keys(); void init_extruder_option_keys();
void init_sla_params(); void init_sla_params();
void init_sla_tilt_params();
void init_sla_support_params(const std::string &method_prefix); void init_sla_support_params(const std::string &method_prefix);
std::vector<std::string> m_extruder_option_keys; std::vector<std::string> m_extruder_option_keys;
@ -305,6 +337,9 @@ public:
{ PrintConfigDef::handle_legacy_composite(*this); } { PrintConfigDef::handle_legacy_composite(*this); }
}; };
// This vector containes list of parameters for preview of tilt profiles
const std::vector<std::string>& tilt_options();
void handle_legacy_sla(DynamicPrintConfig &config); void handle_legacy_sla(DynamicPrintConfig &config);
class StaticPrintConfig : public StaticConfig class StaticPrintConfig : public StaticConfig
@ -1148,11 +1183,28 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatNullable, material_ow_support_head_width)) ((ConfigOptionFloatNullable, material_ow_support_head_width))
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_width)) ((ConfigOptionFloatNullable, material_ow_branchingsupport_head_width))
((ConfigOptionIntNullable, material_ow_support_points_density_relative)) ((ConfigOptionIntNullable, material_ow_support_points_density_relative))
((ConfigOptionFloatNullable, material_ow_elefant_foot_compensation)) ((ConfigOptionFloatNullable, material_ow_elefant_foot_compensation))
((ConfigOptionFloatNullable, material_ow_relative_correction_x)) ((ConfigOptionFloatNullable, material_ow_absolute_correction))
((ConfigOptionFloatNullable, material_ow_relative_correction_y)) ((ConfigOptionFloat, area_fill))
((ConfigOptionFloatNullable, material_ow_relative_correction_z))
//tilt params
((ConfigOptionFloats, delay_before_exposure))
((ConfigOptionFloats, delay_after_exposure))
((ConfigOptionInts, tower_hop_height))
((ConfigOptionEnums<TowerSpeeds>, tower_speed))
((ConfigOptionBools, use_tilt))
((ConfigOptionEnums<TiltSpeeds>, tilt_down_initial_speed))
((ConfigOptionInts, tilt_down_offset_steps))
((ConfigOptionFloats, tilt_down_offset_delay))
((ConfigOptionEnums<TiltSpeeds>, tilt_down_finish_speed))
((ConfigOptionInts, tilt_down_cycles))
((ConfigOptionFloats, tilt_down_delay))
((ConfigOptionEnums<TiltSpeeds>, tilt_up_initial_speed))
((ConfigOptionInts, tilt_up_offset_steps))
((ConfigOptionFloats, tilt_up_offset_delay))
((ConfigOptionEnums<TiltSpeeds>, tilt_up_finish_speed))
((ConfigOptionInts, tilt_up_cycles))
((ConfigOptionFloats, tilt_up_delay))
) )
PRINT_CONFIG_CLASS_DEFINE( PRINT_CONFIG_CLASS_DEFINE(
@ -1179,13 +1231,14 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, fast_tilt_time)) ((ConfigOptionFloat, fast_tilt_time))
((ConfigOptionFloat, slow_tilt_time)) ((ConfigOptionFloat, slow_tilt_time))
((ConfigOptionFloat, high_viscosity_tilt_time)) ((ConfigOptionFloat, high_viscosity_tilt_time))
((ConfigOptionFloat, area_fill)) // ((ConfigOptionFloat, area_fill))
((ConfigOptionFloat, min_exposure_time)) ((ConfigOptionFloat, min_exposure_time))
((ConfigOptionFloat, max_exposure_time)) ((ConfigOptionFloat, max_exposure_time))
((ConfigOptionFloat, min_initial_exposure_time)) ((ConfigOptionFloat, min_initial_exposure_time))
((ConfigOptionFloat, max_initial_exposure_time)) ((ConfigOptionFloat, max_initial_exposure_time))
((ConfigOptionString, sla_archive_format)) ((ConfigOptionString, sla_archive_format))
((ConfigOptionFloat, sla_output_precision)) ((ConfigOptionFloat, sla_output_precision))
((ConfigOptionString, printer_model))
) )
PRINT_CONFIG_CLASS_DERIVED_DEFINE0( PRINT_CONFIG_CLASS_DERIVED_DEFINE0(

View File

@ -219,10 +219,8 @@ static t_config_option_keys print_config_diffs(const StaticPrintConfig &curr
"branchingsupport_head_width"sv, "branchingsupport_head_width"sv,
"branchingsupport_pillar_diameter"sv, "branchingsupport_pillar_diameter"sv,
"support_points_density_relative"sv, "support_points_density_relative"sv,
"relative_correction_x"sv,
"relative_correction_y"sv,
"relative_correction_z"sv,
"elefant_foot_compensation"sv, "elefant_foot_compensation"sv,
"absolute_correction"sv,
}; };
static constexpr auto material_ow_prefix = "material_ow_"; static constexpr auto material_ow_prefix = "material_ow_";
@ -685,6 +683,12 @@ std::string SLAPrint::validate(std::vector<std::string>*) const
} }
} }
if ((!m_material_config.use_tilt.get_at(0) && m_material_config.tower_hop_height.get_at(0) == 0)
|| (!m_material_config.use_tilt.get_at(1) && m_material_config.tower_hop_height.get_at(1) == 0))
return _u8L("Disabling the 'Use tilt' function causes the object to separate away from the film in the "
"vertical direction only. Therefore, it is necessary to set the 'Tower hop height' parameter "
"to reasonable value. The recommended value is 5 mm.");
return ""; return "";
} }
@ -858,7 +862,26 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
"display_mirror_y"sv, "display_mirror_y"sv,
"display_orientation"sv, "display_orientation"sv,
"sla_archive_format"sv, "sla_archive_format"sv,
"sla_output_precision"sv "sla_output_precision"sv,
// tilt params
"delay_before_exposure"sv,
"delay_after_exposure"sv,
"tower_hop_height"sv,
"tower_speed"sv,
"use_tilt"sv,
"tilt_down_initial_speed"sv,
"tilt_down_offset_steps"sv,
"tilt_down_offset_delay"sv,
"tilt_down_finish_speed"sv,
"tilt_down_cycles"sv,
"tilt_down_delay"sv,
"tilt_up_initial_speed"sv,
"tilt_up_offset_steps"sv,
"tilt_up_offset_delay"sv,
"tilt_up_finish_speed"sv,
"tilt_up_cycles"sv,
"tilt_up_delay"sv,
"area_fill"sv,
}; };
static StaticSet steps_ignore = { static StaticSet steps_ignore = {
@ -869,7 +892,6 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
"fast_tilt_time"sv, "fast_tilt_time"sv,
"slow_tilt_time"sv, "slow_tilt_time"sv,
"high_viscosity_tilt_time"sv, "high_viscosity_tilt_time"sv,
"area_fill"sv,
"bottle_cost"sv, "bottle_cost"sv,
"bottle_volume"sv, "bottle_volume"sv,
"bottle_weight"sv, "bottle_weight"sv,
@ -884,9 +906,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
"material_ow_branchingsupport_head_width"sv, "material_ow_branchingsupport_head_width"sv,
"material_ow_elefant_foot_compensation"sv, "material_ow_elefant_foot_compensation"sv,
"material_ow_support_points_density_relative"sv, "material_ow_support_points_density_relative"sv,
"material_ow_relative_correction_x"sv, "material_ow_absolute_correction"sv,
"material_ow_relative_correction_y"sv, "printer_model"sv,
"material_ow_relative_correction_z"sv
}; };
std::vector<SLAPrintStep> steps; std::vector<SLAPrintStep> steps;

View File

@ -406,13 +406,15 @@ struct SLAPrintStatistics
{ {
SLAPrintStatistics() { clear(); } SLAPrintStatistics() { clear(); }
double estimated_print_time; double estimated_print_time;
double estimated_print_time_tolerance;
double objects_used_material; double objects_used_material;
double support_used_material; double support_used_material;
size_t slow_layers_count; size_t slow_layers_count;
size_t fast_layers_count; size_t fast_layers_count;
double total_cost; double total_cost;
double total_weight; double total_weight;
std::vector<double> layers_times; std::vector<double> layers_times_running_total;
std::vector<double> layers_areas;
// Config with the filled in print statistics. // Config with the filled in print statistics.
DynamicConfig config() const; DynamicConfig config() const;
@ -423,13 +425,15 @@ struct SLAPrintStatistics
void clear() { void clear() {
estimated_print_time = 0.; estimated_print_time = 0.;
estimated_print_time_tolerance = 0.;
objects_used_material = 0.; objects_used_material = 0.;
support_used_material = 0.; support_used_material = 0.;
slow_layers_count = 0; slow_layers_count = 0;
fast_layers_count = 0; fast_layers_count = 0;
total_cost = 0.; total_cost = 0.;
total_weight = 0.; total_weight = 0.;
layers_times.clear(); layers_times_running_total.clear();
layers_areas.clear();
} }
}; };

View File

@ -911,6 +911,188 @@ void SLAPrint::Steps::initialize_printer_input()
} }
} }
static int Ms(int s)
{
return s;
}
// constant values from FW
int tiltHeight = 4959; //nm
int tower_microstep_size_nm = 250000;
int first_extra_slow_layers = 3;
int refresh_delay_ms = 0;
static int nm_to_tower_microsteps(int nm) {
// add implementation
return nm / tower_microstep_size_nm;
}
static int count_move_time(const std::string& axis_name, double length, int steprate)
{
if (length < 0 || steprate < 0)
return 0;
// sla - fw checks every 0.1 s if axis is still moving.See: Axis._wait_to_stop_delay.Additional 0.021 s is
// measured average delay of the system.Thus, the axis movement time is always quantized by this value.
double delay = 0.121;
// Both axes use linear ramp movements. This factor compensates the tilt acceleration and deceleration time.
double tilt_comp_factor = 0.1;
// Both axes use linear ramp movements.This factor compensates the tower acceleration and deceleration time.
int tower_comp_factor = 20000;
int l = int(length);
return axis_name == "tower" ? Ms((int(l / (steprate * delay) + (steprate + l) / tower_comp_factor) + 1) * (delay * 1000)) :
Ms((int(l / (steprate * delay) + tilt_comp_factor) + 1) * (delay * 1000));
}
struct ExposureProfile {
// map of internal TowerSpeeds to maximum_steprates (usteps/s)
// this values was provided in default_tower_moving_profiles.json by SLA-team
std::map<TowerSpeeds, int> tower_speeds = {
{ tsLayer1 , 800 },
{ tsLayer2 , 1600 },
{ tsLayer3 , 2400 },
{ tsLayer4 , 3200 },
{ tsLayer5 , 4000 },
{ tsLayer8 , 6400 },
{ tsLayer11, 8800 },
{ tsLayer14, 11200 },
{ tsLayer18, 14400 },
{ tsLayer22, 17600 },
{ tsLayer24, 19200 },
};
// map of internal TiltSpeeds to maximum_steprates (usteps/s)
// this values was provided in default_tilt_moving_profiles.json by SLA-team
std::map<TiltSpeeds, int> tilt_speeds = {
{ tsMove120 , 120 },
{ tsLayer200 , 200 },
{ tsMove300 , 300 },
{ tsLayer400 , 400 },
{ tsLayer600 , 600 },
{ tsLayer800 , 800 },
{ tsLayer1000, 1000 },
{ tsLayer1250, 1250 },
{ tsLayer1500, 1500 },
{ tsLayer1750, 1750 },
{ tsLayer2000, 2000 },
{ tsLayer2250, 2250 },
{ tsMove5120 , 5120 },
{ tsMove8000 , 8000 },
};
int delay_before_exposure_ms { 0 };
int delay_after_exposure_ms { 0 };
int tilt_down_offset_delay_ms { 0 };
int tilt_down_delay_ms { 0 };
int tilt_up_offset_delay_ms { 0 };
int tilt_up_delay_ms { 0 };
int tower_hop_height_nm { 0 };
int tilt_down_offset_steps { 0 };
int tilt_down_cycles { 0 };
int tilt_up_offset_steps { 0 };
int tilt_up_cycles { 0 };
bool use_tilt { true };
int tower_speed { 0 };
int tilt_down_initial_speed { 0 };
int tilt_down_finish_speed { 0 };
int tilt_up_initial_speed { 0 };
int tilt_up_finish_speed { 0 };
ExposureProfile() {}
ExposureProfile(const SLAMaterialConfig& config, int opt_id)
{
delay_before_exposure_ms = int(1000 * config.delay_before_exposure.get_at(opt_id));
delay_after_exposure_ms = int(1000 * config.delay_after_exposure.get_at(opt_id));
tilt_down_offset_delay_ms = int(1000 * config.tilt_down_offset_delay.get_at(opt_id));
tilt_down_delay_ms = int(1000 * config.tilt_down_delay.get_at(opt_id));
tilt_up_offset_delay_ms = int(1000 * config.tilt_up_offset_delay.get_at(opt_id));
tilt_up_delay_ms = int(1000 * config.tilt_up_delay.get_at(opt_id));
tower_hop_height_nm = config.tower_hop_height.get_at(opt_id) * 1000000;
tilt_down_offset_steps = config.tilt_down_offset_steps.get_at(opt_id);
tilt_down_cycles = config.tilt_down_cycles.get_at(opt_id);
tilt_up_offset_steps = config.tilt_up_offset_steps.get_at(opt_id);
tilt_up_cycles = config.tilt_up_cycles.get_at(opt_id);
use_tilt = config.use_tilt.get_at(opt_id);
tower_speed = tower_speeds.at(static_cast<TowerSpeeds>(config.tower_speed.getInts()[opt_id]));
tilt_down_initial_speed = tilt_speeds.at(static_cast<TiltSpeeds>(config.tilt_down_initial_speed.getInts()[opt_id]));
tilt_down_finish_speed = tilt_speeds.at(static_cast<TiltSpeeds>(config.tilt_down_finish_speed.getInts()[opt_id]));
tilt_up_initial_speed = tilt_speeds.at(static_cast<TiltSpeeds>(config.tilt_up_initial_speed.getInts()[opt_id]));
tilt_up_finish_speed = tilt_speeds.at(static_cast<TiltSpeeds>(config.tilt_up_finish_speed.getInts()[opt_id]));
}
};
static int layer_peel_move_time(int layer_height_nm, ExposureProfile p)
{
int profile_change_delay = Ms(20); // propagation delay of sending profile change command to MC
int sleep_delay = Ms(2); // average delay of the Linux system sleep function
int tilt = Ms(0);
if (p.use_tilt) {
tilt += profile_change_delay;
// initial down movement
tilt += count_move_time(
"tilt",
p.tilt_down_offset_steps,
p.tilt_down_initial_speed);
// initial down delay
tilt += p.tilt_down_offset_delay_ms + sleep_delay;
// profile change delay if down finish profile is different from down initial
tilt += profile_change_delay;
// cycle down movement
tilt += p.tilt_down_cycles * count_move_time(
"tilt",
int((tiltHeight - p.tilt_down_offset_steps) / p.tilt_down_cycles),
p.tilt_down_finish_speed);
// cycle down delay
tilt += p.tilt_down_cycles * (p.tilt_down_delay_ms + sleep_delay);
// profile change delay if up initial profile is different from down finish
tilt += profile_change_delay;
// initial up movement
tilt += count_move_time(
"tilt",
tiltHeight - p.tilt_up_offset_steps,
p.tilt_up_initial_speed);
// initial up delay
tilt += p.tilt_up_offset_delay_ms + sleep_delay;
// profile change delay if up initial profile is different from down finish
tilt += profile_change_delay;
// finish up movement
tilt += p.tilt_up_cycles * count_move_time(
"tilt",
int(p.tilt_up_offset_steps / p.tilt_up_cycles),
p.tilt_up_finish_speed);
// cycle down delay
tilt += p.tilt_up_cycles * (p.tilt_up_delay_ms + sleep_delay);
}
int tower = Ms(0);
if (p.tower_hop_height_nm > 0) {
tower += count_move_time(
"tower",
nm_to_tower_microsteps(int(p.tower_hop_height_nm) + layer_height_nm),
p.tower_speed);
tower += count_move_time(
"tower",
nm_to_tower_microsteps(int(p.tower_hop_height_nm)),
p.tower_speed);
tower += profile_change_delay;
}
else {
tower += count_move_time(
"tower",
nm_to_tower_microsteps(layer_height_nm),
p.tower_speed);
tower += profile_change_delay;
}
return int(tilt + tower);
}
// Merging the slices from all the print objects into one slice grid and // Merging the slices from all the print objects into one slice grid and
// calculating print statistics from the merge result. // calculating print statistics from the merge result.
void SLAPrint::Steps::merge_slices_and_eval_stats() { void SLAPrint::Steps::merge_slices_and_eval_stats() {
@ -924,7 +1106,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
print_statistics.clear(); print_statistics.clear();
const double area_fill = printer_config.area_fill.getFloat()*0.01;// 0.5 (50%); const double area_fill = material_config.area_fill.getFloat()*0.01;// 0.5 (50%);
const double fast_tilt = printer_config.fast_tilt_time.getFloat();// 5.0; 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 slow_tilt = printer_config.slow_tilt_time.getFloat();// 8.0;
const double hv_tilt = printer_config.high_viscosity_tilt_time.getFloat();// 10.0; const double hv_tilt = printer_config.high_viscosity_tilt_time.getFloat();// 10.0;
@ -934,34 +1116,29 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
const int fade_layers_cnt = m_print->m_default_object_config.faded_layers.getInt();// 10 // [3;20] const int fade_layers_cnt = m_print->m_default_object_config.faded_layers.getInt();// 10 // [3;20]
ExposureProfile below(material_config, 0);
ExposureProfile above(material_config, 1);
const int first_slow_layers = fade_layers_cnt + first_extra_slow_layers;
const std::string printer_model = printer_config.printer_model;
const bool is_prusa_print = printer_model == "SL1" || printer_model == "SL1S" || printer_model == "M1";
const auto width = scaled<double>(printer_config.display_width.getFloat()); const auto width = scaled<double>(printer_config.display_width.getFloat());
const auto height = scaled<double>(printer_config.display_height.getFloat()); const auto height = scaled<double>(printer_config.display_height.getFloat());
const double display_area = width*height; const double display_area = width*height;
double supports_volume(0.0); std::vector<std::tuple<double, double, bool, double, double>> layers_info; // time, area, is_fast, models_volume, supports_volume
double models_volume(0.0); layers_info.resize(printer_input.size());
double estim_time(0.0);
std::vector<double> layers_times;
layers_times.reserve(printer_input.size());
size_t slow_layers = 0;
size_t fast_layers = 0;
const double delta_fade_time = (init_exp_time - exp_time) / (fade_layers_cnt + 1); const double delta_fade_time = (init_exp_time - exp_time) / (fade_layers_cnt + 1);
double fade_layer_time = init_exp_time;
execution::SpinningMutex<ExecutionTBB> mutex;
using Lock = std::lock_guard<decltype(mutex)>;
// Going to parallel: // Going to parallel:
auto printlayerfn = [this, auto printlayerfn = [this,
// functions and read only vars // functions and read only vars
area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, hv_tilt, material_config, delta_fade_time, area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, hv_tilt, material_config, delta_fade_time, is_prusa_print, first_slow_layers, below, above,
// write vars // write vars
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers, &layers_info](size_t sliced_layer_cnt)
&fast_layers, &fade_layer_time, &layers_times](size_t sliced_layer_cnt)
{ {
PrintLayer &layer = m_print->m_printer_input[sliced_layer_cnt]; PrintLayer &layer = m_print->m_printer_input[sliced_layer_cnt];
@ -1011,9 +1188,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
for (const ExPolygon& polygon : model_polygons) for (const ExPolygon& polygon : model_polygons)
layer_model_area += area(polygon); layer_model_area += area(polygon);
if (layer_model_area < 0 || layer_model_area > 0) { const double models_volume = (layer_model_area < 0 || layer_model_area > 0) ? layer_model_area * l_height : 0.;
Lock lck(mutex); models_volume += layer_model_area * l_height;
}
if(!supports_polygons.empty()) { if(!supports_polygons.empty()) {
if(model_polygons.empty()) supports_polygons = union_ex(supports_polygons); if(model_polygons.empty()) supports_polygons = union_ex(supports_polygons);
@ -1025,9 +1200,8 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
for (const ExPolygon& polygon : supports_polygons) for (const ExPolygon& polygon : supports_polygons)
layer_support_area += area(polygon); layer_support_area += area(polygon);
if (layer_support_area < 0 || layer_support_area > 0) { const double supports_volume = (layer_support_area < 0 || layer_support_area > 0) ? layer_support_area * l_height : 0.;
Lock lck(mutex); supports_volume += layer_support_area * l_height; const double layer_area = layer_model_area + layer_support_area;
}
// Here we can save the expensively calculated polygons for printing // Here we can save the expensively calculated polygons for printing
ExPolygons trslices; ExPolygons trslices;
@ -1037,34 +1211,32 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
layer.transformed_slices(union_ex(trslices)); layer.transformed_slices(union_ex(trslices));
// Calculation of the slow and fast layers to the future controlling those values on FW // Calculation of the printing time
// + Calculation of the slow and fast layers to the future controlling those values on FW
double layer_times = 0.0;
bool is_fast_layer = false;
const bool is_fast_layer = (layer_model_area + layer_support_area) <= display_area*area_fill; if (is_prusa_print) {
const double tilt_time = material_config.material_print_speed == slamsSlow ? slow_tilt : is_fast_layer = int(sliced_layer_cnt) < first_slow_layers || layer_area <= display_area * area_fill;
material_config.material_print_speed == slamsHighViscosity ? hv_tilt : const int l_height_nm = 1000000 * l_height;
is_fast_layer ? fast_tilt : slow_tilt;
{ Lock lck(mutex); layer_times = layer_peel_move_time(l_height_nm, is_fast_layer ? below : above) +
if (is_fast_layer) (is_fast_layer ? below : above).delay_before_exposure_ms +
fast_layers++; (is_fast_layer ? below : above).delay_after_exposure_ms +
else refresh_delay_ms * 5 + // ~ 5x frame display wait
slow_layers++; 124; // Magical constant to compensate remaining computation delay in exposure thread
// Calculation of the printing time layer_times *= 0.001; // All before calculations are made in ms, but we need it in s
}
else {
is_fast_layer = layer_area <= display_area*area_fill;
const double tilt_time = material_config.material_print_speed == slamsSlow ? slow_tilt :
material_config.material_print_speed == slamsHighViscosity ? hv_tilt :
is_fast_layer ? fast_tilt : slow_tilt;
double layer_times = 0.0;
if (sliced_layer_cnt < 3)
layer_times += init_exp_time;
else if (fade_layer_time > exp_time) {
fade_layer_time -= delta_fade_time;
layer_times += fade_layer_time;
}
else
layer_times += exp_time;
layer_times += tilt_time; layer_times += tilt_time;
//// Per layer times (magical constants cuclulated from FW) //// Per layer times (magical constants cuclulated from FW)
static double exposure_safe_delay_before{ 3.0 }; static double exposure_safe_delay_before{ 3.0 };
static double exposure_high_viscosity_delay_before{ 3.5 }; static double exposure_high_viscosity_delay_before{ 3.5 };
static double exposure_slow_move_delay_before{ 1.0 }; static double exposure_slow_move_delay_before{ 1.0 };
@ -1081,33 +1253,41 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
l_height * 5 // tower move l_height * 5 // tower move
+ 120 / 1000 // Magical constant to compensate remaining computation delay in exposure thread + 120 / 1000 // Magical constant to compensate remaining computation delay in exposure thread
); );
layers_times.push_back(layer_times);
estim_time += layer_times;
} }
// We are done with tilt time, but we haven't added the exposure time yet.
layer_times += std::max(exp_time, init_exp_time - sliced_layer_cnt * delta_fade_time);
// Collect values for this layer.
layers_info[sliced_layer_cnt] = std::make_tuple(layer_times, layer_area * SCALING_FACTOR * SCALING_FACTOR, is_fast_layer, models_volume, supports_volume);
}; };
// sequential version for debugging: // sequential version for debugging:
// for(size_t i = 0; i < m_printer_input.size(); ++i) printlayerfn(i); // for(size_t i = 0; i < printer_input.size(); ++i) printlayerfn(i);
execution::for_each(ex_tbb, size_t(0), printer_input.size(), printlayerfn, execution::for_each(ex_tbb, size_t(0), printer_input.size(), printlayerfn,
execution::max_concurrency(ex_tbb)); execution::max_concurrency(ex_tbb));
auto SCALING2 = SCALING_FACTOR * SCALING_FACTOR; print_statistics.clear();
print_statistics.support_used_material = supports_volume * SCALING2;
print_statistics.objects_used_material = models_volume * SCALING2;
// Estimated printing time
// A layers count o the highest object
if (printer_input.size() == 0) if (printer_input.size() == 0)
print_statistics.estimated_print_time = NaNd; print_statistics.estimated_print_time = NaNd;
else { else {
print_statistics.estimated_print_time = estim_time; size_t i=0;
print_statistics.layers_times = layers_times; for (const auto& [time, area, is_fast, models_volume, supports_volume] : layers_info) {
print_statistics.fast_layers_count += int(is_fast);
print_statistics.slow_layers_count += int(! is_fast);
print_statistics.layers_areas.emplace_back(area);
print_statistics.estimated_print_time += time;
print_statistics.layers_times_running_total.emplace_back(time + (i==0 ? 0. : print_statistics.layers_times_running_total[i-1]));
print_statistics.objects_used_material += models_volume * SCALING_FACTOR * SCALING_FACTOR;
print_statistics.support_used_material += supports_volume * SCALING_FACTOR * SCALING_FACTOR;
++i;
}
if (is_prusa_print)
// For our SLA printers, we add an error of the estimate:
print_statistics.estimated_print_time_tolerance = 0.03 * print_statistics.estimated_print_time;
} }
print_statistics.fast_layers_count = fast_layers;
print_statistics.slow_layers_count = slow_layers;
report_status(-2, "", SlicingStatus::RELOAD_SLA_PREVIEW); report_status(-2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
} }

View File

@ -117,8 +117,7 @@ void DSForLayers::SetLayersTimes(const std::vector<double>& layers_times)
{ {
m_ticks.is_wipe_tower = false; m_ticks.is_wipe_tower = false;
m_layers_times = layers_times; m_layers_times = layers_times;
for (size_t i = 1; i < m_layers_times.size(); i++) std::copy(layers_times.begin(), layers_times.end(), m_layers_times.begin());
m_layers_times[i] += m_layers_times[i - 1];
} }
void DSForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print) void DSForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print)

View File

@ -1156,6 +1156,10 @@ void Choice::set_selection()
field->SetSelection(m_opt.default_value->getInt()); field->SetSelection(m_opt.default_value->getInt());
break; break;
} }
case coEnums:{
field->SetSelection(m_opt.default_value->getInts()[m_opt_idx]);
break;
}
case coFloat: case coFloat:
case coPercent: { case coPercent: {
double val = m_opt.default_value->getFloat(); double val = m_opt.default_value->getFloat();
@ -1243,7 +1247,8 @@ void Choice::set_value(const boost::any& value, bool change_event)
break; break;
} }
case coEnum: { case coEnum:
case coEnums: {
auto val = m_opt.enum_def->enum_to_index(boost::any_cast<int>(value)); auto val = m_opt.enum_def->enum_to_index(boost::any_cast<int>(value));
assert(val.has_value()); assert(val.has_value());
field->SetSelection(val.has_value() ? *val : 0); field->SetSelection(val.has_value() ? *val : 0);
@ -1308,7 +1313,7 @@ boost::any& Choice::get_value()
if (m_opt_id == rp_option) if (m_opt_id == rp_option)
return m_value = boost::any(ret_str); 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. // 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()); 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) { else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) {

View File

@ -6250,6 +6250,40 @@ void GLCanvas3D::_render_camera_target()
} }
#endif // ENABLE_SHOW_CAMERA_TARGET #endif // ENABLE_SHOW_CAMERA_TARGET
static void render_sla_layer_legend(const SLAPrint& print, int layer_idx, int cnv_width)
{
const std::vector<double>& areas = print.print_statistics().layers_areas;
const std::vector<double>& times = print.print_statistics().layers_times_running_total;
const double display_area = print.printer_config().display_height * print.printer_config().display_width;
if (layer_idx >= 0 && layer_idx < int(areas.size())) {
const double area = areas[layer_idx];
const double time = times[layer_idx] - (layer_idx == 0 ? 0. : times[layer_idx-1]);
const double time_until_layer = times[layer_idx];
ImGuiWrapper& imgui = *wxGetApp().imgui();
ImGuiPureWrap::set_next_window_pos(float(cnv_width) - imgui.get_style_scaling() * 5.f, 5.f, ImGuiCond_Always, 1.0f, 0.0f);
ImGui::SetNextWindowBgAlpha(0.6f);
ImGuiPureWrap::begin(_u8L("Layer statistics"), ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoFocusOnAppearing);
ImGui::Text("%s", GUI::format(_u8L("Layer area: %1% mm²"), int(0.1 + std::round(area))).c_str());
int area_percent_int = int(std::round(100. * area/display_area));
ImGui::Text("%s", GUI::format(_u8L("Area fill: %1% %%"), area_percent_int == 0 ? "<1" : std::to_string(area_percent_int)).c_str());
ImGui::Separator();
ImGui::Text("%s", GUI::format(_u8L("Layer time: %1%"), get_time_dhms(time)).c_str());
std::string buffer_str = _u8L("Time since start: %1%");
ImGui::Text("%s", GUI::format(buffer_str, get_time_dhms(time_until_layer)).c_str());
// The dummy control below uses the assumption that the total time string will be the longest
// and forces the width of the window large enough so it does not resize depending on the current value.
ImGui::Dummy(ImVec2(ImGui::CalcTextSize(GUI::format(buffer_str, get_time_dhms(82799)).c_str()).x, 0.));
ImGuiPureWrap::end();
}
}
void GLCanvas3D::_render_sla_slices() void GLCanvas3D::_render_sla_slices()
{ {
if (!m_use_clipping_planes || current_printer_technology() != ptSLA) if (!m_use_clipping_planes || current_printer_technology() != ptSLA)
@ -6261,6 +6295,13 @@ void GLCanvas3D::_render_sla_slices()
// nothing to render, return // nothing to render, return
return; return;
if (print->finished()) {
double slider_width = 0.;
if (const Preview* preview = dynamic_cast<Preview*>(m_canvas->GetParent()))
slider_width = preview->get_layers_slider_width();
render_sla_layer_legend(*print, m_layer_slider_index, get_canvas_size().get_width() - slider_width);
}
double clip_min_z = -m_clipping_planes[0].get_data()[3]; double clip_min_z = -m_clipping_planes[0].get_data()[3];
double clip_max_z = m_clipping_planes[1].get_data()[3]; double clip_max_z = m_clipping_planes[1].get_data()[3];
for (unsigned int i = 0; i < (unsigned int)print_objects.size(); ++i) { for (unsigned int i = 0; i < (unsigned int)print_objects.size(); ++i) {

View File

@ -501,6 +501,7 @@ private:
ClippingPlane m_camera_clipping_plane; ClippingPlane m_camera_clipping_plane;
bool m_use_clipping_planes; bool m_use_clipping_planes;
std::array<SlaCap, 2> m_sla_caps; std::array<SlaCap, 2> m_sla_caps;
int m_layer_slider_index = -1;
std::string m_sidebar_field; std::string m_sidebar_field;
// when true renders an extra frame by not resetting m_dirty to false // when true renders an extra frame by not resetting m_dirty to false
// see request_extra_frame() // see request_extra_frame()
@ -763,6 +764,8 @@ public:
void bed_shape_changed(); void bed_shape_changed();
void set_layer_slider_index(int i) { m_layer_slider_index = i; }
void set_clipping_plane(unsigned int id, const ClippingPlane& plane) { void set_clipping_plane(unsigned int id, const ClippingPlane& plane) {
if (id < 2) { if (id < 2) {
m_clipping_planes[id] = plane; m_clipping_planes[id] = plane;

View File

@ -1383,7 +1383,7 @@ bool GUI_App::on_init_inner()
mainframe->select_tab(size_t(0)); mainframe->select_tab(size_t(0));
sidebar().obj_list()->init_objects(); // propagate model objects to object list sidebar().obj_list()->init_objects(); // propagate model objects to object list
// update_mode(); // !!! do that later update_mode(); // mode sizer doesn't exist anymore, so we came update mode here, before load_current_presets
SetTopWindow(mainframe); SetTopWindow(mainframe);
plater_->init_notification_manager(); plater_->init_notification_manager();

View File

@ -328,14 +328,14 @@ void Preview::render_sliders(GLCanvas3D& canvas)
m_moves_slider->Render(canvas_width, canvas_height, extra_scale); m_moves_slider->Render(canvas_width, canvas_height, extra_scale);
} }
float Preview::get_moves_slider_height() float Preview::get_moves_slider_height() const
{ {
if (m_moves_slider && m_moves_slider->IsShown()) if (m_moves_slider && m_moves_slider->IsShown())
return m_moves_slider->GetHeight(); return m_moves_slider->GetHeight();
return 0.0f; return 0.0f;
} }
float Preview::get_layers_slider_width() float Preview::get_layers_slider_width() const
{ {
if (m_layers_slider && m_layers_slider->IsShown()) if (m_layers_slider && m_layers_slider->IsShown())
return m_layers_slider->GetWidth(); return m_layers_slider->GetWidth();
@ -629,7 +629,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects"); bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_layers_slider->SetDrawMode(sla_print_technology, sequential_print); m_layers_slider->SetDrawMode(sla_print_technology, sequential_print);
if (sla_print_technology) if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times); m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times_running_total);
else else
m_layers_slider->SetLayersTimes(m_canvas->get_gcode_layers_times_cache(), m_gcode_result->print_statistics.modes.front().time); m_layers_slider->SetLayersTimes(m_canvas->get_gcode_layers_times_cache(), m_gcode_result->print_statistics.modes.front().time);
@ -1037,6 +1037,7 @@ void Preview::on_layers_slider_scroll_changed()
else if (tech == ptSLA) { else if (tech == ptSLA) {
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValue())); m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValue()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValue())); m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValue()));
m_canvas->set_layer_slider_index(m_layers_slider->GetHigherPos());
m_canvas->render(); m_canvas->render();
} }
} }

View File

@ -136,8 +136,8 @@ public:
void msw_rescale(); void msw_rescale();
void render_sliders(GLCanvas3D& canvas); void render_sliders(GLCanvas3D& canvas);
float get_layers_slider_width(); float get_layers_slider_width() const;
float get_moves_slider_height(); float get_moves_slider_height() const;
bool is_loaded() const { return m_loaded; } bool is_loaded() const { return m_loaded; }

View File

@ -80,7 +80,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
m_fields.emplace(id, SpinCtrl::Create<SpinCtrl>(this->ctrl_parent(), opt, id)); m_fields.emplace(id, SpinCtrl::Create<SpinCtrl>(this->ctrl_parent(), opt, id));
break; break;
case coEnum: case coEnum:
m_fields.emplace(id, Choice::Create<Choice>(this->ctrl_parent(), opt, id)); case coEnums:
m_fields.emplace(id, Choice::Create<Choice>(this->ctrl_parent(), opt, id));
break; break;
case coPoints: case coPoints:
m_fields.emplace(id, PointCtrl::Create<PointCtrl>(this->ctrl_parent(), opt, id)); m_fields.emplace(id, PointCtrl::Create<PointCtrl>(this->ctrl_parent(), opt, id));
@ -239,6 +240,10 @@ void OptionsGroup::change_opt_value(DynamicPrintConfig& config, const t_config_o
config.set_key_value(opt_key, opt); config.set_key_value(opt_key, opt);
} }
break; break;
case coEnums: {
ConfigOptionEnumsGeneric* vec_new = new ConfigOptionEnumsGeneric(1, boost::any_cast<int>(value));;
config.option<ConfigOptionEnumsGeneric>(opt_key)->set_at(vec_new, opt_index, 0);
break; }
case coPoints: { case coPoints: {
if (opt_key == "bed_shape") { if (opt_key == "bed_shape") {
config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value); config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value);
@ -816,7 +821,7 @@ void ConfigOptionsGroup::Hide()
void ConfigOptionsGroup::Show(const bool show) void ConfigOptionsGroup::Show(const bool show)
{ {
sizer->ShowItems(show); if (sizer) sizer->ShowItems(show);
#if 0//#ifdef __WXGTK__ #if 0//#ifdef __WXGTK__
m_panel->Show(show); m_panel->Show(show);
m_grid_sizer->Show(show); m_grid_sizer->Show(show);
@ -1101,6 +1106,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
case coEnum: case coEnum:
ret = config.option(opt_key)->getInt(); ret = config.option(opt_key)->getInt();
break; break;
case coEnums:
ret = config.option(opt_key)->getInts()[idx];
break;
case coPoints: case coPoints:
if (opt_key == "bed_shape") if (opt_key == "bed_shape")
ret = config.option<ConfigOptionPoints>(opt_key)->values; ret = config.option<ConfigOptionPoints>(opt_key)->values;

View File

@ -99,8 +99,11 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
wxString suffix; wxString suffix;
wxString suffix_local; wxString suffix_local;
if (gc.category == "Machine limits") { if (gc.category == "Machine limits" || gc.category == "Material printing profile") {
suffix = id == 1 ? L("Stealth") : L("Normal"); if (gc.category == "Machine limits")
suffix = id == 1 ? L("Stealth") : L("Normal");
else
suffix = id == 1 ? L("Above") : L("Below");
suffix_local = " " + _(suffix); suffix_local = " " + _(suffix);
suffix = " " + suffix; suffix = " " + suffix;
} }
@ -124,7 +127,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
int cnt = 0; 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()) switch (config->option(opt_key)->type())
{ {
case coInts: change_opt_key<ConfigOptionInts >(opt_key, config, cnt); break; case coInts: change_opt_key<ConfigOptionInts >(opt_key, config, cnt); break;
@ -134,6 +137,8 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
case coPercents:change_opt_key<ConfigOptionPercents >(opt_key, config, cnt); break; case coPercents:change_opt_key<ConfigOptionPercents >(opt_key, config, cnt); break;
case coPoints: change_opt_key<ConfigOptionPoints >(opt_key, config, cnt); break; case coPoints: change_opt_key<ConfigOptionPoints >(opt_key, config, cnt); break;
case coFloatsOrPercents: change_opt_key<ConfigOptionFloatsOrPercents >(opt_key, config, cnt); break; case coFloatsOrPercents: change_opt_key<ConfigOptionFloatsOrPercents >(opt_key, config, cnt); break;
case coEnums: change_opt_key<ConfigOptionEnumsGeneric>(opt_key, config, cnt); break;
default: break; default: break;
} }

View File

@ -937,7 +937,13 @@ void Sidebar::update_sliced_info_sizer()
} }
m_sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost"); m_sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost");
wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : from_u8(short_time_ui(get_time_dhms(float(ps.estimated_print_time)))); wxString t_est = "N/A";
if (! std::isnan(ps.estimated_print_time)) {
t_est = from_u8(short_time_ui(get_time_dhms(float(ps.estimated_print_time))));
if (ps.estimated_print_time_tolerance > 0.)
t_est += from_u8(" \u00B1 ") + from_u8(short_time_ui(get_time_dhms(float(ps.estimated_print_time_tolerance))));
}
m_sliced_info->SetTextAndShow(siEstimatedTime, t_est, _L("Estimated printing time") + ":"); m_sliced_info->SetTextAndShow(siEstimatedTime, t_est, _L("Estimated printing time") + ":");
m_plater->get_notification_manager()->set_slicing_complete_print_time(_u8L("Estimated printing time") + ": " + into_u8(t_est), m_plater->is_sidebar_collapsed()); m_plater->get_notification_manager()->set_slicing_complete_print_time(_u8L("Estimated printing time") + ": " + into_u8(t_est), m_plater->is_sidebar_collapsed());

View File

@ -669,7 +669,7 @@ void Tab::init_options_list()
m_options_list.clear(); m_options_list.clear();
for (const std::string& opt_key : m_config->keys()) 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<class T> template<class T>
@ -692,6 +692,7 @@ void Tab::emplace_option(const std::string& opt_key, bool respect_vec_values/* =
case coPercents:add_correct_opts_to_options_list<ConfigOptionPercents >(opt_key, m_options_list, this, m_opt_status_value); break; case coPercents:add_correct_opts_to_options_list<ConfigOptionPercents >(opt_key, m_options_list, this, m_opt_status_value); break;
case coPoints: add_correct_opts_to_options_list<ConfigOptionPoints >(opt_key, m_options_list, this, m_opt_status_value); break; case coPoints: add_correct_opts_to_options_list<ConfigOptionPoints >(opt_key, m_options_list, this, m_opt_status_value); break;
case coFloatsOrPercents: add_correct_opts_to_options_list<ConfigOptionFloatsOrPercents >(opt_key, m_options_list, this, m_opt_status_value); break; case coFloatsOrPercents: add_correct_opts_to_options_list<ConfigOptionFloatsOrPercents >(opt_key, m_options_list, this, m_opt_status_value); break;
case coEnums: add_correct_opts_to_options_list<ConfigOptionEnumsGeneric>(opt_key, m_options_list, this, m_opt_status_value); break;
default: m_options_list.emplace(opt_key, m_opt_status_value); break; default: m_options_list.emplace(opt_key, m_opt_status_value); break;
} }
} }
@ -906,6 +907,7 @@ void Tab::update_mode()
m_mode = wxGetApp().get_mode(); m_mode = wxGetApp().get_mode();
update_visibility(); update_visibility();
update_sla_prusa_specific_visibility();
update_changed_tree_ui(); update_changed_tree_ui();
} }
@ -2937,7 +2939,7 @@ void TabPrinter::build_sla()
line.append_option(optgroup->get_option("slow_tilt_time")); line.append_option(optgroup->get_option("slow_tilt_time"));
line.append_option(optgroup->get_option("high_viscosity_tilt_time")); line.append_option(optgroup->get_option("high_viscosity_tilt_time"));
optgroup->append_line(line); optgroup->append_line(line);
optgroup->append_single_option_line("area_fill"); // optgroup->append_single_option_line("area_fill");
optgroup = page->new_optgroup(L("Corrections")); optgroup = page->new_optgroup(L("Corrections"));
line = Line{ m_config->def()->get("relative_correction")->full_label, "" }; line = Line{ m_config->def()->get("relative_correction")->full_label, "" };
@ -3022,6 +3024,29 @@ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::s
optgroup->append_line(line); optgroup->append_line(line);
} }
// Legend for OptionsGroups column's name tooltip
static void create_legend(Slic3r::GUI::PageShp page, const std::vector<std::pair<std::string, std::string>>& 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() PageShp TabPrinter::build_kinematics_page()
{ {
auto page = add_options_page(L("Machine limits"), "cog", true); auto page = add_options_page(L("Machine limits"), "cog", true);
@ -3059,27 +3084,12 @@ PageShp TabPrinter::build_kinematics_page()
}; };
if (m_use_silent_mode) { if (m_use_silent_mode) {
// Legend for OptionsGroups std::vector<std::pair<std::string, std::string>> legend_columns = {
auto optgroup = page->new_optgroup(""); {L("Normal"), L("Values in this column are for Normal mode")},
auto line = Line{ "", "" }; {L("Stealth"), L("Values in this column are for Stealth mode")}
};
ConfigOptionDef def; create_legend(page, legend_columns, comAdvanced);
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);
} }
const std::vector<std::string> axes{ "x", "y", "z", "e" }; const std::vector<std::string> axes{ "x", "y", "z", "e" };
@ -3606,8 +3616,15 @@ void TabPrinter::update_fff()
toggle_options(); toggle_options();
} }
bool Tab::is_prusa_printer() const
{
std::string printer_model = m_preset_bundle->printers.get_edited_preset().config.opt_string("printer_model");
return printer_model == "SL1" || printer_model == "SL1S" || printer_model == "M1";
}
void TabPrinter::update_sla() void TabPrinter::update_sla()
{ ; } {
}
void Tab::update_ui_items_related_on_parent_preset(const Preset* selected_preset_parent) void Tab::update_ui_items_related_on_parent_preset(const Preset* selected_preset_parent)
{ {
@ -3695,6 +3712,7 @@ void Tab::load_current_preset()
m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue; m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue;
init_options_list(); init_options_list();
update_visibility(); update_visibility();
update_sla_prusa_specific_visibility();
update_changed_ui(); update_changed_ui();
} }
#if 0 #if 0
@ -4049,6 +4067,7 @@ void Tab::activate_selected_page(std::function<void()> throw_if_canceled)
this->compatible_widget_reload(m_compatible_prints); this->compatible_widget_reload(m_compatible_prints);
} }
update_sla_prusa_specific_visibility();
update_changed_ui(); update_changed_ui();
update_description_lines(); update_description_lines();
toggle_options(); toggle_options();
@ -4965,6 +4984,17 @@ bool TabPrinter::apply_extruder_cnt_from_cache()
return false; return false;
} }
void TabPrinter::update_sla_prusa_specific_visibility()
{
if (m_active_page && m_active_page->title() == "General") {
auto og_it = std::find_if(m_active_page->m_optgroups.begin(), m_active_page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Tilt"; });
if (og_it != m_active_page->m_optgroups.end()) {
og_it->get()->Show(m_mode == comExpert && !is_prusa_printer());
Layout();
}
}
}
bool Tab::validate_custom_gcodes() bool Tab::validate_custom_gcodes()
{ {
if (m_type != Preset::TYPE_FILAMENT && if (m_type != Preset::TYPE_FILAMENT &&
@ -5346,17 +5376,101 @@ void TabSLAMaterial::build()
build_preset_description_line(optgroup.get()); build_preset_description_line(optgroup.get());
page = add_options_page(L("Material printing profile"), "note"); page = add_options_page(L("Material printing profile"), "note");
#if 1
optgroup = page->new_optgroup(L("Material printing profile"));
optgroup->append_single_option_line("material_print_speed");
optgroup = page->new_optgroup(L("Tilt"));
optgroup->append_single_option_line("area_fill");
#else
optgroup = page->new_optgroup(L("Material printing profile")); optgroup = page->new_optgroup(L("Material printing profile"));
option = optgroup->get_option("material_print_speed"); option = optgroup->get_option("material_print_speed");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup->append_single_option_line("area_fill");
#endif
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<std::pair<std::string, std::string>> legend_columns = {
// TRN: This is a label of a column of parameters in settings to be used when the area is below certain threshold.
{L("Below"),
L("Values in this column are applied when layer area is smaller than area_fill.")},
// TRN: This is a label of a column of parameters in settings to be used when the area is above certain threshold.
{L("Above"),
L("Values in this column are applied when layer area is larger than area_fill.")},
};
create_legend(page, legend_columns, comExpert/*, true*/);
// TRN: 'Profile' in this context denotes a group of parameters used to configure
// layer separation procedure for SLA printers.
auto optgroup = page->new_optgroup(L("Profile settings"));
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);
}
std::vector<std::string> disable_tilt_options = {
"tilt_down_initial_speed"
,"tilt_down_offset_steps"
,"tilt_down_offset_delay"
,"tilt_down_finish_speed"
,"tilt_down_cycles"
,"tilt_down_delay"
,"tilt_up_initial_speed"
,"tilt_up_offset_steps"
,"tilt_up_offset_delay"
,"tilt_up_finish_speed"
,"tilt_up_cycles"
,"tilt_up_delay"
};
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("Profile settings");
bool use_tilt = boost::any_cast<bool>(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() void TabSLAMaterial::toggle_options()
{ {
const Preset &current_printer = wxGetApp().preset_bundle->printers.get_edited_preset();
std::string model = current_printer.config.opt_string("printer_model");
m_config_manipulation.toggle_field("material_print_speed", model != "SL1");
if (m_active_page->title() == "Material Overrides") if (m_active_page->title() == "Material Overrides")
update_material_overrides_page(); update_material_overrides_page();
} }
@ -5380,6 +5494,33 @@ void TabSLAMaterial::update()
wxGetApp().mainframe->on_config_changed(m_config); wxGetApp().mainframe->on_config_changed(m_config);
} }
void TabSLAMaterial::update_sla_prusa_specific_visibility()
{
if (m_active_page && m_active_page->title() == "Material printing profile") {
for (auto& title : { "", "Profile settings" }) {
auto og_it = std::find_if(m_active_page->m_optgroups.begin(), m_active_page->m_optgroups.end(),
[title](const ConfigOptionsGroupShp og) { return og->title == title; });
if (og_it != m_active_page->m_optgroups.end())
og_it->get()->Show(m_mode >= comAdvanced && is_prusa_printer());
}
auto og_it = std::find_if(m_active_page->m_optgroups.begin(), m_active_page->m_optgroups.end(),
[](const ConfigOptionsGroupShp og) { return og->title == "Material printing profile"; });
if (og_it != m_active_page->m_optgroups.end())
og_it->get()->Show(m_mode >= comAdvanced && !is_prusa_printer());
Layout();
}
}
void TabSLAMaterial::clear_pages()
{
Tab::clear_pages();
for (auto& over_opt : m_overrides_options)
over_opt.second = nullptr;
}
void TabSLAMaterial::msw_rescale() void TabSLAMaterial::msw_rescale()
{ {
for (const auto& over_opt : m_overrides_options) for (const auto& over_opt : m_overrides_options)
@ -5465,10 +5606,6 @@ static std::vector<std::string> get_override_opt_kyes_for_line(const std::string
for (auto& prefix : { "", "branching" }) for (auto& prefix : { "", "branching" })
opt_keys.push_back(preprefix + prefix + key); 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 else
opt_keys.push_back(preprefix + key); opt_keys.push_back(preprefix + key);
@ -5481,17 +5618,7 @@ void TabSLAMaterial::create_line_with_near_label_widget(ConfigOptionsGroupShp op
add_options_into_line(optgroup, { {"", L("Default")}, {"branching", L("Branching")} }, key, "material_ow_"); add_options_into_line(optgroup, { {"", L("Default")}, {"branching", L("Branching")} }, key, "material_ow_");
else { else {
const std::string opt_key = std::string("material_ow_") + key; const std::string opt_key = std::string("material_ow_") + key;
if (key == "relative_correction") { optgroup->append_single_option_line(opt_key);
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(); Line* line = optgroup->get_last_line();
@ -5537,7 +5664,7 @@ std::vector<std::pair<std::string, std::vector<std::string>>> material_overrides
"support_points_density_relative" "support_points_density_relative"
}}, }},
{"Corrections", { {"Corrections", {
"relative_correction", "absolute_correction",
"elefant_foot_compensation" "elefant_foot_compensation"
}} }}
}; };

View File

@ -377,6 +377,7 @@ public:
void update_mode(); void update_mode();
void update_mode_markers(); void update_mode_markers();
void update_visibility(); void update_visibility();
virtual void update_sla_prusa_specific_visibility() {}
virtual void msw_rescale(); virtual void msw_rescale();
virtual void sys_color_changed(); virtual void sys_color_changed();
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
@ -406,11 +407,11 @@ public:
static bool validate_custom_gcode(const wxString& title, const std::string& gcode); static bool validate_custom_gcode(const wxString& title, const std::string& gcode);
bool validate_custom_gcodes(); bool validate_custom_gcodes();
bool validate_custom_gcodes_was_shown{ false }; bool validate_custom_gcodes_was_shown{ false };
bool is_prusa_printer() const;
void edit_custom_gcode(const t_config_option_key& opt_key); void edit_custom_gcode(const t_config_option_key& opt_key);
virtual const std::string& get_custom_gcode(const t_config_option_key& opt_key); virtual const std::string& get_custom_gcode(const t_config_option_key& opt_key);
virtual void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value); virtual void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value);
protected: protected:
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget); void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget);
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps); wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
@ -559,6 +560,7 @@ public:
wxSizer* create_bed_shape_widget(wxWindow* parent); wxSizer* create_bed_shape_widget(wxWindow* parent);
void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr); void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr);
bool apply_extruder_cnt_from_cache(); bool apply_extruder_cnt_from_cache();
void update_sla_prusa_specific_visibility() override;
}; };
class TabSLAMaterial : public Tab class TabSLAMaterial : public Tab
@ -575,11 +577,15 @@ public:
~TabSLAMaterial() {} ~TabSLAMaterial() {}
void build() override; void build() override;
void build_tilt_group(Slic3r::GUI::PageShp page);
void toggle_tilt_options(bool is_above);
void toggle_options() override; void toggle_options() override;
void update() override; void update() override;
void clear_pages() override;
void msw_rescale() override; void msw_rescale() override;
void sys_color_changed() override; void sys_color_changed() override;
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptSLA; } bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptSLA; }
void update_sla_prusa_specific_visibility() override;
}; };
class TabSLAPrint : public Tab class TabSLAPrint : public Tab

View File

@ -1223,6 +1223,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()); 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"); 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: { case coPoints: {
if (opt_key == "bed_shape") { if (opt_key == "bed_shape") {
BedShape shape(*config.option<ConfigOptionPoints>(opt_key)); BedShape shape(*config.option<ConfigOptionPoints>(opt_key));
@ -1313,7 +1321,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)); m_tree->model->AddPreset(type, from_u8(presets->get_edited_preset().name), old_pt, from_u8(new_selected_preset));
// Collect dirty options. // 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); auto dirty_options = presets->current_dirty_options(deep_compare);
// process changes of extruders count // process changes of extruders count