diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index ac6666e7..8439e34a 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -158,7 +158,6 @@ sub thread_cleanup { *Slic3r::Polyline::DESTROY = sub {}; *Slic3r::Polyline::Collection::DESTROY = sub {}; *Slic3r::Print::DESTROY = sub {}; - *Slic3r::Print::State::DESTROY = sub {}; *Slic3r::Print::Region::DESTROY = sub {}; *Slic3r::Surface::DESTROY = sub {}; *Slic3r::Surface::Collection::DESTROY = sub {}; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 65d166e7..51b31a67 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -13,7 +13,6 @@ use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex inter offset2 union union_pt_chained JT_ROUND JT_SQUARE); use Slic3r::Print::State ':steps'; - our $status_cb; sub new { @@ -49,8 +48,8 @@ sub apply_config { if (@$print_diff) { $self->config->apply_dynamic($config); - # TODO: only invalidate changed steps - $self->_state->invalidate_all; + $self->invalidate_all_steps + if !$self->invalidate_state_by_config_options($print_diff); } # handle changes to object config defaults @@ -59,6 +58,7 @@ sub apply_config { # we don't assume that $config contains a full ObjectConfig, # so we base it on the current print-wise default my $new = $self->default_object_config->clone; + $new->apply_dynamic($config); # we override the new config with object-specific options my $model_object_config = $object->model_object->config->clone; @@ -69,8 +69,8 @@ sub apply_config { my $diff = $object->config->diff($new); if (@$diff) { $object->config->apply($new); - # TODO: only invalidate changed steps - $object->_state->invalidate_all; + $object->invalidate_all_steps + if !$object->invalidate_state_by_config_options($diff); } } @@ -188,8 +188,8 @@ sub add_model_object { $o->config->apply($self->default_object_config); $o->config->apply_dynamic($object_config); - $self->_state->invalidate(STEP_SKIRT); - $self->_state->invalidate(STEP_BRIM); + $self->invalidate_step(STEP_SKIRT); + $self->invalidate_step(STEP_BRIM); } sub reload_object { @@ -352,20 +352,20 @@ sub process { my $print_step = sub { my ($step, $cb) = @_; - if (!$self->_state->done($step)) { - $self->_state->set_started($step); + if (!$self->step_done($step)) { + $self->set_step_started($step); $cb->(); - $self->_state->set_done($step); + $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->_state->done($step)) { - $object->_state->set_started($step); + if (!$object->step_done($step)) { + $object->set_step_started($step); $cb->($obj_idx); - $object->_state->set_done($step); + $object->set_step_done($step); } } }; @@ -1082,27 +1082,6 @@ sub expanded_output_filepath { return $self->placeholder_parser->process($path, $extra); } -sub invalidate_step { - my ($self, $step, $obj_idx) = @_; - - # invalidate $step in the correct state object - if ($Slic3r::Print::State::print_step->{$step}) { - $self->_state->invalidate($step); - } else { - # object step - if (defined $obj_idx) { - $self->objects->[$obj_idx]->_state->invalidate($step); - } else { - $_->_state->invalidate($step) for @{$self->objects}; - } - } - - # recursively invalidate steps depending on $step - $self->invalidate_step($_) - for grep { grep { $_ == $step } @{$Slic3r::Print::State::prereqs{$_}} } - keys %Slic3r::Print::State::prereqs; -} - # This method assigns extruders to the volumes having a material # but not having extruders set in the material config. sub auto_assign_extruders { diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 03aa86db..65456594 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -49,8 +49,8 @@ sub _trigger_copies { } @{$self->copies}[@{chained_path($self->copies)}] ]); - $self->print->_state->invalidate(STEP_SKIRT); - $self->print->_state->invalidate(STEP_BRIM); + $self->print->invalidate_step(STEP_SKIRT); + $self->print->invalidate_step(STEP_BRIM); } # in unscaled coordinates diff --git a/lib/Slic3r/Print/State.pm b/lib/Slic3r/Print/State.pm index bd76e380..437f66a7 100644 --- a/lib/Slic3r/Print/State.pm +++ b/lib/Slic3r/Print/State.pm @@ -8,21 +8,4 @@ our @EXPORT_OK = qw(STEP_INIT_EXTRUDERS STEP_SLICE STEP_PERIMETERS STEP_PREPAR STEP_INFILL STEP_SUPPORTMATERIAL STEP_SKIRT STEP_BRIM); our %EXPORT_TAGS = (steps => \@EXPORT_OK); -our %print_steps = map { $_ => 1 } ( - STEP_INIT_EXTRUDERS, - STEP_SKIRT, - STEP_BRIM, -); - -our %prereqs = ( - STEP_INIT_EXTRUDERS => [], - STEP_SLICE => [], - STEP_PERIMETERS => [STEP_SLICE, STEP_INIT_EXTRUDERS], - STEP_PREPARE_INFILL => [STEP_PERIMETERS], - STEP_INFILL => [STEP_INFILL], - STEP_SUPPORTMATERIAL => [STEP_SLICE, STEP_INIT_EXTRUDERS], - STEP_SKIRT => [STEP_PERIMETERS, STEP_INFILL], - STEP_BRIM => [STEP_PERIMETERS, STEP_INFILL, STEP_SKIRT], -); - 1; diff --git a/xs/src/Print.cpp b/xs/src/Print.cpp index 44513e49..bd957a41 100644 --- a/xs/src/Print.cpp +++ b/xs/src/Print.cpp @@ -3,52 +3,56 @@ namespace Slic3r { +template bool -PrintState::started(PrintStep step) const +PrintState::started(StepClass step) const { return this->_started.find(step) != this->_started.end(); } +template bool -PrintState::done(PrintStep step) const +PrintState::done(StepClass step) const { return this->_done.find(step) != this->_done.end(); } +template void -PrintState::set_started(PrintStep step) +PrintState::set_started(StepClass step) { this->_started.insert(step); } +template void -PrintState::set_done(PrintStep step) +PrintState::set_done(StepClass step) { this->_done.insert(step); } +template void -PrintState::invalidate(PrintStep step) +PrintState::invalidate(StepClass step) { this->_started.erase(step); this->_done.erase(step); } +template void -PrintState::invalidate_all() +PrintState::invalidate_all() { this->_started.clear(); this->_done.clear(); } -#ifdef SLIC3RXS -REGISTER_CLASS(PrintState, "Print::State"); -#endif - +template class PrintState; +template class PrintState; PrintRegion::PrintRegion(Print* print) -: config(), _print(print) + : _print(print) { } @@ -67,8 +71,7 @@ REGISTER_CLASS(PrintRegion, "Print::Region"); #endif -PrintObject::PrintObject(Print* print, ModelObject* model_object, - const BoundingBoxf3 &modobj_bbox) +PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox) : _print(print), _model_object(model_object) { @@ -139,8 +142,7 @@ PrintObject::get_layer(int idx) } Layer* -PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, - coordf_t slice_z) +PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z) { Layer* layer = new Layer(id, this, height, print_z, slice_z); layers.push_back(layer); @@ -191,6 +193,68 @@ PrintObject::delete_support_layer(int idx) this->support_layers.erase(i); } +bool +PrintObject::invalidate_state_by_config_options(const std::vector &opt_keys) +{ + std::set steps; + + // this method only accepts PrintObjectConfig option keys + for (std::vector::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) { + if (*opt_key == "perimeters") { + steps.insert(posPerimeters); + } else if (*opt_key == "resolution" + || *opt_key == "layer_height" + || *opt_key == "first_layer_height" + || *opt_key == "xy_size_compensation" + || *opt_key == "raft_layers") { + steps.insert(posSlice); + } else if (*opt_key == "support_material" + || *opt_key == "support_material_angle" + || *opt_key == "support_material_extrusion_width" + || *opt_key == "support_material_interface_layers" + || *opt_key == "support_material_interface_spacing" + || *opt_key == "support_material_interface_speed" + || *opt_key == "support_material_pattern" + || *opt_key == "support_material_spacing" + || *opt_key == "support_material_threshold" + || *opt_key == "dont_support_bridges") { + steps.insert(posSupportMaterial); + } else if (*opt_key == "interface_shells" + || *opt_key == "infill_only_where_needed") { + steps.insert(posPrepareInfill); + } else { + // for legacy, if we can't handle this option let's signal the caller to invalidate all steps + return false; + } + } + + for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) + this->invalidate_step(*step); + + return true; +} + +void +PrintObject::invalidate_step(PrintObjectStep step) +{ + this->state.invalidate(step); + + // propagate to dependent steps + if (step == posPerimeters) { + this->invalidate_step(posPrepareInfill); + this->_print->invalidate_step(psSkirt); + this->_print->invalidate_step(psBrim); + } else if (step == posPrepareInfill) { + this->invalidate_step(posInfill); + } else if (step == posInfill) { + this->_print->invalidate_step(psSkirt); + this->_print->invalidate_step(psBrim); + } else if (step == posSlice) { + this->invalidate_step(posPerimeters); + this->invalidate_step(posSupportMaterial); + } +} + #ifdef SLIC3RXS REGISTER_CLASS(PrintObject, "Print::Object"); @@ -217,8 +281,8 @@ Print::clear_objects() this->clear_regions(); - this->_state.invalidate(psSkirt); - this->_state.invalidate(psBrim); + this->state.invalidate(psSkirt); + this->state.invalidate(psBrim); } PrintObject* @@ -239,7 +303,7 @@ Print::add_object(ModelObject *model_object, PrintObject* Print::set_new_object(size_t idx, ModelObject *model_object, const BoundingBoxf3 &modobj_bbox) { - if (idx < 0 || idx >= this->objects.size()) throw "bad idx"; + if (idx >= this->objects.size()) throw "bad idx"; PrintObjectPtrs::iterator old_it = this->objects.begin() + idx; delete *old_it; @@ -258,8 +322,8 @@ Print::delete_object(size_t idx) // TODO: purge unused regions - this->_state.invalidate(psSkirt); - this->_state.invalidate(psBrim); + this->state.invalidate(psSkirt); + this->state.invalidate(psBrim); } void @@ -291,6 +355,48 @@ Print::delete_region(size_t idx) this->regions.erase(i); } +bool +Print::invalidate_state_by_config_options(const std::vector &opt_keys) +{ + std::set steps; + + // this method only accepts PrintConfig option keys + for (std::vector::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) { + if (*opt_key == "skirts" + || *opt_key == "skirt_height" + || *opt_key == "skirt_distance" + || *opt_key == "min_skirt_length") { + steps.insert(psSkirt); + } else if (*opt_key == "brim_width") { + steps.insert(psBrim); + } else { + // for legacy, if we can't handle this option let's signal the caller to invalidate all steps + return false; + } + } + + for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) + this->invalidate_step(*step); + + return true; +} + +void +Print::invalidate_step(PrintStep step) +{ + this->state.invalidate(step); + + // propagate to dependent steps + if (step == psSkirt) { + this->invalidate_step(psBrim); + } else if (step == psInitExtruders) { + for (PrintObjectPtrs::iterator object = this->objects.begin(); object != this->objects.end(); ++object) { + (*object)->invalidate_step(posPerimeters); + (*object)->invalidate_step(posSupportMaterial); + } + } +} + #ifdef SLIC3RXS REGISTER_CLASS(Print, "Print"); diff --git a/xs/src/Print.hpp b/xs/src/Print.hpp index 41a18c93..c5590277 100644 --- a/xs/src/Print.hpp +++ b/xs/src/Print.hpp @@ -17,22 +17,25 @@ class ModelObject; enum PrintStep { - psInitExtruders, psSlice, psPerimeters, prPrepareInfill, - psInfill, psSupportMaterial, psSkirt, psBrim, + psInitExtruders, psSkirt, psBrim, +}; +enum PrintObjectStep { + posSlice, posPerimeters, posPrepareInfill, + posInfill, posSupportMaterial, }; +template class PrintState { private: - std::set _started; - std::set _done; + std::set _started, _done; public: - bool started(PrintStep step) const; - bool done(PrintStep step) const; - void set_started(PrintStep step); - void set_done(PrintStep step); - void invalidate(PrintStep step); + bool started(StepType step) const; + bool done(StepType step) const; + void set_started(StepType step); + void set_done(StepType step); + void invalidate(StepType step); void invalidate_all(); }; @@ -83,7 +86,7 @@ class PrintObject LayerPtrs layers; SupportLayerPtrs support_layers; // TODO: Fill* fill_maker => (is => 'lazy'); - PrintState _state; + PrintState state; Print* print(); ModelObject* model_object(); @@ -102,7 +105,11 @@ class PrintObject SupportLayer* get_support_layer(int idx); SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z); void delete_support_layer(int idx); - + + // methods for handling state + bool invalidate_state_by_config_options(const std::vector &opt_keys); + void invalidate_step(PrintObjectStep step); + private: Print* _print; ModelObject* _model_object; @@ -127,7 +134,7 @@ class Print PlaceholderParser placeholder_parser; // TODO: status_cb double total_used_filament, total_extruded_volume; - PrintState _state; + PrintState state; // ordered collections of extrusion paths to build skirt loops and brim ExtrusionEntityCollection skirt, brim; @@ -145,6 +152,10 @@ class Print // methods for handling regions PrintRegion* get_region(size_t idx); PrintRegion* add_region(); + + // methods for handling state + bool invalidate_state_by_config_options(const std::vector &opt_keys); + void invalidate_step(PrintStep step); private: void clear_regions(); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index d8319e79..6a69dcc8 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -6,20 +6,6 @@ #include "PlaceholderParser.hpp" %} -%name{Slic3r::Print::State} class PrintState { - PrintState(); - ~PrintState(); - bool started(PrintStep step) const; - bool done(PrintStep step) const; - void set_started(PrintStep step); - void set_done(PrintStep step); - void invalidate(PrintStep step); - void invalidate_all(); -%{ - -%} -}; - %package{Slic3r::Print::State}; %{ @@ -27,11 +13,11 @@ IV _constant() ALIAS: STEP_INIT_EXTRUDERS = psInitExtruders - STEP_SLICE = psSlice - STEP_PERIMETERS = psPerimeters - STEP_PREPARE_INFILL = prPrepareInfill - STEP_INFILL = psInfill - STEP_SUPPORTMATERIAL = psSupportMaterial + STEP_SLICE = posSlice + STEP_PERIMETERS = posPerimeters + STEP_PREPARE_INFILL = posPrepareInfill + STEP_INFILL = posInfill + STEP_SUPPORTMATERIAL = posSupportMaterial STEP_SKIRT = psSkirt STEP_BRIM = psBrim PROTOTYPE: @@ -71,8 +57,6 @@ _constant() %code%{ RETVAL = THIS->copies; %}; t_layer_height_ranges layer_height_ranges() %code%{ RETVAL = THIS->layer_height_ranges; %}; - Ref _state() - %code%{ RETVAL = &THIS->_state; %}; Ref size() %code%{ RETVAL = &THIS->size; %}; Ref _copies_shift() @@ -98,10 +82,20 @@ _constant() size_t support_layer_count(); void clear_support_layers(); Ref get_support_layer(int idx); - Ref add_support_layer(int id, coordf_t height, coordf_t print_z, - coordf_t slice_z); + Ref add_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z); void delete_support_layer(int idx); + bool invalidate_state_by_config_options(std::vector opt_keys); + void invalidate_step(PrintObjectStep step); + void invalidate_all_steps() + %code%{ THIS->state.invalidate_all(); %}; + bool step_done(PrintObjectStep step) + %code%{ RETVAL = THIS->state.done(step); %}; + void set_step_done(PrintObjectStep step) + %code%{ THIS->state.set_done(step); %}; + void set_step_started(PrintObjectStep step) + %code%{ THIS->state.set_started(step); %}; + int ptr() %code%{ RETVAL = (int)(intptr_t)THIS; %}; }; @@ -120,8 +114,6 @@ _constant() Ref placeholder_parser() %code%{ RETVAL = &THIS->placeholder_parser; %}; // TODO: status_cb - Ref _state() - %code%{ RETVAL = &THIS->_state; %}; Ref skirt() %code%{ RETVAL = &THIS->skirt; %}; Ref brim() @@ -147,6 +139,17 @@ _constant() Ref add_region(); size_t region_count() %code%{ RETVAL = THIS->regions.size(); %}; + + bool invalidate_state_by_config_options(std::vector opt_keys); + void invalidate_step(PrintStep step); + void invalidate_all_steps() + %code%{ THIS->state.invalidate_all(); %}; + bool step_done(PrintStep step) + %code%{ RETVAL = THIS->state.done(step); %}; + void set_step_done(PrintStep step) + %code%{ THIS->state.set_done(step); %}; + void set_step_started(PrintStep step) + %code%{ THIS->state.set_started(step); %}; %{ double diff --git a/xs/xsp/my.map b/xs/xsp/my.map index d04024cf..e84a1440 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -153,6 +153,7 @@ ExtrusionLoopRole T_UV ExtrusionRole T_UV FlowRole T_UV PrintStep T_UV +PrintObjectStep T_UV SurfaceType T_UV ClipperLib::JoinType T_UV ClipperLib::PolyFillType T_UV diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index cf5cc3d5..d56f3fda 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -176,3 +176,9 @@ $CVar = (PrintStep)SvUV($PerlVar); %}; }; +%typemap{PrintObjectStep}{parsed}{ + %cpp_type{PrintObjectStep}; + %precall_code{% + $CVar = (PrintObjectStep)SvUV($PerlVar); + %}; +};