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.
degen-loop-screen
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;
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
our $notes = '';
# output options
our $output_filename_format = '[input_filename_base].gcode';
our $post_process = [];
# 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
# The following variables hold the objects used throughout the slicing
# process. They should belong to the Print object, but we are keeping
# them here because it makes accessing them slightly faster.
our $Config;
our $extruders;
our ($flow, $first_layer_flow, $perimeter_flow, $infill_flow, $support_material_flow);
sub parallelize {
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;
$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) };
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);
}
} else {

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -29,15 +29,15 @@ sub mm3_per_mm {
my $cache_key = "${s}_${h}";
if (!exists $self->_mm3_per_mm_cache->{$cache_key}) {
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) {
# 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);
} else {
# 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;
}
}

View File

@ -159,7 +159,7 @@ sub detect_arcs {
my ($max_angle, $len_epsilon) = @_;
$max_angle = deg2rad($max_angle || 15);
$len_epsilon ||= 10 / $Slic3r::scaling_factor;
$len_epsilon ||= 10 / &Slic3r::SCALING_FACTOR;
my @points = @{$self->points};
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);
$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 {
@ -131,8 +131,8 @@ sub make_fill {
my @fills = ();
my @fills_ordering_points = ();
SURFACE: foreach my $surface (@surfaces) {
my $filler = $Slic3r::fill_pattern;
my $density = $Slic3r::fill_density;
my $filler = $Slic3r::Config->fill_pattern;
my $density = $Slic3r::Config->fill_density;
my $flow_spacing = $layer->infill_flow->spacing;
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;
@ -140,10 +140,10 @@ sub make_fill {
# force 100% density and rectilinear fill for external surfaces
if ($surface->surface_type != S_TYPE_INTERNAL) {
$density = 1;
$filler = $Slic3r::solid_fill_pattern;
$filler = $Slic3r::Config->solid_fill_pattern;
if ($is_bridge) {
$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) {
$filler = 'rectilinear';
}
@ -181,7 +181,7 @@ sub make_fill {
{
my %args = (
role => EXTR_ROLE_SOLIDFILL,
flow_spacing => $layer->perimeters_flow->spacing,
flow_spacing => $layer->perimeter_flow->spacing,
);
push @fills, map {
$_->isa('Slic3r::Polygon')

View File

@ -5,7 +5,7 @@ use Moo;
has 'print' => (is => 'rw');
has 'layer' => (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);

View File

@ -4,7 +4,7 @@ use Moo;
use Slic3r::Geometry qw(PI);
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 'spacing' => (is => 'lazy');
@ -52,7 +52,7 @@ sub _build_spacing {
# rectangle with shrunk semicircles at the ends
$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;

View File

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

View File

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

View File

@ -372,7 +372,7 @@ sub apply {
$self->SUPER::apply;
# 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]);
}
@ -395,7 +395,7 @@ sub apply {
$self->SUPER::apply;
# 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('layer_height', $nozzle->[0] - 0.1);
}
@ -435,7 +435,7 @@ sub apply {
$self->SUPER::apply;
# 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]);
}
@ -459,7 +459,7 @@ sub apply {
$self->SUPER::apply;
# 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);
}

View File

@ -1,6 +1,7 @@
package Slic3r::GUI::OptionsGroup;
use Moo;
use List::Util qw(first);
use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl);
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 => [],
values => [],
default => 0.4, # mandatory
readonly => 0,
on_change => sub { print "new value is $_[0]\n" },
},
],
@ -86,6 +88,7 @@ sub BUILD {
$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::TextCtrl->new($self->parent, -1, $opt->{default}, wxDefaultPosition, $size, $style);
$field->Disable if $opt->{readonly};
$self->_setters->{$opt_key} = sub { $field->SetValue($_[0]) };
my $on_change = sub { $self->_on_change($opt_key, $field->GetValue) };
@ -145,6 +148,13 @@ sub BUILD {
$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 {
my $self = shift;
my ($opt_key, $value) = @_;
@ -189,6 +199,7 @@ Slic3r::GUI::ConfigOptionsGroup - pre-filled Wx::StaticBoxSizer wrapper containi
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
parent => $self->parent,
title => 'Layers',
config => $config,
options => ['layer_height'],
on_change => sub { print "new value for $_[0] is $_[1]\n" },
no_labels => 0,
@ -198,7 +209,7 @@ Slic3r::GUI::ConfigOptionsGroup - pre-filled Wx::StaticBoxSizer wrapper containi
=cut
use List::Util qw(first);
has 'config' => (is => 'ro', required => 1);
sub _trigger_options {
my $self = shift;
@ -212,7 +223,7 @@ sub _trigger_options {
$opt = {
opt_key => $full_key,
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),
on_change => sub { $self->_set_config($opt_key, $index, $_[0]) },
};
@ -225,7 +236,10 @@ sub set_value {
my $self = shift;
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);
}
@ -234,7 +248,8 @@ sub set_value {
my ($key, $index) = $self->_split_key($full_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;
}
}
@ -252,11 +267,14 @@ sub _split_key {
sub _get_config {
my $self = shift;
my ($opt_key, $index, $value) = @_;
my ($opt_key, $index) = @_;
my ($get_m, $set_m) = $self->_config_methods($opt_key, $index);
$value ||= Slic3r::Config->$get_m($opt_key);
$value = $value->[$index] if defined $index;
my ($get_m, $serialized) = $self->_config_methods($opt_key, $index);
my $value = $self->config->$get_m($opt_key);
if (defined $index) {
$value->[$index] //= $value->[0]; #/
$value = $value->[$index];
}
return $value;
}
@ -264,10 +282,10 @@ sub _set_config {
my $self = shift;
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
? Slic3r::Config->$get_m($opt_key)->[$index] = $value
: Slic3r::Config->$set_m($opt_key, $value);
? $self->config->$get_m($opt_key)->[$index] = $value
: $self->config->set($opt_key, $value, $serialized);
}
sub _config_methods {
@ -275,9 +293,9 @@ sub _config_methods {
my ($opt_key, $index) = @_;
# if it's an array type but no index was specified, use the serialized version
return $Slic3r::Config::Options->{$opt_key}{type} =~ /\@$/ && !defined $index
? qw(serialize deserialize)
: qw(get_raw set);
return ($Slic3r::Config::Options->{$opt_key}{type} =~ /\@$/ && !defined $index)
? qw(serialize 1)
: qw(get 0);
}
1;

View File

@ -26,10 +26,17 @@ my $MESSAGE_DIALOG_EVENT : shared = Wx::NewEventType;
my $EXPORT_COMPLETED_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 {
my $class = shift;
my ($parent) = @_;
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}->SetBackgroundColour(Wx::wxWHITE);
@ -173,7 +180,7 @@ sub new {
$self->on_export_failed;
});
$self->update_bed_size;
$self->_update_bed_size;
$self->{print} = Slic3r::Print->new;
$self->{thumbnails} = []; # polygons, each one aligned to 0,0
$self->{scale} = [];
@ -229,6 +236,11 @@ sub new {
return $self;
}
sub skeinpanel {
my $self = shift;
return $self->GetParent->GetParent;
}
sub load {
my $self = shift;
@ -428,7 +440,7 @@ sub split_object {
my $current_object = $self->{print}->objects->[$obj_idx];
my $current_copies_num = @{$self->{print}->copies->[$obj_idx]};
my $mesh = $current_object->mesh->clone;
$mesh->scale($Slic3r::scaling_factor);
$mesh->scale(&Slic3r::SCALING_FACTOR);
my @new_meshes = $mesh->split_mesh;
if (@new_meshes == 1) {
@ -517,10 +529,9 @@ sub export_gcode2 {
} if $Slic3r::have_threads;
eval {
# validate configuration
Slic3r::Config->validate;
my $print = $self->{print};
$print->config($self->skeinpanel->config);
$print->config->validate;
$print->validate;
{
@ -607,7 +618,7 @@ sub export_stl {
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;
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;
# supposing the preview canvas is square, calculate the scaling factor
# to constrain print bed area inside preview
my $bed_size = $self->{config}->bed_size;
my $canvas_side = $self->{canvas}->GetSize->GetWidth;
my $bed_largest_side = $Slic3r::bed_size->[X] > $Slic3r::bed_size->[Y]
? $Slic3r::bed_size->[X] : $Slic3r::bed_size->[Y];
my $bed_largest_side = $bed_size->[X] > $bed_size->[Y] ? $bed_size->[X] : $bed_size->[Y];
my $old_scaling_factor = $self->{scaling_factor};
$self->{scaling_factor} = $canvas_side / $bed_largest_side;
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 {
my ($self, $event) = @_;
my $parent = $self->GetParent;
@ -681,9 +700,6 @@ sub repaint {
my $size = $self->GetSize;
my @size = ($size->GetWidth, $size->GetHeight);
# calculate scaling factor for preview
$parent->update_bed_size;
# draw grid
$dc->SetPen($parent->{grid_pen});
my $step = 10 * $parent->{scaling_factor};
@ -701,8 +717,8 @@ sub repaint {
$dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2);
$dc->SetTextForeground(Wx::Colour->new(0,0,0));
$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->DrawRotatedText("Y = " . $Slic3r::print_center->[Y], 0, $size[Y]/2+15, 90);
$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 = " . $parent->{config}->print_center->[Y], 0, $size[Y]/2+15, 90);
}
# draw frame
@ -714,7 +730,7 @@ sub repaint {
if (!@{$print->objects}) {
$dc->SetTextForeground(Wx::Colour->new(150,50,50));
$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
@ -738,8 +754,8 @@ sub repaint {
$dc->DrawPolygon($parent->_y($parent->{object_previews}->[-1][2]), 0, 0);
# if sequential printing is enabled and we have more than one object
if ($Slic3r::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];
if ($parent->{config}->complete_objects && (map @$_, @{$print->copies}) > 1) {
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->SetBrush($parent->{transparent_brush});
$dc->DrawPolygon($parent->_y($clearance), 0, 0);
@ -748,9 +764,9 @@ sub repaint {
}
# 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}} ]));
$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->SetBrush($parent->{transparent_brush});
$dc->DrawPolygon($parent->_y($convex_hull), 0, 0) if $convex_hull;
@ -853,7 +869,7 @@ sub selected_object_idx {
sub statusbar {
my $self = shift;
return $self->GetParent->GetParent->GetParent->{statusbar};
return $self->skeinpanel->GetParent->{statusbar};
}
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}),
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}{filament}, $self->{options_tabs}{filament}->title);
$self->{tabpanel}->AddPage($self->{options_tabs}{printer}, $self->{options_tabs}{printer}->title);
@ -53,11 +57,12 @@ sub do_slice {
my $process_dialog;
eval {
# validate configuration
Slic3r::Config->validate;
my $config = $self->config;
$config->validate;
# confirm slicing of more than one copies
my $copies = $Slic3r::duplicate_grid->[X] * $Slic3r::duplicate_grid->[Y];
$copies = $Slic3r::duplicate if $Slic3r::duplicate > 1;
my $copies = $Slic3r::Config->duplicate_grid->[X] * $Slic3r::Config->duplicate_grid->[Y];
$copies = $Slic3r::Config->duplicate if $Slic3r::Config->duplicate > 1;
if ($copies > 1) {
my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?",
'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL);
@ -93,7 +98,7 @@ sub do_slice {
my $input_file_basename = basename($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->validate;
@ -160,12 +165,12 @@ sub do_slice {
sub save_config {
my $self = shift;
my $process_dialog;
my $config = $self->config;
eval {
# 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 $filename = $last_config ? basename($last_config) : "config.ini";
@ -175,12 +180,12 @@ sub save_config {
my $file = $dlg->GetPath;
$last_config_dir = dirname($file);
$last_config = $file;
Slic3r::Config->save($file);
$config->save($file);
}
$dlg->Destroy;
}
sub load_config {
sub load_config_file {
my $self = shift;
my ($file) = @_;
@ -198,15 +203,40 @@ sub load_config {
$_->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 {
my $self = shift;
return unless $self->check_unsaved_changes;
if (my %settings = Slic3r::GUI::ConfigWizard->new($self)->run) {
$self->set_value($_, $settings{$_}) for keys %settings;
if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) {
# 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 {
my $self = shift;
my ($opt_key, $value) = @_;

View File

@ -13,6 +13,7 @@ sub new {
my $class = shift;
my ($parent, %params) = @_;
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};
EVT_CHOICE($parent, $self->{sync_presets_with}, sub {
@ -100,8 +101,8 @@ sub new {
);
return unless $dlg->ShowModal == wxID_OK;
my $file = sprintf "$Slic3r::GUI::datadir/$self->{presets_group}/%s.ini", $dlg->get_name;
Slic3r::Config->save($file, $self->{presets_group});
my $file = sprintf "$Slic3r::GUI::datadir/%s/%s.ini", $self->name, $dlg->get_name;
$self->{config}->save($file);
$self->set_dirty(0);
$self->load_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->{config} = Slic3r::Config->new;
$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;
}
@ -135,8 +142,15 @@ sub current_preset {
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 hidden_options {}
sub config { $_[0]->{config}->clone }
sub on_select_preset {
my $self = shift;
@ -155,7 +169,7 @@ sub on_select_preset {
my $preset = $self->current_preset;
if ($preset->{default}) {
# 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;
} else {
if (!-e $preset->{file}) {
@ -164,7 +178,7 @@ sub on_select_preset {
}
eval {
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);
$preset->{external}
@ -174,8 +188,8 @@ sub on_select_preset {
$self->on_preset_loaded;
$self->reload_values;
$self->set_dirty(0);
$Slic3r::Settings->{presets}{$self->{presets_group}} = $preset->{file} ? basename($preset->{file}) : '';
Slic3r::Config->save_settings("$Slic3r::GUI::datadir/slic3r.ini");
$Slic3r::GUI::Settings->{presets}{$self->name} = $preset->{file} ? basename($preset->{file}) : '';
Slic3r::GUI->save_settings("$Slic3r::GUI::datadir/slic3r.ini");
}
sub add_options_page {
@ -188,6 +202,19 @@ sub add_options_page {
$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 {
$self->on_value_change(@_);
$self->set_dirty(1);
@ -214,8 +241,7 @@ sub set_value {
sub reload_values {
my $self = shift;
my $current = Slic3r::Config->current;
$self->set_value($_, $current->{$_}) for keys %$current;
$self->set_value($_, $self->{config}->get($_)) for keys %{$self->{config}};
}
sub update_tree {
@ -262,20 +288,18 @@ sub is_dirty {
sub load_presets {
my $self = shift;
my ($group) = @_;
$self->{presets_group} ||= $group;
$self->{presets} = [{
default => 1,
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) {
my $name = basename($file);
$name =~ s/\.ini$//;
push @{$self->{presets}}, {
file => "$Slic3r::GUI::datadir/$self->{presets_group}/$file",
file => "$Slic3r::GUI::datadir/" . $self->name . "/$file",
name => $name,
};
}
@ -285,7 +309,7 @@ sub load_presets {
$self->{presets_choice}->Append($_->{name}) for @{$self->{presets}};
{
# 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->on_select_preset;
}
@ -326,6 +350,7 @@ sub sync_presets {
package Slic3r::GUI::Tab::Print;
use base 'Slic3r::GUI::Tab';
sub name { 'print' }
sub title { 'Print Settings' }
sub build {
@ -422,16 +447,17 @@ sub build {
},
{
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;
use base 'Slic3r::GUI::Tab';
sub name { 'filament' }
sub title { 'Filament Settings' }
sub build {
@ -463,13 +489,12 @@ sub build {
options => [qw(fan_below_layer_time slowdown_below_layer_time min_print_speed)],
},
]);
$self->load_presets('filament');
}
package Slic3r::GUI::Tab::Printer;
use base 'Slic3r::GUI::Tab';
sub name { 'printer' }
sub title { 'Printer Settings' }
sub build {
@ -521,22 +546,28 @@ sub build {
]);
$self->{extruder_pages} = [];
$self->build_extruder_pages;
$self->load_presets('printer');
$self->_build_extruder_pages;
}
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;
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
$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;
}
# 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
$self->build_extruder_pages;
$self->_build_extruder_pages;
# update page list and select first page (General)
$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 {
my $self = shift;
# update the extruders count field
{
# 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
$self->on_value_change('extruders_count');
@ -617,7 +642,11 @@ sub new {
$self->SetSizer($self->{vsizer});
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;
@ -627,7 +656,12 @@ sub append_optgroup {
my $self = shift;
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);
push @{$self->{optgroups}}, $optgroup;
}

View File

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

View File

@ -20,7 +20,7 @@ has 'slice_z' => (is => 'lazy');
has 'print_z' => (is => 'lazy');
has 'height' => (is => 'lazy');
has 'flow' => (is => 'lazy');
has 'perimeters_flow' => (is => 'lazy');
has 'perimeter_flow' => (is => 'lazy');
has 'infill_flow' => (is => 'lazy');
# collection of spare segments generated by slicing the original geometry;
@ -61,21 +61,21 @@ sub _build_slice_z {
my $self = shift;
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))
/ $Slic3r::scaling_factor; #/
return ($Slic3r::Config->get_value('first_layer_height') + (($self->id-1) * $Slic3r::Config->layer_height) + ($Slic3r::Config->layer_height/2))
/ &Slic3r::SCALING_FACTOR; #/
}
# Z used for printing
sub _build_print_z {
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 {
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 {
@ -85,11 +85,11 @@ sub _build_flow {
: $Slic3r::flow;
}
sub _build_perimeters_flow {
sub _build_perimeter_flow {
my $self = shift;
return $self->id == 0 && $Slic3r::first_layer_flow
? $Slic3r::first_layer_flow
: $Slic3r::perimeters_flow;
: $Slic3r::perimeter_flow;
}
sub _build_infill_flow {
@ -120,7 +120,7 @@ sub make_surfaces {
# 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};
@{$self->slices} = ();
foreach my $surface (@surfaces) {
@ -141,10 +141,10 @@ sub make_surfaces {
$self->thin_walls([]);
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;
@{$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};
}
@ -163,7 +163,7 @@ sub make_perimeters {
my $self = shift;
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);
# each item of this arrayref is an arrayref representing a depth (from outer
@ -197,7 +197,7 @@ sub make_perimeters {
if (0) {
foreach my $hole ($last_offsets[0]->holes) {
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
# overcompensate for hexagons and other shapes having straight edges.
# 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
# of the hole
my $radius = ($circumference / PI / 2) - scale $self->perimeters_flow->spacing/2;
my $new_radius = (scale($self->perimeters_flow->width) + sqrt((scale($self->perimeters_flow->width)**2) + (4*($radius**2)))) / 2;
my $radius = ($circumference / PI / 2) - scale $self->perimeter_flow->spacing/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
$hole->reverse;
my @offsetted = $hole->offset(+ ($new_radius - $radius));
@ -219,7 +219,7 @@ sub make_perimeters {
my @gaps = ();
# 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, [];
for (my $loop = 0; $loop < $loop_number; $loop++) {
# offsetting a polygon can result in one or many offset polygons
@ -241,19 +241,19 @@ sub make_perimeters {
push @{ $perimeters[-1] }, [@last_offsets];
# 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
{
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;
# detect the small gaps that we need to treat like thin polygons,
# thus generating the skeleton and using it to fill them
push @{ $self->thin_fills },
map $_->medial_axis(scale $self->perimeters_flow->width),
map $_->medial_axis(scale $self->perimeter_flow->width),
@gaps;
Slic3r::debugf " %d gaps filled\n", scalar @{ $self->thin_fills }
if @{ $self->thin_fills };
@ -323,7 +323,7 @@ sub make_perimeters {
my @thin_paths = ();
my %properties = (
role => EXTR_ROLE_PERIMETER,
flow_spacing => $self->perimeters_flow->spacing,
flow_spacing => $self->perimeter_flow->spacing,
);
for (@{ $self->thin_walls }) {
push @thin_paths, $_->isa('Slic3r::Polygon')
@ -339,11 +339,11 @@ sub _add_perimeter {
my $self = shift;
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(
polygon => $polygon,
role => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER), #/
flow_spacing => $self->perimeters_flow->spacing,
role => (abs($polygon->length) <= &Slic3r::SMALL_PERIMETER_LENGTH) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER), #/
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
# 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;
}
# 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;
}
# 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;
$_->surface_type(S_TYPE_INTERNALSOLID) for @small;
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;
# 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 = ();

View File

@ -72,7 +72,7 @@ sub safety_offset {
sub offset {
my $self = shift;
my ($distance, $scale, $joinType, $miterLimit) = @_;
$scale ||= $Slic3r::scaling_factor * 1000000;
$scale ||= &Slic3r::SCALING_FACTOR * 1000000;
$joinType = JT_MITER if !defined $joinType;
$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 Time::HiRes qw(gettimeofday tv_interval);
has 'config' => (is => 'rw', default => sub { Slic3r::Config->new_from_defaults });
has 'objects' => (is => 'rw', default => sub {[]});
has 'copies' => (is => 'rw', default => sub {[]}); # obj_idx => [copies...]
has 'total_extrusion_length' => (is => 'rw');
@ -27,6 +28,49 @@ has 'brim' => (
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 {
my $self = shift;
my ($input_file) = @_;
@ -55,8 +99,8 @@ sub add_object_from_mesh {
my $self = shift;
my ($mesh) = @_;
$mesh->rotate($Slic3r::rotate);
$mesh->scale($Slic3r::scale / $Slic3r::scaling_factor);
$mesh->rotate($Slic3r::Config->rotate);
$mesh->scale($Slic3r::Config->scale / &Slic3r::SCALING_FACTOR);
$mesh->align_to_origin;
# initialize print object
@ -75,7 +119,7 @@ sub add_object_from_mesh {
sub validate {
my $self = shift;
if ($Slic3r::complete_objects) {
if ($Slic3r::Config->complete_objects) {
# check horizontal clearance
{
my @a = ();
@ -84,7 +128,7 @@ sub validate {
{
my @points = map [ @$_[X,Y] ], @{$self->objects->[$obj_idx]->mesh->vertices};
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]}) {
my $copy_clearance = $clearance->clone;
@ -101,7 +145,7 @@ sub validate {
{
my @obj_copies = $self->object_copies;
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";
}
}
@ -137,26 +181,26 @@ sub layer_count {
sub duplicate {
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) {
die "Grid duplication is not supported with multiple objects\n";
}
my $object = $self->objects->[0];
# generate offsets for copies
my $dist = scale $Slic3r::duplicate_distance;
my $dist = scale $Slic3r::Config->duplicate_distance;
@{$self->copies->[0]} = ();
for my $x_copy (1..$Slic3r::duplicate_grid->[X]) {
for my $y_copy (1..$Slic3r::duplicate_grid->[Y]) {
for my $x_copy (1..$Slic3r::Config->duplicate_grid->[X]) {
for my $y_copy (1..$Slic3r::Config->duplicate_grid->[Y]) {
push @{$self->copies->[0]}, [
($object->x_length + $dist) * ($x_copy-1),
($object->y_length + $dist) * ($y_copy-1),
];
}
}
} elsif ($Slic3r::duplicate > 1) {
} elsif ($Slic3r::Config->duplicate > 1) {
foreach my $copies (@{$self->copies}) {
@$copies = map [0,0], 1..$Slic3r::duplicate;
@$copies = map [0,0], 1..$Slic3r::Config->duplicate;
}
$self->arrange_objects;
}
@ -173,12 +217,12 @@ sub arrange_objects {
}
# object distance is max(duplicate_distance, clearance_radius)
my $distance = $Slic3r::complete_objects && $Slic3r::extruder_clearance_radius > $Slic3r::duplicate_distance
? $Slic3r::extruder_clearance_radius
: $Slic3r::duplicate_distance;
my $distance = $Slic3r::Config->complete_objects && $Slic3r::Config->extruder_clearance_radius > $Slic3r::Config->duplicate_distance
? $Slic3r::Config->extruder_clearance_radius
: $Slic3r::Config->duplicate_distance;
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}) {
@{$self->copies->[$obj_idx]} = splice @positions, 0, scalar @{$self->copies->[$obj_idx]};
@ -229,7 +273,7 @@ sub export_gcode {
$_->make_perimeters for @{$self->objects};
# 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};
# this will clip $layer->surfaces to the infill boundaries
@ -297,7 +341,7 @@ sub export_gcode {
}
# generate support material
if ($Slic3r::support_material) {
if ($Slic3r::Config->support_material) {
$status_cb->(85, "Generating support material");
$_->generate_support_material(print => $self) for @{$self->objects};
}
@ -316,10 +360,10 @@ sub export_gcode {
$self->write_gcode($output_file);
# run post-processing scripts
if (@$Slic3r::post_process) {
if (@{$Slic3r::Config->post_process}) {
$status_cb->(95, "Running post-processing scripts");
Slic3r::Config->setenv;
for (@$Slic3r::post_process) {
$Slic3r::Config->setenv;
for (@{$Slic3r::Config->post_process}) {
Slic3r::debugf " '%s' '%s'\n", $_, $output_file;
system($_, $output_file);
}
@ -388,7 +432,7 @@ EOF
}
}
# generate support material
if ($Slic3r::support_material && $layer_id > 0) {
if ($Slic3r::Config->support_material && $layer_id > 0) {
my (@supported_slices, @unsupported_slices) = ();
foreach my $expolygon (@current_layer_slices) {
my $intersection = intersection_ex(
@ -420,10 +464,10 @@ EOF
sub make_skirt {
my $self = shift;
return unless $Slic3r::skirts > 0;
return unless $Slic3r::Config->skirts > 0;
# 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;
my @points = ();
foreach my $obj_idx (0 .. $#{$self->objects}) {
@ -443,9 +487,9 @@ sub make_skirt {
# draw outlines from outside to inside
my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
my @skirt = ();
for (my $i = $Slic3r::skirts; $i > 0; $i--) {
my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i));
my $outline = offset([$convex_hull], $distance, $Slic3r::scaling_factor * 100, JT_ROUND);
for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
my $distance = scale ($Slic3r::Config->skirt_distance + ($flow->spacing * $i));
my $outline = offset([$convex_hull], $distance, &Slic3r::SCALING_FACTOR * 100, JT_ROUND);
push @skirt, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new(@{$outline->[0]}),
role => EXTR_ROLE_SKIRT,
@ -456,7 +500,7 @@ sub make_skirt {
sub make_brim {
my $self = shift;
return unless $Slic3r::brim_width > 0;
return unless $Slic3r::Config->brim_width > 0;
my @islands = (); # array of polygons
foreach my $obj_idx (0 .. $#{$self->objects}) {
@ -467,7 +511,7 @@ sub make_brim {
}
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) {
push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
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",
$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" if $Slic3r::notes;
print $fh "; $_\n" foreach split /\R/, $Slic3r::Config->notes;
print $fh "\n" if $Slic3r::Config->notes;
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)) {
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 "; first layer single wall width = %.2fmm\n", $Slic3r::first_layer_flow->width
@ -505,29 +549,29 @@ sub write_gcode {
# set up our extruder object
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;
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
printf $fh $gcodegen->set_bed_temperature($Slic3r::first_layer_bed_temperature, 1),
if $Slic3r::first_layer_bed_temperature && $Slic3r::start_gcode !~ /M190/i;
for my $t (grep $Slic3r::extruders->[$_], 0 .. $#$Slic3r::first_layer_temperature) {
printf $fh $gcodegen->set_bed_temperature($Slic3r::Config->first_layer_bed_temperature, 1),
if $Slic3r::Config->first_layer_bed_temperature && $Slic3r::Config->start_gcode !~ /M190/i;
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)
if $Slic3r::extruders->[$t]->first_layer_temperature;
}
printf $fh "%s\n", Slic3r::Config->replace_options($Slic3r::start_gcode);
for my $t (grep $Slic3r::extruders->[$_], 0 .. $#$Slic3r::first_layer_temperature) {
printf $fh "%s\n", $Slic3r::Config->replace_options($Slic3r::Config->start_gcode);
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)
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 "G21 ; set units to millimeters\n";
if ($Slic3r::gcode_flavor =~ /^(?:reprap|teacup)$/) {
if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|teacup)$/) {
printf $fh $gcodegen->reset_e;
if ($Slic3r::gcode_flavor =~ /^(?:reprap|makerbot)$/) {
if ($Slic3r::use_relative_e_distances) {
if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|makerbot)$/) {
if ($Slic3r::Config->use_relative_e_distances) {
print $fh "M83 ; use relative distances for extrusion\n";
} else {
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
my @print_bb = $self->bounding_box;
my @shift = (
$Slic3r::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->[X] - (unscale ($print_bb[X2] - $print_bb[X1]) / 2) - unscale $print_bb[X1],
$Slic3r::Config->print_center->[Y] - (unscale ($print_bb[Y2] - $print_bb[Y1]) / 2) - unscale $print_bb[Y1],
);
# prepare the logic to print one layer
@ -550,12 +594,12 @@ sub write_gcode {
my $gcode = "";
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)
if $Slic3r::extruders->[$t]->temperature && $Slic3r::extruders->[$t]->temperature != $Slic3r::extruders->[$t]->first_layer_temperature;
}
$gcode .= $gcodegen->set_bed_temperature($Slic3r::bed_temperature)
if $Slic3r::first_layer_bed_temperature && $Slic3r::bed_temperature != $Slic3r::first_layer_bed_temperature;
$gcode .= $gcodegen->set_bed_temperature($Slic3r::Config->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)
@ -563,12 +607,12 @@ sub write_gcode {
$gcodegen->elapsed_time(0);
# extrude skirt
if ($skirt_done < $Slic3r::skirt_height) {
if ($skirt_done < $Slic3r::Config->skirt_height) {
$gcodegen->shift_x($shift[X]);
$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
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};
}
$skirt_done++;
@ -592,12 +636,12 @@ sub write_gcode {
$gcodegen->shift_y($shift[Y] + unscale $copy->[Y]);
# 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 };
# extrude fills
$gcode .= $gcodegen->set_tool($Slic3r::infill_extruder-1);
$gcode .= $gcodegen->set_acceleration($Slic3r::infill_acceleration);
$gcode .= $gcodegen->set_tool($Slic3r::Config->infill_extruder-1);
$gcode .= $gcodegen->set_acceleration($Slic3r::Config->infill_acceleration);
for my $fill (@{ $layer->fills }) {
if ($fill->isa('Slic3r::ExtrusionPath::Collection')) {
$gcode .= $gcodegen->extrude($_, 'fill')
@ -609,25 +653,25 @@ sub write_gcode {
# extrude support material
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')
for $layer->support_fills->shortest_path($gcodegen->last_pos);
}
}
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;
if ($Slic3r::cooling) {
if ($Slic3r::Config->cooling) {
my $layer_time = $gcodegen->elapsed_time;
Slic3r::debugf "Layer %d estimated printing time: %d seconds\n", $layer_id, $layer_time;
if ($layer_time < $Slic3r::slowdown_below_layer_time) {
$fan_speed = $Slic3r::max_fan_speed;
$speed_factor = $layer_time / $Slic3r::slowdown_below_layer_time;
} elsif ($layer_time < $Slic3r::fan_below_layer_time) {
$fan_speed = $Slic3r::max_fan_speed - ($Slic3r::max_fan_speed - $Slic3r::min_fan_speed)
* ($layer_time - $Slic3r::slowdown_below_layer_time)
/ ($Slic3r::fan_below_layer_time - $Slic3r::slowdown_below_layer_time); #/
if ($layer_time < $Slic3r::Config->slowdown_below_layer_time) {
$fan_speed = $Slic3r::Config->max_fan_speed;
$speed_factor = $layer_time / $Slic3r::Config->slowdown_below_layer_time;
} elsif ($layer_time < $Slic3r::Config->fan_below_layer_time) {
$fan_speed = $Slic3r::Config->max_fan_speed - ($Slic3r::Config->max_fan_speed - $Slic3r::Config->min_fan_speed)
* ($layer_time - $Slic3r::Config->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;
@ -637,15 +681,15 @@ sub write_gcode {
$1 . sprintf("%.${dec}f", $new_speed < $min_print_speed ? $min_print_speed : $new_speed)
/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;
# 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;
} 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;
}
@ -653,7 +697,7 @@ sub write_gcode {
};
# 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
# 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
# is triggered, so machine has more time to reach such temperatures
if ($layer_id == 0 && $finished_objects > 0) {
printf $fh $gcodegen->set_bed_temperature($Slic3r::first_layer_bed_temperature),
if $Slic3r::first_layer_bed_temperature;
printf $fh $gcodegen->set_temperature($Slic3r::first_layer_temperature)
if $Slic3r::first_layer_temperature;
printf $fh $gcodegen->set_bed_temperature($Slic3r::Config->first_layer_bed_temperature),
if $Slic3r::Config->first_layer_bed_temperature;
printf $fh $gcodegen->set_temperature($Slic3r::Config->first_layer_temperature)
if $Slic3r::Config->first_layer_temperature;
}
print $fh $extrude_layer->($layer_id, [[ $obj_idx, $copy ]]);
}
@ -703,8 +747,8 @@ sub write_gcode {
# write end commands to file
print $fh $gcodegen->retract;
print $fh $gcodegen->set_fan(0);
print $fh "M501 ; reset acceleration\n" if $Slic3r::acceleration;
printf $fh "%s\n", Slic3r::Config->replace_options($Slic3r::end_gcode);
print $fh "M501 ; reset acceleration\n" if $Slic3r::Config->acceleration;
printf $fh "%s\n", $Slic3r::Config->replace_options($Slic3r::Config->end_gcode);
printf $fh "; filament used = %.1fmm (%.1fcm3)\n",
$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
# file directory and append the specified filename format
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);
$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_base => $input_filename_base,
});

View File

@ -170,18 +170,18 @@ sub make_perimeters {
# one additional inner perimeter, like the top of domed objects-
# 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) {
my $layer = $self->layers->[$layer_id];
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
# the upper layer slices
my $upper = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(+ 0.5 * scale $layer->perimeters_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(+ 0.5 * scale $layer->perimeter_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;
@ -190,22 +190,22 @@ sub make_perimeters {
my $ignore = [];
{
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} ],
);
$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}) {
my $hypothetical_perimeter_num = $Slic3r::perimeters + 1;
my $hypothetical_perimeter_num = $Slic3r::Config->perimeters + 1;
CYCLE: while (1) {
# compute polygons representing the thickness of the hypotetical new internal perimeter
# of our slice
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;
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;
$hypothetical_perimeter = diff_ex($outer, $inner);
}
@ -317,14 +317,14 @@ sub discover_horizontal_shells {
foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
# find surfaces of current type for current layer
# 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;
my $surfaces_p = [ map $_->p, @surfaces ];
Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n",
$i, scalar(@surfaces), ($type == S_TYPE_TOP ? 'top' : 'bottom');
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++) {
next if $n < 0 || $n >= $self->layer_count;
@ -394,7 +394,7 @@ sub discover_horizontal_shells {
# combine fill surfaces across layers
sub combine_infill {
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;
@ -407,7 +407,7 @@ sub combine_infill {
# for each possible depth, look for intersections with the lower layer
# 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;
my $lower_layer = $self->layer($i - 1);
@ -437,7 +437,7 @@ sub combine_infill {
push @new_surfaces, map Slic3r::Surface->new
(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
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
@ -459,7 +459,7 @@ sub combine_infill {
{
my @new_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
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
@ -486,8 +486,8 @@ sub generate_support_material {
my $self = shift;
my %params = @_;
my $threshold_rad = deg2rad($Slic3r::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 $threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive
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;
# determine support regions in each layer (for upper layers)
@ -538,14 +538,14 @@ sub generate_support_material {
@{union_ex([ map $_->contour, map @$_, values %layers ])};
my $fill = Slic3r::Fill->new(print => $params{print});
my $filler = $fill->filler($Slic3r::support_material_pattern);
$filler->angle($Slic3r::support_material_angle);
my $filler = $fill->filler($Slic3r::Config->support_material_pattern);
$filler->angle($Slic3r::Config->support_material_angle);
{
my @patterns = ();
foreach my $expolygon (@support_material_areas) {
my @paths = $filler->fill_surface(
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,
);
my $params = shift @paths;

View File

@ -8,12 +8,12 @@ use constant X => 0;
use constant Y => 1;
sub factor {
return $Slic3r::scaling_factor * 10;
return &Slic3r::SCALING_FACTOR * 10;
}
sub svg {
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 $marker_end = $svg->marker(

View File

@ -401,9 +401,9 @@ sub slice_facet {
}
# 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;
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;
my $lines = {}; # layer_id => [ lines ]

179
slic3r.pl
View File

@ -30,66 +30,59 @@ my %cli_options = ();
'export-svg' => \$opt{export_svg},
'merge|m' => \$opt{merge},
);
foreach my $opt_key (keys %$Slic3r::Config::Options) {
my $opt = $Slic3r::Config::Options->{$opt_key};
my $cli = $opt->{cli} or next;
if ($cli =~ /-/) {
# allow alternative options with '_' in place of '-'
$cli = $opt_key.'|'.$cli;
}
$options{ $cli } = \$cli_options{$opt_key};
foreach my $opt_key (keys %{$Slic3r::Config::Options}) {
my $cli = $Slic3r::Config::Options->{$opt_key}->{cli} or next;
# allow both the dash-separated option name and the full opt_key
$options{ "$opt_key|$cli" } = \$cli_options{$opt_key};
}
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}) {
foreach my $configfile (@{$opt{load}}) {
if (-e $configfile) {
Slic3r::Config->load($configfile);
push @external_configs, Slic3r::Config->load($configfile);
} elsif (-e "$FindBin::Bin/$configfile") {
printf STDERR "Loading $FindBin::Bin/$configfile\n";
Slic3r::Config->load("$FindBin::Bin/$configfile");
push @external_configs, Slic3r::Config->load("$FindBin::Bin/$configfile");
} else {
$opt{ignore_nonexistent_config} or die "Cannot find specified configuration file ($configfile).\n";
}
}
}
# validate command line options
delete $cli_options{$_} for grep !defined $cli_options{$_}, keys %cli_options;
Slic3r::Config->validate_cli(\%cli_options);
# merge configuration
my $config = Slic3r::Config->new_from_defaults;
$config->apply($_) for @external_configs, $cli_config;
# initialize GUI
# save configuration
if ($opt{save}) {
$config->validate;
$config->save($opt{save});
}
# launch GUI
my $gui;
if (!@ARGV && !$opt{save} && eval "require Slic3r::GUI; 1") {
$gui = Slic3r::GUI->new;
$gui->{skeinpanel}->load_config($opt{load}[0]) if $opt{load};
}
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->{skeinpanel}->load_config_file($opt{load}[0]) if $opt{load};
$gui->{skeinpanel}->load_config($cli_config);
$gui->MainLoop;
exit;
}
die $@ if $@ && $opt{gui};
if (@ARGV) {
if (@ARGV) { # slicing from command line
$config->validate;
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);
if ($opt{merge}) {
$print->add_object_from_file($_) for splice @ARGV, 0;
@ -117,10 +110,12 @@ if (@ARGV) {
sub usage {
my ($exit_code) = @_;
my $config = Slic3r::Config->new_from_defaults;
my $j = '';
if ($Slic3r::have_threads) {
$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
}
@ -143,7 +138,7 @@ $j
--output-filename-format
Output file name format; all config options enclosed in brackets
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;
call this more than once to process through multiple scripts.
--export-svg Export a SVG file containing slices instead of G-code.
@ -151,13 +146,13 @@ $j
print rather than processed individually.
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
(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
(+/-, default: $Slic3r::z_offset)
(+/-, default: $config->{z_offset})
--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
--gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported
by all firmwares)
@ -166,50 +161,50 @@ $j
--gcode-comments Make G-code verbose by adding comments (default: no)
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
Change this to alter the amount of plastic extruded. There should be
very little need to change this value, which is only useful to
compensate for filament packing (default: @$Slic3r::extrusion_multiplier)
--temperature Extrusion temperature in degree Celsius, set 0 to disable (default: @$Slic3r::temperature)
compensate for filament packing (default: $config->{extrusion_multiplier}->[0])
--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,
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,
set 0 to disable (default: same as --bed-temperature)
Speed options:
--travel-speed Speed of non-print moves in mm/s (default: $Slic3r::travel_speed)
--perimeter-speed Speed of print moves for perimeters in mm/s (default: $Slic3r::perimeter_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: $config->{perimeter_speed})
--small-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
Speed of print moves for the external perimeter in mm/s or % over perimeter speed
(default: $Slic3r::external_perimeter_speed)
--infill-speed Speed of print moves in mm/s (default: $Slic3r::infill_speed)
(default: $config->{external_perimeter_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
(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
(default: $Slic3r::top_solid_infill_speed)
--bridge-speed Speed of bridge print moves in mm/s (default: $Slic3r::bridge_speed)
(default: $config->{top_solid_infill_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
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:
--layer-height Layer height in mm (default: $Slic3r::layer_height)
--first-layer-height Layer height for first layer (mm or %, default: $Slic3r::first_layer_height)
--layer-height Layer height in mm (default: $config->{layer_height})
--first-layer-height Layer height for first layer (mm or %, default: $config->{first_layer_height})
--infill-every-layers
Infill every N layers (default: $Slic3r::infill_every_layers)
Infill every N layers (default: $config->{infill_every_layers})
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
(range: 1+, default: $Slic3r::solid_layers)
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density)
--fill-angle Infill angle in degrees (range: 0-90, default: $Slic3r::fill_angle)
--fill-pattern Pattern to use to fill non-solid layers (default: $Slic3r::fill_pattern)
--solid-fill-pattern Pattern to use to fill solid layers (default: $Slic3r::solid_fill_pattern)
(range: 1+, default: $config->{solid_layers})
--fill-density Infill density (range: 0-1, default: $config->{fill_density})
--fill-angle Infill angle in degrees (range: 0-90, default: $config->{fill_angle})
--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: $config->{solid_fill_pattern})
--start-gcode Load initial G-code from the supplied file. This will overwrite
the default command (home all axes [G28]).
--end-gcode Load final G-code from the supplied file. This will overwrite
@ -222,62 +217,62 @@ $j
Support material options:
--support-material Generate support material for overhangs
--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
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
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 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:
--retract-length Length of retraction in mm when pausing extrusion
(default: $Slic3r::retract_length)
--retract-speed Speed for retraction in mm/s (default: $Slic3r::retract_speed)
(default: $config->{retract_length})
--retract-speed Speed for retraction in mm/s (default: $config->{retract_speed})
--retract-restart-extra
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
Only retract before travel moves of this length in mm (default: $Slic3r::retract_before_travel)
--retract-lift Lift Z by the given distance in mm when retracting (default: $Slic3r::retract_lift)
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: $config->{retract_lift})
Cooling options:
--cooling Enable fan and cooling control
--min-fan-speed Minimum fan speed (default: $Slic3r::min_fan_speed%)
--max-fan-speed Maximum fan speed (default: $Slic3r::max_fan_speed%)
--bridge-fan-speed Fan speed to use when bridging (default: $Slic3r::bridge_fan_speed%)
--min-fan-speed Minimum fan speed (default: $config->{min_fan_speed}%)
--max-fan-speed Maximum fan speed (default: $config->{max_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
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
of seconds (default: $Slic3r::slowdown_below_layer_time)
--min-print-speed Minimum print speed (mm/s, default: $Slic3r::min_print_speed)
--disable-fan-first-layers Disable fan for the first N layers (default: $Slic3r::disable_fan_first_layers)
of seconds (default: $config->{slowdown_below_layer_time})
--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: $config->{disable_fan_first_layers})
--fan-always-on Keep fan always on at min fan speed, even for layers that don't need
cooling
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
(default: $Slic3r::skirt_distance)
--skirt-height Height of skirts to draw (expressed in layers, 0+, default: $Slic3r::skirt_height)
(default: $config->{skirt_distance})
--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
(mm, default: $Slic3r::brim_width)
(mm, default: $config->{brim_width})
Transform options:
--scale Factor for scaling input object (default: $Slic3r::scale)
--rotate Rotation angle in degrees (0-360, default: $Slic3r::rotate)
--duplicate Number of items with auto-arrange (1+, default: $Slic3r::duplicate)
--bed-size Bed size, only used for auto-arrange (mm, default: $Slic3r::bed_size->[0],$Slic3r::bed_size->[1])
--duplicate-grid Number of items with grid arrangement (default: $Slic3r::duplicate_grid->[0],$Slic3r::duplicate_grid->[1])
--duplicate-distance Distance in mm between copies (default: $Slic3r::duplicate_distance)
--scale Factor for scaling input object (default: $config->{scale})
--rotate Rotation angle in degrees (0-360, default: $config->{rotate})
--duplicate Number of items with auto-arrange (1+, default: $config->{duplicate})
--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: $config->{duplicate_grid}->[0],$config->{duplicate_grid}->[1])
--duplicate-distance Distance in mm between copies (default: $config->{duplicate_distance})
Sequential printing options:
--complete-objects When printing multiple objects and/or copies, complete each one before
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
(default: $Slic3r::extruder_clearance_radius)
(default: $config->{extruder_clearance_radius})
--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:
--notes Notes to be added as comments to the output file
@ -293,7 +288,7 @@ $j
Set a different extrusion width for infill
--support-material-extrusion-width
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:
--perimeters-extruder