Only expand shortcut options in StaticConfig objects. This way we can keep a default extruder value in the parts panel

This commit is contained in:
Alessandro Ranellucci 2014-03-22 20:12:54 +01:00
parent 61db9530d9
commit 21e6de0e59
7 changed files with 116 additions and 26 deletions

View File

@ -408,6 +408,7 @@ sub load_model_objects {
$o->add_instance(offset => [ @{$self->{config}->print_center} ]); $o->add_instance(offset => [ @{$self->{config}->print_center} ]);
} }
$self->{print}->auto_assign_extruders($o);
$self->{print}->add_model_object($o); $self->{print}->add_model_object($o);
} }

View File

@ -392,7 +392,7 @@ sub config {
$filament_config = $config; $filament_config = $config;
next; next;
} }
foreach my $opt_key (keys %$config) { foreach my $opt_key (@{$config->get_keys}) {
next unless ref $filament_config->get($opt_key) eq 'ARRAY'; next unless ref $filament_config->get($opt_key) eq 'ARRAY';
push @{ $filament_config->get($opt_key) }, $config->get($opt_key)->[0]; push @{ $filament_config->get($opt_key) }, $config->get($opt_key)->[0];
} }

View File

@ -1090,10 +1090,11 @@ sub auto_assign_extruders {
my $material = $model_object->model->materials->{ $volume->material_id }; my $material = $model_object->model->materials->{ $volume->material_id };
my $config = $material->config; my $config = $material->config;
my $extruder_id = $i + 1; my $extruder_id = $i + 1;
$config->set_ifndef('perimeter_extruder', $extruder_id); $config->set_ifndef('extruder', $extruder_id);
$config->set_ifndef('infill_extruder', $extruder_id); #$config->set_ifndef('perimeter_extruder', $extruder_id);
$config->set_ifndef('support_material_extruder', $extruder_id); #$config->set_ifndef('infill_extruder', $extruder_id);
$config->set_ifndef('support_material_interface_extruder', $extruder_id); #$config->set_ifndef('support_material_extruder', $extruder_id);
#$config->set_ifndef('support_material_interface_extruder', $extruder_id);
} }
} }
} }

View File

