2012-06-28 12:44:54 +00:00
package Slic3r::GCode ;
use Moo ;
2012-08-25 15:18:12 +00:00
use List::Util qw( first ) ;
2012-06-28 12:44:54 +00:00
use Slic3r::ExtrusionPath ':roles' ;
2012-10-28 18:15:34 +00:00
use Slic3r::Geometry qw( scale unscale scaled_epsilon points_coincide PI X Y A B ) ;
2012-06-28 12:44:54 +00:00
2012-09-23 00:40:25 +00:00
has 'multiple_extruders' = > ( is = > 'ro' , default = > sub { 0 } ) ;
2012-10-28 15:59:20 +00:00
has 'layer' = > ( is = > 'rw' ) ; # this is not very correct, we should replace it with explicit layer_id and avoid using $self->layer->flow at all here because it's too general
2012-06-28 12:44:54 +00:00
has 'shift_x' = > ( is = > 'rw' , default = > sub { 0 } ) ;
has 'shift_y' = > ( is = > 'rw' , default = > sub { 0 } ) ;
2012-10-28 18:24:24 +00:00
has 'z' = > ( is = > 'rw' ) ;
2012-06-28 12:44:54 +00:00
has 'speed' = > ( is = > 'rw' ) ;
2012-09-23 00:40:25 +00:00
has 'extruder' = > ( is = > 'rw' ) ;
2012-06-28 12:44:54 +00:00
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 } ) ;
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_fan_speed' = > ( is = > 'rw' , default = > sub { 0 } ) ;
2012-10-28 18:15:34 +00:00
has 'last_path' = > ( is = > 'rw' ) ;
2012-06-28 12:44:54 +00:00
has 'dec' = > ( is = > 'ro' , default = > sub { 3 } ) ;
# calculate speeds (mm/min)
has 'speeds' = > (
is = > 'ro' ,
default = > sub { {
2012-07-27 19:13:03 +00:00
travel = > 60 * $ Slic3r:: Config - > get_value ( 'travel_speed' ) ,
perimeter = > 60 * $ Slic3r:: Config - > get_value ( 'perimeter_speed' ) ,
small_perimeter = > 60 * $ Slic3r:: Config - > get_value ( 'small_perimeter_speed' ) ,
external_perimeter = > 60 * $ Slic3r:: Config - > get_value ( 'external_perimeter_speed' ) ,
infill = > 60 * $ Slic3r:: Config - > get_value ( 'infill_speed' ) ,
solid_infill = > 60 * $ Slic3r:: Config - > get_value ( 'solid_infill_speed' ) ,
top_solid_infill = > 60 * $ Slic3r:: Config - > get_value ( 'top_solid_infill_speed' ) ,
bridge = > 60 * $ Slic3r:: Config - > get_value ( 'bridge_speed' ) ,
2012-06-28 12:44:54 +00:00
} } ,
) ;
my % role_speeds = (
& EXTR_ROLE_PERIMETER = > 'perimeter' ,
& EXTR_ROLE_SMALLPERIMETER = > 'small_perimeter' ,
& EXTR_ROLE_EXTERNAL_PERIMETER = > 'external_perimeter' ,
& EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER = > 'perimeter' ,
& 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_SUPPORTMATERIAL = > 'perimeter' ,
) ;
sub change_layer {
my $ self = shift ;
2012-10-28 15:59:20 +00:00
my ( $ layer , % params ) = @ _ ;
2012-06-28 12:44:54 +00:00
$ self - > layer ( $ layer ) ;
my $ gcode = "" ;
2012-10-28 15:59:20 +00:00
$ gcode . = $ self - > move_z ( $ layer - > print_z ) unless $ params { dont_move_z } ;
2012-06-28 12:44:54 +00:00
2012-07-27 19:13:03 +00:00
$ gcode . = $ Slic3r:: Config - > replace_options ( $ Slic3r:: Config - > layer_gcode ) . "\n"
if $ Slic3r:: Config - > layer_gcode ;
2012-06-28 12:44:54 +00:00
return $ gcode ;
}
2012-10-28 15:59:20 +00:00
# this method accepts Z in scaled coordinates
sub move_z {
my $ self = shift ;
my ( $ z , $ comment ) = @ _ ;
2012-10-29 18:54:04 +00:00
$ z = $ z * & Slic3r:: SCALING_FACTOR ;
2012-10-28 15:59:20 +00:00
my $ gcode = "" ;
$ gcode . = $ self - > retract ( move_z = > $ z ) ;
$ gcode . = $ self - > G0 ( undef , $ z , 0 , $ comment || 'move to next layer (' . $ self - > layer - > id . ')' )
2012-10-28 18:24:24 +00:00
if ( ! defined $ self - > z || $ self - > z != $ z ) && ! $ self - > lifted ;
2012-10-28 15:59:20 +00:00
return $ gcode ;
}
2012-06-28 12:44:54 +00:00
sub extrude {
my $ self = shift ;
2012-07-23 15:51:04 +00:00
( $ _ [ 0 ] - > isa ( 'Slic3r::ExtrusionLoop' ) || $ _ [ 0 ] - > isa ( 'Slic3r::ExtrusionLoop::Packed' ) )
2012-07-20 12:39:07 +00:00
? $ self - > extrude_loop ( @ _ )
: $ self - > extrude_path ( @ _ ) ;
2012-06-28 12:44:54 +00:00
}
sub extrude_loop {
my $ self = shift ;
my ( $ loop , $ description ) = @ _ ;
# extrude all loops ccw
2012-07-23 15:56:20 +00:00
$ loop = $ loop - > unpack if $ loop - > isa ( 'Slic3r::ExtrusionLoop::Packed' ) ;
2012-06-28 12:44:54 +00:00
$ loop - > polygon - > make_counter_clockwise ;
# find the point of the loop that is closest to the current extruder position
# or randomize if requested
my $ last_pos = $ self - > last_pos ;
2012-07-27 19:13:03 +00:00
if ( $ Slic3r:: Config - > randomize_start && $ loop - > role == EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER ) {
$ last_pos = Slic3r::Point - > new ( scale $ Slic3r:: Config - > print_center - > [ X ] , scale $ Slic3r:: Config - > bed_size - > [ Y ] ) ;
$ last_pos - > rotate ( rand ( 2 * PI ) , $ Slic3r:: Config - > print_center ) ;
2012-06-28 12:44:54 +00:00
}
2012-07-02 19:26:56 +00:00
my $ start_index = $ loop - > nearest_point_index_to ( $ last_pos ) ;
2012-06-28 12:44:54 +00:00
# split the loop at the starting point and make a path
2012-07-02 19:26:56 +00:00
my $ extrusion_path = $ loop - > split_at_index ( $ start_index ) ;
2012-06-28 12:44:54 +00:00
# clip the path to avoid the extruder to get exactly on the first point of the loop;
# if polyline was shorter than the clipping distance we'd get a null polyline, so
# we discard it in that case
2012-10-29 10:20:27 +00:00
$ extrusion_path - > clip_end ( ( $ self - > layer ? $ self - > layer - > flow - > scaled_width : $ Slic3r:: flow - > scaled_width ) * & Slic3r:: LOOP_CLIPPING_LENGTH_OVER_WIDTH ) ;
2012-06-28 12:44:54 +00:00
return '' if ! @ { $ extrusion_path - > polyline } ;
# extrude along the path
return $ self - > extrude_path ( $ extrusion_path , $ description ) ;
}
sub extrude_path {
my $ self = shift ;
my ( $ path , $ description , $ recursive ) = @ _ ;
2012-07-20 12:39:07 +00:00
$ path = $ path - > unpack if $ path - > isa ( 'Slic3r::ExtrusionPath::Packed' ) ;
2012-06-28 12:44:54 +00:00
$ path - > merge_continuous_lines ;
# detect arcs
2012-07-27 19:13:03 +00:00
if ( $ Slic3r:: Config - > gcode_arcs && ! $ recursive ) {
2012-06-28 12:44:54 +00:00
my $ gcode = "" ;
foreach my $ arc_path ( $ path - > detect_arcs ) {
$ gcode . = $ self - > extrude_path ( $ arc_path , $ description , 1 ) ;
}
return $ gcode ;
}
my $ gcode = "" ;
# retract if distance from previous position is greater or equal to the one
2012-08-25 14:30:11 +00:00
# specified by the user
2012-06-28 12:44:54 +00:00
{
2012-08-25 14:30:11 +00:00
my $ travel = Slic3r::Line - > new ( $ self - > last_pos , $ path - > points - > [ 0 ] ) ;
if ( $ travel - > length >= scale $ self - > extruder - > retract_before_travel ) {
2012-09-23 16:07:44 +00:00
if ( ! $ Slic3r:: Config - > only_retract_when_crossing_perimeters || $ path - > role != EXTR_ROLE_FILL || ! first { $ _ - > encloses_line ( $ travel , scaled_epsilon ) } @ { $ self - > layer - > slices } ) {
2012-10-28 18:15:34 +00:00
if ( $ self - > last_path && $ self - > last_path - > role == & EXTR_ROLE_EXTERNAL_PERIMETER ) {
my @ lines = $ self - > last_path - > lines ;
my $ last_line = $ lines [ - 1 ] ;
if ( points_coincide ( $ last_line - > [ B ] , $ self - > last_pos ) ) {
my $ point = Slic3r::Geometry:: point_along_segment ( @$ last_line , $ last_line - > length + scale $ self - > layer - > flow - > spacing ) ;
bless $ point , 'Slic3r::Point' ;
2012-10-29 10:21:41 +00:00
$ point - > rotate ( PI / 6 , $ last_line - > [ B ] ) ;
2012-10-28 18:15:34 +00:00
$ gcode . = $ self - > G0 ( $ point , undef , 0 , "move inwards before travel" ) ;
}
}
2012-08-25 14:30:11 +00:00
$ gcode . = $ self - > retract ( travel_to = > $ path - > points - > [ 0 ] ) ;
}
2012-06-28 12:44:54 +00:00
}
}
# go to first point of extrusion path
$ gcode . = $ self - > G0 ( $ path - > points - > [ 0 ] , undef , 0 , "move to first $description point" )
if ! points_coincide ( $ self - > last_pos , $ path - > points - > [ 0 ] ) ;
# compensate retraction
2012-08-22 16:57:03 +00:00
$ gcode . = $ self - > unretract if $ self - > extruder - > retracted ;
2012-06-28 12:44:54 +00:00
2012-07-03 16:05:31 +00:00
my $ area ; # mm^3 of extrudate per mm of tool movement
2012-06-28 12:44:54 +00:00
if ( $ path - > role == EXTR_ROLE_BRIDGE ) {
2012-07-03 16:05:31 +00:00
my $ s = $ path - > flow_spacing || $ self - > extruder - > nozzle_diameter ;
2012-06-28 12:44:54 +00:00
$ area = ( $ s ** 2 ) * PI / 4 ;
} else {
2012-07-03 16:05:31 +00:00
my $ s = $ path - > flow_spacing || ( $ self - > layer ? $ self - > layer - > flow - > spacing : $ Slic3r:: flow - > spacing ) ;
2012-10-28 13:22:51 +00:00
my $ h = $ path - > height // $ self - > layer - > height ;
2012-07-03 16:05:31 +00:00
$ area = $ self - > extruder - > mm3_per_mm ( $ s , $ h ) ;
2012-06-28 12:44:54 +00:00
}
2012-07-03 16:05:31 +00:00
# calculate extrusion length per distance unit
2012-07-02 15:09:09 +00:00
my $ e = $ self - > extruder - > e_per_mm3 * $ area ;
2012-06-28 12:44:54 +00:00
# extrude arc or line
$ self - > speed ( $ role_speeds { $ path - > role } || die "Unknown role: " . $ path - > role ) ;
my $ path_length = 0 ;
if ( $ path - > isa ( 'Slic3r::ExtrusionPath::Arc' ) ) {
$ path_length = $ path - > length ;
$ gcode . = $ self - > G2_G3 ( $ path - > points - > [ - 1 ] , $ path - > orientation ,
2012-07-03 16:05:31 +00:00
$ path - > center , $ e * unscale $ path_length , $ description ) ;
2012-06-28 12:44:54 +00:00
} else {
foreach my $ line ( $ path - > lines ) {
my $ line_length = $ line - > length ;
$ path_length += $ line_length ;
2012-07-03 16:05:31 +00:00
$ gcode . = $ self - > G1 ( $ line - > b , undef , $ e * unscale $ line_length , $ description ) ;
2012-06-28 12:44:54 +00:00
}
}
2012-07-27 19:13:03 +00:00
if ( $ Slic3r:: Config - > cooling ) {
2012-06-28 12:44:54 +00:00
my $ path_time = unscale ( $ path_length ) / $ self - > speeds - > { $ self - > last_speed } * 60 ;
if ( $ self - > layer - > id == 0 ) {
2012-07-27 19:13:03 +00:00
$ path_time = $ Slic3r:: Config - > first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/
2012-06-28 12:44:54 +00:00
? $ path_time / ($1/ 100 )
2012-07-27 19:13:03 +00:00
: unscale ( $ path_length ) / $ Slic3r:: Config - > first_layer_speed * 60 ;
2012-06-28 12:44:54 +00:00
}
$ self - > elapsed_time ( $ self - > elapsed_time + $ path_time ) ;
}
2012-10-28 18:15:34 +00:00
$ self - > last_path ( $ path ) ;
2012-06-28 12:44:54 +00:00
return $ gcode ;
}
sub retract {
my $ self = shift ;
my % params = @ _ ;
2012-08-22 18:31:03 +00:00
# get the retraction length and abort if none
my ( $ length , $ restart_extra , $ comment ) = $ params { toolchange }
? ( $ self - > extruder - > retract_length_toolchange , $ self - > extruder - > retract_restart_extra_toolchange , "retract for tool change" )
: ( $ self - > extruder - > retract_length , $ self - > extruder - > retract_restart_extra , "retract" ) ;
2012-08-22 17:11:45 +00:00
2012-08-22 18:31:03 +00:00
# if we already retracted, reduce the required amount of retraction
$ length -= $ self - > extruder - > retracted ;
return "" unless $ length > 0 ;
2012-06-28 12:44:54 +00:00
# prepare moves
$ self - > speed ( 'retract' ) ;
2012-08-22 18:31:03 +00:00
my $ retract = [ undef , undef , - $ length , $ comment ] ;
2012-08-07 19:08:56 +00:00
my $ lift = ( $ self - > extruder - > retract_lift == 0 || defined $ params { move_z } )
2012-06-28 12:44:54 +00:00
? undef
2012-08-07 19:08:56 +00:00
: [ undef , $ self - > z + $ self - > extruder - > retract_lift , 0 , 'lift plate during retraction' ] ;
2012-06-28 12:44:54 +00:00
my $ gcode = "" ;
2012-07-27 19:13:03 +00:00
if ( ( $ Slic3r:: Config - > g0 || $ Slic3r:: Config - > gcode_flavor eq 'mach3' ) && $ params { travel_to } ) {
2012-06-28 12:44:54 +00:00
if ( $ lift ) {
# combine lift and retract
$ lift - > [ 2 ] = $ retract - > [ 2 ] ;
$ gcode . = $ self - > G0 ( @$ lift ) ;
} else {
# combine travel and retract
2012-08-22 18:31:03 +00:00
my $ travel = [ $ params { travel_to } , undef , $ retract - > [ 2 ] , "travel and $comment" ] ;
2012-06-28 12:44:54 +00:00
$ gcode . = $ self - > G0 ( @$ travel ) ;
}
2012-07-27 19:13:03 +00:00
} elsif ( ( $ Slic3r:: Config - > g0 || $ Slic3r:: Config - > gcode_flavor eq 'mach3' ) && defined $ params { move_z } ) {
2012-06-28 12:44:54 +00:00
# combine Z change and retraction
2012-08-22 18:31:03 +00:00
my $ travel = [ undef , $ params { move_z } , $ retract - > [ 2 ] , "change layer and $comment" ] ;
2012-06-28 12:44:54 +00:00
$ gcode . = $ self - > G0 ( @$ travel ) ;
} else {
$ gcode . = $ self - > G1 ( @$ retract ) ;
2012-08-07 19:08:56 +00:00
if ( defined $ params { move_z } && $ self - > extruder - > retract_lift > 0 ) {
my $ travel = [ undef , $ params { move_z } + $ self - > extruder - > retract_lift , 0 , 'move to next layer (' . $ self - > layer - > id . ') and lift' ] ;
2012-06-28 12:44:54 +00:00
$ gcode . = $ self - > G0 ( @$ travel ) ;
2012-08-07 19:08:56 +00:00
$ self - > lifted ( $ self - > extruder - > retract_lift ) ;
2012-06-28 12:44:54 +00:00
} elsif ( $ lift ) {
$ gcode . = $ self - > G1 ( @$ lift ) ;
}
}
2012-08-22 18:31:03 +00:00
$ self - > extruder - > retracted ( $ self - > extruder - > retracted + $ length + $ restart_extra ) ;
2012-08-07 19:08:56 +00:00
$ self - > lifted ( $ self - > extruder - > retract_lift ) if $ lift ;
2012-06-28 12:44:54 +00:00
# reset extrusion distance during retracts
# this makes sure we leave sufficient precision in the firmware
2012-07-27 19:13:03 +00:00
$ gcode . = $ self - > reset_e if $ Slic3r:: Config - > gcode_flavor !~ /^(?:mach3|makerbot)$/ ;
2012-06-28 12:44:54 +00:00
return $ gcode ;
}
sub unretract {
my $ self = shift ;
2012-08-22 16:57:03 +00:00
2012-06-28 12:44:54 +00:00
my $ gcode = "" ;
if ( $ self - > lifted ) {
2012-08-07 19:08:56 +00:00
$ gcode . = $ self - > G0 ( undef , $ self - > z - $ self - > lifted , 0 , 'restore layer Z' ) ;
2012-06-28 12:44:54 +00:00
$ self - > lifted ( 0 ) ;
}
$ self - > speed ( 'retract' ) ;
2012-08-22 16:57:03 +00:00
$ gcode . = $ self - > G0 ( undef , undef , $ self - > extruder - > retracted , "compensate retraction" ) ;
$ self - > extruder - > retracted ( 0 ) ;
2012-06-28 12:44:54 +00:00
return $ gcode ;
}
2012-07-06 17:57:58 +00:00
sub reset_e {
my $ self = shift ;
$ self - > extrusion_distance ( 0 ) ;
2012-07-27 19:13:03 +00:00
return sprintf "G92 %s0%s\n" , $ Slic3r:: Config - > extrusion_axis , ( $ Slic3r:: Config - > gcode_comments ? ' ; reset extrusion distance' : '' )
if $ Slic3r:: Config - > extrusion_axis && ! $ Slic3r:: Config - > use_relative_e_distances ;
2012-07-06 17:57:58 +00:00
}
2012-06-28 12:44:54 +00:00
sub set_acceleration {
my $ self = shift ;
my ( $ acceleration ) = @ _ ;
2012-07-27 19:13:03 +00:00
return "" unless $ Slic3r:: Config - > acceleration ;
2012-06-28 12:44:54 +00:00
return sprintf "M201 E%s%s\n" ,
2012-07-27 19:13:03 +00:00
$ acceleration , ( $ Slic3r:: Config - > gcode_comments ? ' ; adjust acceleration' : '' ) ;
2012-06-28 12:44:54 +00:00
}
sub G0 {
my $ self = shift ;
2012-07-27 19:13:03 +00:00
return $ self - > G1 ( @ _ ) if ! ( $ Slic3r:: Config - > g0 || $ Slic3r:: Config - > gcode_flavor eq 'mach3' ) ;
2012-06-28 12:44:54 +00:00
return $ self - > _G0_G1 ( "G0" , @ _ ) ;
}
sub G1 {
my $ self = shift ;
return $ self - > _G0_G1 ( "G1" , @ _ ) ;
}
sub _G0_G1 {
my $ self = shift ;
my ( $ gcode , $ point , $ z , $ e , $ comment ) = @ _ ;
my $ dec = $ self - > dec ;
if ( $ point ) {
$ gcode . = sprintf " X%.${dec}f Y%.${dec}f" ,
2012-08-07 19:39:45 +00:00
( $ point - > x * & Slic3r:: SCALING_FACTOR ) + $ self - > shift_x - $ self - > extruder - > extruder_offset - > [ X ] ,
( $ point - > y * & Slic3r:: SCALING_FACTOR ) + $ self - > shift_y - $ self - > extruder - > extruder_offset - > [ Y ] ; #**
2012-06-28 12:44:54 +00:00
$ self - > last_pos ( $ point ) ;
}
2012-10-28 18:24:24 +00:00
if ( defined $ z && ( ! defined $ self - > z || $ z != $ self - > z ) ) {
2012-06-28 12:44:54 +00:00
$ self - > z ( $ z ) ;
$ gcode . = sprintf " Z%.${dec}f" , $ z ;
}
return $ self - > _Gx ( $ gcode , $ e , $ comment ) ;
}
sub G2_G3 {
my $ self = shift ;
my ( $ point , $ orientation , $ center , $ e , $ comment ) = @ _ ;
my $ dec = $ self - > dec ;
my $ gcode = $ orientation eq 'cw' ? "G2" : "G3" ;
$ gcode . = sprintf " X%.${dec}f Y%.${dec}f" ,
2012-08-07 19:39:45 +00:00
( $ point - > x * & Slic3r:: SCALING_FACTOR ) + $ self - > shift_x - $ self - > extruder - > extruder_offset - > [ X ] ,
( $ point - > y * & Slic3r:: SCALING_FACTOR ) + $ self - > shift_y - $ self - > extruder - > extruder_offset - > [ Y ] ; #**
2012-06-28 12:44:54 +00:00
# XY distance of the center from the start position
$ gcode . = sprintf " I%.${dec}f J%.${dec}f" ,
2012-07-27 19:13:03 +00:00
( $ center - > [ X ] - $ self - > last_pos - > [ X ] ) * & Slic3r:: SCALING_FACTOR ,
( $ center - > [ Y ] - $ self - > last_pos - > [ Y ] ) * & Slic3r:: SCALING_FACTOR ;
2012-06-28 12:44:54 +00:00
$ self - > last_pos ( $ point ) ;
return $ self - > _Gx ( $ gcode , $ e , $ comment ) ;
}
sub _Gx {
my $ self = shift ;
my ( $ gcode , $ e , $ comment ) = @ _ ;
my $ dec = $ self - > dec ;
# determine speed
my $ speed = ( $ e ? $ self - > speed : 'travel' ) ;
# output speed if it's different from last one used
# (goal: reduce gcode size)
my $ append_bridge_off = 0 ;
if ( $ speed ne $ self - > last_speed ) {
if ( $ speed eq 'bridge' ) {
$ gcode = ";_BRIDGE_FAN_START\n$gcode" ;
} elsif ( $ self - > last_speed eq 'bridge' ) {
$ append_bridge_off = 1 ;
}
# apply the speed reduction for print moves on bottom layer
2012-08-07 19:08:56 +00:00
my $ speed_f = $ speed eq 'retract'
? ( $ self - > extruder - > retract_speed_mm_min )
: $ self - > speeds - > { $ speed } ;
2012-08-22 16:57:03 +00:00
if ( $ e && $ self - > layer && $ self - > layer - > id == 0 && $ comment !~ /retract/ ) {
2012-07-27 19:13:03 +00:00
$ speed_f = $ Slic3r:: Config - > first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/
2012-06-28 12:44:54 +00:00
? ( $ speed_f * $ 1 / 100 )
2012-07-27 19:13:03 +00:00
: $ Slic3r:: Config - > first_layer_speed * 60 ;
2012-06-28 12:44:54 +00:00
}
$ gcode . = sprintf " F%.${dec}f" , $ speed_f ;
$ self - > last_speed ( $ speed ) ;
}
# output extrusion distance
2012-07-27 19:13:03 +00:00
if ( $ e && $ Slic3r:: Config - > extrusion_axis ) {
$ self - > extrusion_distance ( 0 ) if $ Slic3r:: Config - > use_relative_e_distances ;
2012-06-28 12:44:54 +00:00
$ self - > extrusion_distance ( $ self - > extrusion_distance + $ e ) ;
$ self - > total_extrusion_length ( $ self - > total_extrusion_length + $ e ) ;
2012-07-27 19:13:03 +00:00
$ gcode . = sprintf " %s%.5f" , $ Slic3r:: Config - > extrusion_axis , $ self - > extrusion_distance ;
2012-06-28 12:44:54 +00:00
}
2012-07-27 19:13:03 +00:00
$ gcode . = sprintf " ; %s" , $ comment if $ comment && $ Slic3r:: Config - > gcode_comments ;
2012-06-28 12:44:54 +00:00
if ( $ append_bridge_off ) {
$ gcode . = "\n;_BRIDGE_FAN_END" ;
}
return "$gcode\n" ;
}
2012-09-23 00:40:25 +00:00
sub set_extruder {
2012-06-28 12:44:54 +00:00
my $ self = shift ;
2012-09-23 00:40:25 +00:00
my ( $ extruder ) = @ _ ;
2012-06-28 12:44:54 +00:00
2012-09-23 00:40:25 +00:00
# return nothing if this extruder was already selected
2012-10-25 16:49:59 +00:00
return "" if ( defined $ self - > extruder ) && ( $ self - > extruder - > id == $ extruder - > id ) ;
2012-08-22 17:47:59 +00:00
# if we are running a single-extruder setup, just set the extruder and return nothing
2012-09-23 00:40:25 +00:00
if ( ! $ self - > multiple_extruders ) {
$ self - > extruder ( $ extruder ) ;
2012-08-22 17:47:59 +00:00
return "" ;
}
2012-09-23 00:40:25 +00:00
# trigger retraction on the current extruder (if any)
2012-08-22 17:47:59 +00:00
my $ gcode = "" ;
2012-09-23 00:40:25 +00:00
$ gcode . = $ self - > retract ( toolchange = > 1 ) if defined $ self - > extruder ;
2012-08-22 17:47:59 +00:00
2012-09-23 00:40:25 +00:00
# set the new extruder
$ self - > extruder ( $ extruder ) ;
2012-10-01 16:22:35 +00:00
$ gcode . = sprintf "T%d%s\n" , $ extruder - > id , ( $ Slic3r:: Config - > gcode_comments ? ' ; change extruder' : '' ) ;
2012-08-22 17:47:59 +00:00
$ gcode . = $ self - > reset_e ;
2012-08-22 17:20:34 +00:00
2012-08-22 17:47:59 +00:00
return $ gcode ;
2012-06-28 12:44:54 +00:00
}
sub set_fan {
my $ self = shift ;
my ( $ speed , $ dont_save ) = @ _ ;
if ( $ self - > last_fan_speed != $ speed || $ dont_save ) {
$ self - > last_fan_speed ( $ speed ) if ! $ dont_save ;
if ( $ speed == 0 ) {
2012-07-27 19:13:03 +00:00
return sprintf "M107%s\n" , ( $ Slic3r:: Config - > gcode_comments ? ' ; disable fan' : '' ) ;
2012-06-28 12:44:54 +00:00
} else {
2012-07-27 19:13:03 +00:00
return sprintf "M106 %s%d%s\n" , ( $ Slic3r:: Config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) ,
( 255 * $ speed / 100 ) , ( $ Slic3r:: Config - > gcode_comments ? ' ; enable fan' : '' ) ;
2012-06-28 12:44:54 +00:00
}
}
return "" ;
}
sub set_temperature {
my $ self = shift ;
2012-06-28 14:22:11 +00:00
my ( $ temperature , $ wait , $ tool ) = @ _ ;
2012-06-28 12:44:54 +00:00
2012-07-27 19:13:03 +00:00
return "" if $ wait && $ Slic3r:: Config - > gcode_flavor eq 'makerbot' ;
2012-06-28 12:44:54 +00:00
2012-08-30 21:13:28 +00:00
my ( $ code , $ comment ) = ( $ wait && $ Slic3r:: Config - > gcode_flavor ne 'teacup' )
2012-06-28 12:44:54 +00:00
? ( 'M109' , 'wait for temperature to be reached' )
: ( 'M104' , 'set temperature' ) ;
2012-08-30 21:13:28 +00:00
my $ gcode = sprintf "$code %s%d %s; $comment\n" ,
2012-07-27 19:13:03 +00:00
( $ Slic3r:: Config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ,
2012-10-21 19:44:06 +00:00
( defined $ tool && $ self - > multiple_extruders ) ? "T$tool " : "" ;
2012-08-30 21:13:28 +00:00
$ gcode . = "M116 ; wait for temperature to be reached\n"
if $ Slic3r:: Config - > gcode_flavor eq 'teacup' && $ wait ;
return $ gcode ;
2012-06-28 12:44:54 +00:00
}
sub set_bed_temperature {
my $ self = shift ;
my ( $ temperature , $ wait ) = @ _ ;
2012-08-30 21:13:28 +00:00
my ( $ code , $ comment ) = ( $ wait && $ Slic3r:: Config - > gcode_flavor ne 'teacup' )
2012-07-27 19:13:03 +00:00
? ( ( $ Slic3r:: Config - > gcode_flavor eq 'makerbot' ? 'M109'
2012-07-10 17:31:09 +00:00
: 'M190' ) , 'wait for bed temperature to be reached' )
2012-06-28 12:44:54 +00:00
: ( 'M140' , 'set bed temperature' ) ;
2012-08-30 21:13:28 +00:00
my $ gcode = sprintf "$code %s%d ; $comment\n" ,
2012-07-27 19:13:03 +00:00
( $ Slic3r:: Config - > gcode_flavor eq 'mach3' ? 'P' : 'S' ) , $ temperature ;
2012-08-30 21:13:28 +00:00
$ gcode . = "M116 ; wait for bed temperature to be reached\n"
if $ Slic3r:: Config - > gcode_flavor eq 'teacup' && $ wait ;
return $ gcode ;
2012-06-28 12:44:54 +00:00
}
1 ;