Optimization of the configuration layer:
The values of StaticPrintConfig derived objects were searched by a name walking through a huge chained if. Now they are being mapped with a std::map. Also initialization of StaticPrintConfig classes from their ConfigOptionDef defaults is done by maintaining a single global definition of each StaticPrintConfig derived class, and a new instance is initialized from this static copy. Also the ConfigOption instances are casted using static_cast wherever possible, and their types are verified by a virtual type() method. This approach avoids insiginificant performance penalty of a dynamic_cast. Also the compare and clone methods were added to ConfigOption, and the cloning & compare work on binary values, not by serialization.
This commit is contained in:
parent
a91d7cb2f7
commit
3731820c48
@ -31,10 +31,9 @@ $Options->{threads}{readonly} = !$Slic3r::have_threads;
|
||||
|
||||
# Fill in the underlying C++ Slic3r::DynamicPrintConfig with the content of the defaults
|
||||
# provided by the C++ class Slic3r::FullPrintConfig.
|
||||
# Used by the UI.
|
||||
sub new_from_defaults {
|
||||
my $class = shift;
|
||||
my (@opt_keys) = @_;
|
||||
|
||||
my ($class, @opt_keys) = @_;
|
||||
my $self = $class->new;
|
||||
# Instantiating the C++ class Slic3r::FullPrintConfig.
|
||||
my $defaults = Slic3r::Config::Full->new;
|
||||
@ -47,7 +46,7 @@ sub new_from_defaults {
|
||||
return $self;
|
||||
}
|
||||
|
||||
# From command line parameters
|
||||
# From command line parameters, used by slic3r.pl
|
||||
sub new_from_cli {
|
||||
my $class = shift;
|
||||
my %args = @_;
|
||||
@ -112,12 +111,6 @@ sub load {
|
||||
}
|
||||
}
|
||||
|
||||
# Save the content of the underlying C++ Slic3r::DynamicPrintConfig as a flat ini file without any category.
|
||||
sub save {
|
||||
my ($self, $file) = @_;
|
||||
return $self->_save($file);
|
||||
}
|
||||
|
||||
# Deserialize a perl hash into the underlying C++ Slic3r::DynamicConfig class,
|
||||
# convert legacy configuration names.
|
||||
# Used to load a config bundle.
|
||||
@ -309,6 +302,7 @@ sub validate {
|
||||
# CLASS METHODS:
|
||||
|
||||
# Write a "Windows" style ini file with categories enclosed in squre brackets.
|
||||
# Used by config-bundle-to-config.pl and to save slic3r.ini.
|
||||
sub write_ini {
|
||||
my $class = shift;
|
||||
my ($file, $ini) = @_;
|
||||
@ -331,6 +325,7 @@ sub write_ini {
|
||||
# Returns a hash of hashes over strings.
|
||||
# {category}{name}=value
|
||||
# Non-categorized entries are stored under a category '_'.
|
||||
# Used by config-bundle-to-config.pl and to read slic3r.ini.
|
||||
sub read_ini {
|
||||
my $class = shift;
|
||||
my ($file) = @_;
|
||||
|
@ -177,20 +177,24 @@ bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &o
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigBase::apply(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
|
||||
void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
|
||||
{
|
||||
// loop through options and apply them
|
||||
for (const t_config_option_key &key : keys) {
|
||||
ConfigOption *my_opt = this->option(key, true);
|
||||
for (const t_config_option_key &opt_key : keys) {
|
||||
// Create a new option with default value for the key.
|
||||
// If the key is not in the parameter definition, or this ConfigBase is a static type and it does not support the parameter,
|
||||
// an exception is thrown if not ignore_nonexistent.
|
||||
ConfigOption *my_opt = this->option(opt_key, true);
|
||||
if (my_opt == nullptr) {
|
||||
if (! ignore_nonexistent)
|
||||
throw "Attempt to apply non-existent option";
|
||||
continue;
|
||||
// opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def().
|
||||
// This is only possible if other is of DynamicConfig type.
|
||||
if (ignore_nonexistent)
|
||||
continue;
|
||||
throw UnknownOptionException();
|
||||
}
|
||||
// not the most efficient way, but easier than casting pointers to subclasses
|
||||
const ConfigOption *other_opt = other.option(key);
|
||||
if (other_opt != nullptr && ! my_opt->deserialize(other_opt->serialize()))
|
||||
CONFESS((std::string("Unexpected failure when deserializing serialized value for ") + key).c_str());
|
||||
const ConfigOption *other_opt = other.option(opt_key);
|
||||
if (other_opt != nullptr)
|
||||
my_opt->set(other_opt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,9 +202,12 @@ void ConfigBase::apply(const ConfigBase &other, const t_config_option_keys &keys
|
||||
t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
|
||||
{
|
||||
t_config_option_keys diff;
|
||||
for (const t_config_option_key &opt_key : this->keys())
|
||||
if (other.has(opt_key) && other.serialize(opt_key) != this->serialize(opt_key))
|
||||
diff.push_back(opt_key);
|
||||
for (const t_config_option_key &opt_key : this->keys()) {
|
||||
const ConfigOption *this_opt = this->option(opt_key);
|
||||
const ConfigOption *other_opt = other.option(opt_key);
|
||||
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
|
||||
diff.emplace_back(opt_key);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
@ -211,12 +218,27 @@ std::string ConfigBase::serialize(const t_config_option_key &opt_key) const
|
||||
return opt->serialize();
|
||||
}
|
||||
|
||||
bool ConfigBase::set_deserialize(t_config_option_key opt_key, const std::string &str, bool append)
|
||||
bool ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
||||
{
|
||||
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
||||
t_config_option_key opt_key = opt_key_src;
|
||||
std::string value = value_src;
|
||||
// Both opt_key and value may be modified by _handle_legacy().
|
||||
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by _handle_legacy().
|
||||
this->handle_legacy(opt_key, value);
|
||||
if (opt_key.empty())
|
||||
// Ignore the option.
|
||||
return true;
|
||||
return this->set_deserialize_raw(opt_key, value, append);
|
||||
}
|
||||
|
||||
bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &value, bool append)
|
||||
{
|
||||
t_config_option_key opt_key = opt_key_src;
|
||||
// Try to deserialize the option by its name.
|
||||
const ConfigOptionDef* optdef = this->def()->get(opt_key);
|
||||
if (optdef == nullptr) {
|
||||
// If we didn't find an option, look for any other option having this as an alias.
|
||||
for (const auto &opt : this->def->options) {
|
||||
for (const auto &opt : this->def()->options) {
|
||||
for (const t_config_option_key &opt_key2 : opt.second.aliases) {
|
||||
if (opt_key2 == opt_key) {
|
||||
opt_key = opt_key2;
|
||||
@ -232,44 +254,49 @@ bool ConfigBase::set_deserialize(t_config_option_key opt_key, const std::string
|
||||
}
|
||||
|
||||
if (! optdef->shortcut.empty()) {
|
||||
// Aliasing for example "solid_layers" to "top_solid_layers" and "bottom_solid_layers".
|
||||
for (const t_config_option_key &shortcut : optdef->shortcut)
|
||||
if (! this->set_deserialize(shortcut, str))
|
||||
// Recursive call.
|
||||
if (! this->set_deserialize_raw(shortcut, value, append))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ConfigOption *opt = this->option(opt_key, true);
|
||||
assert(opt != nullptr);
|
||||
return opt->deserialize(str, append);
|
||||
return opt->deserialize(value, append);
|
||||
}
|
||||
|
||||
// Return an absolute value of a possibly relative config variable.
|
||||
// For example, return absolute infill extrusion width, either from an absolute value, or relative to the layer height.
|
||||
double ConfigBase::get_abs_value(const t_config_option_key &opt_key) const
|
||||
{
|
||||
const ConfigOption* opt = this->option(opt_key);
|
||||
if (const ConfigOptionFloatOrPercent* optv = dynamic_cast<const ConfigOptionFloatOrPercent*>(opt)) {
|
||||
// get option definition
|
||||
const ConfigOptionDef* def = this->def->get(opt_key);
|
||||
// Get stored option value.
|
||||
const ConfigOption *raw_opt = this->option(opt_key);
|
||||
assert(raw_opt != nullptr);
|
||||
if (raw_opt->type() == coFloat)
|
||||
return static_cast<const ConfigOptionFloat*>(raw_opt)->value;
|
||||
if (raw_opt->type() == coFloatOrPercent) {
|
||||
// Get option definition.
|
||||
const ConfigOptionDef *def = this->def()->get(opt_key);
|
||||
assert(def != nullptr);
|
||||
// compute absolute value over the absolute value of the base option
|
||||
return optv->get_abs_value(this->get_abs_value(def->ratio_over));
|
||||
} else if (const ConfigOptionFloat* optv = dynamic_cast<const ConfigOptionFloat*>(opt)) {
|
||||
return optv->value;
|
||||
} else {
|
||||
throw "Not a valid option type for get_abs_value()";
|
||||
// Compute absolute value over the absolute value of the base option.
|
||||
return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(this->get_abs_value(def->ratio_over));
|
||||
}
|
||||
throw std::runtime_error("ConfigBase::get_abs_value(): Not a valid option type for get_abs_value()");
|
||||
}
|
||||
|
||||
// Return an absolute value of a possibly relative config variable.
|
||||
// For example, return absolute infill extrusion width, either from an absolute value, or relative to a provided value.
|
||||
double ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) const
|
||||
{
|
||||
// get stored option value
|
||||
const ConfigOptionFloatOrPercent* opt = dynamic_cast<const ConfigOptionFloatOrPercent*>(this->option(opt_key));
|
||||
assert(opt != nullptr);
|
||||
// compute absolute value
|
||||
return opt->get_abs_value(ratio_over);
|
||||
// Get stored option value.
|
||||
const ConfigOption *raw_opt = this->option(opt_key);
|
||||
assert(raw_opt != nullptr);
|
||||
if (raw_opt->type() != coFloatOrPercent)
|
||||
throw std::runtime_error("ConfigBase::get_abs_value(): opt_key is not of coFloatOrPercent");
|
||||
// Compute absolute value.
|
||||
return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(ratio_over);
|
||||
}
|
||||
|
||||
void ConfigBase::setenv_()
|
||||
@ -301,8 +328,7 @@ void ConfigBase::load(const std::string &file)
|
||||
for (const pt::ptree::value_type &v : tree) {
|
||||
try {
|
||||
t_config_option_key opt_key = v.first;
|
||||
std::string value = v.second.get_value<std::string>();
|
||||
this->set_deserialize(opt_key, value);
|
||||
this->set_deserialize(opt_key, v.second.get_value<std::string>());
|
||||
} catch (UnknownOptionException & /* e */) {
|
||||
// ignore
|
||||
}
|
||||
@ -400,64 +426,43 @@ void ConfigBase::save(const std::string &file) const
|
||||
c.close();
|
||||
}
|
||||
|
||||
ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
|
||||
ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create)
|
||||
{
|
||||
t_options_map::iterator it = options.find(opt_key);
|
||||
if (it == options.end()) {
|
||||
if (create) {
|
||||
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
||||
assert(optdef != NULL);
|
||||
ConfigOption* opt;
|
||||
if (optdef->type == coFloat) {
|
||||
opt = new ConfigOptionFloat ();
|
||||
} else if (optdef->type == coFloats) {
|
||||
opt = new ConfigOptionFloats ();
|
||||
} else if (optdef->type == coInt) {
|
||||
opt = new ConfigOptionInt ();
|
||||
} else if (optdef->type == coInts) {
|
||||
opt = new ConfigOptionInts ();
|
||||
} else if (optdef->type == coString) {
|
||||
opt = new ConfigOptionString ();
|
||||
} else if (optdef->type == coStrings) {
|
||||
opt = new ConfigOptionStrings ();
|
||||
} else if (optdef->type == coPercent) {
|
||||
opt = new ConfigOptionPercent ();
|
||||
} else if (optdef->type == coPercents) {
|
||||
opt = new ConfigOptionPercents ();
|
||||
} else if (optdef->type == coFloatOrPercent) {
|
||||
opt = new ConfigOptionFloatOrPercent ();
|
||||
} else if (optdef->type == coPoint) {
|
||||
opt = new ConfigOptionPoint ();
|
||||
} else if (optdef->type == coPoints) {
|
||||
opt = new ConfigOptionPoints ();
|
||||
} else if (optdef->type == coBool) {
|
||||
opt = new ConfigOptionBool ();
|
||||
} else if (optdef->type == coBools) {
|
||||
opt = new ConfigOptionBools ();
|
||||
} else if (optdef->type == coEnum) {
|
||||
ConfigOptionEnumGeneric* optv = new ConfigOptionEnumGeneric ();
|
||||
optv->keys_map = &optdef->enum_keys_map;
|
||||
opt = static_cast<ConfigOption*>(optv);
|
||||
} else {
|
||||
throw "Unknown option type";
|
||||
}
|
||||
this->options[opt_key] = opt;
|
||||
return opt;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
if (it != options.end())
|
||||
// Option was found.
|
||||
return it->second;
|
||||
if (! create)
|
||||
// Option was not found and a new option shall not be created.
|
||||
return nullptr;
|
||||
// Try to create a new ConfigOption.
|
||||
const ConfigOptionDef *optdef = this->def()->get(opt_key);
|
||||
if (optdef == nullptr)
|
||||
// throw std::runtime_error(std::string("Invalid option name: ") + opt_key);
|
||||
// Let the parent decide what to do if the opt_key is not defined by this->def().
|
||||
return nullptr;
|
||||
ConfigOption *opt = nullptr;
|
||||
switch (optdef->type) {
|
||||
case coFloat: opt = new ConfigOptionFloat(); break;
|
||||
case coFloats: opt = new ConfigOptionFloats(); break;
|
||||
case coInt: opt = new ConfigOptionInt(); break;
|
||||
case coInts: opt = new ConfigOptionInts(); break;
|
||||
case coString: opt = new ConfigOptionString(); break;
|
||||
case coStrings: opt = new ConfigOptionStrings(); break;
|
||||
case coPercent: opt = new ConfigOptionPercent(); break;
|
||||
case coPercents: opt = new ConfigOptionPercents(); break;
|
||||
case coFloatOrPercent: opt = new ConfigOptionFloatOrPercent(); break;
|
||||
case coPoint: opt = new ConfigOptionPoint(); break;
|
||||
case coPoints: opt = new ConfigOptionPoints(); break;
|
||||
case coBool: opt = new ConfigOptionBool(); break;
|
||||
case coBools: opt = new ConfigOptionBools(); break;
|
||||
case coEnum: opt = new ConfigOptionEnumGeneric(optdef->enum_keys_map); break;
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + opt_key);
|
||||
}
|
||||
return it->second;
|
||||
this->options[opt_key] = opt;
|
||||
return opt;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* DynamicConfig::opt(const t_config_option_key &opt_key, bool create) {
|
||||
return dynamic_cast<T*>(this->option(opt_key, create));
|
||||
}
|
||||
template ConfigOptionInt* DynamicConfig::opt<ConfigOptionInt>(const t_config_option_key &opt_key, bool create);
|
||||
template ConfigOptionBool* DynamicConfig::opt<ConfigOptionBool>(const t_config_option_key &opt_key, bool create);
|
||||
template ConfigOptionBools* DynamicConfig::opt<ConfigOptionBools>(const t_config_option_key &opt_key, bool create);
|
||||
template ConfigOptionPercent* DynamicConfig::opt<ConfigOptionPercent>(const t_config_option_key &opt_key, bool create);
|
||||
|
||||
t_config_option_keys DynamicConfig::keys() const
|
||||
{
|
||||
t_config_option_keys keys;
|
||||
@ -470,11 +475,13 @@ t_config_option_keys DynamicConfig::keys() const
|
||||
void StaticConfig::set_defaults()
|
||||
{
|
||||
// use defaults from definition
|
||||
if (this->def != nullptr) {
|
||||
auto *defs = this->def();
|
||||
if (defs != nullptr) {
|
||||
for (const std::string &key : this->keys()) {
|
||||
const ConfigOptionDef* def = this->def->get(key);
|
||||
if (def->default_value != nullptr)
|
||||
this->option(key)->set(*def->default_value);
|
||||
const ConfigOptionDef *def = defs->get(key);
|
||||
ConfigOption *opt = this->option(key);
|
||||
if (def != nullptr && opt != nullptr && def->default_value != nullptr)
|
||||
opt->set(def->default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -483,7 +490,7 @@ t_config_option_keys StaticConfig::keys() const
|
||||
{
|
||||
t_config_option_keys keys;
|
||||
assert(this->def != nullptr);
|
||||
for (const auto &opt_def : this->def->options)
|
||||
for (const auto &opt_def : this->def()->options)
|
||||
if (this->option(opt_def.first) != nullptr)
|
||||
keys.push_back(opt_def.first);
|
||||
return keys;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,13 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void GCodeReader::apply_config(const PrintConfigBase &config)
|
||||
void GCodeReader::apply_config(const GCodeConfig &config)
|
||||
{
|
||||
m_config = config;
|
||||
m_extrusion_axis = m_config.get_extrusion_axis()[0];
|
||||
}
|
||||
|
||||
void GCodeReader::apply_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
m_config.apply(config, true);
|
||||
m_extrusion_axis = m_config.get_extrusion_axis()[0];
|
||||
|
@ -50,7 +50,8 @@ public:
|
||||
callback_t callback;
|
||||
|
||||
GCodeReader() : X(0), Y(0), Z(0), E(0), F(0), verbose(false), m_extrusion_axis('E') {};
|
||||
void apply_config(const PrintConfigBase &config);
|
||||
void apply_config(const GCodeConfig &config);
|
||||
void apply_config(const DynamicPrintConfig &config);
|
||||
void parse(const std::string &gcode, callback_t callback);
|
||||
void parse_line(std::string line, callback_t callback);
|
||||
void parse_file(const std::string &file, callback_t callback);
|
||||
|
@ -260,7 +260,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||
#endif
|
||||
if (bd.detect_angle(Geometry::deg2rad(this->region()->config.bridge_angle))) {
|
||||
if (bd.detect_angle(Geometry::deg2rad(this->region()->config.bridge_angle.value))) {
|
||||
bridges[idx_last].bridge_angle = bd.angle;
|
||||
if (this->layer()->object()->config.support_material) {
|
||||
polygons_append(this->bridged, bd.coverage());
|
||||
|
@ -64,7 +64,7 @@ void PlaceholderParser::update_timestamp()
|
||||
void PlaceholderParser::apply_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
for (const t_config_option_key &opt_key : config.keys()) {
|
||||
const ConfigOptionDef* def = config.def->get(opt_key);
|
||||
const ConfigOptionDef* def = config.def()->get(opt_key);
|
||||
if (def->multiline || opt_key == "post_process")
|
||||
continue;
|
||||
|
||||
|
@ -389,7 +389,7 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||
|
||||
// handle changes to print config
|
||||
t_config_option_keys print_diff = this->config.diff(config);
|
||||
this->config.apply(config, print_diff, true);
|
||||
this->config.apply_only(config, print_diff, true);
|
||||
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
||||
|
||||
// handle changes to object config defaults
|
||||
@ -410,7 +410,7 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||
}
|
||||
// check whether the new config is different from the current one
|
||||
t_config_option_keys diff = object->config.diff(new_config);
|
||||
object->config.apply(new_config, diff, true);
|
||||
object->config.apply_only(new_config, diff, true);
|
||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||
if (this_region_config_set) {
|
||||
t_config_option_keys diff = region.config.diff(this_region_config);
|
||||
if (! diff.empty()) {
|
||||
region.config.apply(this_region_config, diff);
|
||||
region.config.apply_only(this_region_config, diff);
|
||||
for (PrintObject *object : this->objects)
|
||||
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <float.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -221,7 +222,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->category = "Infill";
|
||||
def->tooltip = "Fill pattern for top/bottom infill. This only affects the external visible layer, and not its adjacent solid shells.";
|
||||
def->cli = "external-fill-pattern|solid-fill-pattern=s";
|
||||
def->enum_keys_map = ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values.push_back("rectilinear");
|
||||
def->enum_values.push_back("concentric");
|
||||
def->enum_values.push_back("hilbertcurve");
|
||||
@ -529,7 +530,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->category = "Infill";
|
||||
def->tooltip = "Fill pattern for general low-density infill.";
|
||||
def->cli = "fill-pattern=s";
|
||||
def->enum_keys_map = ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values.push_back("rectilinear");
|
||||
def->enum_values.push_back("grid");
|
||||
def->enum_values.push_back("triangles");
|
||||
@ -633,7 +634,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->label = "G-code flavor";
|
||||
def->tooltip = "Some G/M-code commands, including temperature control and others, are not universal. Set this option to your printer's firmware to get a compatible output. The \"No extrusion\" flavor prevents Slic3r from exporting any extrusion value at all.";
|
||||
def->cli = "gcode-flavor=s";
|
||||
def->enum_keys_map = ConfigOptionEnum<GCodeFlavor>::get_enum_values();
|
||||
def->enum_keys_map = &ConfigOptionEnum<GCodeFlavor>::get_enum_values();
|
||||
def->enum_values.push_back("reprap");
|
||||
def->enum_values.push_back("repetier");
|
||||
def->enum_values.push_back("teacup");
|
||||
@ -1136,7 +1137,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->category = "Layers and Perimeters";
|
||||
def->tooltip = "Position of perimeters starting points.";
|
||||
def->cli = "seam-position=s";
|
||||
def->enum_keys_map = ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values();
|
||||
def->enum_values.push_back("random");
|
||||
def->enum_values.push_back("nearest");
|
||||
def->enum_values.push_back("aligned");
|
||||
@ -1458,7 +1459,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->category = "Support material";
|
||||
def->tooltip = "Pattern used to generate support material.";
|
||||
def->cli = "support-material-pattern=s";
|
||||
def->enum_keys_map = ConfigOptionEnum<SupportMaterialPattern>::get_enum_values();
|
||||
def->enum_keys_map = &ConfigOptionEnum<SupportMaterialPattern>::get_enum_values();
|
||||
def->enum_values.push_back("rectilinear");
|
||||
def->enum_values.push_back("rectilinear-grid");
|
||||
def->enum_values.push_back("honeycomb");
|
||||
@ -1538,7 +1539,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->readonly = true;
|
||||
def->min = 1;
|
||||
{
|
||||
unsigned int threads = boost::thread::hardware_concurrency();
|
||||
int threads = (unsigned int)boost::thread::hardware_concurrency();
|
||||
def->default_value = new ConfigOptionInt(threads > 0 ? threads : 2);
|
||||
}
|
||||
|
||||
@ -1671,56 +1672,7 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->default_value = new ConfigOptionFloat(0);
|
||||
}
|
||||
|
||||
PrintConfigDef print_config_def;
|
||||
|
||||
void
|
||||
DynamicPrintConfig::normalize() {
|
||||
if (this->has("extruder")) {
|
||||
int extruder = this->option("extruder")->getInt();
|
||||
this->erase("extruder");
|
||||
if (extruder != 0) {
|
||||
if (!this->has("infill_extruder"))
|
||||
this->option("infill_extruder", true)->setInt(extruder);
|
||||
if (!this->has("perimeter_extruder"))
|
||||
this->option("perimeter_extruder", true)->setInt(extruder);
|
||||
// Don't propagate the current extruder to support.
|
||||
// For non-soluble supports, the default "0" extruder means to use the active extruder,
|
||||
// for soluble supports one certainly does not want to set the extruder to non-soluble.
|
||||
// if (!this->has("support_material_extruder"))
|
||||
// this->option("support_material_extruder", true)->setInt(extruder);
|
||||
// if (!this->has("support_material_interface_extruder"))
|
||||
// this->option("support_material_interface_extruder", true)->setInt(extruder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->has("solid_infill_extruder") && this->has("infill_extruder"))
|
||||
this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt());
|
||||
|
||||
if (this->has("spiral_vase") && this->opt<ConfigOptionBool>("spiral_vase", true)->value) {
|
||||
{
|
||||
// this should be actually done only on the spiral layers instead of all
|
||||
ConfigOptionBools* opt = this->opt<ConfigOptionBools>("retract_layer_change", true);
|
||||
opt->values.assign(opt->values.size(), false); // set all values to false
|
||||
}
|
||||
{
|
||||
this->opt<ConfigOptionInt>("perimeters", true)->value = 1;
|
||||
this->opt<ConfigOptionInt>("top_solid_layers", true)->value = 0;
|
||||
this->opt<ConfigOptionPercent>("fill_density", true)->value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PrintConfigBase::set_deserialize(t_config_option_key opt_key, std::string str, bool append)
|
||||
{
|
||||
this->_handle_legacy(opt_key, str);
|
||||
return opt_key.empty() ?
|
||||
// ignore option
|
||||
true :
|
||||
ConfigBase::set_deserialize(opt_key, str, append);
|
||||
}
|
||||
|
||||
void PrintConfigBase::_handle_legacy(t_config_option_key &opt_key, std::string &value) const
|
||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||
{
|
||||
// handle legacy options
|
||||
if (opt_key == "extrusion_width_ratio" || opt_key == "bottom_layer_speed_ratio"
|
||||
@ -1783,22 +1735,249 @@ void PrintConfigBase::_handle_legacy(t_config_option_key &opt_key, std::string &
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->def->has(opt_key)) {
|
||||
if (! print_config_def.has(opt_key)) {
|
||||
//printf("Unknown option %s\n", opt_key.c_str());
|
||||
opt_key = "";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double PrintConfigBase::min_object_distance() const
|
||||
PrintConfigDef print_config_def;
|
||||
|
||||
void DynamicPrintConfig::normalize()
|
||||
{
|
||||
double extruder_clearance_radius = this->option("extruder_clearance_radius")->getFloat();
|
||||
double duplicate_distance = this->option("duplicate_distance")->getFloat();
|
||||
if (this->has("extruder")) {
|
||||
int extruder = this->option("extruder")->getInt();
|
||||
this->erase("extruder");
|
||||
if (extruder != 0) {
|
||||
if (!this->has("infill_extruder"))
|
||||
this->option("infill_extruder", true)->setInt(extruder);
|
||||
if (!this->has("perimeter_extruder"))
|
||||
this->option("perimeter_extruder", true)->setInt(extruder);
|
||||
// Don't propagate the current extruder to support.
|
||||
// For non-soluble supports, the default "0" extruder means to use the active extruder,
|
||||
// for soluble supports one certainly does not want to set the extruder to non-soluble.
|
||||
// if (!this->has("support_material_extruder"))
|
||||
// this->option("support_material_extruder", true)->setInt(extruder);
|
||||
// if (!this->has("support_material_interface_extruder"))
|
||||
// this->option("support_material_interface_extruder", true)->setInt(extruder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->has("solid_infill_extruder") && this->has("infill_extruder"))
|
||||
this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt());
|
||||
|
||||
if (this->has("spiral_vase") && this->opt<ConfigOptionBool>("spiral_vase", true)->value) {
|
||||
{
|
||||
// this should be actually done only on the spiral layers instead of all
|
||||
ConfigOptionBools* opt = this->opt<ConfigOptionBools>("retract_layer_change", true);
|
||||
opt->values.assign(opt->values.size(), false); // set all values to false
|
||||
}
|
||||
{
|
||||
this->opt<ConfigOptionInt>("perimeters", true)->value = 1;
|
||||
this->opt<ConfigOptionInt>("top_solid_layers", true)->value = 0;
|
||||
this->opt<ConfigOptionPercent>("fill_density", true)->value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string DynamicPrintConfig::validate()
|
||||
{
|
||||
// Full print config is initialized from the defaults.
|
||||
FullPrintConfig fpc;
|
||||
fpc.apply(*this);
|
||||
// Verify this print options through the FullPrintConfig.
|
||||
return fpc.validate();
|
||||
}
|
||||
|
||||
double PrintConfig::min_object_distance() const
|
||||
{
|
||||
return PrintConfig::min_object_distance(static_cast<const ConfigBase*>(this));
|
||||
}
|
||||
|
||||
double PrintConfig::min_object_distance(const ConfigBase *config)
|
||||
{
|
||||
double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat();
|
||||
double duplicate_distance = config->option("duplicate_distance")->getFloat();
|
||||
|
||||
// min object distance is max(duplicate_distance, clearance_radius)
|
||||
return (this->option("complete_objects")->getBool() && extruder_clearance_radius > duplicate_distance)
|
||||
return (config->option("complete_objects")->getBool() && extruder_clearance_radius > duplicate_distance)
|
||||
? extruder_clearance_radius
|
||||
: duplicate_distance;
|
||||
}
|
||||
|
||||
std::string FullPrintConfig::validate()
|
||||
{
|
||||
// --layer-height
|
||||
if (this->get_abs_value("layer_height") <= 0)
|
||||
return "Invalid value for --layer-height";
|
||||
if (fabs(fmod(this->get_abs_value("layer_height"), SCALING_FACTOR)) > 1e-4)
|
||||
return "--layer-height must be a multiple of print resolution";
|
||||
|
||||
// --first-layer-height
|
||||
if (this->get_abs_value("first_layer_height") <= 0)
|
||||
return "Invalid value for --first-layer-height";
|
||||
|
||||
// --filament-diameter
|
||||
for (double fd : this->filament_diameter.values)
|
||||
if (fd < 1)
|
||||
return "Invalid value for --filament-diameter";
|
||||
|
||||
// --nozzle-diameter
|
||||
for (double nd : this->nozzle_diameter.values)
|
||||
if (nd < 1)
|
||||
return "Invalid value for --nozzle-diameter";
|
||||
|
||||
// --perimeters
|
||||
if (this->perimeters.value < 0)
|
||||
return "Invalid value for --perimeters";
|
||||
|
||||
// --solid-layers
|
||||
if (this->top_solid_layers < 0)
|
||||
return "Invalid value for --top-solid-layers";
|
||||
if (this->bottom_solid_layers < 0)
|
||||
return "Invalid value for --bottom-solid-layers";
|
||||
|
||||
if (this->use_firmware_retraction.value &&
|
||||
this->gcode_flavor.value != gcfSmoothie &&
|
||||
this->gcode_flavor.value != gcfRepRap &&
|
||||
this->gcode_flavor.value != gcfMachinekit &&
|
||||
this->gcode_flavor.value != gcfRepetier)
|
||||
return "--use-firmware-retraction is only supported by Marlin, Smoothie, Repetier and Machinekit firmware";
|
||||
|
||||
if (this->use_firmware_retraction.value)
|
||||
for (bool wipe : this->wipe.values)
|
||||
if (wipe)
|
||||
return "--use-firmware-retraction is not compatible with --wipe";
|
||||
|
||||
// --gcode-flavor
|
||||
if (! print_config_def.get("gcode_flavor")->has_enum_value(this->gcode_flavor.serialize()))
|
||||
return "Invalid value for --gcode-flavor";
|
||||
|
||||
// --fill-pattern
|
||||
if (! print_config_def.get("fill_pattern")->has_enum_value(this->fill_pattern.serialize()))
|
||||
return "Invalid value for --fill-pattern";
|
||||
|
||||
// --external-fill-pattern
|
||||
if (! print_config_def.get("external_fill_pattern")->has_enum_value(this->external_fill_pattern.serialize()))
|
||||
return "Invalid value for --external-fill-pattern";
|
||||
|
||||
// --fill-density
|
||||
if (fabs(this->fill_density.value - 100.) < EPSILON &&
|
||||
! print_config_def.get("external_fill_pattern")->has_enum_value(this->fill_pattern.serialize()))
|
||||
return "The selected fill pattern is not supposed to work at 100% density";
|
||||
|
||||
// --infill-every-layers
|
||||
if (this->infill_every_layers < 1)
|
||||
return "Invalid value for --infill-every-layers";
|
||||
|
||||
// --skirt-height
|
||||
if (this->skirt_height < -1) // -1 means as tall as the object
|
||||
return "Invalid value for --skirt-height";
|
||||
|
||||
// --bridge-flow-ratio
|
||||
if (this->bridge_flow_ratio <= 0)
|
||||
return "Invalid value for --bridge-flow-ratio";
|
||||
|
||||
// extruder clearance
|
||||
if (this->extruder_clearance_radius <= 0)
|
||||
return "Invalid value for --extruder-clearance-radius";
|
||||
if (this->extruder_clearance_height <= 0)
|
||||
return "Invalid value for --extruder-clearance-height";
|
||||
|
||||
// --extrusion-multiplier
|
||||
for (float em : this->extrusion_multiplier.values)
|
||||
if (em <= 0)
|
||||
return "Invalid value for --extrusion-multiplier";
|
||||
|
||||
// --default-acceleration
|
||||
if ((this->perimeter_acceleration != 0. || this->infill_acceleration != 0. || this->bridge_acceleration != 0. || this->first_layer_acceleration != 0.) &&
|
||||
this->default_acceleration == 0.)
|
||||
return "Invalid zero value for --default-acceleration when using other acceleration settings";
|
||||
|
||||
// --spiral-vase
|
||||
if (this->spiral_vase) {
|
||||
// Note that we might want to have more than one perimeter on the bottom
|
||||
// solid layers.
|
||||
if (this->perimeters > 1)
|
||||
return "Can't make more than one perimeter when spiral vase mode is enabled";
|
||||
else if (this->perimeters < 1)
|
||||
return "Can't make less than one perimeter when spiral vase mode is enabled";
|
||||
if (this->fill_density > 0)
|
||||
return "Spiral vase mode can only print hollow objects, so you need to set Fill density to 0";
|
||||
if (this->top_solid_layers > 0)
|
||||
return "Spiral vase mode is not compatible with top solid layers";
|
||||
if (this->support_material || this->support_material_enforce_layers > 0)
|
||||
return "Spiral vase mode is not compatible with support material";
|
||||
}
|
||||
|
||||
// extrusion widths
|
||||
{
|
||||
double max_nozzle_diameter = 0.;
|
||||
for (double dmr : this->nozzle_diameter.values)
|
||||
max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
|
||||
const char *widths[] = { "external_perimeter", "perimeter", "infill", "solid_infill", "top_infill", "support_material", "first_layer" };
|
||||
for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++ i) {
|
||||
std::string key(widths[i]);
|
||||
key += "_extrusion_width";
|
||||
if (this->get_abs_value(key, max_nozzle_diameter) > 10. * max_nozzle_diameter)
|
||||
return std::string("Invalid extrusion width (too large): ") + key;
|
||||
}
|
||||
}
|
||||
|
||||
// Out of range validation of numeric values.
|
||||
for (const std::string &opt_key : this->keys()) {
|
||||
const ConfigOption *opt = this->optptr(opt_key);
|
||||
assert(opt != nullptr);
|
||||
const ConfigOptionDef *optdef = print_config_def.get(opt_key);
|
||||
assert(optdef != nullptr);
|
||||
bool out_of_range = false;
|
||||
switch (opt->type()) {
|
||||
case coFloat:
|
||||
case coPercent:
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto *fopt = static_cast<const ConfigOptionFloat*>(opt);
|
||||
out_of_range = fopt->value < optdef->min || fopt->value > optdef->max;
|
||||
break;
|
||||
}
|
||||
case coFloats:
|
||||
case coPercents:
|
||||
for (double v : static_cast<const ConfigOptionFloats*>(opt)->values)
|
||||
if (v < optdef->min || v > optdef->max) {
|
||||
out_of_range = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case coInt:
|
||||
{
|
||||
auto *iopt = static_cast<const ConfigOptionInt*>(opt);
|
||||
out_of_range = iopt->value < optdef->min || iopt->value > optdef->max;
|
||||
break;
|
||||
}
|
||||
case coInts:
|
||||
for (int v : static_cast<const ConfigOptionInts*>(opt)->values)
|
||||
if (v < optdef->min || v > optdef->max) {
|
||||
out_of_range = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
if (out_of_range)
|
||||
return std::string("Value out of range: " + opt_key);
|
||||
}
|
||||
|
||||
// The configuration is valid.
|
||||
return "";
|
||||
}
|
||||
|
||||
// Declare the static caches for each StaticPrintConfig derived class.
|
||||
StaticPrintConfig::StaticCache<class Slic3r::PrintObjectConfig> PrintObjectConfig::s_cache;
|
||||
StaticPrintConfig::StaticCache<class Slic3r::PrintRegionConfig> PrintRegionConfig::s_cache;
|
||||
StaticPrintConfig::StaticCache<class Slic3r::GCodeConfig> GCodeConfig::s_cache;
|
||||
StaticPrintConfig::StaticCache<class Slic3r::PrintConfig> PrintConfig::s_cache;
|
||||
StaticPrintConfig::StaticCache<class Slic3r::HostConfig> HostConfig::s_cache;
|
||||
StaticPrintConfig::StaticCache<class Slic3r::FullPrintConfig> FullPrintConfig::s_cache;
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
// during the slicing and the g-code generation.
|
||||
//
|
||||
// The classes derived from StaticPrintConfig form a following hierarchy.
|
||||
// Virtual inheritance is used for some of the parent objects.
|
||||
//
|
||||
// FullPrintConfig
|
||||
// PrintObjectConfig
|
||||
@ -21,8 +20,6 @@
|
||||
#include "libslic3r.h"
|
||||
#include "Config.hpp"
|
||||
|
||||
#define OPT_PTR(KEY) if (opt_key == #KEY) return &this->KEY
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum GCodeFlavor {
|
||||
@ -46,66 +43,76 @@ enum FilamentType {
|
||||
ftPLA, ftABS, ftPET, ftHIPS, ftFLEX, ftSCAFF, ftEDGE, ftNGEN, ftPVA
|
||||
};
|
||||
|
||||
template<> inline t_config_enum_values ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
|
||||
t_config_enum_values keys_map;
|
||||
keys_map["reprap"] = gcfRepRap;
|
||||
keys_map["repetier"] = gcfRepetier;
|
||||
keys_map["teacup"] = gcfTeacup;
|
||||
keys_map["makerware"] = gcfMakerWare;
|
||||
keys_map["sailfish"] = gcfSailfish;
|
||||
keys_map["smoothie"] = gcfSmoothie;
|
||||
keys_map["mach3"] = gcfMach3;
|
||||
keys_map["machinekit"] = gcfMachinekit;
|
||||
keys_map["no-extrusion"] = gcfNoExtrusion;
|
||||
template<> inline t_config_enum_values& ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["reprap"] = gcfRepRap;
|
||||
keys_map["repetier"] = gcfRepetier;
|
||||
keys_map["teacup"] = gcfTeacup;
|
||||
keys_map["makerware"] = gcfMakerWare;
|
||||
keys_map["sailfish"] = gcfSailfish;
|
||||
keys_map["smoothie"] = gcfSmoothie;
|
||||
keys_map["mach3"] = gcfMach3;
|
||||
keys_map["machinekit"] = gcfMachinekit;
|
||||
keys_map["no-extrusion"] = gcfNoExtrusion;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline t_config_enum_values ConfigOptionEnum<InfillPattern>::get_enum_values() {
|
||||
t_config_enum_values keys_map;
|
||||
keys_map["rectilinear"] = ipRectilinear;
|
||||
keys_map["grid"] = ipGrid;
|
||||
keys_map["triangles"] = ipTriangles;
|
||||
keys_map["stars"] = ipStars;
|
||||
keys_map["cubic"] = ipCubic;
|
||||
keys_map["line"] = ipLine;
|
||||
keys_map["concentric"] = ipConcentric;
|
||||
keys_map["honeycomb"] = ipHoneycomb;
|
||||
keys_map["3dhoneycomb"] = ip3DHoneycomb;
|
||||
keys_map["hilbertcurve"] = ipHilbertCurve;
|
||||
keys_map["archimedeanchords"] = ipArchimedeanChords;
|
||||
keys_map["octagramspiral"] = ipOctagramSpiral;
|
||||
template<> inline t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["rectilinear"] = ipRectilinear;
|
||||
keys_map["grid"] = ipGrid;
|
||||
keys_map["triangles"] = ipTriangles;
|
||||
keys_map["stars"] = ipStars;
|
||||
keys_map["cubic"] = ipCubic;
|
||||
keys_map["line"] = ipLine;
|
||||
keys_map["concentric"] = ipConcentric;
|
||||
keys_map["honeycomb"] = ipHoneycomb;
|
||||
keys_map["3dhoneycomb"] = ip3DHoneycomb;
|
||||
keys_map["hilbertcurve"] = ipHilbertCurve;
|
||||
keys_map["archimedeanchords"] = ipArchimedeanChords;
|
||||
keys_map["octagramspiral"] = ipOctagramSpiral;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline t_config_enum_values ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
|
||||
t_config_enum_values keys_map;
|
||||
keys_map["rectilinear"] = smpRectilinear;
|
||||
keys_map["rectilinear-grid"] = smpRectilinearGrid;
|
||||
keys_map["honeycomb"] = smpHoneycomb;
|
||||
keys_map["pillars"] = smpPillars;
|
||||
template<> inline t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["rectilinear"] = smpRectilinear;
|
||||
keys_map["rectilinear-grid"] = smpRectilinearGrid;
|
||||
keys_map["honeycomb"] = smpHoneycomb;
|
||||
keys_map["pillars"] = smpPillars;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline t_config_enum_values ConfigOptionEnum<SeamPosition>::get_enum_values() {
|
||||
t_config_enum_values keys_map;
|
||||
keys_map["random"] = spRandom;
|
||||
keys_map["nearest"] = spNearest;
|
||||
keys_map["aligned"] = spAligned;
|
||||
keys_map["rear"] = spRear;
|
||||
template<> inline t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["random"] = spRandom;
|
||||
keys_map["nearest"] = spNearest;
|
||||
keys_map["aligned"] = spAligned;
|
||||
keys_map["rear"] = spRear;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline t_config_enum_values ConfigOptionEnum<FilamentType>::get_enum_values() {
|
||||
t_config_enum_values keys_map;
|
||||
keys_map["PLA"] = ftPLA;
|
||||
keys_map["ABS"] = ftABS;
|
||||
keys_map["PET"] = ftPET;
|
||||
keys_map["HIPS"] = ftHIPS;
|
||||
keys_map["FLEX"] = ftFLEX;
|
||||
keys_map["SCAFF"] = ftSCAFF;
|
||||
keys_map["EDGE"] = ftEDGE;
|
||||
keys_map["NGEN"] = ftNGEN;
|
||||
keys_map["PVA"] = ftPVA;
|
||||
template<> inline t_config_enum_values& ConfigOptionEnum<FilamentType>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["PLA"] = ftPLA;
|
||||
keys_map["ABS"] = ftABS;
|
||||
keys_map["PET"] = ftPET;
|
||||
keys_map["HIPS"] = ftHIPS;
|
||||
keys_map["FLEX"] = ftFLEX;
|
||||
keys_map["SCAFF"] = ftSCAFF;
|
||||
keys_map["EDGE"] = ftEDGE;
|
||||
keys_map["NGEN"] = ftNGEN;
|
||||
keys_map["PVA"] = ftPVA;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
@ -113,60 +120,177 @@ template<> inline t_config_enum_values ConfigOptionEnum<FilamentType>::get_enum_
|
||||
// Does not store the actual values, but defines default values.
|
||||
class PrintConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
public:
|
||||
PrintConfigDef();
|
||||
|
||||
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
|
||||
};
|
||||
|
||||
// The one and only global definition of SLic3r configuration options.
|
||||
// This definition is constant.
|
||||
extern PrintConfigDef print_config_def;
|
||||
|
||||
// Slic3r configuration storage with print_config_def assigned.
|
||||
class PrintConfigBase : public virtual ConfigBase
|
||||
{
|
||||
public:
|
||||
PrintConfigBase() {
|
||||
this->def = &print_config_def;
|
||||
};
|
||||
|
||||
bool set_deserialize(t_config_option_key opt_key, std::string str, bool append = false);
|
||||
|
||||
double min_object_distance() const;
|
||||
|
||||
protected:
|
||||
void _handle_legacy(t_config_option_key &opt_key, std::string &value) const;
|
||||
};
|
||||
|
||||
// Slic3r dynamic configuration, used to override the configuration
|
||||
// per object, per modification volume or per printing material.
|
||||
// The dynamic configuration is also used to store user modifications of the print global parameters,
|
||||
// so the modified configuration values may be diffed against the active configuration
|
||||
// to invalidate the proper slicing resp. g-code generation processing steps.
|
||||
// This object is mapped to Perl as Slic3r::Config.
|
||||
class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
|
||||
class DynamicPrintConfig : public DynamicConfig
|
||||
{
|
||||
public:
|
||||
DynamicPrintConfig() : PrintConfigBase(), DynamicConfig() {};
|
||||
void normalize();
|
||||
public:
|
||||
DynamicPrintConfig() {}
|
||||
DynamicPrintConfig(const DynamicPrintConfig &other) : DynamicConfig(other) {}
|
||||
|
||||
// Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
const ConfigDef* def() const override { return &print_config_def; }
|
||||
|
||||
void normalize();
|
||||
|
||||
// Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||
std::string validate();
|
||||
};
|
||||
|
||||
template<typename CONFIG>
|
||||
void normalize_and_apply_config(CONFIG &dst, const DynamicPrintConfig &src)
|
||||
{
|
||||
DynamicPrintConfig src_normalized = src;
|
||||
DynamicPrintConfig src_normalized(src);
|
||||
src_normalized.normalize();
|
||||
dst.apply(src_normalized, true);
|
||||
}
|
||||
|
||||
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
||||
class StaticPrintConfig : public StaticConfig
|
||||
{
|
||||
public:
|
||||
StaticPrintConfig() {}
|
||||
|
||||
// Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
const ConfigDef* def() const override { return &print_config_def; }
|
||||
|
||||
protected:
|
||||
// Verify whether the opt_key has not been obsoleted or renamed.
|
||||
// Both opt_key and value may be modified by handle_legacy().
|
||||
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
|
||||
// handle_legacy() is called internally by set_deserialize().
|
||||
void handle_legacy(t_config_option_key &opt_key, std::string &value) const override
|
||||
{ PrintConfigDef::handle_legacy(opt_key, value); }
|
||||
|
||||
// Internal class for keeping a dynamic map to static options.
|
||||
class StaticCacheBase
|
||||
{
|
||||
public:
|
||||
StaticPrintConfig() : PrintConfigBase(), StaticConfig() {};
|
||||
// To be called during the StaticCache setup.
|
||||
// Add one ConfigOption into m_map_name_to_offset.
|
||||
template<typename T>
|
||||
void opt_add(const std::string &name, const char *base_ptr, const T &opt)
|
||||
{
|
||||
assert(m_map_name_to_offset.find(name) == m_map_name_to_offset.end());
|
||||
m_map_name_to_offset[name] = (const char*)&opt - base_ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::map<std::string, ptrdiff_t> m_map_name_to_offset;
|
||||
};
|
||||
|
||||
// Parametrized by the type of the topmost class owning the options.
|
||||
template<typename T>
|
||||
class StaticCache : public StaticCacheBase
|
||||
{
|
||||
public:
|
||||
// Calling the constructor of m_defaults with 0 forces m_defaults to not run the initialization.
|
||||
StaticCache() : m_defaults(nullptr) {}
|
||||
~StaticCache() { delete m_defaults; m_defaults = nullptr; }
|
||||
|
||||
bool initialized() const { return ! m_keys.empty(); }
|
||||
|
||||
ConfigOption* optptr(const std::string &name, T *owner) const
|
||||
{
|
||||
const auto it = m_map_name_to_offset.find(name);
|
||||
return (it == m_map_name_to_offset.end()) ? nullptr : reinterpret_cast<ConfigOption*>((char*)owner + it->second);
|
||||
}
|
||||
|
||||
const ConfigOption* optptr(const std::string &name, const T *owner) const
|
||||
{
|
||||
const auto it = m_map_name_to_offset.find(name);
|
||||
return (it == m_map_name_to_offset.end()) ? nullptr : reinterpret_cast<const ConfigOption*>((const char*)owner + it->second);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& keys() const { return m_keys; }
|
||||
const T& defaults() const { return *m_defaults; }
|
||||
|
||||
// To be called during the StaticCache setup.
|
||||
// Collect option keys from m_map_name_to_offset,
|
||||
// assign default values to m_defaults.
|
||||
void finalize(T *defaults, const ConfigDef *defs)
|
||||
{
|
||||
assert(defs != nullptr);
|
||||
m_defaults = defaults;
|
||||
m_keys.clear();
|
||||
m_keys.reserve(m_map_name_to_offset.size());
|
||||
for (const auto &kvp : defs->options) {
|
||||
// Find the option given the option name kvp.first by an offset from (char*)m_defaults.
|
||||
ConfigOption *opt = this->optptr(kvp.first, m_defaults);
|
||||
if (opt == nullptr)
|
||||
// This option is not defined by the ConfigBase of type T.
|
||||
continue;
|
||||
m_keys.emplace_back(kvp.first);
|
||||
const ConfigOptionDef *def = defs->get(kvp.first);
|
||||
assert(def != nullptr);
|
||||
if (def->default_value != nullptr)
|
||||
opt->set(def->default_value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_defaults;
|
||||
std::vector<std::string> m_keys;
|
||||
};
|
||||
};
|
||||
|
||||
#define STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
|
||||
public: \
|
||||
/* Overrides ConfigBase::optptr(). Find ando/or create a ConfigOption instance for a given name. */ \
|
||||
ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override \
|
||||
{ return s_cache.optptr(opt_key, this); } \
|
||||
/* Overrides ConfigBase::keys(). Collect names of all configuration values maintained by this configuration store. */ \
|
||||
t_config_option_keys keys() const override { return s_cache.keys(); } \
|
||||
static const CLASS_NAME& defaults() { initialize_cache(); return s_cache.defaults(); } \
|
||||
protected: \
|
||||
static void initialize_cache() \
|
||||
{ \
|
||||
if (! s_cache.initialized()) { \
|
||||
CLASS_NAME *inst = new CLASS_NAME(1); \
|
||||
inst->initialize(s_cache, (const char*)inst); \
|
||||
s_cache.finalize(inst, inst->def()); \
|
||||
} \
|
||||
} \
|
||||
/* Cache object holding a key/option map, a list of option keys and a copy of this static config initialized with the defaults. */ \
|
||||
static StaticCache<CLASS_NAME> s_cache;
|
||||
|
||||
#define STATIC_PRINT_CONFIG_CACHE(CLASS_NAME) \
|
||||
STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
|
||||
public: \
|
||||
/* Public default constructor will initialize the key/option cache and the default object copy if needed. */ \
|
||||
CLASS_NAME() { initialize_cache(); *this = s_cache.defaults(); } \
|
||||
protected: \
|
||||
/* Protected constructor to be called when compounded. */ \
|
||||
CLASS_NAME(int) {}
|
||||
|
||||
#define STATIC_PRINT_CONFIG_CACHE_DERIVED(CLASS_NAME) \
|
||||
STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
|
||||
public: \
|
||||
/* Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here. */ \
|
||||
const ConfigDef* def() const override { return &print_config_def; } \
|
||||
/* Handle legacy and obsoleted config keys */ \
|
||||
void handle_legacy(t_config_option_key &opt_key, std::string &value) const override \
|
||||
{ PrintConfigDef::handle_legacy(opt_key, value); }
|
||||
|
||||
#define OPT_PTR(KEY) cache.opt_add(#KEY, base_ptr, this->KEY)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::PrintObject.
|
||||
class PrintObjectConfig : public virtual StaticPrintConfig
|
||||
class PrintObjectConfig : public StaticPrintConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE(PrintObjectConfig)
|
||||
public:
|
||||
ConfigOptionBool clip_multipart_objects;
|
||||
ConfigOptionBool dont_support_bridges;
|
||||
@ -201,13 +325,9 @@ public:
|
||||
ConfigOptionFloatOrPercent support_material_xy_spacing;
|
||||
ConfigOptionFloat xy_size_compensation;
|
||||
|
||||
PrintObjectConfig(bool initialize = true) : StaticPrintConfig() {
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
OPT_PTR(clip_multipart_objects);
|
||||
OPT_PTR(dont_support_bridges);
|
||||
OPT_PTR(elefant_foot_compensation);
|
||||
@ -240,14 +360,13 @@ public:
|
||||
OPT_PTR(support_material_threshold);
|
||||
OPT_PTR(support_material_with_sheath);
|
||||
OPT_PTR(xy_size_compensation);
|
||||
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
||||
class PrintRegionConfig : public virtual StaticPrintConfig
|
||||
class PrintRegionConfig : public StaticPrintConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE(PrintRegionConfig)
|
||||
public:
|
||||
ConfigOptionFloat bridge_angle;
|
||||
ConfigOptionInt bottom_solid_layers;
|
||||
@ -283,14 +402,10 @@ public:
|
||||
ConfigOptionFloatOrPercent top_infill_extrusion_width;
|
||||
ConfigOptionInt top_solid_layers;
|
||||
ConfigOptionFloatOrPercent top_solid_infill_speed;
|
||||
|
||||
PrintRegionConfig(bool initialize = true) : StaticPrintConfig() {
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
OPT_PTR(bridge_angle);
|
||||
OPT_PTR(bottom_solid_layers);
|
||||
OPT_PTR(bridge_flow_ratio);
|
||||
@ -325,14 +440,13 @@ public:
|
||||
OPT_PTR(top_infill_extrusion_width);
|
||||
OPT_PTR(top_solid_infill_speed);
|
||||
OPT_PTR(top_solid_layers);
|
||||
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::GCode.
|
||||
class GCodeConfig : public virtual StaticPrintConfig
|
||||
class GCodeConfig : public StaticPrintConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE(GCodeConfig)
|
||||
public:
|
||||
ConfigOptionString before_layer_gcode;
|
||||
ConfigOptionFloats deretract_speed;
|
||||
@ -372,13 +486,16 @@ public:
|
||||
ConfigOptionBool use_volumetric_e;
|
||||
ConfigOptionBool variable_layer_height;
|
||||
|
||||
GCodeConfig(bool initialize = true) : StaticPrintConfig() {
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
std::string get_extrusion_axis() const
|
||||
{
|
||||
return
|
||||
((this->gcode_flavor.value == gcfMach3) || (this->gcode_flavor.value == gcfMachinekit)) ? "A" :
|
||||
(this->gcode_flavor.value == gcfNoExtrusion) ? "" : this->extrusion_axis.value;
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
OPT_PTR(before_layer_gcode);
|
||||
OPT_PTR(deretract_speed);
|
||||
OPT_PTR(end_gcode);
|
||||
@ -416,25 +533,18 @@ public:
|
||||
OPT_PTR(use_relative_e_distances);
|
||||
OPT_PTR(use_volumetric_e);
|
||||
OPT_PTR(variable_layer_height);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
std::string get_extrusion_axis() const
|
||||
{
|
||||
if ((this->gcode_flavor.value == gcfMach3) || (this->gcode_flavor.value == gcfMachinekit)) {
|
||||
return "A";
|
||||
} else if (this->gcode_flavor.value == gcfNoExtrusion) {
|
||||
return "";
|
||||
} else {
|
||||
return this->extrusion_axis.value;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::Print.
|
||||
class PrintConfig : public GCodeConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig)
|
||||
PrintConfig() : GCodeConfig(0) { initialize_cache(); *this = s_cache.defaults(); }
|
||||
public:
|
||||
double min_object_distance() const;
|
||||
static double min_object_distance(const ConfigBase *config);
|
||||
|
||||
ConfigOptionBool avoid_crossing_perimeters;
|
||||
ConfigOptionPoints bed_shape;
|
||||
ConfigOptionInts bed_temperature;
|
||||
@ -494,12 +604,11 @@ public:
|
||||
ConfigOptionFloat wipe_tower_per_color_wipe;
|
||||
ConfigOptionFloat z_offset;
|
||||
|
||||
PrintConfig(bool initialize = true) : GCodeConfig(false) {
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
protected:
|
||||
PrintConfig(int) : GCodeConfig(1) {}
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
this->GCodeConfig::initialize(cache, base_ptr);
|
||||
OPT_PTR(avoid_crossing_perimeters);
|
||||
OPT_PTR(bed_shape);
|
||||
OPT_PTR(bed_temperature);
|
||||
@ -558,64 +667,58 @@ public:
|
||||
OPT_PTR(wipe_tower_width);
|
||||
OPT_PTR(wipe_tower_per_color_wipe);
|
||||
OPT_PTR(z_offset);
|
||||
|
||||
// look in parent class
|
||||
ConfigOption* opt;
|
||||
if ((opt = GCodeConfig::optptr(opt_key, create)) != NULL) return opt;
|
||||
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class HostConfig : public virtual StaticPrintConfig
|
||||
class HostConfig : public StaticPrintConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE(HostConfig)
|
||||
public:
|
||||
ConfigOptionString octoprint_host;
|
||||
ConfigOptionString octoprint_apikey;
|
||||
ConfigOptionString serial_port;
|
||||
ConfigOptionInt serial_speed;
|
||||
|
||||
HostConfig(bool initialize = true) : StaticPrintConfig() {
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
OPT_PTR(octoprint_host);
|
||||
OPT_PTR(octoprint_apikey);
|
||||
OPT_PTR(serial_port);
|
||||
OPT_PTR(serial_speed);
|
||||
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::Full.
|
||||
class FullPrintConfig
|
||||
: public PrintObjectConfig, public PrintRegionConfig, public PrintConfig, public HostConfig
|
||||
class FullPrintConfig :
|
||||
public PrintObjectConfig,
|
||||
public PrintRegionConfig,
|
||||
public PrintConfig,
|
||||
public HostConfig
|
||||
{
|
||||
public:
|
||||
FullPrintConfig(bool initialize = true) :
|
||||
PrintObjectConfig(false),
|
||||
PrintRegionConfig(false),
|
||||
PrintConfig(false),
|
||||
HostConfig(false)
|
||||
{
|
||||
if (initialize)
|
||||
this->set_defaults();
|
||||
}
|
||||
STATIC_PRINT_CONFIG_CACHE_DERIVED(FullPrintConfig)
|
||||
FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) { initialize_cache(); *this = s_cache.defaults(); }
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
ConfigOption* opt;
|
||||
if ((opt = PrintObjectConfig::optptr(opt_key, create)) != NULL) return opt;
|
||||
if ((opt = PrintRegionConfig::optptr(opt_key, create)) != NULL) return opt;
|
||||
if ((opt = PrintConfig::optptr(opt_key, create)) != NULL) return opt;
|
||||
if ((opt = HostConfig::optptr(opt_key, create)) != NULL) return opt;
|
||||
return NULL;
|
||||
};
|
||||
public:
|
||||
// Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||
std::string validate();
|
||||
protected:
|
||||
// Protected constructor to be called to initialize ConfigCache::m_default.
|
||||
FullPrintConfig(int) : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) {}
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
this->PrintObjectConfig::initialize(cache, base_ptr);
|
||||
this->PrintRegionConfig::initialize(cache, base_ptr);
|
||||
this->PrintConfig ::initialize(cache, base_ptr);
|
||||
this->HostConfig ::initialize(cache, base_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
#undef STATIC_PRINT_CONFIG_CACHE
|
||||
#undef STATIC_PRINT_CONFIG_CACHE_BASE
|
||||
#undef STATIC_PRINT_CONFIG_CACHE_DERIVED
|
||||
#undef OPT_PTR
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -948,7 +948,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
slices_margin_cached,
|
||||
// How much to offset the extracted contour outside of the grid.
|
||||
m_object_config->support_material_spacing.value + m_support_material_flow.spacing(),
|
||||
Geometry::deg2rad(m_object_config->support_material_angle));
|
||||
Geometry::deg2rad(m_object_config->support_material_angle.value));
|
||||
// 1) infill polygons, expand them by half the extrusion width + a tiny bit of extra.
|
||||
new_layer.polygons = support_grid_pattern.extract_support(m_support_material_flow.scaled_spacing()/2 + 5);
|
||||
// 2) Contact polygons will be projected down. To keep the interface and base layers to grow, return a contour a tiny bit smaller than the grid cells.
|
||||
@ -1155,7 +1155,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||
trimming,
|
||||
// How much to offset the extracted contour outside of the grid.
|
||||
m_object_config->support_material_spacing.value + m_support_material_flow.spacing(),
|
||||
Geometry::deg2rad(m_object_config->support_material_angle));
|
||||
Geometry::deg2rad(m_object_config->support_material_angle.value));
|
||||
tbb::task_group task_group_inner;
|
||||
// 1) Cache the slice of a support volume. The support volume is expanded by 1/2 of support material flow spacing
|
||||
// to allow a placement of suppot zig-zag snake along the grid lines.
|
||||
@ -2471,8 +2471,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||
LoopInterfaceProcessor loop_interface_processor(1.5 * m_support_material_interface_flow.scaled_width());
|
||||
loop_interface_processor.n_contact_loops = this->has_contact_loops() ? 1 : 0;
|
||||
|
||||
float base_angle = Geometry::deg2rad(float(m_object_config->support_material_angle));
|
||||
float interface_angle = Geometry::deg2rad(float(m_object_config->support_material_angle + 90.));
|
||||
float base_angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value));
|
||||
float interface_angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.));
|
||||
coordf_t interface_spacing = m_object_config->support_material_interface_spacing.value + m_support_material_interface_flow.spacing();
|
||||
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
||||
coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
|
||||
@ -2763,7 +2763,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||
if (base_layer.layer->bottom_z < EPSILON) {
|
||||
// Base flange (the 1st layer).
|
||||
filler = filler_interface.get();
|
||||
filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle + 90.));
|
||||
filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.));
|
||||
density = 0.5f;
|
||||
flow = m_first_layer_flow;
|
||||
// use the proper spacing for first layer as we don't need to align
|
||||
|
@ -77,7 +77,7 @@ ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) {
|
||||
ConfigOption* opt = THIS->option(opt_key);
|
||||
if (opt == NULL) return &PL_sv_undef;
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
const ConfigOptionDef* def = THIS->def()->get(opt_key);
|
||||
return ConfigOption_to_SV(*opt, *def);
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t
|
||||
ConfigOption* opt = THIS->option(opt_key);
|
||||
if (opt == NULL) return &PL_sv_undef;
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
const ConfigOptionDef* def = THIS->def()->get(opt_key);
|
||||
if (def->type == coFloats || def->type == coPercents) {
|
||||
ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
|
||||
return newSVnv(optv->get_at(i));
|
||||
@ -183,7 +183,7 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
ConfigOption* opt = THIS->option(opt_key, true);
|
||||
if (opt == NULL) CONFESS("Trying to set non-existing option");
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
const ConfigOptionDef* def = THIS->def()->get(opt_key);
|
||||
if (def->type == coFloat) {
|
||||
if (!looks_like_number(value)) return false;
|
||||
ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt);
|
||||
@ -297,7 +297,7 @@ ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV*
|
||||
|
||||
bool
|
||||
StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) {
|
||||
const ConfigOptionDef* optdef = THIS->def->get(opt_key);
|
||||
const ConfigOptionDef* optdef = THIS->def()->get(opt_key);
|
||||
if (!optdef->shortcut.empty()) {
|
||||
for (std::vector<t_config_option_key>::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) {
|
||||
if (!StaticConfig__set(THIS, *it, value)) return false;
|
||||
|
@ -23,7 +23,7 @@ DynamicPrintConfig& Preset::load(const std::vector<std::string> &keys)
|
||||
{
|
||||
// Set the configuration from the defaults.
|
||||
Slic3r::FullPrintConfig defaults;
|
||||
this->config.apply(defaults, keys.empty() ? defaults.keys() : keys);
|
||||
this->config.apply_only(defaults, keys.empty() ? defaults.keys() : keys);
|
||||
|
||||
if (! this->is_default) {
|
||||
// Load the preset file, apply preset values on top of defaults.
|
||||
|
@ -37,7 +37,7 @@
|
||||
void erase(t_config_option_key opt_key);
|
||||
void normalize();
|
||||
%name{setenv} void setenv_();
|
||||
double min_object_distance();
|
||||
double min_object_distance() %code{% RETVAL = PrintConfig::min_object_distance(THIS); %};
|
||||
%name{_load} void load(std::string file);
|
||||
%name{_load_from_gcode} void load_from_gcode(std::string input_file)
|
||||
%code%{
|
||||
@ -47,20 +47,20 @@
|
||||
croak("Error extracting configuration from a g-code %s:\n%s\n", input_file.c_str(), e.what());
|
||||
}
|
||||
%};
|
||||
%name{_save} void save(std::string file);
|
||||
void save(std::string file);
|
||||
};
|
||||
|
||||
%name{Slic3r::Config::Static} class StaticPrintConfig {
|
||||
static StaticPrintConfig* new_GCodeConfig()
|
||||
%code{% RETVAL = new GCodeConfig (); %};
|
||||
%code{% RETVAL = new GCodeConfig(); %};
|
||||
static StaticPrintConfig* new_PrintConfig()
|
||||
%code{% RETVAL = new PrintConfig (); %};
|
||||
%code{% RETVAL = new PrintConfig(); %};
|
||||
static StaticPrintConfig* new_PrintObjectConfig()
|
||||
%code{% RETVAL = new PrintObjectConfig (); %};
|
||||
%code{% RETVAL = new PrintObjectConfig(); %};
|
||||
static StaticPrintConfig* new_PrintRegionConfig()
|
||||
%code{% RETVAL = new PrintRegionConfig (); %};
|
||||
%code{% RETVAL = new PrintRegionConfig(); %};
|
||||
static StaticPrintConfig* new_FullPrintConfig()
|
||||
%code{% RETVAL = new FullPrintConfig (); %};
|
||||
%code{% RETVAL = static_cast<PrintObjectConfig*>(new FullPrintConfig()); %};
|
||||
~StaticPrintConfig();
|
||||
bool has(t_config_option_key opt_key);
|
||||
SV* as_hash()
|
||||
@ -93,10 +93,10 @@
|
||||
}
|
||||
%};
|
||||
%name{setenv} void setenv_();
|
||||
double min_object_distance();
|
||||
double min_object_distance() %code{% RETVAL = PrintConfig::min_object_distance(THIS); %};
|
||||
%name{_load} void load(std::string file);
|
||||
%name{_load_from_gcode} void load_from_gcode(std::string file);
|
||||
%name{_save} void save(std::string file);
|
||||
void save(std::string file);
|
||||
};
|
||||
|
||||
%package{Slic3r::Config};
|
||||
|
Loading…
Reference in New Issue
Block a user