@ -8,7 +8,7 @@ ConfigBase::has(const t_config_option_key opt_key) {
} }
void void
ConfigBase::apply(ConfigBase &other, bool ignore_nonexistent) { ConfigBase::apply(const ConfigBase &other, bool ignore_nonexistent) {
// get list of option keys to apply // get list of option keys to apply
t_config_option_keys opt_keys; t_config_option_keys opt_keys;
other.keys(&opt_keys); other.keys(&opt_keys);
@ -169,13 +169,6 @@ ConfigBase::set(t_config_option_key opt_key, SV* value) {
ConfigOption* opt = this->option(opt_key, true); ConfigOption* opt = this->option(opt_key, true);
if (opt == NULL) CONFESS("Trying to set non-existing option"); if (opt == NULL) CONFESS("Trying to set non-existing option");
ConfigOptionDef* optdef = &(*this->def)[opt_key];
if (!optdef->shortcut.empty()) {
for (std::vector<t_config_option_key>::iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it)
this->set(*it, value);
return;
}
if (ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt)) { if (ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt)) {
optv->value = SvNV(value); optv->value = SvNV(value);
} else if (ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt)) { } else if (ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt)) {
@ -241,6 +234,11 @@ DynamicConfig::~DynamicConfig () {
} }
} }
DynamicConfig::DynamicConfig (const DynamicConfig& other) {
this->def = other.def;
this->apply(other, false);
}
ConfigOption* ConfigOption*
DynamicConfig::option(const t_config_option_key opt_key, bool create) { DynamicConfig::option(const t_config_option_key opt_key, bool create) {
if (this->options.count(opt_key) == 0) { if (this->options.count(opt_key) == 0) {
@ -287,8 +285,13 @@ DynamicConfig::option(const t_config_option_key opt_key, bool create) {
return this->options[opt_key]; return this->options[opt_key];
} }
const ConfigOption*
DynamicConfig::option(const t_config_option_key opt_key) const {
return const_cast<DynamicConfig*>(this)->option(opt_key, false);
}
void void
DynamicConfig::keys(t_config_option_keys *keys) { DynamicConfig::keys(t_config_option_keys *keys) const {
for (t_options_map::const_iterator it = this->options.begin(); it != this->options.end(); ++it) for (t_options_map::const_iterator it = this->options.begin(); it != this->options.end(); ++it)
keys->push_back(it->first); keys->push_back(it->first);
} }
@ -299,11 +302,62 @@ DynamicConfig::erase(const t_config_option_key opt_key) {
} }
void void
StaticConfig::keys(t_config_option_keys *keys) { StaticConfig::keys(t_config_option_keys *keys) const {
for (t_optiondef_map::const_iterator it = this->def->begin(); it != this->def->end(); ++it) { for (t_optiondef_map::const_iterator it = this->def->begin(); it != this->def->end(); ++it) {
ConfigOption* opt = this->option(it->first); const ConfigOption* opt = this->option(it->first);
if (opt != NULL) keys->push_back(it->first); if (opt != NULL) keys->push_back(it->first);
} }
} }
void
StaticConfig::apply(const DynamicConfig &other, bool ignore_nonexistent) {
// clone the other config so that we can remove shortcut options after applying them
DynamicConfig other_clone = other;
// get list of option keys to apply
t_config_option_keys opt_keys;
other_clone.keys(&opt_keys);
// loop through options and apply them
for (t_config_option_keys::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) {
// if this is not a shortcut, skip it
ConfigOptionDef* optdef = &(*this->def)[*opt_key];
if (optdef->shortcut.empty()) continue;
// expand the option into other_clone if it does not exist already
for (std::vector<t_config_option_key>::iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) {
if (other_clone.has(*it)) continue;
ConfigOption* my_opt = other_clone.option(*it, true);
// not the most efficient way, but easier than casting pointers to subclasses
my_opt->deserialize( other_clone.option(*opt_key)->serialize() );
}
// remove the shortcut option from other_clone
other_clone.erase(*opt_key);
}
static_cast<ConfigBase*>(this)->apply(other_clone, ignore_nonexistent);
}
const ConfigOption*
StaticConfig::option(const t_config_option_key opt_key) const
{
return const_cast<StaticConfig*>(this)->option(opt_key, false);
}
#ifdef SLIC3RXS
void
StaticConfig::set(t_config_option_key opt_key, SV* value) {
ConfigOptionDef* optdef = &(*this->def)[opt_key];
if (!optdef->shortcut.empty()) {
for (std::vector<t_config_option_key>::iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it)
this->set(*it, value);
return;
}
static_cast<ConfigBase*>(this)->set(opt_key, value);
}
#endif
} }

View File

