mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
New feature: ability to override specific settings for individual objects in the plater. #344
This commit is contained in:
parent
2dd6325bf8
commit
3d6fb1b05c
12 changed files with 248 additions and 55 deletions
|
@ -15,18 +15,22 @@ has 'size' => (is => 'rw', required => 1); # XYZ in scaled coordina
|
|||
has 'copies' => (is => 'rw', trigger => 1); # in scaled coordinates
|
||||
has 'layers' => (is => 'rw', default => sub { [] });
|
||||
has 'support_layers' => (is => 'rw', default => sub { [] });
|
||||
has 'config_overrides' => (is => 'rw', default => sub { Slic3r::Config->new });
|
||||
has 'config' => (is => 'rw');
|
||||
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
|
||||
has 'fill_maker' => (is => 'lazy');
|
||||
has '_slice_z_table' => (is => 'lazy');
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
|
||||
$self->init_config;
|
||||
|
||||
# make layers taking custom heights into account
|
||||
my $print_z = my $slice_z = my $height = 0;
|
||||
|
||||
# add raft layers
|
||||
for my $id (0 .. $Slic3r::Config->raft_layers-1) {
|
||||
for my $id (0 .. $self->config->raft_layers-1) {
|
||||
$height = ($id == 0)
|
||||
? $Slic3r::Config->get_value('first_layer_height')
|
||||
: $Slic3r::Config->layer_height;
|
||||
|
@ -99,6 +103,11 @@ sub _trigger_copies {
|
|||
@{$self->copies} = @{chained_path_points($self->copies)}
|
||||
}
|
||||
|
||||
sub init_config {
|
||||
my $self = shift;
|
||||
$self->config(Slic3r::Config->merge($self->print->config, $self->config_overrides));
|
||||
}
|
||||
|
||||
sub layer_count {
|
||||
my $self = shift;
|
||||
return scalar @{ $self->layers };
|
||||
|
@ -249,7 +258,7 @@ sub slice {
|
|||
}
|
||||
|
||||
# remove empty layers from bottom
|
||||
my $first_object_layer_id = $Slic3r::Config->raft_layers;
|
||||
my $first_object_layer_id = $self->config->raft_layers;
|
||||
while (@{$self->layers} && !@{$self->layers->[$first_object_layer_id]->slices} && !map @{$_->thin_walls}, @{$self->layers->[$first_object_layer_id]->regions}) {
|
||||
splice @{$self->layers}, $first_object_layer_id, 1;
|
||||
for (my $i = $first_object_layer_id; $i <= $#{$self->layers}; $i++) {
|
||||
|
@ -268,7 +277,7 @@ sub make_perimeters {
|
|||
# but we don't generate any extra perimeter if fill density is zero, as they would be floating
|
||||
# inside the object - infill_only_where_needed should be the method of choice for printing
|
||||
# hollow objects
|
||||
if ($Slic3r::Config->extra_perimeters && $Slic3r::Config->perimeters > 0 && $Slic3r::Config->fill_density > 0) {
|
||||
if ($self->config->extra_perimeters && $self->config->perimeters > 0 && $self->config->fill_density > 0) {
|
||||
for my $region_id (0 .. ($self->print->regions_count-1)) {
|
||||
for my $layer_id (0 .. $self->layer_count-2) {
|
||||
my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
|
||||
|
@ -278,7 +287,7 @@ sub make_perimeters {
|
|||
my $overlap = $perimeter_spacing; # one perimeter
|
||||
|
||||
my $diff = diff(
|
||||
[ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)) ],
|
||||
[ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($self->config->perimeters * $perimeter_spacing)) ],
|
||||
[ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ],
|
||||
);
|
||||
next if !@$diff;
|
||||
|
@ -299,8 +308,8 @@ sub make_perimeters {
|
|||
# of our slice
|
||||
$extra_perimeters++;
|
||||
my $hypothetical_perimeter = diff(
|
||||
[ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters-1))) ],
|
||||
[ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters))) ],
|
||||
[ offset($slice->expolygon, -($perimeter_spacing * ($self->config->perimeters + $extra_perimeters-1))) ],
|
||||
[ offset($slice->expolygon, -($perimeter_spacing * ($self->config->perimeters + $extra_perimeters))) ],
|
||||
);
|
||||
last CYCLE if !@$hypothetical_perimeter; # no extra perimeter is possible
|
||||
|
||||
|
@ -451,7 +460,7 @@ sub detect_surfaces_type {
|
|||
|
||||
sub clip_fill_surfaces {
|
||||
my $self = shift;
|
||||
return unless $Slic3r::Config->infill_only_where_needed;
|
||||
return unless $self->config->infill_only_where_needed;
|
||||
|
||||
# We only want infill under ceilings; this is almost like an
|
||||
# internal support material.
|
||||
|
@ -498,7 +507,7 @@ sub clip_fill_surfaces {
|
|||
|
||||
sub bridge_over_infill {
|
||||
my $self = shift;
|
||||
return if $Slic3r::Config->fill_density == 1;
|
||||
return if $self->config->fill_density == 1;
|
||||
|
||||
for my $layer_id (1..$#{$self->layers}) {
|
||||
my $layer = $self->layers->[$layer_id];
|
||||
|
@ -578,8 +587,8 @@ sub discover_horizontal_shells {
|
|||
for (my $i = 0; $i < $self->layer_count; $i++) {
|
||||
my $layerm = $self->layers->[$i]->regions->[$region_id];
|
||||
|
||||
if ($Slic3r::Config->solid_infill_every_layers && $Slic3r::Config->fill_density > 0
|
||||
&& ($i % $Slic3r::Config->solid_infill_every_layers) == 0) {
|
||||
if ($self->config->solid_infill_every_layers && $self->config->fill_density > 0
|
||||
&& ($i % $self->config->solid_infill_every_layers) == 0) {
|
||||
$_->surface_type(S_TYPE_INTERNALSOLID)
|
||||
for grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces};
|
||||
}
|
||||
|
@ -597,8 +606,8 @@ sub discover_horizontal_shells {
|
|||
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP ? 'top' : 'bottom');
|
||||
|
||||
my $solid_layers = ($type == S_TYPE_TOP)
|
||||
? $Slic3r::Config->top_solid_layers
|
||||
: $Slic3r::Config->bottom_solid_layers;
|
||||
? $self->config->top_solid_layers
|
||||
: $self->config->bottom_solid_layers;
|
||||
NEIGHBOR: for (my $n = $type == S_TYPE_TOP ? $i-1 : $i+1;
|
||||
abs($n - $i) <= $solid_layers-1;
|
||||
$type == S_TYPE_TOP ? $n-- : $n++) {
|
||||
|
@ -636,7 +645,7 @@ sub discover_horizontal_shells {
|
|||
|
||||
# if some parts are going to collapse, use a different strategy according to fill density
|
||||
if (@$too_narrow) {
|
||||
if ($Slic3r::Config->fill_density > 0) {
|
||||
if ($self->config->fill_density > 0) {
|
||||
# if we have internal infill, grow the collapsing parts and add the extra area to
|
||||
# the neighbor layer as well as to our original surfaces so that we support this
|
||||
# additional area in the next shell too
|
||||
|
@ -704,8 +713,8 @@ sub discover_horizontal_shells {
|
|||
# combine fill surfaces across layers
|
||||
sub combine_infill {
|
||||
my $self = shift;
|
||||
return unless $Slic3r::Config->infill_every_layers > 1 && $Slic3r::Config->fill_density > 0;
|
||||
my $every = $Slic3r::Config->infill_every_layers;
|
||||
return unless $self->config->infill_every_layers > 1 && $self->config->fill_density > 0;
|
||||
my $every = $self->config->infill_every_layers;
|
||||
|
||||
my $layer_count = $self->layer_count;
|
||||
my @layer_heights = map $self->layers->[$_]->height, 0 .. $layer_count-1;
|
||||
|
@ -768,7 +777,7 @@ sub combine_infill {
|
|||
+ $layerms[-1]->perimeter_flow->scaled_width / 2
|
||||
# Because fill areas for rectilinear and honeycomb are grown
|
||||
# later to overlap perimeters, we need to counteract that too.
|
||||
+ (($type == S_TYPE_INTERNALSOLID || $Slic3r::Config->fill_pattern =~ /(rectilinear|honeycomb)/)
|
||||
+ (($type == S_TYPE_INTERNALSOLID || $self->config->fill_pattern =~ /(rectilinear|honeycomb)/)
|
||||
? $layerms[-1]->solid_infill_flow->scaled_width * &Slic3r::INFILL_OVERLAP_OVER_SPACING
|
||||
: 0)
|
||||
), @$intersection;
|
||||
|
@ -813,7 +822,7 @@ sub combine_infill {
|
|||
|
||||
sub generate_support_material {
|
||||
my $self = shift;
|
||||
return if $self->layer_count < 2;
|
||||
return unless $self->config->support_material && $self->layer_count >= 2;
|
||||
|
||||
my $flow = $self->print->support_material_flow;
|
||||
|
||||
|
@ -826,8 +835,8 @@ sub generate_support_material {
|
|||
|
||||
# if user specified a custom angle threshold, convert it to radians
|
||||
my $threshold_rad;
|
||||
if ($Slic3r::Config->support_material_threshold) {
|
||||
$threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive
|
||||
if ($self->config->support_material_threshold) {
|
||||
$threshold_rad = deg2rad($self->config->support_material_threshold + 1); # +1 makes the threshold inclusive
|
||||
Slic3r::debugf "Threshold angle = %d°\n", rad2deg($threshold_rad);
|
||||
}
|
||||
|
||||
|
@ -851,7 +860,7 @@ sub generate_support_material {
|
|||
my $diff;
|
||||
|
||||
# If a threshold angle was specified, use a different logic for detecting overhangs.
|
||||
if (defined $threshold_rad || $layer_id <= $Slic3r::Config->support_material_enforce_layers) {
|
||||
if (defined $threshold_rad || $layer_id <= $self->config->support_material_enforce_layers) {
|
||||
my $d = defined $threshold_rad
|
||||
? scale $lower_layer->height * ((cos $threshold_rad) / (sin $threshold_rad))
|
||||
: 0;
|
||||
|
@ -963,14 +972,14 @@ sub generate_support_material {
|
|||
|
||||
# we now know the upper and lower boundaries for our support material object
|
||||
# (@contact_z and @top_z), so we can generate intermediate layers
|
||||
my @support_layers = _compute_support_layers(\@contact_z, \@top_z, $Slic3r::Config, $flow);
|
||||
my @support_layers = _compute_support_layers(\@contact_z, \@top_z, $self->config, $flow);
|
||||
|
||||
# if we wanted to apply some special logic to the first support layers lying on
|
||||
# object's top surfaces this is the place to detect them
|
||||
|
||||
# let's now generate interface layers below contact areas
|
||||
my %interface = (); # layer_id => [ polygons ]
|
||||
my $interface_layers = $Slic3r::Config->support_material_interface_layers;
|
||||
my $interface_layers = $self->config->support_material_interface_layers;
|
||||
for my $layer_id (0 .. $#support_layers) {
|
||||
my $z = $support_layers[$layer_id];
|
||||
my $this = $contact{$z} // next;
|
||||
|
@ -1029,8 +1038,8 @@ sub generate_support_material {
|
|||
Slic3r::debugf "Generating patterns\n";
|
||||
|
||||
# prepare fillers
|
||||
my $pattern = $Slic3r::Config->support_material_pattern;
|
||||
my @angles = ($Slic3r::Config->support_material_angle);
|
||||
my $pattern = $self->config->support_material_pattern;
|
||||
my @angles = ($self->config->support_material_angle);
|
||||
if ($pattern eq 'rectilinear-grid') {
|
||||
$pattern = 'rectilinear';
|
||||
push @angles, $angles[0] + 90;
|
||||
|
@ -1041,10 +1050,10 @@ sub generate_support_material {
|
|||
support => $self->fill_maker->filler($pattern),
|
||||
);
|
||||
|
||||
my $interface_angle = $Slic3r::Config->support_material_angle + 90;
|
||||
my $interface_spacing = $Slic3r::Config->support_material_interface_spacing + $flow->spacing;
|
||||
my $interface_angle = $self->config->support_material_angle + 90;
|
||||
my $interface_spacing = $self->config->support_material_interface_spacing + $flow->spacing;
|
||||
my $interface_density = $interface_spacing == 0 ? 1 : $flow->spacing / $interface_spacing;
|
||||
my $support_spacing = $Slic3r::Config->support_material_spacing + $flow->spacing;
|
||||
my $support_spacing = $self->config->support_material_spacing + $flow->spacing;
|
||||
my $support_density = $support_spacing == 0 ? 1 : $flow->spacing / $support_spacing;
|
||||
|
||||
my $process_layer = sub {
|
||||
|
@ -1167,7 +1176,7 @@ sub generate_support_material {
|
|||
# base flange
|
||||
if ($layer_id == 0) {
|
||||
$filler = $fillers{interface};
|
||||
$filler->angle($Slic3r::Config->support_material_angle + 90);
|
||||
$filler->angle($self->config->support_material_angle + 90);
|
||||
$density = 0.5;
|
||||
$flow_spacing = $self->print->first_layer_support_material_flow->spacing;
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue