Fix the extruder override logic. All role-based extruder options now default to 0, meaning no override is defined and the default (inherited) extruder is used. The default extruder option does not use the shortcut logic anymore (it was thus moved to be a CLI-specific logic)

This commit is contained in:
Alessandro Ranellucci 2014-03-26 00:08:15 +01:00
parent 2e6213fea6
commit 0ff33f47f1
8 changed files with 147 additions and 83 deletions

View File

@ -57,6 +57,8 @@ sub new_from_cli {
foreach my $opt_key (keys %args) { foreach my $opt_key (keys %args) {
if ($opt_key =~ /^(?:print_center|bed_size|duplicate_grid|extruder_offset|retract_layer_change|wipe)$/) { if ($opt_key =~ /^(?:print_center|bed_size|duplicate_grid|extruder_offset|retract_layer_change|wipe)$/) {
$self->set_deserialize($opt_key, $args{$opt_key}); $self->set_deserialize($opt_key, $args{$opt_key});
} elsif (my $shortcut = $Options->{$opt_key}{shortcut}) {
$self->set($_, $args{$opt_key}) for @$shortcut;
} else { } else {
$self->set($opt_key, $args{$opt_key}); $self->set($opt_key, $args{$opt_key});
} }

View File

@ -528,7 +528,7 @@ sub build {
$self->add_options_page('Multiple Extruders', 'funnel.png', optgroups => [ $self->add_options_page('Multiple Extruders', 'funnel.png', optgroups => [
{ {
title => 'Extruders', title => 'Override extruders',
options => [qw(perimeter_extruder infill_extruder support_material_extruder support_material_interface_extruder)], options => [qw(perimeter_extruder infill_extruder support_material_extruder support_material_interface_extruder)],
}, },
{ {

View File

@ -319,37 +319,6 @@ StaticConfig::keys(t_config_option_keys *keys) const {
} }
} }
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* const ConfigOption*
StaticConfig::option(const t_config_option_key opt_key) const StaticConfig::option(const t_config_option_key opt_key) const
{ {

View File

@ -22,6 +22,8 @@ class ConfigOption {
virtual ~ConfigOption() {}; virtual ~ConfigOption() {};
virtual std::string serialize() const = 0; virtual std::string serialize() const = 0;
virtual bool deserialize(std::string str) = 0; virtual bool deserialize(std::string str) = 0;
virtual int getInt() const { return 0; };
virtual void setInt(int val) {};
}; };
template <class T> template <class T>
@ -91,6 +93,8 @@ class ConfigOptionInt : public ConfigOption
ConfigOptionInt() : value(0) {}; ConfigOptionInt() : value(0) {};
operator int() const { return this->value; }; operator int() const { return this->value; };
int getInt() const { return this->value; };
void setInt(int val) { this->value = val; };
std::string serialize() const { std::string serialize() const {
std::ostringstream ss; std::ostringstream ss;
@ -499,11 +503,6 @@ class StaticConfig : public ConfigBase
{ {
public: public:
void keys(t_config_option_keys *keys) const; 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; 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; const ConfigOption* option(const t_config_option_key opt_key) const;

View File

@ -4,4 +4,44 @@ namespace Slic3r {
t_optiondef_map PrintConfigDef::def = PrintConfigDef::build_def(); t_optiondef_map PrintConfigDef::def = PrintConfigDef::build_def();
void
StaticPrintConfig::prepare_extruder_option(const t_config_option_key opt_key, DynamicPrintConfig& other)
{
// don't apply role-based extruders if their value is zero
if (other.has(opt_key) && other.option(opt_key)->getInt() == 0)
other.erase(opt_key);
// only apply default extruder if our role-based value is zero
// (i.e. default extruder has the lowest priority among all other values)
if (other.has("extruder")) {
int extruder = other.option("extruder")->getInt();
if (extruder > 0) {
if (!other.has(opt_key) && this->option(opt_key)->getInt() == 0)
other.option(opt_key, true)->setInt(extruder);
}
}
}
void
PrintObjectConfig::apply(const ConfigBase &other, bool ignore_nonexistent) {
DynamicPrintConfig other_clone;
other_clone.apply(other);
this->prepare_extruder_option("support_material_extruder", other_clone);
this->prepare_extruder_option("support_material_interface_extruder", other_clone);
StaticConfig::apply(other_clone, ignore_nonexistent);
};
void
PrintRegionConfig::apply(const ConfigBase &other, bool ignore_nonexistent) {
DynamicPrintConfig other_clone;
other_clone.apply(other);
this->prepare_extruder_option("infill_extruder", other_clone);
this->prepare_extruder_option("perimeter_extruder", other_clone);
StaticConfig::apply(other_clone, ignore_nonexistent);
};
} }

View File

@ -177,10 +177,6 @@ class PrintConfigDef
Options["extruder"].tooltip = "The extruder to use (unless more specific extruder settings are specified)."; Options["extruder"].tooltip = "The extruder to use (unless more specific extruder settings are specified).";
Options["extruder"].cli = "extruder=i"; Options["extruder"].cli = "extruder=i";
Options["extruder"].min = 1; Options["extruder"].min = 1;
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_interface_extruder");
Options["extruder_clearance_height"].type = coFloat; Options["extruder_clearance_height"].type = coFloat;
Options["extruder_clearance_height"].label = "Height"; Options["extruder_clearance_height"].label = "Height";
@ -404,8 +400,9 @@ class PrintConfigDef
Options["infill_extruder"].label = "Infill extruder"; Options["infill_extruder"].label = "Infill extruder";
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"].sidetext = "(leave 0 for default)";
Options["infill_extruder"].cli = "infill-extruder=i"; Options["infill_extruder"].cli = "infill-extruder=i";
Options["infill_extruder"].min = 1; Options["infill_extruder"].min = 0;
Options["infill_extrusion_width"].type = coFloatOrPercent; Options["infill_extrusion_width"].type = coFloatOrPercent;
Options["infill_extrusion_width"].label = "Infill"; Options["infill_extrusion_width"].label = "Infill";
@ -528,9 +525,10 @@ class PrintConfigDef
Options["perimeter_extruder"].label = "Perimeter extruder"; Options["perimeter_extruder"].label = "Perimeter extruder";
Options["perimeter_extruder"].category = "Extruders"; Options["perimeter_extruder"].category = "Extruders";
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"].sidetext = "(leave 0 for default)";
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_extruder"].min = 0;
Options["perimeter_extrusion_width"].type = coFloatOrPercent; Options["perimeter_extrusion_width"].type = coFloatOrPercent;
Options["perimeter_extrusion_width"].label = "Perimeters"; Options["perimeter_extrusion_width"].label = "Perimeters";
@ -777,8 +775,9 @@ class PrintConfigDef
Options["support_material_extruder"].label = "Support material extruder"; Options["support_material_extruder"].label = "Support material extruder";
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"].sidetext = "(leave 0 for default)";
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_extruder"].min = 0;
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";
@ -791,8 +790,9 @@ class PrintConfigDef
Options["support_material_interface_extruder"].label = "Support material interface extruder"; Options["support_material_interface_extruder"].label = "Support material interface extruder";
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"].sidetext = "(leave 0 for default)";
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_extruder"].min = 0;
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";
@ -934,7 +934,26 @@ class PrintConfigDef
}; };
}; };
class PrintObjectConfig : public virtual StaticConfig class DynamicPrintConfig : public DynamicConfig
{
public:
DynamicPrintConfig() {
this->def = &PrintConfigDef::def;
};
};
class StaticPrintConfig : public virtual StaticConfig
{
public:
StaticPrintConfig() {
this->def = &PrintConfigDef::def;
};
protected:
void prepare_extruder_option(const t_config_option_key opt_key, DynamicPrintConfig& other);
};
class PrintObjectConfig : public virtual StaticPrintConfig
{ {
public: public:
ConfigOptionFloatOrPercent extrusion_width; ConfigOptionFloatOrPercent extrusion_width;
@ -956,9 +975,7 @@ class PrintObjectConfig : public virtual StaticConfig
ConfigOptionFloat support_material_speed; ConfigOptionFloat support_material_speed;
ConfigOptionInt support_material_threshold; ConfigOptionInt support_material_threshold;
PrintObjectConfig() { PrintObjectConfig() : StaticPrintConfig() {
this->def = &PrintConfigDef::def;
this->extrusion_width.value = 0; this->extrusion_width.value = 0;
this->extrusion_width.percent = false; this->extrusion_width.percent = false;
this->first_layer_height.value = 0.35; this->first_layer_height.value = 0.35;
@ -970,10 +987,10 @@ class PrintObjectConfig : public virtual StaticConfig
this->support_material.value = false; this->support_material.value = false;
this->support_material_angle.value = 0; this->support_material_angle.value = 0;
this->support_material_enforce_layers.value = 0; this->support_material_enforce_layers.value = 0;
this->support_material_extruder.value = 1; this->support_material_extruder.value = 0;
this->support_material_extrusion_width.value = 0; this->support_material_extrusion_width.value = 0;
this->support_material_extrusion_width.percent = false; this->support_material_extrusion_width.percent = false;
this->support_material_interface_extruder.value = 1; this->support_material_interface_extruder.value = 0;
this->support_material_interface_layers.value = 3; this->support_material_interface_layers.value = 3;
this->support_material_interface_spacing.value = 0; this->support_material_interface_spacing.value = 0;
this->support_material_pattern.value = smpHoneycomb; this->support_material_pattern.value = smpHoneycomb;
@ -1004,9 +1021,11 @@ class PrintObjectConfig : public virtual StaticConfig
return NULL; return NULL;
}; };
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
}; };
class PrintRegionConfig : public virtual StaticConfig class PrintRegionConfig : public virtual StaticPrintConfig
{ {
public: public:
ConfigOptionInt bottom_solid_layers; ConfigOptionInt bottom_solid_layers;
@ -1028,19 +1047,17 @@ class PrintRegionConfig : public virtual StaticConfig
ConfigOptionFloatOrPercent top_infill_extrusion_width; ConfigOptionFloatOrPercent top_infill_extrusion_width;
ConfigOptionInt top_solid_layers; ConfigOptionInt top_solid_layers;
PrintRegionConfig() { PrintRegionConfig() : StaticPrintConfig() {
this->def = &PrintConfigDef::def;
this->bottom_solid_layers.value = 3; this->bottom_solid_layers.value = 3;
this->extra_perimeters.value = true; this->extra_perimeters.value = true;
this->fill_angle.value = 45; this->fill_angle.value = 45;
this->fill_density.value = 40; this->fill_density.value = 40;
this->fill_pattern.value = ipHoneycomb; this->fill_pattern.value = ipHoneycomb;
this->infill_extruder.value = 1; this->infill_extruder.value = 0;
this->infill_extrusion_width.value = 0; this->infill_extrusion_width.value = 0;
this->infill_extrusion_width.percent = false; this->infill_extrusion_width.percent = false;
this->infill_every_layers.value = 1; this->infill_every_layers.value = 1;
this->perimeter_extruder.value = 1; this->perimeter_extruder.value = 0;
this->perimeter_extrusion_width.value = 0; this->perimeter_extrusion_width.value = 0;
this->perimeter_extrusion_width.percent = false; this->perimeter_extrusion_width.percent = false;
this->perimeters.value = 3; this->perimeters.value = 3;
@ -1077,9 +1094,11 @@ class PrintRegionConfig : public virtual StaticConfig
return NULL; return NULL;
}; };
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
}; };
class PrintConfig : public virtual StaticConfig class PrintConfig : public virtual StaticPrintConfig
{ {
public: public:
ConfigOptionBool avoid_crossing_perimeters; ConfigOptionBool avoid_crossing_perimeters;
@ -1166,9 +1185,7 @@ class PrintConfig : public virtual StaticConfig
ConfigOptionBools wipe; ConfigOptionBools wipe;
ConfigOptionFloat z_offset; ConfigOptionFloat z_offset;
PrintConfig() { PrintConfig() : StaticPrintConfig() {
this->def = &PrintConfigDef::def;
this->avoid_crossing_perimeters.value = false; this->avoid_crossing_perimeters.value = false;
this->bed_size.point = Pointf(200,200); this->bed_size.point = Pointf(200,200);
this->bed_temperature.value = 0; this->bed_temperature.value = 0;
@ -1372,15 +1389,8 @@ class PrintConfig : public virtual StaticConfig
} }
}; };
class DynamicPrintConfig : public DynamicConfig
{
public:
DynamicPrintConfig() {
this->def = &PrintConfigDef::def;
};
};
class FullPrintConfig : public PrintObjectConfig, public PrintRegionConfig, public PrintConfig { class FullPrintConfig : public PrintObjectConfig, public PrintRegionConfig, public PrintConfig {
public:
ConfigOption* option(const t_config_option_key opt_key, bool create = false) { ConfigOption* option(const t_config_option_key opt_key, bool create = false) {
ConfigOption* opt; ConfigOption* opt;
if ((opt = PrintObjectConfig::option(opt_key, create)) != NULL) return opt; if ((opt = PrintObjectConfig::option(opt_key, create)) != NULL) return opt;
@ -1388,6 +1398,12 @@ class FullPrintConfig : public PrintObjectConfig, public PrintRegionConfig, publ
if ((opt = PrintConfig::option(opt_key, create)) != NULL) return opt; if ((opt = PrintConfig::option(opt_key, create)) != NULL) return opt;
return NULL; return NULL;
}; };
void apply(const ConfigBase &other, bool ignore_nonexistent = false) {
PrintObjectConfig::apply(other, ignore_nonexistent);
PrintRegionConfig::apply(other, ignore_nonexistent);
PrintConfig::apply(other, ignore_nonexistent);
};
}; };
} }

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 95; use Test::More tests => 99;
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);
@ -127,20 +127,60 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) {
} }
{ {
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; my $config = Slic3r::Config->new;
$config2->set('extruder', 2); $config->set('infill_extruder', 2);
is $config2->get('perimeter_extruder'), 2, 'shortcut is expanded in static config (set)'; my $config2 = Slic3r::Config::PrintRegion->new;
$config2->apply($config);
is $config2->get('infill_extruder'), $config->get('infill_extruder'),
'non-zero infill_extruder is applied';
} }
{ {
my $config3 = Slic3r::Config::Full->new; my $config = Slic3r::Config->new;
$config3->apply_dynamic($config); $config->set('infill_extruder', 0);
is $config3->get('perimeter_extruder'), 2, 'shortcut is expanded in static config (apply)'; my $config2 = Slic3r::Config::PrintRegion->new;
$config2->set('infill_extruder', 3);
$config2->apply($config);
isnt $config2->get('infill_extruder'), $config->get('infill_extruder'),
'zero infill_extruder is not applied';
}
{
my $config = Slic3r::Config->new;
$config->set('extruder', 3);
my $config2 = Slic3r::Config::PrintRegion->new;
$config2->set('infill_extruder', 2);
$config2->apply($config);
is $config2->get('infill_extruder'), 2, 'extruder does not overwrite non-zero role extruders';
is $config2->get('perimeter_extruder'), 3, 'extruder overwrites zero role extruders';
}
}
{
{
my $config = Slic3r::Config->new;
$config->set('support_material_extruder', 2);
my $config2 = Slic3r::Config::PrintObject->new;
$config2->apply($config);
is $config2->get('support_material_extruder'), $config->get('support_material_extruder'),
'non-zero support_material_extruder is applied';
}
{
my $config = Slic3r::Config->new;
$config->set('support_material_extruder', 0);
my $config2 = Slic3r::Config::PrintObject->new;
$config2->set('support_material_extruder', 3);
$config2->apply($config);
isnt $config2->get('support_material_extruder'), $config->get('support_material_extruder'),
'zero support_material_extruder is not applied';
}
{
my $config = Slic3r::Config->new;
$config->set('extruder', 3);
my $config2 = Slic3r::Config::PrintObject->new;
$config2->set('support_material_extruder', 2);
$config2->apply($config);
is $config2->get('support_material_extruder'), 2, 'extruder does not overwrite non-zero role extruders';
is $config2->get('support_material_interface_extruder'), 3, 'extruder overwrites zero role extruders';
} }
} }

View File

@ -102,8 +102,6 @@
double get_abs_value(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key);
%name{get_abs_value_over} %name{get_abs_value_over}
double get_abs_value(t_config_option_key opt_key, double ratio_over); double get_abs_value(t_config_option_key opt_key, double ratio_over);
void apply(PrintObjectConfig* other)
%code{% THIS->apply(*other, true); %};
void apply_dynamic(DynamicPrintConfig* other) void apply_dynamic(DynamicPrintConfig* other)
%code{% THIS->apply(*other, true); %}; %code{% THIS->apply(*other, true); %};
std::vector<std::string> get_keys() std::vector<std::string> get_keys()