diff --git a/README.md b/README.md index a298ec85..167c3f33 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ The author of the Silk icon set is Mark James. --top-solid-layers Number of solid layers to do for top surfaces (range: 0+, default: 3) --bottom-solid-layers Number of solid layers to do for bottom surfaces (range: 0+, default: 3) --solid-layers Shortcut for setting the two options above at once - --fill-density Infill density (range: 0-1, default: 0.4) + --fill-density Infill density (range: 0%-100%, default: 40%) --fill-angle Infill angle in degrees (range: 0-90, default: 45) --fill-pattern Pattern to use to fill non-solid layers (default: honeycomb) --solid-fill-pattern Pattern to use to fill solid layers (default: rectilinear) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index e8884d6a..22088ff3 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -119,6 +119,11 @@ sub _handle_legacy { if ($opt_key eq 'gcode_flavor' && $value eq 'makerbot') { $value = 'makerware'; } + if ($opt_key eq 'fill_density' && $value <= 1) { + # fill_density was turned into a percent value + $value *= 100; + $value = "$value"; # force update of the PV value, workaround for bug https://rt.cpan.org/Ticket/Display.html?id=94110 + } # For historical reasons, the world's full of configs having these very low values; # to avoid unexpected behavior we need to ignore them. Banning these two hard-coded @@ -258,9 +263,9 @@ sub validate { # --fill-density die "Invalid value for --fill-density\n" - if $self->fill_density < 0 || $self->fill_density > 1; + if $self->fill_density < 0 || $self->fill_density > 100; die "The selected fill pattern is not supposed to work at 100% density\n" - if $self->fill_density == 1 + if $self->fill_density == 100 && !first { $_ eq $self->fill_pattern } @{$Options->{solid_fill_pattern}{values}}; # --infill-every-layers @@ -343,10 +348,11 @@ sub validate { @values = ($self->$opt_key); } foreach my $value (@values) { - if ($type eq 'i' || $type eq 'f') { + if ($type eq 'i' || $type eq 'f' || $opt->{type} eq 'percent') { + $value =~ s/%$// if $opt->{type} eq 'percent'; die "Invalid value for $opt_key\n" if ($type eq 'i' && $value !~ /^-?\d+$/) - || ($type eq 'f' && $value !~ /^-?(?:\d+|\d*\.\d+)$/) + || (($type eq 'f' || $opt->{type} eq 'percent') && $value !~ /^-?(?:\d+|\d*\.\d+)$/) || (defined $opt->{min} && $value < $opt->{min}) || (defined $opt->{max} && $value > $opt->{max}); } elsif ($type eq 's' && $opt->{type} eq 'select') { diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 43a88120..968b27f6 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -192,7 +192,7 @@ sub make_fill { # force 100% density and rectilinear fill for external surfaces if ($surface->surface_type != S_TYPE_INTERNAL) { - $density = 1; + $density = 100; $filler = $layerm->config->solid_fill_pattern; if ($is_bridge) { $filler = 'rectilinear'; @@ -209,7 +209,7 @@ sub make_fill { $f->angle($layerm->config->fill_angle); my ($params, @polylines) = $f->fill_surface( $surface, - density => $density, + density => $density/100, flow => $flow, ); next unless @polylines; diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index d849405b..c1cbe2d1 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -165,7 +165,7 @@ sub _build_field { my $field; my $tooltip = $opt->{tooltip}; - if ($opt->{type} =~ /^(i|f|s|s@)$/) { + if ($opt->{type} =~ /^(i|f|s|s@|percent)$/) { my $style = 0; $style = wxTE_MULTILINE if $opt->{multiline}; # default width on Windows is too large diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 68c31969..bc0c358b 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -604,7 +604,7 @@ sub bridge_over_infill { for my $region_id (0..$#{$self->print->regions}) { my $fill_density = $self->print->regions->[$region_id]->config->fill_density; - next if $fill_density == 1 || $fill_density == 0; + next if $fill_density == 100 || $fill_density == 0; for my $layer_id (1..$#{$self->layers}) { my $layer = $self->layers->[$layer_id]; diff --git a/slic3r.pl b/slic3r.pl index f633d69c..284f9169 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -301,7 +301,7 @@ $j --top-solid-layers Number of solid layers to do for top surfaces (range: 0+, default: $config->{top_solid_layers}) --bottom-solid-layers Number of solid layers to do for bottom surfaces (range: 0+, default: $config->{bottom_solid_layers}) --solid-layers Shortcut for setting the two options above at once - --fill-density Infill density (range: 0-1, default: $config->{fill_density}) + --fill-density Infill density (range: 0%-100%, default: $config->{fill_density}%) --fill-angle Infill angle in degrees (range: 0-90, default: $config->{fill_angle}) --fill-pattern Pattern to use to fill non-solid layers (default: $config->{fill_pattern}) --solid-fill-pattern Pattern to use to fill solid layers (default: $config->{solid_fill_pattern}) diff --git a/t/fill.t b/t/fill.t index 55116016..365d8e06 100644 --- a/t/fill.t +++ b/t/fill.t @@ -172,7 +172,7 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { $config->set('fill_pattern', $pattern); $config->set('perimeters', 1); $config->set('skirts', 0); - $config->set('fill_density', 0.2); + $config->set('fill_density', 20); $config->set('layer_height', 0.05); $config->set('perimeter_extruder', 1); $config->set('infill_extruder', 2); diff --git a/xs/src/Config.cpp b/xs/src/Config.cpp index a4e2def8..6f59290b 100644 --- a/xs/src/Config.cpp +++ b/xs/src/Config.cpp @@ -95,6 +95,8 @@ ConfigBase::get(t_config_option_key opt_key) { if (opt == NULL) return &PL_sv_undef; if (ConfigOptionFloat* optv = dynamic_cast(opt)) { return newSVnv(optv->value); + } else if (ConfigOptionPercent* optv = dynamic_cast(opt)) { + return newSVnv(optv->value); } else if (ConfigOptionFloats* optv = dynamic_cast(opt)) { AV* av = newAV(); av_fill(av, optv->values.size()-1); @@ -257,6 +259,8 @@ DynamicConfig::option(const t_config_option_key opt_key, bool create) { opt = new ConfigOptionString (); } else if (optdef->type == coStrings) { opt = new ConfigOptionStrings (); + } else if (optdef->type == coPercent) { + opt = new ConfigOptionPercent (); } else if (optdef->type == coFloatOrPercent) { opt = new ConfigOptionFloatOrPercent (); } else if (optdef->type == coPoint) { diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index 9dcb4983..d5f280f2 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -181,6 +181,30 @@ class ConfigOptionStrings : public ConfigOption, public ConfigOptionVectorvalue / 100; + }; + + std::string serialize() const { + std::ostringstream ss; + ss << this->value; + std::string s(ss.str()); + s += "%"; + return s; + }; + + void deserialize(std::string str) { + // don't try to parse the trailing % since it's optional + sscanf(str.c_str(), "%lf", &this->value); + }; +}; + class ConfigOptionFloatOrPercent : public ConfigOption { public: @@ -360,6 +384,7 @@ enum ConfigOptionType { coInts, coString, coStrings, + coPercent, coFloatOrPercent, coPoint, coPoints, diff --git a/xs/src/PrintConfig.hpp b/xs/src/PrintConfig.hpp index fe0c6ce8..b9fce0e6 100644 --- a/xs/src/PrintConfig.hpp +++ b/xs/src/PrintConfig.hpp @@ -241,11 +241,12 @@ class PrintConfigDef Options["fill_angle"].cli = "fill-angle=i"; Options["fill_angle"].max = 359; - Options["fill_density"].type = coFloat; + Options["fill_density"].type = coPercent; Options["fill_density"].label = "Fill density"; Options["fill_density"].category = "Infill"; - Options["fill_density"].tooltip = "Density of internal infill, expressed in the range 0 - 1."; - Options["fill_density"].cli = "fill-density=f"; + Options["fill_density"].tooltip = "Density of internal infill, expressed in the range 0% - 100%."; + Options["fill_density"].sidetext = "%"; + Options["fill_density"].cli = "fill-density=s"; Options["fill_pattern"].type = coEnum; Options["fill_pattern"].label = "Fill pattern"; @@ -962,7 +963,7 @@ class PrintRegionConfig : public virtual StaticConfig ConfigOptionInt bottom_solid_layers; ConfigOptionBool extra_perimeters; ConfigOptionInt fill_angle; - ConfigOptionFloat fill_density; + ConfigOptionPercent fill_density; ConfigOptionEnum fill_pattern; ConfigOptionInt infill_extruder; ConfigOptionFloatOrPercent infill_extrusion_width; @@ -984,7 +985,7 @@ class PrintRegionConfig : public virtual StaticConfig this->bottom_solid_layers.value = 3; this->extra_perimeters.value = true; this->fill_angle.value = 45; - this->fill_density.value = 0.4; + this->fill_density.value = 40; this->fill_pattern.value = ipHoneycomb; this->infill_extruder.value = 1; this->infill_extrusion_width.value = 0; diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 1e59eb00..7b611b39 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -131,6 +131,8 @@ print_config_def() const char* opt_type; if (optdef->type == coFloat || optdef->type == coFloats || optdef->type == coFloatOrPercent) { opt_type = "f"; + } else if (optdef->type == coPercent) { + opt_type = "percent"; } else if (optdef->type == coInt || optdef->type == coInts) { opt_type = "i"; } else if (optdef->type == coString) {