diff options
Diffstat (limited to 'xs/src/libslic3r/Print.cpp')
-rw-r--r-- | xs/src/libslic3r/Print.cpp | 401 |
1 files changed, 203 insertions, 198 deletions
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index d67fe5884..e8a010a79 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -20,24 +20,27 @@ template class PrintState<PrintObjectStep, posCount>; void Print::clear_objects() { - for (int i = int(this->objects.size())-1; i >= 0; --i) + tbb::mutex::scoped_lock lock(m_mutex); + for (int i = int(m_objects.size())-1; i >= 0; --i) this->delete_object(i); - for (PrintRegion *region : this->regions) + for (PrintRegion *region : m_regions) delete region; - this->regions.clear(); + m_regions.clear(); } void Print::delete_object(size_t idx) { + tbb::mutex::scoped_lock lock(m_mutex); // destroy object and remove it from our container - delete this->objects[idx]; - this->objects.erase(this->objects.begin() + idx); + delete m_objects[idx]; + m_objects.erase(m_objects.begin() + idx); this->invalidate_all_steps(); // TODO: purge unused regions } void Print::reload_object(size_t /* idx */) { + tbb::mutex::scoped_lock lock(m_mutex); /* TODO: this method should check whether the per-object config and per-material configs have changed in such a way that regions need to be rearranged or we can just apply the diff and invalidate something. Same logic as apply_config() @@ -46,8 +49,8 @@ void Print::reload_object(size_t /* idx */) // collect all current model objects ModelObjectPtrs model_objects; - model_objects.reserve(this->objects.size()); - for (PrintObject *object : this->objects) + model_objects.reserve(m_objects.size()); + for (PrintObject *object : m_objects) model_objects.push_back(object->model_object()); // remove our print objects this->clear_objects(); @@ -63,15 +66,21 @@ void Print::reload_object(size_t /* idx */) bool Print::reload_model_instances() { bool invalidated = false; - for (PrintObject *object : this->objects) + for (PrintObject *object : m_objects) invalidated |= object->reload_model_instances(); return invalidated; } PrintRegion* Print::add_region() { - regions.push_back(new PrintRegion(this)); - return regions.back(); + m_regions.emplace_back(new PrintRegion(this)); + return m_regions.back(); +} + +PrintRegion* Print::add_region(const PrintRegionConfig &config) +{ + m_regions.emplace_back(new PrintRegion(this, config)); + return m_regions.back(); } // Called by Print::apply_config(). @@ -224,18 +233,18 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option invalidated |= this->invalidate_step(step); sort_remove_duplicates(osteps); for (PrintObjectStep ostep : osteps) - for (PrintObject *object : this->objects) + for (PrintObject *object : m_objects) invalidated |= object->invalidate_step(ostep); return invalidated; } bool Print::invalidate_step(PrintStep step) { - bool invalidated = m_state.invalidate(step); + bool invalidated = m_state.invalidate(step, m_mutex, m_cancel_callback); // Propagate to dependent steps. //FIXME Why should skirt invalidate brim? Shouldn't it be vice versa? if (step == psSkirt) - invalidated |= m_state.invalidate(psBrim); + invalidated |= m_state.invalidate(psBrim, m_mutex, m_cancel_callback); return invalidated; } @@ -243,9 +252,9 @@ bool Print::invalidate_step(PrintStep step) // and there's at least one object bool Print::is_step_done(PrintObjectStep step) const { - if (this->objects.empty()) + if (m_objects.empty()) return false; - for (const PrintObject *object : this->objects) + for (const PrintObject *object : m_objects) if (!object->m_state.is_done(step)) return false; return true; @@ -256,15 +265,15 @@ std::vector<unsigned int> Print::object_extruders() const { std::vector<unsigned int> extruders; - for (PrintRegion* region : this->regions) { + for (PrintRegion* region : m_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 || m_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); @@ -277,16 +286,16 @@ std::vector<unsigned int> Print::support_material_extruders() const std::vector<unsigned int> extruders; bool support_uses_current_extruder = false; - for (PrintObject *object : this->objects) { + for (PrintObject *object : m_objects) { if (object->has_support_material()) { - if (object->config.support_material_extruder == 0) + if (object->config().support_material_extruder == 0) support_uses_current_extruder = true; else - extruders.push_back(object->config.support_material_extruder - 1); - if (object->config.support_material_interface_extruder == 0) + extruders.push_back(object->config().support_material_extruder - 1); + if (object->config().support_material_interface_extruder == 0) support_uses_current_extruder = true; else - extruders.push_back(object->config.support_material_interface_extruder - 1); + extruders.push_back(object->config().support_material_interface_extruder - 1); } } @@ -309,10 +318,10 @@ std::vector<unsigned int> Print::extruders() const void Print::_simplify_slices(double distance) { - for (PrintObject *object : this->objects) { - for (Layer *layer : object->layers) { + for (PrintObject *object : m_objects) { + for (Layer *layer : object->m_layers) { layer->slices.simplify(distance); - for (LayerRegion *layerm : layer->regions) + for (LayerRegion *layerm : layer->regions()) layerm->slices.simplify(distance); } } @@ -322,7 +331,7 @@ double Print::max_allowed_layer_height() const { double nozzle_diameter_max = 0.; for (unsigned int extruder_id : this->extruders()) - nozzle_diameter_max = std::max(nozzle_diameter_max, this->config.nozzle_diameter.get_at(extruder_id)); + nozzle_diameter_max = std::max(nozzle_diameter_max, m_config.nozzle_diameter.get_at(extruder_id)); return nozzle_diameter_max; } @@ -333,10 +342,10 @@ void Print::add_model_object(ModelObject* model_object, int idx) // Initialize a new print object and store it at the given position. PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box()); if (idx != -1) { - delete this->objects[idx]; - this->objects[idx] = object; + delete m_objects[idx]; + m_objects[idx] = object; } else - this->objects.emplace_back(object); + m_objects.emplace_back(object); // Invalidate all print steps. this->invalidate_all_steps(); @@ -345,37 +354,42 @@ void Print::add_model_object(ModelObject* model_object, int idx) PrintRegionConfig config = this->_region_config_from_model_volume(*model_object->volumes[volume_id]); // Find an existing print region with the same config. size_t region_id = size_t(-1); - for (size_t i = 0; i < this->regions.size(); ++ i) - if (config.equals(this->regions[i]->config)) { + for (size_t i = 0; i < m_regions.size(); ++ i) + if (config.equals(m_regions[i]->config())) { region_id = i; break; } // If no region exists with the same config, create a new one. if (region_id == size_t(-1)) { - region_id = this->regions.size(); - this->add_region()->config.apply(config); + region_id = this->regions().size(); + this->add_region(config); } // Assign volume to a region. object->add_region_volume(region_id, volume_id); } // Apply config to print object. - object->config.apply(this->default_object_config); - normalize_and_apply_config(object->config, model_object->config); + object->config_apply(this->default_object_config()); + { + //normalize_and_apply_config(object->config(), model_object->config); + DynamicPrintConfig src_normalized(model_object->config); + src_normalized.normalize(); + object->config_apply(src_normalized, true); + } // update placeholders { // get the first input file name std::string input_file; std::vector<std::string> v_scale; - for (const PrintObject *object : this->objects) { + for (const PrintObject *object : m_objects) { const ModelObject &mobj = *object->model_object(); v_scale.push_back(boost::lexical_cast<std::string>(mobj.instances[0]->scaling_factor*100) + "%"); if (input_file.empty()) input_file = mobj.input_file; } - PlaceholderParser &pp = this->placeholder_parser; + PlaceholderParser &pp = m_placeholder_parser; pp.set("scale", v_scale); if (! input_file.empty()) { // get basename with and without suffix @@ -393,19 +407,19 @@ bool Print::apply_config(DynamicPrintConfig config) config.normalize(); // apply variables to placeholder parser - this->placeholder_parser.apply_config(config); + m_placeholder_parser.apply_config(config); // handle changes to print config - t_config_option_keys print_diff = this->config.diff(config); - this->config.apply_only(config, print_diff, true); + t_config_option_keys print_diff = m_config.diff(config); + m_config.apply_only(config, print_diff, true); bool invalidated = this->invalidate_state_by_config_options(print_diff); // handle changes to object config defaults - this->default_object_config.apply(config, true); - for (PrintObject *object : this->objects) { + m_default_object_config.apply(config, true); + for (PrintObject *object : m_objects) { // we don't assume that config contains a full ObjectConfig, // so we base it on the current print-wise default - PrintObjectConfig new_config = this->default_object_config; + PrintObjectConfig new_config = this->default_object_config(); // we override the new config with object-specific options normalize_and_apply_config(new_config, object->model_object()->config); // Force a refresh of a variable layer height profile at the PrintObject if it is not valid. @@ -417,13 +431,13 @@ bool Print::apply_config(DynamicPrintConfig config) invalidated = true; } // check whether the new config is different from the current one - t_config_option_keys diff = object->config.diff(new_config); - object->config.apply_only(new_config, diff, true); + t_config_option_keys diff = object->config().diff(new_config); + object->config_apply_only(new_config, diff, true); invalidated |= object->invalidate_state_by_config_options(diff); } // handle changes to regions config defaults - this->default_region_config.apply(config, true); + m_default_region_config.apply(config, true); // All regions now have distinct settings. // Check whether applying the new region config defaults we'd get different regions. @@ -432,11 +446,11 @@ bool Print::apply_config(DynamicPrintConfig config) // Collect the already visited region configs into other_region_configs, // so one may check for duplicates. std::vector<PrintRegionConfig> other_region_configs; - for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id) { - PrintRegion ®ion = *this->regions[region_id]; + for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) { + PrintRegion ®ion = *m_regions[region_id]; PrintRegionConfig this_region_config; bool this_region_config_set = false; - for (PrintObject *object : this->objects) { + for (PrintObject *object : m_objects) { if (region_id < object->region_volumes.size()) { for (int volume_id : object->region_volumes[region_id]) { const ModelVolume &volume = *object->model_object()->volumes[volume_id]; @@ -466,10 +480,10 @@ bool Print::apply_config(DynamicPrintConfig config) } } if (this_region_config_set) { - t_config_option_keys diff = region.config.diff(this_region_config); + t_config_option_keys diff = region.config().diff(this_region_config); if (! diff.empty()) { - region.config.apply_only(this_region_config, diff); - for (PrintObject *object : this->objects) + region.config_apply_only(this_region_config, diff, false); + for (PrintObject *object : m_objects) if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty()) invalidated |= object->invalidate_state_by_config_options(diff); } @@ -484,8 +498,8 @@ exit_for_rearrange_regions: // The current subdivision of regions does not make sense anymore. // We need to remove all objects and re-add them. ModelObjectPtrs model_objects; - model_objects.reserve(this->objects.size()); - for (PrintObject *object : this->objects) + model_objects.reserve(m_objects.size()); + for (PrintObject *object : m_objects) model_objects.push_back(object->model_object()); this->clear_objects(); for (ModelObject *mo : model_objects) @@ -494,7 +508,7 @@ exit_for_rearrange_regions: } // Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads. - for (PrintObject *object : this->objects) + for (PrintObject *object : m_objects) if (! object->layer_height_profile_valid) object->update_layer_height_profile(); @@ -503,32 +517,32 @@ exit_for_rearrange_regions: bool Print::has_infinite_skirt() const { - return (this->config.skirt_height == -1 && this->config.skirts > 0) - || (this->config.ooze_prevention && this->extruders().size() > 1); + return (m_config.skirt_height == -1 && m_config.skirts > 0) + || (m_config.ooze_prevention && this->extruders().size() > 1); } bool Print::has_skirt() const { - return (this->config.skirt_height > 0 && this->config.skirts > 0) + return (m_config.skirt_height > 0 && m_config.skirts > 0) || this->has_infinite_skirt(); } std::string Print::validate() const { - BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values)); - BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height)); + BoundingBox bed_box_2D = get_extents(Polygon::new_scale(m_config.bed_shape.values)); + BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), m_config.max_print_height)); // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. print_volume.min.z = -1e10; - for (PrintObject *po : this->objects) { + for (PrintObject *po : m_objects) { if (! print_volume.contains(po->model_object()->tight_bounding_box(false))) return "Some objects are outside of the print volume."; } - if (this->config.complete_objects) { + if (m_config.complete_objects) { // Check horizontal clearance. { Polygons convex_hulls_other; - for (PrintObject *object : this->objects) { + for (PrintObject *object : m_objects) { // Get convex hull of all meshes assigned to this print object. Polygon convex_hull; { @@ -542,7 +556,7 @@ std::string Print::validate() const // Apply the same transformations we apply to the actual meshes when slicing them. object->model_object()->instances.front()->transform_polygon(&convex_hull); // Grow convex hull with the clearance margin. - convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); + convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); // Now we check that no instance of convex_hull intersects any of the previously checked object instances. for (const Point © : object->_shifted_copies) { Polygon p = convex_hull; @@ -556,47 +570,47 @@ std::string Print::validate() const // Check vertical clearance. { std::vector<coord_t> object_height; - for (const PrintObject *object : this->objects) + for (const PrintObject *object : m_objects) object_height.insert(object_height.end(), object->copies().size(), object->size.z); std::sort(object_height.begin(), object_height.end()); // Ignore the tallest *copy* (this is why we repeat height for all of them): // it will be printed as last one so its height doesn't matter. object_height.pop_back(); - if (! object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value)) + if (! object_height.empty() && object_height.back() > scale_(m_config.extruder_clearance_height.value)) return "Some objects are too tall and cannot be printed without extruder collisions."; } - } // end if (this->config.complete_objects) + } // end if (m_config.complete_objects) - if (this->config.spiral_vase) { + if (m_config.spiral_vase) { size_t total_copies_count = 0; - for (const PrintObject *object : this->objects) + for (const PrintObject *object : m_objects) total_copies_count += object->copies().size(); // #4043 - if (total_copies_count > 1 && ! this->config.complete_objects.value) + if (total_copies_count > 1 && ! m_config.complete_objects.value) return "The Spiral Vase option can only be used when printing a single object."; - if (this->regions.size() > 1) + if (m_regions.size() > 1) return "The Spiral Vase option can only be used when printing single material objects."; } - if (this->has_wipe_tower() && ! this->objects.empty()) { + if (this->has_wipe_tower() && ! m_objects.empty()) { #if 0 - for (auto dmr : this->config.nozzle_diameter.values) + for (auto dmr : m_config.nozzle_diameter.values) if (std::abs(dmr - 0.4) > EPSILON) return "The Wipe Tower is currently only supported for the 0.4mm nozzle diameter."; #endif - if (this->config.gcode_flavor != gcfRepRap && this->config.gcode_flavor != gcfMarlin) + if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfMarlin) return "The Wipe Tower is currently only supported for the Marlin and RepRap/Sprinter G-code flavors."; - if (! this->config.use_relative_e_distances) + if (! m_config.use_relative_e_distances) return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."; - SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters(); - for (PrintObject *object : this->objects) { + SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters(); + for (PrintObject *object : m_objects) { SlicingParameters slicing_params = object->slicing_parameters(); if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON || std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON) return "The Wipe Tower is only supported for multiple objects if they have equal layer heigths"; if (slicing_params.raft_layers() != slicing_params0.raft_layers()) return "The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers"; - if (object->config.support_material_contact_distance != this->objects.front()->config.support_material_contact_distance) + if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance) return "The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance"; if (! equal_layering(slicing_params, slicing_params0)) return "The Wipe Tower is only supported for multiple objects if they are sliced equally."; @@ -605,7 +619,7 @@ std::string Print::validate() const object->layer_height_profile_valid = was_layer_height_profile_valid; for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON && - std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON) + std::abs(object->layer_height_profile[i] - object->config().layer_height) > EPSILON) return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed."; } } @@ -618,12 +632,12 @@ std::string Print::validate() const std::vector<double> nozzle_diameters; for (unsigned int extruder_id : extruders) - nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id)); + nozzle_diameters.push_back(m_config.nozzle_diameter.get_at(extruder_id)); double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end()); - for (PrintObject *object : this->objects) { - if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) && - (object->config.raft_layers > 0 || object->config.support_material.value)) { + for (PrintObject *object : m_objects) { + if ((object->config().support_material_extruder == -1 || object->config().support_material_interface_extruder == -1) && + (object->config().raft_layers > 0 || object->config().support_material.value)) { // The object has some form of support and either support_material_extruder or support_material_interface_extruder // will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles // are of the same diameter. @@ -634,16 +648,16 @@ std::string Print::validate() const } // validate first_layer_height - double first_layer_height = object->config.get_abs_value("first_layer_height"); + double first_layer_height = object->config().get_abs_value("first_layer_height"); double first_layer_min_nozzle_diameter; - if (object->config.raft_layers > 0) { + if (object->config().raft_layers > 0) { // if we have raft layers, only support material extruder is used on first layer - size_t first_layer_extruder = object->config.raft_layers == 1 - ? object->config.support_material_interface_extruder-1 - : object->config.support_material_extruder-1; + size_t first_layer_extruder = object->config().raft_layers == 1 + ? object->config().support_material_interface_extruder-1 + : object->config().support_material_extruder-1; first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ? min_nozzle_diameter : - this->config.nozzle_diameter.get_at(first_layer_extruder); + m_config.nozzle_diameter.get_at(first_layer_extruder); } else { // if we don't have raft layers, any nozzle diameter is potentially used in first layer first_layer_min_nozzle_diameter = min_nozzle_diameter; @@ -652,7 +666,7 @@ std::string Print::validate() const return "First layer height can't be greater than nozzle diameter"; // validate layer_height - if (object->config.layer_height.value > min_nozzle_diameter) + if (object->config().layer_height.value > min_nozzle_diameter) return "Layer height can't be greater than nozzle diameter"; } } @@ -665,7 +679,7 @@ std::string Print::validate() const BoundingBox Print::bounding_box() const { BoundingBox bb; - for (const PrintObject *object : this->objects) + for (const PrintObject *object : m_objects) for (Point copy : object->_shifted_copies) { bb.merge(copy); copy.translate(object->size); @@ -683,7 +697,7 @@ BoundingBox Print::total_bounding_box() const BoundingBox bb = this->bounding_box(); // we need to offset the objects bounding box by at least half the perimeters extrusion width - Flow perimeter_flow = this->objects.front()->get_layer(0)->get_region(0)->flow(frPerimeter); + Flow perimeter_flow = m_objects.front()->get_layer(0)->get_region(0)->flow(frPerimeter); double extra = perimeter_flow.width/2; // consider support material @@ -692,18 +706,18 @@ BoundingBox Print::total_bounding_box() const } // consider brim and skirt - if (this->config.brim_width.value > 0) { + if (m_config.brim_width.value > 0) { Flow brim_flow = this->brim_flow(); - extra = std::max(extra, this->config.brim_width.value + brim_flow.width/2); + extra = std::max(extra, m_config.brim_width.value + brim_flow.width/2); } if (this->has_skirt()) { - int skirts = this->config.skirts.value; + int skirts = m_config.skirts.value; if (skirts == 0 && this->has_infinite_skirt()) skirts = 1; Flow skirt_flow = this->skirt_flow(); extra = std::max( extra, - this->config.brim_width.value - + this->config.skirt_distance.value + m_config.brim_width.value + + m_config.skirt_distance.value + skirts * skirt_flow.spacing() + skirt_flow.width/2 ); @@ -717,17 +731,17 @@ BoundingBox Print::total_bounding_box() const double Print::skirt_first_layer_height() const { - if (this->objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects"); - return this->objects.front()->config.get_abs_value("first_layer_height"); + if (m_objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects"); + return m_objects.front()->config().get_abs_value("first_layer_height"); } Flow Print::brim_flow() const { - ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width; + ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width; if (width.value == 0) - width = this->regions.front()->config.perimeter_extrusion_width; + width = m_regions.front()->config().perimeter_extrusion_width; if (width.value == 0) - width = this->objects.front()->config.extrusion_width; + width = m_objects.front()->config().extrusion_width; /* We currently use a random region's perimeter extruder. While this works for most cases, we should probably consider all of the perimeter @@ -737,7 +751,7 @@ Flow Print::brim_flow() const return Flow::new_from_config_width( frPerimeter, width, - this->config.nozzle_diameter.get_at(this->regions.front()->config.perimeter_extruder-1), + m_config.nozzle_diameter.get_at(m_regions.front()->config().perimeter_extruder-1), this->skirt_first_layer_height(), 0 ); @@ -745,11 +759,11 @@ Flow Print::brim_flow() const Flow Print::skirt_flow() const { - ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width; + ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width; if (width.value == 0) - width = this->regions.front()->config.perimeter_extrusion_width; + width = m_regions.front()->config().perimeter_extrusion_width; if (width.value == 0) - width = this->objects.front()->config.extrusion_width; + width = m_objects.front()->config().extrusion_width; /* We currently use a random object's support material extruder. While this works for most cases, we should probably consider all of the support material @@ -759,7 +773,7 @@ Flow Print::skirt_flow() const return Flow::new_from_config_width( frPerimeter, width, - this->config.nozzle_diameter.get_at(this->objects.front()->config.support_material_extruder-1), + m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1), this->skirt_first_layer_height(), 0 ); @@ -767,7 +781,7 @@ Flow Print::skirt_flow() const PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume) { - PrintRegionConfig config = this->default_region_config; + PrintRegionConfig config = this->default_region_config(); normalize_and_apply_config(config, volume.get_object()->config); normalize_and_apply_config(config, volume.config); if (! volume.material_id().empty()) @@ -777,7 +791,7 @@ PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &vol bool Print::has_support_material() const { - for (const PrintObject *object : this->objects) + for (const PrintObject *object : m_objects) if (object->has_support_material()) return true; return false; @@ -791,7 +805,7 @@ void Print::auto_assign_extruders(ModelObject* model_object) const if (model_object->volumes.size() < 2) return; -// size_t extruders = this->config.nozzle_diameter.values.size(); +// size_t extruders = m_config.nozzle_diameter.values.size(); for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) { ModelVolume *volume = model_object->volumes[volume_id]; //FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned. @@ -804,44 +818,44 @@ void Print::auto_assign_extruders(ModelObject* model_object) const void Print::process() { BOOST_LOG_TRIVIAL(info) << "Staring the slicing process."; - for (PrintObject *obj : this->objects) + for (PrintObject *obj : m_objects) obj->make_perimeters(); this->throw_if_canceled(); this->set_status(70, "Infilling layers"); - for (PrintObject *obj : this->objects) + for (PrintObject *obj : m_objects) obj->infill(); this->throw_if_canceled(); - for (PrintObject *obj : this->objects) + for (PrintObject *obj : m_objects) obj->generate_support_material(); this->throw_if_canceled(); if (! m_state.is_done(psSkirt)) { this->set_started(psSkirt); - this->skirt.clear(); + m_skirt.clear(); if (this->has_skirt()) { this->set_status(88, "Generating skirt"); this->_make_skirt(); } - m_state.set_done(psSkirt); + this->set_done(psSkirt); } this->throw_if_canceled(); if (! m_state.is_done(psBrim)) { this->set_started(psBrim); - this->brim.clear(); - if (this->config.brim_width > 0) { + m_brim.clear(); + if (m_config.brim_width > 0) { this->set_status(88, "Generating brim"); this->_make_brim(); } - m_state.set_done(psBrim); + this->set_done(psBrim); } this->throw_if_canceled(); if (! m_state.is_done(psWipeTower)) { this->set_started(psWipeTower); - this->_clear_wipe_tower(); + m_wipe_tower_data.clear(); if (this->has_wipe_tower()) { //this->set_status(95, "Generating wipe tower"); this->_make_wipe_tower(); } - m_state.set_done(psWipeTower); + this->set_done(psWipeTower); } BOOST_LOG_TRIVIAL(info) << "Slicing process finished."; } @@ -883,20 +897,20 @@ void Print::_make_skirt() // prepended to the first 'n' layers (with 'n' = skirt_height). // $skirt_height_z in this case is the highest possible skirt height for safety. coordf_t skirt_height_z = 0.; - for (const PrintObject *object : this->objects) { + for (const PrintObject *object : m_objects) { size_t skirt_layers = this->has_infinite_skirt() ? object->layer_count() : - std::min(size_t(this->config.skirt_height.value), object->layer_count()); - skirt_height_z = std::max(skirt_height_z, object->layers[skirt_layers-1]->print_z); + std::min(size_t(m_config.skirt_height.value), object->layer_count()); + skirt_height_z = std::max(skirt_height_z, object->m_layers[skirt_layers-1]->print_z); } // Collect points from all layers contained in skirt height. Points points; - for (const PrintObject *object : this->objects) { + for (const PrintObject *object : m_objects) { this->throw_if_canceled(); Points object_points; // Get object layers up to skirt_height_z. - for (const Layer *layer : object->layers) { + for (const Layer *layer : object->m_layers) { if (layer->print_z > skirt_height_z) break; for (const ExPolygon &expoly : layer->slices.expolygons) @@ -904,7 +918,7 @@ void Print::_make_skirt() append(object_points, expoly.contour.points); } // Get support layers up to skirt_height_z. - for (const SupportLayer *layer : object->support_layers) { + for (const SupportLayer *layer : object->support_layers()) { if (layer->print_z > skirt_height_z) break; for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities) @@ -942,18 +956,18 @@ void Print::_make_skirt() extruders_e_per_mm.reserve(set_extruders.size()); for (auto &extruder_id : set_extruders) { extruders.push_back(extruder_id); - extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &this->config).e_per_mm(mm3_per_mm)); + extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &m_config).e_per_mm(mm3_per_mm)); } } // Number of skirt loops per skirt layer. - int n_skirts = this->config.skirts.value; + int n_skirts = m_config.skirts.value; if (this->has_infinite_skirt() && n_skirts == 0) n_skirts = 1; // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. - coord_t distance = scale_(std::max(this->config.skirt_distance.value, this->config.brim_width.value)); + coord_t distance = scale_(std::max(m_config.skirt_distance.value, m_config.brim_width.value)); // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector<coordf_t> extruded_length(extruders.size(), 0.); @@ -978,16 +992,16 @@ void Print::_make_skirt() first_layer_height // this will be overridden at G-code export time ))); eloop.paths.back().polyline = loop.split_at_first_point(); - this->skirt.append(eloop); - if (this->config.min_skirt_length.value > 0) { + m_skirt.append(eloop); + if (m_config.min_skirt_length.value > 0) { // The skirt length is limited. Sum the total amount of filament length extruded, in mm. extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; - if (extruded_length[extruder_idx] < this->config.min_skirt_length.value) { + if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) { // Not extruded enough yet with the current extruder. Add another loop. if (i == 1) ++ i; } else { - assert(extruded_length[extruder_idx] >= this->config.min_skirt_length.value); + assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value); // Enough extruded with the current extruder. Extrude with the next one, // until the prescribed number of skirt loops is extruded. if (extruder_idx + 1 < extruders.size()) @@ -998,7 +1012,7 @@ void Print::_make_skirt() } } // Brims were generated inside out, reverse to print the outmost contour first. - this->skirt.reverse(); + m_skirt.reverse(); } void Print::_make_brim() @@ -1006,13 +1020,13 @@ void Print::_make_brim() // Brim is only printed on first layer and uses perimeter extruder. Flow flow = this->brim_flow(); Polygons islands; - for (PrintObject *object : this->objects) { + for (PrintObject *object : m_objects) { this->throw_if_canceled(); Polygons object_islands; - for (ExPolygon &expoly : object->layers.front()->slices.expolygons) + for (ExPolygon &expoly : object->m_layers.front()->slices.expolygons) object_islands.push_back(expoly.contour); - if (! object->support_layers.empty()) - object->support_layers.front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); + if (! object->support_layers().empty()) + object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); islands.reserve(islands.size() + object_islands.size() * object->_shifted_copies.size()); for (const Point &pt : object->_shifted_copies) for (Polygon &poly : object_islands) { @@ -1021,7 +1035,7 @@ void Print::_make_brim() } } Polygons loops; - size_t num_loops = size_t(floor(this->config.brim_width.value / flow.width)); + size_t num_loops = size_t(floor(m_config.brim_width.value / flow.width)); for (size_t i = 0; i < num_loops; ++ i) { this->throw_if_canceled(); islands = offset(islands, float(flow.scaled_spacing()), jtSquare); @@ -1037,32 +1051,24 @@ void Print::_make_brim() loops = union_pt_chained(loops, false); std::reverse(loops.begin(), loops.end()); - extrusion_entities_append_loops(this->brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height())); + extrusion_entities_append_loops(m_brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height())); } // Wipe tower support. bool Print::has_wipe_tower() const { return - this->config.single_extruder_multi_material.value && - ! this->config.spiral_vase.value && - this->config.wipe_tower.value && - this->config.nozzle_diameter.values.size() > 1; -} - -void Print::_clear_wipe_tower() -{ - m_tool_ordering.clear(); - m_wipe_tower_priming.reset(nullptr); - m_wipe_tower_tool_changes.clear(); - m_wipe_tower_final_purge.reset(nullptr); + m_config.single_extruder_multi_material.value && + ! m_config.spiral_vase.value && + m_config.wipe_tower.value && + m_config.nozzle_diameter.values.size() > 1; } void Print::_make_wipe_tower() { // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print. - m_tool_ordering = ToolOrdering(*this, (unsigned int)-1, true); - if (! m_tool_ordering.has_wipe_tower()) + m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true); + if (! m_wipe_tower_data.tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; @@ -1072,33 +1078,31 @@ void Print::_make_wipe_tower() // see https://github.com/prusa3d/Slic3r/issues/607 { size_t idx_begin = size_t(-1); - size_t idx_end = m_tool_ordering.layer_tools().size(); + size_t idx_end = m_wipe_tower_data.tool_ordering.layer_tools().size(); // Find the first wipe tower layer, which does not have a counterpart in an object or a support layer. for (size_t i = 0; i < idx_end; ++ i) { - const ToolOrdering::LayerTools < = m_tool_ordering.layer_tools()[i]; + const ToolOrdering::LayerTools < = m_wipe_tower_data.tool_ordering.layer_tools()[i]; if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) { idx_begin = i; break; } } if (idx_begin != size_t(-1)) { - // Find the position in this->objects.first()->support_layers to insert these new support layers. - double wipe_tower_new_layer_print_z_first = m_tool_ordering.layer_tools()[idx_begin].print_z; - SupportLayerPtrs::iterator it_layer = this->objects.front()->support_layers.begin(); - SupportLayerPtrs::iterator it_end = this->objects.front()->support_layers.end(); + // Find the position in m_objects.first()->support_layers to insert these new support layers. + double wipe_tower_new_layer_print_z_first = m_wipe_tower_data.tool_ordering.layer_tools()[idx_begin].print_z; + SupportLayerPtrs::const_iterator it_layer = m_objects.front()->support_layers().begin(); + SupportLayerPtrs::const_iterator it_end = m_objects.front()->support_layers().end(); for (; it_layer != it_end && (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer); // Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer. for (size_t i = idx_begin; i < idx_end; ++ i) { - ToolOrdering::LayerTools < = const_cast<ToolOrdering::LayerTools&>(m_tool_ordering.layer_tools()[i]); + ToolOrdering::LayerTools < = const_cast<ToolOrdering::LayerTools&>(m_wipe_tower_data.tool_ordering.layer_tools()[i]); if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support)) break; lt.has_support = true; // Insert the new support layer. - double height = lt.print_z - m_tool_ordering.layer_tools()[i-1].print_z; + double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z; //FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway. - auto *new_layer = new SupportLayer(size_t(-1), this->objects.front(), - height, lt.print_z, lt.print_z - 0.5 * height); - it_layer = this->objects.front()->support_layers.insert(it_layer, new_layer); + it_layer = m_objects.front()->insert_support_layer(it_layer, size_t(-1), height, lt.print_z, lt.print_z - 0.5 * height); ++ it_layer; } } @@ -1107,9 +1111,9 @@ void Print::_make_wipe_tower() // Initialize the wipe tower. WipeTowerPrusaMM wipe_tower( - float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), - float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - m_tool_ordering.first_extruder()); + float(m_config.wipe_tower_x.value), float(m_config.wipe_tower_y.value), + float(m_config.wipe_tower_width.value), float(m_config.wipe_tower_per_color_wipe.value), + m_wipe_tower_data.tool_ordering.first_extruder()); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); @@ -1118,29 +1122,29 @@ void Print::_make_wipe_tower() for (size_t i = 0; i < 4; ++ i) wipe_tower.set_extruder( i, - WipeTowerPrusaMM::parse_material(this->config.filament_type.get_at(i).c_str()), - this->config.temperature.get_at(i), - this->config.first_layer_temperature.get_at(i)); + WipeTowerPrusaMM::parse_material(m_config.filament_type.get_at(i).c_str()), + m_config.temperature.get_at(i), + m_config.first_layer_temperature.get_at(i)); // When printing the first layer's wipe tower, the first extruder is expected to be active and primed. - // Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer. + // Therefore the number of wipe sections at the wipe tower will be (m_wipe_tower_data.tool_ordering.front().extruders-1) at the 1st layer. // The following variable is true if the last priming section cannot be squeezed inside the wipe tower. - bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions; + bool last_priming_wipe_full = m_wipe_tower_data.tool_ordering.front().extruders.size() > m_wipe_tower_data.tool_ordering.front().wipe_tower_partitions; - m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>( - wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE)); + m_wipe_tower_data.priming = Slic3r::make_unique<WipeTower::ToolChangeResult>( + wipe_tower.prime(this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE)); // Generate the wipe tower layers. - m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); + m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size()); // Set current_extruder_id to the last extruder primed. - unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); - for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) { + unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.all_extruders().back(); + for (const ToolOrdering::LayerTools &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { this->throw_if_canceled(); if (! layer_tools.has_wipe_tower) // This is a support only layer, or the wipe tower does not reach to this height. continue; - bool first_layer = &layer_tools == &m_tool_ordering.front(); - bool last_layer = &layer_tools == &m_tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0; + bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); + bool last_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0; wipe_tower.set_layer( float(layer_tools.print_z), float(layer_tools.wipe_tower_layer_height), @@ -1151,7 +1155,7 @@ void Print::_make_wipe_tower() for (unsigned int extruder_id : layer_tools.extruders) // Call the wipe_tower.tool_change() at the first layer for the initial extruder // to extrude the wipe tower brim, - if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || + if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || // or when an extruder shall be switched. extruder_id != current_extruder_id) { tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, extruder_id == layer_tools.extruders.back(), WipeTower::PURPOSE_EXTRUDE)); @@ -1175,48 +1179,49 @@ void Print::_make_wipe_tower() tool_changes.pop_back(); } } - m_wipe_tower_tool_changes.emplace_back(std::move(tool_changes)); + m_wipe_tower_data.tool_changes.emplace_back(std::move(tool_changes)); if (last_layer) break; } // Unload the current filament over the purge tower. - coordf_t layer_height = this->objects.front()->config.layer_height.value; - if (m_tool_ordering.back().wipe_tower_partitions > 0) { + coordf_t layer_height = m_objects.front()->config().layer_height.value; + if (m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions > 0) { // The wipe tower goes up to the last layer of the print. if (wipe_tower.layer_finished()) { // The wipe tower is printed to the top of the print and it has no space left for the final extruder purge. // Lift Z to the next layer. - wipe_tower.set_layer(float(m_tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true); + wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true); } else { // There is yet enough space at this layer of the wipe tower for the final purge. } } else { // The wipe tower does not reach the last print layer, perform the pruge at the last print layer. - assert(m_tool_ordering.back().wipe_tower_partitions == 0); - wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true); + assert(m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions == 0); + wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z), float(layer_height), 0, false, true); } - m_wipe_tower_final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>( + m_wipe_tower_data.final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>( wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE)); } -std::string Print::output_filename() +std::string Print::output_filename() const { - this->placeholder_parser.update_timestamp(); + DynamicConfig cfg_timestamp; + PlaceholderParser::update_timestamp(cfg_timestamp); try { - return this->placeholder_parser.process(this->config.output_filename_format.value, 0); + return this->placeholder_parser().process(m_config.output_filename_format.value, 0, &cfg_timestamp); } catch (std::runtime_error &err) { throw std::runtime_error(std::string("Failed processing of the output_filename_format template.\n") + err.what()); } } -std::string Print::output_filepath(const std::string &path) +std::string Print::output_filepath(const std::string &path) const { // if we were supplied no path, generate an automatic one based on our first object's input file if (path.empty()) { // get the first input file name std::string input_file; - for (const PrintObject *object : this->objects) { + for (const PrintObject *object : m_objects) { input_file = object->model_object()->input_file; if (! input_file.empty()) break; |