mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Avoid closures, move planning code to _plan() and layer G-code generation to Slic3r::GCode::Layer
This commit is contained in:
		
							parent
							
								
									08a0bbd7f0
								
							
						
					
					
						commit
						f599ed00c6
					
				
					 5 changed files with 246 additions and 210 deletions
				
			
		
							
								
								
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							|  | @ -25,6 +25,7 @@ lib/Slic3r/Format/OBJ.pm | |||
| lib/Slic3r/Format/STL.pm | ||||
| lib/Slic3r/GCode.pm | ||||
| lib/Slic3r/GCode/CoolingBuffer.pm | ||||
| lib/Slic3r/GCode/Layer.pm | ||||
| lib/Slic3r/GCode/MotionPlanner.pm | ||||
| lib/Slic3r/GCode/Reader.pm | ||||
| lib/Slic3r/GCode/SpiralVase.pm | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ use Slic3r::Format::OBJ; | |||
| use Slic3r::Format::STL; | ||||
| use Slic3r::GCode; | ||||
| use Slic3r::GCode::CoolingBuffer; | ||||
| use Slic3r::GCode::Layer; | ||||
| use Slic3r::GCode::MotionPlanner; | ||||
| use Slic3r::GCode::Reader; | ||||
| use Slic3r::GCode::SpiralVase; | ||||
|  |  | |||
|  | @ -294,34 +294,6 @@ sub travel_to { | |||
|         $self->speed('travel'); | ||||
|         $gcode .= $self->G0($point, undef, 0, $comment || ""); | ||||
|     } else { | ||||
|         my $plan = sub { | ||||
|             my $mp = shift; | ||||
|              | ||||
|             my $gcode = ""; | ||||
|             my @travel = $mp->shortest_path($self->last_pos, $point)->lines; | ||||
|              | ||||
|             # if the path is not contained in a single island we need to retract | ||||
|             my $need_retract = !$Slic3r::Config->only_retract_when_crossing_perimeters; | ||||
|             if (!$need_retract) { | ||||
|                 $need_retract = 1; | ||||
|                 foreach my $slice (@{$self->layer->slices}) { | ||||
|                     # discard the island if at any line is not enclosed in it | ||||
|                     next if first { !$slice->encloses_line($_, scaled_epsilon) } @travel; | ||||
|                     # okay, this island encloses the full travel path | ||||
|                     $need_retract = 0; | ||||
|                     last; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             # do the retract (the travel_to argument is broken) | ||||
|             $gcode .= $self->retract(travel_to => $point) if $need_retract; | ||||
|              | ||||
|             # append the actual path and return | ||||
|             $self->speed('travel'); | ||||
|             $gcode .= join '', map $self->G0($_->[B], undef, 0, $comment || ""), @travel; | ||||
|             return $gcode; | ||||
|         }; | ||||
|          | ||||
|         if ($self->new_object) { | ||||
|             $self->new_object(0); | ||||
|              | ||||
|  | @ -332,16 +304,45 @@ sub travel_to { | |||
|              | ||||
|             # calculate path (external_mp uses G-code coordinates so we temporary need a null shift) | ||||
|             $self->set_shift(0,0); | ||||
|             $gcode .= $plan->($self->external_mp); | ||||
|             $gcode .= $self->_plan($self->external_mp, $point, $comment); | ||||
|             $self->set_shift(@shift); | ||||
|         } else { | ||||
|             $gcode .= $plan->($self->layer_mp); | ||||
|             $gcode .= $self->_plan($self->layer_mp, $point, $comment); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return $gcode; | ||||
| } | ||||
| 
 | ||||
| sub _plan { | ||||
|     my $self = shift; | ||||
|     my ($mp, $point, $comment) = @_; | ||||
|      | ||||
|     my $gcode = ""; | ||||
|     my @travel = $mp->shortest_path($self->last_pos, $point)->lines; | ||||
|      | ||||
|     # if the path is not contained in a single island we need to retract | ||||
|     my $need_retract = !$Slic3r::Config->only_retract_when_crossing_perimeters; | ||||
|     if (!$need_retract) { | ||||
|         $need_retract = 1; | ||||
|         foreach my $slice (@{$self->layer->slices}) { | ||||
|             # discard the island if at any line is not enclosed in it | ||||
|             next if first { !$slice->encloses_line($_, scaled_epsilon) } @travel; | ||||
|             # okay, this island encloses the full travel path | ||||
|             $need_retract = 0; | ||||
|             last; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     # do the retract (the travel_to argument is broken) | ||||
|     $gcode .= $self->retract(travel_to => $point) if $need_retract; | ||||
|      | ||||
|     # append the actual path and return | ||||
|     $self->speed('travel'); | ||||
|     $gcode .= join '', map $self->G0($_->[B], undef, 0, $comment || ""), @travel; | ||||
|     return $gcode; | ||||
| } | ||||
| 
 | ||||
| sub retract { | ||||
|     my $self = shift; | ||||
|     my %params = @_; | ||||
|  |  | |||
							
								
								
									
										202
									
								
								lib/Slic3r/GCode/Layer.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								lib/Slic3r/GCode/Layer.pm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,202 @@ | |||
| package Slic3r::GCode::Layer; | ||||
| use Moo; | ||||
| 
 | ||||
| use Slic3r::Geometry qw(X Y unscale); | ||||
| 
 | ||||
| has 'print'                         => (is => 'ro', required => 1, handles => [qw(extruders)]); | ||||
| has 'gcodegen'                      => (is => 'ro', required => 1); | ||||
| has 'shift'                         => (is => 'ro', required => 1); | ||||
| 
 | ||||
| has 'spiralvase'                    => (is => 'lazy'); | ||||
| has 'skirt_done'                    => (is => 'rw', default => sub {0});  # count of skirt layers done | ||||
| has 'brim_done'                     => (is => 'rw'); | ||||
| has 'second_layer_things_done'      => (is => 'rw'); | ||||
| has '_last_obj_copy'                => (is => 'rw'); | ||||
| 
 | ||||
| sub _build_spiralvase { | ||||
|     my $self = shift; | ||||
|      | ||||
|     return $Slic3r::Config->spiral_vase | ||||
|         ? Slic3r::GCode::SpiralVase->new | ||||
|         : undef; | ||||
| } | ||||
| 
 | ||||
| sub process_layer { | ||||
|     my $self = shift; | ||||
|     my ($layer, $object_copies) = @_; | ||||
|     my $gcode = ""; | ||||
|      | ||||
|     if (!$self->second_layer_things_done && $layer->id == 1) { | ||||
|         for my $t (grep $self->extruders->[$_], 0 .. $#{$Slic3r::Config->temperature}) { | ||||
|             $gcode .= $self->gcodegen->set_temperature($self->extruders->[$t]->temperature, 0, $t) | ||||
|                 if $self->print->extruders->[$t]->temperature && $self->extruders->[$t]->temperature != $self->extruders->[$t]->first_layer_temperature; | ||||
|         } | ||||
|         $gcode .= $self->gcodegen->set_bed_temperature($Slic3r::Config->bed_temperature) | ||||
|             if $Slic3r::Config->bed_temperature && $Slic3r::Config->bed_temperature != $Slic3r::Config->first_layer_bed_temperature; | ||||
|         $self->second_layer_things_done(1); | ||||
|     } | ||||
|      | ||||
|     # set new layer, but don't move Z as support material contact areas may need an intermediate one | ||||
|     $gcode .= $self->gcodegen->change_layer($layer); | ||||
|      | ||||
|     # prepare callback to call as soon as a Z command is generated | ||||
|     $self->gcodegen->move_z_callback(sub { | ||||
|         $self->gcodegen->move_z_callback(undef);  # circular ref or not? | ||||
|         return "" if !$Slic3r::Config->layer_gcode; | ||||
|         return $Slic3r::Config->replace_options($Slic3r::Config->layer_gcode) . "\n"; | ||||
|     }); | ||||
|      | ||||
|     # extrude skirt | ||||
|     if ($self->skirt_done < $Slic3r::Config->skirt_height) { | ||||
|         $self->gcodegen->set_shift(@{$self->shift}); | ||||
|         $gcode .= $self->gcodegen->set_extruder($self->extruders->[0]);  # move_z requires extruder | ||||
|         $gcode .= $self->gcodegen->move_z($self->gcodegen->layer->print_z); | ||||
|         # skip skirt if we have a large brim | ||||
|         if ($layer->id < $Slic3r::Config->skirt_height) { | ||||
|             # distribute skirt loops across all extruders | ||||
|             for my $i (0 .. $#{$self->print->skirt}) { | ||||
|                 # when printing layers > 0 ignore 'min_skirt_length' and  | ||||
|                 # just use the 'skirts' setting; also just use the current extruder | ||||
|                 last if ($layer->id > 0) && ($i >= $Slic3r::Config->skirts); | ||||
|                 $gcode .= $self->gcodegen->set_extruder($self->extruders->[ ($i/@{$self->extruders}) % @{$self->extruders} ]) | ||||
|                     if $layer->id == 0; | ||||
|                 $gcode .= $self->gcodegen->extrude_loop($self->print->skirt->[$i], 'skirt'); | ||||
|             } | ||||
|         } | ||||
|         $self->skirt_done($self->skirt_done + 1); | ||||
|         $self->gcodegen->straight_once(1); | ||||
|     } | ||||
|      | ||||
|     # extrude brim | ||||
|     if (!$self->brim_done) { | ||||
|         $gcode .= $self->gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]);  # move_z requires extruder | ||||
|         $gcode .= $self->gcodegen->move_z($self->gcodegen->layer->print_z); | ||||
|         $self->gcodegen->set_shift(@{$self->shift}); | ||||
|         $gcode .= $self->gcodegen->extrude_loop($_, 'brim') for @{$self->print->brim}; | ||||
|         $self->brim_done(1); | ||||
|         $self->gcodegen->straight_once(1); | ||||
|     } | ||||
|      | ||||
|     for my $copy (@$object_copies) { | ||||
|         $self->gcodegen->new_object(1) if ($self->_last_obj_copy // '') ne "$copy"; | ||||
|         $self->_last_obj_copy("$copy"); | ||||
|          | ||||
|         $self->gcodegen->set_shift(map $self->shift->[$_] + unscale $copy->[$_], X,Y); | ||||
|          | ||||
|         # extrude support material before other things because it might use a lower Z | ||||
|         # and also because we avoid travelling on other things when printing it | ||||
|         if ($self->print->has_support_material) { | ||||
|             $gcode .= $self->gcodegen->move_z($layer->support_material_contact_z) | ||||
|                 if ($layer->support_contact_fills && @{ $layer->support_contact_fills->paths }); | ||||
|             $gcode .= $self->gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]); | ||||
|             if ($layer->support_contact_fills) { | ||||
|                 $gcode .= $self->gcodegen->extrude_path($_, 'support material contact area')  | ||||
|                     for $layer->support_contact_fills->chained_path($self->gcodegen->last_pos);  | ||||
|             } | ||||
|              | ||||
|             $gcode .= $self->gcodegen->move_z($layer->print_z); | ||||
|             if ($layer->support_fills) { | ||||
|                 $gcode .= $self->gcodegen->extrude_path($_, 'support material')  | ||||
|                     for $layer->support_fills->chained_path($self->gcodegen->last_pos); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         # set actual Z - this will force a retraction | ||||
|         $gcode .= $self->gcodegen->move_z($layer->print_z); | ||||
|          | ||||
|         # tweak region ordering to save toolchanges | ||||
|         my @region_ids = 0 .. ($self->print->regions_count-1); | ||||
|         if ($self->gcodegen->multiple_extruders) { | ||||
|             my $last_extruder = $self->gcodegen->extruder; | ||||
|             my $best_region_id = first { $self->print->regions->[$_]->extruders->{perimeter} eq $last_extruder } @region_ids; | ||||
|             @region_ids = ($best_region_id, grep $_ != $best_region_id, @region_ids) if $best_region_id; | ||||
|         } | ||||
|          | ||||
|         foreach my $region_id (@region_ids) { | ||||
|             my $layerm = $layer->regions->[$region_id]; | ||||
|             my $region = $self->print->regions->[$region_id]; | ||||
|              | ||||
|             my @islands = (); | ||||
|             if ($Slic3r::Config->avoid_crossing_perimeters) { | ||||
|                 push @islands, map +{ perimeters => [], fills => [] }, @{$layer->slices}; | ||||
|                 PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) { | ||||
|                     my $p = $perimeter->unpack; | ||||
|                     for my $i (0 .. $#{$layer->slices}-1) { | ||||
|                         if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) { | ||||
|                             push @{ $islands[$i]{perimeters} }, $p; | ||||
|                             next PERIMETER; | ||||
|                         } | ||||
|                     } | ||||
|                     push @{ $islands[-1]{perimeters} }, $p; # optimization | ||||
|                 } | ||||
|                 FILL: foreach my $fill (@{$layerm->fills}) { | ||||
|                     my $f = $fill->unpack; | ||||
|                     for my $i (0 .. $#{$layer->slices}-1) { | ||||
|                         if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) { | ||||
|                             push @{ $islands[$i]{fills} }, $f; | ||||
|                             next FILL; | ||||
|                         } | ||||
|                     } | ||||
|                     push @{ $islands[-1]{fills} }, $f; # optimization | ||||
|                 } | ||||
|             } else { | ||||
|                 push @islands, { | ||||
|                     perimeters  => $layerm->perimeters, | ||||
|                     fills       => $layerm->fills, | ||||
|                 }; | ||||
|             } | ||||
|              | ||||
|             foreach my $island (@islands) { | ||||
|                 # give priority to infill if we were already using its extruder and it wouldn't | ||||
|                 # be good for perimeters | ||||
|                 if ($Slic3r::Config->infill_first | ||||
|                     || ($self->gcodegen->multiple_extruders && $region->extruders->{infill} eq $self->gcodegen->extruder) && $region->extruders->{infill} ne $region->extruders->{perimeter}) { | ||||
|                     $gcode .= $self->_extrude_infill($island, $region); | ||||
|                     $gcode .= $self->_extrude_perimeters($island, $region); | ||||
|                 } else { | ||||
|                     $gcode .= $self->_extrude_perimeters($island, $region); | ||||
|                     $gcode .= $self->_extrude_infill($island, $region); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     # apply spiral vase post-processing if this layer contains suitable geometry | ||||
|     $gcode = $self->spiralvase->process_layer($gcode, $layer) | ||||
|         if defined $self->spiralvase | ||||
|         && ($layer->id > 0 || $Slic3r::Config->brim_width == 0) | ||||
|         && ($layer->id >= $Slic3r::Config->skirt_height) | ||||
|         && ($layer->id >= $Slic3r::Config->bottom_solid_layers); | ||||
|      | ||||
|     return $gcode; | ||||
| } | ||||
| 
 | ||||
| sub _extrude_perimeters { | ||||
|     my $self = shift; | ||||
|     my ($island, $region) = @_; | ||||
|      | ||||
|     return "" if !@{ $island->{perimeters} }; | ||||
|     return $self->gcodegen->set_extruder($region->extruders->{perimeter}) | ||||
|         . $self->gcodegen->extrude($_, 'perimeter') for @{ $island->{perimeters} }; | ||||
| } | ||||
| 
 | ||||
| sub _extrude_infill { | ||||
|     my $self = shift; | ||||
|     my ($island, $region) = @_; | ||||
|      | ||||
|     return "" if !@{ $island->{fills} }; | ||||
|      | ||||
|     my $gcode = ""; | ||||
|     $gcode .= $self->gcodegen->set_extruder($region->extruders->{infill}); | ||||
|     for my $fill (@{ $island->{fills} }) { | ||||
|         if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { | ||||
|             $gcode .= $self->gcodegen->extrude($_, 'fill')  | ||||
|                 for $fill->chained_path($self->gcodegen->last_pos); | ||||
|         } else { | ||||
|             $gcode .= $self->gcodegen->extrude($fill, 'fill') ; | ||||
|         } | ||||
|     } | ||||
|     return $gcode; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  | @ -759,183 +759,12 @@ sub write_gcode { | |||
|         )); | ||||
|     } | ||||
|      | ||||
|     # prepare the SpiralVase processor if it's possible | ||||
|     my $spiralvase = $Slic3r::Config->spiral_vase | ||||
|         ? Slic3r::GCode::SpiralVase->new | ||||
|         : undef; | ||||
|      | ||||
|     # prepare the logic to print one layer | ||||
|     my $skirt_done = 0;  # count of skirt layers done | ||||
|     my $brim_done = 0; | ||||
|     my $second_layer_things_done = 0; | ||||
|     my $last_obj_copy = ""; | ||||
|     my $extrude_layer = sub { | ||||
|         my ($layer, $object_copies) = @_; | ||||
|         my $gcode = ""; | ||||
|          | ||||
|         if (!$second_layer_things_done && $layer->id == 1) { | ||||
|             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->bed_temperature && $Slic3r::Config->bed_temperature != $Slic3r::Config->first_layer_bed_temperature; | ||||
|             $second_layer_things_done = 1; | ||||
|         } | ||||
|          | ||||
|         # set new layer, but don't move Z as support material contact areas may need an intermediate one | ||||
|         $gcode .= $gcodegen->change_layer($layer); | ||||
|          | ||||
|         # prepare callback to call as soon as a Z command is generated | ||||
|         $gcodegen->move_z_callback(sub { | ||||
|             $gcodegen->move_z_callback(undef);  # circular ref or not? | ||||
|             return "" if !$Slic3r::Config->layer_gcode; | ||||
|             return $Slic3r::Config->replace_options($Slic3r::Config->layer_gcode) . "\n"; | ||||
|         }); | ||||
|          | ||||
|         # extrude skirt | ||||
|         if ($skirt_done < $Slic3r::Config->skirt_height) { | ||||
|             $gcodegen->set_shift(@shift); | ||||
|             $gcode .= $gcodegen->set_extruder($self->extruders->[0]);  # move_z requires extruder | ||||
|             $gcode .= $gcodegen->move_z($gcodegen->layer->print_z); | ||||
|             # skip skirt if we have a large brim | ||||
|             if ($layer->id < $Slic3r::Config->skirt_height) { | ||||
|                 # distribute skirt loops across all extruders | ||||
|                 for my $i (0 .. $#{$self->skirt}) { | ||||
|                     # when printing layers > 0 ignore 'min_skirt_length' and  | ||||
|                     # just use the 'skirts' setting; also just use the current extruder | ||||
|                     last if ($layer->id > 0) && ($i >= $Slic3r::Config->skirts); | ||||
|                     $gcode .= $gcodegen->set_extruder($self->extruders->[ ($i/@{$self->extruders}) % @{$self->extruders} ]) | ||||
|                         if $layer->id == 0; | ||||
|                     $gcode .= $gcodegen->extrude_loop($self->skirt->[$i], 'skirt'); | ||||
|                 } | ||||
|             } | ||||
|             $skirt_done++; | ||||
|             $gcodegen->straight_once(1); | ||||
|         } | ||||
|          | ||||
|         # extrude brim | ||||
|         if (!$brim_done) { | ||||
|             $gcode .= $gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]);  # move_z requires extruder | ||||
|             $gcode .= $gcodegen->move_z($gcodegen->layer->print_z); | ||||
|             $gcodegen->set_shift(@shift); | ||||
|             $gcode .= $gcodegen->extrude_loop($_, 'brim') for @{$self->brim}; | ||||
|             $brim_done = 1; | ||||
|             $gcodegen->straight_once(1); | ||||
|         } | ||||
|          | ||||
|         for my $copy (@$object_copies) { | ||||
|             $gcodegen->new_object(1) if $last_obj_copy && $last_obj_copy ne "$copy"; | ||||
|             $last_obj_copy = "$copy"; | ||||
|              | ||||
|             $gcodegen->set_shift(map $shift[$_] + unscale $copy->[$_], X,Y); | ||||
|              | ||||
|             # extrude support material before other things because it might use a lower Z | ||||
|             # and also because we avoid travelling on other things when printing it | ||||
|             if ($self->has_support_material) { | ||||
|                 $gcode .= $gcodegen->move_z($layer->support_material_contact_z) | ||||
|                     if ($layer->support_contact_fills && @{ $layer->support_contact_fills->paths }); | ||||
|                 $gcode .= $gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]); | ||||
|                 if ($layer->support_contact_fills) { | ||||
|                     $gcode .= $gcodegen->extrude_path($_, 'support material contact area')  | ||||
|                         for $layer->support_contact_fills->chained_path($gcodegen->last_pos);  | ||||
|                 } | ||||
|                  | ||||
|                 $gcode .= $gcodegen->move_z($layer->print_z); | ||||
|                 if ($layer->support_fills) { | ||||
|                     $gcode .= $gcodegen->extrude_path($_, 'support material')  | ||||
|                         for $layer->support_fills->chained_path($gcodegen->last_pos); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             # set actual Z - this will force a retraction | ||||
|             $gcode .= $gcodegen->move_z($layer->print_z); | ||||
|              | ||||
|             # tweak region ordering to save toolchanges | ||||
|             my @region_ids = 0 .. ($self->regions_count-1); | ||||
|             if ($gcodegen->multiple_extruders) { | ||||
|                 my $last_extruder = $gcodegen->extruder; | ||||
|                 my $best_region_id = first { $self->regions->[$_]->extruders->{perimeter} eq $last_extruder } @region_ids; | ||||
|                 @region_ids = ($best_region_id, grep $_ != $best_region_id, @region_ids) if $best_region_id; | ||||
|             } | ||||
|              | ||||
|             foreach my $region_id (@region_ids) { | ||||
|                 my $layerm = $layer->regions->[$region_id]; | ||||
|                 my $region = $self->regions->[$region_id]; | ||||
|                  | ||||
|                 my @islands = (); | ||||
|                 if ($Slic3r::Config->avoid_crossing_perimeters) { | ||||
|                     push @islands, map +{ perimeters => [], fills => [] }, @{$layer->slices}; | ||||
|                     PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) { | ||||
|                         my $p = $perimeter->unpack; | ||||
|                         for my $i (0 .. $#{$layer->slices}-1) { | ||||
|                             if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) { | ||||
|                                 push @{ $islands[$i]{perimeters} }, $p; | ||||
|                                 next PERIMETER; | ||||
|                             } | ||||
|                         } | ||||
|                         push @{ $islands[-1]{perimeters} }, $p; # optimization | ||||
|                     } | ||||
|                     FILL: foreach my $fill (@{$layerm->fills}) { | ||||
|                         my $f = $fill->unpack; | ||||
|                         for my $i (0 .. $#{$layer->slices}-1) { | ||||
|                             if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) { | ||||
|                                 push @{ $islands[$i]{fills} }, $f; | ||||
|                                 next FILL; | ||||
|                             } | ||||
|                         } | ||||
|                         push @{ $islands[-1]{fills} }, $f; # optimization | ||||
|                     } | ||||
|                 } else { | ||||
|                     push @islands, { | ||||
|                         perimeters  => $layerm->perimeters, | ||||
|                         fills       => $layerm->fills, | ||||
|                     }; | ||||
|                 } | ||||
|                  | ||||
|                 foreach my $island (@islands) { | ||||
|                     my $extrude_perimeters = sub { | ||||
|                         return if !@{ $island->{perimeters} }; | ||||
|                         $gcode .= $gcodegen->set_extruder($region->extruders->{perimeter}); | ||||
|                         $gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $island->{perimeters} }; | ||||
|                     }; | ||||
|                      | ||||
|                     my $extrude_fills = sub { | ||||
|                         return if !@{ $island->{fills} }; | ||||
|                         $gcode .= $gcodegen->set_extruder($region->extruders->{infill}); | ||||
|                         for my $fill (@{ $island->{fills} }) { | ||||
|                             if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { | ||||
|                                 $gcode .= $gcodegen->extrude($_, 'fill')  | ||||
|                                     for $fill->chained_path($gcodegen->last_pos); | ||||
|                             } else { | ||||
|                                 $gcode .= $gcodegen->extrude($fill, 'fill') ; | ||||
|                             } | ||||
|                         } | ||||
|                     }; | ||||
|                      | ||||
|                     # give priority to infill if we were already using its extruder and it wouldn't | ||||
|                     # be good for perimeters | ||||
|                     if ($Slic3r::Config->infill_first | ||||
|                         || ($gcodegen->multiple_extruders && $region->extruders->{infill} eq $gcodegen->extruder) && $region->extruders->{infill} ne $region->extruders->{perimeter}) { | ||||
|                         $extrude_fills->(); | ||||
|                         $extrude_perimeters->(); | ||||
|                     } else { | ||||
|                         $extrude_perimeters->(); | ||||
|                         $extrude_fills->(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         # apply spiral vase post-processing if this layer contains suitable geometry | ||||
|         $gcode = $spiralvase->process_layer($gcode, $layer) | ||||
|             if defined $spiralvase | ||||
|             && ($layer->id > 0 || $Slic3r::Config->brim_width == 0) | ||||
|             && ($layer->id >= $Slic3r::Config->skirt_height) | ||||
|             && ($layer->id >= $Slic3r::Config->bottom_solid_layers); | ||||
|          | ||||
|         return $gcode; | ||||
|     }; | ||||
|     # prepare the layer processor | ||||
|     my $layer_gcode = Slic3r::GCode::Layer->new( | ||||
|         print       => $self, | ||||
|         gcodegen    => $gcodegen, | ||||
|         shift       => \@shift, | ||||
|     ); | ||||
|      | ||||
|     # do all objects for each layer | ||||
|     if ($Slic3r::Config->complete_objects) { | ||||
|  | @ -970,7 +799,7 @@ sub write_gcode { | |||
|                             if $Slic3r::Config->first_layer_bed_temperature; | ||||
|                         $print_first_layer_temperature->(); | ||||
|                     } | ||||
|                     print $fh $buffer->append($extrude_layer->($layer, [$copy]), $layer); | ||||
|                     print $fh $buffer->append($layer_gcode->process_layer($layer, [$copy]), $layer); | ||||
|                 } | ||||
|                 print $fh $buffer->flush; | ||||
|                 $finished_objects++; | ||||
|  | @ -981,8 +810,10 @@ sub write_gcode { | |||
|             config      => $Slic3r::Config, | ||||
|             gcodegen    => $gcodegen, | ||||
|         ); | ||||
|         print $fh $buffer->append($extrude_layer->($_, $_->object->copies), $_) | ||||
|             for sort { $a->print_z <=> $b->print_z } map @{$_->layers}, @{$self->objects}; | ||||
|         my @layers = sort { $a->print_z <=> $b->print_z } map @{$_->layers}, @{$self->objects}; | ||||
|         foreach my $layer (@layers) { | ||||
|             print $fh $buffer->append($layer_gcode->process_layer($layer, $layer->object->copies), $layer); | ||||
|         } | ||||
|         print $fh $buffer->flush; | ||||
|     } | ||||
|      | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci