2011-10-03 11:55:32 +02:00
package Slic3r::Config ;
use strict ;
use warnings ;
2011-10-09 22:29:13 +02:00
use utf8 ;
2011-10-03 11:55:32 +02:00
use constant PI => 4 * atan2 ( 1 , 1 );
2012-04-11 15:58:09 +02:00
# cemetery of old config settings
2012-06-28 16:22:11 +02:00
our @Ignore = qw(duplicate_x duplicate_y multiply_x multiply_y support_material_tool) ;
2012-04-11 15:58:09 +02:00
2011-10-05 18:13:47 +02:00
our $Options = {
2012-02-05 20:55:17 +01:00
# miscellaneous options
'notes' => {
2012-03-03 22:53:12 +01:00
label => 'Configuration notes' ,
2012-03-06 14:55:21 +11:00
cli => 'notes=s' ,
2012-02-05 20:55:17 +01:00
type => 's' ,
multiline => 1 ,
2012-06-23 22:43:23 +02:00
width => 400 ,
height => 100 ,
2012-02-05 20:55:17 +01:00
serialize => sub { join '\n' , split /\R/ , $_ [ 0 ] },
deserialize => sub { join "\n" , split /\\n/ , $_ [ 0 ] },
},
2012-05-19 15:08:32 +02:00
'threads' => {
label => 'Threads (more speed, more memory usage)' ,
cli => 'threads|j=i' ,
type => 'i' ,
},
2012-02-05 20:55:17 +01:00
2011-12-26 04:20:45 -05:00
# output options
'output_filename_format' => {
label => 'Output filename format' ,
2011-12-26 17:20:26 +01:00
cli => 'output-filename-format=s' ,
2011-12-26 04:20:45 -05:00
type => 's' ,
},
2011-10-05 18:13:47 +02:00
# printer options
'print_center' => {
2012-02-12 22:42:03 +01:00
label => 'Print center (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'print-center=s' ,
2011-10-05 18:13:47 +02:00
type => 'point' ,
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
},
2012-02-20 11:44:30 +01:00
'gcode_flavor' => {
label => 'G-code flavor' ,
cli => 'gcode-flavor=s' ,
type => 'select' ,
values => [ qw(reprap teacup makerbot mach3 no-extrusion) ],
labels => [ 'RepRap (Marlin/Sprinter)' , 'Teacup' , 'MakerBot' , 'Mach3/EMC' , 'No extrusion' ],
},
2011-10-05 18:13:47 +02:00
'use_relative_e_distances' => {
label => 'Use relative E distances' ,
2012-06-18 23:39:53 +02:00
cli => 'use-relative-e-distances!' ,
2011-11-13 18:26:31 +01:00
type => 'bool' ,
},
2011-12-01 22:34:21 +01:00
'extrusion_axis' => {
label => 'Extrusion axis' ,
2012-02-26 11:33:58 +01:00
cli => 'extrusion-axis=s' ,
2011-12-01 22:34:21 +01:00
type => 's' ,
2011-10-05 18:13:47 +02:00
},
'z_offset' => {
2012-02-12 22:42:03 +01:00
label => 'Z offset (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'z-offset=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
2011-12-01 22:03:13 +01:00
'gcode_arcs' => {
2012-03-26 22:33:43 +02:00
label => 'Use native G-code arcs' ,
2012-06-18 23:39:53 +02:00
cli => 'gcode-arcs!' ,
2011-12-01 22:03:13 +01:00
type => 'bool' ,
},
'g0' => {
2012-02-06 21:17:01 +01:00
label => 'Use G0 for travel moves' ,
2012-06-18 23:39:53 +02:00
cli => 'g0!' ,
2011-12-01 22:03:13 +01:00
type => 'bool' ,
},
2011-12-14 19:49:21 +01:00
'gcode_comments' => {
2012-03-03 22:53:12 +01:00
label => 'Verbose G-code' ,
2012-06-18 23:39:53 +02:00
cli => 'gcode-comments!' ,
2011-12-14 19:49:21 +01:00
type => 'bool' ,
},
2011-10-05 18:13:47 +02:00
2012-06-28 14:44:54 +02:00
# extruders options
'nozzle_diameter' => {
label => 'Nozzle diameter (mm)' ,
cli => 'nozzle-diameter=f@' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
2011-12-02 17:02:36 +01:00
important => 1 ,
2012-06-28 14:44:54 +02:00
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
},
'filament_diameter' => {
label => 'Diameter (mm)' ,
cli => 'filament-diameter=f@' ,
type => 'f' ,
important => 1 ,
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
2011-10-05 18:13:47 +02:00
},
2011-11-25 11:15:20 +01:00
'extrusion_multiplier' => {
label => 'Extrusion multiplier' ,
2012-06-28 14:44:54 +02:00
cli => 'extrusion-multiplier=f@' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
2011-11-25 11:15:20 +01:00
aliases => [ qw(filament_packing_density) ],
2012-06-28 14:44:54 +02:00
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
2011-10-05 18:13:47 +02:00
},
2012-06-28 16:22:11 +02:00
'temperature' => {
label => 'Temperature (°C)' ,
cli => 'temperature=i@' ,
type => 'i' ,
important => 1 ,
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
},
2012-02-26 14:54:38 +01:00
'first_layer_temperature' => {
label => 'First layer temperature (°C)' ,
2012-06-28 16:22:11 +02:00
cli => 'first-layer-temperature=i@' ,
2012-02-26 14:54:38 +01:00
type => 'i' ,
2012-06-28 16:22:11 +02:00
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
2012-02-26 14:54:38 +01:00
},
2012-06-28 16:22:11 +02:00
2012-06-28 16:48:56 +02:00
# extruder mapping
2012-06-30 23:18:15 +01:00
'perimeter_extruder' => {
label => 'Perimeter extruder' ,
cli => 'perimeter-extruder=i' ,
2012-06-28 16:48:56 +02:00
type => 'i' ,
2012-06-30 23:18:15 +01:00
aliases => [ qw(perimeters_extruder) ],
2012-06-28 16:48:56 +02:00
},
'infill_extruder' => {
label => 'Infill extruder' ,
cli => 'infill-extruder=i' ,
type => 'i' ,
},
'support_material_extruder' => {
label => 'Extruder' ,
cli => 'support-material-extruder=i' ,
type => 'i' ,
},
2012-06-28 16:22:11 +02:00
# filament options
2012-03-01 14:08:07 +11:00
'first_layer_bed_temperature' => {
label => 'First layer bed temperature (°C)' ,
cli => 'first-layer-bed-temperature=i' ,
type => 'i' ,
},
'bed_temperature' => {
label => 'Bed Temperature (°C)' ,
cli => 'bed-temperature=i' ,
type => 'i' ,
},
2011-10-05 18:13:47 +02:00
# speed options
2011-12-01 22:03:13 +01:00
'travel_speed' => {
2011-11-28 19:11:26 +01:00
label => 'Travel (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'travel-speed=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
2011-12-01 22:03:13 +01:00
aliases => [ qw(travel_feed_rate) ],
2011-10-05 18:13:47 +02:00
},
2011-12-01 22:03:13 +01:00
'perimeter_speed' => {
2011-11-28 19:11:26 +01:00
label => 'Perimeters (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'perimeter-speed=f' ,
2011-11-28 19:11:26 +01:00
type => 'f' ,
2011-12-01 22:03:13 +01:00
aliases => [ qw(perimeter_feed_rate) ],
2011-11-28 19:11:26 +01:00
},
2011-12-04 20:50:03 +01:00
'small_perimeter_speed' => {
2012-06-06 19:57:16 +02:00
label => 'Small perimeters (mm/s or %)' ,
2012-06-19 11:38:12 +02:00
cli => 'small-perimeter-speed=s' ,
2012-06-27 19:37:34 +02:00
type => 'f' ,
ratio_over => 'perimeter_speed' ,
},
'external_perimeter_speed' => {
label => 'External perimeters (mm/s or %)' ,
cli => 'external-perimeter-speed=s' ,
2011-12-04 20:50:03 +01:00
type => 'f' ,
2012-06-06 19:57:16 +02:00
ratio_over => 'perimeter_speed' ,
2011-12-04 20:50:03 +01:00
},
2011-12-01 22:03:13 +01:00
'infill_speed' => {
2011-11-28 19:11:26 +01:00
label => 'Infill (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'infill-speed=f' ,
2011-11-28 19:11:26 +01:00
type => 'f' ,
2011-12-01 22:03:13 +01:00
aliases => [ qw(print_feed_rate infill_feed_rate) ],
2011-11-28 19:11:26 +01:00
},
2011-12-01 22:03:13 +01:00
'solid_infill_speed' => {
2012-06-06 19:57:16 +02:00
label => 'Solid infill (mm/s or %)' ,
2012-06-19 11:38:12 +02:00
cli => 'solid-infill-speed=s' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
2012-06-06 19:57:16 +02:00
ratio_over => 'infill_speed' ,
2011-12-01 22:03:13 +01:00
aliases => [ qw(solid_infill_feed_rate) ],
2011-10-05 18:13:47 +02:00
},
2012-06-06 19:57:16 +02:00
'top_solid_infill_speed' => {
2012-06-11 13:45:03 +02:00
label => 'Top solid infill (mm/s or %)' ,
2012-06-19 11:38:12 +02:00
cli => 'top-solid-infill-speed=s' ,
2012-06-06 19:57:16 +02:00
type => 'f' ,
ratio_over => 'solid_infill_speed' ,
},
2011-12-01 22:03:13 +01:00
'bridge_speed' => {
2011-11-28 19:11:26 +01:00
label => 'Bridges (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'bridge-speed=f' ,
2011-11-28 18:37:53 +01:00
type => 'f' ,
2011-12-01 22:03:13 +01:00
aliases => [ qw(bridge_feed_rate) ],
2011-11-28 18:37:53 +01:00
},
2012-06-06 15:52:21 +02:00
'first_layer_speed' => {
label => 'First layer speed (mm/s or %)' ,
2012-06-06 17:29:12 +02:00
cli => 'first-layer-speed=s' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
2012-02-10 14:53:44 +01:00
# acceleration options
'acceleration' => {
label => 'Enable acceleration control' ,
2012-06-18 23:39:53 +02:00
cli => 'acceleration!' ,
2012-02-10 14:53:44 +01:00
type => 'bool' ,
},
'perimeter_acceleration' => {
2012-02-18 22:36:13 +01:00
label => 'Perimeters (mm/s²)' ,
2012-02-10 14:53:44 +01:00
cli => 'perimeter-acceleration' ,
type => 'f' ,
},
'infill_acceleration' => {
2012-02-18 22:36:13 +01:00
label => 'Infill (mm/s²)' ,
2012-02-10 14:53:44 +01:00
cli => 'infill-acceleration' ,
type => 'f' ,
},
2011-10-05 18:13:47 +02:00
# accuracy options
'layer_height' => {
label => 'Layer height (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'layer-height=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
2012-06-06 16:11:38 +02:00
'first_layer_height' => {
label => 'First layer height (mm or %)' ,
2012-06-06 17:29:12 +02:00
cli => 'first-layer-height=s' ,
2011-12-07 19:33:59 +01:00
type => 'f' ,
2012-06-06 19:57:16 +02:00
ratio_over => 'layer_height' ,
2011-12-07 19:33:59 +01:00
},
'infill_every_layers' => {
label => 'Infill every N layers' ,
cli => 'infill-every-layers=i' ,
type => 'i' ,
},
# flow options
2012-06-06 15:23:34 +02:00
'extrusion_width' => {
label => 'Extrusion width (mm or %; leave zero to calculate automatically)' ,
2012-06-06 17:29:12 +02:00
cli => 'extrusion-width=s' ,
type => 'f' ,
},
'first_layer_extrusion_width' => {
2012-06-06 18:05:03 +02:00
label => 'First layer extrusion width (mm or % or 0 for default)' ,
2012-06-06 17:29:12 +02:00
cli => 'first-layer-extrusion-width=s' ,
2011-11-25 10:58:13 +01:00
type => 'f' ,
},
2012-06-30 23:18:15 +01:00
'perimeter_extrusion_width' => {
label => 'Perimeter extrusion width (mm or % or 0 for default)' ,
cli => 'perimeter-extrusion-width=s' ,
2012-06-06 18:05:03 +02:00
type => 'f' ,
2012-06-30 23:18:15 +01:00
aliases => [ qw(perimeters_extrusion_width) ],
2012-06-06 18:05:03 +02:00
},
'infill_extrusion_width' => {
label => 'Infill extrusion width (mm or % or 0 for default)' ,
cli => 'infill-extrusion-width=s' ,
type => 'f' ,
},
2012-06-28 16:33:07 +02:00
'support_material_extrusion_width' => {
label => 'Support material extrusion width (mm or % or 0 for default)' ,
cli => 'support-material-extrusion-width=s' ,
type => 'f' ,
},
2011-12-04 20:29:21 +01:00
'bridge_flow_ratio' => {
label => 'Bridge flow ratio' ,
cli => 'bridge-flow-ratio=f' ,
type => 'f' ,
},
2011-10-05 18:13:47 +02:00
# print options
2011-11-17 10:38:23 +01:00
'perimeters' => {
2012-06-23 17:10:30 +02:00
label => 'Perimeters' ,
2011-12-01 22:03:13 +01:00
cli => 'perimeters=i' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
2011-11-17 10:38:23 +01:00
aliases => [ qw(perimeter_offsets) ],
2011-10-05 18:13:47 +02:00
},
'solid_layers' => {
label => 'Solid layers' ,
2011-12-01 22:03:13 +01:00
cli => 'solid-layers=i' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
},
2011-11-13 18:14:02 +01:00
'fill_pattern' => {
label => 'Fill pattern' ,
2011-12-01 22:03:13 +01:00
cli => 'fill-pattern=s' ,
2011-11-13 18:14:02 +01:00
type => 'select' ,
2012-04-16 11:55:14 +02:00
values => [ qw(rectilinear line concentric honeycomb hilbertcurve archimedeanchords octagramspiral) ],
labels => [ qw(rectilinear line concentric honeycomb) , 'hilbertcurve (slow)' , 'archimedeanchords (slow)' , 'octagramspiral (slow)' ],
2011-11-13 18:14:02 +01:00
},
'solid_fill_pattern' => {
label => 'Solid fill pattern' ,
2011-12-01 22:03:13 +01:00
cli => 'solid-fill-pattern=s' ,
2011-11-13 18:14:02 +01:00
type => 'select' ,
2011-11-26 10:38:05 +01:00
values => [ qw(rectilinear concentric hilbertcurve archimedeanchords octagramspiral) ],
2011-11-26 22:41:23 +01:00
labels => [ qw(rectilinear concentric) , 'hilbertcurve (slow)' , 'archimedeanchords (slow)' , 'octagramspiral (slow)' ],
2011-11-13 18:14:02 +01:00
},
2011-10-05 18:13:47 +02:00
'fill_density' => {
label => 'Fill density' ,
2011-12-01 22:03:13 +01:00
cli => 'fill-density=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
'fill_angle' => {
label => 'Fill angle (°)' ,
2011-12-01 22:03:13 +01:00
cli => 'fill-angle=i' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
},
2012-06-23 17:10:30 +02:00
'extra_perimeters' => {
label => 'Generate extra perimeters when needed' ,
cli => 'extra-perimeters!' ,
type => 'bool' ,
},
2012-05-19 22:36:29 +02:00
'randomize_start' => {
label => 'Randomize starting points' ,
2012-06-18 23:39:53 +02:00
cli => 'randomize-start!' ,
2012-05-19 22:36:29 +02:00
type => 'bool' ,
},
2012-02-19 12:03:36 +01:00
'support_material' => {
label => 'Generate support material' ,
2012-06-18 23:39:53 +02:00
cli => 'support-material!' ,
2012-02-19 12:03:36 +01:00
type => 'bool' ,
},
2012-06-23 23:54:39 +02:00
'support_material_threshold' => {
label => 'Overhang threshold (°)' ,
cli => 'support-material-threshold=i' ,
type => 'i' ,
},
2012-06-23 22:43:23 +02:00
'support_material_pattern' => {
label => 'Pattern' ,
cli => 'support-material-pattern=s' ,
type => 'select' ,
values => [ qw(rectilinear honeycomb) ],
labels => [ qw(rectilinear honeycomb) ],
},
2012-06-24 14:39:35 +02:00
'support_material_spacing' => {
label => 'Pattern spacing (mm)' ,
cli => 'support-material-spacing=f' ,
type => 'f' ,
},
2012-06-23 22:43:23 +02:00
'support_material_angle' => {
2012-06-23 23:54:39 +02:00
label => 'Pattern angle (°)' ,
2012-06-23 22:43:23 +02:00
cli => 'support-material-angle=i' ,
type => 'i' ,
},
2011-10-14 16:24:55 +02:00
'start_gcode' => {
2012-03-26 22:33:43 +02:00
label => 'Start G-code' ,
2011-12-01 22:03:13 +01:00
cli => 'start-gcode=s' ,
2011-10-14 16:24:55 +02:00
type => 's' ,
2011-11-13 22:48:21 +01:00
multiline => 1 ,
width => 350 ,
2012-03-26 12:14:15 +02:00
height => 120 ,
2011-10-14 16:24:55 +02:00
serialize => sub { join '\n' , split /\R+/ , $_ [ 0 ] },
deserialize => sub { join "\n" , split /\\n/ , $_ [ 0 ] },
},
'end_gcode' => {
2012-03-26 22:33:43 +02:00
label => 'End G-code' ,
2011-12-01 22:03:13 +01:00
cli => 'end-gcode=s' ,
2011-10-14 16:24:55 +02:00
type => 's' ,
2011-11-13 22:48:21 +01:00
multiline => 1 ,
width => 350 ,
2012-03-26 12:14:15 +02:00
height => 120 ,
serialize => sub { join '\n' , split /\R+/ , $_ [ 0 ] },
deserialize => sub { join "\n" , split /\\n/ , $_ [ 0 ] },
},
'layer_gcode' => {
2012-06-06 17:29:12 +02:00
label => 'Layer change G-code' ,
2012-03-26 12:14:15 +02:00
cli => 'layer-gcode=s' ,
type => 's' ,
multiline => 1 ,
width => 350 ,
height => 50 ,
2011-10-14 16:24:55 +02:00
serialize => sub { join '\n' , split /\R+/ , $_ [ 0 ] },
deserialize => sub { join "\n" , split /\\n/ , $_ [ 0 ] },
},
2012-02-20 12:50:05 +01:00
'post_process' => {
label => 'Post-processing scripts' ,
cli => 'post-process=s@' ,
type => 's@' ,
multiline => 1 ,
width => 350 ,
height => 60 ,
serialize => sub { join '; ' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /\s*;\s*/ , $_ [ 0 ] ] },
},
2011-10-05 18:13:47 +02:00
# retraction options
'retract_length' => {
label => 'Length (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'retract-length=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
'retract_speed' => {
label => 'Speed (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'retract-speed=f' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
},
'retract_restart_extra' => {
label => 'Extra length on restart (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'retract-restart-extra=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
'retract_before_travel' => {
label => 'Minimum travel after retraction (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'retract-before-travel=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
2011-11-07 15:58:47 +01:00
'retract_lift' => {
label => 'Lift Z (mm)' ,
2011-12-01 22:03:13 +01:00
cli => 'retract-lift=f' ,
2011-11-07 15:58:47 +01:00
type => 'f' ,
},
2011-10-05 18:13:47 +02:00
2012-02-25 21:01:00 +01:00
# cooling options
2012-02-25 21:56:36 +01:00
'cooling' => {
label => 'Enable cooling' ,
2012-06-18 23:39:53 +02:00
cli => 'cooling!' ,
2012-02-25 21:56:36 +01:00
type => 'bool' ,
},
2012-02-25 21:01:00 +01:00
'min_fan_speed' => {
label => 'Min fan speed (%)' ,
cli => 'min-fan-speed=i' ,
type => 'i' ,
},
'max_fan_speed' => {
label => 'Max fan speed (%)' ,
cli => 'max-fan-speed=i' ,
type => 'i' ,
},
'bridge_fan_speed' => {
label => 'Bridge fan speed (%)' ,
cli => 'bridge-fan-speed=i' ,
type => 'i' ,
},
'fan_below_layer_time' => {
label => 'Enable fan if layer print time is below (approximate seconds)' ,
cli => 'fan-below-layer-time=i' ,
type => 'i' ,
},
'slowdown_below_layer_time' => {
label => 'Slow down if layer print time is below (approximate seconds)' ,
cli => 'slowdown-below-layer-time=i' ,
type => 'i' ,
},
'min_print_speed' => {
label => 'Min print speed (mm/s)' ,
2012-03-26 15:20:59 +02:00
cli => 'min-print-speed=f' ,
2012-02-25 21:01:00 +01:00
type => 'i' ,
},
'disable_fan_first_layers' => {
label => 'Disable fan for the first N layers' ,
cli => 'disable-fan-first-layers=i' ,
type => 'i' ,
},
2012-03-03 22:21:30 +01:00
'fan_always_on' => {
label => 'Keep fan always on' ,
2012-06-18 23:39:53 +02:00
cli => 'fan-always-on!' ,
2012-03-03 22:21:30 +01:00
type => 'bool' ,
},
2012-02-25 21:01:00 +01:00
2012-06-23 21:31:29 +02:00
# skirt/brim options
2011-10-05 18:13:47 +02:00
'skirts' => {
label => 'Loops' ,
2011-12-01 22:03:13 +01:00
cli => 'skirts=i' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
},
'skirt_distance' => {
label => 'Distance from object (mm)' ,
2012-03-26 15:20:59 +02:00
cli => 'skirt-distance=f' ,
2012-06-23 21:31:29 +02:00
type => 'f' ,
2011-10-05 18:13:47 +02:00
},
2011-11-13 18:41:12 +01:00
'skirt_height' => {
label => 'Skirt height (layers)' ,
2011-12-01 22:03:13 +01:00
cli => 'skirt-height=i' ,
2011-11-13 18:41:12 +01:00
type => 'i' ,
},
2012-06-23 22:27:59 +02:00
'brim_width' => {
label => 'Brim width (mm)' ,
cli => 'brim-width=f' ,
2012-06-23 21:31:29 +02:00
type => 'f' ,
},
2011-10-05 18:13:47 +02:00
# transform options
'scale' => {
label => 'Scale' ,
2011-12-01 22:03:13 +01:00
cli => 'scale=f' ,
2011-10-05 18:13:47 +02:00
type => 'f' ,
},
'rotate' => {
label => 'Rotate (°)' ,
2011-12-01 22:03:13 +01:00
cli => 'rotate=i' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
},
2012-04-11 17:38:56 +02:00
'duplicate_mode' => {
label => 'Duplicate' ,
gui_only => 1 ,
type => 'select' ,
values => [ qw(no autoarrange grid) ],
labels => [ 'No' , 'Autoarrange' , 'Grid' ],
},
2012-03-06 14:55:21 +11:00
'duplicate' => {
2012-04-11 16:30:58 +02:00
label => 'Copies (autoarrange)' ,
2012-03-06 14:55:21 +11:00
cli => 'duplicate=i' ,
type => 'i' ,
},
2012-04-11 16:30:58 +02:00
'bed_size' => {
2012-04-30 14:56:01 +02:00
label => 'Bed size (mm)' ,
2012-04-11 16:30:58 +02:00
cli => 'bed-size=s' ,
type => 'point' ,
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
},
2012-04-11 15:58:09 +02:00
'duplicate_grid' => {
label => 'Copies (grid)' ,
cli => 'duplicate-grid=s' ,
type => 'point' ,
serialize => sub { join ',' , @ { $_ [ 0 ]} },
deserialize => sub { [ split /,/ , $_ [ 0 ] ] },
2011-10-05 18:13:47 +02:00
},
2011-11-07 15:49:07 +01:00
'duplicate_distance' => {
label => 'Distance between copies' ,
2012-03-26 15:20:59 +02:00
cli => 'duplicate-distance=f' ,
2011-10-05 18:13:47 +02:00
type => 'i' ,
2011-11-07 17:16:34 +01:00
aliases => [ qw(multiply_distance) ],
2011-10-05 18:13:47 +02:00
},
2012-05-23 11:47:52 +02:00
# sequential printing options
'complete_objects' => {
label => 'Complete individual objects (watch out for extruder collisions)' ,
2012-06-18 23:39:53 +02:00
cli => 'complete-objects!' ,
2012-05-23 11:47:52 +02:00
type => 'bool' ,
},
'extruder_clearance_radius' => {
label => 'Extruder clearance radius (mm)' ,
cli => 'extruder-clearance-radius=f' ,
type => 'i' ,
},
'extruder_clearance_height' => {
label => 'Extruder clearance height (mm)' ,
cli => 'extruder-clearance-height=f' ,
type => 'i' ,
},
2011-10-05 18:13:47 +02:00
};
sub get {
my $class = @_ == 2 ? shift : undef ;
my ( $opt_key ) = @_ ;
no strict 'refs' ;
2012-06-06 19:57:16 +02:00
my $value = $ { "Slic3r::$opt_key" };
$value = get ( $Options -> { $opt_key }{ ratio_over }) * $1 / 100
if $Options -> { $opt_key }{ ratio_over } && $value =~ /^(\d+(?:\.\d+)?)%$/ ;
return $value ;
2011-10-05 18:13:47 +02:00
}
2012-06-19 15:32:56 +02:00
sub get_raw {
my $class = @_ == 2 ? shift : undef ;
my ( $opt_key ) = @_ ;
no strict 'refs' ;
my $value = $ { "Slic3r::$opt_key" };
return $value ;
}
2011-10-05 18:13:47 +02:00
sub set {
my $class = @_ == 3 ? shift : undef ;
my ( $opt_key , $value ) = @_ ;
no strict 'refs' ;
$ { "Slic3r::$opt_key" } = $value ;
}
2011-12-26 17:20:26 +01:00
sub serialize {
my $class = @_ == 2 ? shift : undef ;
my ( $opt_key ) = @_ ;
return $Options -> { $opt_key }{ serialize }
2012-06-19 15:32:56 +02:00
? $Options -> { $opt_key }{ serialize } -> ( get_raw ( $opt_key ))
: get_raw ( $opt_key );
2011-12-26 17:20:26 +01:00
}
2012-02-20 12:50:05 +01:00
sub deserialize {
my $class = @_ == 3 ? shift : undef ;
my ( $opt_key , $value ) = @_ ;
return $Options -> { $opt_key }{ deserialize }
? set ( $opt_key , $Options -> { $opt_key }{ deserialize } -> ( $value ))
: set ( $opt_key , $value );
}
2011-10-05 18:13:47 +02:00
sub save {
my $class = shift ;
my ( $file ) = @_ ;
open my $fh , '>' , $file ;
2012-02-12 23:33:25 +01:00
binmode $fh , ':utf8' ;
2012-07-01 18:53:01 +02:00
printf $fh "# generated by Slic3r $Slic3r::VERSION\n" ;
2011-10-05 18:13:47 +02:00
foreach my $opt ( sort keys %$Options ) {
2012-04-11 17:38:56 +02:00
next if $Options -> { $opt }{ gui_only };
2012-06-19 15:32:56 +02:00
my $value = get_raw ( $opt );
2011-10-05 18:13:47 +02:00
$value = $Options -> { $opt }{ serialize } -> ( $value ) if $Options -> { $opt }{ serialize };
printf $fh "%s = %s\n" , $opt , $value ;
}
close $fh ;
}
2012-06-09 17:52:03 +02:00
sub setenv {
my $class = shift ;
foreach my $opt ( sort keys %$Options ) {
next if $Options -> { $opt }{ gui_only };
my $value = get ( $opt );
$value = $Options -> { $opt }{ serialize } -> ( $value ) if $Options -> { $opt }{ serialize };
$ENV { "SLIC3R_" . uc $opt } = $value ;
}
}
2011-10-05 18:13:47 +02:00
sub load {
my $class = shift ;
my ( $file ) = @_ ;
2012-04-11 15:58:09 +02:00
my %ignore = map { $_ => 1 } @Ignore ;
2012-01-22 20:10:23 +01:00
local $/ = "\n" ;
2011-10-05 18:13:47 +02:00
open my $fh , '<' , $file ;
2012-02-12 23:33:25 +01:00
binmode $fh , ':utf8' ;
2011-10-05 18:13:47 +02:00
while ( <$fh> ) {
2012-01-22 20:10:23 +01:00
s/\R+$// ;
2011-12-04 20:41:17 +01:00
next if /^\s+/ ;
next if /^$/ ;
2011-10-05 18:13:47 +02:00
next if /^\s*#/ ;
2011-12-01 22:06:07 +01:00
/^(\w+) = (.*)/ or die "Unreadable configuration file (invalid data at line $.)\n" ;
2012-06-06 15:23:34 +02:00
my ( $key , $val ) = ( $1 , $2 );
# handle legacy options
2012-04-11 15:58:09 +02:00
next if $ignore { $key };
2012-06-06 18:47:11 +02:00
if ( $key =~ /^(extrusion_width|bottom_layer_speed|first_layer_height)_ratio$/ ) {
2012-06-06 15:48:14 +02:00
$key = $1 ;
2012-06-06 15:52:21 +02:00
$key =~ s/^bottom_layer_speed$/first_layer_speed/ ;
2012-06-07 11:24:45 +02:00
$val = $val =~ /^\d+(?:\.\d+)?$/ && $val != 0 ? ( $val * 100 ) . "%" : 0 ;
2012-06-06 15:23:34 +02:00
}
2011-11-07 17:16:34 +01:00
if ( ! exists $Options -> { $key }) {
$key = + ( grep { $Options -> { $_ }{ aliases } && grep $_ eq $key , @ { $Options -> { $_ }{ aliases }} }
2012-06-06 15:23:34 +02:00
keys %$Options )[ 0 ] or warn "Unknown option $key at line $.\n" ;
2011-11-07 17:16:34 +01:00
}
2011-12-10 10:39:07 +01:00
next unless $key ;
2011-11-07 17:16:34 +01:00
my $opt = $Options -> { $key };
2012-06-06 15:23:34 +02:00
set ( $key , $opt -> { deserialize } ? $opt -> { deserialize } -> ( $val ) : $val );
2011-10-05 18:13:47 +02:00
}
close $fh ;
}
2011-10-14 16:24:55 +02:00
sub validate_cli {
my $class = shift ;
my ( $opt ) = @_ ;
2012-03-26 12:14:15 +02:00
for ( qw(start end layer) ) {
2011-10-14 16:24:55 +02:00
if ( defined $opt -> { $_ . "_gcode" }) {
if ( $opt -> { $_ . "_gcode" } eq "" ) {
set ( $_ . "_gcode" , "" );
} else {
die "Invalid value for --${_}-gcode: file does not exist"
if !- e $opt -> { $_ . "_gcode" };
open my $fh , "<" , $opt -> { $_ . "_gcode" };
2011-12-01 22:03:13 +01:00
$opt -> { $_ . "_gcode" } = do { local $/ ; <$fh> };
2011-10-14 16:24:55 +02:00
close $fh ;
}
}
}
}
2011-10-03 11:55:32 +02:00
sub validate {
my $class = shift ;
2012-04-10 16:26:56 +02:00
# -j, --threads
die "Invalid value for --threads\n"
2012-05-20 17:21:31 +02:00
if $ Slic3r:: threads < 1 ;
2012-04-10 16:26:56 +02:00
die "Your perl wasn't built with multithread support\n"
2012-05-20 17:21:31 +02:00
if $ Slic3r:: threads > 1 && ! $ Slic3r:: have_threads ;
2011-10-03 11:55:32 +02:00
# --layer-height
die "Invalid value for --layer-height\n"
if $ Slic3r:: layer_height <= 0 ;
die "--layer-height must be a multiple of print resolution\n"
2012-04-16 14:05:38 +02:00
if $ Slic3r:: layer_height / $ Slic3r:: scaling_factor % 1 != 0 ;
2011-10-03 11:55:32 +02:00
2012-06-06 16:11:38 +02:00
# --first-layer-height
die "Invalid value for --first-layer-height\n"
if $ Slic3r:: first_layer_height !~ /^(?:\d+(?:\.\d+)?)%?$/ ;
2012-06-06 19:57:16 +02:00
$ Slic3r:: _first_layer_height = Slic3r::Config -> get ( 'first_layer_height' );
2011-11-13 19:08:19 +01:00
2011-10-03 11:55:32 +02:00
# --filament-diameter
die "Invalid value for --filament-diameter\n"
2012-06-28 14:49:20 +02:00
if grep $_ < 1 , @$ Slic3r:: filament_diameter ;
2011-10-03 11:55:32 +02:00
# --nozzle-diameter
die "Invalid value for --nozzle-diameter\n"
2012-06-28 14:44:54 +02:00
if grep $_ < 0 , @$ Slic3r:: nozzle_diameter ;
2011-10-03 11:55:32 +02:00
die "--layer-height can't be greater than --nozzle-diameter\n"
2012-06-28 14:44:54 +02:00
if grep $ Slic3r:: layer_height > $_ , @$ Slic3r:: nozzle_diameter ;
2011-11-13 19:08:19 +01:00
die "First layer height can't be greater than --nozzle-diameter\n"
2012-06-28 14:44:54 +02:00
if grep $ Slic3r:: _first_layer_height > $_ , @$ Slic3r:: nozzle_diameter ;
# initialize extruder(s)
$ Slic3r:: extruders = [] ;
2012-06-30 23:18:15 +01:00
for my $t ( 0 , map $_ - 1 , $ Slic3r:: perimeter_extruder , $ Slic3r:: infill_extruder , $ Slic3r:: support_material_extruder ) {
2012-06-28 16:22:11 +02:00
$ Slic3r:: extruders -> [ $t ] ||= Slic3r::Extruder -> new (
map { $_ => Slic3r::Config -> get ( $_ ) -> [ $t ] // Slic3r::Config -> get ( $_ ) -> [ 0 ] } #/
qw(nozzle_diameter filament_diameter extrusion_multiplier temperature first_layer_temperature)
);
}
2011-10-03 11:55:32 +02:00
2012-06-06 17:29:12 +02:00
# calculate flow
2012-06-28 14:44:54 +02:00
$ Slic3r:: flow = $ Slic3r:: extruders -> [ 0 ] -> make_flow ( width => $ Slic3r:: extrusion_width );
2012-06-07 11:17:35 +02:00
if ( $ Slic3r:: first_layer_extrusion_width ) {
2012-06-28 14:44:54 +02:00
$ Slic3r:: first_layer_flow = $ Slic3r:: extruders -> [ 0 ] -> make_flow (
layer_height => $ Slic3r:: _first_layer_height ,
width => $ Slic3r:: first_layer_extrusion_width ,
);
2012-06-07 11:17:35 +02:00
}
2012-06-30 23:18:15 +01:00
$ Slic3r:: perimeters_flow = $ Slic3r:: extruders -> [ $ Slic3r:: perimeter_extruder - 1 ]
-> make_flow ( width => $ Slic3r:: perimeter_extrusion_width || $ Slic3r:: extrusion_width );
2012-06-28 16:48:56 +02:00
$ Slic3r:: infill_flow = $ Slic3r:: extruders -> [ $ Slic3r:: infill_extruder - 1 ]
-> make_flow ( width => $ Slic3r:: infill_extrusion_width || $ Slic3r:: extrusion_width );
$ Slic3r:: support_material_flow = $ Slic3r:: extruders -> [ $ Slic3r:: support_material_extruder - 1 ]
2012-06-28 16:33:07 +02:00
-> make_flow ( width => $ Slic3r:: support_material_extrusion_width || $ Slic3r:: extrusion_width );
2012-06-27 19:49:53 +02:00
2012-07-03 18:05:31 +02:00
Slic3r:: debugf "Default flow width = %s (spacing = %s)\n" ,
$ Slic3r:: flow -> width , $ Slic3r:: flow -> spacing ;
2012-06-06 17:29:12 +02:00
2011-10-03 11:55:32 +02:00
# --perimeters
die "Invalid value for --perimeters\n"
2012-03-26 11:32:59 +02:00
if $ Slic3r:: perimeters < 0 ;
2011-10-03 11:55:32 +02:00
# --solid-layers
die "Invalid value for --solid-layers\n"
2011-11-30 12:51:34 +11:00
if $ Slic3r:: solid_layers < 0 ;
2011-10-03 11:55:32 +02:00
# --print-center
die "Invalid value for --print-center\n"
if ! ref $ Slic3r:: print_center
&& ( ! $ Slic3r:: print_center || $ Slic3r:: print_center !~ /^\d+,\d+$/ );
2012-04-11 18:18:01 +02:00
$ Slic3r:: print_center = [ split /[,x]/ , $ Slic3r:: print_center ]
2011-10-03 11:55:32 +02:00
if ! ref $ Slic3r:: print_center ;
2011-11-13 18:14:02 +01:00
# --fill-pattern
die "Invalid value for --fill-pattern\n"
if ! exists $ Slic3r::Fill:: FillTypes { $ Slic3r:: fill_pattern };
# --solid-fill-pattern
die "Invalid value for --solid-fill-pattern\n"
if ! exists $ Slic3r::Fill:: FillTypes { $ Slic3r:: solid_fill_pattern };
2011-10-06 15:24:21 +02:00
2011-10-03 11:55:32 +02:00
# --fill-density
die "Invalid value for --fill-density\n"
if $ Slic3r:: fill_density < 0 || $ Slic3r:: fill_density > 1 ;
2011-10-18 15:57:53 +02:00
# --infill-every-layers
die "Invalid value for --infill-every-layers\n"
if $ Slic3r:: infill_every_layers !~ /^\d+$/ || $ Slic3r:: infill_every_layers < 1 ;
2012-06-28 14:44:54 +02:00
# TODO: this check should be limited to the extruder used for infill
2011-10-18 15:57:53 +02:00
die "Maximum infill thickness can't exceed nozzle diameter\n"
2012-06-28 14:44:54 +02:00
if grep $ Slic3r:: infill_every_layers * $ Slic3r:: layer_height > $_ , @$ Slic3r:: nozzle_diameter ;
2011-10-18 15:57:53 +02:00
2011-10-03 11:55:32 +02:00
# --scale
die "Invalid value for --scale\n"
if $ Slic3r:: scale <= 0 ;
2012-04-11 17:52:06 +02:00
# --bed-size
die "Invalid value for --bed-size\n"
if ! ref $ Slic3r:: bed_size
&& ( ! $ Slic3r:: bed_size || $ Slic3r:: bed_size !~ /^\d+,\d+$/ );
2012-04-11 18:18:01 +02:00
$ Slic3r:: bed_size = [ split /[,x]/ , $ Slic3r:: bed_size ]
2012-04-11 17:52:06 +02:00
if ! ref $ Slic3r:: bed_size ;
# --duplicate-grid
die "Invalid value for --duplicate-grid\n"
if ! ref $ Slic3r:: duplicate_grid
&& ( ! $ Slic3r:: duplicate_grid || $ Slic3r:: duplicate_grid !~ /^\d+,\d+$/ );
2012-04-11 18:18:01 +02:00
$ Slic3r:: duplicate_grid = [ split /[,x]/ , $ Slic3r:: duplicate_grid ]
2012-04-11 17:52:06 +02:00
if ! ref $ Slic3r:: duplicate_grid ;
2012-03-06 14:55:21 +11:00
# --duplicate
2012-04-11 15:58:09 +02:00
die "Invalid value for --duplicate or --duplicate-grid\n"
if ! $ Slic3r:: duplicate || $ Slic3r:: duplicate < 1 || ! $ Slic3r:: duplicate_grid
|| ( grep ! $_ , @$ Slic3r:: duplicate_grid );
die "Use either --duplicate or --duplicate-grid (using both doesn't make sense)\n"
if $ Slic3r:: duplicate > 1 && $ Slic3r:: duplicate_grid && ( grep $_ && $_ > 1 , @$ Slic3r:: duplicate_grid );
2012-04-11 17:38:56 +02:00
$ Slic3r:: duplicate_mode = 'autoarrange' if $ Slic3r:: duplicate > 1 ;
$ Slic3r:: duplicate_mode = 'grid' if grep $_ && $_ > 1 , @$ Slic3r:: duplicate_grid ;
2011-10-03 11:55:32 +02:00
2011-11-13 18:41:12 +01:00
# --skirt-height
die "Invalid value for --skirt-height\n"
2011-12-16 09:55:13 +01:00
if $ Slic3r:: skirt_height < 0 ;
2011-11-28 18:37:53 +01:00
2012-02-19 09:32:16 +01:00
# --bridge-flow-ratio
die "Invalid value for --bridge-flow-ratio\n"
if $ Slic3r:: bridge_flow_ratio <= 0 ;
2012-05-23 11:47:52 +02:00
# extruder clearance
die "Invalid value for --extruder-clearance-radius\n"
if $ Slic3r:: extruder_clearance_radius <= 0 ;
die "Invalid value for --extruder-clearance-height\n"
if $ Slic3r:: extruder_clearance_height <= 0 ;
2012-06-28 16:22:11 +02:00
$_ -> first_layer_temperature ( $_ -> temperature ) for grep ! defined $_ -> first_layer_temperature , @$ Slic3r:: extruders ;
$ Slic3r:: first_layer_temperature -> [ $_ ] = $ Slic3r:: extruders -> [ $_ ] -> first_layer_temperature for 0 .. $#$ Slic3r:: extruders ; # this is needed to provide a value to the legacy GUI and for config file re-serialization
2012-03-06 14:55:21 +11:00
$ Slic3r:: first_layer_bed_temperature // = $ Slic3r:: bed_temperature ; #/
2012-02-19 09:32:16 +01:00
2012-02-20 11:44:30 +01:00
# G-code flavors
$ Slic3r:: extrusion_axis = 'A' if $ Slic3r:: gcode_flavor eq 'mach3' ;
2012-04-08 21:27:38 +02:00
$ Slic3r:: extrusion_axis = '' if $ Slic3r:: gcode_flavor eq 'no-extrusion' ;
2012-02-20 11:44:30 +01:00
2011-11-28 18:37:53 +01:00
# legacy with existing config files
2011-12-04 20:50:03 +01:00
$ Slic3r:: small_perimeter_speed ||= $ Slic3r:: perimeter_speed ;
2011-12-01 22:03:13 +01:00
$ Slic3r:: bridge_speed ||= $ Slic3r:: infill_speed ;
$ Slic3r:: solid_infill_speed ||= $ Slic3r:: infill_speed ;
2012-06-06 19:57:16 +02:00
$ Slic3r:: top_solid_infill_speed ||= $ Slic3r:: solid_infill_speed ;
2011-10-03 11:55:32 +02:00
}
2012-03-03 23:29:08 +01:00
sub replace_options {
my $class = shift ;
my ( $string , $more_variables ) = @_ ;
if ( $more_variables ) {
my $variables = join '|' , keys %$more_variables ;
$string =~ s/\[($variables)\]/$more_variables->{$1}/eg ;
}
2012-05-01 15:01:56 +02:00
my @lt = localtime ; $lt [ 5 ] += 1900 ; $lt [ 4 ] += 1 ;
$string =~ s/\[timestamp\]/sprintf '%04d%02d%02d-%02d%02d%02d', @lt[5,4,3,2,1,0]/egx ;
$string =~ s/\[year\]/$lt[5]/eg ;
$string =~ s/\[month\]/$lt[4]/eg ;
$string =~ s/\[day\]/$lt[3]/eg ;
$string =~ s/\[hour\]/$lt[2]/eg ;
$string =~ s/\[minute\]/$lt[1]/eg ;
$string =~ s/\[second\]/$lt[0]/eg ;
$string =~ s/\[version\]/$Slic3r::VERSION/eg ;
2012-03-03 23:29:08 +01:00
# build a regexp to match the available options
my $options = join '|' ,
grep ! $ Slic3r::Config:: Options -> { $_ }{ multiline },
keys %$ Slic3r::Config:: Options ;
# use that regexp to search and replace option names with option values
$string =~ s/\[($options)\]/Slic3r::Config->serialize($1)/eg ;
return $string ;
}
2011-10-03 11:55:32 +02:00
1 ;