Refactoring: better API for Print/Object steps with explicit dependencies
This commit is contained in:
parent
d896ad090b
commit
4d76d05bbb
4 changed files with 182 additions and 160 deletions
|
@ -565,8 +565,9 @@ sub rotate {
|
||||||
$_->set_rotation($new_angle) for @{ $model_object->instances };
|
$_->set_rotation($new_angle) for @{ $model_object->instances };
|
||||||
$model_object->update_bounding_box;
|
$model_object->update_bounding_box;
|
||||||
|
|
||||||
# update print
|
# update print and start background processing
|
||||||
$self->{print}->add_model_object($model_object, $obj_idx);
|
$self->{print}->add_model_object($model_object, $obj_idx);
|
||||||
|
$self->start_background_process;
|
||||||
|
|
||||||
$object->transform_thumbnail($self->{model}, $obj_idx);
|
$object->transform_thumbnail($self->{model}, $obj_idx);
|
||||||
}
|
}
|
||||||
|
@ -600,8 +601,9 @@ sub changescale {
|
||||||
$_->set_scaling_factor($scale) for @{ $model_object->instances };
|
$_->set_scaling_factor($scale) for @{ $model_object->instances };
|
||||||
$model_object->update_bounding_box;
|
$model_object->update_bounding_box;
|
||||||
|
|
||||||
# update print
|
# update print and start background processing
|
||||||
$self->{print}->add_model_object($model_object, $obj_idx);
|
$self->{print}->add_model_object($model_object, $obj_idx);
|
||||||
|
$self->start_background_process;
|
||||||
|
|
||||||
$object->transform_thumbnail($self->{model}, $obj_idx);
|
$object->transform_thumbnail($self->{model}, $obj_idx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,9 +219,6 @@ sub add_model_object {
|
||||||
# apply config to print object
|
# apply config to print object
|
||||||
$o->config->apply($self->default_object_config);
|
$o->config->apply($self->default_object_config);
|
||||||
$o->config->apply_dynamic($object_config);
|
$o->config->apply_dynamic($object_config);
|
||||||
|
|
||||||
$self->invalidate_step(STEP_SKIRT);
|
|
||||||
$self->invalidate_step(STEP_BRIM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub reload_object {
|
sub reload_object {
|
||||||
|
@ -328,12 +325,17 @@ sub extruders {
|
||||||
sub init_extruders {
|
sub init_extruders {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_INIT_EXTRUDERS);
|
||||||
|
$self->set_step_started(STEP_INIT_EXTRUDERS);
|
||||||
|
|
||||||
# enforce tall skirt if using ooze_prevention
|
# enforce tall skirt if using ooze_prevention
|
||||||
# FIXME: this is not idempotent (i.e. switching ooze_prevention off will not revert skirt settings)
|
# FIXME: this is not idempotent (i.e. switching ooze_prevention off will not revert skirt settings)
|
||||||
if ($self->config->ooze_prevention && @{$self->extruders} > 1) {
|
if ($self->config->ooze_prevention && @{$self->extruders} > 1) {
|
||||||
$self->config->set('skirt_height', -1);
|
$self->config->set('skirt_height', -1);
|
||||||
$self->config->set('skirts', 1) if $self->config->skirts == 0;
|
$self->config->set('skirts', 1) if $self->config->skirts == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_INIT_EXTRUDERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
# this value is not supposed to be compared with $layer->id
|
# this value is not supposed to be compared with $layer->id
|
||||||
|
@ -380,131 +382,11 @@ sub _simplify_slices {
|
||||||
sub process {
|
sub process {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
my $status_cb = $self->status_cb // sub {};
|
$_->make_perimeters for @{$self->objects};
|
||||||
|
$_->infill for @{$self->objects};
|
||||||
my $print_step = sub {
|
$_->generate_support_material for @{$self->objects};
|
||||||
my ($step, $cb) = @_;
|
|
||||||
if (!$self->step_done($step)) {
|
|
||||||
$self->set_step_started($step);
|
|
||||||
$cb->();
|
|
||||||
$self->set_step_done($step);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
my $object_step = sub {
|
|
||||||
my ($step, $cb) = @_;
|
|
||||||
for my $obj_idx (0..($self->object_count - 1)) {
|
|
||||||
my $object = $self->objects->[$obj_idx];
|
|
||||||
if (!$object->step_done($step)) {
|
|
||||||
$object->set_step_started($step);
|
|
||||||
$cb->($obj_idx);
|
|
||||||
$object->set_step_done($step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
# STEP_INIT_EXTRUDERS
|
|
||||||
$print_step->(STEP_INIT_EXTRUDERS, sub {
|
|
||||||
$self->init_extruders;
|
|
||||||
});
|
|
||||||
|
|
||||||
# STEP_SLICE
|
|
||||||
# skein the STL into layers
|
|
||||||
# each layer has surfaces with holes
|
|
||||||
$status_cb->(10, "Processing triangulated mesh");
|
|
||||||
$object_step->(STEP_SLICE, sub {
|
|
||||||
$self->objects->[$_[0]]->slice;
|
|
||||||
});
|
|
||||||
|
|
||||||
die "No layers were detected. You might want to repair your STL file(s) or check their size and retry.\n"
|
|
||||||
if !grep @{$_->layers}, @{$self->objects};
|
|
||||||
|
|
||||||
# make perimeters
|
|
||||||
# this will add a set of extrusion loops to each layer
|
|
||||||
# as well as generate infill boundaries
|
|
||||||
$status_cb->(20, "Generating perimeters");
|
|
||||||
$object_step->(STEP_PERIMETERS, sub {
|
|
||||||
$self->objects->[$_[0]]->make_perimeters;
|
|
||||||
});
|
|
||||||
|
|
||||||
$status_cb->(30, "Preparing infill");
|
|
||||||
$object_step->(STEP_PREPARE_INFILL, sub {
|
|
||||||
my $object = $self->objects->[$_[0]];
|
|
||||||
|
|
||||||
# this will assign a type (top/bottom/internal) to $layerm->slices
|
|
||||||
# and transform $layerm->fill_surfaces from expolygon
|
|
||||||
# to typed top/bottom/internal surfaces;
|
|
||||||
$object->detect_surfaces_type;
|
|
||||||
|
|
||||||
# decide what surfaces are to be filled
|
|
||||||
$_->prepare_fill_surfaces for map @{$_->regions}, @{$object->layers};
|
|
||||||
|
|
||||||
# this will detect bridges and reverse bridges
|
|
||||||
# and rearrange top/bottom/internal surfaces
|
|
||||||
$object->process_external_surfaces;
|
|
||||||
|
|
||||||
# detect which fill surfaces are near external layers
|
|
||||||
# they will be split in internal and internal-solid surfaces
|
|
||||||
$object->discover_horizontal_shells;
|
|
||||||
$object->clip_fill_surfaces;
|
|
||||||
|
|
||||||
# the following step needs to be done before combination because it may need
|
|
||||||
# to remove only half of the combined infill
|
|
||||||
$object->bridge_over_infill;
|
|
||||||
|
|
||||||
# combine fill surfaces to honor the "infill every N layers" option
|
|
||||||
$object->combine_infill;
|
|
||||||
});
|
|
||||||
|
|
||||||
# this will generate extrusion paths for each layer
|
|
||||||
$status_cb->(70, "Infilling layers");
|
|
||||||
$object_step->(STEP_INFILL, sub {
|
|
||||||
my $object = $self->objects->[$_[0]];
|
|
||||||
|
|
||||||
Slic3r::parallelize(
|
|
||||||
threads => $self->config->threads,
|
|
||||||
items => sub {
|
|
||||||
my @items = (); # [layer_id, region_id]
|
|
||||||
for my $region_id (0 .. ($self->regions_count-1)) {
|
|
||||||
push @items, map [$_, $region_id], 0..($object->layer_count - 1);
|
|
||||||
}
|
|
||||||
@items;
|
|
||||||
},
|
|
||||||
thread_cb => sub {
|
|
||||||
my $q = shift;
|
|
||||||
while (defined (my $obj_layer = $q->dequeue)) {
|
|
||||||
my ($i, $region_id) = @$obj_layer;
|
|
||||||
my $layerm = $object->layers->[$i]->regions->[$region_id];
|
|
||||||
$layerm->fills->clear;
|
|
||||||
$layerm->fills->append( $object->fill_maker->make_fill($layerm) );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
collect_cb => sub {},
|
|
||||||
no_threads_cb => sub {
|
|
||||||
foreach my $layerm (map @{$_->regions}, @{$object->layers}) {
|
|
||||||
$layerm->fills->clear;
|
|
||||||
$layerm->fills->append($object->fill_maker->make_fill($layerm));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
### we could free memory now, but this would make this step not idempotent
|
|
||||||
### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
|
|
||||||
});
|
|
||||||
|
|
||||||
# generate support material
|
|
||||||
$status_cb->(85, "Generating support material") if $self->has_support_material;
|
|
||||||
$object_step->(STEP_SUPPORTMATERIAL, sub {
|
|
||||||
$self->objects->[$_[0]]->generate_support_material;
|
|
||||||
});
|
|
||||||
|
|
||||||
# make skirt
|
|
||||||
$status_cb->(88, "Generating skirt/brim");
|
|
||||||
$print_step->(STEP_SKIRT, sub {
|
|
||||||
$self->make_skirt;
|
$self->make_skirt;
|
||||||
});
|
|
||||||
$print_step->(STEP_BRIM, sub {
|
|
||||||
$self->make_brim; # must come after make_skirt
|
$self->make_brim; # must come after make_skirt
|
||||||
});
|
|
||||||
|
|
||||||
# time to make some statistics
|
# time to make some statistics
|
||||||
if (0) {
|
if (0) {
|
||||||
|
@ -639,6 +521,15 @@ EOF
|
||||||
sub make_skirt {
|
sub make_skirt {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$_->make_perimeters for @{$self->objects};
|
||||||
|
$_->infill for @{$self->objects};
|
||||||
|
$_->generate_support_material for @{$self->objects};
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_SKIRT);
|
||||||
|
$self->set_step_started(STEP_SKIRT);
|
||||||
|
$self->status_cb->(88, "Generating skirt/brim");
|
||||||
|
|
||||||
# since this method must be idempotent, we clear skirt paths *before*
|
# since this method must be idempotent, we clear skirt paths *before*
|
||||||
# checking whether we need to generate them
|
# checking whether we need to generate them
|
||||||
$self->skirt->clear;
|
$self->skirt->clear;
|
||||||
|
@ -749,11 +640,23 @@ sub make_skirt {
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->skirt->reverse;
|
$self->skirt->reverse;
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_SKIRT);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_brim {
|
sub make_brim {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$_->make_perimeters for @{$self->objects};
|
||||||
|
$_->infill for @{$self->objects};
|
||||||
|
$_->generate_support_material for @{$self->objects};
|
||||||
|
$self->make_skirt;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_BRIM);
|
||||||
|
$self->set_step_started(STEP_BRIM);
|
||||||
|
$self->status_cb->(88, "Generating skirt/brim");
|
||||||
|
|
||||||
# since this method must be idempotent, we clear brim paths *before*
|
# since this method must be idempotent, we clear brim paths *before*
|
||||||
# checking whether we need to generate them
|
# checking whether we need to generate them
|
||||||
$self->brim->clear;
|
$self->brim->clear;
|
||||||
|
@ -818,6 +721,8 @@ sub make_brim {
|
||||||
height => $first_layer_height,
|
height => $first_layer_height,
|
||||||
),
|
),
|
||||||
), reverse @{union_pt_chained(\@loops)});
|
), reverse @{union_pt_chained(\@loops)});
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_BRIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub write_gcode {
|
sub write_gcode {
|
||||||
|
|
|
@ -97,7 +97,10 @@ sub bounding_box {
|
||||||
# this should be idempotent
|
# this should be idempotent
|
||||||
sub slice {
|
sub slice {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my %params = @_;
|
|
||||||
|
return if $self->step_done(STEP_SLICE);
|
||||||
|
$self->set_step_started(STEP_SLICE);
|
||||||
|
$self->print->status_cb->(10, "Processing triangulated mesh");
|
||||||
|
|
||||||
# init layers
|
# init layers
|
||||||
{
|
{
|
||||||
|
@ -357,6 +360,11 @@ sub slice {
|
||||||
if ($self->print->config->resolution) {
|
if ($self->print->config->resolution) {
|
||||||
$self->_simplify_slices(scale($self->print->config->resolution));
|
$self->_simplify_slices(scale($self->print->config->resolution));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
die "No layers were detected. You might want to repair your STL file(s) or check their size and retry.\n"
|
||||||
|
if !@{$self->layers};
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_SLICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _slice_region {
|
sub _slice_region {
|
||||||
|
@ -394,6 +402,14 @@ sub _slice_region {
|
||||||
sub make_perimeters {
|
sub make_perimeters {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$self->print->init_extruders;
|
||||||
|
$self->slice;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_PERIMETERS);
|
||||||
|
$self->set_step_started(STEP_PERIMETERS);
|
||||||
|
$self->print->status_cb->(20, "Generating perimeters");
|
||||||
|
|
||||||
# compare each layer to the one below, and mark those slices needing
|
# compare each layer to the one below, and mark those slices needing
|
||||||
# one additional inner perimeter, like the top of domed objects-
|
# one additional inner perimeter, like the top of domed objects-
|
||||||
|
|
||||||
|
@ -473,6 +489,125 @@ sub make_perimeters {
|
||||||
# we only need the max resolution for perimeters
|
# we only need the max resolution for perimeters
|
||||||
### This makes this method not-idempotent, so we keep it disabled for now.
|
### This makes this method not-idempotent, so we keep it disabled for now.
|
||||||
###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION);
|
###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION);
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_PERIMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prepare_infill {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$self->make_perimeters;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_PREPARE_INFILL);
|
||||||
|
$self->set_step_started(STEP_PREPARE_INFILL);
|
||||||
|
$self->print->status_cb->(30, "Preparing infill");
|
||||||
|
|
||||||
|
# this will assign a type (top/bottom/internal) to $layerm->slices
|
||||||
|
# and transform $layerm->fill_surfaces from expolygon
|
||||||
|
# to typed top/bottom/internal surfaces;
|
||||||
|
$self->detect_surfaces_type;
|
||||||
|
|
||||||
|
# decide what surfaces are to be filled
|
||||||
|
$_->prepare_fill_surfaces for map @{$_->regions}, @{$self->layers};
|
||||||
|
|
||||||
|
# this will detect bridges and reverse bridges
|
||||||
|
# and rearrange top/bottom/internal surfaces
|
||||||
|
$self->process_external_surfaces;
|
||||||
|
|
||||||
|
# detect which fill surfaces are near external layers
|
||||||
|
# they will be split in internal and internal-solid surfaces
|
||||||
|
$self->discover_horizontal_shells;
|
||||||
|
$self->clip_fill_surfaces;
|
||||||
|
|
||||||
|
# the following step needs to be done before combination because it may need
|
||||||
|
# to remove only half of the combined infill
|
||||||
|
$self->bridge_over_infill;
|
||||||
|
|
||||||
|
# combine fill surfaces to honor the "infill every N layers" option
|
||||||
|
$self->combine_infill;
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_PREPARE_INFILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub infill {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$self->prepare_infill;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_INFILL);
|
||||||
|
$self->set_step_started(STEP_INFILL);
|
||||||
|
$self->print->status_cb->(70, "Infilling layers");
|
||||||
|
|
||||||
|
Slic3r::parallelize(
|
||||||
|
threads => $self->print->config->threads,
|
||||||
|
items => sub {
|
||||||
|
my @items = (); # [layer_id, region_id]
|
||||||
|
for my $region_id (0 .. ($self->print->regions_count-1)) {
|
||||||
|
push @items, map [$_, $region_id], 0..($self->layer_count - 1);
|
||||||
|
}
|
||||||
|
@items;
|
||||||
|
},
|
||||||
|
thread_cb => sub {
|
||||||
|
my $q = shift;
|
||||||
|
while (defined (my $obj_layer = $q->dequeue)) {
|
||||||
|
my ($i, $region_id) = @$obj_layer;
|
||||||
|
my $layerm = $self->layers->[$i]->regions->[$region_id];
|
||||||
|
$layerm->fills->clear;
|
||||||
|
$layerm->fills->append( $self->fill_maker->make_fill($layerm) );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
collect_cb => sub {},
|
||||||
|
no_threads_cb => sub {
|
||||||
|
foreach my $layerm (map @{$_->regions}, @{$self->layers}) {
|
||||||
|
$layerm->fills->clear;
|
||||||
|
$layerm->fills->append($self->fill_maker->make_fill($layerm));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
### we could free memory now, but this would make this step not idempotent
|
||||||
|
### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_INFILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub generate_support_material {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
# prerequisites
|
||||||
|
$self->print->init_extruders;
|
||||||
|
$self->slice;
|
||||||
|
|
||||||
|
return if $self->step_done(STEP_SUPPORTMATERIAL);
|
||||||
|
$self->set_step_started(STEP_SUPPORTMATERIAL);
|
||||||
|
$self->print->status_cb->(85, "Generating support material");
|
||||||
|
|
||||||
|
$self->clear_support_layers;
|
||||||
|
|
||||||
|
return unless ($self->config->support_material || $self->config->raft_layers > 0)
|
||||||
|
&& scalar(@{$self->layers}) >= 2;
|
||||||
|
|
||||||
|
my $first_layer_flow = Slic3r::Flow->new_from_width(
|
||||||
|
width => ($self->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
|
||||||
|
role => FLOW_ROLE_SUPPORT_MATERIAL,
|
||||||
|
nozzle_diameter => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
|
||||||
|
// $self->print->config->nozzle_diameter->[0],
|
||||||
|
layer_height => $self->config->get_abs_value('first_layer_height'),
|
||||||
|
bridge_flow_ratio => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
my $s = Slic3r::Print::SupportMaterial->new(
|
||||||
|
print_config => $self->print->config,
|
||||||
|
object_config => $self->config,
|
||||||
|
first_layer_flow => $first_layer_flow,
|
||||||
|
flow => $self->support_material_flow,
|
||||||
|
interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
|
||||||
|
);
|
||||||
|
$s->generate($self);
|
||||||
|
|
||||||
|
$self->set_step_done(STEP_SUPPORTMATERIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub detect_surfaces_type {
|
sub detect_surfaces_type {
|
||||||
|
@ -1005,33 +1140,6 @@ sub combine_infill {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub generate_support_material {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
$self->clear_support_layers;
|
|
||||||
|
|
||||||
return unless ($self->config->support_material || $self->config->raft_layers > 0)
|
|
||||||
&& scalar(@{$self->layers}) >= 2;
|
|
||||||
|
|
||||||
my $first_layer_flow = Slic3r::Flow->new_from_width(
|
|
||||||
width => ($self->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
|
|
||||||
role => FLOW_ROLE_SUPPORT_MATERIAL,
|
|
||||||
nozzle_diameter => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
|
|
||||||
// $self->print->config->nozzle_diameter->[0],
|
|
||||||
layer_height => $self->config->get_abs_value('first_layer_height'),
|
|
||||||
bridge_flow_ratio => 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
my $s = Slic3r::Print::SupportMaterial->new(
|
|
||||||
print_config => $self->print->config,
|
|
||||||
object_config => $self->config,
|
|
||||||
first_layer_flow => $first_layer_flow,
|
|
||||||
flow => $self->support_material_flow,
|
|
||||||
interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
|
|
||||||
);
|
|
||||||
$s->generate($self);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _simplify_slices {
|
sub _simplify_slices {
|
||||||
my ($self, $distance) = @_;
|
my ($self, $distance) = @_;
|
||||||
|
|
||||||
|
|
|
@ -333,11 +333,15 @@ Print::get_object(size_t idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintObject*
|
PrintObject*
|
||||||
Print::add_object(ModelObject *model_object,
|
Print::add_object(ModelObject *model_object, const BoundingBoxf3 &modobj_bbox)
|
||||||
const BoundingBoxf3 &modobj_bbox)
|
|
||||||
{
|
{
|
||||||
PrintObject *object = new PrintObject(this, model_object, modobj_bbox);
|
PrintObject *object = new PrintObject(this, model_object, modobj_bbox);
|
||||||
objects.push_back(object);
|
objects.push_back(object);
|
||||||
|
|
||||||
|
// invalidate steps
|
||||||
|
this->invalidate_step(psSkirt);
|
||||||
|
this->invalidate_step(psBrim);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +351,9 @@ Print::set_new_object(size_t idx, ModelObject *model_object, const BoundingBoxf3
|
||||||
if (idx >= this->objects.size()) throw "bad idx";
|
if (idx >= this->objects.size()) throw "bad idx";
|
||||||
|
|
||||||
PrintObjectPtrs::iterator old_it = this->objects.begin() + idx;
|
PrintObjectPtrs::iterator old_it = this->objects.begin() + idx;
|
||||||
|
// before deleting object, invalidate all of its steps in order to
|
||||||
|
// invalidate all of the dependent ones in Print
|
||||||
|
(*old_it)->invalidate_all_steps();
|
||||||
delete *old_it;
|
delete *old_it;
|
||||||
|
|
||||||
PrintObject *object = new PrintObject(this, model_object, modobj_bbox);
|
PrintObject *object = new PrintObject(this, model_object, modobj_bbox);
|
||||||
|
|
Loading…
Add table
Reference in a new issue