Refactoring: move ooze prevention, wipe and avoid crossing perimeters into nested classes for better isolation
This commit is contained in:
parent
3605289bbc
commit
c1e26a70f8
@ -50,7 +50,6 @@ use Slic3r::GCode::ArcFitting;
|
||||
use Slic3r::GCode::CoolingBuffer;
|
||||
use Slic3r::GCode::Layer;
|
||||
use Slic3r::GCode::MotionPlanner;
|
||||
use Slic3r::GCode::OozePrevention;
|
||||
use Slic3r::GCode::PlaceholderParser;
|
||||
use Slic3r::GCode::Reader;
|
||||
use Slic3r::GCode::SpiralVase;
|
||||
|
@ -17,9 +17,10 @@ has 'origin' => (is => 'rw', default => sub { Slic3r::Pointf->new })
|
||||
has 'config' => (is => 'ro', default => sub { Slic3r::Config::Full->new });
|
||||
has 'writer' => (is => 'ro', default => sub { Slic3r::GCode::Writer->new });
|
||||
has 'placeholder_parser' => (is => 'rw', default => sub { Slic3r::GCode::PlaceholderParser->new });
|
||||
has 'ooze_prevention' => (is => 'rw');
|
||||
has 'ooze_prevention' => (is => 'rw', default => sub { Slic3r::GCode::OozePrevention->new });
|
||||
has 'wipe' => (is => 'rw', default => sub { Slic3r::GCode::Wipe->new });
|
||||
has 'avoid_crossing_perimeters' => (is => 'rw', default => sub { Slic3r::GCode::AvoidCrossingPerimeters->new });
|
||||
has 'enable_loop_clipping' => (is => 'rw', default => sub {1});
|
||||
has 'enable_wipe' => (is => 'rw', default => sub {0}); # at least one extruder has wipe enabled
|
||||
has 'enable_cooling_markers' => (is =>'rw', default => sub {0});
|
||||
has 'layer_count' => (is => 'ro');
|
||||
has '_layer_index' => (is => 'rw', default => sub {-1}); # just a counter
|
||||
@ -27,14 +28,9 @@ has 'layer' => (is => 'rw');
|
||||
has '_layer_islands' => (is => 'rw');
|
||||
has '_upper_layer_islands' => (is => 'rw');
|
||||
has '_seam_position' => (is => 'ro', default => sub { {} }); # $object => pos
|
||||
has '_external_mp' => (is => 'rw');
|
||||
has '_layer_mp' => (is => 'rw');
|
||||
has 'new_object' => (is => 'rw', default => sub {0}); # this flag triggers the use of the external configuration space for avoid_crossing_perimeters for the next travel move
|
||||
has 'straight_once' => (is => 'rw', default => sub {1}); # this flag disables avoid_crossing_perimeters just for the next travel move
|
||||
has 'first_layer' => (is => 'rw', default => sub {0}); # this flag triggers first layer speeds
|
||||
has 'elapsed_time' => (is => 'rw', default => sub {0} ); # seconds
|
||||
has 'last_pos' => (is => 'rw', default => sub { Slic3r::Point->new(0,0) } );
|
||||
has '_wipe_path' => (is => 'rw');
|
||||
|
||||
sub apply_print_config {
|
||||
my ($self, $print_config) = @_;
|
||||
@ -49,7 +45,7 @@ sub set_extruders {
|
||||
$self->writer->set_extruders($extruder_ids);
|
||||
|
||||
# enable wipe path generation if any extruder has wipe enabled
|
||||
$self->enable_wipe(defined first { $self->config->get_at('wipe', $_) } @$extruder_ids);
|
||||
$self->wipe->enable(defined first { $self->config->get_at('wipe', $_) } @$extruder_ids);
|
||||
}
|
||||
|
||||
sub set_origin {
|
||||
@ -61,16 +57,11 @@ sub set_origin {
|
||||
scale ($self->origin->y - $pointf->y), #-
|
||||
);
|
||||
$self->last_pos->translate(@translate);
|
||||
$self->_wipe_path->translate(@translate) if $self->_wipe_path;
|
||||
$self->wipe->path->translate(@translate) if $self->wipe->path;
|
||||
|
||||
$self->origin($pointf);
|
||||
}
|
||||
|
||||
sub init_external_mp {
|
||||
my ($self, $islands) = @_;
|
||||
$self->_external_mp(Slic3r::MotionPlanner->new($islands));
|
||||
}
|
||||
|
||||
sub preamble {
|
||||
my ($self) = @_;
|
||||
|
||||
@ -96,9 +87,9 @@ sub change_layer {
|
||||
$self->_layer_islands($layer->islands);
|
||||
$self->_upper_layer_islands($layer->upper_layer ? $layer->upper_layer->islands : []);
|
||||
if ($self->config->avoid_crossing_perimeters) {
|
||||
$self->_layer_mp(Slic3r::MotionPlanner->new(
|
||||
$self->avoid_crossing_perimeters->init_layer_mp(
|
||||
union_ex([ map @$_, @{$layer->slices} ], 1),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
my $gcode = "";
|
||||
@ -213,7 +204,7 @@ sub extrude_loop {
|
||||
# reset acceleration
|
||||
$gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
|
||||
|
||||
$self->_wipe_path($paths[0]->polyline->clone) if $self->enable_wipe; # TODO: don't limit wipe to last path
|
||||
$self->wipe->path($paths[0]->polyline->clone) if $self->wipe->enable; # TODO: don't limit wipe to last path
|
||||
|
||||
# make a little move inwards before leaving loop
|
||||
if ($paths[-1]->role == EXTR_ROLE_EXTERNAL_PERIMETER && defined $self->layer && $self->config->perimeters > 1) {
|
||||
@ -324,9 +315,9 @@ sub _extrude_path {
|
||||
$self->writer->extrusion_axis,
|
||||
$self->config->gcode_comments ? " ; $description" : "");
|
||||
|
||||
if ($self->enable_wipe) {
|
||||
$self->_wipe_path($path->polyline->clone);
|
||||
$self->_wipe_path->reverse;
|
||||
if ($self->wipe->enable) {
|
||||
$self->wipe->path($path->polyline->clone);
|
||||
$self->wipe->path->reverse;
|
||||
}
|
||||
}
|
||||
$gcode .= ";_BRIDGE_FAN_END\n" if $path->is_bridge && $self->enable_cooling_markers;
|
||||
@ -366,25 +357,8 @@ sub travel_to {
|
||||
) {
|
||||
# Just perform a straight travel move without any retraction.
|
||||
$gcode .= $self->writer->travel_to_xy($self->point_to_gcode($point), $comment);
|
||||
} elsif ($self->config->avoid_crossing_perimeters && !$self->straight_once) {
|
||||
# If avoid_crossing_perimeters is enabled and the straight_once flag is not set
|
||||
# we need to plan a multi-segment travel move inside the configuration space.
|
||||
if ($self->new_object) {
|
||||
# If we're moving to a new object we need to use the external configuration space.
|
||||
$self->new_object(0);
|
||||
|
||||
# represent $point in G-code coordinates
|
||||
$point = $point->clone;
|
||||
my $origin = $self->origin;
|
||||
$point->translate(map scale $_, @$origin);
|
||||
|
||||
# calculate path (external_mp uses G-code coordinates so we set a temporary null origin)
|
||||
$self->set_origin(Slic3r::Pointf->new(0,0));
|
||||
$gcode .= $self->_plan($self->_external_mp, $point, $comment);
|
||||
$self->set_origin($origin);
|
||||
} else {
|
||||
$gcode .= $self->_plan($self->_layer_mp, $point, $comment);
|
||||
}
|
||||
} elsif ($self->config->avoid_crossing_perimeters && !$self->avoid_crossing_perimeters->straight_once) {
|
||||
$gcode .= $self->avoid_crossing_perimeters->travel_to($self, $point, $comment);
|
||||
} else {
|
||||
# If avoid_crossing_perimeters is disabled or the straight_once flag is set,
|
||||
# perform a straight move with a retraction.
|
||||
@ -393,41 +367,11 @@ sub travel_to {
|
||||
}
|
||||
|
||||
# Re-allow avoid_crossing_perimeters for the next travel moves
|
||||
$self->straight_once(0);
|
||||
$self->avoid_crossing_perimeters->straight_once(0);
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub _plan {
|
||||
my ($self, $mp, $point, $comment) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
my @travel = @{$mp->shortest_path($self->last_pos, $point)->lines};
|
||||
|
||||
# if the path is not contained in a single island we need to retract
|
||||
my $need_retract = !$self->config->only_retract_when_crossing_perimeters;
|
||||
if (!$need_retract) {
|
||||
$need_retract = 1;
|
||||
foreach my $island (@{$self->_upper_layer_islands}) {
|
||||
# discard the island if at any line is not enclosed in it
|
||||
next if first { !$island->contains_line($_) } @travel;
|
||||
# okay, this island encloses the full travel path
|
||||
$need_retract = 0;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# perform the retraction
|
||||
$gcode .= $self->retract if $need_retract;
|
||||
|
||||
# append the actual path and return
|
||||
# use G1 because we rely on paths being straight (G0 may make round paths)
|
||||
$gcode .= join '',
|
||||
map $self->writer->travel_to_xy($self->point_to_gcode($_->b), $comment),
|
||||
@travel;
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub retract {
|
||||
my ($self, $toolchange) = @_;
|
||||
|
||||
@ -436,48 +380,8 @@ sub retract {
|
||||
my $gcode = "";
|
||||
|
||||
# wipe (if it's enabled for this extruder and we have a stored wipe path)
|
||||
if ($self->config->get_at('wipe', $self->writer->extruder->id) && $self->_wipe_path) {
|
||||
# Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
# Too fast = ripping of existing material; too slow = short wipe path, thus more blob.
|
||||
my $wipe_speed = $self->writer->config->get('travel_speed') * 0.8;
|
||||
|
||||
# get the retraction length
|
||||
my $length = $toolchange
|
||||
? $self->writer->extruder->retract_length_toolchange
|
||||
: $self->writer->extruder->retract_length;
|
||||
|
||||
if ($length) {
|
||||
# Calculate how long we need to travel in order to consume the required
|
||||
# amount of retraction. In other words, how far do we move in XY at $wipe_speed
|
||||
# for the time needed to consume retract_length at retract_speed?
|
||||
my $wipe_dist = scale($length / $self->writer->extruder->retract_speed * $wipe_speed);
|
||||
|
||||
# Take the stored wipe path and replace first point with the current actual position
|
||||
# (they might be different, for example, in case of loop clipping).
|
||||
my $wipe_path = Slic3r::Polyline->new(
|
||||
$self->last_pos,
|
||||
@{$self->_wipe_path}[1..$#{$self->_wipe_path}],
|
||||
);
|
||||
#
|
||||
$wipe_path->clip_end($wipe_path->length - $wipe_dist);
|
||||
|
||||
# subdivide the retraction in segments
|
||||
my $retracted = 0;
|
||||
foreach my $line (@{$wipe_path->lines}) {
|
||||
my $segment_length = $line->length;
|
||||
# Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
# due to rounding (TODO: test and/or better math for this)
|
||||
my $dE = $length * ($segment_length / $wipe_dist) * 0.95;
|
||||
$gcode .= $self->writer->set_speed($wipe_speed*60);
|
||||
$gcode .= $self->writer->extrude_to_xy(
|
||||
$self->point_to_gcode($line->b),
|
||||
-$dE,
|
||||
'retract' . ($self->enable_cooling_markers ? ';_WIPE' : ''),
|
||||
);
|
||||
$retracted += $dE;
|
||||
}
|
||||
$self->writer->extruder->set_retracted($self->writer->extruder->retracted + $retracted);
|
||||
}
|
||||
if ($self->config->get_at('wipe', $self->writer->extruder->id) && $self->wipe->path) {
|
||||
$gcode .= $self->wipe->wipe($self, $toolchange);
|
||||
}
|
||||
|
||||
# The parent class will decide whether we need to perform an actual retraction
|
||||
@ -537,14 +441,196 @@ sub set_extruder {
|
||||
# if ooze prevention is enabled, park current extruder in the nearest
|
||||
# standby point and set it to the standby temperature
|
||||
$gcode .= $self->ooze_prevention->pre_toolchange($self)
|
||||
if $self->ooze_prevention && defined $self->writer->extruder;
|
||||
if $self->ooze_prevention->enable && defined $self->writer->extruder;
|
||||
|
||||
# append the toolchange command
|
||||
$gcode .= $self->writer->toolchange($extruder_id);
|
||||
|
||||
# set the new extruder to the operating temperature
|
||||
$gcode .= $self->ooze_prevention->post_toolchange($self)
|
||||
if $self->ooze_prevention;
|
||||
if $self->ooze_prevention->enable;
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
package Slic3r::GCode::OozePrevention;
|
||||
use Moo;
|
||||
|
||||
use Slic3r::Geometry qw(scale);
|
||||
|
||||
has 'enable' => (is => 'rw', default => sub { 0 });
|
||||
has 'standby_points' => (is => 'rw');
|
||||
|
||||
sub pre_toolchange {
|
||||
my ($self, $gcodegen) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
# move to the nearest standby point
|
||||
if (@{$self->standby_points}) {
|
||||
my $last_pos = $gcodegen->last_pos->clone;
|
||||
$last_pos->translate(scale +$gcodegen->origin->x, scale +$gcodegen->origin->y); #))
|
||||
my $standby_point = $last_pos->nearest_point($self->standby_points);
|
||||
$standby_point->translate(scale -$gcodegen->origin->x, scale -$gcodegen->origin->y); #))
|
||||
$gcode .= $gcodegen->travel_to($standby_point);
|
||||
}
|
||||
|
||||
if ($gcodegen->config->standby_temperature_delta != 0) {
|
||||
my $temp = defined $gcodegen->layer && $gcodegen->layer->id == 0
|
||||
? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id)
|
||||
: $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id);
|
||||
# we assume that heating is always slower than cooling, so no need to block
|
||||
$gcode .= $gcodegen->writer->set_temperature($temp + $gcodegen->config->standby_temperature_delta, 0);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub post_toolchange {
|
||||
my ($self, $gcodegen) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
if ($gcodegen->config->standby_temperature_delta != 0) {
|
||||
my $temp = defined $gcodegen->layer && $gcodegen->layer->id == 0
|
||||
? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id)
|
||||
: $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id);
|
||||
$gcode .= $gcodegen->writer->set_temperature($temp, 1);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
package Slic3r::GCode::Wipe;
|
||||
use Moo;
|
||||
|
||||
use Slic3r::Geometry qw(scale);
|
||||
|
||||
has 'enable' => (is => 'rw', default => sub { 0 });
|
||||
has 'path' => (is => 'rw');
|
||||
|
||||
sub wipe {
|
||||
my ($self, $gcodegen, $toolchange) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
# Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
# Too fast = ripping of existing material; too slow = short wipe path, thus more blob.
|
||||
my $wipe_speed = $gcodegen->writer->config->get('travel_speed') * 0.8;
|
||||
|
||||
# get the retraction length
|
||||
my $length = $toolchange
|
||||
? $gcodegen->writer->extruder->retract_length_toolchange
|
||||
: $gcodegen->writer->extruder->retract_length;
|
||||
|
||||
if ($length) {
|
||||
# Calculate how long we need to travel in order to consume the required
|
||||
# amount of retraction. In other words, how far do we move in XY at $wipe_speed
|
||||
# for the time needed to consume retract_length at retract_speed?
|
||||
my $wipe_dist = scale($length / $gcodegen->writer->extruder->retract_speed * $wipe_speed);
|
||||
|
||||
# Take the stored wipe path and replace first point with the current actual position
|
||||
# (they might be different, for example, in case of loop clipping).
|
||||
my $wipe_path = Slic3r::Polyline->new(
|
||||
$gcodegen->last_pos,
|
||||
@{$self->path}[1..$#{$self->path}],
|
||||
);
|
||||
#
|
||||
$wipe_path->clip_end($wipe_path->length - $wipe_dist);
|
||||
|
||||
# subdivide the retraction in segments
|
||||
my $retracted = 0;
|
||||
foreach my $line (@{$wipe_path->lines}) {
|
||||
my $segment_length = $line->length;
|
||||
# Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
# due to rounding (TODO: test and/or better math for this)
|
||||
my $dE = $length * ($segment_length / $wipe_dist) * 0.95;
|
||||
$gcode .= $gcodegen->writer->set_speed($wipe_speed*60);
|
||||
$gcode .= $gcodegen->writer->extrude_to_xy(
|
||||
$gcodegen->point_to_gcode($line->b),
|
||||
-$dE,
|
||||
'retract' . ($gcodegen->enable_cooling_markers ? ';_WIPE' : ''),
|
||||
);
|
||||
$retracted += $dE;
|
||||
}
|
||||
$gcodegen->writer->extruder->set_retracted($gcodegen->writer->extruder->retracted + $retracted);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
package Slic3r::GCode::AvoidCrossingPerimeters;
|
||||
use Moo;
|
||||
|
||||
has '_external_mp' => (is => 'rw');
|
||||
has '_layer_mp' => (is => 'rw');
|
||||
has 'new_object' => (is => 'rw', default => sub {0}); # this flag triggers the use of the external configuration space for avoid_crossing_perimeters for the next travel move
|
||||
has 'straight_once' => (is => 'rw', default => sub {1}); # this flag disables avoid_crossing_perimeters just for the next travel move
|
||||
|
||||
sub init_external_mp {
|
||||
my ($self, $islands) = @_;
|
||||
$self->_external_mp(Slic3r::MotionPlanner->new($islands));
|
||||
}
|
||||
|
||||
sub init_layer_mp {
|
||||
my ($self, $islands) = @_;
|
||||
$self->_layer_mp(Slic3r::MotionPlanner->new($islands));
|
||||
}
|
||||
|
||||
sub travel_to {
|
||||
my ($self, $gcodegen, $point, $comment) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
# If avoid_crossing_perimeters is enabled and the straight_once flag is not set
|
||||
# we need to plan a multi-segment travel move inside the configuration space.
|
||||
if ($self->new_object) {
|
||||
# If we're moving to a new object we need to use the external configuration space.
|
||||
$self->new_object(0);
|
||||
|
||||
# represent $point in G-code coordinates
|
||||
$point = $point->clone;
|
||||
my $origin = $gcodegen->origin;
|
||||
$point->translate(map scale $_, @$origin);
|
||||
|
||||
# calculate path (external_mp uses G-code coordinates so we set a temporary null origin)
|
||||
$gcodegen->set_origin(Slic3r::Pointf->new(0,0));
|
||||
$gcode .= $self->_plan($gcodegen, $self->_external_mp, $point, $comment);
|
||||
$gcodegen->set_origin($origin);
|
||||
} else {
|
||||
$gcode .= $self->_plan($gcodegen, $self->_layer_mp, $point, $comment);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub _plan {
|
||||
my ($self, $gcodegen, $mp, $point, $comment) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
my @travel = @{$mp->shortest_path($gcodegen->last_pos, $point)->lines};
|
||||
|
||||
# if the path is not contained in a single island we need to retract
|
||||
my $need_retract = !$gcodegen->config->only_retract_when_crossing_perimeters;
|
||||
if (!$need_retract) {
|
||||
$need_retract = 1;
|
||||
foreach my $island (@{$gcodegen->_upper_layer_islands}) {
|
||||
# discard the island if at any line is not enclosed in it
|
||||
next if first { !$island->contains_line($_) } @travel;
|
||||
# okay, this island encloses the full travel path
|
||||
$need_retract = 0;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# perform the retraction
|
||||
$gcode .= $gcodegen->retract if $need_retract;
|
||||
|
||||
# append the actual path and return
|
||||
# use G1 because we rely on paths being straight (G0 may make round paths)
|
||||
$gcode .= join '',
|
||||
map $gcodegen->writer->travel_to_xy($self->point_to_gcode($_->b), $comment),
|
||||
@travel;
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ sub process_layer {
|
||||
}
|
||||
}
|
||||
$self->skirt_done->{$layer->print_z} = 1;
|
||||
$self->gcodegen->straight_once(1);
|
||||
$self->gcodegen->avoid_crossing_perimeters->straight_once(1);
|
||||
}
|
||||
|
||||
# extrude brim
|
||||
@ -110,11 +110,11 @@ sub process_layer {
|
||||
$gcode .= $self->gcodegen->extrude_loop($_, 'brim', $object->config->support_material_speed)
|
||||
for @{$self->print->brim};
|
||||
$self->brim_done(1);
|
||||
$self->gcodegen->straight_once(1);
|
||||
$self->gcodegen->avoid_crossing_perimeters->straight_once(1);
|
||||
}
|
||||
|
||||
for my $copy (@$object_copies) {
|
||||
$self->gcodegen->new_object(1) if ($self->_last_obj_copy // '') ne "$copy";
|
||||
$self->gcodegen->avoid_crossing_perimeters->new_object(1) if ($self->_last_obj_copy // '') ne "$copy";
|
||||
$self->_last_obj_copy("$copy");
|
||||
|
||||
$self->gcodegen->set_origin(Slic3r::Pointf->new(map $self->origin->[$_] + unscale $copy->[$_], X,Y));
|
||||
|
@ -1,48 +0,0 @@
|
||||
package Slic3r::GCode::OozePrevention;
|
||||
use Moo;
|
||||
|
||||
use Slic3r::Geometry qw(scale);
|
||||
|
||||
has 'standby_points' => (is => 'rw', required => 1);
|
||||
|
||||
sub pre_toolchange {
|
||||
my ($self, $gcodegen) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
# move to the nearest standby point
|
||||
if (@{$self->standby_points}) {
|
||||
my $last_pos = $gcodegen->last_pos->clone;
|
||||
$last_pos->translate(scale +$gcodegen->origin->x, scale +$gcodegen->origin->y); #))
|
||||
my $standby_point = $last_pos->nearest_point($self->standby_points);
|
||||
$standby_point->translate(scale -$gcodegen->origin->x, scale -$gcodegen->origin->y); #))
|
||||
$gcode .= $gcodegen->travel_to($standby_point);
|
||||
}
|
||||
|
||||
if ($gcodegen->config->standby_temperature_delta != 0) {
|
||||
my $temp = defined $gcodegen->layer && $gcodegen->layer->id == 0
|
||||
? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id)
|
||||
: $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id);
|
||||
# we assume that heating is always slower than cooling, so no need to block
|
||||
$gcode .= $gcodegen->writer->set_temperature($temp + $gcodegen->config->standby_temperature_delta, 0);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub post_toolchange {
|
||||
my ($self, $gcodegen) = @_;
|
||||
|
||||
my $gcode = "";
|
||||
|
||||
if ($gcodegen->config->standby_temperature_delta != 0) {
|
||||
my $temp = defined $gcodegen->layer && $gcodegen->layer->id == 0
|
||||
? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id)
|
||||
: $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id);
|
||||
$gcode .= $gcodegen->writer->set_temperature($temp, 1);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
1;
|
@ -552,7 +552,7 @@ sub write_gcode {
|
||||
}
|
||||
}
|
||||
}
|
||||
$gcodegen->init_external_mp(union_ex([ map @$_, @islands ]));
|
||||
$gcodegen->avoid_crossing_perimeters->init_external_mp(union_ex([ map @$_, @islands ]));
|
||||
}
|
||||
|
||||
# calculate wiping points if needed
|
||||
@ -567,10 +567,10 @@ sub write_gcode {
|
||||
}
|
||||
my $convex_hull = convex_hull([ map @$_, @skirts ]);
|
||||
|
||||
my $oozeprev = Slic3r::GCode::OozePrevention->new(
|
||||
standby_points => [ map $_->clone, map @$_, map $_->subdivide(scale 10), @{offset([$convex_hull], scale 3)} ],
|
||||
$gcodegen->ooze_prevention->enable(1);
|
||||
$gcodegen->ooze_prevention->standby_points(
|
||||
[ map $_->clone, map @$_, map $_->subdivide(scale 10), @{offset([$convex_hull], scale 3)} ]
|
||||
);
|
||||
$gcodegen->ooze_prevention($oozeprev);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user