@ -431,8 +431,9 @@ class ConfigBase
ConfigBase() : def(NULL) {}; ConfigBase() : def(NULL) {};
bool has(const t_config_option_key opt_key); bool has(const t_config_option_key opt_key);
virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0; virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0;
virtual void keys(t_config_option_keys *keys) = 0; virtual const ConfigOption* option(const t_config_option_key opt_key) const = 0;
void apply(ConfigBase &other, bool ignore_nonexistent = false); virtual void keys(t_config_option_keys *keys) const = 0;
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
std::string serialize(const t_config_option_key opt_key); std::string serialize(const t_config_option_key opt_key);
void set_deserialize(const t_config_option_key opt_key, std::string str); void set_deserialize(const t_config_option_key opt_key, std::string str);
double get_abs_value(const t_config_option_key opt_key); double get_abs_value(const t_config_option_key opt_key);
@ -450,13 +451,14 @@ class DynamicConfig : public ConfigBase
{ {
public: public:
DynamicConfig() {}; DynamicConfig() {};
DynamicConfig(const DynamicConfig& other);
~DynamicConfig(); ~DynamicConfig();
ConfigOption* option(const t_config_option_key opt_key, bool create = false); ConfigOption* option(const t_config_option_key opt_key, bool create = false);
void keys(t_config_option_keys *keys); const ConfigOption* option(const t_config_option_key opt_key) const;
void keys(t_config_option_keys *keys) const;
void erase(const t_config_option_key opt_key); void erase(const t_config_option_key opt_key);
private: private:
DynamicConfig(const DynamicConfig& other); // we disable this by making it private and unimplemented
DynamicConfig& operator= (const DynamicConfig& other); // we disable this by making it private and unimplemented DynamicConfig& operator= (const DynamicConfig& other); // we disable this by making it private and unimplemented
typedef std::map<t_config_option_key,ConfigOption*> t_options_map; typedef std::map<t_config_option_key,ConfigOption*> t_options_map;
t_options_map options; t_options_map options;
@ -465,7 +467,18 @@ class DynamicConfig : public ConfigBase
class StaticConfig : public ConfigBase class StaticConfig : public ConfigBase
{ {
public: public:
void keys(t_config_option_keys *keys); void keys(t_config_option_keys *keys) const;
void apply(const ConfigBase &other, bool ignore_nonexistent = false) {
// this proxy appears to be needed otherwise the inherited signature couldn't be found from .xsp
ConfigBase::apply(other, ignore_nonexistent);
};
void apply(const DynamicConfig &other, bool ignore_nonexistent = false);
virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0;
const ConfigOption* option(const t_config_option_key opt_key) const;
#ifdef SLIC3RXS
void set(t_config_option_key opt_key, SV* value);
#endif
}; };
} }

View File

