Refactored configuration handling.

Slic3r::Config is now an object. Multiple partial config objects are used throughout the codebase as local repositories, then merged and serialized when necessary.
This commit is contained in:
Alessandro Ranellucci 2012-07-27 21:13:03 +02:00
parent f0579e59bd
commit 7e34244b05
23 changed files with 918 additions and 833 deletions

View file

@ -50,153 +50,27 @@ use Slic3r::Surface;
use Slic3r::TriangleMesh; use Slic3r::TriangleMesh;
eval "use Slic3r::Build"; eval "use Slic3r::Build";
our $threads = $have_threads ? 2 : 1; use constant SCALING_FACTOR => 0.000001;
use constant RESOLUTION => 0.01;
use constant OVERLAP_FACTOR => 0.5;
use constant SMALL_PERIMETER_LENGTH => (6.5 / SCALING_FACTOR) * 2 * PI;
# miscellaneous options # The following variables hold the objects used throughout the slicing
our $notes = ''; # process. They should belong to the Print object, but we are keeping
# them here because it makes accessing them slightly faster.
# output options our $Config;
our $output_filename_format = '[input_filename_base].gcode'; our $extruders;
our $post_process = []; our ($flow, $first_layer_flow, $perimeter_flow, $infill_flow, $support_material_flow);
# printer options
our $print_center = [100,100]; # object will be centered around this point
our $z_offset = 0;
our $gcode_flavor = 'reprap';
our $use_relative_e_distances = 0;
our $extrusion_axis = 'E';
our $gcode_arcs = 0;
our $g0 = 0;
our $gcode_comments = 0;
# filament options
our $filament_diameter = [3]; # mm
our $extrusion_multiplier = [1];
our $temperature = [200];
our $first_layer_temperature= [@$temperature];
our $bed_temperature = 0;
our $first_layer_bed_temperature = $bed_temperature;
# extruders
our $extruders = [];
our $nozzle_diameter = [0.5];
# extruder mapping (1-based indexes)
our $perimeter_extruder = 1;
our $infill_extruder = 1;
our $support_material_extruder = 1;
# speed options
our $travel_speed = 130; # mm/s
our $perimeter_speed = 30; # mm/s
our $small_perimeter_speed = 30; # mm/s or %
our $external_perimeter_speed = '100%'; # mm/s or %
our $infill_speed = 60; # mm/s
our $solid_infill_speed = 60; # mm/s or %
our $top_solid_infill_speed = 50; # mm/s or %
our $bridge_speed = 60; # mm/s
our $first_layer_speed = '30%'; # mm/s or %
# acceleration options
our $acceleration = 0;
our $perimeter_acceleration = 25; # mm/s^2
our $infill_acceleration = 50; # mm/s^2
# accuracy options
our $scaling_factor = 0.000001;
our $resolution = 0.01;
our $small_perimeter_length = (6.5 / $scaling_factor)*2*PI;
our $layer_height = 0.4;
our $first_layer_height = '100%'; # mm or %
our $_first_layer_height = undef; # mm (computed)
our $infill_every_layers = 1;
# flow options
our $extrusion_width = 0;
our $first_layer_extrusion_width = '200%';
our $perimeter_extrusion_width = 0;
our $infill_extrusion_width = 0;
our $support_material_extrusion_width = 0;
our $bridge_flow_ratio = 1;
our $overlap_factor = 0.5;
our $flow;
our $first_layer_flow;
our $perimeters_flow;
our $infill_flow;
our $support_material_flow;
# print options
our $perimeters = 3;
our $solid_layers = 3;
our $fill_pattern = 'rectilinear';
our $solid_fill_pattern = 'rectilinear';
our $fill_density = 0.4; # 1 = 100%
our $fill_angle = 45;
our $extra_perimeters = 1;
our $randomize_start = 1;
our $support_material = 0;
our $support_material_threshold = 45;
our $support_material_pattern = 'rectilinear';
our $support_material_spacing = 2.5;
our $support_material_angle = 0;
our $start_gcode = "G28 ; home all axes";
our $end_gcode = <<"END";
M104 S0 ; turn off temperature
G28 X0 ; home X axis
M84 ; disable motors
END
our $layer_gcode = '';
# retraction options
our $retract_length = 1; # mm
our $retract_restart_extra = 0; # mm
our $retract_speed = 30; # mm/s
our $retract_before_travel = 2; # mm
our $retract_lift = 0; # mm
# cooling options
our $cooling = 0;
our $min_fan_speed = 35;
our $max_fan_speed = 100;
our $bridge_fan_speed = 100;
our $fan_below_layer_time = 60;
our $slowdown_below_layer_time = 15;
our $min_print_speed = 10;
our $disable_fan_first_layers = 1;
our $fan_always_on = 0;
# skirt/brim options
our $skirts = 1;
our $skirt_distance = 6; # mm
our $skirt_height = 1; # layers
our $brim_width = 0; # mm
# transform options
our $scale = 1;
our $rotate = 0;
our $duplicate_mode = 'no';
our $duplicate = 1;
our $bed_size = [200,200];
our $duplicate_grid = [1,1];
our $duplicate_distance = 6; # mm
# sequential printing
our $complete_objects = 0;
our $extruder_clearance_radius = 20; # mm
our $extruder_clearance_height = 20; # mm
our $Defaults = Slic3r::Config->current;
our $Settings = { presets => {} }; # application settings
sub parallelize { sub parallelize {
my %params = @_; my %params = @_;
if (!$params{disable} && $Slic3r::have_threads && $Slic3r::threads > 1) { if (!$params{disable} && $Slic3r::have_threads && $Config->threads > 1) {
my $q = Thread::Queue->new; my $q = Thread::Queue->new;
$q->enqueue(@{ $params{items} }, (map undef, 1..$Slic3r::threads)); $q->enqueue(@{ $params{items} }, (map undef, 1..$Config->threads));
my $thread_cb = sub { $params{thread_cb}->($q) }; my $thread_cb = sub { $params{thread_cb}->($q) };
foreach my $th (map threads->create($thread_cb), 1..$Slic3r::threads) { foreach my $th (map threads->create($thread_cb), 1..$Config->threads) {
$params{collect_cb}->($th->join); $params{collect_cb}->($th->join);
} }
} else { } else {

File diff suppressed because it is too large Load diff

View file

@ -62,7 +62,7 @@ sub boost_polygon {
sub offset { sub offset {
my $self = shift; my $self = shift;
my ($distance, $scale, $joinType, $miterLimit) = @_; my ($distance, $scale, $joinType, $miterLimit) = @_;
$scale ||= $Slic3r::scaling_factor * 1000000; $scale ||= &Slic3r::SCALING_FACTOR * 1000000;
$joinType = JT_MITER if !defined $joinType; $joinType = JT_MITER if !defined $joinType;
$miterLimit ||= 2; $miterLimit ||= 2;

View file

@ -29,15 +29,15 @@ sub mm3_per_mm {
my $cache_key = "${s}_${h}"; my $cache_key = "${s}_${h}";
if (!exists $self->_mm3_per_mm_cache->{$cache_key}) { if (!exists $self->_mm3_per_mm_cache->{$cache_key}) {
my $w_threshold = $h + $self->nozzle_diameter; my $w_threshold = $h + $self->nozzle_diameter;
my $s_threshold = $w_threshold - $Slic3r::overlap_factor * ($w_threshold - ($w_threshold - $h * (1 - PI/4))); my $s_threshold = $w_threshold - &Slic3r::OVERLAP_FACTOR * ($w_threshold - ($w_threshold - $h * (1 - PI/4)));
if ($s >= $s_threshold) { if ($s >= $s_threshold) {
# rectangle with semicircles at the ends # rectangle with semicircles at the ends
my $w = $s + $Slic3r::overlap_factor * $h * (1 - PI/4); my $w = $s + &Slic3r::OVERLAP_FACTOR * $h * (1 - PI/4);
$self->_mm3_per_mm_cache->{$cache_key} = $w * $h + ($h**2) / 4 * (PI - 4); $self->_mm3_per_mm_cache->{$cache_key} = $w * $h + ($h**2) / 4 * (PI - 4);
} else { } else {
# rectangle with shrunk semicircles at the ends # rectangle with shrunk semicircles at the ends
my $w = ($s + $self->nozzle_diameter * $Slic3r::overlap_factor * (PI/4 - 1)) / (1 + $Slic3r::overlap_factor * (PI/4 - 1)); my $w = ($s + $self->nozzle_diameter * &Slic3r::OVERLAP_FACTOR * (PI/4 - 1)) / (1 + &Slic3r::OVERLAP_FACTOR * (PI/4 - 1));
$self->_mm3_per_mm_cache->{$cache_key} = $self->nozzle_diameter * $h * (1 - PI/4) + $h * $w * PI/4; $self->_mm3_per_mm_cache->{$cache_key} = $self->nozzle_diameter * $h * (1 - PI/4) + $h * $w * PI/4;
} }
} }

View file

@ -159,7 +159,7 @@ sub detect_arcs {
my ($max_angle, $len_epsilon) = @_; my ($max_angle, $len_epsilon) = @_;
$max_angle = deg2rad($max_angle || 15); $max_angle = deg2rad($max_angle || 15);
$len_epsilon ||= 10 / $Slic3r::scaling_factor; $len_epsilon ||= 10 / &Slic3r::SCALING_FACTOR;
my @points = @{$self->points}; my @points = @{$self->points};
my @paths = (); my @paths = ();

View file

@ -39,7 +39,7 @@ sub BUILD {
my $max_print_dimension = ($print_size->[X] > $print_size->[Y] ? $print_size->[X] : $print_size->[Y]) * sqrt(2); my $max_print_dimension = ($print_size->[X] > $print_size->[Y] ? $print_size->[X] : $print_size->[Y]) * sqrt(2);
$self->max_print_dimension($max_print_dimension); $self->max_print_dimension($max_print_dimension);
$self->filler($_) for ('rectilinear', $Slic3r::fill_pattern, $Slic3r::solid_fill_pattern); $self->filler($_) for ('rectilinear', $Slic3r::Config->fill_pattern, $Slic3r::Config->solid_fill_pattern);
} }
sub filler { sub filler {
@ -131,8 +131,8 @@ sub make_fill {
my @fills = (); my @fills = ();
my @fills_ordering_points = (); my @fills_ordering_points = ();
SURFACE: foreach my $surface (@surfaces) { SURFACE: foreach my $surface (@surfaces) {
my $filler = $Slic3r::fill_pattern; my $filler = $Slic3r::Config->fill_pattern;
my $density = $Slic3r::fill_density; my $density = $Slic3r::Config->fill_density;
my $flow_spacing = $layer->infill_flow->spacing; my $flow_spacing = $layer->infill_flow->spacing;
my $is_bridge = $layer->id > 0 && $surface->surface_type == S_TYPE_BOTTOM; my $is_bridge = $layer->id > 0 && $surface->surface_type == S_TYPE_BOTTOM;
my $is_solid = (grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID) ? 1 : 0; my $is_solid = (grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID) ? 1 : 0;
@ -140,10 +140,10 @@ sub make_fill {
# force 100% density and rectilinear fill for external surfaces # force 100% density and rectilinear fill for external surfaces
if ($surface->surface_type != S_TYPE_INTERNAL) { if ($surface->surface_type != S_TYPE_INTERNAL) {
$density = 1; $density = 1;
$filler = $Slic3r::solid_fill_pattern; $filler = $Slic3r::Config->solid_fill_pattern;
if ($is_bridge) { if ($is_bridge) {
$filler = 'rectilinear'; $filler = 'rectilinear';
$flow_spacing = sqrt($Slic3r::bridge_flow_ratio * ($layer->infill_flow->nozzle_diameter**2)); $flow_spacing = sqrt($Slic3r::Config->bridge_flow_ratio * ($layer->infill_flow->nozzle_diameter**2));
} elsif ($surface->surface_type == S_TYPE_INTERNALSOLID) { } elsif ($surface->surface_type == S_TYPE_INTERNALSOLID) {
$filler = 'rectilinear'; $filler = 'rectilinear';
} }
@ -181,7 +181,7 @@ sub make_fill {
{ {
my %args = ( my %args = (
role => EXTR_ROLE_SOLIDFILL, role => EXTR_ROLE_SOLIDFILL,
flow_spacing => $layer->perimeters_flow->spacing, flow_spacing => $layer->perimeter_flow->spacing,
); );
push @fills, map { push @fills, map {
$_->isa('Slic3r::Polygon') $_->isa('Slic3r::Polygon')

View file

@ -5,7 +5,7 @@ use Moo;
has 'print' => (is => 'rw'); has 'print' => (is => 'rw');
has 'layer' => (is => 'rw'); has 'layer' => (is => 'rw');
has 'max_print_dimension' => (is => 'rw'); has 'max_print_dimension' => (is => 'rw');
has 'angle' => (is => 'rw', default => sub { $Slic3r::fill_angle }); has 'angle' => (is => 'rw', default => sub { $Slic3r::Config->fill_angle });
use constant PI => 4 * atan2(1, 1); use constant PI => 4 * atan2(1, 1);

View file

@ -4,7 +4,7 @@ use Moo;
use Slic3r::Geometry qw(PI); use Slic3r::Geometry qw(PI);
has 'nozzle_diameter' => (is => 'ro', required => 1); has 'nozzle_diameter' => (is => 'ro', required => 1);
has 'layer_height' => (is => 'ro', default => sub { $Slic3r::layer_height }); has 'layer_height' => (is => 'ro', default => sub { $Slic3r::Config->layer_height });
has 'width' => (is => 'rwp', builder => 1); has 'width' => (is => 'rwp', builder => 1);
has 'spacing' => (is => 'lazy'); has 'spacing' => (is => 'lazy');
@ -52,7 +52,7 @@ sub _build_spacing {
# rectangle with shrunk semicircles at the ends # rectangle with shrunk semicircles at the ends
$min_flow_spacing = $self->nozzle_diameter * (1 - PI/4) + $self->width * PI/4; $min_flow_spacing = $self->nozzle_diameter * (1 - PI/4) + $self->width * PI/4;
} }
return $self->width - $Slic3r::overlap_factor * ($self->width - $min_flow_spacing); return $self->width - &Slic3r::OVERLAP_FACTOR * ($self->width - $min_flow_spacing);
} }
1; 1;

View file

@ -25,15 +25,15 @@ has 'dec' => (is => 'ro', default => sub { 3 } );
has 'speeds' => ( has 'speeds' => (
is => 'ro', is => 'ro',
default => sub {{ default => sub {{
travel => 60 * Slic3r::Config->get('travel_speed'), travel => 60 * $Slic3r::Config->get_value('travel_speed'),
perimeter => 60 * Slic3r::Config->get('perimeter_speed'), perimeter => 60 * $Slic3r::Config->get_value('perimeter_speed'),
small_perimeter => 60 * Slic3r::Config->get('small_perimeter_speed'), small_perimeter => 60 * $Slic3r::Config->get_value('small_perimeter_speed'),
external_perimeter => 60 * Slic3r::Config->get('external_perimeter_speed'), external_perimeter => 60 * $Slic3r::Config->get_value('external_perimeter_speed'),
infill => 60 * Slic3r::Config->get('infill_speed'), infill => 60 * $Slic3r::Config->get_value('infill_speed'),
solid_infill => 60 * Slic3r::Config->get('solid_infill_speed'), solid_infill => 60 * $Slic3r::Config->get_value('solid_infill_speed'),
top_solid_infill => 60 * Slic3r::Config->get('top_solid_infill_speed'), top_solid_infill => 60 * $Slic3r::Config->get_value('top_solid_infill_speed'),
bridge => 60 * Slic3r::Config->get('bridge_speed'), bridge => 60 * $Slic3r::Config->get_value('bridge_speed'),
retract => 60 * Slic3r::Config->get('retract_speed'), retract => 60 * $Slic3r::Config->get_value('retract_speed'),
}}, }},
); );
@ -62,7 +62,7 @@ sub change_layer {
my ($layer) = @_; my ($layer) = @_;
$self->layer($layer); $self->layer($layer);
my $z = $Slic3r::z_offset + $layer->print_z * $Slic3r::scaling_factor; my $z = $Slic3r::Config->z_offset + $layer->print_z * &Slic3r::SCALING_FACTOR;
my $gcode = ""; my $gcode = "";
@ -70,8 +70,8 @@ sub change_layer {
$gcode .= $self->G0(undef, $z, 0, 'move to next layer (' . $layer->id . ')') $gcode .= $self->G0(undef, $z, 0, 'move to next layer (' . $layer->id . ')')
if $self->z != $z && !$self->lifted; if $self->z != $z && !$self->lifted;
$gcode .= Slic3r::Config->replace_options($Slic3r::layer_gcode) . "\n" $gcode .= $Slic3r::Config->replace_options($Slic3r::Config->layer_gcode) . "\n"
if $Slic3r::layer_gcode; if $Slic3r::Config->layer_gcode;
return $gcode; return $gcode;
} }
@ -95,10 +95,10 @@ sub extrude_loop {
# find the point of the loop that is closest to the current extruder position # find the point of the loop that is closest to the current extruder position
# or randomize if requested # or randomize if requested
my $last_pos = $self->last_pos; my $last_pos = $self->last_pos;
if ($Slic3r::randomize_start && $loop->role == EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER) { if ($Slic3r::Config->randomize_start && $loop->role == EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER) {
srand $self->layer->id * 10; srand $self->layer->id * 10;
$last_pos = Slic3r::Point->new(scale $Slic3r::print_center->[X], scale $Slic3r::bed_size->[Y]); $last_pos = Slic3r::Point->new(scale $Slic3r::Config->print_center->[X], scale $Slic3r::Config->bed_size->[Y]);
$last_pos->rotate(rand(2*PI), $Slic3r::print_center); $last_pos->rotate(rand(2*PI), $Slic3r::Config->print_center);
} }
my $start_index = $loop->nearest_point_index_to($last_pos); my $start_index = $loop->nearest_point_index_to($last_pos);
@ -123,7 +123,7 @@ sub extrude_path {
$path->merge_continuous_lines; $path->merge_continuous_lines;
# detect arcs # detect arcs
if ($Slic3r::gcode_arcs && !$recursive) { if ($Slic3r::Config->gcode_arcs && !$recursive) {
my $gcode = ""; my $gcode = "";
foreach my $arc_path ($path->detect_arcs) { foreach my $arc_path ($path->detect_arcs) {
$gcode .= $self->extrude_path($arc_path, $description, 1); $gcode .= $self->extrude_path($arc_path, $description, 1);
@ -136,10 +136,10 @@ sub extrude_path {
# retract if distance from previous position is greater or equal to the one # retract if distance from previous position is greater or equal to the one
# specified by the user *and* to the maximum distance between infill lines # specified by the user *and* to the maximum distance between infill lines
{ {
my $distance_from_last_pos = $self->last_pos->distance_to($path->points->[0]) * $Slic3r::scaling_factor; my $distance_from_last_pos = $self->last_pos->distance_to($path->points->[0]) * &Slic3r::SCALING_FACTOR;
my $distance_threshold = $Slic3r::retract_before_travel; my $distance_threshold = $Slic3r::Config->retract_before_travel;
$distance_threshold = 2 * ($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) / $Slic3r::fill_density * sqrt(2) $distance_threshold = 2 * ($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) / $Slic3r::Config->fill_density * sqrt(2)
if 0 && $Slic3r::fill_density > 0 && $description =~ /fill/; if 0 && $Slic3r::Config->fill_density > 0 && $description =~ /fill/;
if ($distance_from_last_pos >= $distance_threshold) { if ($distance_from_last_pos >= $distance_threshold) {
$gcode .= $self->retract(travel_to => $path->points->[0]); $gcode .= $self->retract(travel_to => $path->points->[0]);
@ -181,12 +181,12 @@ sub extrude_path {
} }
} }
if ($Slic3r::cooling) { if ($Slic3r::Config->cooling) {
my $path_time = unscale($path_length) / $self->speeds->{$self->last_speed} * 60; my $path_time = unscale($path_length) / $self->speeds->{$self->last_speed} * 60;
if ($self->layer->id == 0) { if ($self->layer->id == 0) {
$path_time = $Slic3r::first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/ $path_time = $Slic3r::Config->first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/
? $path_time / ($1/100) ? $path_time / ($1/100)
: unscale($path_length) / $Slic3r::first_layer_speed * 60; : unscale($path_length) / $Slic3r::Config->first_layer_speed * 60;
} }
$self->elapsed_time($self->elapsed_time + $path_time); $self->elapsed_time($self->elapsed_time + $path_time);
} }
@ -198,18 +198,18 @@ sub retract {
my $self = shift; my $self = shift;
my %params = @_; my %params = @_;
return "" unless $Slic3r::retract_length > 0 return "" unless $Slic3r::Config->retract_length > 0
&& !$self->retracted; && !$self->retracted;
# prepare moves # prepare moves
$self->speed('retract'); $self->speed('retract');
my $retract = [undef, undef, -$Slic3r::retract_length, "retract"]; my $retract = [undef, undef, -$Slic3r::Config->retract_length, "retract"];
my $lift = ($Slic3r::retract_lift == 0 || defined $params{move_z}) my $lift = ($Slic3r::Config->retract_lift == 0 || defined $params{move_z})
? undef ? undef
: [undef, $self->z + $Slic3r::retract_lift, 0, 'lift plate during retraction']; : [undef, $self->z + $Slic3r::Config->retract_lift, 0, 'lift plate during retraction'];
my $gcode = ""; my $gcode = "";
if (($Slic3r::g0 || $Slic3r::gcode_flavor eq 'mach3') && $params{travel_to}) { if (($Slic3r::Config->g0 || $Slic3r::Config->gcode_flavor eq 'mach3') && $params{travel_to}) {
if ($lift) { if ($lift) {
# combine lift and retract # combine lift and retract
$lift->[2] = $retract->[2]; $lift->[2] = $retract->[2];
@ -219,14 +219,14 @@ sub retract {
my $travel = [$params{travel_to}, undef, $retract->[2], 'travel and retract']; my $travel = [$params{travel_to}, undef, $retract->[2], 'travel and retract'];
$gcode .= $self->G0(@$travel); $gcode .= $self->G0(@$travel);
} }
} elsif (($Slic3r::g0 || $Slic3r::gcode_flavor eq 'mach3') && defined $params{move_z}) { } elsif (($Slic3r::Config->g0 || $Slic3r::Config->gcode_flavor eq 'mach3') && defined $params{move_z}) {
# combine Z change and retraction # combine Z change and retraction
my $travel = [undef, $params{move_z}, $retract->[2], 'change layer and retract']; my $travel = [undef, $params{move_z}, $retract->[2], 'change layer and retract'];
$gcode .= $self->G0(@$travel); $gcode .= $self->G0(@$travel);
} else { } else {
$gcode .= $self->G1(@$retract); $gcode .= $self->G1(@$retract);
if (defined $params{move_z} && $Slic3r::retract_lift > 0) { if (defined $params{move_z} && $Slic3r::Config->retract_lift > 0) {
my $travel = [undef, $params{move_z} + $Slic3r::retract_lift, 0, 'move to next layer (' . $self->layer->id . ') and lift']; my $travel = [undef, $params{move_z} + $Slic3r::Config->retract_lift, 0, 'move to next layer (' . $self->layer->id . ') and lift'];
$gcode .= $self->G0(@$travel); $gcode .= $self->G0(@$travel);
$self->lifted(1); $self->lifted(1);
} elsif ($lift) { } elsif ($lift) {
@ -238,7 +238,7 @@ sub retract {
# reset extrusion distance during retracts # reset extrusion distance during retracts
# this makes sure we leave sufficient precision in the firmware # this makes sure we leave sufficient precision in the firmware
$gcode .= $self->reset_e if $Slic3r::gcode_flavor !~ /^(?:mach3|makerbot)$/; $gcode .= $self->reset_e if $Slic3r::Config->gcode_flavor !~ /^(?:mach3|makerbot)$/;
return $gcode; return $gcode;
} }
@ -249,12 +249,12 @@ sub unretract {
my $gcode = ""; my $gcode = "";
if ($self->lifted) { if ($self->lifted) {
$gcode .= $self->G0(undef, $self->z - $Slic3r::retract_lift, 0, 'restore layer Z'); $gcode .= $self->G0(undef, $self->z - $Slic3r::Config->retract_lift, 0, 'restore layer Z');
$self->lifted(0); $self->lifted(0);
} }
$self->speed('retract'); $self->speed('retract');
$gcode .= $self->G0(undef, undef, ($Slic3r::retract_length + $Slic3r::retract_restart_extra), $gcode .= $self->G0(undef, undef, ($Slic3r::Config->retract_length + $Slic3r::Config->retract_restart_extra),
"compensate retraction"); "compensate retraction");
return $gcode; return $gcode;
@ -264,22 +264,22 @@ sub reset_e {
my $self = shift; my $self = shift;
$self->extrusion_distance(0); $self->extrusion_distance(0);
return sprintf "G92 %s0%s\n", $Slic3r::extrusion_axis, ($Slic3r::gcode_comments ? ' ; reset extrusion distance' : '') return sprintf "G92 %s0%s\n", $Slic3r::Config->extrusion_axis, ($Slic3r::Config->gcode_comments ? ' ; reset extrusion distance' : '')
if $Slic3r::extrusion_axis && !$Slic3r::use_relative_e_distances; if $Slic3r::Config->extrusion_axis && !$Slic3r::Config->use_relative_e_distances;
} }
sub set_acceleration { sub set_acceleration {
my $self = shift; my $self = shift;
my ($acceleration) = @_; my ($acceleration) = @_;
return "" unless $Slic3r::acceleration; return "" unless $Slic3r::Config->acceleration;
return sprintf "M201 E%s%s\n", return sprintf "M201 E%s%s\n",
$acceleration, ($Slic3r::gcode_comments ? ' ; adjust acceleration' : ''); $acceleration, ($Slic3r::Config->gcode_comments ? ' ; adjust acceleration' : '');
} }
sub G0 { sub G0 {
my $self = shift; my $self = shift;
return $self->G1(@_) if !($Slic3r::g0 || $Slic3r::gcode_flavor eq 'mach3'); return $self->G1(@_) if !($Slic3r::Config->g0 || $Slic3r::Config->gcode_flavor eq 'mach3');
return $self->_G0_G1("G0", @_); return $self->_G0_G1("G0", @_);
} }
@ -295,8 +295,8 @@ sub _G0_G1 {
if ($point) { if ($point) {
$gcode .= sprintf " X%.${dec}f Y%.${dec}f", $gcode .= sprintf " X%.${dec}f Y%.${dec}f",
($point->x * $Slic3r::scaling_factor) + $self->shift_x, ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x,
($point->y * $Slic3r::scaling_factor) + $self->shift_y; #** ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y; #**
$self->last_pos($point); $self->last_pos($point);
} }
if (defined $z && $z != $self->z) { if (defined $z && $z != $self->z) {
@ -315,13 +315,13 @@ sub G2_G3 {
my $gcode = $orientation eq 'cw' ? "G2" : "G3"; my $gcode = $orientation eq 'cw' ? "G2" : "G3";
$gcode .= sprintf " X%.${dec}f Y%.${dec}f", $gcode .= sprintf " X%.${dec}f Y%.${dec}f",
($point->x * $Slic3r::scaling_factor) + $self->shift_x, ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x,
($point->y * $Slic3r::scaling_factor) + $self->shift_y; #** ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y; #**
# XY distance of the center from the start position # XY distance of the center from the start position
$gcode .= sprintf " I%.${dec}f J%.${dec}f", $gcode .= sprintf " I%.${dec}f J%.${dec}f",
($center->[X] - $self->last_pos->[X]) * $Slic3r::scaling_factor, ($center->[X] - $self->last_pos->[X]) * &Slic3r::SCALING_FACTOR,
($center->[Y] - $self->last_pos->[Y]) * $Slic3r::scaling_factor; ($center->[Y] - $self->last_pos->[Y]) * &Slic3r::SCALING_FACTOR;
$self->last_pos($point); $self->last_pos($point);
return $self->_Gx($gcode, $e, $comment); return $self->_Gx($gcode, $e, $comment);
@ -348,23 +348,23 @@ sub _Gx {
# apply the speed reduction for print moves on bottom layer # apply the speed reduction for print moves on bottom layer
my $speed_f = $self->speeds->{$speed}; my $speed_f = $self->speeds->{$speed};
if ($e && $self->layer->id == 0 && $comment !~ /retract/) { if ($e && $self->layer->id == 0 && $comment !~ /retract/) {
$speed_f = $Slic3r::first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/ $speed_f = $Slic3r::Config->first_layer_speed =~ /^(\d+(?:\.\d+)?)%$/
? ($speed_f * $1/100) ? ($speed_f * $1/100)
: $Slic3r::first_layer_speed * 60; : $Slic3r::Config->first_layer_speed * 60;
} }
$gcode .= sprintf " F%.${dec}f", $speed_f; $gcode .= sprintf " F%.${dec}f", $speed_f;
$self->last_speed($speed); $self->last_speed($speed);
} }
# output extrusion distance # output extrusion distance
if ($e && $Slic3r::extrusion_axis) { if ($e && $Slic3r::Config->extrusion_axis) {
$self->extrusion_distance(0) if $Slic3r::use_relative_e_distances; $self->extrusion_distance(0) if $Slic3r::Config->use_relative_e_distances;
$self->extrusion_distance($self->extrusion_distance + $e); $self->extrusion_distance($self->extrusion_distance + $e);
$self->total_extrusion_length($self->total_extrusion_length + $e); $self->total_extrusion_length($self->total_extrusion_length + $e);
$gcode .= sprintf " %s%.5f", $Slic3r::extrusion_axis, $self->extrusion_distance; $gcode .= sprintf " %s%.5f", $Slic3r::Config->extrusion_axis, $self->extrusion_distance;
} }
$gcode .= sprintf " ; %s", $comment if $comment && $Slic3r::gcode_comments; $gcode .= sprintf " ; %s", $comment if $comment && $Slic3r::Config->gcode_comments;
if ($append_bridge_off) { if ($append_bridge_off) {
$gcode .= "\n;_BRIDGE_FAN_END"; $gcode .= "\n;_BRIDGE_FAN_END";
} }
@ -379,7 +379,7 @@ sub set_tool {
$self->extruder_idx($tool); $self->extruder_idx($tool);
return $self->retract return $self->retract
. (sprintf "T%d%s\n", $tool, ($Slic3r::gcode_comments ? ' ; change tool' : '')) . (sprintf "T%d%s\n", $tool, ($Slic3r::Config->gcode_comments ? ' ; change tool' : ''))
. $self->reset_e . $self->reset_e
. $self->unretract; . $self->unretract;
} }
@ -391,10 +391,10 @@ sub set_fan {
if ($self->last_fan_speed != $speed || $dont_save) { if ($self->last_fan_speed != $speed || $dont_save) {
$self->last_fan_speed($speed) if !$dont_save; $self->last_fan_speed($speed) if !$dont_save;
if ($speed == 0) { if ($speed == 0) {
return sprintf "M107%s\n", ($Slic3r::gcode_comments ? ' ; disable fan' : ''); return sprintf "M107%s\n", ($Slic3r::Config->gcode_comments ? ' ; disable fan' : '');
} else { } else {
return sprintf "M106 %s%d%s\n", ($Slic3r::gcode_flavor eq 'mach3' ? 'P' : 'S'), return sprintf "M106 %s%d%s\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'),
(255 * $speed / 100), ($Slic3r::gcode_comments ? ' ; enable fan' : ''); (255 * $speed / 100), ($Slic3r::Config->gcode_comments ? ' ; enable fan' : '');
} }
} }
return ""; return "";
@ -404,13 +404,13 @@ sub set_temperature {
my $self = shift; my $self = shift;
my ($temperature, $wait, $tool) = @_; my ($temperature, $wait, $tool) = @_;
return "" if $wait && $Slic3r::gcode_flavor eq 'makerbot'; return "" if $wait && $Slic3r::Config->gcode_flavor eq 'makerbot';
my ($code, $comment) = $wait my ($code, $comment) = $wait
? ('M109', 'wait for temperature to be reached') ? ('M109', 'wait for temperature to be reached')
: ('M104', 'set temperature'); : ('M104', 'set temperature');
return sprintf "$code %s%d %s; $comment\n", return sprintf "$code %s%d %s; $comment\n",
($Slic3r::gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature, ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature,
(defined $tool && $tool != $self->extruder_idx) ? "T$tool " : ""; (defined $tool && $tool != $self->extruder_idx) ? "T$tool " : "";
} }
@ -419,12 +419,12 @@ sub set_bed_temperature {
my ($temperature, $wait) = @_; my ($temperature, $wait) = @_;
my ($code, $comment) = $wait my ($code, $comment) = $wait
? (($Slic3r::gcode_flavor eq 'makerbot' ? 'M109' ? (($Slic3r::Config->gcode_flavor eq 'makerbot' ? 'M109'
: $Slic3r::gcode_flavor eq 'teacup' ? 'M109 P1' : $Slic3r::Config->gcode_flavor eq 'teacup' ? 'M109 P1'
: 'M190'), 'wait for bed temperature to be reached') : 'M190'), 'wait for bed temperature to be reached')
: ('M140', 'set bed temperature'); : ('M140', 'set bed temperature');
return sprintf "$code %s%d ; $comment\n", return sprintf "$code %s%d ; $comment\n",
($Slic3r::gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature; ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature;
} }
1; 1;

View file

@ -31,6 +31,7 @@ use constant MI_CONF_WIZARD => 11;
use constant MI_WEBSITE => 12; use constant MI_WEBSITE => 12;
our $datadir; our $datadir;
our $Settings;
our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
$small_font->SetPointSize(11) if !&Wx::wxMSW; $small_font->SetPointSize(11) if !&Wx::wxMSW;
@ -57,7 +58,7 @@ sub OnInit {
# load settings # load settings
if (-f "$datadir/slic3r.ini") { if (-f "$datadir/slic3r.ini") {
my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") }; my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") };
$Slic3r::Settings = $ini if $ini; $Settings = $ini if $ini;
} }
# application frame # application frame
@ -86,7 +87,7 @@ sub OnInit {
$fileMenu->Append(MI_SLICE_SVG, "Slice to SV&G…\tCtrl+G", 'Slice file to SVG'); $fileMenu->Append(MI_SLICE_SVG, "Slice to SV&G…\tCtrl+G", 'Slice file to SVG');
$fileMenu->AppendSeparator(); $fileMenu->AppendSeparator();
$fileMenu->Append(wxID_EXIT, "&Quit", 'Quit Slic3r'); $fileMenu->Append(wxID_EXIT, "&Quit", 'Quit Slic3r');
EVT_MENU($frame, MI_LOAD_CONF, sub { $self->{skeinpanel}->load_config }); EVT_MENU($frame, MI_LOAD_CONF, sub { $self->{skeinpanel}->load_config_file });
EVT_MENU($frame, MI_EXPORT_CONF, sub { $self->{skeinpanel}->save_config }); EVT_MENU($frame, MI_EXPORT_CONF, sub { $self->{skeinpanel}->save_config });
EVT_MENU($frame, MI_QUICK_SLICE, sub { $self->{skeinpanel}->do_slice; EVT_MENU($frame, MI_QUICK_SLICE, sub { $self->{skeinpanel}->do_slice;
$repeat->Enable(defined $Slic3r::GUI::SkeinPanel::last_input_file) }); $repeat->Enable(defined $Slic3r::GUI::SkeinPanel::last_input_file) });
@ -205,6 +206,12 @@ sub notify {
$self->{notifier}->notify($message); $self->{notifier}->notify($message);
} }
sub save_settings {
my $self = shift;
Slic3r::Config->write_ini("$datadir/slic3r.ini", $Settings);
}
package Slic3r::GUI::ProgressStatusBar; package Slic3r::GUI::ProgressStatusBar;
use Wx qw(:gauge :misc); use Wx qw(:gauge :misc);
use base 'Wx::StatusBar'; use base 'Wx::StatusBar';

View file

@ -372,7 +372,7 @@ sub apply {
$self->SUPER::apply; $self->SUPER::apply;
# set print_center to centre of bed_size # set print_center to centre of bed_size
my $bed_size = Slic3r::Config->get_raw('bed_size'); my $bed_size = $Slic3r::Config->bed_size;
Slic3r::Config->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]); Slic3r::Config->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]);
} }
@ -395,7 +395,7 @@ sub apply {
$self->SUPER::apply; $self->SUPER::apply;
# set first_layer_height + layer_height based on nozzle_diameter # set first_layer_height + layer_height based on nozzle_diameter
my $nozzle = Slic3r::Config->get_raw('nozzle_diameter'); my $nozzle = $Slic3r::Config->nozzle_diameter;
Slic3r::Config->set('first_layer_height', $nozzle->[0]); Slic3r::Config->set('first_layer_height', $nozzle->[0]);
Slic3r::Config->set('layer_height', $nozzle->[0] - 0.1); Slic3r::Config->set('layer_height', $nozzle->[0] - 0.1);
} }
@ -435,7 +435,7 @@ sub apply {
$self->SUPER::apply; $self->SUPER::apply;
# set first_layer_temperature to temperature + 5 # set first_layer_temperature to temperature + 5
my $temperature = Slic3r::Config->get_raw('temperature'); my $temperature = $Slic3r::Config->temperature;
Slic3r::Config->set('first_layer_temperature', [$temperature->[0] + 5]); Slic3r::Config->set('first_layer_temperature', [$temperature->[0] + 5]);
} }
@ -459,7 +459,7 @@ sub apply {
$self->SUPER::apply; $self->SUPER::apply;
# set first_layer_bed_temperature to temperature + 5 # set first_layer_bed_temperature to temperature + 5
my $temperature = Slic3r::Config->get_raw('bed_temperature'); my $temperature = $Slic3r::Config->bed_temperature;
Slic3r::Config->set('first_layer_bed_temperature', $temperature + 5); Slic3r::Config->set('first_layer_bed_temperature', $temperature + 5);
} }

View file

@ -1,6 +1,7 @@
package Slic3r::GUI::OptionsGroup; package Slic3r::GUI::OptionsGroup;
use Moo; use Moo;
use List::Util qw(first);
use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl); use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl);
use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT); use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT);
@ -28,6 +29,7 @@ Slic3r::GUI::OptionsGroup - pre-filled Wx::StaticBoxSizer wrapper containing one
labels => [], labels => [],
values => [], values => [],
default => 0.4, # mandatory default => 0.4, # mandatory
readonly => 0,
on_change => sub { print "new value is $_[0]\n" }, on_change => sub { print "new value is $_[0]\n" },
}, },
], ],
@ -86,6 +88,7 @@ sub BUILD {
$field = $opt->{type} eq 'i' $field = $opt->{type} eq 'i'
? Wx::SpinCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $opt->{default}) ? Wx::SpinCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style, $opt->{min} || 0, $opt->{max} || 100, $opt->{default})
: Wx::TextCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style); : Wx::TextCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style);
$field->Disable if $opt->{readonly};
$self->_setters->{$opt_key} = sub { $field->SetValue($_[0]) }; $self->_setters->{$opt_key} = sub { $field->SetValue($_[0]) };
my $on_change = sub { $self->_on_change($opt_key, $field->GetValue) }; my $on_change = sub { $self->_on_change($opt_key, $field->GetValue) };
@ -145,6 +148,13 @@ sub BUILD {
$self->sizer->Add($grid_sizer, 0, wxEXPAND); $self->sizer->Add($grid_sizer, 0, wxEXPAND);
} }
sub _option {
my $self = shift;
my ($opt_key) = @_;
return first { $_->{opt_key} eq $opt_key } @{$self->options};
}
sub _on_change { sub _on_change {
my $self = shift; my $self = shift;
my ($opt_key, $value) = @_; my ($opt_key, $value) = @_;
@ -189,6 +199,7 @@ Slic3r::GUI::ConfigOptionsGroup - pre-filled Wx::StaticBoxSizer wrapper containi
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new( my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
parent => $self->parent, parent => $self->parent,
title => 'Layers', title => 'Layers',
config => $config,
options => ['layer_height'], options => ['layer_height'],
on_change => sub { print "new value for $_[0] is $_[1]\n" }, on_change => sub { print "new value for $_[0] is $_[1]\n" },
no_labels => 0, no_labels => 0,
@ -198,7 +209,7 @@ Slic3r::GUI::ConfigOptionsGroup - pre-filled Wx::StaticBoxSizer wrapper containi
=cut =cut
use List::Util qw(first); has 'config' => (is => 'ro', required => 1);
sub _trigger_options { sub _trigger_options {
my $self = shift; my $self = shift;
@ -212,7 +223,7 @@ sub _trigger_options {
$opt = { $opt = {
opt_key => $full_key, opt_key => $full_key,
config => 1, config => 1,
(map { $_ => $config_opt->{$_} } qw(type label tooltip sidetext width height full_width min max labels values multiline)), (map { $_ => $config_opt->{$_} } qw(type label tooltip sidetext width height full_width min max labels values multiline readonly)),
default => $self->_get_config($opt_key, $index), default => $self->_get_config($opt_key, $index),
on_change => sub { $self->_set_config($opt_key, $index, $_[0]) }, on_change => sub { $self->_set_config($opt_key, $index, $_[0]) },
}; };
@ -225,7 +236,10 @@ sub set_value {
my $self = shift; my $self = shift;
my ($opt_key, $value) = @_; my ($opt_key, $value) = @_;
if (first { $_->{opt_key} eq $opt_key && !$_->{config} } @{$self->options}) { my $opt = $self->_option($opt_key) or return 0;
# if user is setting a non-config option, forward the call to the parent
if (!$opt->{config}) {
return $self->SUPER::set_value($opt_key, $value); return $self->SUPER::set_value($opt_key, $value);
} }
@ -234,7 +248,8 @@ sub set_value {
my ($key, $index) = $self->_split_key($full_key); my ($key, $index) = $self->_split_key($full_key);
if ($key eq $opt_key) { if ($key eq $opt_key) {
$self->SUPER::set_value($full_key, $self->_get_config($key, $index, $value)); $self->config->set($key, $value);
$self->SUPER::set_value($full_key, $self->_get_config($key, $index));
$changed = 1; $changed = 1;
} }
} }
@ -252,11 +267,14 @@ sub _split_key {
sub _get_config { sub _get_config {
my $self = shift; my $self = shift;
my ($opt_key, $index, $value) = @_; my ($opt_key, $index) = @_;
my ($get_m, $set_m) = $self->_config_methods($opt_key, $index); my ($get_m, $serialized) = $self->_config_methods($opt_key, $index);
$value ||= Slic3r::Config->$get_m($opt_key); my $value = $self->config->$get_m($opt_key);
$value = $value->[$index] if defined $index; if (defined $index) {
$value->[$index] //= $value->[0]; #/
$value = $value->[$index];
}
return $value; return $value;
} }
@ -264,10 +282,10 @@ sub _set_config {
my $self = shift; my $self = shift;
my ($opt_key, $index, $value) = @_; my ($opt_key, $index, $value) = @_;
my ($get_m, $set_m) = $self->_config_methods($opt_key, $index); my ($get_m, $serialized) = $self->_config_methods($opt_key, $index);
defined $index defined $index
? Slic3r::Config->$get_m($opt_key)->[$index] = $value ? $self->config->$get_m($opt_key)->[$index] = $value
: Slic3r::Config->$set_m($opt_key, $value); : $self->config->set($opt_key, $value, $serialized);
} }
sub _config_methods { sub _config_methods {
@ -275,9 +293,9 @@ sub _config_methods {
my ($opt_key, $index) = @_; my ($opt_key, $index) = @_;
# if it's an array type but no index was specified, use the serialized version # if it's an array type but no index was specified, use the serialized version
return $Slic3r::Config::Options->{$opt_key}{type} =~ /\@$/ && !defined $index return ($Slic3r::Config::Options->{$opt_key}{type} =~ /\@$/ && !defined $index)
? qw(serialize deserialize) ? qw(serialize 1)
: qw(get_raw set); : qw(get 0);
} }
1; 1;

View file

@ -26,10 +26,17 @@ my $MESSAGE_DIALOG_EVENT : shared = Wx::NewEventType;
my $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType; my $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType;
my $EXPORT_FAILED_EVENT : shared = Wx::NewEventType; my $EXPORT_FAILED_EVENT : shared = Wx::NewEventType;
use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8'
? 'What do you want to print today? ™' # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap.
: 'Drag your objects here';
sub new { sub new {
my $class = shift; my $class = shift;
my ($parent) = @_; my ($parent) = @_;
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{config} = Slic3r::Config->new_from_defaults(qw(
bed_size print_center complete_objects extruder_clearance_radius skirts skirt_distance
));
$self->{canvas} = Wx::Panel->new($self, -1, wxDefaultPosition, [300, 300], wxTAB_TRAVERSAL); $self->{canvas} = Wx::Panel->new($self, -1, wxDefaultPosition, [300, 300], wxTAB_TRAVERSAL);
$self->{canvas}->SetBackgroundColour(Wx::wxWHITE); $self->{canvas}->SetBackgroundColour(Wx::wxWHITE);
@ -173,7 +180,7 @@ sub new {
$self->on_export_failed; $self->on_export_failed;
}); });
$self->update_bed_size; $self->_update_bed_size;
$self->{print} = Slic3r::Print->new; $self->{print} = Slic3r::Print->new;
$self->{thumbnails} = []; # polygons, each one aligned to 0,0 $self->{thumbnails} = []; # polygons, each one aligned to 0,0
$self->{scale} = []; $self->{scale} = [];
@ -229,6 +236,11 @@ sub new {
return $self; return $self;
} }
sub skeinpanel {
my $self = shift;
return $self->GetParent->GetParent;
}
sub load { sub load {
my $self = shift; my $self = shift;
@ -428,7 +440,7 @@ sub split_object {
my $current_object = $self->{print}->objects->[$obj_idx]; my $current_object = $self->{print}->objects->[$obj_idx];
my $current_copies_num = @{$self->{print}->copies->[$obj_idx]}; my $current_copies_num = @{$self->{print}->copies->[$obj_idx]};
my $mesh = $current_object->mesh->clone; my $mesh = $current_object->mesh->clone;
$mesh->scale($Slic3r::scaling_factor); $mesh->scale(&Slic3r::SCALING_FACTOR);
my @new_meshes = $mesh->split_mesh; my @new_meshes = $mesh->split_mesh;
if (@new_meshes == 1) { if (@new_meshes == 1) {
@ -517,10 +529,9 @@ sub export_gcode2 {
} if $Slic3r::have_threads; } if $Slic3r::have_threads;
eval { eval {
# validate configuration
Slic3r::Config->validate;
my $print = $self->{print}; my $print = $self->{print};
$print->config($self->skeinpanel->config);
$print->config->validate;
$print->validate; $print->validate;
{ {
@ -607,7 +618,7 @@ sub export_stl {
push @{$mesh->facets}, map [ $_->[0], map $vertices_offset + $_, @$_[-3..-1] ], @{$cloned_mesh->facets}; push @{$mesh->facets}, map [ $_->[0], map $vertices_offset + $_, @$_[-3..-1] ], @{$cloned_mesh->facets};
} }
} }
$mesh->scale($Slic3r::scaling_factor); $mesh->scale(&Slic3r::SCALING_FACTOR);
$mesh->align_to_origin; $mesh->align_to_origin;
Slic3r::Format::STL->write_file($output_file, $mesh, 1); Slic3r::Format::STL->write_file($output_file, $mesh, 1);
@ -657,14 +668,21 @@ sub recenter {
]; ];
} }
sub update_bed_size { sub on_config_change {
my $self = shift;
my ($opt_key, $value) = @_;
$self->{config}->set($opt_key, $value) if exists $self->{config}{$opt_key};
$self->_update_bed_size;
}
sub _update_bed_size {
my $self = shift; my $self = shift;
# supposing the preview canvas is square, calculate the scaling factor # supposing the preview canvas is square, calculate the scaling factor
# to constrain print bed area inside preview # to constrain print bed area inside preview
my $bed_size = $self->{config}->bed_size;
my $canvas_side = $self->{canvas}->GetSize->GetWidth; my $canvas_side = $self->{canvas}->GetSize->GetWidth;
my $bed_largest_side = $Slic3r::bed_size->[X] > $Slic3r::bed_size->[Y] my $bed_largest_side = $bed_size->[X] > $bed_size->[Y] ? $bed_size->[X] : $bed_size->[Y];
? $Slic3r::bed_size->[X] : $Slic3r::bed_size->[Y];
my $old_scaling_factor = $self->{scaling_factor}; my $old_scaling_factor = $self->{scaling_factor};
$self->{scaling_factor} = $canvas_side / $bed_largest_side; $self->{scaling_factor} = $canvas_side / $bed_largest_side;
if (defined $old_scaling_factor && $self->{scaling_factor} != $old_scaling_factor) { if (defined $old_scaling_factor && $self->{scaling_factor} != $old_scaling_factor) {
@ -672,6 +690,7 @@ sub update_bed_size {
} }
} }
# this is called on the canvas
sub repaint { sub repaint {
my ($self, $event) = @_; my ($self, $event) = @_;
my $parent = $self->GetParent; my $parent = $self->GetParent;
@ -681,9 +700,6 @@ sub repaint {
my $size = $self->GetSize; my $size = $self->GetSize;
my @size = ($size->GetWidth, $size->GetHeight); my @size = ($size->GetWidth, $size->GetHeight);
# calculate scaling factor for preview
$parent->update_bed_size;
# draw grid # draw grid
$dc->SetPen($parent->{grid_pen}); $dc->SetPen($parent->{grid_pen});
my $step = 10 * $parent->{scaling_factor}; my $step = 10 * $parent->{scaling_factor};
@ -701,8 +717,8 @@ sub repaint {
$dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2); $dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2);
$dc->SetTextForeground(Wx::Colour->new(0,0,0)); $dc->SetTextForeground(Wx::Colour->new(0,0,0));
$dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL)); $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL));
$dc->DrawLabel("X = " . $Slic3r::print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); $dc->DrawLabel("X = " . $parent->{config}->print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
$dc->DrawRotatedText("Y = " . $Slic3r::print_center->[Y], 0, $size[Y]/2+15, 90); $dc->DrawRotatedText("Y = " . $parent->{config}->print_center->[Y], 0, $size[Y]/2+15, 90);
} }
# draw frame # draw frame
@ -714,7 +730,7 @@ sub repaint {
if (!@{$print->objects}) { if (!@{$print->objects}) {
$dc->SetTextForeground(Wx::Colour->new(150,50,50)); $dc->SetTextForeground(Wx::Colour->new(150,50,50));
$dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL)); $dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL));
$dc->DrawLabel("Drag your objects here", Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); $dc->DrawLabel(CANVAS_TEXT, Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
} }
# draw thumbnails # draw thumbnails
@ -738,8 +754,8 @@ sub repaint {
$dc->DrawPolygon($parent->_y($parent->{object_previews}->[-1][2]), 0, 0); $dc->DrawPolygon($parent->_y($parent->{object_previews}->[-1][2]), 0, 0);
# if sequential printing is enabled and we have more than one object # if sequential printing is enabled and we have more than one object
if ($Slic3r::complete_objects && (map @$_, @{$print->copies}) > 1) { if ($parent->{config}->complete_objects && (map @$_, @{$print->copies}) > 1) {
my $clearance = +($parent->{object_previews}->[-1][2]->offset($Slic3r::extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0]; my $clearance = +($parent->{object_previews}->[-1][2]->offset($parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0];
$dc->SetPen($parent->{clearance_pen}); $dc->SetPen($parent->{clearance_pen});
$dc->SetBrush($parent->{transparent_brush}); $dc->SetBrush($parent->{transparent_brush});
$dc->DrawPolygon($parent->_y($clearance), 0, 0); $dc->DrawPolygon($parent->_y($clearance), 0, 0);
@ -748,9 +764,9 @@ sub repaint {
} }
# draw skirt # draw skirt
if (@{$parent->{object_previews}} && $Slic3r::skirts) { if (@{$parent->{object_previews}} && $parent->{config}->skirts) {
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->[2]}, @{$parent->{object_previews}} ])); my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->[2]}, @{$parent->{object_previews}} ]));
$convex_hull = +($convex_hull->offset($Slic3r::skirt_distance * $parent->{scaling_factor}, 1, JT_ROUND))[0]; $convex_hull = +($convex_hull->offset($parent->{config}->skirt_distance * $parent->{scaling_factor}, 1, JT_ROUND))[0];
$dc->SetPen($parent->{skirt_pen}); $dc->SetPen($parent->{skirt_pen});
$dc->SetBrush($parent->{transparent_brush}); $dc->SetBrush($parent->{transparent_brush});
$dc->DrawPolygon($parent->_y($convex_hull), 0, 0) if $convex_hull; $dc->DrawPolygon($parent->_y($convex_hull), 0, 0) if $convex_hull;
@ -853,7 +869,7 @@ sub selected_object_idx {
sub statusbar { sub statusbar {
my $self = shift; my $self = shift;
return $self->GetParent->GetParent->GetParent->{statusbar}; return $self->skeinpanel->GetParent->{statusbar};
} }
sub to_pixel { sub to_pixel {

View file

@ -27,6 +27,10 @@ sub new {
filament => Slic3r::GUI::Tab::Filament->new ($self->{tabpanel}, sync_presets_with => $self->{plater}{preset_choosers}{filament}), filament => Slic3r::GUI::Tab::Filament->new ($self->{tabpanel}, sync_presets_with => $self->{plater}{preset_choosers}{filament}),
printer => Slic3r::GUI::Tab::Printer->new ($self->{tabpanel}, sync_presets_with => $self->{plater}{preset_choosers}{printer}), printer => Slic3r::GUI::Tab::Printer->new ($self->{tabpanel}, sync_presets_with => $self->{plater}{preset_choosers}{printer}),
}; };
# propagate config change events to the plater
$_->{on_value_change} = sub { $self->{plater}->on_config_change(@_) } for values %{$self->{options_tabs}};
$self->{tabpanel}->AddPage($self->{options_tabs}{print}, $self->{options_tabs}{print}->title); $self->{tabpanel}->AddPage($self->{options_tabs}{print}, $self->{options_tabs}{print}->title);
$self->{tabpanel}->AddPage($self->{options_tabs}{filament}, $self->{options_tabs}{filament}->title); $self->{tabpanel}->AddPage($self->{options_tabs}{filament}, $self->{options_tabs}{filament}->title);
$self->{tabpanel}->AddPage($self->{options_tabs}{printer}, $self->{options_tabs}{printer}->title); $self->{tabpanel}->AddPage($self->{options_tabs}{printer}, $self->{options_tabs}{printer}->title);
@ -53,11 +57,12 @@ sub do_slice {
my $process_dialog; my $process_dialog;
eval { eval {
# validate configuration # validate configuration
Slic3r::Config->validate; my $config = $self->config;
$config->validate;
# confirm slicing of more than one copies # confirm slicing of more than one copies
my $copies = $Slic3r::duplicate_grid->[X] * $Slic3r::duplicate_grid->[Y]; my $copies = $Slic3r::Config->duplicate_grid->[X] * $Slic3r::Config->duplicate_grid->[Y];
$copies = $Slic3r::duplicate if $Slic3r::duplicate > 1; $copies = $Slic3r::Config->duplicate if $Slic3r::Config->duplicate > 1;
if ($copies > 1) { if ($copies > 1) {
my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?", my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?",
'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL); 'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL);
@ -93,7 +98,7 @@ sub do_slice {
my $input_file_basename = basename($input_file); my $input_file_basename = basename($input_file);
$last_skein_dir = dirname($input_file); $last_skein_dir = dirname($input_file);
my $print = Slic3r::Print->new; my $print = Slic3r::Print->new(config => $config);
$print->add_object_from_file($input_file); $print->add_object_from_file($input_file);
$print->validate; $print->validate;
@ -160,12 +165,12 @@ sub do_slice {
sub save_config { sub save_config {
my $self = shift; my $self = shift;
my $process_dialog; my $config = $self->config;
eval { eval {
# validate configuration # validate configuration
Slic3r::Config->validate; $config->validate;
}; };
Slic3r::GUI::catch_error($self, sub { $process_dialog->Destroy if $process_dialog }) and return; Slic3r::GUI::catch_error($self) and return;
my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || ""; my $dir = $last_config ? dirname($last_config) : $last_config_dir || $last_skein_dir || "";
my $filename = $last_config ? basename($last_config) : "config.ini"; my $filename = $last_config ? basename($last_config) : "config.ini";
@ -175,12 +180,12 @@ sub save_config {
my $file = $dlg->GetPath; my $file = $dlg->GetPath;
$last_config_dir = dirname($file); $last_config_dir = dirname($file);
$last_config = $file; $last_config = $file;
Slic3r::Config->save($file); $config->save($file);
} }
$dlg->Destroy; $dlg->Destroy;
} }
sub load_config { sub load_config_file {
my $self = shift; my $self = shift;
my ($file) = @_; my ($file) = @_;
@ -198,15 +203,40 @@ sub load_config {
$_->load_external_config($file) for values %{$self->{options_tabs}}; $_->load_external_config($file) for values %{$self->{options_tabs}};
} }
sub load_config {
my $self = shift;
my ($config) = @_;
foreach my $tab (values %{$self->{options_tabs}}) {
$tab->set_value($_, $config->$_) for keys %$config;
}
}
sub config_wizard { sub config_wizard {
my $self = shift; my $self = shift;
return unless $self->check_unsaved_changes; return unless $self->check_unsaved_changes;
if (my %settings = Slic3r::GUI::ConfigWizard->new($self)->run) { if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) {
$self->set_value($_, $settings{$_}) for keys %settings; # TODO: select the default preset in all tabs
$self->load_config($config);
} }
} }
=head2 config
This method collects all config values from the tabs and merges them into a single config object.
=cut
sub config {
my $self = shift;
return Slic3r::Config->merge(
Slic3r::Config->new_from_defaults,
(map $_->config, values %{$self->{options_tabs}}),
);
}
sub set_value { sub set_value {
my $self = shift; my $self = shift;
my ($opt_key, $value) = @_; my ($opt_key, $value) = @_;

View file

@ -13,6 +13,7 @@ sub new {
my $class = shift; my $class = shift;
my ($parent, %params) = @_; my ($parent, %params) = @_;
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
$self->{options} = []; # array of option names handled by this tab
$self->{sync_presets_with} = $params{sync_presets_with}; $self->{sync_presets_with} = $params{sync_presets_with};
EVT_CHOICE($parent, $self->{sync_presets_with}, sub { EVT_CHOICE($parent, $self->{sync_presets_with}, sub {
@ -100,8 +101,8 @@ sub new {
); );
return unless $dlg->ShowModal == wxID_OK; return unless $dlg->ShowModal == wxID_OK;
my $file = sprintf "$Slic3r::GUI::datadir/$self->{presets_group}/%s.ini", $dlg->get_name; my $file = sprintf "$Slic3r::GUI::datadir/%s/%s.ini", $self->name, $dlg->get_name;
Slic3r::Config->save($file, $self->{presets_group}); $self->{config}->save($file);
$self->set_dirty(0); $self->set_dirty(0);
$self->load_presets; $self->load_presets;
$self->{presets_choice}->SetSelection(first { basename($self->{presets}[$_]{file}) eq $dlg->get_name . ".ini" } 1 .. $#{$self->{presets}}); $self->{presets_choice}->SetSelection(first { basename($self->{presets}[$_]{file}) eq $dlg->get_name . ".ini" } 1 .. $#{$self->{presets}});
@ -125,7 +126,13 @@ sub new {
$self->sync_presets; $self->sync_presets;
}); });
$self->{config} = Slic3r::Config->new;
$self->build; $self->build;
if ($self->hidden_options) {
$self->{config}->apply(Slic3r::Config->new_from_defaults($self->hidden_options));
push @{$self->{options}}, $self->hidden_options;
}
$self->load_presets;
return $self; return $self;
} }
@ -135,8 +142,15 @@ sub current_preset {
return $self->{presets}[ $self->{presets_choice}->GetSelection ]; return $self->{presets}[ $self->{presets_choice}->GetSelection ];
} }
sub on_value_change {} # propagate event to the parent
sub on_value_change {
my $self = shift;
$self->{on_value_change}->(@_) if $self->{on_value_change};
}
sub on_preset_loaded {} sub on_preset_loaded {}
sub hidden_options {}
sub config { $_[0]->{config}->clone }
sub on_select_preset { sub on_select_preset {
my $self = shift; my $self = shift;
@ -155,7 +169,7 @@ sub on_select_preset {
my $preset = $self->current_preset; my $preset = $self->current_preset;
if ($preset->{default}) { if ($preset->{default}) {
# default settings: disable the delete button # default settings: disable the delete button
Slic3r::Config->load_hash($Slic3r::Defaults, $self->{presets_group}, 1); $self->{config}->apply(Slic3r::Config->new_from_defaults(@{$self->{options}}));
$self->{btn_delete_preset}->Disable; $self->{btn_delete_preset}->Disable;
} else { } else {
if (!-e $preset->{file}) { if (!-e $preset->{file}) {
@ -164,7 +178,7 @@ sub on_select_preset {
} }
eval { eval {
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
Slic3r::Config->load($preset->{file}, $self->{presets_group}); $self->{config}->apply(Slic3r::Config->load($preset->{file}));
}; };
Slic3r::GUI::catch_error($self); Slic3r::GUI::catch_error($self);
$preset->{external} $preset->{external}
@ -174,8 +188,8 @@ sub on_select_preset {
$self->on_preset_loaded; $self->on_preset_loaded;
$self->reload_values; $self->reload_values;
$self->set_dirty(0); $self->set_dirty(0);
$Slic3r::Settings->{presets}{$self->{presets_group}} = $preset->{file} ? basename($preset->{file}) : ''; $Slic3r::GUI::Settings->{presets}{$self->name} = $preset->{file} ? basename($preset->{file}) : '';
Slic3r::Config->save_settings("$Slic3r::GUI::datadir/slic3r.ini"); Slic3r::GUI->save_settings("$Slic3r::GUI::datadir/slic3r.ini");
} }
sub add_options_page { sub add_options_page {
@ -188,6 +202,19 @@ sub add_options_page {
$self->{iconcount}++; $self->{iconcount}++;
} }
{
# get all config options being added to the current page; remove indexes; associate defaults
my @options = map { $_ =~ s/#.+//; $_ } grep !ref($_), map @{$_->{options}}, @{$params{optgroups}};
my %defaults_to_set = map { $_ => 1 } @options;
# apply default values for the options we don't have already
delete $defaults_to_set{$_} for @{$self->{options}};
$self->{config}->apply(Slic3r::Config->new_from_defaults(keys %defaults_to_set)) if %defaults_to_set;
# append such options to our list
push @{$self->{options}}, @options;
}
my $page = Slic3r::GUI::Tab::Page->new($self, $title, $self->{iconcount}, %params, on_change => sub { my $page = Slic3r::GUI::Tab::Page->new($self, $title, $self->{iconcount}, %params, on_change => sub {
$self->on_value_change(@_); $self->on_value_change(@_);
$self->set_dirty(1); $self->set_dirty(1);
@ -214,8 +241,7 @@ sub set_value {
sub reload_values { sub reload_values {
my $self = shift; my $self = shift;
my $current = Slic3r::Config->current; $self->set_value($_, $self->{config}->get($_)) for keys %{$self->{config}};
$self->set_value($_, $current->{$_}) for keys %$current;
} }
sub update_tree { sub update_tree {
@ -262,20 +288,18 @@ sub is_dirty {
sub load_presets { sub load_presets {
my $self = shift; my $self = shift;
my ($group) = @_;
$self->{presets_group} ||= $group;
$self->{presets} = [{ $self->{presets} = [{
default => 1, default => 1,
name => '- default -', name => '- default -',
}]; }];
opendir my $dh, "$Slic3r::GUI::datadir/$self->{presets_group}" or die "Failed to read directory $Slic3r::GUI::datadir/$self->{presets_group} (errno: $!)\n"; opendir my $dh, "$Slic3r::GUI::datadir/" . $self->name or die "Failed to read directory $Slic3r::GUI::datadir/" . $self->name . " (errno: $!)\n";
foreach my $file (sort grep /\.ini$/i, readdir $dh) { foreach my $file (sort grep /\.ini$/i, readdir $dh) {
my $name = basename($file); my $name = basename($file);
$name =~ s/\.ini$//; $name =~ s/\.ini$//;
push @{$self->{presets}}, { push @{$self->{presets}}, {
file => "$Slic3r::GUI::datadir/$self->{presets_group}/$file", file => "$Slic3r::GUI::datadir/" . $self->name . "/$file",
name => $name, name => $name,
}; };
} }
@ -285,7 +309,7 @@ sub load_presets {
$self->{presets_choice}->Append($_->{name}) for @{$self->{presets}}; $self->{presets_choice}->Append($_->{name}) for @{$self->{presets}};
{ {
# load last used preset # load last used preset
my $i = first { basename($self->{presets}[$_]{file}) eq ($Slic3r::Settings->{presets}{$self->{presets_group}} || '') } 1 .. $#{$self->{presets}}; my $i = first { basename($self->{presets}[$_]{file}) eq ($Slic3r::GUI::Settings->{presets}{$self->name} || '') } 1 .. $#{$self->{presets}};
$self->{presets_choice}->SetSelection($i || 0); $self->{presets_choice}->SetSelection($i || 0);
$self->on_select_preset; $self->on_select_preset;
} }
@ -326,6 +350,7 @@ sub sync_presets {
package Slic3r::GUI::Tab::Print; package Slic3r::GUI::Tab::Print;
use base 'Slic3r::GUI::Tab'; use base 'Slic3r::GUI::Tab';
sub name { 'print' }
sub title { 'Print Settings' } sub title { 'Print Settings' }
sub build { sub build {
@ -422,16 +447,17 @@ sub build {
}, },
{ {
title => 'Other', title => 'Other',
options => [qw(duplicate_distance), ($Slic3r::have_threads ? qw(threads) : ())], options => [($Slic3r::have_threads ? qw(threads) : ())],
}, },
]); ]);
$self->load_presets('print');
} }
sub hidden_options { !$Slic3r::have_threads ? qw(threads) : () }
package Slic3r::GUI::Tab::Filament; package Slic3r::GUI::Tab::Filament;
use base 'Slic3r::GUI::Tab'; use base 'Slic3r::GUI::Tab';
sub name { 'filament' }
sub title { 'Filament Settings' } sub title { 'Filament Settings' }
sub build { sub build {
@ -463,13 +489,12 @@ sub build {
options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)], options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)],
}, },
]); ]);
$self->load_presets('filament');
} }
package Slic3r::GUI::Tab::Printer; package Slic3r::GUI::Tab::Printer;
use base 'Slic3r::GUI::Tab'; use base 'Slic3r::GUI::Tab';
sub name { 'printer' }
sub title { 'Printer Settings' } sub title { 'Printer Settings' }
sub build { sub build {
@ -521,22 +546,28 @@ sub build {
]); ]);
$self->{extruder_pages} = []; $self->{extruder_pages} = [];
$self->build_extruder_pages; $self->_build_extruder_pages;
$self->load_presets('printer');
} }
sub extruder_options { qw(nozzle_diameter) } sub _extruder_options { qw(nozzle_diameter) }
sub build_extruder_pages { sub config {
my $self = shift;
my $config = $self->SUPER::config(@_);
# remove all unused values
foreach my $opt_key ($self->_extruder_options) {
splice @{ $config->{$opt_key} }, $self->{extruders_count};
}
return $config;
}
sub _build_extruder_pages {
my $self = shift; my $self = shift;
foreach my $extruder_idx (0 .. $self->{extruders_count}-1) { foreach my $extruder_idx (0 .. $self->{extruders_count}-1) {
# set default values
for my $opt_key ($self->extruder_options) {
Slic3r::Config->get_raw($opt_key)->[$extruder_idx] //= Slic3r::Config->get_raw($opt_key)->[0]; #/
}
# build page if it doesn't exist # build page if it doesn't exist
$self->{extruder_pages}[$extruder_idx] ||= $self->add_options_page("Extruder " . ($extruder_idx + 1), 'funnel.png', optgroups => [ $self->{extruder_pages}[$extruder_idx] ||= $self->add_options_page("Extruder " . ($extruder_idx + 1), 'funnel.png', optgroups => [
{ {
@ -571,28 +602,22 @@ sub on_value_change {
$page->{disabled} = 1; $page->{disabled} = 1;
} }
# delete values for unused extruders
for my $opt_key ($self->extruder_options) {
my $values = Slic3r::Config->get_raw($opt_key);
splice @$values, $self->{extruders_count} if $self->{extruders_count} <= $#$values;
}
# add extra pages # add extra pages
$self->build_extruder_pages; $self->_build_extruder_pages;
# update page list and select first page (General) # update page list and select first page (General)
$self->update_tree(0); $self->update_tree(0);
} }
} }
# this gets executed after preset is loaded in repository and before GUI fields are updated # this gets executed after preset is loaded and before GUI fields are updated
sub on_preset_loaded { sub on_preset_loaded {
my $self = shift; my $self = shift;
# update the extruders count field # update the extruders count field
{ {
# update the GUI field according to the number of nozzle diameters supplied # update the GUI field according to the number of nozzle diameters supplied
$self->set_value('extruders_count', scalar @{ Slic3r::Config->get_raw('nozzle_diameter') }); $self->set_value('extruders_count', scalar @{ $self->{config}->nozzle_diameter });
# update extruder page list # update extruder page list
$self->on_value_change('extruders_count'); $self->on_value_change('extruders_count');
@ -617,7 +642,11 @@ sub new {
$self->SetSizer($self->{vsizer}); $self->SetSizer($self->{vsizer});
if ($params{optgroups}) { if ($params{optgroups}) {
$self->append_optgroup(%$_, on_change => $params{on_change}) for @{$params{optgroups}}; $self->append_optgroup(
%$_,
config => $parent->{config},
on_change => $params{on_change},
) for @{$params{optgroups}};
} }
return $self; return $self;
@ -627,7 +656,12 @@ sub append_optgroup {
my $self = shift; my $self = shift;
my %params = @_; my %params = @_;
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(parent => $self, label_width => 200, %params); my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
parent => $self,
config => $self->GetParent->{config},
label_width => 200,
%params,
);
$self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 5); $self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 5);
push @{$self->{optgroups}}, $optgroup; push @{$self->{optgroups}}, $optgroup;
} }

View file

@ -39,8 +39,8 @@ our $parallel_degrees_limit = abs(deg2rad(3));
sub epsilon () { 1E-4 } sub epsilon () { 1E-4 }
sub scale ($) { $_[0] / $Slic3r::scaling_factor } sub scale ($) { $_[0] / &Slic3r::SCALING_FACTOR }
sub unscale ($) { $_[0] * $Slic3r::scaling_factor } sub unscale ($) { $_[0] * &Slic3r::SCALING_FACTOR }
sub slope { sub slope {
my ($line) = @_; my ($line) = @_;
@ -893,8 +893,8 @@ sub arrange {
# margin needed for the skirt # margin needed for the skirt
my $skirt_margin; my $skirt_margin;
if ($Slic3r::skirts > 0) { if ($Slic3r::Config->skirts > 0) {
$skirt_margin = ($Slic3r::flow->spacing * $Slic3r::skirts + $Slic3r::skirt_distance) * 2; $skirt_margin = ($Slic3r::flow->spacing * $Slic3r::Config->skirts + $Slic3r::Config->skirt_distance) * 2;
} else { } else {
$skirt_margin = 0; $skirt_margin = 0;
} }

View file

@ -20,7 +20,7 @@ has 'slice_z' => (is => 'lazy');
has 'print_z' => (is => 'lazy'); has 'print_z' => (is => 'lazy');
has 'height' => (is => 'lazy'); has 'height' => (is => 'lazy');
has 'flow' => (is => 'lazy'); has 'flow' => (is => 'lazy');
has 'perimeters_flow' => (is => 'lazy'); has 'perimeter_flow' => (is => 'lazy');
has 'infill_flow' => (is => 'lazy'); has 'infill_flow' => (is => 'lazy');
# collection of spare segments generated by slicing the original geometry; # collection of spare segments generated by slicing the original geometry;
@ -61,21 +61,21 @@ sub _build_slice_z {
my $self = shift; my $self = shift;
if ($self->id == 0) { if ($self->id == 0) {
return $Slic3r::_first_layer_height / 2 / $Slic3r::scaling_factor; return $Slic3r::Config->get_value('first_layer_height') / 2 / &Slic3r::SCALING_FACTOR;
} }
return ($Slic3r::_first_layer_height + (($self->id-1) * $Slic3r::layer_height) + ($Slic3r::layer_height/2)) return ($Slic3r::Config->get_value('first_layer_height') + (($self->id-1) * $Slic3r::Config->layer_height) + ($Slic3r::Config->layer_height/2))
/ $Slic3r::scaling_factor; #/ / &Slic3r::SCALING_FACTOR; #/
} }
# Z used for printing # Z used for printing
sub _build_print_z { sub _build_print_z {
my $self = shift; my $self = shift;
return ($Slic3r::_first_layer_height + ($self->id * $Slic3r::layer_height)) / $Slic3r::scaling_factor; return ($Slic3r::Config->get_value('first_layer_height') + ($self->id * $Slic3r::Config->layer_height)) / &Slic3r::SCALING_FACTOR;
} }
sub _build_height { sub _build_height {
my $self = shift; my $self = shift;
return $self->id == 0 ? $Slic3r::_first_layer_height : $Slic3r::layer_height; return $self->id == 0 ? $Slic3r::Config->get_value('first_layer_height') : $Slic3r::Config->layer_height;
} }
sub _build_flow { sub _build_flow {
@ -85,11 +85,11 @@ sub _build_flow {
: $Slic3r::flow; : $Slic3r::flow;
} }
sub _build_perimeters_flow { sub _build_perimeter_flow {
my $self = shift; my $self = shift;
return $self->id == 0 && $Slic3r::first_layer_flow return $self->id == 0 && $Slic3r::first_layer_flow
? $Slic3r::first_layer_flow ? $Slic3r::first_layer_flow
: $Slic3r::perimeters_flow; : $Slic3r::perimeter_flow;
} }
sub _build_infill_flow { sub _build_infill_flow {
@ -120,7 +120,7 @@ sub make_surfaces {
# the contours must be offsetted by half extrusion width inwards # the contours must be offsetted by half extrusion width inwards
{ {
my $distance = scale $self->perimeters_flow->width / 2; my $distance = scale $self->perimeter_flow->width / 2;
my @surfaces = @{$self->slices}; my @surfaces = @{$self->slices};
@{$self->slices} = (); @{$self->slices} = ();
foreach my $surface (@surfaces) { foreach my $surface (@surfaces) {
@ -141,10 +141,10 @@ sub make_surfaces {
$self->thin_walls([]); $self->thin_walls([]);
if (@$diff) { if (@$diff) {
my $area_threshold = scale($self->perimeters_flow->spacing) ** 2; my $area_threshold = scale($self->perimeter_flow->spacing) ** 2;
@$diff = grep $_->area > ($area_threshold), @$diff; @$diff = grep $_->area > ($area_threshold), @$diff;
@{$self->thin_walls} = map $_->medial_axis(scale $self->perimeters_flow->width), @$diff; @{$self->thin_walls} = map $_->medial_axis(scale $self->perimeter_flow->width), @$diff;
Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls}; Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls};
} }
@ -163,7 +163,7 @@ sub make_perimeters {
my $self = shift; my $self = shift;
Slic3r::debugf "Making perimeters for layer %d\n", $self->id; Slic3r::debugf "Making perimeters for layer %d\n", $self->id;
my $gap_area_threshold = scale($self->perimeters_flow->width)** 2; my $gap_area_threshold = scale($self->perimeter_flow->width)** 2;
# this array will hold one arrayref per original surface (island); # this array will hold one arrayref per original surface (island);
# each item of this arrayref is an arrayref representing a depth (from outer # each item of this arrayref is an arrayref representing a depth (from outer
@ -197,7 +197,7 @@ sub make_perimeters {
if (0) { if (0) {
foreach my $hole ($last_offsets[0]->holes) { foreach my $hole ($last_offsets[0]->holes) {
my $circumference = abs($hole->length); my $circumference = abs($hole->length);
next unless $circumference <= $Slic3r::small_perimeter_length; next unless $circumference <= &Slic3r::SMALL_PERIMETER_LENGTH;
# this compensation only works for circular holes, while it would # this compensation only works for circular holes, while it would
# overcompensate for hexagons and other shapes having straight edges. # overcompensate for hexagons and other shapes having straight edges.
# so we require a minimum number of vertices. # so we require a minimum number of vertices.
@ -205,8 +205,8 @@ sub make_perimeters {
# revert the compensation done in make_surfaces() and get the actual radius # revert the compensation done in make_surfaces() and get the actual radius
# of the hole # of the hole
my $radius = ($circumference / PI / 2) - scale $self->perimeters_flow->spacing/2; my $radius = ($circumference / PI / 2) - scale $self->perimeter_flow->spacing/2;
my $new_radius = (scale($self->perimeters_flow->width) + sqrt((scale($self->perimeters_flow->width)**2) + (4*($radius**2)))) / 2; my $new_radius = (scale($self->perimeter_flow->width) + sqrt((scale($self->perimeter_flow->width)**2) + (4*($radius**2)))) / 2;
# holes are always turned to contours, so reverse point order before and after # holes are always turned to contours, so reverse point order before and after
$hole->reverse; $hole->reverse;
my @offsetted = $hole->offset(+ ($new_radius - $radius)); my @offsetted = $hole->offset(+ ($new_radius - $radius));
@ -219,7 +219,7 @@ sub make_perimeters {
my @gaps = (); my @gaps = ();
# generate perimeters inwards # generate perimeters inwards
my $loop_number = $Slic3r::perimeters + ($surface->additional_inner_perimeters || 0); my $loop_number = $Slic3r::Config->perimeters + ($surface->additional_inner_perimeters || 0);
push @perimeters, []; push @perimeters, [];
for (my $loop = 0; $loop < $loop_number; $loop++) { for (my $loop = 0; $loop < $loop_number; $loop++) {
# offsetting a polygon can result in one or many offset polygons # offsetting a polygon can result in one or many offset polygons
@ -241,19 +241,19 @@ sub make_perimeters {
push @{ $perimeters[-1] }, [@last_offsets]; push @{ $perimeters[-1] }, [@last_offsets];
# offset distance for inner loops # offset distance for inner loops
$distance = scale $self->perimeters_flow->spacing; $distance = scale $self->perimeter_flow->spacing;
} }
# create one more offset to be used as boundary for fill # create one more offset to be used as boundary for fill
{ {
my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets; my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets;
$_->simplify(scale $Slic3r::resolution) for @fill_boundaries; $_->simplify(scale &Slic3r::RESOLUTION) for @fill_boundaries;
push @{ $self->surfaces }, @fill_boundaries; push @{ $self->surfaces }, @fill_boundaries;
# detect the small gaps that we need to treat like thin polygons, # detect the small gaps that we need to treat like thin polygons,
# thus generating the skeleton and using it to fill them # thus generating the skeleton and using it to fill them
push @{ $self->thin_fills }, push @{ $self->thin_fills },
map $_->medial_axis(scale $self->perimeters_flow->width), map $_->medial_axis(scale $self->perimeter_flow->width),
@gaps; @gaps;
Slic3r::debugf " %d gaps filled\n", scalar @{ $self->thin_fills } Slic3r::debugf " %d gaps filled\n", scalar @{ $self->thin_fills }
if @{ $self->thin_fills }; if @{ $self->thin_fills };
@ -323,7 +323,7 @@ sub make_perimeters {
my @thin_paths = (); my @thin_paths = ();
my %properties = ( my %properties = (
role => EXTR_ROLE_PERIMETER, role => EXTR_ROLE_PERIMETER,
flow_spacing => $self->perimeters_flow->spacing, flow_spacing => $self->perimeter_flow->spacing,
); );
for (@{ $self->thin_walls }) { for (@{ $self->thin_walls }) {
push @thin_paths, $_->isa('Slic3r::Polygon') push @thin_paths, $_->isa('Slic3r::Polygon')
@ -339,11 +339,11 @@ sub _add_perimeter {
my $self = shift; my $self = shift;
my ($polygon, $role) = @_; my ($polygon, $role) = @_;
return unless $polygon->is_printable($self->perimeters_flow->width); return unless $polygon->is_printable($self->perimeter_flow->width);
push @{ $self->perimeters }, Slic3r::ExtrusionLoop->pack( push @{ $self->perimeters }, Slic3r::ExtrusionLoop->pack(
polygon => $polygon, polygon => $polygon,
role => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER), #/ role => (abs($polygon->length) <= &Slic3r::SMALL_PERIMETER_LENGTH) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER), #/
flow_spacing => $self->perimeters_flow->spacing, flow_spacing => $self->perimeter_flow->spacing,
); );
} }
@ -354,18 +354,18 @@ sub prepare_fill_surfaces {
# if no solid layers are requested, turn top/bottom surfaces to internal # if no solid layers are requested, turn top/bottom surfaces to internal
# note that this modifies $self->surfaces in place # note that this modifies $self->surfaces in place
if ($Slic3r::solid_layers == 0) { if ($Slic3r::Config->solid_layers == 0) {
$_->surface_type(S_TYPE_INTERNAL) for grep $_->surface_type != S_TYPE_INTERNAL, @surfaces; $_->surface_type(S_TYPE_INTERNAL) for grep $_->surface_type != S_TYPE_INTERNAL, @surfaces;
} }
# if hollow object is requested, remove internal surfaces # if hollow object is requested, remove internal surfaces
if ($Slic3r::fill_density == 0) { if ($Slic3r::Config->fill_density == 0) {
@surfaces = grep $_->surface_type != S_TYPE_INTERNAL, @surfaces; @surfaces = grep $_->surface_type != S_TYPE_INTERNAL, @surfaces;
} }
# turn too small internal regions into solid regions # turn too small internal regions into solid regions
{ {
my $min_area = ((7 * $self->infill_flow->spacing / $Slic3r::scaling_factor)**2) * PI; my $min_area = ((7 * $self->infill_flow->spacing / &Slic3r::SCALING_FACTOR)**2) * PI;
my @small = grep $_->surface_type == S_TYPE_INTERNAL && $_->expolygon->contour->area <= $min_area, @surfaces; my @small = grep $_->surface_type == S_TYPE_INTERNAL && $_->expolygon->contour->area <= $min_area, @surfaces;
$_->surface_type(S_TYPE_INTERNALSOLID) for @small; $_->surface_type(S_TYPE_INTERNALSOLID) for @small;
Slic3r::debugf "identified %d small surfaces at layer %d\n", scalar(@small), $self->id if @small > 0; Slic3r::debugf "identified %d small surfaces at layer %d\n", scalar(@small), $self->id if @small > 0;
@ -379,7 +379,7 @@ sub process_bridges {
my $self = shift; my $self = shift;
# no bridges are possible if we have no internal surfaces # no bridges are possible if we have no internal surfaces
return if $Slic3r::fill_density == 0; return if $Slic3r::Config->fill_density == 0;
my @bridges = (); my @bridges = ();

View file

@ -72,7 +72,7 @@ sub safety_offset {
sub offset { sub offset {
my $self = shift; my $self = shift;
my ($distance, $scale, $joinType, $miterLimit) = @_; my ($distance, $scale, $joinType, $miterLimit) = @_;
$scale ||= $Slic3r::scaling_factor * 1000000; $scale ||= &Slic3r::SCALING_FACTOR * 1000000;
$joinType = JT_MITER if !defined $joinType; $joinType = JT_MITER if !defined $joinType;
$miterLimit ||= 2; $miterLimit ||= 2;

View file

@ -8,6 +8,7 @@ use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 PI scale unscale move_points);
use Slic3r::Geometry::Clipper qw(diff_ex union_ex intersection_ex offset JT_ROUND); use Slic3r::Geometry::Clipper qw(diff_ex union_ex intersection_ex offset JT_ROUND);
use Time::HiRes qw(gettimeofday tv_interval); use Time::HiRes qw(gettimeofday tv_interval);
has 'config' => (is => 'rw', default => sub { Slic3r::Config->new_from_defaults });
has 'objects' => (is => 'rw', default => sub {[]}); has 'objects' => (is => 'rw', default => sub {[]});
has 'copies' => (is => 'rw', default => sub {[]}); # obj_idx => [copies...] has 'copies' => (is => 'rw', default => sub {[]}); # obj_idx => [copies...]
has 'total_extrusion_length' => (is => 'rw'); has 'total_extrusion_length' => (is => 'rw');
@ -27,6 +28,49 @@ has 'brim' => (
default => sub { [] }, default => sub { [] },
); );
sub BUILD {
my $self = shift;
# store config in a handy place
$Slic3r::Config = $self->config;
# initialize extruder(s)
$Slic3r::extruders = [];
for my $t (0, map $_-1, map $self->config->get($_), qw(perimeter_extruder infill_extruder support_material_extruder)) {
$Slic3r::extruders->[$t] ||= Slic3r::Extruder->new(
map { $_ => $self->config->get($_)->[$t] // $self->config->get($_)->[0] } #/
qw(nozzle_diameter filament_diameter extrusion_multiplier temperature first_layer_temperature)
);
}
# calculate flow
$Slic3r::flow = $Slic3r::extruders->[0]->make_flow(width => $self->config->extrusion_width);
if ($self->config->first_layer_extrusion_width) {
$Slic3r::first_layer_flow = $Slic3r::extruders->[0]->make_flow(
layer_height => $self->config->get_value('first_layer_height'),
width => $self->config->first_layer_extrusion_width,
);
}
for (qw(perimeter infill support_material)) {
no strict 'refs';
${"Slic3r::${_}_flow"} = $Slic3r::extruders->[ $self->config->get("${_}_extruder")-1 ]
->make_flow(width => $self->config->get("${_}_extrusion_width") || $self->config->extrusion_width);
}
Slic3r::debugf "Default flow width = %s (spacing = %s)\n",
$Slic3r::flow->width, $Slic3r::flow->spacing;
# G-code flavors
$self->config->set('extrusion_axis', 'A') if $self->config->gcode_flavor eq 'mach3';
$self->config->set('extrusion_axis', '') if $self->config->gcode_flavor eq 'no-extrusion';
# legacy with existing config files
$self->config->set_ifndef('small_perimeter_speed', $self->config->perimeter_speed);
$self->config->set_ifndef('bridge_speed', $self->config->infill_speed);
$self->config->set_ifndef('solid_infill_speed', $self->config->infill_speed);
$self->config->set_ifndef('top_solid_infill_speed', $self->config->solid_infill_speed);
}
sub add_object_from_file { sub add_object_from_file {
my $self = shift; my $self = shift;
my ($input_file) = @_; my ($input_file) = @_;
@ -55,8 +99,8 @@ sub add_object_from_mesh {
my $self = shift; my $self = shift;
my ($mesh) = @_; my ($mesh) = @_;
$mesh->rotate($Slic3r::rotate); $mesh->rotate($Slic3r::Config->rotate);
$mesh->scale($Slic3r::scale / $Slic3r::scaling_factor); $mesh->scale($Slic3r::Config->scale / &Slic3r::SCALING_FACTOR);
$mesh->align_to_origin; $mesh->align_to_origin;
# initialize print object # initialize print object
@ -75,7 +119,7 @@ sub add_object_from_mesh {
sub validate { sub validate {
my $self = shift; my $self = shift;
if ($Slic3r::complete_objects) { if ($Slic3r::Config->complete_objects) {
# check horizontal clearance # check horizontal clearance
{ {
my @a = (); my @a = ();
@ -84,7 +128,7 @@ sub validate {
{ {
my @points = map [ @$_[X,Y] ], @{$self->objects->[$obj_idx]->mesh->vertices}; my @points = map [ @$_[X,Y] ], @{$self->objects->[$obj_idx]->mesh->vertices};
my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points)); my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points));
$clearance = +($convex_hull->offset(scale $Slic3r::extruder_clearance_radius / 2, 1, JT_ROUND))[0]; $clearance = +($convex_hull->offset(scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND))[0];
} }
for my $copy (@{$self->copies->[$obj_idx]}) { for my $copy (@{$self->copies->[$obj_idx]}) {
my $copy_clearance = $clearance->clone; my $copy_clearance = $clearance->clone;
@ -101,7 +145,7 @@ sub validate {
{ {
my @obj_copies = $self->object_copies; my @obj_copies = $self->object_copies;
pop @obj_copies; # ignore the last copy: its height doesn't matter pop @obj_copies; # ignore the last copy: its height doesn't matter
if (grep { +($self->objects->[$_->[0]]->mesh->size)[Z] > scale $Slic3r::extruder_clearance_height } @obj_copies) { if (grep { +($self->objects->[$_->[0]]->mesh->size)[Z] > scale $Slic3r::Config->extruder_clearance_height } @obj_copies) {
die "Some objects are too tall and cannot be printed without extruder collisions.\n"; die "Some objects are too tall and cannot be printed without extruder collisions.\n";
} }
} }
@ -137,26 +181,26 @@ sub layer_count {
sub duplicate { sub duplicate {
my $self = shift; my $self = shift;
if ($Slic3r::duplicate_grid->[X] > 1 || $Slic3r::duplicate_grid->[Y] > 1) { if ($Slic3r::Config->duplicate_grid->[X] > 1 || $Slic3r::Config->duplicate_grid->[Y] > 1) {
if (@{$self->objects} > 1) { if (@{$self->objects} > 1) {
die "Grid duplication is not supported with multiple objects\n"; die "Grid duplication is not supported with multiple objects\n";
} }
my $object = $self->objects->[0]; my $object = $self->objects->[0];
# generate offsets for copies # generate offsets for copies
my $dist = scale $Slic3r::duplicate_distance; my $dist = scale $Slic3r::Config->duplicate_distance;
@{$self->copies->[0]} = (); @{$self->copies->[0]} = ();
for my $x_copy (1..$Slic3r::duplicate_grid->[X]) { for my $x_copy (1..$Slic3r::Config->duplicate_grid->[X]) {
for my $y_copy (1..$Slic3r::duplicate_grid->[Y]) { for my $y_copy (1..$Slic3r::Config->duplicate_grid->[Y]) {
push @{$self->copies->[0]}, [ push @{$self->copies->[0]}, [
($object->x_length + $dist) * ($x_copy-1), ($object->x_length + $dist) * ($x_copy-1),
($object->y_length + $dist) * ($y_copy-1), ($object->y_length + $dist) * ($y_copy-1),
]; ];
} }
} }
} elsif ($Slic3r::duplicate > 1) { } elsif ($Slic3r::Config->duplicate > 1) {
foreach my $copies (@{$self->copies}) { foreach my $copies (@{$self->copies}) {
@$copies = map [0,0], 1..$Slic3r::duplicate; @$copies = map [0,0], 1..$Slic3r::Config->duplicate;
} }
$self->arrange_objects; $self->arrange_objects;
} }
@ -173,12 +217,12 @@ sub arrange_objects {
} }
# object distance is max(duplicate_distance, clearance_radius) # object distance is max(duplicate_distance, clearance_radius)
my $distance = $Slic3r::complete_objects && $Slic3r::extruder_clearance_radius > $Slic3r::duplicate_distance my $distance = $Slic3r::Config->complete_objects && $Slic3r::Config->extruder_clearance_radius > $Slic3r::Config->duplicate_distance
? $Slic3r::extruder_clearance_radius ? $Slic3r::Config->extruder_clearance_radius
: $Slic3r::duplicate_distance; : $Slic3r::Config->duplicate_distance;
my @positions = Slic3r::Geometry::arrange my @positions = Slic3r::Geometry::arrange
($total_parts, $partx, $party, (map scale $_, @$Slic3r::bed_size), scale $distance); ($total_parts, $partx, $party, (map scale $_, @$Slic3r::Config->bed_size), scale $distance);
for my $obj_idx (0..$#{$self->objects}) { for my $obj_idx (0..$#{$self->objects}) {
@{$self->copies->[$obj_idx]} = splice @positions, 0, scalar @{$self->copies->[$obj_idx]}; @{$self->copies->[$obj_idx]} = splice @positions, 0, scalar @{$self->copies->[$obj_idx]};
@ -229,7 +273,7 @@ sub export_gcode {
$_->make_perimeters for @{$self->objects}; $_->make_perimeters for @{$self->objects};
# simplify slices, we only need the max resolution for perimeters # simplify slices, we only need the max resolution for perimeters
$_->simplify(scale $Slic3r::resolution) $_->simplify(scale &Slic3r::RESOLUTION)
for map @{$_->expolygon}, map @{$_->slices}, map @{$_->layers}, @{$self->objects}; for map @{$_->expolygon}, map @{$_->slices}, map @{$_->layers}, @{$self->objects};
# this will clip $layer->surfaces to the infill boundaries # this will clip $layer->surfaces to the infill boundaries
@ -297,7 +341,7 @@ sub export_gcode {
} }
# generate support material # generate support material
if ($Slic3r::support_material) { if ($Slic3r::Config->support_material) {
$status_cb->(85, "Generating support material"); $status_cb->(85, "Generating support material");
$_->generate_support_material(print => $self) for @{$self->objects}; $_->generate_support_material(print => $self) for @{$self->objects};
} }
@ -316,10 +360,10 @@ sub export_gcode {
$self->write_gcode($output_file); $self->write_gcode($output_file);
# run post-processing scripts # run post-processing scripts
if (@$Slic3r::post_process) { if (@{$Slic3r::Config->post_process}) {
$status_cb->(95, "Running post-processing scripts"); $status_cb->(95, "Running post-processing scripts");
Slic3r::Config->setenv; $Slic3r::Config->setenv;
for (@$Slic3r::post_process) { for (@{$Slic3r::Config->post_process}) {
Slic3r::debugf " '%s' '%s'\n", $_, $output_file; Slic3r::debugf " '%s' '%s'\n", $_, $output_file;
system($_, $output_file); system($_, $output_file);
} }
@ -388,7 +432,7 @@ EOF
} }
} }
# generate support material # generate support material
if ($Slic3r::support_material && $layer_id > 0) { if ($Slic3r::Config->support_material && $layer_id > 0) {
my (@supported_slices, @unsupported_slices) = (); my (@supported_slices, @unsupported_slices) = ();
foreach my $expolygon (@current_layer_slices) { foreach my $expolygon (@current_layer_slices) {
my $intersection = intersection_ex( my $intersection = intersection_ex(
@ -420,10 +464,10 @@ EOF
sub make_skirt { sub make_skirt {
my $self = shift; my $self = shift;
return unless $Slic3r::skirts > 0; return unless $Slic3r::Config->skirts > 0;
# collect points from all layers contained in skirt height # collect points from all layers contained in skirt height
my $skirt_height = $Slic3r::skirt_height; my $skirt_height = $Slic3r::Config->skirt_height;
$skirt_height = $self->layer_count if $skirt_height > $self->layer_count; $skirt_height = $self->layer_count if $skirt_height > $self->layer_count;
my @points = (); my @points = ();
foreach my $obj_idx (0 .. $#{$self->objects}) { foreach my $obj_idx (0 .. $#{$self->objects}) {
@ -443,9 +487,9 @@ sub make_skirt {
# draw outlines from outside to inside # draw outlines from outside to inside
my $flow = $Slic3r::first_layer_flow || $Slic3r::flow; my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
my @skirt = (); my @skirt = ();
for (my $i = $Slic3r::skirts; $i > 0; $i--) { for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i)); my $distance = scale ($Slic3r::Config->skirt_distance + ($flow->spacing * $i));
my $outline = offset([$convex_hull], $distance, $Slic3r::scaling_factor * 100, JT_ROUND); my $outline = offset([$convex_hull], $distance, &Slic3r::SCALING_FACTOR * 100, JT_ROUND);
push @skirt, Slic3r::ExtrusionLoop->pack( push @skirt, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new(@{$outline->[0]}), polygon => Slic3r::Polygon->new(@{$outline->[0]}),
role => EXTR_ROLE_SKIRT, role => EXTR_ROLE_SKIRT,
@ -456,7 +500,7 @@ sub make_skirt {
sub make_brim { sub make_brim {
my $self = shift; my $self = shift;
return unless $Slic3r::brim_width > 0; return unless $Slic3r::Config->brim_width > 0;
my @islands = (); # array of polygons my @islands = (); # array of polygons
foreach my $obj_idx (0 .. $#{$self->objects}) { foreach my $obj_idx (0 .. $#{$self->objects}) {
@ -467,7 +511,7 @@ sub make_brim {
} }
my $flow = $Slic3r::first_layer_flow || $Slic3r::flow; my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
my $num_loops = sprintf "%.0f", $Slic3r::brim_width / $flow->width; my $num_loops = sprintf "%.0f", $Slic3r::Config->brim_width / $flow->width;
for my $i (reverse 1 .. $num_loops) { for my $i (reverse 1 .. $num_loops) {
push @{$self->brim}, Slic3r::ExtrusionLoop->pack( push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new($_), polygon => Slic3r::Polygon->new($_),
@ -489,14 +533,14 @@ sub write_gcode {
printf $fh "; generated by Slic3r $Slic3r::VERSION on %04d-%02d-%02d at %02d:%02d:%02d\n\n", printf $fh "; generated by Slic3r $Slic3r::VERSION on %04d-%02d-%02d at %02d:%02d:%02d\n\n",
$lt[5] + 1900, $lt[4]+1, $lt[3], $lt[2], $lt[1], $lt[0]; $lt[5] + 1900, $lt[4]+1, $lt[3], $lt[2], $lt[1], $lt[0];
print $fh "; $_\n" foreach split /\R/, $Slic3r::notes; print $fh "; $_\n" foreach split /\R/, $Slic3r::Config->notes;
print $fh "\n" if $Slic3r::notes; print $fh "\n" if $Slic3r::Config->notes;
for (qw(layer_height perimeters solid_layers fill_density perimeter_speed infill_speed travel_speed scale)) { for (qw(layer_height perimeters solid_layers fill_density perimeter_speed infill_speed travel_speed scale)) {
printf $fh "; %s = %s\n", $_, Slic3r::Config->get($_); printf $fh "; %s = %s\n", $_, $Slic3r::Config->$_;
} }
for (qw(nozzle_diameter filament_diameter extrusion_multiplier)) { for (qw(nozzle_diameter filament_diameter extrusion_multiplier)) {
printf $fh "; %s = %s\n", $_, Slic3r::Config->get($_)->[0]; printf $fh "; %s = %s\n", $_, $Slic3r::Config->$_->[0];
} }
printf $fh "; single wall width = %.2fmm\n", $Slic3r::flow->width; printf $fh "; single wall width = %.2fmm\n", $Slic3r::flow->width;
printf $fh "; first layer single wall width = %.2fmm\n", $Slic3r::first_layer_flow->width printf $fh "; first layer single wall width = %.2fmm\n", $Slic3r::first_layer_flow->width
@ -505,29 +549,29 @@ sub write_gcode {
# set up our extruder object # set up our extruder object
my $gcodegen = Slic3r::GCode->new; my $gcodegen = Slic3r::GCode->new;
my $min_print_speed = 60 * $Slic3r::min_print_speed; my $min_print_speed = 60 * $Slic3r::Config->min_print_speed;
my $dec = $gcodegen->dec; my $dec = $gcodegen->dec;
print $fh $gcodegen->set_tool(0) if @$Slic3r::extruders > 1; print $fh $gcodegen->set_tool(0) if @$Slic3r::extruders > 1;
print $fh $gcodegen->set_fan(0, 1) if $Slic3r::cooling && $Slic3r::disable_fan_first_layers; print $fh $gcodegen->set_fan(0, 1) if $Slic3r::Config->cooling && $Slic3r::Config->disable_fan_first_layers;
# write start commands to file # write start commands to file
printf $fh $gcodegen->set_bed_temperature($Slic3r::first_layer_bed_temperature, 1), printf $fh $gcodegen->set_bed_temperature($Slic3r::Config->first_layer_bed_temperature, 1),
if $Slic3r::first_layer_bed_temperature && $Slic3r::start_gcode !~ /M190/i; if $Slic3r::Config->first_layer_bed_temperature && $Slic3r::Config->start_gcode !~ /M190/i;
for my $t (grep $Slic3r::extruders->[$_], 0 .. $#$Slic3r::first_layer_temperature) { for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) {
printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 0, $t) printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 0, $t)
if $Slic3r::extruders->[$t]->first_layer_temperature; if $Slic3r::extruders->[$t]->first_layer_temperature;
} }
printf $fh "%s\n", Slic3r::Config->replace_options($Slic3r::start_gcode); printf $fh "%s\n", $Slic3r::Config->replace_options($Slic3r::Config->start_gcode);
for my $t (grep $Slic3r::extruders->[$_], 0 .. $#$Slic3r::first_layer_temperature) { for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->first_layer_temperature}) {
printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 1, $t) printf $fh $gcodegen->set_temperature($Slic3r::extruders->[$t]->first_layer_temperature, 1, $t)
if $Slic3r::extruders->[$t]->first_layer_temperature && $Slic3r::start_gcode !~ /M109/i; if $Slic3r::extruders->[$t]->first_layer_temperature && $Slic3r::Config->start_gcode !~ /M109/i;
} }
print $fh "G90 ; use absolute coordinates\n"; print $fh "G90 ; use absolute coordinates\n";
print $fh "G21 ; set units to millimeters\n"; print $fh "G21 ; set units to millimeters\n";
if ($Slic3r::gcode_flavor =~ /^(?:reprap|teacup)$/) { if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|teacup)$/) {
printf $fh $gcodegen->reset_e; printf $fh $gcodegen->reset_e;
if ($Slic3r::gcode_flavor =~ /^(?:reprap|makerbot)$/) { if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|makerbot)$/) {
if ($Slic3r::use_relative_e_distances) { if ($Slic3r::Config->use_relative_e_distances) {
print $fh "M83 ; use relative distances for extrusion\n"; print $fh "M83 ; use relative distances for extrusion\n";
} else { } else {
print $fh "M82 ; use absolute distances for extrusion\n"; print $fh "M82 ; use absolute distances for extrusion\n";
@ -538,8 +582,8 @@ sub write_gcode {
# calculate X,Y shift to center print around specified origin # calculate X,Y shift to center print around specified origin
my @print_bb = $self->bounding_box; my @print_bb = $self->bounding_box;
my @shift = ( my @shift = (
$Slic3r::print_center->[X] - (unscale ($print_bb[X2] - $print_bb[X1]) / 2) - unscale $print_bb[X1], $Slic3r::Config->print_center->[X] - (unscale ($print_bb[X2] - $print_bb[X1]) / 2) - unscale $print_bb[X1],
$Slic3r::print_center->[Y] - (unscale ($print_bb[Y2] - $print_bb[Y1]) / 2) - unscale $print_bb[Y1], $Slic3r::Config->print_center->[Y] - (unscale ($print_bb[Y2] - $print_bb[Y1]) / 2) - unscale $print_bb[Y1],
); );
# prepare the logic to print one layer # prepare the logic to print one layer
@ -550,12 +594,12 @@ sub write_gcode {
my $gcode = ""; my $gcode = "";
if ($layer_id == 1) { if ($layer_id == 1) {
for my $t (grep $Slic3r::extruders->[$_], 0 .. $#$Slic3r::temperature) { for my $t (grep $Slic3r::extruders->[$_], 0 .. $#{$Slic3r::Config->temperature}) {
$gcode .= $gcodegen->set_temperature($Slic3r::extruders->[$t]->temperature, 0, $t) $gcode .= $gcodegen->set_temperature($Slic3r::extruders->[$t]->temperature, 0, $t)
if $Slic3r::extruders->[$t]->temperature && $Slic3r::extruders->[$t]->temperature != $Slic3r::extruders->[$t]->first_layer_temperature; if $Slic3r::extruders->[$t]->temperature && $Slic3r::extruders->[$t]->temperature != $Slic3r::extruders->[$t]->first_layer_temperature;
} }
$gcode .= $gcodegen->set_bed_temperature($Slic3r::bed_temperature) $gcode .= $gcodegen->set_bed_temperature($Slic3r::Config->bed_temperature)
if $Slic3r::first_layer_bed_temperature && $Slic3r::bed_temperature != $Slic3r::first_layer_bed_temperature; if $Slic3r::Config->first_layer_bed_temperature && $Slic3r::Config->bed_temperature != $Slic3r::Config->first_layer_bed_temperature;
} }
# go to layer (just use the first one, we only need Z from it) # go to layer (just use the first one, we only need Z from it)
@ -563,12 +607,12 @@ sub write_gcode {
$gcodegen->elapsed_time(0); $gcodegen->elapsed_time(0);
# extrude skirt # extrude skirt
if ($skirt_done < $Slic3r::skirt_height) { if ($skirt_done < $Slic3r::Config->skirt_height) {
$gcodegen->shift_x($shift[X]); $gcodegen->shift_x($shift[X]);
$gcodegen->shift_y($shift[Y]); $gcodegen->shift_y($shift[Y]);
$gcode .= $gcodegen->set_acceleration($Slic3r::perimeter_acceleration); $gcode .= $gcodegen->set_acceleration($Slic3r::Config->perimeter_acceleration);
# skip skirt if we have a large brim # skip skirt if we have a large brim
if ($layer_id < $Slic3r::skirt_height && ($layer_id != 0 || $Slic3r::skirt_distance + ($Slic3r::skirts * $Slic3r::flow->width) > $Slic3r::brim_width)) { if ($layer_id < $Slic3r::Config->skirt_height && ($layer_id != 0 || $Slic3r::Config->skirt_distance + ($Slic3r::Config->skirts * $Slic3r::flow->width) > $Slic3r::Config->brim_width)) {
$gcode .= $gcodegen->extrude_loop($_, 'skirt') for @{$self->skirt}; $gcode .= $gcodegen->extrude_loop($_, 'skirt') for @{$self->skirt};
} }
$skirt_done++; $skirt_done++;
@ -592,12 +636,12 @@ sub write_gcode {
$gcodegen->shift_y($shift[Y] + unscale $copy->[Y]); $gcodegen->shift_y($shift[Y] + unscale $copy->[Y]);
# extrude perimeters # extrude perimeters
$gcode .= $gcodegen->set_tool($Slic3r::perimeter_extruder-1); $gcode .= $gcodegen->set_tool($Slic3r::Config->perimeter_extruder-1);
$gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $layer->perimeters }; $gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $layer->perimeters };
# extrude fills # extrude fills
$gcode .= $gcodegen->set_tool($Slic3r::infill_extruder-1); $gcode .= $gcodegen->set_tool($Slic3r::Config->infill_extruder-1);
$gcode .= $gcodegen->set_acceleration($Slic3r::infill_acceleration); $gcode .= $gcodegen->set_acceleration($Slic3r::Config->infill_acceleration);
for my $fill (@{ $layer->fills }) { for my $fill (@{ $layer->fills }) {
if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { if ($fill->isa('Slic3r::ExtrusionPath::Collection')) {
$gcode .= $gcodegen->extrude($_, 'fill') $gcode .= $gcodegen->extrude($_, 'fill')
@ -609,25 +653,25 @@ sub write_gcode {
# extrude support material # extrude support material
if ($layer->support_fills) { if ($layer->support_fills) {
$gcode .= $gcodegen->set_tool($Slic3r::support_material_extruder-1); $gcode .= $gcodegen->set_tool($Slic3r::Config->support_material_extruder-1);
$gcode .= $gcodegen->extrude_path($_, 'support material') $gcode .= $gcodegen->extrude_path($_, 'support material')
for $layer->support_fills->shortest_path($gcodegen->last_pos); for $layer->support_fills->shortest_path($gcodegen->last_pos);
} }
} }
return if !$gcode; return if !$gcode;
my $fan_speed = $Slic3r::fan_always_on ? $Slic3r::min_fan_speed : 0; my $fan_speed = $Slic3r::Config->fan_always_on ? $Slic3r::Config->min_fan_speed : 0;
my $speed_factor = 1; my $speed_factor = 1;
if ($Slic3r::cooling) { if ($Slic3r::Config->cooling) {
my $layer_time = $gcodegen->elapsed_time; my $layer_time = $gcodegen->elapsed_time;
Slic3r::debugf "Layer %d estimated printing time: %d seconds\n", $layer_id, $layer_time; Slic3r::debugf "Layer %d estimated printing time: %d seconds\n", $layer_id, $layer_time;
if ($layer_time < $Slic3r::slowdown_below_layer_time) { if ($layer_time < $Slic3r::Config->slowdown_below_layer_time) {
$fan_speed = $Slic3r::max_fan_speed; $fan_speed = $Slic3r::Config->max_fan_speed;
$speed_factor = $layer_time / $Slic3r::slowdown_below_layer_time; $speed_factor = $layer_time / $Slic3r::Config->slowdown_below_layer_time;
} elsif ($layer_time < $Slic3r::fan_below_layer_time) { } elsif ($layer_time < $Slic3r::Config->fan_below_layer_time) {
$fan_speed = $Slic3r::max_fan_speed - ($Slic3r::max_fan_speed - $Slic3r::min_fan_speed) $fan_speed = $Slic3r::Config->max_fan_speed - ($Slic3r::Config->max_fan_speed - $Slic3r::Config->min_fan_speed)
* ($layer_time - $Slic3r::slowdown_below_layer_time) * ($layer_time - $Slic3r::Config->slowdown_below_layer_time)
/ ($Slic3r::fan_below_layer_time - $Slic3r::slowdown_below_layer_time); #/ / ($Slic3r::Config->fan_below_layer_time - $Slic3r::Config->slowdown_below_layer_time); #/
} }
Slic3r::debugf " fan = %d%%, speed = %d%%\n", $fan_speed, $speed_factor * 100; Slic3r::debugf " fan = %d%%, speed = %d%%\n", $fan_speed, $speed_factor * 100;
@ -637,15 +681,15 @@ sub write_gcode {
$1 . sprintf("%.${dec}f", $new_speed < $min_print_speed ? $min_print_speed : $new_speed) $1 . sprintf("%.${dec}f", $new_speed < $min_print_speed ? $min_print_speed : $new_speed)
/gexm; /gexm;
} }
$fan_speed = 0 if $layer_id < $Slic3r::disable_fan_first_layers; $fan_speed = 0 if $layer_id < $Slic3r::Config->disable_fan_first_layers;
} }
$gcode = $gcodegen->set_fan($fan_speed) . $gcode; $gcode = $gcodegen->set_fan($fan_speed) . $gcode;
# bridge fan speed # bridge fan speed
if (!$Slic3r::cooling || $Slic3r::bridge_fan_speed == 0 || $layer_id < $Slic3r::disable_fan_first_layers) { if (!$Slic3r::Config->cooling || $Slic3r::Config->bridge_fan_speed == 0 || $layer_id < $Slic3r::Config->disable_fan_first_layers) {
$gcode =~ s/^;_BRIDGE_FAN_(?:START|END)\n//gm; $gcode =~ s/^;_BRIDGE_FAN_(?:START|END)\n//gm;
} else { } else {
$gcode =~ s/^;_BRIDGE_FAN_START\n/ $gcodegen->set_fan($Slic3r::bridge_fan_speed, 1) /gmex; $gcode =~ s/^;_BRIDGE_FAN_START\n/ $gcodegen->set_fan($Slic3r::Config->bridge_fan_speed, 1) /gmex;
$gcode =~ s/^;_BRIDGE_FAN_END\n/ $gcodegen->set_fan($fan_speed, 1) /gmex; $gcode =~ s/^;_BRIDGE_FAN_END\n/ $gcodegen->set_fan($fan_speed, 1) /gmex;
} }
@ -653,7 +697,7 @@ sub write_gcode {
}; };
# do all objects for each layer # do all objects for each layer
if ($Slic3r::complete_objects) { if ($Slic3r::Config->complete_objects) {
# print objects from the smallest to the tallest to avoid collisions # print objects from the smallest to the tallest to avoid collisions
# when moving onto next object starting point # when moving onto next object starting point
@ -677,10 +721,10 @@ sub write_gcode {
# another one, set first layer temperatures. this happens before the Z move # another one, set first layer temperatures. this happens before the Z move
# is triggered, so machine has more time to reach such temperatures # is triggered, so machine has more time to reach such temperatures
if ($layer_id == 0 && $finished_objects > 0) { if ($layer_id == 0 && $finished_objects > 0) {
printf $fh $gcodegen->set_bed_temperature($Slic3r::first_layer_bed_temperature), printf $fh $gcodegen->set_bed_temperature($Slic3r::Config->first_layer_bed_temperature),
if $Slic3r::first_layer_bed_temperature; if $Slic3r::Config->first_layer_bed_temperature;
printf $fh $gcodegen->set_temperature($Slic3r::first_layer_temperature) printf $fh $gcodegen->set_temperature($Slic3r::Config->first_layer_temperature)
if $Slic3r::first_layer_temperature; if $Slic3r::Config->first_layer_temperature;
} }
print $fh $extrude_layer->($layer_id, [[ $obj_idx, $copy ]]); print $fh $extrude_layer->($layer_id, [[ $obj_idx, $copy ]]);
} }
@ -703,8 +747,8 @@ sub write_gcode {
# write end commands to file # write end commands to file
print $fh $gcodegen->retract; print $fh $gcodegen->retract;
print $fh $gcodegen->set_fan(0); print $fh $gcodegen->set_fan(0);
print $fh "M501 ; reset acceleration\n" if $Slic3r::acceleration; print $fh "M501 ; reset acceleration\n" if $Slic3r::Config->acceleration;
printf $fh "%s\n", Slic3r::Config->replace_options($Slic3r::end_gcode); printf $fh "%s\n", $Slic3r::Config->replace_options($Slic3r::Config->end_gcode);
printf $fh "; filament used = %.1fmm (%.1fcm3)\n", printf $fh "; filament used = %.1fmm (%.1fcm3)\n",
$self->total_extrusion_length, $self->total_extrusion_volume; $self->total_extrusion_length, $self->total_extrusion_volume;
@ -727,12 +771,12 @@ sub expanded_output_filepath {
# if no explicit output file was defined, we take the input # if no explicit output file was defined, we take the input
# file directory and append the specified filename format # file directory and append the specified filename format
my $input_file = $self->objects->[0]->input_file; my $input_file = $self->objects->[0]->input_file;
$path ||= (fileparse($input_file))[1] . $Slic3r::output_filename_format; $path ||= (fileparse($input_file))[1] . $Slic3r::Config->output_filename_format;
my $input_filename = my $input_filename_base = basename($input_file); my $input_filename = my $input_filename_base = basename($input_file);
$input_filename_base =~ s/\.(?:stl|amf(?:\.xml)?)$//i; $input_filename_base =~ s/\.(?:stl|amf(?:\.xml)?)$//i;
return Slic3r::Config->replace_options($path, { return $Slic3r::Config->replace_options($path, {
input_filename => $input_filename, input_filename => $input_filename,
input_filename_base => $input_filename_base, input_filename_base => $input_filename_base,
}); });

View file

@ -170,18 +170,18 @@ sub make_perimeters {
# one additional inner perimeter, like the top of domed objects- # one additional inner perimeter, like the top of domed objects-
# this algorithm makes sure that almost one perimeter is overlapping # this algorithm makes sure that almost one perimeter is overlapping
if ($Slic3r::extra_perimeters && $Slic3r::perimeters > 0) { if ($Slic3r::Config->extra_perimeters && $Slic3r::Config->perimeters > 0) {
for my $layer_id (0 .. $self->layer_count-2) { for my $layer_id (0 .. $self->layer_count-2) {
my $layer = $self->layers->[$layer_id]; my $layer = $self->layers->[$layer_id];
my $upper_layer = $self->layers->[$layer_id+1]; my $upper_layer = $self->layers->[$layer_id+1];
my $overlap = $layer->perimeters_flow->spacing; # one perimeter my $overlap = $layer->perimeter_flow->spacing; # one perimeter
# compute polygons representing the thickness of the first external perimeter of # compute polygons representing the thickness of the first external perimeter of
# the upper layer slices # the upper layer slices
my $upper = diff_ex( my $upper = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(+ 0.5 * scale $layer->perimeters_flow->spacing), @{$upper_layer->slices} ], [ map @$_, map $_->expolygon->offset_ex(+ 0.5 * scale $layer->perimeter_flow->spacing), @{$upper_layer->slices} ],
[ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * scale $layer->perimeters_flow->spacing)), @{$upper_layer->slices} ], [ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * scale $layer->perimeter_flow->spacing)), @{$upper_layer->slices} ],
); );
next if !@$upper; next if !@$upper;
@ -190,22 +190,22 @@ sub make_perimeters {
my $ignore = []; my $ignore = [];
{ {
my $diff = diff_ex( my $diff = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::perimeters-0.5) * scale $layer->perimeters_flow->spacing), @{$layer->slices} ], [ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::Config->perimeters-0.5) * scale $layer->perimeter_flow->spacing), @{$layer->slices} ],
[ map @{$_->expolygon}, @{$upper_layer->slices} ], [ map @{$_->expolygon}, @{$upper_layer->slices} ],
); );
$ignore = [ map @$_, map $_->offset_ex(scale $layer->perimeters_flow->spacing), @$diff ]; $ignore = [ map @$_, map $_->offset_ex(scale $layer->perimeter_flow->spacing), @$diff ];
} }
foreach my $slice (@{$layer->slices}) { foreach my $slice (@{$layer->slices}) {
my $hypothetical_perimeter_num = $Slic3r::perimeters + 1; my $hypothetical_perimeter_num = $Slic3r::Config->perimeters + 1;
CYCLE: while (1) { CYCLE: while (1) {
# compute polygons representing the thickness of the hypotetical new internal perimeter # compute polygons representing the thickness of the hypotetical new internal perimeter
# of our slice # of our slice
my $hypothetical_perimeter; my $hypothetical_perimeter;
{ {
my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * scale $layer->perimeters_flow->spacing) ]; my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * scale $layer->perimeter_flow->spacing) ];
last CYCLE if !@$outer; last CYCLE if !@$outer;
my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * scale $layer->perimeters_flow->spacing) ]; my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * scale $layer->perimeter_flow->spacing) ];
last CYCLE if !@$inner; last CYCLE if !@$inner;
$hypothetical_perimeter = diff_ex($outer, $inner); $hypothetical_perimeter = diff_ex($outer, $inner);
} }
@ -317,14 +317,14 @@ sub discover_horizontal_shells {
foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) { foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
# find surfaces of current type for current layer # find surfaces of current type for current layer
# and offset them to take perimeters into account # and offset them to take perimeters into account
my @surfaces = map $_->offset($Slic3r::perimeters * scale $layer->perimeters_flow->width), my @surfaces = map $_->offset($Slic3r::Config->perimeters * scale $layer->perimeter_flow->width),
grep $_->surface_type == $type, @{$layer->fill_surfaces} or next; grep $_->surface_type == $type, @{$layer->fill_surfaces} or next;
my $surfaces_p = [ map $_->p, @surfaces ]; my $surfaces_p = [ map $_->p, @surfaces ];
Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n", Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n",
$i, scalar(@surfaces), ($type == S_TYPE_TOP ? 'top' : 'bottom'); $i, scalar(@surfaces), ($type == S_TYPE_TOP ? 'top' : 'bottom');
for (my $n = $type == S_TYPE_TOP ? $i-1 : $i+1; for (my $n = $type == S_TYPE_TOP ? $i-1 : $i+1;
abs($n - $i) <= $Slic3r::solid_layers-1; abs($n - $i) <= $Slic3r::Config->solid_layers-1;
$type == S_TYPE_TOP ? $n-- : $n++) { $type == S_TYPE_TOP ? $n-- : $n++) {
next if $n < 0 || $n >= $self->layer_count; next if $n < 0 || $n >= $self->layer_count;
@ -394,7 +394,7 @@ sub discover_horizontal_shells {
# combine fill surfaces across layers # combine fill surfaces across layers
sub combine_infill { sub combine_infill {
my $self = shift; my $self = shift;
return unless $Slic3r::infill_every_layers > 1 && $Slic3r::fill_density > 0; return unless $Slic3r::Config->infill_every_layers > 1 && $Slic3r::Config->fill_density > 0;
my $area_threshold = scale($Slic3r::flow->spacing) ** 2; my $area_threshold = scale($Slic3r::flow->spacing) ** 2;
@ -407,7 +407,7 @@ sub combine_infill {
# for each possible depth, look for intersections with the lower layer # for each possible depth, look for intersections with the lower layer
# we do this from the greater depth to the smaller # we do this from the greater depth to the smaller
for (my $d = $Slic3r::infill_every_layers - 1; $d >= 1; $d--) { for (my $d = $Slic3r::Config->infill_every_layers - 1; $d >= 1; $d--) {
next if ($i - $d) < 0; next if ($i - $d) < 0;
my $lower_layer = $self->layer($i - 1); my $lower_layer = $self->layer($i - 1);
@ -437,7 +437,7 @@ sub combine_infill {
push @new_surfaces, map Slic3r::Surface->new push @new_surfaces, map Slic3r::Surface->new
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $d + 1), @$intersection; (expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $d + 1), @$intersection;
foreach my $depth (reverse $d..$Slic3r::infill_every_layers) { foreach my $depth (reverse $d..$Slic3r::Config->infill_every_layers) {
push @new_surfaces, map Slic3r::Surface->new push @new_surfaces, map Slic3r::Surface->new
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth), (expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
@ -459,7 +459,7 @@ sub combine_infill {
{ {
my @new_surfaces = (); my @new_surfaces = ();
push @new_surfaces, grep $_->surface_type != S_TYPE_INTERNAL, @{$lower_layer->fill_surfaces}; push @new_surfaces, grep $_->surface_type != S_TYPE_INTERNAL, @{$lower_layer->fill_surfaces};
foreach my $depth (1..$Slic3r::infill_every_layers) { foreach my $depth (1..$Slic3r::Config->infill_every_layers) {
push @new_surfaces, map Slic3r::Surface->new push @new_surfaces, map Slic3r::Surface->new
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth), (expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
@ -486,8 +486,8 @@ sub generate_support_material {
my $self = shift; my $self = shift;
my %params = @_; my %params = @_;
my $threshold_rad = deg2rad($Slic3r::support_material_threshold + 1); # +1 makes the threshold inclusive my $threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive
my $overhang_width = $threshold_rad == 0 ? undef : scale $Slic3r::layer_height * ((cos $threshold_rad) / (sin $threshold_rad)); my $overhang_width = $threshold_rad == 0 ? undef : scale $Slic3r::Config->layer_height * ((cos $threshold_rad) / (sin $threshold_rad));
my $distance_from_object = 1.5 * scale $Slic3r::support_material_flow->width; my $distance_from_object = 1.5 * scale $Slic3r::support_material_flow->width;
# determine support regions in each layer (for upper layers) # determine support regions in each layer (for upper layers)
@ -538,14 +538,14 @@ sub generate_support_material {
@{union_ex([ map $_->contour, map @$_, values %layers ])}; @{union_ex([ map $_->contour, map @$_, values %layers ])};
my $fill = Slic3r::Fill->new(print => $params{print}); my $fill = Slic3r::Fill->new(print => $params{print});
my $filler = $fill->filler($Slic3r::support_material_pattern); my $filler = $fill->filler($Slic3r::Config->support_material_pattern);
$filler->angle($Slic3r::support_material_angle); $filler->angle($Slic3r::Config->support_material_angle);
{ {
my @patterns = (); my @patterns = ();
foreach my $expolygon (@support_material_areas) { foreach my $expolygon (@support_material_areas) {
my @paths = $filler->fill_surface( my @paths = $filler->fill_surface(
Slic3r::Surface->new(expolygon => $expolygon), Slic3r::Surface->new(expolygon => $expolygon),
density => $Slic3r::support_material_flow->spacing / $Slic3r::support_material_spacing, density => $Slic3r::support_material_flow->spacing / $Slic3r::Config->support_material_spacing,
flow_spacing => $Slic3r::support_material_flow->spacing, flow_spacing => $Slic3r::support_material_flow->spacing,
); );
my $params = shift @paths; my $params = shift @paths;

View file

@ -8,12 +8,12 @@ use constant X => 0;
use constant Y => 1; use constant Y => 1;
sub factor { sub factor {
return $Slic3r::scaling_factor * 10; return &Slic3r::SCALING_FACTOR * 10;
} }
sub svg { sub svg {
my ($print) = @_; my ($print) = @_;
$print ||= Slic3r::Print->new(x_length => 200 / $Slic3r::scaling_factor, y_length => 200 / $Slic3r::scaling_factor); $print ||= Slic3r::Print->new(x_length => 200 / &Slic3r::SCALING_FACTOR, y_length => 200 / &Slic3r::SCALING_FACTOR);
my $svg = SVG->new(width => 200 * 10, height => 200 * 10); my $svg = SVG->new(width => 200 * 10, height => 200 * 10);
my $marker_end = $svg->marker( my $marker_end = $svg->marker(

View file

@ -401,9 +401,9 @@ sub slice_facet {
} }
# calculate the layer extents # calculate the layer extents
my $min_layer = int((unscale($min_z) - ($Slic3r::_first_layer_height + $Slic3r::layer_height / 2)) / $Slic3r::layer_height) - 2; my $min_layer = int((unscale($min_z) - ($Slic3r::Config->get_value('first_layer_height') + $Slic3r::Config->layer_height / 2)) / $Slic3r::Config->layer_height) - 2;
$min_layer = 0 if $min_layer < 0; $min_layer = 0 if $min_layer < 0;
my $max_layer = int((unscale($max_z) - ($Slic3r::_first_layer_height + $Slic3r::layer_height / 2)) / $Slic3r::layer_height) + 2; my $max_layer = int((unscale($max_z) - ($Slic3r::Config->get_value('first_layer_height') + $Slic3r::Config->layer_height / 2)) / $Slic3r::Config->layer_height) + 2;
Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer; Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer;
my $lines = {}; # layer_id => [ lines ] my $lines = {}; # layer_id => [ lines ]

179
slic3r.pl
View file

@ -30,66 +30,59 @@ my %cli_options = ();
'export-svg' => \$opt{export_svg}, 'export-svg' => \$opt{export_svg},
'merge|m' => \$opt{merge}, 'merge|m' => \$opt{merge},
); );
foreach my $opt_key (keys %$Slic3r::Config::Options) { foreach my $opt_key (keys %{$Slic3r::Config::Options}) {
my $opt = $Slic3r::Config::Options->{$opt_key}; my $cli = $Slic3r::Config::Options->{$opt_key}->{cli} or next;
my $cli = $opt->{cli} or next; # allow both the dash-separated option name and the full opt_key
if ($cli =~ /-/) { $options{ "$opt_key|$cli" } = \$cli_options{$opt_key};
# allow alternative options with '_' in place of '-'
$cli = $opt_key.'|'.$cli;
}
$options{ $cli } = \$cli_options{$opt_key};
} }
GetOptions(%options) or usage(1); GetOptions(%options) or usage(1);
} }
# load configuration # process command line options
my $cli_config = Slic3r::Config->new_from_cli(%cli_options);
# load configuration files
my @external_configs = ();
if ($opt{load}) { if ($opt{load}) {
foreach my $configfile (@{$opt{load}}) { foreach my $configfile (@{$opt{load}}) {
if (-e $configfile) { if (-e $configfile) {
Slic3r::Config->load($configfile); push @external_configs, Slic3r::Config->load($configfile);
} elsif (-e "$FindBin::Bin/$configfile") { } elsif (-e "$FindBin::Bin/$configfile") {
printf STDERR "Loading $FindBin::Bin/$configfile\n"; printf STDERR "Loading $FindBin::Bin/$configfile\n";
Slic3r::Config->load("$FindBin::Bin/$configfile"); push @external_configs, Slic3r::Config->load("$FindBin::Bin/$configfile");
} else { } else {
$opt{ignore_nonexistent_config} or die "Cannot find specified configuration file ($configfile).\n"; $opt{ignore_nonexistent_config} or die "Cannot find specified configuration file ($configfile).\n";
} }
} }
} }
# validate command line options # merge configuration
delete $cli_options{$_} for grep !defined $cli_options{$_}, keys %cli_options; my $config = Slic3r::Config->new_from_defaults;
Slic3r::Config->validate_cli(\%cli_options); $config->apply($_) for @external_configs, $cli_config;
# initialize GUI # save configuration
if ($opt{save}) {
$config->validate;
$config->save($opt{save});
}
# launch GUI
my $gui; my $gui;
if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") { if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") {
$gui = Slic3r::GUI->new; $gui = Slic3r::GUI->new;
$gui->{skeinpanel}->load_config($opt{load}[0]) if $opt{load}; $gui->{skeinpanel}->load_config_file($opt{load}[0]) if $opt{load};
} $gui->{skeinpanel}->load_config($cli_config);
die $@ if $@ && $opt{gui};
# apply command line options
Slic3r::Config->set($_ => $cli_options{$_}) for keys %cli_options;
# validate configuration, convert options like --print-center to arrayrefs, init extruders etc.
# ignore errors if we're launching the GUI
eval { Slic3r::Config->validate };
die $@ if $@ && !$gui;
# save configuration
Slic3r::Config->save($opt{save}) if $opt{save};
# apply command line options to GUI as well and start it
if ($gui) {
$gui->{skeinpanel}->set_value($_, $cli_options{$_}) for keys %cli_options;
$gui->MainLoop; $gui->MainLoop;
exit; exit;
} }
die $@ if $@ && $opt{gui};
if (@ARGV) { # slicing from command line
$config->validate;
if (@ARGV) {
while (my $input_file = shift @ARGV) { while (my $input_file = shift @ARGV) {
my $print = Slic3r::Print->new; my $print = Slic3r::Print->new(config => $config);
$print->add_object_from_file($input_file); $print->add_object_from_file($input_file);
if ($opt{merge}) { if ($opt{merge}) {
$print->add_object_from_file($_) for splice @ARGV, 0; $print->add_object_from_file($_) for splice @ARGV, 0;
@ -117,10 +110,12 @@ if (@ARGV) {
sub usage { sub usage {
my ($exit_code) = @_; my ($exit_code) = @_;
my $config = Slic3r::Config->new_from_defaults;
my $j = ''; my $j = '';
if ($Slic3r::have_threads) { if ($Slic3r::have_threads) {
$j = <<"EOF"; $j = <<"EOF";
-j, --threads <num> Number of threads to use (1+, default: $Slic3r::threads) -j, --threads <num> Number of threads to use (1+, default: $config->{threads})
EOF EOF
} }
@ -143,7 +138,7 @@ $j
--output-filename-format --output-filename-format
Output file name format; all config options enclosed in brackets Output file name format; all config options enclosed in brackets
will be replaced by their values, as well as [input_filename_base] will be replaced by their values, as well as [input_filename_base]
and [input_filename] (default: $Slic3r::output_filename_format) and [input_filename] (default: $config->{output_filename_format})
--post-process Generated G-code will be processed with the supplied script; --post-process Generated G-code will be processed with the supplied script;
call this more than once to process through multiple scripts. call this more than once to process through multiple scripts.
--export-svg Export a SVG file containing slices instead of G-code. --export-svg Export a SVG file containing slices instead of G-code.
@ -151,13 +146,13 @@ $j
print rather than processed individually. print rather than processed individually.
Printer options: Printer options:
--nozzle-diameter Diameter of nozzle in mm (default: @$Slic3r::nozzle_diameter) --nozzle-diameter Diameter of nozzle in mm (default: $config->{nozzle_diameter}->[0])
--print-center Coordinates in mm of the point to center the print around --print-center Coordinates in mm of the point to center the print around
(default: $Slic3r::print_center->[0],$Slic3r::print_center->[1]) (default: $config->{print_center}->[0],$config->{print_center}->[1])
--z-offset Additional height in mm to add to vertical coordinates --z-offset Additional height in mm to add to vertical coordinates
(+/-, default: $Slic3r::z_offset) (+/-, default: $config->{z_offset})
--gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/mach3/no-extrusion, --gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/mach3/no-extrusion,
default: $Slic3r::gcode_flavor) default: $config->{gcode_flavor})
--use-relative-e-distances Enable this to get relative E values --use-relative-e-distances Enable this to get relative E values
--gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported --gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported
by all firmwares) by all firmwares)
@ -166,50 +161,50 @@ $j
--gcode-comments Make G-code verbose by adding comments (default: no) --gcode-comments Make G-code verbose by adding comments (default: no)
Filament options: Filament options:
--filament-diameter Diameter in mm of your raw filament (default: @$Slic3r::filament_diameter) --filament-diameter Diameter in mm of your raw filament (default: $config->{filament_diameter}->[0])
--extrusion-multiplier --extrusion-multiplier
Change this to alter the amount of plastic extruded. There should be Change this to alter the amount of plastic extruded. There should be
very little need to change this value, which is only useful to very little need to change this value, which is only useful to
compensate for filament packing (default: @$Slic3r::extrusion_multiplier) compensate for filament packing (default: $config->{extrusion_multiplier}->[0])
--temperature Extrusion temperature in degree Celsius, set 0 to disable (default: @$Slic3r::temperature) --temperature Extrusion temperature in degree Celsius, set 0 to disable (default: $config->{temperature}->[0])
--first-layer-temperature Extrusion temperature for the first layer, in degree Celsius, --first-layer-temperature Extrusion temperature for the first layer, in degree Celsius,
set 0 to disable (default: same as --temperature) set 0 to disable (default: same as --temperature)
--bed-temperature Heated bed temperature in degree Celsius, set 0 to disable (default: @$Slic3r::temperature) --bed-temperature Heated bed temperature in degree Celsius, set 0 to disable (default: $config->{bed_temperature})
--first-layer-bed-temperature Heated bed temperature for the first layer, in degree Celsius, --first-layer-bed-temperature Heated bed temperature for the first layer, in degree Celsius,
set 0 to disable (default: same as --bed-temperature) set 0 to disable (default: same as --bed-temperature)
Speed options: Speed options:
--travel-speed Speed of non-print moves in mm/s (default: $Slic3r::travel_speed) --travel-speed Speed of non-print moves in mm/s (default: $config->{travel_speed})
--perimeter-speed Speed of print moves for perimeters in mm/s (default: $Slic3r::perimeter_speed) --perimeter-speed Speed of print moves for perimeters in mm/s (default: $config->{perimeter_speed})
--small-perimeter-speed --small-perimeter-speed
Speed of print moves for small perimeters in mm/s or % over perimeter speed Speed of print moves for small perimeters in mm/s or % over perimeter speed
(default: $Slic3r::small_perimeter_speed) (default: $config->{small_perimeter_speed})
--external-perimeter-speed --external-perimeter-speed
Speed of print moves for the external perimeter in mm/s or % over perimeter speed Speed of print moves for the external perimeter in mm/s or % over perimeter speed
(default: $Slic3r::external_perimeter_speed) (default: $config->{external_perimeter_speed})
--infill-speed Speed of print moves in mm/s (default: $Slic3r::infill_speed) --infill-speed Speed of print moves in mm/s (default: $config->{infill_speed})
--solid-infill-speed Speed of print moves for solid surfaces in mm/s or % over infill speed --solid-infill-speed Speed of print moves for solid surfaces in mm/s or % over infill speed
(default: $Slic3r::solid_infill_speed) (default: $config->{solid_infill_speed})
--top-solid-infill-speed Speed of print moves for top surfaces in mm/s or % over solid infill speed --top-solid-infill-speed Speed of print moves for top surfaces in mm/s or % over solid infill speed
(default: $Slic3r::top_solid_infill_speed) (default: $config->{top_solid_infill_speed})
--bridge-speed Speed of bridge print moves in mm/s (default: $Slic3r::bridge_speed) --bridge-speed Speed of bridge print moves in mm/s (default: $config->{bridge_speed})
--first-layer-speed Speed of print moves for bottom layer, expressed either as an absolute --first-layer-speed Speed of print moves for bottom layer, expressed either as an absolute
value or as a percentage over normal speeds (default: $Slic3r::first_layer_speed) value or as a percentage over normal speeds (default: $config->{first_layer_speed})
Accuracy options: Accuracy options:
--layer-height Layer height in mm (default: $Slic3r::layer_height) --layer-height Layer height in mm (default: $config->{layer_height})
--first-layer-height Layer height for first layer (mm or %, default: $Slic3r::first_layer_height) --first-layer-height Layer height for first layer (mm or %, default: $config->{first_layer_height})
--infill-every-layers --infill-every-layers
Infill every N layers (default: $Slic3r::infill_every_layers) Infill every N layers (default: $config->{infill_every_layers})
Print options: Print options:
--perimeters Number of perimeters/horizontal skins (range: 0+, default: $Slic3r::perimeters) --perimeters Number of perimeters/horizontal skins (range: 0+, default: $config->{perimeters})
--solid-layers Number of solid layers to do for top/bottom surfaces --solid-layers Number of solid layers to do for top/bottom surfaces
(range: 1+, default: $Slic3r::solid_layers) (range: 1+, default: $config->{solid_layers})
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density) --fill-density Infill density (range: 0-1, default: $config->{fill_density})
--fill-angle Infill angle in degrees (range: 0-90, default: $Slic3r::fill_angle) --fill-angle Infill angle in degrees (range: 0-90, default: $config->{fill_angle})
--fill-pattern Pattern to use to fill non-solid layers (default: $Slic3r::fill_pattern) --fill-pattern Pattern to use to fill non-solid layers (default: $config->{fill_pattern})
--solid-fill-pattern Pattern to use to fill solid layers (default: $Slic3r::solid_fill_pattern) --solid-fill-pattern Pattern to use to fill solid layers (default: $config->{solid_fill_pattern})
--start-gcode Load initial G-code from the supplied file. This will overwrite --start-gcode Load initial G-code from the supplied file. This will overwrite
the default command (home all axes [G28]). the default command (home all axes [G28]).
--end-gcode Load final G-code from the supplied file. This will overwrite --end-gcode Load final G-code from the supplied file. This will overwrite
@ -222,62 +217,62 @@ $j
Support material options: Support material options:
--support-material Generate support material for overhangs --support-material Generate support material for overhangs
--support-material-threshold --support-material-threshold
Overhang threshold angle (range: 0-90, default: $Slic3r::support_material_threshold) Overhang threshold angle (range: 0-90, default: $config->{support_material_threshold})
--support-material-pattern --support-material-pattern
Pattern to use for support material (default: $Slic3r::support_material_pattern) Pattern to use for support material (default: $config->{support_material_pattern})
--support-material-spacing --support-material-spacing
Spacing between pattern lines (mm, default: $Slic3r::support_material_spacing) Spacing between pattern lines (mm, default: $config->{support_material_spacing})
--support-material-angle --support-material-angle
Support material angle in degrees (range: 0-90, default: $Slic3r::support_material_angle) Support material angle in degrees (range: 0-90, default: $config->{support_material_angle})
Retraction options: Retraction options:
--retract-length Length of retraction in mm when pausing extrusion --retract-length Length of retraction in mm when pausing extrusion
(default: $Slic3r::retract_length) (default: $config->{retract_length})
--retract-speed Speed for retraction in mm/s (default: $Slic3r::retract_speed) --retract-speed Speed for retraction in mm/s (default: $config->{retract_speed})
--retract-restart-extra --retract-restart-extra
Additional amount of filament in mm to push after Additional amount of filament in mm to push after
compensating retraction (default: $Slic3r::retract_restart_extra) compensating retraction (default: $config->{retract_restart_extra})
--retract-before-travel --retract-before-travel
Only retract before travel moves of this length in mm (default: $Slic3r::retract_before_travel) Only retract before travel moves of this length in mm (default: $config->{retract_before_travel})
--retract-lift Lift Z by the given distance in mm when retracting (default: $Slic3r::retract_lift) --retract-lift Lift Z by the given distance in mm when retracting (default: $config->{retract_lift})
Cooling options: Cooling options:
--cooling Enable fan and cooling control --cooling Enable fan and cooling control
--min-fan-speed Minimum fan speed (default: $Slic3r::min_fan_speed%) --min-fan-speed Minimum fan speed (default: $config->{min_fan_speed}%)
--max-fan-speed Maximum fan speed (default: $Slic3r::max_fan_speed%) --max-fan-speed Maximum fan speed (default: $config->{max_fan_speed}%)
--bridge-fan-speed Fan speed to use when bridging (default: $Slic3r::bridge_fan_speed%) --bridge-fan-speed Fan speed to use when bridging (default: $config->{bridge_fan_speed}%)
--fan-below-layer-time Enable fan if layer print time is below this approximate number --fan-below-layer-time Enable fan if layer print time is below this approximate number
of seconds (default: $Slic3r::fan_below_layer_time) of seconds (default: $config->{fan_below_layer_time})
--slowdown-below-layer-time Slow down if layer print time is below this approximate number --slowdown-below-layer-time Slow down if layer print time is below this approximate number
of seconds (default: $Slic3r::slowdown_below_layer_time) of seconds (default: $config->{slowdown_below_layer_time})
--min-print-speed Minimum print speed (mm/s, default: $Slic3r::min_print_speed) --min-print-speed Minimum print speed (mm/s, default: $config->{min_print_speed})
--disable-fan-first-layers Disable fan for the first N layers (default: $Slic3r::disable_fan_first_layers) --disable-fan-first-layers Disable fan for the first N layers (default: $config->{disable_fan_first_layers})
--fan-always-on Keep fan always on at min fan speed, even for layers that don't need --fan-always-on Keep fan always on at min fan speed, even for layers that don't need
cooling cooling
Skirt options: Skirt options:
--skirts Number of skirts to draw (0+, default: $Slic3r::skirts) --skirts Number of skirts to draw (0+, default: $config->{skirts})
--skirt-distance Distance in mm between innermost skirt and object --skirt-distance Distance in mm between innermost skirt and object
(default: $Slic3r::skirt_distance) (default: $config->{skirt_distance})
--skirt-height Height of skirts to draw (expressed in layers, 0+, default: $Slic3r::skirt_height) --skirt-height Height of skirts to draw (expressed in layers, 0+, default: $config->{skirt_height})
--brim-width Width of the brim that will get added to each object to help adhesion --brim-width Width of the brim that will get added to each object to help adhesion
(mm, default: $Slic3r::brim_width) (mm, default: $config->{brim_width})
Transform options: Transform options:
--scale Factor for scaling input object (default: $Slic3r::scale) --scale Factor for scaling input object (default: $config->{scale})
--rotate Rotation angle in degrees (0-360, default: $Slic3r::rotate) --rotate Rotation angle in degrees (0-360, default: $config->{rotate})
--duplicate Number of items with auto-arrange (1+, default: $Slic3r::duplicate) --duplicate Number of items with auto-arrange (1+, default: $config->{duplicate})
--bed-size Bed size, only used for auto-arrange (mm, default: $Slic3r::bed_size->[0],$Slic3r::bed_size->[1]) --bed-size Bed size, only used for auto-arrange (mm, default: $config->{bed_size}->[0],$config->{bed_size}->[1])
--duplicate-grid Number of items with grid arrangement (default: $Slic3r::duplicate_grid->[0],$Slic3r::duplicate_grid->[1]) --duplicate-grid Number of items with grid arrangement (default: $config->{duplicate_grid}->[0],$config->{duplicate_grid}->[1])
--duplicate-distance Distance in mm between copies (default: $Slic3r::duplicate_distance) --duplicate-distance Distance in mm between copies (default: $config->{duplicate_distance})
Sequential printing options: Sequential printing options:
--complete-objects When printing multiple objects and/or copies, complete each one before --complete-objects When printing multiple objects and/or copies, complete each one before
starting the next one; watch out for extruder collisions (default: no) starting the next one; watch out for extruder collisions (default: no)
--extruder-clearance-radius Radius in mm above which extruder won't collide with anything --extruder-clearance-radius Radius in mm above which extruder won't collide with anything
(default: $Slic3r::extruder_clearance_radius) (default: $config->{extruder_clearance_radius})
--extruder-clearance-height Maximum vertical extruder depth; i.e. vertical distance from --extruder-clearance-height Maximum vertical extruder depth; i.e. vertical distance from
extruder tip and carriage bottom (default: $Slic3r::extruder_clearance_height) extruder tip and carriage bottom (default: $config->{extruder_clearance_height})
Miscellaneous options: Miscellaneous options:
--notes Notes to be added as comments to the output file --notes Notes to be added as comments to the output file
@ -293,7 +288,7 @@ $j
Set a different extrusion width for infill Set a different extrusion width for infill
--support-material-extrusion-width --support-material-extrusion-width
Set a different extrusion width for support material Set a different extrusion width for support material
--bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: $Slic3r::bridge_flow_ratio) --bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: $config->{bridge_flow_ratio})
Multiple extruder options: Multiple extruder options:
--perimeters-extruder --perimeters-extruder