diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index ab5babcaa..2b80c3ab5 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -12,8 +12,8 @@ namespace Slic3r { -template class PrintState; -template class PrintState; +template class PrintState; +template class PrintState; Print::Print() @@ -113,105 +113,105 @@ Print::delete_region(size_t idx) bool Print::invalidate_state_by_config_options(const std::vector &opt_keys) { - std::set steps; - std::set osteps; + std::vector steps; + std::vector osteps; // 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" - || *opt_key == "ooze_prevention") { - steps.insert(psSkirt); - } else if (*opt_key == "brim_width") { - steps.insert(psBrim); - steps.insert(psSkirt); - } else if (*opt_key == "nozzle_diameter" - || *opt_key == "resolution") { - osteps.insert(posSlice); + for (const t_config_option_key &opt_key : opt_keys) { + if ( opt_key == "skirts" + || opt_key == "skirt_height" + || opt_key == "skirt_distance" + || opt_key == "min_skirt_length" + || opt_key == "ooze_prevention") { + steps.emplace_back(psSkirt); + } else if (opt_key == "brim_width") { + steps.emplace_back(psBrim); + steps.emplace_back(psSkirt); + } else if (opt_key == "nozzle_diameter" + || opt_key == "resolution") { + osteps.emplace_back(posSlice); } else if ( - *opt_key == "complete_objects" - || *opt_key == "filament_type" - || *opt_key == "first_layer_temperature" - || *opt_key == "gcode_flavor" - || *opt_key == "single_extruder_multi_material" - || *opt_key == "spiral_vase" - || *opt_key == "temperature" - || *opt_key == "wipe_tower" - || *opt_key == "wipe_tower_x" - || *opt_key == "wipe_tower_y" - || *opt_key == "wipe_tower_width" - || *opt_key == "wipe_tower_per_color_wipe" - || *opt_key == "z_offset") { - steps.insert(psWipeTower); - } else if (*opt_key == "avoid_crossing_perimeters" - || *opt_key == "bed_shape" - || *opt_key == "bed_temperature" - || *opt_key == "bridge_acceleration" - || *opt_key == "bridge_fan_speed" - || *opt_key == "cooling" - || *opt_key == "default_acceleration" - || *opt_key == "disable_fan_first_layers" - || *opt_key == "duplicate_distance" - || *opt_key == "end_gcode" - || *opt_key == "extruder_clearance_height" - || *opt_key == "extruder_clearance_radius" - || *opt_key == "extruder_colour" - || *opt_key == "extruder_offset" - || *opt_key == "extrusion_axis" - || *opt_key == "extrusion_multiplier" - || *opt_key == "fan_always_on" - || *opt_key == "fan_below_layer_time" - || *opt_key == "filament_diameter" - || *opt_key == "filament_notes" - || *opt_key == "filament_soluble" - || *opt_key == "first_layer_acceleration" - || *opt_key == "first_layer_bed_temperature" - || *opt_key == "first_layer_speed" - || *opt_key == "gcode_comments" - || *opt_key == "infill_acceleration" - || *opt_key == "infill_first" - || *opt_key == "layer_gcode" - || *opt_key == "min_fan_speed" - || *opt_key == "max_fan_speed" - || *opt_key == "min_print_speed" - || *opt_key == "notes" - || *opt_key == "only_retract_when_crossing_perimeters" - || *opt_key == "output_filename_format" - || *opt_key == "perimeter_acceleration" - || *opt_key == "post_process" - || *opt_key == "retract_before_travel" - || *opt_key == "retract_before_wipe" - || *opt_key == "retract_layer_change" - || *opt_key == "retract_length" - || *opt_key == "retract_length_toolchange" - || *opt_key == "retract_lift" - || *opt_key == "retract_lift_above" - || *opt_key == "retract_lift_below" - || *opt_key == "retract_restart_extra" - || *opt_key == "retract_restart_extra_toolchange" - || *opt_key == "retract_speed" - || *opt_key == "deretract_speed" - || *opt_key == "slowdown_below_layer_time" - || *opt_key == "standby_temperature_delta" - || *opt_key == "start_gcode" - || *opt_key == "threads" - || *opt_key == "toolchange_gcode" - || *opt_key == "travel_speed" - || *opt_key == "use_firmware_retraction" - || *opt_key == "use_relative_e_distances" - || *opt_key == "wipe" - || *opt_key == "max_volumetric_extrusion_rate_slope_negative" - || *opt_key == "max_volumetric_extrusion_rate_slope_positive") { + opt_key == "complete_objects" + || opt_key == "filament_type" + || opt_key == "first_layer_temperature" + || opt_key == "gcode_flavor" + || opt_key == "single_extruder_multi_material" + || opt_key == "spiral_vase" + || opt_key == "temperature" + || opt_key == "wipe_tower" + || opt_key == "wipe_tower_x" + || opt_key == "wipe_tower_y" + || opt_key == "wipe_tower_width" + || opt_key == "wipe_tower_per_color_wipe" + || opt_key == "z_offset") { + steps.emplace_back(psWipeTower); + } else if (opt_key == "avoid_crossing_perimeters" + || opt_key == "bed_shape" + || opt_key == "bed_temperature" + || opt_key == "bridge_acceleration" + || opt_key == "bridge_fan_speed" + || opt_key == "cooling" + || opt_key == "default_acceleration" + || opt_key == "disable_fan_first_layers" + || opt_key == "duplicate_distance" + || opt_key == "end_gcode" + || opt_key == "extruder_clearance_height" + || opt_key == "extruder_clearance_radius" + || opt_key == "extruder_colour" + || opt_key == "extruder_offset" + || opt_key == "extrusion_axis" + || opt_key == "extrusion_multiplier" + || opt_key == "fan_always_on" + || opt_key == "fan_below_layer_time" + || opt_key == "filament_diameter" + || opt_key == "filament_notes" + || opt_key == "filament_soluble" + || opt_key == "first_layer_acceleration" + || opt_key == "first_layer_bed_temperature" + || opt_key == "first_layer_speed" + || opt_key == "gcode_comments" + || opt_key == "infill_acceleration" + || opt_key == "infill_first" + || opt_key == "layer_gcode" + || opt_key == "min_fan_speed" + || opt_key == "max_fan_speed" + || opt_key == "min_print_speed" + || opt_key == "notes" + || opt_key == "only_retract_when_crossing_perimeters" + || opt_key == "output_filename_format" + || opt_key == "perimeter_acceleration" + || opt_key == "post_process" + || opt_key == "retract_before_travel" + || opt_key == "retract_before_wipe" + || opt_key == "retract_layer_change" + || opt_key == "retract_length" + || opt_key == "retract_length_toolchange" + || opt_key == "retract_lift" + || opt_key == "retract_lift_above" + || opt_key == "retract_lift_below" + || opt_key == "retract_restart_extra" + || opt_key == "retract_restart_extra_toolchange" + || opt_key == "retract_speed" + || opt_key == "deretract_speed" + || opt_key == "slowdown_below_layer_time" + || opt_key == "standby_temperature_delta" + || opt_key == "start_gcode" + || opt_key == "threads" + || opt_key == "toolchange_gcode" + || opt_key == "travel_speed" + || opt_key == "use_firmware_retraction" + || opt_key == "use_relative_e_distances" + || opt_key == "wipe" + || opt_key == "max_volumetric_extrusion_rate_slope_negative" + || opt_key == "max_volumetric_extrusion_rate_slope_positive") { // these options only affect G-code export, so nothing to invalidate - } else if (*opt_key == "first_layer_extrusion_width") { - osteps.insert(posPerimeters); - osteps.insert(posInfill); - osteps.insert(posSupportMaterial); - steps.insert(psSkirt); - steps.insert(psBrim); - steps.insert(psWipeTower); + } else if (opt_key == "first_layer_extrusion_width") { + osteps.emplace_back(posPerimeters); + osteps.emplace_back(posInfill); + osteps.emplace_back(posSupportMaterial); + steps.emplace_back(psSkirt); + steps.emplace_back(psBrim); + steps.emplace_back(psWipeTower); } else { // for legacy, if we can't handle this option let's invalidate all steps return this->invalidate_all_steps(); @@ -219,53 +219,34 @@ Print::invalidate_state_by_config_options(const std::vector } bool invalidated = false; - for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { - if (this->invalidate_step(*step)) invalidated = true; - } - for (std::set::const_iterator ostep = osteps.begin(); ostep != osteps.end(); ++ostep) { - FOREACH_OBJECT(this, object) { - if ((*object)->invalidate_step(*ostep)) invalidated = true; - } - } - + sort_remove_duplicates(steps); + for (PrintStep step : steps) + invalidated |= this->invalidate_step(step); + sort_remove_duplicates(osteps); + for (PrintObjectStep ostep : osteps) + FOREACH_OBJECT(this, object) + invalidated |= (*object)->invalidate_step(ostep); return invalidated; } -bool -Print::invalidate_step(PrintStep step) +bool Print::invalidate_step(PrintStep step) { bool invalidated = this->state.invalidate(step); - - // propagate to dependent steps + // Propagate to dependent steps. if (step == psSkirt) - this->invalidate_step(psBrim); - - return invalidated; -} - -bool Print::invalidate_all_steps() -{ - // make a copy because when invalidating steps the iterators are not working anymore - std::set steps = this->state.started; - - bool invalidated = false; - for (PrintStep step : steps) - if (this->invalidate_step(step)) - invalidated = true; - + invalidated |= this->state.invalidate(psBrim); return invalidated; } // returns true if an object step is done on all objects // and there's at least one object -bool -Print::step_done(PrintObjectStep step) const +bool Print::step_done(PrintObjectStep step) const { - if (this->objects.empty()) return false; - FOREACH_OBJECT(this, object) { - if (!(*object)->state.is_done(step)) + if (this->objects.empty()) + return false; + for (const PrintObject *object : this->objects) + if (!object->state.is_done(step)) return false; - } return true; } @@ -274,15 +255,15 @@ std::vector Print::object_extruders() const { std::vector extruders; - FOREACH_REGION(this, region) { + for (PrintRegion* region : this->regions) { // these checks reflect the same logic used in the GUI for enabling/disabling // extruder selection fields - if ((*region)->config.perimeters.value > 0 || this->config.brim_width.value > 0) - extruders.push_back((*region)->config.perimeter_extruder - 1); - if ((*region)->config.fill_density.value > 0) - extruders.push_back((*region)->config.infill_extruder - 1); - if ((*region)->config.top_solid_layers.value > 0 || (*region)->config.bottom_solid_layers.value > 0) - extruders.push_back((*region)->config.solid_infill_extruder - 1); + if (region->config.perimeters.value > 0 || this->config.brim_width.value > 0) + extruders.push_back(region->config.perimeter_extruder - 1); + if (region->config.fill_density.value > 0) + extruders.push_back(region->config.infill_extruder - 1); + if (region->config.top_solid_layers.value > 0 || region->config.bottom_solid_layers.value > 0) + extruders.push_back(region->config.solid_infill_extruder - 1); } sort_remove_duplicates(extruders); @@ -376,27 +357,24 @@ void Print::add_model_object(ModelObject* model_object, int idx) } } - for (ModelVolumePtrs::const_iterator v_i = model_object->volumes.begin(); v_i != model_object->volumes.end(); ++v_i) { - size_t volume_id = v_i - model_object->volumes.begin(); - ModelVolume* volume = *v_i; + for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) { + ModelVolume* volume = model_object->volumes[volume_id]; // get the config applied to this volume PrintRegionConfig config = this->_region_config_from_model_volume(*volume); // find an existing print region with the same config - int region_id = -1; - for (PrintRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region) { - if (config.equals((*region)->config)) { - region_id = region - this->regions.begin(); + size_t region_id = size_t(-1); + for (size_t i = 0; i < this->regions.size(); ++ i) + if (config.equals(this->regions[i]->config)) { + region_id = i; break; } - } // if no region exists with the same config, create a new one - if (region_id == -1) { - PrintRegion* r = this->add_region(); - r->config.apply(config); - region_id = this->regions.size() - 1; + if (region_id == size_t(-1)) { + region_id = this->regions.size(); + this->add_region()->config.apply(config); } // assign volume to region diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 01180863f..1ac9b15f8 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -24,27 +24,44 @@ class ModelObject; // Print step IDs for keeping track of the print state. enum PrintStep { - psSkirt, psBrim, psWipeTower + psSkirt, psBrim, psWipeTower, psCount, }; enum PrintObjectStep { posSlice, posPerimeters, posPrepareInfill, - posInfill, posSupportMaterial, + posInfill, posSupportMaterial, posCount, }; // To be instantiated over PrintStep or PrintObjectStep enums. -template +template class PrintState { public: - std::set started, done; + PrintState() { memset(state, 0, sizeof(state)); } + + enum State { + INVALID, + STARTED, + DONE, + }; + State state[COUNT]; - bool is_started(StepType step) const { return this->started.find(step) != this->started.end(); } - bool is_done(StepType step) const { return this->done.find(step) != this->done.end(); } - void set_started(StepType step) { this->started.insert(step); } - void set_done(StepType step) { this->done.insert(step); } + bool is_started(StepType step) const { return this->state[step] == STARTED; } + bool is_done(StepType step) const { return this->state[step] == DONE; } + void set_started(StepType step) { this->state[step] = STARTED; } + void set_done(StepType step) { this->state[step] = DONE; } bool invalidate(StepType step) { - bool invalidated = this->started.erase(step) > 0; - this->done.erase(step); + bool invalidated = this->state[step] != INVALID; + this->state[step] = INVALID; + return invalidated; + } + bool invalidate_all() { + bool invalidated = false; + for (size_t i = 0; i < COUNT; ++ i) + if (this->state[i] != INVALID) { + invalidated = true; + break; + } + memset(state, 0, sizeof(state)); return invalidated; } }; @@ -112,7 +129,7 @@ public: LayerPtrs layers; SupportLayerPtrs support_layers; - PrintState state; + PrintState state; Print* print() { return this->_print; } const Print* print() const { return this->_print; } @@ -152,7 +169,7 @@ public: // methods for handling state bool invalidate_state_by_config_options(const std::vector &opt_keys); bool invalidate_step(PrintObjectStep step); - bool invalidate_all_steps(); + bool invalidate_all_steps() { return this->state.invalidate_all(); } // To be used over the layer_height_profile of both the PrintObject and ModelObject // to initialize the height profile with the height ranges. @@ -211,7 +228,7 @@ public: // TODO: status_cb double total_used_filament, total_extruded_volume, total_cost, total_weight; std::map filament_stats; - PrintState state; + PrintState state; // ordered collections of extrusion paths to build skirt loops and brim ExtrusionEntityCollection skirt, brim; @@ -236,7 +253,7 @@ public: // methods for handling state bool invalidate_state_by_config_options(const std::vector &opt_keys); bool invalidate_step(PrintStep step); - bool invalidate_all_steps(); + bool invalidate_all_steps() { return this->state.invalidate_all(); } bool step_done(PrintObjectStep step) const; void add_model_object(ModelObject* model_object, int idx = -1); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 5eb08a833..b716846aa 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -74,15 +74,7 @@ PrintObject::delete_last_copy() return this->set_copies(points); } -bool -PrintObject::delete_all_copies() -{ - Points points; - return this->set_copies(points); -} - -bool -PrintObject::set_copies(const Points &points) +bool PrintObject::set_copies(const Points &points) { this->_copies = points; @@ -94,16 +86,12 @@ PrintObject::set_copies(const Points &points) std::vector ordered_copies; Slic3r::Geometry::chained_path(points, ordered_copies); - for (std::vector::const_iterator it = ordered_copies.begin(); it != ordered_copies.end(); ++it) { - Point copy = points[*it]; + for (Point copy : ordered_copies) { copy.translate(this->_copies_shift); this->_shifted_copies.push_back(copy); } - bool invalidated = false; - if (this->_print->invalidate_step(psSkirt)) invalidated = true; - if (this->_print->invalidate_step(psBrim)) invalidated = true; - return invalidated; + return this->_print->invalidate_step(psSkirt) || this->_print->invalidate_step(psBrim); } bool @@ -116,27 +104,6 @@ PrintObject::reload_model_instances() return this->set_copies(copies); } -void -PrintObject::add_region_volume(int region_id, int volume_id) -{ - region_volumes[region_id].push_back(volume_id); -} - -/* This is the *total* layer count (including support layers) - this value is not supposed to be compared with Layer::id - since they have different semantics */ -size_t -PrintObject::total_layer_count() const -{ - return this->layer_count() + this->support_layer_count(); -} - -size_t -PrintObject::layer_count() const -{ - return this->layers.size(); -} - void PrintObject::clear_layers() { @@ -164,12 +131,6 @@ PrintObject::delete_layer(int idx) this->layers.erase(i); } -size_t -PrintObject::support_layer_count() const -{ - return this->support_layers.size(); -} - void PrintObject::clear_support_layers() { @@ -181,12 +142,6 @@ PrintObject::clear_support_layers() this->support_layers.clear(); } -SupportLayer* -PrintObject::get_support_layer(int idx) -{ - return this->support_layers.at(idx); -} - SupportLayer* PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z) { @@ -203,93 +158,92 @@ PrintObject::delete_support_layer(int idx) this->support_layers.erase(i); } -bool -PrintObject::invalidate_state_by_config_options(const std::vector &opt_keys) +bool PrintObject::invalidate_state_by_config_options(const std::vector &opt_keys) { - std::set steps; + std::vector steps; // this method only accepts PrintObjectConfig and PrintRegionConfig option keys - for (std::vector::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) { - if (*opt_key == "perimeters" - || *opt_key == "extra_perimeters" - || *opt_key == "gap_fill_speed" - || *opt_key == "overhangs" - || *opt_key == "first_layer_extrusion_width" - || *opt_key == "perimeter_extrusion_width" - || *opt_key == "infill_overlap" - || *opt_key == "thin_walls" - || *opt_key == "external_perimeters_first") { - steps.insert(posPerimeters); - } else if (*opt_key == "layer_height" - || *opt_key == "first_layer_height" - || *opt_key == "raft_layers") { - steps.insert(posSlice); + for (const t_config_option_key &opt_key : opt_keys) { + if (opt_key == "perimeters" + || opt_key == "extra_perimeters" + || opt_key == "gap_fill_speed" + || opt_key == "overhangs" + || opt_key == "first_layer_extrusion_width" + || opt_key == "perimeter_extrusion_width" + || opt_key == "infill_overlap" + || opt_key == "thin_walls" + || opt_key == "external_perimeters_first") { + steps.emplace_back(posPerimeters); + } else if (opt_key == "layer_height" + || opt_key == "first_layer_height" + || opt_key == "raft_layers") { + steps.emplace_back(posSlice); this->reset_layer_height_profile(); } - else if (*opt_key == "clip_multipart_objects" - || *opt_key == "xy_size_compensation") { - steps.insert(posSlice); - } else if (*opt_key == "support_material" - || *opt_key == "support_material_angle" - || *opt_key == "support_material_extruder" - || *opt_key == "support_material_extrusion_width" - || *opt_key == "support_material_interface_layers" - || *opt_key == "support_material_interface_contact_loops" - || *opt_key == "support_material_interface_extruder" - || *opt_key == "support_material_interface_spacing" - || *opt_key == "support_material_interface_speed" - || *opt_key == "support_material_buildplate_only" - || *opt_key == "support_material_pattern" - || *opt_key == "support_material_xy_spacing" - || *opt_key == "support_material_spacing" - || *opt_key == "support_material_synchronize_layers" - || *opt_key == "support_material_threshold" - || *opt_key == "support_material_with_sheath" - || *opt_key == "dont_support_bridges" - || *opt_key == "first_layer_extrusion_width") { - steps.insert(posSupportMaterial); - } else if (*opt_key == "interface_shells" - || *opt_key == "infill_only_where_needed" - || *opt_key == "infill_every_layers" - || *opt_key == "solid_infill_every_layers" - || *opt_key == "bottom_solid_layers" - || *opt_key == "top_solid_layers" - || *opt_key == "solid_infill_below_area" - || *opt_key == "infill_extruder" - || *opt_key == "solid_infill_extruder" - || *opt_key == "infill_extrusion_width" - || *opt_key == "ensure_vertical_shell_thickness") { - steps.insert(posPrepareInfill); - } else if (*opt_key == "external_fill_pattern" - || *opt_key == "external_fill_link_max_length" - || *opt_key == "fill_angle" - || *opt_key == "fill_pattern" - || *opt_key == "fill_link_max_length" - || *opt_key == "top_infill_extrusion_width" - || *opt_key == "first_layer_extrusion_width") { - steps.insert(posInfill); - } else if (*opt_key == "fill_density" - || *opt_key == "solid_infill_extrusion_width") { - steps.insert(posPerimeters); - steps.insert(posPrepareInfill); - } else if (*opt_key == "external_perimeter_extrusion_width" - || *opt_key == "perimeter_extruder") { - steps.insert(posPerimeters); - steps.insert(posSupportMaterial); - } else if (*opt_key == "bridge_flow_ratio") { - steps.insert(posPerimeters); - steps.insert(posInfill); - } else if (*opt_key == "seam_position" - || *opt_key == "seam_preferred_direction" - || *opt_key == "seam_preferred_direction_jitter" - || *opt_key == "support_material_speed" - || *opt_key == "bridge_speed" - || *opt_key == "external_perimeter_speed" - || *opt_key == "infill_speed" - || *opt_key == "perimeter_speed" - || *opt_key == "small_perimeter_speed" - || *opt_key == "solid_infill_speed" - || *opt_key == "top_solid_infill_speed") { + else if (opt_key == "clip_multipart_objects" + || opt_key == "xy_size_compensation") { + steps.emplace_back(posSlice); + } else if (opt_key == "support_material" + || opt_key == "support_material_angle" + || opt_key == "support_material_extruder" + || opt_key == "support_material_extrusion_width" + || opt_key == "support_material_interface_layers" + || opt_key == "support_material_interface_contact_loops" + || opt_key == "support_material_interface_extruder" + || opt_key == "support_material_interface_spacing" + || opt_key == "support_material_interface_speed" + || opt_key == "support_material_buildplate_only" + || opt_key == "support_material_pattern" + || opt_key == "support_material_xy_spacing" + || opt_key == "support_material_spacing" + || opt_key == "support_material_synchronize_layers" + || opt_key == "support_material_threshold" + || opt_key == "support_material_with_sheath" + || opt_key == "dont_support_bridges" + || opt_key == "first_layer_extrusion_width") { + steps.emplace_back(posSupportMaterial); + } else if (opt_key == "interface_shells" + || opt_key == "infill_only_where_needed" + || opt_key == "infill_every_layers" + || opt_key == "solid_infill_every_layers" + || opt_key == "bottom_solid_layers" + || opt_key == "top_solid_layers" + || opt_key == "solid_infill_below_area" + || opt_key == "infill_extruder" + || opt_key == "solid_infill_extruder" + || opt_key == "infill_extrusion_width" + || opt_key == "ensure_vertical_shell_thickness") { + steps.emplace_back(posPrepareInfill); + } else if (opt_key == "external_fill_pattern" + || opt_key == "external_fill_link_max_length" + || opt_key == "fill_angle" + || opt_key == "fill_pattern" + || opt_key == "fill_link_max_length" + || opt_key == "top_infill_extrusion_width" + || opt_key == "first_layer_extrusion_width") { + steps.emplace_back(posInfill); + } else if (opt_key == "fill_density" + || opt_key == "solid_infill_extrusion_width") { + steps.emplace_back(posPerimeters); + steps.emplace_back(posPrepareInfill); + } else if (opt_key == "external_perimeter_extrusion_width" + || opt_key == "perimeter_extruder") { + steps.emplace_back(posPerimeters); + steps.emplace_back(posSupportMaterial); + } else if (opt_key == "bridge_flow_ratio") { + steps.emplace_back(posPerimeters); + steps.emplace_back(posInfill); + } else if (opt_key == "seam_position" + || opt_key == "seam_preferred_direction" + || opt_key == "seam_preferred_direction_jitter" + || opt_key == "support_material_speed" + || opt_key == "bridge_speed" + || opt_key == "external_perimeter_speed" + || opt_key == "infill_speed" + || opt_key == "perimeter_speed" + || opt_key == "small_perimeter_speed" + || opt_key == "solid_infill_speed" + || opt_key == "top_solid_infill_speed") { // these options only affect G-code export, so nothing to invalidate } else { // for legacy, if we can't handle this option let's invalidate all steps @@ -299,58 +253,47 @@ PrintObject::invalidate_state_by_config_options(const std::vector::const_iterator step = steps.begin(); step != steps.end(); ++step) { - if (this->invalidate_step(*step)) invalidated = true; - } - + sort_remove_duplicates(steps); + for (PrintObjectStep step : steps) + invalidated |= this->invalidate_step(step); return invalidated; } -bool -PrintObject::invalidate_step(PrintObjectStep step) +bool PrintObject::invalidate_step(PrintObjectStep step) { bool invalidated = 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); - this->_print->invalidate_step(psWipeTower); + invalidated |= + this->invalidate_step(posPrepareInfill) || + this->_print->invalidate_step(psSkirt) || + this->_print->invalidate_step(psBrim) || + this->_print->invalidate_step(psWipeTower); } else if (step == posPrepareInfill) { - this->invalidate_step(posInfill); + invalidated |= + this->invalidate_step(posInfill); } else if (step == posInfill) { - this->_print->invalidate_step(psSkirt); - this->_print->invalidate_step(psBrim); - this->_print->invalidate_step(psWipeTower); + invalidated |= + this->_print->invalidate_step(psSkirt) || + this->_print->invalidate_step(psBrim) || + this->_print->invalidate_step(psWipeTower); } else if (step == posSlice) { - this->invalidate_step(posPerimeters); - this->invalidate_step(posSupportMaterial); - this->_print->invalidate_step(psWipeTower); + invalidated |= + this->invalidate_step(posPerimeters) || + this->invalidate_step(posSupportMaterial) || + this->_print->invalidate_step(psWipeTower); } else if (step == posSupportMaterial) { - this->_print->invalidate_step(psSkirt); - this->_print->invalidate_step(psBrim); - this->_print->invalidate_step(psWipeTower); + invalidated |= + this->_print->invalidate_step(psSkirt) || + this->_print->invalidate_step(psBrim) || + this->_print->invalidate_step(psWipeTower); } - + return invalidated; } -bool -PrintObject::invalidate_all_steps() -{ - // make a copy because when invalidating steps the iterators are not working anymore - std::set steps = this->state.started; - - bool invalidated = false; - for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { - if (this->invalidate_step(*step)) invalidated = true; - } - return invalidated; -} - -bool -PrintObject::has_support_material() const +bool PrintObject::has_support_material() const { return this->config.support_material || this->config.raft_layers > 0