diff --git a/MANIFEST b/MANIFEST index f006c50ae..06f04a966 100644 --- a/MANIFEST +++ b/MANIFEST @@ -41,6 +41,7 @@ lib/Slic3r/Point.pm lib/Slic3r/Polygon.pm lib/Slic3r/Polyline.pm lib/Slic3r/Print.pm +lib/Slic3r/Print/Material.pm lib/Slic3r/Print/Object.pm lib/Slic3r/Surface.pm lib/Slic3r/SVG.pm diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index fbeae4000..700572b47 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -50,6 +50,7 @@ use Slic3r::Point; use Slic3r::Polygon; use Slic3r::Polyline; use Slic3r::Print; +use Slic3r::Print::Material; use Slic3r::Print::Object; use Slic3r::Surface; use Slic3r::TriangleMesh; @@ -64,8 +65,7 @@ use constant SMALL_PERIMETER_LENGTH => (6.5 / SCALING_FACTOR) * 2 * PI; # process. They should belong to the Print object, but we are keeping # them here because it makes accessing them slightly faster. our $Config; -our $extruders; -our ($flow, $first_layer_flow, $perimeter_flow, $infill_flow, $support_material_flow); +our $flow; sub parallelize { my %params = @_; diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index 4b7b6b19a..3b77a3497 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -9,7 +9,9 @@ use constant OPTIONS => [qw( retract_length retract_lift retract_speed retract_restart_extra retract_before_travel retract_length_toolchange retract_restart_extra_toolchange )]; -has $_ => (is => 'ro', required => 1) for @{&OPTIONS}; + +has 'id' => (is => 'rw', required => 1); +has $_ => (is => 'ro', required => 1) for @{&OPTIONS}; has 'retracted' => (is => 'rw', default => sub {0} ); has 'e_per_mm3' => (is => 'lazy'); diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 4f29fa0b9..f465a6400 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -5,13 +5,14 @@ use List::Util qw(first); use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(scale unscale scaled_epsilon points_coincide PI X Y); +has 'multiple_extruders' => (is => 'ro', default => sub {0} ); has 'layer' => (is => 'rw'); has 'shift_x' => (is => 'rw', default => sub {0} ); has 'shift_y' => (is => 'rw', default => sub {0} ); has 'z' => (is => 'rw', default => sub {0} ); has 'speed' => (is => 'rw'); -has 'extruder_idx' => (is => 'rw'); +has 'extruder' => (is => 'rw'); has 'extrusion_distance' => (is => 'rw', default => sub {0} ); has 'elapsed_time' => (is => 'rw', default => sub {0} ); # seconds has 'total_extrusion_length' => (is => 'rw', default => sub {0} ); @@ -49,11 +50,6 @@ my %role_speeds = ( &EXTR_ROLE_SUPPORTMATERIAL => 'perimeter', ); -sub extruder { - my $self = shift; - return $Slic3r::extruders->[$self->extruder_idx]; -} - sub change_layer { my $self = shift; my ($layer) = @_; @@ -374,26 +370,26 @@ sub _Gx { return "$gcode\n"; } -sub set_tool { +sub set_extruder { my $self = shift; - my ($tool) = @_; + my ($extruder) = @_; - # return nothing if this tool was already selected - return "" if (defined $self->extruder_idx) && ($self->extruder_idx == $tool); + # return nothing if this extruder was already selected + return "" if (defined $self->extruder) && ($self->extruder->id == $extruder); # if we are running a single-extruder setup, just set the extruder and return nothing - if (@{$Slic3r::extruders} == 1) { - $self->extruder_idx($tool); + if (!$self->multiple_extruders) { + $self->extruder($extruder); return ""; } - # trigger retraction on the current tool (if any) + # trigger retraction on the current extruder (if any) my $gcode = ""; - $gcode .= $self->retract(toolchange => 1) if defined $self->extruder_idx; + $gcode .= $self->retract(toolchange => 1) if defined $self->extruder; - # set the new tool - $self->extruder_idx($tool); - $gcode .= sprintf "T%d%s\n", $tool, ($Slic3r::Config->gcode_comments ? ' ; change tool' : ''); + # set the new extruder + $self->extruder($extruder); + $gcode .= sprintf "T%d%s\n", $extruder, ($Slic3r::Config->gcode_comments ? ' ; change extruder' : ''); $gcode .= $self->reset_e; return $gcode; @@ -426,7 +422,7 @@ sub set_temperature { : ('M104', 'set temperature'); my $gcode = sprintf "$code %s%d %s; $comment\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature, - (defined $tool && $tool != $self->extruder_idx) ? "T$tool " : ""; + (defined $tool && $tool != $self->extruder->id) ? "T$tool " : ""; $gcode .= "M116 ; wait for temperature to be reached\n" if $Slic3r::Config->gcode_flavor eq 'teacup' && $wait; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d5bb34e3b..e68b72778 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -601,7 +601,6 @@ sub export_gcode2 { } $message .= "."; $params{on_completed}->($message); - $print->cleanup; }; $params{catch_error}->(); } diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index e99b44ba9..869cf9329 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -4,15 +4,14 @@ use Moo; use Slic3r::Geometry::Clipper qw(union_ex); has 'id' => (is => 'rw', required => 1); # sequential number of layer, 0-based +has 'object' => (is => 'ro', weak_ref => 1, required => 1); has 'materials' => (is => 'ro', default => sub { [] }); has 'slicing_errors' => (is => 'rw'); has 'slice_z' => (is => 'lazy'); has 'print_z' => (is => 'lazy'); has 'height' => (is => 'lazy'); -has 'flow' => (is => 'lazy'); -has 'perimeter_flow' => (is => 'lazy'); -has 'infill_flow' => (is => 'lazy'); +has 'flow' => (is => 'ro', default => sub { $Slic3r::flow }); # collection of expolygons generated by slicing the original geometry; # also known as 'islands' (all materials are merged here) @@ -43,34 +42,14 @@ sub _build_height { return $self->id == 0 ? $Slic3r::Config->get_value('first_layer_height') : $Slic3r::Config->layer_height; } -sub _build_flow { - my $self = shift; - return $self->id == 0 && $Slic3r::first_layer_flow - ? $Slic3r::first_layer_flow - : $Slic3r::flow; -} - -sub _build_perimeter_flow { - my $self = shift; - return $self->id == 0 && $Slic3r::first_layer_flow - ? $Slic3r::first_layer_flow - : $Slic3r::perimeter_flow; -} - -sub _build_infill_flow { - my $self = shift; - return $self->id == 0 && $Slic3r::first_layer_flow - ? $Slic3r::first_layer_flow - : $Slic3r::infill_flow; -} - sub material { my $self = shift; my ($material_idx) = @_; if (!defined $self->materials->[$material_idx]) { $self->materials->[$material_idx] = Slic3r::Layer::Material->new( - layer => $self, + layer => $self, + material => $self->object->print->materials->[$material_idx], ); } return $self->materials->[$material_idx]; diff --git a/lib/Slic3r/Layer/Material.pm b/lib/Slic3r/Layer/Material.pm index 389c5618b..798cf4c85 100644 --- a/lib/Slic3r/Layer/Material.pm +++ b/lib/Slic3r/Layer/Material.pm @@ -11,8 +11,11 @@ has 'layer' => ( is => 'ro', weak_ref => 1, required => 1, - handles => [qw(id slice_z print_z height flow perimeter_flow infill_flow)], + handles => [qw(id slice_z print_z height flow)], ); +has 'material' => (is => 'ro', required => 1); +has 'perimeter_flow' => (is => 'lazy'); +has 'infill_flow' => (is => 'lazy'); # collection of spare segments generated by slicing the original geometry; # these need to be merged in continuos (closed) polylines @@ -44,6 +47,20 @@ has 'perimeters' => (is => 'rw', default => sub { [] }); # ordered collection of extrusion paths to fill surfaces has 'fills' => (is => 'rw', default => sub { [] }); +sub _build_perimeter_flow { + my $self = shift; + return $self->id == 0 + ? $self->material->first_layer_flows->{perimeter} + : $self->material->flows->{perimeter} +} + +sub _build_infill_flow { + my $self = shift; + return $self->id == 0 + ? $self->material->first_layer_flows->{infill} + : $self->material->flows->{infill} +} + # build polylines from lines sub make_surfaces { my $self = shift; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 8304357d2..75877ba55 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -14,9 +14,11 @@ has 'config' => (is => 'rw', default => sub { Slic3r::Config->ne has 'extra_variables' => (is => 'rw', default => sub {{}}); has 'objects' => (is => 'rw', default => sub {[]}); has 'total_extrusion_length' => (is => 'rw'); -has 'processing_time' => (is => 'rw', required => 0); - -has 'materials_count' => (is => 'rw', default => sub {1}); +has 'processing_time' => (is => 'rw'); +has 'extruders' => (is => 'rw', default => sub {[]}); +has 'materials' => (is => 'rw', default => sub {[]}); +has 'support_material_flow' => (is => 'rw'); +has 'first_layer_support_material_flow' => (is => 'rw'); # ordered collection of extrusion paths to build skirt loops has 'skirt' => ( @@ -53,32 +55,6 @@ sub _trigger_config { $self->config->set_ifndef('solid_infill_speed', $self->config->infill_speed); $self->config->set_ifndef('top_solid_infill_speed', $self->config->solid_infill_speed); - # initialize extruder(s) - $Slic3r::extruders = []; - for my $t (0, map $_-1, map $self->config->get($_), qw(perimeter_extruder infill_extruder support_material_extruder)) { - $Slic3r::extruders->[$t] ||= Slic3r::Extruder->new( - map { $_ => $self->config->get($_)->[$t] // $self->config->get($_)->[0] } #/ - @{&Slic3r::Extruder::OPTIONS} - ); - } - - # calculate flow - $Slic3r::flow = $Slic3r::extruders->[0]->make_flow(width => $self->config->extrusion_width); - if ($self->config->first_layer_extrusion_width) { - $Slic3r::first_layer_flow = $Slic3r::extruders->[0]->make_flow( - layer_height => $self->config->get_value('first_layer_height'), - width => $self->config->first_layer_extrusion_width, - ); - } - for (qw(perimeter infill support_material)) { - no strict 'refs'; - ${"Slic3r::${_}_flow"} = $Slic3r::extruders->[ $self->config->get("${_}_extruder")-1 ] - ->make_flow(width => $self->config->get("${_}_extrusion_width") || $self->config->extrusion_width); - } - - Slic3r::debugf "Default flow width = %s (spacing = %s)\n", - $Slic3r::flow->width, $Slic3r::flow->spacing; - # G-code flavors $self->config->set('extrusion_axis', 'A') if $self->config->gcode_flavor eq 'mach3'; $self->config->set('extrusion_axis', '') if $self->config->gcode_flavor eq 'no-extrusion'; @@ -88,15 +64,24 @@ sub add_model { my $self = shift; my ($model) = @_; - # update materials count - $self->materials_count(max($self->materials_count, scalar keys %{$model->materials})); + # append/merge materials and preserve a mapping between the original material ID + # and our numeric material index + my %materials = (); + { + my @material_ids = sort keys %{$model->materials}; + @material_ids = (0) if !@material_ids; + for (my $i = $self->materials_count; $i < @material_ids; $i++) { + push @{$self->materials}, Slic3r::Print::Material->new; + $materials{$material_ids[$i]} = $#{$self->materials}; + } + } foreach my $object (@{ $model->objects }) { my @meshes = (); # by material_id foreach my $volume (@{$object->volumes}) { # should the object contain multiple volumes of the same material, merge them - my $material_id = $volume->material_id // 0; #/ + my $material_id = defined $volume->material_id ? $materials{$volume->material_id} : 0; my $mesh = $volume->mesh->clone; $meshes[$material_id] = $meshes[$material_id] ? Slic3r::TriangleMesh->merge($meshes[$material_id], $mesh) @@ -180,6 +165,62 @@ sub validate { } } +sub init_extruders { + my $self = shift; + + # map materials to extruders (ghetto mapping for now) + my %extruder_mapping = map { $_ => $_ } 0..$#{$self->materials}; + + # initialize all extruder(s) we need + my @used_extruders = ( + 0, + (map $self->config->get("${_}_extruder")-1, qw(perimeter infill support_material)), + (values %extruder_mapping), + ); + for my $extruder_id (keys %{{ map {$_ => 1} @used_extruders }}) { + $self->extruders->[$extruder_id] = Slic3r::Extruder->new( + id => $extruder_id, + map { $_ => $self->config->get($_)->[$extruder_id] // $self->config->get($_)->[0] } #/ + @{&Slic3r::Extruder::OPTIONS} + ); + } + + # calculate materials' flows + $Slic3r::flow = $self->extruders->[0]->make_flow(width => $self->config->extrusion_width); + for my $material_id (0 .. $#{$self->materials}) { + my $material = $self->materials->[$material_id]; + + # per-role extruders and flows + for (qw(perimeter infill)) { + $material->extruders->{$_} = ($self->materials_count > 1) + ? $self->extruders->[$extruder_mapping{$material_id}] + : $self->extruders->[$self->config->get("${_}_extruder")-1]; + $material->flows->{$_} = $material->extruders->{$_}->make_flow( + width => $self->config->get("${_}_extrusion_width") || $self->config->extrusion_width, + ); + $material->first_layer_flows->{$_} = $material->extruders->{$_}->make_flow( + layer_height => $self->config->get_value('first_layer_height'), + width => $self->config->first_layer_extrusion_width, + ); + } + } + + # calculate support material flow + if ($self->config->support_material) { + my $extruder = $self->extruders->[$self->config->support_material_extruder-1]; + $self->support_material_flow($extruder->make_flow( + width => $self->config->support_material_extrusion_width || $self->config->extrusion_width, + )); + $self->first_layer_support_material_flow($extruder->make_flow( + layer_height => $self->config->get_value('first_layer_height'), + width => $self->config->first_layer_extrusion_width, + )); + } + + Slic3r::debugf "Default flow width = %s (spacing = %s)\n", + $Slic3r::flow->width, $Slic3r::flow->spacing; +} + sub object_copies { my $self = shift; my @oc = (); @@ -189,14 +230,6 @@ sub object_copies { return @oc; } -sub cleanup { - my $self = shift; - $_->cleanup for @{$self->objects}; - @{$self->skirt} = (); - $self->total_extrusion_length(0); - $self->processing_time(0); -} - sub layer_count { my $self = shift; my $count = 0; @@ -206,6 +239,11 @@ sub layer_count { return $count; } +sub materials_count { + my $self = shift; + return scalar @{$self->materials}; +} + sub duplicate { my $self = shift; @@ -275,12 +313,12 @@ sub export_gcode { my $self = shift; my %params = @_; + $self->init_extruders; my $status_cb = $params{status_cb} || sub {}; my $t0 = [gettimeofday]; # skein the STL into layers # each layer has surfaces with holes - $status_cb->(5, "Processing input file"); $status_cb->(10, "Processing triangulated mesh"); $_->slice(keep_meshes => $params{keep_meshes}) for @{$self->objects}; @@ -587,26 +625,28 @@ sub write_gcode { print $fh "\n"; # set up our extruder object - my $gcodegen = Slic3r::GCode->new; + my $gcodegen = Slic3r::GCode->new( + multiple_extruders => (@{$self->extruders} > 1), + ); my $min_print_speed = 60 * $Slic3r::Config->min_print_speed; my $dec = $gcodegen->dec; - print $fh $gcodegen->set_tool(0); + print $fh $gcodegen->set_extruder($self->extruders->[0]); print $fh $gcodegen->set_fan(0, 1) if $Slic3r::Config->cooling && $Slic3r::Config->disable_fan_first_layers; # write start commands to file printf $fh $gcodegen->set_bed_temperature($Slic3r::Config->first_layer_bed_temperature, 1), if $Slic3r::Config->first_layer_bed_temperature && $Slic3r::Config->start_gcode !~ /M190/i; my $print_first_layer_temperature = sub { - for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) { - printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 0, $t) - if $Slic3r::extruders->[$t]->first_layer_temperature; + for my $t (grep $self->extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) { + printf $fh $gcodegen->set_temperature($self->extruders->[$t]->first_layer_temperature, 0, $t) + if $self->extruders->[$t]->first_layer_temperature; } }; $print_first_layer_temperature->(); printf $fh "%s\n", $Slic3r::Config->replace_options($Slic3r::Config->start_gcode); - for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) { - printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 1, $t) - if $Slic3r::extruders->[$t]->first_layer_temperature && $Slic3r::Config->start_gcode !~ /M109/i; + for my $t (grep $self->extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) { + printf $fh $gcodegen->set_temperature($self->extruders->[$t]->first_layer_temperature, 1, $t) + if $self->extruders->[$t]->first_layer_temperature && $Slic3r::Config->start_gcode !~ /M109/i; } print $fh "G90 ; use absolute coordinates\n"; print $fh "G21 ; set units to millimeters\n"; @@ -636,9 +676,9 @@ sub write_gcode { my $gcode = ""; if ($layer_id == 1) { - for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->temperature}) { - $gcode .= $gcodegen->set_temperature($Slic3r::extruders->[$t]->temperature, 0, $t) - if $Slic3r::extruders->[$t]->temperature && $Slic3r::extruders->[$t]->temperature != $Slic3r::extruders->[$t]->first_layer_temperature; + for my $t (grep $self->extruders->[$_], 0 .. $#{$Slic3r::Config->temperature}) { + $gcode .= $gcodegen->set_temperature($self->extruders->[$t]->temperature, 0, $t) + if $self->extruders->[$t]->temperature && $self->extruders->[$t]->temperature != $self->extruders->[$t]->first_layer_temperature; } $gcode .= $gcodegen->set_bed_temperature($Slic3r::Config->bed_temperature) if $Slic3r::Config->first_layer_bed_temperature && $Slic3r::Config->bed_temperature != $Slic3r::Config->first_layer_bed_temperature; @@ -662,7 +702,7 @@ sub write_gcode { # extrude brim if ($layer_id == 0 && !$brim_done) { - $gcode .= $gcodegen->set_tool($Slic3r::Config->support_material_extruder-1); + $gcode .= $gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]); $gcodegen->shift_x($shift[X]); $gcodegen->shift_y($shift[Y]); $gcode .= $gcodegen->extrude_loop($_, 'brim') for @{$self->brim}; @@ -682,13 +722,14 @@ sub write_gcode { foreach my $material_id (0 .. ($self->materials_count-1)) { my $layerm = $layer->materials->[$material_id]; + my $material = $self->materials->[$material_id]; # extrude perimeters - $gcode .= $gcodegen->set_tool($Slic3r::Config->perimeter_extruder-1); + $gcode .= $gcodegen->set_extruder($material->extruders->{perimeter}); $gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $layerm->perimeters }; # extrude fills - $gcode .= $gcodegen->set_tool($Slic3r::Config->infill_extruder-1); + $gcode .= $gcodegen->set_extruder($material->extruders->{infill}); $gcode .= $gcodegen->set_acceleration($Slic3r::Config->infill_acceleration); for my $fill (@{ $layerm->fills }) { if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { @@ -702,7 +743,7 @@ sub write_gcode { # extrude support material if ($layer->support_fills) { - $gcode .= $gcodegen->set_tool($Slic3r::Config->support_material_extruder-1); + $gcode .= $gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]); $gcode .= $gcodegen->extrude_path($_, 'support material') for $layer->support_fills->shortest_path($gcodegen->last_pos); } @@ -807,7 +848,7 @@ sub write_gcode { sub total_extrusion_volume { my $self = shift; - return $self->total_extrusion_length * ($Slic3r::extruders->[0]->filament_diameter**2) * PI/4 / 1000; + return $self->total_extrusion_length * ($self->extruders->[0]->filament_diameter**2) * PI/4 / 1000; } # this method will return the supplied input file path after expanding its diff --git a/lib/Slic3r/Print/Material.pm b/lib/Slic3r/Print/Material.pm new file mode 100644 index 000000000..45fe0fdf7 --- /dev/null +++ b/lib/Slic3r/Print/Material.pm @@ -0,0 +1,8 @@ +package Slic3r::Print::Material; +use Moo; + +has 'extruders' => (is => 'rw', default => sub { {} }); # by role +has 'flows' => (is => 'rw', default => sub { {} }); # by role +has 'first_layer_flows' => (is => 'rw', default => sub { {} }); # by role + +1; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index a1ebbc3db..6ae7eec78 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -23,11 +23,8 @@ sub layer { my ($layer_id) = @_; # extend our print by creating all necessary layers - - if ($self->layer_count < $layer_id + 1) { - for (my $i = $self->layer_count; $i <= $layer_id; $i++) { - push @{ $self->layers }, Slic3r::Layer->new(id => $i); - } + for (my $i = $self->layer_count; $i <= $layer_id; $i++) { + push @{ $self->layers }, Slic3r::Layer->new(id => $i, object => $self); } return $self->layers->[$layer_id]; @@ -172,11 +169,6 @@ sub slice { if !@{$self->layers}; } -sub cleanup { - my $self = shift; - @{$self->layers} = (); -} - sub make_perimeters { my $self = shift; @@ -510,9 +502,10 @@ sub combine_infill { sub generate_support_material { my $self = shift; + my $flow = $self->print->support_material_flow; my $threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive my $overhang_width = $threshold_rad == 0 ? undef : scale $Slic3r::Config->layer_height * ((cos $threshold_rad) / (sin $threshold_rad)); - my $distance_from_object = 1.5 * scale $Slic3r::support_material_flow->width; + my $distance_from_object = 1.5 * scale $flow->width; # determine support regions in each layer (for upper layers) Slic3r::debugf "Detecting regions\n"; @@ -536,7 +529,7 @@ sub generate_support_material { [ map @$_, @current_support_regions ], [ map @$_, map $_->offset_ex($distance_from_object), @{$layer->slices} ], ); - $_->simplify(scale $Slic3r::support_material_flow->spacing * 2) for @{$layers{$i}}; + $_->simplify(scale $flow->spacing * 2) for @{$layers{$i}}; # step 2: get layer overhangs and put them into queue for adding support inside lower layers # we need an angle threshold for this @@ -558,7 +551,7 @@ sub generate_support_material { my $support_patterns = []; # in case we want cross-hatching { # 0.5 makes sure the paths don't get clipped externally when applying them to layers - my @support_material_areas = map $_->offset_ex(- 0.5 * scale $Slic3r::support_material_flow->width), + my @support_material_areas = map $_->offset_ex(- 0.5 * scale $flow->width), @{union_ex([ map $_->contour, map @$_, values %layers ])}; my $fill = Slic3r::Fill->new(print => $self->print); @@ -569,8 +562,8 @@ sub generate_support_material { foreach my $expolygon (@support_material_areas) { my @paths = $filler->fill_surface( Slic3r::Surface->new(expolygon => $expolygon), - density => $Slic3r::support_material_flow->spacing / $Slic3r::Config->support_material_spacing, - flow_spacing => $Slic3r::support_material_flow->spacing, + density => $flow->spacing / $Slic3r::Config->support_material_spacing, + flow_spacing => $flow->spacing, ); my $params = shift @paths; @@ -603,6 +596,11 @@ sub generate_support_material { foreach my $expolygon (@$expolygons) { push @paths, map $_->pack, + map { + $_->flow_spacing($self->print->first_layer_support_material_flow->spacing) + if $layer_id == 0; + $_; + } map $_->clip_with_expolygon($expolygon), map $_->clip_with_polygon($expolygon->bounding_box_polygon), @{$support_patterns->[ $layer_id % @$support_patterns ]};