@ -172,10 +172,11 @@ class PrintConfigDef
Options["extra_perimeters"].cli = "extra-perimeters!"; Options["extra_perimeters"].cli = "extra-perimeters!";
Options["extruder"].type = coInt; Options["extruder"].type = coInt;
Options["extruder"].label = "Extruder"; Options["extruder"].label = "Default extruder";
Options["extruder"].cli = "extruder=i"; Options["extruder"].cli = "extruder=i";
Options["extruder"].shortcut.push_back("perimeter_extruder"); Options["extruder"].min = 1;
Options["extruder"].shortcut.push_back("infill_extruder"); Options["extruder"].shortcut.push_back("infill_extruder");
Options["extruder"].shortcut.push_back("perimeter_extruder");
Options["extruder"].shortcut.push_back("support_material_extruder"); Options["extruder"].shortcut.push_back("support_material_extruder");
Options["extruder"].shortcut.push_back("support_material_interface_extruder"); Options["extruder"].shortcut.push_back("support_material_interface_extruder");
@ -397,6 +398,7 @@ class PrintConfigDef
Options["infill_extruder"].category = "Extruders"; Options["infill_extruder"].category = "Extruders";
Options["infill_extruder"].tooltip = "The extruder to use when printing infill."; Options["infill_extruder"].tooltip = "The extruder to use when printing infill.";
Options["infill_extruder"].cli = "infill-extruder=i"; Options["infill_extruder"].cli = "infill-extruder=i";
Options["infill_extruder"].min = 1;
Options["infill_extrusion_width"].type = coFloatOrPercent; Options["infill_extrusion_width"].type = coFloatOrPercent;
Options["infill_extrusion_width"].label = "Infill"; Options["infill_extrusion_width"].label = "Infill";
@ -515,6 +517,7 @@ class PrintConfigDef
Options["perimeter_extruder"].tooltip = "The extruder to use when printing perimeters."; Options["perimeter_extruder"].tooltip = "The extruder to use when printing perimeters.";
Options["perimeter_extruder"].cli = "perimeter-extruder=i"; Options["perimeter_extruder"].cli = "perimeter-extruder=i";
Options["perimeter_extruder"].aliases.push_back("perimeters_extruder"); Options["perimeter_extruder"].aliases.push_back("perimeters_extruder");
Options["perimeter_extruder"].min = 1;
Options["perimeter_extrusion_width"].type = coFloatOrPercent; Options["perimeter_extrusion_width"].type = coFloatOrPercent;
Options["perimeter_extrusion_width"].label = "Perimeters"; Options["perimeter_extrusion_width"].label = "Perimeters";
@ -762,6 +765,7 @@ class PrintConfigDef
Options["support_material_extruder"].category = "Extruders"; Options["support_material_extruder"].category = "Extruders";
Options["support_material_extruder"].tooltip = "The extruder to use when printing support material. This affects brim and raft too."; Options["support_material_extruder"].tooltip = "The extruder to use when printing support material. This affects brim and raft too.";
Options["support_material_extruder"].cli = "support-material-extruder=i"; Options["support_material_extruder"].cli = "support-material-extruder=i";
Options["support_material_extruder"].min = 1;
Options["support_material_extrusion_width"].type = coFloatOrPercent; Options["support_material_extrusion_width"].type = coFloatOrPercent;
Options["support_material_extrusion_width"].label = "Support material"; Options["support_material_extrusion_width"].label = "Support material";
@ -775,6 +779,7 @@ class PrintConfigDef
Options["support_material_interface_extruder"].category = "Extruders"; Options["support_material_interface_extruder"].category = "Extruders";
Options["support_material_interface_extruder"].tooltip = "The extruder to use when printing support material interface. This affects raft too."; Options["support_material_interface_extruder"].tooltip = "The extruder to use when printing support material interface. This affects raft too.";
Options["support_material_interface_extruder"].cli = "support-material-interface-extruder=i"; Options["support_material_interface_extruder"].cli = "support-material-interface-extruder=i";
Options["support_material_interface_extruder"].min = 1;
Options["support_material_interface_layers"].type = coInt; Options["support_material_interface_layers"].type = coInt;
Options["support_material_interface_layers"].label = "Interface layers"; Options["support_material_interface_layers"].label = "Interface layers";

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 91; use Test::More tests => 94;
foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) { foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) {
$config->set('layer_height', 0.3); $config->set('layer_height', 0.3);
@ -97,8 +97,6 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) {
{ {
my $config = Slic3r::Config->new; my $config = Slic3r::Config->new;
$config->set('perimeters', 2); $config->set('perimeters', 2);
$config->set('solid_layers', 2);
is $config->get('top_solid_layers'), 2, 'shortcut';
# test that no crash happens when using set_deserialize() with a key that hasn't been set() yet # test that no crash happens when using set_deserialize() with a key that hasn't been set() yet
$config->set_deserialize('filament_diameter', '3'); $config->set_deserialize('filament_diameter', '3');
@ -128,4 +126,22 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) {
is $config->get('fill_pattern'), 'line', 'no interferences between DynamicConfig objects'; is $config->get('fill_pattern'), 'line', 'no interferences between DynamicConfig objects';
} }
{
my $config = Slic3r::Config->new;
$config->set('extruder', 2);
is $config->get('extruder'), 2, 'shortcut option value is kept in dynamic config';
ok !$config->has('perimeter_extruder'), 'shortcut is not expanded in dynamic config';
{
my $config2 = Slic3r::Config::Full->new;
$config2->set('extruder', 2);
is $config2->get('perimeter_extruder'), 2, 'shortcut is expanded in static config (set)';
}
{
my $config3 = Slic3r::Config::Full->new;
$config3->apply_dynamic($config);
is $config3->get('perimeter_extruder'), 2, 'shortcut is expanded in static config (apply)';
}
}
__END__ __END__