@@ -9,7 +9,7 @@ use Slic3r::Geometry qw(epsilon scale unscale scaled_epsilon points_coincide PI
use Slic3r::Geometry::Clipper qw( union_ex offset_ex ) ;
use Slic3r::Surface ':types' ;
has 'print_ config' = > ( is = > 'ro' , default = > sub { Slic3r::Config::Print - > new } ) ;
has 'config' = > ( is = > 'ro' , default = > sub { Slic3r::Config::Full - > new } ) ;
has 'placeholder_parser' = > ( is = > 'rw' , default = > sub { Slic3r::GCode::PlaceholderParser - > new } ) ;
has 'standby_points' = > ( is = > 'rw' ) ;
has 'enable_loop_clipping' = > ( is = > 'rw' , default = > sub { 1 } ) ;
@@ -17,19 +17,16 @@ has 'enable_wipe' => (is => 'rw', default => sub {0}); # at least one e
has 'layer_count' = > ( is = > 'ro' , required = > 1 ) ;
has '_layer_index' = > ( is = > 'rw' , default = > sub { - 1 } ) ; # just a counter
has 'layer' = > ( is = > 'rw' ) ;
has 'region' = > ( is = > 'rw' ) ;
has '_layer_islands' = > ( is = > 'rw' ) ;
has '_upper_layer_islands' = > ( is = > 'rw' ) ;
has 'shift_x' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'shift_y' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'z' = > ( is = > 'rw' ) ;
has 'speed' = > ( is = > 'rw' ) ;
has '_extrusion_axis' = > ( is = > 'rw' ) ;
has '_retract_lift' = > ( is = > 'rw' ) ;
has 'extruders' = > ( is = > 'ro' , default = > sub { { } } ) ;
has 'multiple_extruders' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'extruder' = > ( is = > 'rw' ) ;
has 'speeds' = > ( is = > 'lazy' ) ; # mm/min
has 'external_mp' = > ( is = > 'rw' ) ;
has 'layer_mp' = > ( is = > 'rw' ) ;
has 'new_object' = > ( is = > 'rw' , default = > sub { 0 } ) ;
@@ -37,23 +34,21 @@ has 'straight_once' => (is => 'rw', default => sub {1});
has 'elapsed_time' = > ( is = > 'rw' , default = > sub { 0 } ) ; # seconds
has 'lifted' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'last_pos' = > ( is = > 'rw' , default = > sub { Slic3r::Point - > new ( 0 , 0 ) } ) ;
has 'last_speed' = > ( is = > 'rw' , default = > sub { "" } ) ;
has 'last_f' = > ( is = > 'rw' , default = > sub { "" } ) ;
has 'last_fan_speed' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'wipe_path' = > ( is = > 'rw' ) ;
sub BUILD {
my ( $ self ) = @ _ ;
$ self - > _extrusion_axis ( $ self - > print_ config- > get_extrusion_axis ) ;
$ self - > _retract_lift ( $ self - > print_ config- > retract_lift - > [ 0 ] ) ;
$ self - > _extrusion_axis ( $ self - > config - > get_extrusion_axis ) ;
$ self - > _retract_lift ( $ self - > config - > retract_lift - > [ 0 ] ) ;
}
sub set_extruders {
my ( $ self , $ extruder_ids ) = @ _ ;
my ( $ self , $ extruder_ids , $ print_config ) = @ _ ;
foreach my $ i ( @$ extruder_ids ) {
$ self - > extruders - > { $ i } = my $ e = Slic3r::Extruder - > new ( $ i , $ self - > print_config) ;
$ self - > extruders - > { $ i } = my $ e = Slic3r::Extruder - > new ( $ i , $ print_config ) ;
$ self - > enable_wipe ( 1 ) if $ e - > wipe ;
}
@@ -63,28 +58,6 @@ sub set_extruders {
$ self - > multiple_extruders ( max ( @$ extruder_ids ) > 0 ) ;
}
sub _build_speeds {
my $ self = shift ;
return {
map { $ _ = > 60 * $ self - > print_config - > get_value ( "${_}_speed" ) }
qw( travel perimeter small_perimeter external_perimeter infill
solid_infill top_solid_infill bridge gap_fill retract ) ,
} ;
}
# assign speeds to roles
my % role_speeds = (
& EXTR_ROLE_PERIMETER = > 'perimeter' ,
& EXTR_ROLE_EXTERNAL_PERIMETER = > 'external_perimeter' ,
& EXTR_ROLE_OVERHANG_PERIMETER = > 'bridge' ,
& EXTR_ROLE_FILL = > 'infill' ,
& EXTR_ROLE_SOLIDFILL = > 'solid_infill' ,
& EXTR_ROLE_TOPSOLIDFILL = > 'top_solid_infill' ,
& EXTR_ROLE_BRIDGE = > 'bridge' ,
& EXTR_ROLE_SKIRT = > 'perimeter' ,
& EXTR_ROLE_GAPFILL = > 'gap_fill' ,
) ;
sub set_shift {
my ( $ self , @ shift ) = @ _ ;
@@ -109,23 +82,23 @@ sub change_layer {
# avoid computing islands and overhangs if they're not needed
$ self - > _layer_islands ( $ layer - > islands ) ;
$ self - > _upper_layer_islands ( $ layer - > upper_layer ? $ layer - > upper_layer - > islands : [] ) ;
if ( $ self - > print_ config- > avoid_crossing_perimeters ) {
if ( $ self - > config - > avoid_crossing_perimeters ) {
$ self - > layer_mp ( Slic3r::GCode::MotionPlanner - > new (
islands = > union_ex ( [ map @$ _ , @ { $ layer - > slices } ] , 1 ) ,
) ) ;
}
my $ gcode = "" ;
if ( $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) {
if ( $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) {
$ gcode . = sprintf "M73 P%s%s\n" ,
int ( 99 * ( $ self - > _layer_index / ( $ self - > layer_count - 1 ) ) ) ,
( $ self - > print_ config- > gcode_comments ? ' ; update progress' : '' ) ;
( $ self - > config - > gcode_comments ? ' ; update progress' : '' ) ;
}
if ( $ self - > print_ config- > first_layer_acceleration ) {
if ( $ self - > config - > first_layer_acceleration ) {
if ( $ layer - > id == 0 ) {
$ gcode . = $ self - > set_acceleration ( $ self - > print_ config- > first_layer_acceleration ) ;
$ gcode . = $ self - > set_acceleration ( $ self - > config - > first_layer_acceleration ) ;
} elsif ( $ layer - > id == 1 ) {
$ gcode . = $ self - > set_acceleration ( $ self - > print_ config- > default_acceleration ) ;
$ gcode . = $ self - > set_acceleration ( $ self - > config - > default_acceleration ) ;
}
}
@@ -139,7 +112,7 @@ sub move_z {
my $ gcode = "" ;
$ z += $ self - > print_ config- > z_offset ;
$ z += $ self - > config - > z_offset ;
my $ current_z = $ self - > z ;
my $ nominal_z = defined $ current_z ? ( $ current_z - $ self - > lifted ) : undef ;
@@ -156,8 +129,7 @@ sub move_z {
$ current_z = $ self - > z ; # update current z in case retract() changed it
$ nominal_z = defined $ current_z ? ( $ current_z - $ self - > lifted ) : undef ;
}
$ self - > speed ( 'travel ') ;
$ gcode . = $ self - > G0 ( undef , $ z , 0 , $ comment || ( 'move to next layer (' . $ self - > layer - > id . ')' ) )
$ gcode . = $ self - > G0 ( undef , $ z , 0 , $ self - > config - > travel_speed * 60 , $ comment || ( 'move to next layer (' . $ self - > layer - > id . ') ') )
if ! defined $ current_z || abs ( $ z - $ nominal_z ) > epsilon ;
} elsif ( $ z < $ current_z ) {
# we're moving above the current nominal layer height and below the current actual one.
@@ -191,11 +163,11 @@ sub extrude_loop {
# start looking for concave vertices not being overhangs
my $ polygon = $ loop - > polygon ;
my @ concave = ( ) ;
if ( $ self - > print_ config- > start_perimeters_at_concave_points ) {
if ( $ self - > config - > start_perimeters_at_concave_points ) {
@ concave = $ polygon - > concave_points ;
}
my @ candidates = ( ) ;
if ( $ self - > print_ config- > start_perimeters_at_non_overhang ) {
if ( $ self - > config - > start_perimeters_at_non_overhang ) {
@ candidates = grep ! $ loop - > has_overhang_point ( $ _ ) , @ concave ;
}
if ( ! @ candidates ) {
@@ -203,7 +175,7 @@ sub extrude_loop {
@ candidates = @ concave ;
if ( ! @ candidates ) {
# if none, look for any non-overhang vertex
if ( $ self - > print_ config- > start_perimeters_at_non_overhang ) {
if ( $ self - > config - > start_perimeters_at_non_overhang ) {
@ candidates = grep ! $ loop - > has_overhang_point ( $ _ ) , @$ polygon ;
}
if ( ! @ candidates ) {
@@ -216,9 +188,9 @@ sub extrude_loop {
# find the point of the loop that is closest to the current extruder position
# or randomize if requested
my $ last_pos = $ self - > last_pos ;
if ( $ self - > print_ config- > randomize_start && $ loop - > role == EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER ) {
$ last_pos = Slic3r::Point - > new ( scale $ self - > print_ config- > print_center - > [ X ] , scale $ self - > print_ config- > bed_size - > [ Y ] ) ;
$ last_pos - > rotate ( rand ( 2 * PI ) , $ self - > print_ config- > print_center ) ;
if ( $ self - > config - > randomize_start && $ loop - > role == EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER ) {
$ last_pos = Slic3r::Point - > new ( scale $ self - > config - > print_center - > [ X ] , scale $ self - > config - > bed_size - > [ Y ] ) ;
$ last_pos - > rotate ( rand ( 2 * PI ) , $ self - > config - > print_center ) ;
}
# split the loop at the starting point
@@ -236,17 +208,17 @@ sub extrude_loop {
return '' if ! @ paths ;
# apply the small perimeter speed
my % params = ( ) ;
if ( $ paths [ 0 ] - > is_perimeter && abs ( $ loop - > length ) <= & Slic3r:: SMALL_PERIMETER_LENGTH ) {
$ params { speed } = 'small_perimeter' ;
my $ speed = - 1 ;
if ( $ paths [ 0 ] - > is_perimeter && $ loop - > length <= & Slic3r:: SMALL_PERIMETER_LENGTH ) {
$ speed = $ self - > config - > get_abs_value ( 'small_perimeter_speed' ) ;
}
# extrude along the path
my $ gcode = join '' , map $ self - > extrude_path ( $ _ , $ description , % params ) , @ paths ;
my $ gcode = join '' , map $ self - > extrude_path ( $ _ , $ description , $ speed ) , @ paths ;
$ self - > wipe_path ( $ paths [ - 1 ] - > polyline - > clone ) if $ self - > enable_wipe ; # TODO: don't limit wipe to last path
# make a little move inwards before leaving loop
if ( $ paths [ - 1 ] - > role == EXTR_ROLE_EXTERNAL_PERIMETER && defined $ self - > layer && $ self - > region - > config- > perimeters > 1 ) {
if ( $ paths [ - 1 ] - > role == EXTR_ROLE_EXTERNAL_PERIMETER && defined $ self - > layer && $ self - > config - > perimeters > 1 ) {
my $ last_path_polyline = $ paths [ - 1 ] - > polyline ;
# detect angle between last and first segment
# the side depends on the original winding order of the polygon (left for contours, right for holes)
@@ -270,7 +242,7 @@ sub extrude_loop {
}
sub extrude_path {
my ( $ self , $ path , $ description , % params ) = @ _ ;
my ( $ self , $ path , $ description , $ speed ) = @ _ ;
$ path - > simplify ( & Slic3r:: SCALED_RESOLUTION ) ;
@@ -287,13 +259,13 @@ sub extrude_path {
# adjust acceleration
my $ acceleration ;
if ( ! $ self - > print_ config- > first_layer_acceleration || $ self - > layer - > id != 0 ) {
if ( $ self - > print_ config- > perimeter_acceleration && $ path - > is_perimeter ) {
$ acceleration = $ self - > print_ config- > perimeter_acceleration ;
} elsif ( $ self - > print_ config- > infill_acceleration && $ path - > is_fill ) {
$ acceleration = $ self - > print_ config- > infill_acceleration ;
} elsif ( $ self - > print_ config- > infill_acceleration && $ path - > is_bridge ) {
$ acceleration = $ self - > print_ config- > bridge_acceleration ;
if ( ! $ self - > config - > first_layer_acceleration || $ self - > layer - > id != 0 ) {
if ( $ self - > config - > perimeter_acceleration && $ path - > is_perimeter ) {
$ acceleration = $ self - > config - > perimeter_acceleration ;
} elsif ( $ self - > config - > infill_acceleration && $ path - > is_fill ) {
$ acceleration = $ self - > config - > infill_acceleration ;
} elsif ( $ self - > config - > infill_acceleration && $ path - > is_bridge ) {
$ acceleration = $ self - > config - > bridge_acceleration ;
}
$ gcode . = $ self - > set_acceleration ( $ acceleration ) if $ acceleration ;
}
@@ -303,10 +275,29 @@ sub extrude_path {
$ e = 0 if ! $ self - > _extrusion_axis ;
# set speed
$ self - > speed ( $ params { speed } || $ role_speeds { $ path - > role } || die "Unknown role: " . $ path - > role ) ;
my $ F = $ self - > speeds - > { $ self - > speed } // $ self - > speed ;
my $ F ;
if ( $ path - > role == EXTR_ROLE_PERIMETER || $ path - > role == EXTR_ROLE_SKIRT ) {
$ F = $ self - > config - > get_abs_value ( 'perimeter_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_EXTERNAL_PERIMETER ) {
$ F = $ self - > config - > get_abs_value ( 'external_perimeter_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_OVERHANG_PERIMETER || $ path - > role == EXTR_ROLE_BRIDGE ) {
$ F = $ self - > config - > get_abs_value ( 'bridge_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_FILL ) {
$ F = $ self - > config - > get_abs_value ( 'infill_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_SOLIDFILL ) {
$ F = $ self - > config - > get_abs_value ( 'solid_infill_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_TOPSOLIDFILL ) {
$ F = $ self - > config - > get_abs_value ( 'top_solid_infill_speed' ) ;
} elsif ( $ path - > role == EXTR_ROLE_GAPFILL ) {
$ F = $ self - > config - > get_abs_value ( 'gap_fill_speed' ) ;
} else {
$ F = $ speed ;
die "Invalid speed" if $ F < 0 ; # $speed == -1
}
$ F *= 60 ; # convert mm/sec to mm/min
if ( $ self - > layer - > id == 0 ) {
$ F = $ self - > print_ config- > get_abs_value_over ( 'first_layer_speed' , $ F / 60 ) * 60 ;
$ F = $ self - > config - > get_abs_value_over ( 'first_layer_speed' , $ F / 60 ) * 60 ;
}
# extrude arc or line
@@ -317,7 +308,7 @@ sub extrude_path {
$ self - > shift_x - $ self - > extruder - > extruder_offset - > x ,
$ self - > shift_y - $ self - > extruder - > extruder_offset - > y , #,,
$ self - > _extrusion_axis ,
$ self - > print_ config- > gcode_comments ? " ; $description" : "" ) ;
$ self - > config - > gcode_comments ? " ; $description" : "" ) ;
if ( $ self - > enable_wipe ) {
$ self - > wipe_path ( $ path - > polyline - > clone ) ;
@@ -327,14 +318,14 @@ sub extrude_path {
$ gcode . = ";_BRIDGE_FAN_END\n" if $ path - > is_bridge ;
$ self - > last_pos ( $ path - > last_point ) ;
if ( $ self - > print_ config- > cooling ) {
if ( $ self - > config - > cooling ) {
my $ path_time = $ path_length / $ F * 60 ;
$ self - > elapsed_time ( $ self - > elapsed_time + $ path_time ) ;
}
# reset acceleration
$ gcode . = $ self - > set_acceleration ( $ self - > print_ config- > default_acceleration )
if $ acceleration && $ self - > print_ config- > default_acceleration ;
$ gcode . = $ self - > set_acceleration ( $ self - > config - > default_acceleration )
if $ acceleration && $ self - > config - > default_acceleration ;
return $ gcode ;
}
@@ -353,19 +344,17 @@ sub travel_to {
# skip retraction if the travel move is contained in an island in the current layer
# *and* in an island in the upper layer (so that the ooze will not be visible)
if ( $ travel - > length < scale $ self - > extruder - > retract_before_travel
|| ( $ self - > print_ config- > only_retract_when_crossing_perimeters
|| ( $ self - > config - > only_retract_when_crossing_perimeters
&& ( first { $ _ - > contains_line ( $ travel ) } @ { $ self - > _upper_layer_islands } )
&& ( first { $ _ - > contains_line ( $ travel ) } @ { $ self - > _layer_islands } ) )
|| ( defined $ role && $ role == EXTR_ROLE_SUPPORTMATERIAL && ( first { $ _ - > contains_line ( $ travel ) } @ { $ self - > layer - > support_islands } ) )
) {
$ self - > straight_once ( 0 ) ;
$ self - > speed ( 'travel' ) ;
$ gcode . = $ self - > G0 ( $ point , undef , 0 , $ comment || "" ) ;
} elsif ( ! $ self - > print_config - > avoid_crossing_perimeters || $ self - > straight_once ) {
$ gcode . = $ self - > G0 ( $ point , undef , 0 , $ self - > config - > travel_speed * 60 , $ comment || "" ) ;
} elsif ( ! $ self - > config - > avoid_crossing_perimeters || $ self - > straight_once ) {
$ self - > straight_once ( 0 ) ;
$ gcode . = $ self - > retract ;
$ self - > speed ( 'travel' ) ;
$ gcode . = $ self - > G0 ( $ point , undef , 0 , $ comment || "" ) ;
$ gcode . = $ self - > G0 ( $ point , undef , 0 , $ self - > config - > travel_speed * 60 , $ comment || "" ) ;
} else {
if ( $ self - > new_object ) {
$ self - > new_object ( 0 ) ;
@@ -394,7 +383,7 @@ sub _plan {
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 = ! $ self - > print_ config- > only_retract_when_crossing_perimeters ;
my $ need_retract = ! $ self - > config - > only_retract_when_crossing_perimeters ;
if ( ! $ need_retract ) {
$ need_retract = 1 ;
foreach my $ island ( @ { $ self - > _upper_layer_islands } ) {
@@ -410,9 +399,8 @@ sub _plan {
$ gcode . = $ self - > retract if $ need_retract ;
# append the actual path and return
$ self - > speed ( 'travel' ) ;
# use G1 because we rely on paths being straight (G0 may make round paths)
$ gcode . = join '' , map $ self - > G1 ( $ _ - > b , undef , 0 , $ comment || "" ) , @ travel ;
$ gcode . = join '' , map $ self - > G1 ( $ _ - > b , undef , 0 , $ self - > config - > travel_speed * 60 , $ comment || "" ) , @ travel ;
return $ gcode ;
}
@@ -434,45 +422,40 @@ sub retract {
if ( $ self - > extruder - > wipe && $ self - > wipe_path ) {
my @ points = @ { $ self - > wipe_path } ;
$ wipe_path = Slic3r::Polyline - > new ( $ self - > last_pos , @ { $ self - > wipe_path } [ 1 .. $# { $ self - > wipe_path } ] ) ;
$ wipe_path - > clip_end ( $ wipe_path - > length - $ self - > extruder - > scaled_wipe_distance ( $ self - > print_ config- > travel_speed ) ) ;
$ wipe_path - > clip_end ( $ wipe_path - > length - $ self - > extruder - > scaled_wipe_distance ( $ self - > config - > travel_speed ) ) ;
}
# prepare moves
my $ retract = [ undef , undef , - $ length , $ comment ] ;
my $ retract = [ undef , undef , - $ length , $ self - > extruder - > retract_speed_mm_min , $ comment] ;
my $ lift = ( $ self - > _retract_lift == 0 || defined $ params { move_z } ) && ! $ self - > lifted
? undef
: [ undef , $ self - > z + $ self - > _retract_lift , 0 , 'lift plate during travel' ] ;
: [ undef , $ self - > z + $ self - > _retract_lift , 0 , $ self - > config - > travel_speed * 60 , 'lift plate during travel' ] ;
# check that we have a positive wipe length
if ( $ wipe_path ) {
$ self - > speed ( $ self - > speeds - > { travel } * 0.8 ) ;
# subdivide the retraction
my $ retracted = 0 ;
foreach my $ line ( @ { $ wipe_path - > lines } ) {
my $ segment_length = $ line - > length ;
# reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
# due to rounding
my $ e = $ retract - > [ 2 ] * ( $ segment_length / $ self - > extruder - > scaled_wipe_distance ( $ self - > print_ config- > travel_speed ) ) * 0.95 ;
my $ e = $ retract - > [ 2 ] * ( $ segment_length / $ self - > extruder - > scaled_wipe_distance ( $ self - > config - > travel_speed ) ) * 0.95 ;
$ retracted += $ e ;
$ gcode . = $ self - > G1 ( $ line - > b , undef , $ e , $ retract - > [ 3 ] . ";_WIPE" ) ;
$ gcode . = $ self - > G1 ( $ line - > b , undef , $ e , $ self - > config - > travel_speed * 60 * 0.8 , $ retract- > [ 3 ] . ";_WIPE" ) ;
}
if ( $ retracted > $ retract - > [ 2 ] ) {
# if we retracted less than we had to, retract the remainder
# TODO: add regression test
$ self - > speed ( 'retract' ) ;
$ gcode . = $ self - > G1 ( undef , undef , $ retract - > [ 2 ] - $ retracted , $ comment ) ;
$ gcode . = $ self - > G1 ( undef , undef , $ retract - > [ 2 ] - $ retracted , $ self - > extruder - > retract_speed_mm_min , $ comment ) ;
}
} elsif ( $ self - > print_ config- > use_firmware_retraction ) {
} elsif ( $ self - > config - > use_firmware_retraction ) {
$ gcode . = "G10 ; retract\n" ;
} else {
$ self - > speed ( 'retract' ) ;
$ gcode . = $ self - > G1 ( @$ retract ) ;
}
if ( ! $ self - > lifted ) {
$ self - > speed ( 'travel' ) ;
if ( defined $ params { move_z } && $ self - > _retract_lift > 0 ) {
my $ travel = [ undef , $ params { move_z } + $ self - > _retract_lift , 0 , 'move to next layer (' . $ self - > layer - > id . ') and lift' ] ;
my $ travel = [ undef , $ params { move_z } + $ self - > _retract_lift , 0 , $ self - > config - > travel_speed * 60 , 'move to next layer (' . $ self - > layer - > id . ') and lift' ] ;
$ gcode . = $ self - > G0 ( @$ travel ) ;
$ self - > lifted ( $ self - > _retract_lift ) ;
} elsif ( $ lift ) {
@@ -487,7 +470,7 @@ sub retract {
# this makes sure we leave sufficient precision in the firmware
$ gcode . = $ self - > reset_e ;
$ gcode . = "M103 ; extruder off\n" if $ self - > print_ config- > gcode_flavor eq 'makerware' ;
$ gcode . = "M103 ; extruder off\n" if $ self - > config - > gcode_flavor eq 'makerware' ;
return $ gcode ;
}
@@ -496,18 +479,16 @@ sub unretract {
my ( $ self ) = @ _ ;
my $ gcode = "" ;
$ gcode . = "M101 ; extruder on\n" if $ self - > print_ config- > gcode_flavor eq 'makerware' ;
$ gcode . = "M101 ; extruder on\n" if $ self - > config - > gcode_flavor eq 'makerware' ;
if ( $ self - > lifted ) {
$ self - > speed ( 'travel ') ;
$ gcode . = $ self - > G0 ( undef , $ self - > z - $ self - > lifted , 0 , 'restore layer Z' ) ;
$ gcode . = $ self - > G0 ( undef , $ self - > z - $ self - > lifted , 0 , $ self - > config - > travel_speed * 60 , 'restore layer Z ') ;
$ self - > lifted ( 0 ) ;
}
my $ to_unretract = $ self - > extruder - > retracted + $ self - > extruder - > restart_extra ;
if ( $ to_unretract ) {
$ self - > speed ( ' retract' ) ;
if ( $ self - > print_config - > use_firmware_retraction ) {
if ( $ self - > config - > use_firmware_ retraction ) {
$ gcode . = "G11 ; unretract\n" ;
} elsif ( $ self - > _extrusion_axis ) {
# use G1 instead of G0 because G0 will blend the restart with the previous travel move
@@ -515,7 +496,7 @@ sub unretract {
$ self - > _extrusion_axis ,
$ self - > extruder - > extrude ( $ to_unretract ) ,
$ self - > extruder - > retract_speed_mm_min ;
$ gcode . = " ; compensate retraction" if $ self - > print_ config- > gcode_comments ;
$ gcode . = " ; compensate retraction" if $ self - > config - > gcode_comments ;
$ gcode . = "\n" ;
}
$ self - > extruder - > set_retracted ( 0 ) ;
@@ -527,11 +508,11 @@ sub unretract {
sub reset_e {
my ( $ self ) = @ _ ;
return "" if $ self - > print_ config- > gcode_flavor =~ /^(?:mach3|makerware|sailfish)$/ ;
return "" if $ self - > config - > gcode_flavor =~ /^(?:mach3|makerware|sailfish)$/ ;
$ self - > extruder - > set_E ( 0 ) if $ self - > extruder ;
return sprintf "G92 %s0%s\n" , $ self - > _extrusion_axis , ( $ self - > print_ config- > gcode_comments ? ' ; reset extrusion distance' : '' )
if $ self - > _extrusion_axis && ! $ self - > print_ config- > use_relative_e_distances ;
return sprintf "G92 %s0%s\n" , $ self - > _extrusion_axis , ( $ self - > config - > gcode_comments ? ' ; reset extrusion distance' : '' )
if $ self - > _extrusion_axis && ! $ self - > config - > use_relative_e_distances ;
}
sub set_acceleration {
@@ -539,12 +520,12 @@ sub set_acceleration {
return "" if ! $ acceleration ;
return sprintf "M204 S%s%s\n" ,
$ acceleration , ( $ self - > print_ config- > gcode_comments ? ' ; adjust acceleration' : '' ) ;
$ acceleration , ( $ self - > config - > gcode_comments ? ' ; adjust acceleration' : '' ) ;
}
sub G0 {
my $ self = shift ;
return $ self - > G1 ( @ _ ) if ! ( $ self - > print_ config- > g0 || $ self - > print_ config- > gcode_flavor eq 'mach3' ) ;
return $ self - > G1 ( @ _ ) if ! ( $ self - > config - > g0 || $ self - > config - > gcode_flavor eq 'mach3' ) ;
return $ self - > _G0_G1 ( "G0" , @ _ ) ;
}
@@ -554,7 +535,7 @@ sub G1 {
}
sub _G0_G1 {
my ( $ self , $ gcode , $ point , $ z , $ e , $ comment ) = @ _ ;
my ( $ self , $ gcode , $ point , $ z , $ e , $ F , $ comment) = @ _ ;
if ( $ point ) {
$ gcode . = sprintf " X%.3f Y%.3f" ,
@@ -567,17 +548,12 @@ sub _G0_G1 {
$ gcode . = sprintf " Z%.3f" , $ z ;
}
return $ self - > _Gx ( $ gcode , $ e , $ comment ) ;
return $ self - > _Gx ( $ gcode , $ e , $ F , $ comment) ;
}
sub _Gx {
my ( $ self , $ gcode , $ e , $ comment ) = @ _ ;
my ( $ self , $ gcode , $ e , $ F , $ comment) = @ _ ;
my $ F = $ self - > speed eq 'retract'
? ( $ self - > extruder - > retract_speed_mm_min )
: $ self - > speeds - > { $ self - > speed } // $ self - > speed ;
$ self - > last_speed ( $ self - > speed ) ;
$ self - > last_f ( $ F ) ;
$ gcode . = sprintf " F%.3f" , $ F ;
# output extrusion distance
@@ -585,7 +561,7 @@ sub _Gx {
$ gcode . = sprintf " %s%.5f" , $ self - > _extrusion_axis , $ self - > extruder - > extrude ( $ e ) ;
}
$ gcode . = " ; $comment" if $ comment && $ self - > print_ config- > gcode_comments ;
$ gcode . = " ; $comment" if $ comment && $ self - > config - > gcode_comments ;
return "$gcode\n" ;
}
@@ -606,8 +582,8 @@ sub set_extruder {
$ gcode . = $ self - > retract ( toolchange = > 1 ) if defined $ self - > extruder ;
# append custom toolchange G-code
if ( defined $ self - > extruder && $ self - > print_ config- > toolchange_gcode ) {
$ gcode . = sprintf "%s\n" , $ self - > placeholder_parser - > process ( $ self - > print_ config- > toolchange_gcode , {
if ( defined $ self - > extruder && $ self - > config - > toolchange_gcode ) {
$ gcode . = sprintf "%s\n" , $ self - > placeholder_parser - > process ( $ self - > config - > toolchange_gcode , {
previous_extruder = > $ self - > extruder - > id ,
next_extruder = > $ extruder_id ,
} ) ;
@@ -622,24 +598,24 @@ sub set_extruder {
? $ self - > extruder - > first_layer_temperature
: $ self - > extruder - > temperature ;
# we assume that heating is always slower than cooling, so no need to block
$ gcode . = $ self - > set_temperature ( $ temp + $ self - > print_ config- > standby_temperature_delta , 0 ) ;
$ gcode . = $ self - > set_temperature ( $ temp + $ self - > config - > standby_temperature_delta , 0 ) ;
}
# set the new extruder
$ self - > extruder ( $ self - > extruders - > { $ extruder_id } ) ;
$ gcode . = sprintf "%s%d%s\n" ,
( $ self - > print_ config- > gcode_flavor eq 'makerware'
( $ self - > config - > gcode_flavor eq 'makerware'
? 'M135 T'
: $ self - > print_ config- > gcode_flavor eq 'sailfish'
: $ self - > config - > gcode_flavor eq 'sailfish'
? 'M108 T'
: 'T' ) ,
$ extruder_id ,
( $ self - > print_ config- > gcode_comments ? ' ; change extruder' : '' ) ;
( $ self - > config - > gcode_comments ? ' ; change extruder' : '' ) ;
$ gcode . = $ self - > reset_e ;
# set the new extruder to the operating temperature
if ( $ self - > print_ config- > ooze_prevention ) {
if ( $ self - > config - > ooze_prevention ) {
my $ temp = defined $ self - > layer && $ self - > layer - > id == 0
? $ self - > extruder - > first_layer_temperature
: $ self - > extruder - > temperature ;
@@ -655,18 +631,18 @@ sub set_fan {
if ( $ self - > last_fan_speed != $ speed || $ dont_save ) {
$ self - > last_fan_speed ( $ speed ) if ! $ dont_save ;
if ( $ speed == 0 ) {
my $ code = $ self - > print_ config- > gcode_flavor eq 'teacup'
my $ code = $ self - > config - > gcode_flavor eq 'teacup'
? 'M106 S0'
: $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/
: $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/
? 'M127'
: 'M107' ;
return sprintf "$code%s\n" , ( $ self - > print_ config- > gcode_comments ? ' ; disable fan' : '' ) ;
return sprintf "$code%s\n" , ( $ self - > config - > gcode_comments ? ' ; disable fan' : '' ) ;
} else {
if ( $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) {
return sprintf "M126%s\n" , ( $ self - > print_ config- > gcode_comments ? ' ; enable fan' : '' ) ;
if ( $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) {
return sprintf "M126%s\n" , ( $ self - > config - > gcode_comments ? ' ; enable fan' : '' ) ;
} else {
return sprintf "M106 %s%d%s\n" , ( $ self - > print_ config- > gcode_flavor eq 'mach3' ? 'P' : 'S' ) ,
( 255 * $ speed / 100 ) , ( $ self - > print_ config- > gcode_comments ? ' ; enable fan' : '' ) ;
return sprintf "M106 %s%d%s\n" , ( $ self - > config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) ,
( 255 * $ speed / 100 ) , ( $ self - > config - > gcode_comments ? ' ; enable fan' : '' ) ;
}
}
}
@@ -676,17 +652,17 @@ sub set_fan {
sub set_temperature {
my ( $ self , $ temperature , $ wait , $ tool ) = @ _ ;
return "" if $ wait && $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/ ;
return "" if $ wait && $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/ ;
my ( $ code , $ comment ) = ( $ wait && $ self - > print_ config- > gcode_flavor ne 'teacup' )
my ( $ code , $ comment ) = ( $ wait && $ self - > config - > gcode_flavor ne 'teacup' )
? ( 'M109' , 'wait for temperature to be reached' )
: ( 'M104' , 'set temperature' ) ;
my $ gcode = sprintf "$code %s%d %s; $comment\n" ,
( $ self - > print_ config- > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ,
( defined $ tool && ( $ self - > multiple_extruders || $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) ) ? "T$tool " : "" ;
( $ self - > config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ,
( defined $ tool && ( $ self - > multiple_extruders || $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/ ) ) ? "T$tool " : "" ;
$ gcode . = "M116 ; wait for temperature to be reached\n"
if $ self - > print_ config- > gcode_flavor eq 'teacup' && $ wait ;
if $ self - > config - > gcode_flavor eq 'teacup' && $ wait ;
return $ gcode ;
}
@@ -694,14 +670,14 @@ sub set_temperature {
sub set_bed_temperature {
my ( $ self , $ temperature , $ wait ) = @ _ ;
my ( $ code , $ comment ) = ( $ wait && $ self - > print_ config- > gcode_flavor ne 'teacup' )
? ( ( $ self - > print_ config- > gcode_flavor =~ /^(?:makerware|sailfish)$/ ? 'M109' : 'M190' ) , 'wait for bed temperature to be reached' )
my ( $ code , $ comment ) = ( $ wait && $ self - > config - > gcode_flavor ne 'teacup' )
? ( ( $ self - > config - > gcode_flavor =~ /^(?:makerware|sailfish)$/ ? 'M109' : 'M190' ) , 'wait for bed temperature to be reached' )
: ( 'M140' , 'set bed temperature' ) ;
my $ gcode = sprintf "$code %s%d ; $comment\n" ,
( $ self - > print_ config- > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ;
( $ self - > config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ;
$ gcode . = "M116 ; wait for bed temperature to be reached\n"
if $ self - > print_ config- > gcode_flavor eq 'teacup' && $ wait ;
if $ self - > config - > gcode_flavor eq 'teacup' && $ wait ;
return $ gcode ;
}