From 088b92917c00e4b1abbd9b517705125f107201a6 Mon Sep 17 00:00:00 2001 From: supermerill Date: Sun, 26 Sep 2021 13:50:49 +0200 Subject: [PATCH] Add filament_max_overlap, to control the line spacing via filament setting It allows to control the spacing vs width (10%% fill vs a bit less) The 'enforce 100% fill volume' is also adjusted to take that into account Note that if you're using multiple extruders/filament everywhere (and spacing setting for width setting), the result may be a bit unexpected, as the gui can't display all the interactions, also some features (like support) may revert to default overlap value, if printed with multiple filaments. supermerill/SuperSlicer#1590 --- resources/ui_layout/filament.ui | 1 + src/libslic3r/Config.cpp | 8 +- src/libslic3r/ExtrusionEntity.cpp | 8 +- src/libslic3r/ExtrusionEntity.hpp | 24 ++--- src/libslic3r/ExtrusionEntityCollection.cpp | 4 +- src/libslic3r/ExtrusionEntityCollection.hpp | 6 +- src/libslic3r/Fill/Fill.cpp | 11 ++- src/libslic3r/Fill/FillBase.cpp | 19 ++-- src/libslic3r/Fill/FillBase.hpp | 2 +- src/libslic3r/Fill/FillRectilinear.cpp | 29 +++--- src/libslic3r/Fill/FillSmooth.cpp | 43 +++++---- src/libslic3r/Flow.cpp | 36 +++++-- src/libslic3r/Flow.hpp | 14 +-- src/libslic3r/GCode/WipeTower.cpp | 3 +- src/libslic3r/MedialAxis.cpp | 2 +- src/libslic3r/PerimeterGenerator.cpp | 6 +- src/libslic3r/Preset.cpp | 1 + src/libslic3r/PresetBundle.cpp | 80 ++++++++-------- src/libslic3r/PresetBundle.hpp | 8 +- src/libslic3r/Print.cpp | 27 ++++-- src/libslic3r/PrintConfig.cpp | 101 ++++++++++++++------ src/libslic3r/PrintConfig.hpp | 7 +- src/libslic3r/PrintObject.cpp | 1 + src/libslic3r/PrintRegion.cpp | 4 +- src/libslic3r/SupportMaterial.cpp | 6 +- src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GUI_ObjectList.cpp | 8 +- src/slic3r/GUI/GUI_ObjectSettings.cpp | 4 +- src/slic3r/GUI/GUI_Preview.cpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 8 +- src/slic3r/GUI/PresetComboBoxes.cpp | 2 +- src/slic3r/GUI/PresetHints.cpp | 63 ++++++++---- src/slic3r/GUI/Tab.cpp | 51 +++++++--- src/slic3r/Utils/PresetUpdater.cpp | 8 +- 37 files changed, 380 insertions(+), 227 deletions(-) diff --git a/resources/ui_layout/filament.ui b/resources/ui_layout/filament.ui index 38ada3066..daed21468 100644 --- a/resources/ui_layout/filament.ui +++ b/resources/ui_layout/filament.ui @@ -21,6 +21,7 @@ group:Filament properties setting:width$7:filament_type setting:filament_soluble setting:filament_shrink + setting:filament_max_overlap group:Print speed override setting:filament_max_speed setting:filament_max_volumetric_speed diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 8964d73b0..21d3a835f 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -742,7 +742,9 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex if (def == nullptr) throw NoDefinitionException(opt_key); const ConfigOptionDef* opt_def = def->get(opt_key); - if (!opt_def->ratio_over.empty() && opt_def->ratio_over != "depends") + if (opt_def->ratio_over.empty()) + return opt_fl_per->get_abs_value(extruder_id, 1); + if (opt_def->ratio_over != "depends") return opt_fl_per->get_abs_value(extruder_id, this->get_computed_value(opt_def->ratio_over, extruder_id)); std::stringstream ss; ss << "ConfigBase::get_abs_value(): " << opt_key << " has no valid ratio_over to compute of"; throw ConfigurationError(ss.str()); @@ -753,7 +755,9 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex if (def == nullptr) throw NoDefinitionException(opt_key); const ConfigOptionDef* opt_def = def->get(opt_key); - if (!opt_def->ratio_over.empty() && opt_def->ratio_over != "depends") + if (opt_def->ratio_over.empty()) + return opt_per->get_abs_value(extruder_id, 1); + if (opt_def->ratio_over != "depends") return opt_per->get_abs_value(extruder_id, this->get_computed_value(opt_def->ratio_over, extruder_id)); std::stringstream ss; ss << "ConfigBase::get_abs_value(): " << opt_key << " has no valid ratio_over to compute of"; throw ConfigurationError(ss.str()); diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 5c825f5c7..3ec8800bb 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -64,12 +64,12 @@ void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_ polygons_append(out, offset(this->polyline, double(scale_(this->width/2)) + scaled_epsilon)); } -void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const +void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const { // Instantiating the Flow class to get the line spacing. // Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler. // if the spacing is negative, use the width instead. can happen on ironing second pass. - Flow flow(this->width, this->height, 0.f, (this->width*4 < this->height)?true:is_bridge(this->role())); + Flow flow(this->width, this->height, 0.f, spacing_ratio, (this->width*4 < this->height)?true:is_bridge(this->role())); polygons_append(out, offset(this->polyline, 0.5f * double(flow.scaled_spacing()) + scaled_epsilon)); } @@ -249,10 +249,10 @@ void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_ path.polygons_covered_by_width(out, scaled_epsilon); } -void ExtrusionLoop::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const +void ExtrusionLoop::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const { for (const ExtrusionPath &path : this->paths) - path.polygons_covered_by_spacing(out, scaled_epsilon); + path.polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); } std::string ExtrusionEntity::role_to_string(ExtrusionRole role) diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index a675ae9e7..8ce95e910 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -196,11 +196,11 @@ public: // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill. - virtual void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const = 0; + virtual void polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const = 0; virtual Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } - virtual Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const - { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + virtual Polygons polygons_covered_by_spacing(const float spacing_ratio, const float scaled_epsilon) const + { Polygons out; this->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); return out; } virtual Polyline as_polyline() const = 0; virtual void collect_polylines(Polylines &dst) const = 0; virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; } @@ -262,11 +262,11 @@ public: // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill. - void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override; + void polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const override; virtual Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } - virtual Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const - { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + virtual Polygons polygons_covered_by_spacing(const float spacing_ratio, const float scaled_epsilon) const + { Polygons out; this->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); return out; } Polyline as_polyline() const override { return this->polyline; } void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline); } double total_volume() const override { return mm3_per_mm * unscale(length()); } @@ -353,9 +353,9 @@ public: // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill. - void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override { + void polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const override { for (const THING &entity : this->paths) - entity.polygons_covered_by_spacing(out, scaled_epsilon); + entity.polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); } Polyline as_polyline() const override { @@ -381,7 +381,7 @@ public: return out; } Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const override{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } - Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const override { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + Polygons polygons_covered_by_spacing(const float spacing_ratio, const float scaled_epsilon) const override { Polygons out; this->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); return out; } void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (!pl.empty()) dst.emplace_back(std::move(pl)); } double total_volume() const override { double volume = 0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } }; @@ -463,11 +463,11 @@ public: // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill. - void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override; + void polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const override; Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } - Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const - { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + Polygons polygons_covered_by_spacing(const float spacing_ratio, const float scaled_epsilon) const + { Polygons out; this->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); return out; } Polyline as_polyline() const override { return this->polygon().split_at_first_point(); } void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); } double total_volume() const override { double volume = 0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } diff --git a/src/libslic3r/ExtrusionEntityCollection.cpp b/src/libslic3r/ExtrusionEntityCollection.cpp index c80028780..c31b06966 100644 --- a/src/libslic3r/ExtrusionEntityCollection.cpp +++ b/src/libslic3r/ExtrusionEntityCollection.cpp @@ -121,10 +121,10 @@ void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const f entity->polygons_covered_by_width(out, scaled_epsilon); } -void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const +void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const { for (const ExtrusionEntity *entity : this->entities) - entity->polygons_covered_by_spacing(out, scaled_epsilon); + entity->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); } // Recursively count paths and loops contained in this collection. diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index 439dddab2..08d2fddba 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -103,11 +103,11 @@ public: // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill. - void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override; + void polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const override; Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } - Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const - { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + Polygons polygons_covered_by_spacing(const float spacing_ratio, const float scaled_epsilon) const + { Polygons out; this->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); return out; } /// Recursively count paths and loops contained in this collection size_t items_count() const; diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 26952ae46..cd4cfc248 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -149,7 +149,7 @@ std::vector group_fills(const Layer &layer) } //adjust spacing/density (to over-extrude when needed) if (surface.has_mod_overBridge()) { - params.density = float(layerm.region()->config().over_bridge_flow_ratio.get_abs_value(1)); + params.density = float(region_config.over_bridge_flow_ratio.get_abs_value(1)); } //note: same as getRoleFromSurfaceType() @@ -442,7 +442,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: // so we can safely ignore the slight variation that might have // been applied to $f->flow_spacing } else { - surface_fill.params.flow = Flow::new_from_spacing((float)f->get_spacing(), surface_fill.params.flow.nozzle_diameter, (float)surface_fill.params.flow.height, surface_fill.params.flow.bridge); + float overlap = surface_fill.params.config->get_computed_value("filament_max_overlap", surface_fill.params.extruder - 1); + surface_fill.params.flow = Flow::new_from_spacing((float)f->get_spacing(), surface_fill.params.flow.nozzle_diameter, (float)surface_fill.params.flow.height, overlap, surface_fill.params.flow.bridge); } //apply bridge_overlap if needed @@ -452,8 +453,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: for (ExPolygon &expoly : surface_fill.expolygons) { //set overlap polygons - if (layerm->region()->config().perimeters > 0) { - f->overlap = layerm->region()->config().get_abs_value("infill_overlap", (perimeter_spacing + (f->get_spacing())) / 2); + if (surface_fill.params.config->perimeters > 0) { + f->overlap = surface_fill.params.config->infill_overlap.get_abs_value((perimeter_spacing + (f->get_spacing())) / 2); if (f->overlap != 0) { f->no_overlap_expolygons = intersection_ex(layerm->fill_no_overlap_expolygons, ExPolygons() = { expoly }); } else { @@ -646,7 +647,7 @@ void Layer::make_ironing() fill.angle = float(ironing_params.angle + 0.25 * M_PI); fill.link_max_length = (coord_t)scale_(3. * fill.get_spacing()); double height = ironing_params.height * fill.get_spacing() / nozzle_dmr; - Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height), false); + Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height), 1.f, false); double flow_mm3_per_mm = flow.mm3_per_mm(); Surface surface_fill((stPosTop | stDensSolid), ExPolygon()); for (ExPolygon &expoly : ironing_areas) { diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 619b41629..e7d0585c5 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -189,18 +189,21 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ length_tot += unscaled(line->length()); } } - double extruded_volume = params.flow.mm3_per_mm() * length_tot; + //compute flow to remove spacing_ratio from the equation + double extruded_volume = 0; + if (params.flow.spacing_ratio < 1.f && !params.flow.bridge) { + // the spacing is larger than usual. get the flow from the current spacing + Flow test_flow = Flow::new_from_spacing(params.flow.spacing(), params.flow.nozzle_diameter, params.flow.height, 1, params.flow.bridge); + extruded_volume = test_flow.mm3_per_mm() * length_tot; + }else + extruded_volume = params.flow.mm3_per_mm() * length_tot; // compute real volume double polyline_volume = compute_unscaled_volume_to_fill(surface, params); - //printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n", - // extrudedVolume, - // (poylineVolume), - // (poylineVolume) / extrudedVolume, - // this->no_overlap_expolygons.size()); - if (extruded_volume != 0 && polyline_volume != 0) mult_flow = polyline_volume / extruded_volume; + if (extruded_volume != 0 && polyline_volume != 0) mult_flow *= polyline_volume / extruded_volume; //failsafe, it can happen if (mult_flow > 1.3) mult_flow = 1.3; if (mult_flow < 0.8) mult_flow = 0.8; + BOOST_LOG_TRIVIAL(info) << "Infill process extrude " << extruded_volume << " mm3 for a volume of " << polyline_volume << " mm3 : we mult the flow by " << mult_flow; } // Save into layer. @@ -237,7 +240,7 @@ Fill::do_gap_fill(const ExPolygons& gapfill_areas, const FillParams& params, Ext double max = 2. * params.flow.scaled_width(); // collapse //be sure we don't gapfill where the perimeters are already touching each other (negative spacing). - min = std::max(min, double(Flow::new_from_spacing((float)EPSILON, (float)params.flow.nozzle_diameter, (float)params.flow.height, false).scaled_width())); + min = std::max(min, double(Flow::new_from_spacing((float)EPSILON, (float)params.flow.nozzle_diameter, (float)params.flow.height, 1, false).scaled_width())); //ExPolygons gapfill_areas_collapsed = diff_ex( // offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2)), // offset2_ex(gapfill_areas, double(-max / 2), double(+max / 2)), diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 1d97fb38c..afdcf833a 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -72,7 +72,7 @@ struct FillParams ExtrusionRole role { erNone }; //flow to use - Flow flow = Flow(0.f, 0.f, 0.f, false); + Flow flow = Flow(0.f, 0.f, 0.f, 1.f, false); //full configuration for the region, to avoid copying every bit that is needed. Use this for process-specific parameters. PrintRegionConfig const *config{ nullptr }; diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 1dd8acd3d..69615f0c4 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -3402,27 +3402,30 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi //check if not over-extruding if (!params.dont_adjust && params.full_infill() && !params.flow.bridge && params.fill_exactly) { // compute the path of the nozzle -> extruded volume - double lengthTot = 0; - int nbLines = 0; + double length_tot = 0; + int nb_lines = 0; for (const Polyline &pline : polylines_rectilinear) { Lines lines = pline.lines(); for (auto line = lines.begin(); line != lines.end(); ++line) { - lengthTot += unscaled(line->length()); - nbLines++; + length_tot += unscaled(line->length()); + nb_lines++; } } - double extrudedVolume = params.flow.mm3_per_mm() * lengthTot; + //compute flow to remove spacing_ratio from the equation + double extruded_volume = 0; + if (params.flow.spacing_ratio < 1.f && !params.flow.bridge) { + // the spacing is larger than usual. get the flow from the current spacing + Flow test_flow = Flow::new_from_spacing(params.flow.spacing(), params.flow.nozzle_diameter, params.flow.height, 1, params.flow.bridge); + extruded_volume = test_flow.mm3_per_mm() * length_tot; + } else + extruded_volume = params.flow.mm3_per_mm() * length_tot; // compute real volume - double poylineVolume = compute_unscaled_volume_to_fill(surface, params); - //printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n", - // extrudedVolume, - // (poylineVolume), - // (poylineVolume) / extrudedVolume, - // this->no_overlap_expolygons.size()); - if (extrudedVolume != 0 && poylineVolume != 0) flow_mult_exact_volume = poylineVolume / extrudedVolume; + double polyline_volume = compute_unscaled_volume_to_fill(surface, params); + if (extruded_volume != 0 && polyline_volume != 0) flow_mult_exact_volume = polyline_volume / extruded_volume; //failsafe, it can happen if (flow_mult_exact_volume > 1.3) flow_mult_exact_volume = 1.3; if (flow_mult_exact_volume < 0.8) flow_mult_exact_volume = 0.8; + BOOST_LOG_TRIVIAL(info) << "Infill (without gapfil) process extrude " << extruded_volume << " mm3 for a volume of " << polyline_volume << " mm3 : we mult the flow by " << flow_mult_exact_volume; } //Create extrusions @@ -3443,7 +3446,7 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi coll_nosort->entities.push_back(eec); - unextruded_areas = diff_ex(rectilinear_areas, union_ex(eec->polygons_covered_by_spacing(10), true)); + unextruded_areas = diff_ex(rectilinear_areas, union_ex(eec->polygons_covered_by_spacing(params.flow.spacing_ratio , 10), true)); } else unextruded_areas = rectilinear_areas; diff --git a/src/libslic3r/Fill/FillSmooth.cpp b/src/libslic3r/Fill/FillSmooth.cpp index 8c4e89bdc..561c6a0f6 100644 --- a/src/libslic3r/Fill/FillSmooth.cpp +++ b/src/libslic3r/Fill/FillSmooth.cpp @@ -73,27 +73,38 @@ namespace Slic3r { Polylines polylines_layer = f2->fill_surface(&srf_to_fill, params); if (!polylines_layer.empty()) { - - //compute the path of the nozzle - double lengthTot = 0; - int nbLines = 0; - for (Polyline &pline : polylines_layer) { - Lines lines = pline.lines(); - for (Line &line : lines) { - lengthTot += unscaled(line.length()); - nbLines++; - } - } - double extrudedVolume = params.flow.mm3_per_mm() * lengthTot / params.density; - if (extrudedVolume == 0) extrudedVolume = volume; - //get the role ExtrusionRole good_role = params.role; if (good_role == erNone || good_role == erCustom) { good_role = params.flow.bridge && idx == 0 ? erBridgeInfill : rolePass[idx]; } - // print - float mult_flow = float(params.fill_exactly /*&& idx == 0*/ ? std::min(2., volume / extrudedVolume) : 1); + //get the flow + float mult_flow = 1; + if (params.fill_exactly) { + //compute the path of the nozzle + double length_tot = 0; + int nb_lines = 0; + for (Polyline& pline : polylines_layer) { + Lines lines = pline.lines(); + for (Line& line : lines) { + length_tot += unscaled(line.length()); + nb_lines++; + } + } + //compute flow to remove spacing_ratio from the equation + double extruded_volume = 0; + if (params.flow.spacing_ratio < 1.f && !params.flow.bridge) { + // the spacing is larger than usual. get the flow from the current spacing + Flow test_flow = Flow::new_from_spacing(params.flow.spacing(), params.flow.nozzle_diameter, params.flow.height, 1, params.flow.bridge); + extruded_volume = test_flow.mm3_per_mm() * length_tot / params.density; + } else + extruded_volume = params.flow.mm3_per_mm() * length_tot / params.density; + if (extruded_volume == 0) extruded_volume = volume; + + // print + mult_flow = (float)std::min(2., volume / extruded_volume); + BOOST_LOG_TRIVIAL(info) << "Ironing process extrude " << extruded_volume << " mm3 for a volume of " << volume << " mm3 : we mult the flow by " << mult_flow; + } extrusion_entities_append_paths( eec.entities, std::move(polylines_layer), good_role, diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index b13eb3f87..274c5af26 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -1,6 +1,7 @@ #include "Flow.hpp" #include "I18N.hpp" #include "Print.hpp" +#include "Layer.hpp" #include #include @@ -180,7 +181,7 @@ double Flow::extrusion_width(const std::string& opt_key, const ConfigOptionResol // This constructor builds a Flow object from an extrusion width config setting // and other context properties. -Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio) +Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float spacing_ratio, float bridge_flow_ratio) { // we need layer height unless it's a bridge if (height <= 0 && bridge_flow_ratio == 0) @@ -201,11 +202,11 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent w = float(width.get_abs_value(nozzle_diameter)); } - return Flow(w, height, nozzle_diameter, bridge_flow_ratio > 0); + return Flow(w, height, nozzle_diameter, spacing_ratio, bridge_flow_ratio > 0); } // This constructor builds a Flow object from a given centerline spacing. -Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) +Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, float spacing_ratio, bool bridge) { // we need layer height unless it's a bridge if (height <= 0 && !bridge) @@ -216,11 +217,11 @@ Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, float width = float(bridge ? (spacing - BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : #ifdef HAS_PERIMETER_LINE_OVERLAP - (spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI)); + (spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI) * spacing_ratio); #else - (spacing + height * (1. - 0.25 * PI))); + (spacing + height * (1. - 0.25 * PI) * spacing_ratio)); #endif - return Flow(width, bridge ? width : height, nozzle_diameter, bridge); + return Flow(width, bridge ? width : height, nozzle_diameter, spacing_ratio, bridge); } // This method returns the centerline spacing between two adjacent extrusions @@ -231,7 +232,7 @@ float Flow::spacing() const if (this->bridge) return this->width + BRIDGE_EXTRA_SPACING; // rectangle with semicircles at the ends - float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI); + float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI) * spacing_ratio; float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing); #else float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI) * spacing_ratio)); @@ -274,13 +275,18 @@ double Flow::mm3_per_mm() const Flow support_material_flow(const PrintObject *object, float layer_height) { + int extruder_id = object->config().support_material_extruder.value - 1; + if (extruder_id < 0) { + extruder_id = object->layers().front()->get_region(0)->region()->config().perimeter_extruder - 1; + } return Flow::new_from_config_width( frSupportMaterial, // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution. (object->config().support_material_extrusion_width.value > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width, // if object->config().support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component. - float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)), + float(object->print()->config().nozzle_diameter.get_at(extruder_id)), (layer_height > 0.f) ? layer_height : float(object->config().layer_height.value), + extruder_id < 0 ? 1 : object->config().get_computed_value("filament_max_overlap", extruder_id), //if can get an extruder, then use its param, or use full overlap if we don't know the extruder id. // bridge_flow_ratio 0.f); } @@ -292,25 +298,35 @@ Flow support_material_1st_layer_flow(const PrintObject *object, float layer_heig if (layer_height <= 0.f && !object->print()->config().nozzle_diameter.empty()){ slice_height = (float)object->get_first_layer_height(); } + int extruder_id = object->config().support_material_extruder.value -1; + if (extruder_id < 0) { + extruder_id = object->layers().front()->get_region(0)->region()->config().infill_extruder - 1; + } return Flow::new_from_config_width( frSupportMaterial, // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution. (width.value > 0) ? width : object->config().extrusion_width, - float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder - 1)), + float(object->print()->config().nozzle_diameter.get_at(extruder_id)), slice_height, + extruder_id < 0 ? 1 : object->config().get_computed_value("filament_max_overlap", extruder_id), //if can get an extruder, then use its param, or use full overlap if we don't know the extruder id. // bridge_flow_ratio 0.f); } Flow support_material_interface_flow(const PrintObject *object, float layer_height) { + int extruder_id = object->config().support_material_interface_extruder.value - 1; + if (extruder_id < 0) { + extruder_id = object->layers().front()->get_region(0)->region()->config().infill_extruder - 1; + } return Flow::new_from_config_width( frSupportMaterialInterface, // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution. (object->config().support_material_extrusion_width > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width, // if object->config().support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component. - float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_interface_extruder-1)), + float(object->print()->config().nozzle_diameter.get_at(extruder_id)), (layer_height > 0.f) ? layer_height : float(object->config().layer_height.value), + extruder_id < 0 ? 1 : object->config().get_computed_value("filament_max_overlap", extruder_id), //if can get an extruder, then use its param, or use full overlap if we don't know the extruder id. // bridge_flow_ratio 0.f); } diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp index 99fe93bad..06c4a158f 100644 --- a/src/libslic3r/Flow.hpp +++ b/src/libslic3r/Flow.hpp @@ -67,10 +67,10 @@ public: // Is it a bridge? bool bridge; // % of spacing taken into account 1=>all/default, 0=> width=spacing - float spacing_ratio = 1; + float spacing_ratio; - Flow(float _w, float _h, float _nd, bool _bridge = false) : - width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {} + Flow(float _w, float _h, float _nd, float spacing_ratio, bool _bridge) : + width(_w), height(_h), nozzle_diameter(_nd), spacing_ratio(spacing_ratio), bridge(_bridge) {} float spacing() const; float spacing(const Flow &other) const; @@ -87,14 +87,14 @@ public: bool operator==(const Flow &rhs) const { return this->width == rhs.width && this->height == rhs.height && this->nozzle_diameter == rhs.nozzle_diameter && this->bridge == rhs.bridge; } - static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio = 0); + static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float spacing_ratio, float bridge_flow_ratio); // Create a flow from the spacing of extrusion lines. // This method is used exclusively to calculate new flow of 100% infill, where the extrusion width was allowed to scale // to fit a region with integer number of lines. - static Flow new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge); + static Flow new_from_spacing(float spacing, float nozzle_diameter, float height, float spacing_ratio, bool bridge); - static float overlap(float height) { - return (float)(height * (1. - 0.25 * PI)); + float overlap(float height) { + return (float)(height * (1. - 0.25 * PI)) * spacing_ratio; } // Sane extrusion width defautl based on nozzle diameter. diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 094640846..30c29e177 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -933,7 +933,8 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of m_wipe_tower_width, m_wipe_tower_depth); double unscaled_brim_width = m_config->wipe_tower_brim.get_abs_value(m_nozzle_diameter); - Slic3r::Flow brim_flow = Flow::new_from_config_width(FlowRole::frPerimeter, m_object_config->first_layer_extrusion_width, m_nozzle_diameter, m_layer_height); + Slic3r::Flow brim_flow = Flow::new_from_config_width(FlowRole::frPerimeter, m_object_config->first_layer_extrusion_width, m_nozzle_diameter, m_layer_height, + 1,0); //don't care of spacing and bridge WipeTowerWriter writer(m_layer_height, brim_flow.width, m_gcode_flavor, m_filpar); writer.set_extrusion_flow(brim_flow.mm3_per_mm()) diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp index 22a26950a..b75fb7168 100644 --- a/src/libslic3r/MedialAxis.cpp +++ b/src/libslic3r/MedialAxis.cpp @@ -1518,7 +1518,7 @@ MedialAxis::grow_to_nozzle_diameter(ThickPolylines& pp, const ExPolygons& anchor float(unscaled(this->nozzle_diameter)), float(unscaled(this->nozzle_diameter)), float(unscaled(this->height)), - false).scaled_width(); + 1, false).scaled_width(); //ensure the width is not lower than min_width. for (ThickPolyline& polyline : pp) { for (int i = 0; i < polyline.points.size(); ++i) { diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index d01ef6ed2..3bc2340c1 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -38,8 +38,8 @@ namespace Slic3r { void PerimeterGenerator::process() { //set spacing - this->perimeter_flow.spacing_ratio = this->config->perimeter_overlap.get_abs_value(1); - this->ext_perimeter_flow.spacing_ratio = this->config->external_perimeter_overlap.get_abs_value(1); + this->perimeter_flow.spacing_ratio = std::min(this->perimeter_flow.spacing_ratio, (float)this->config->perimeter_overlap.get_abs_value(1)); + this->ext_perimeter_flow.spacing_ratio = std::min(this->ext_perimeter_flow.spacing_ratio, (float)this->config->external_perimeter_overlap.get_abs_value(1)); // other perimeters this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm(); @@ -991,7 +991,7 @@ void PerimeterGenerator::process() // collapse double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE); //be sure we don't gapfill where the perimeters are already touching each other (negative spacing). - min = std::max(min, double(Flow::new_from_spacing(EPSILON, (float)nozzle_diameter, (float)this->layer->height, false).scaled_width())); + min = std::max(min, double(Flow::new_from_spacing(EPSILON, (float)nozzle_diameter, (float)this->layer->height, this->perimeter_flow.spacing_ratio, false).scaled_width())); double max = 2.2 * perimeter_spacing; //remove areas that are too big (shouldn't occur...) ExPolygons too_big = offset2_ex(gaps, double(-max / 2), double(+max / 2)); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 66ae0080f..ea17f99d5 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -656,6 +656,7 @@ const std::vector& Preset::filament_options() "extrusion_multiplier", "filament_density", "filament_cost", "filament_spool_weight", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time", "filament_unloading_speed", "filament_toolchange_delay", "filament_unloading_speed_start", "filament_unload_time", "filament_cooling_moves", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower", + "filament_max_overlap", "filament_shrink", "filament_use_skinnydip", // skinnydip params start "filament_use_fast_skinnydip", diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 82f44251a..61788dbe1 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -38,7 +38,7 @@ static std::vector s_project_options { const char *PresetBundle::PRUSA_BUNDLE = "PrusaResearch"; PresetBundle::PresetBundle() : - prints(Preset::TYPE_FFF_PRINT, Preset::print_options(), static_cast(FullPrintConfig::defaults())), + fff_prints(Preset::TYPE_FFF_PRINT, Preset::print_options(), static_cast(FullPrintConfig::defaults())), filaments(Preset::TYPE_FFF_FILAMENT, Preset::filament_options(), static_cast(FullPrintConfig::defaults())), sla_materials(Preset::TYPE_SLA_MATERIAL, Preset::sla_material_options(), static_cast(SLAFullPrintConfig::defaults())), sla_prints(Preset::TYPE_SLA_PRINT, Preset::sla_print_options(), static_cast(SLAFullPrintConfig::defaults())), @@ -54,9 +54,9 @@ PresetBundle::PresetBundle() : // "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" // Create the ID config keys, as they are not part of the Static print config classes. - this->prints.default_preset().config.optptr("print_settings_id", true); - this->prints.default_preset().compatible_printers_condition(); - this->prints.default_preset().inherits(); + this->fff_prints.default_preset().config.optptr("print_settings_id", true); + this->fff_prints.default_preset().compatible_printers_condition(); + this->fff_prints.default_preset().inherits(); this->filaments.default_preset().config.option("filament_settings_id", true)->values = { "" }; this->filaments.default_preset().compatible_printers_condition(); @@ -96,7 +96,7 @@ PresetBundle::PresetBundle() : } // Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above. - this->prints .select_preset(0); + this->fff_prints .select_preset(0); this->sla_prints .select_preset(0); this->filaments .select_preset(0); this->sla_materials.select_preset(0); @@ -113,14 +113,14 @@ void PresetBundle::reset(bool delete_files) { // Clear the existing presets, delete their respective files. this->vendors.clear(); - this->prints .reset(delete_files); + this->fff_prints .reset(delete_files); this->sla_prints .reset(delete_files); this->filaments .reset(delete_files); this->sla_materials.reset(delete_files); this->printers .reset(delete_files); this->filament_presets.clear(); this->filament_presets.emplace_back(this->filaments.get_selected_preset_name()); - this->obsolete_presets.prints.clear(); + this->obsolete_presets.fff_prints.clear(); this->obsolete_presets.sla_prints.clear(); this->obsolete_presets.filaments.clear(); this->obsolete_presets.sla_materials.clear(); @@ -179,7 +179,7 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward ; try { - this->prints.load_presets(dir_user_presets, "print", substitutions, substitution_rule); + this->fff_prints.load_presets(dir_user_presets, "print", substitutions, substitution_rule); } catch (const std::runtime_error &err) { errors_cummulative += err.what(); } @@ -278,32 +278,32 @@ std::pair PresetBundle::load_system_pre std::vector PresetBundle::merge_presets(PresetBundle &&other) { this->vendors.insert(other.vendors.begin(), other.vendors.end()); - std::vector duplicate_prints = this->prints .merge_presets(std::move(other.prints), this->vendors); + std::vector duplicate_fff_prints = this->fff_prints .merge_presets(std::move(other.fff_prints), this->vendors); std::vector duplicate_sla_prints = this->sla_prints .merge_presets(std::move(other.sla_prints), this->vendors); std::vector duplicate_filaments = this->filaments .merge_presets(std::move(other.filaments), this->vendors); std::vector duplicate_sla_materials = this->sla_materials.merge_presets(std::move(other.sla_materials), this->vendors); std::vector duplicate_printers = this->printers .merge_presets(std::move(other.printers), this->vendors); - append(this->obsolete_presets.prints, std::move(other.obsolete_presets.prints)); + append(this->obsolete_presets.fff_prints, std::move(other.obsolete_presets.fff_prints)); append(this->obsolete_presets.sla_prints, std::move(other.obsolete_presets.sla_prints)); append(this->obsolete_presets.filaments, std::move(other.obsolete_presets.filaments)); append(this->obsolete_presets.sla_materials, std::move(other.obsolete_presets.sla_materials)); append(this->obsolete_presets.printers, std::move(other.obsolete_presets.printers)); - append(duplicate_prints, std::move(duplicate_sla_prints)); - append(duplicate_prints, std::move(duplicate_filaments)); - append(duplicate_prints, std::move(duplicate_sla_materials)); - append(duplicate_prints, std::move(duplicate_printers)); - return duplicate_prints; + append(duplicate_fff_prints, std::move(duplicate_sla_prints)); + append(duplicate_fff_prints, std::move(duplicate_filaments)); + append(duplicate_fff_prints, std::move(duplicate_sla_materials)); + append(duplicate_fff_prints, std::move(duplicate_printers)); + return duplicate_fff_prints; } void PresetBundle::update_system_maps() { - this->prints .update_map_system_profile_renamed(); + this->fff_prints .update_map_system_profile_renamed(); this->sla_prints .update_map_system_profile_renamed(); this->filaments .update_map_system_profile_renamed(); this->sla_materials.update_map_system_profile_renamed(); this->printers .update_map_system_profile_renamed(); - this->prints .update_map_alias_to_profile_name(); + this->fff_prints .update_map_alias_to_profile_name(); this->sla_prints .update_map_alias_to_profile_name(); this->filaments .update_map_alias_to_profile_name(); this->sla_materials.update_map_alias_to_profile_name(); @@ -333,8 +333,8 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p if (preset_type == Preset::TYPE_PRINTER || preset_type == Preset::TYPE_INVALID) return alias; - const PresetCollection& presets = preset_type == Preset::TYPE_FFF_PRINT ? prints : - preset_type == Preset::TYPE_SLA_PRINT ? sla_prints : + const PresetCollection& presets = preset_type == Preset::TYPE_FFF_PRINT ? fff_prints : + preset_type == Preset::TYPE_SLA_PRINT ? sla_prints : preset_type == Preset::TYPE_FFF_FILAMENT ? filaments : sla_materials; @@ -344,8 +344,8 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector& unselected_options) { - PresetCollection& presets = type == Preset::TYPE_FFF_PRINT ? prints : - type == Preset::TYPE_SLA_PRINT ? sla_prints : + PresetCollection& presets = type == Preset::TYPE_FFF_PRINT ? fff_prints : + type == Preset::TYPE_SLA_PRINT ? sla_prints : type == Preset::TYPE_FFF_FILAMENT ? filaments : type == Preset::TYPE_SLA_MATERIAL ? sla_materials : printers; @@ -446,7 +446,7 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr true); // Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found. - prints.select_preset_by_name_strict(initial_print_profile_name); + fff_prints.select_preset_by_name_strict(initial_print_profile_name); filaments.select_preset_by_name_strict(initial_filament_profile_name); sla_prints.select_preset_by_name_strict(initial_sla_print_profile_name); sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name); @@ -485,7 +485,7 @@ void PresetBundle::export_selections(AppConfig &config) assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() >= 1); //assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() > 1 || filaments.get_selected_preset_name() == filament_presets.front()); config.clear_section("presets"); - config.set("presets", "print", prints.get_selected_preset_name()); + config.set("presets", "print", fff_prints.get_selected_preset_name()); config.set("presets", "filament", filament_presets.front()); for (unsigned i = 1; i < filament_presets.size(); ++i) { char name[64]; @@ -521,7 +521,7 @@ DynamicPrintConfig PresetBundle::full_fff_config() const { DynamicPrintConfig out; out.apply(FullPrintConfig::defaults()); - out.apply(this->prints.get_edited_preset().config); + out.apply(this->fff_prints.get_edited_preset().config); // Add the default filament preset to have the "filament_preset_id" defined. out.apply(this->filaments.default_preset().config); out.apply(this->printers.get_edited_preset().config); @@ -533,8 +533,8 @@ DynamicPrintConfig PresetBundle::full_fff_config() const std::vector compatible_printers_condition; std::vector compatible_prints_condition; std::vector inherits; - compatible_printers_condition.emplace_back(this->prints.get_edited_preset().compatible_printers_condition()); - inherits .emplace_back(this->prints.get_edited_preset().inherits()); + compatible_printers_condition.emplace_back(this->fff_prints.get_edited_preset().compatible_printers_condition()); + inherits .emplace_back(this->fff_prints.get_edited_preset().inherits()); if (num_extruders <= 1) { out.apply(this->filaments.get_edited_preset().config); @@ -597,7 +597,7 @@ DynamicPrintConfig PresetBundle::full_fff_config() const opt->value = boost::algorithm::clamp(opt->value, 0, int(num_extruders)); } - out.option("print_settings_id", true)->value = this->prints.get_selected_preset_name(); + out.option("print_settings_id", true)->value = this->fff_prints.get_selected_preset_name(); out.option("filament_settings_id", true)->values = this->filament_presets; out.option("printer_settings_id", true)->value = this->printers.get_selected_preset_name(); out.option("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_name(); @@ -809,7 +809,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool switch (Preset::printer_technology(config)) { case ptFFF: { - load_preset(this->prints, 0, "print_settings_id"); + load_preset(this->fff_prints, 0, "print_settings_id"); load_preset(this->printers, num_extruders + 1, "printer_settings_id"); // 3) Now load the filaments. If there are multiple filament presets, split them and load them. @@ -1052,7 +1052,7 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, co // preset_bundle is set when loading user config bundles, which must not overwrite the system profiles. static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, const PresetBundle *preset_bundle) { - flatten_configbundle_hierarchy(tree, "print", preset_bundle ? preset_bundle->prints.system_preset_names() : std::vector()); + flatten_configbundle_hierarchy(tree, "print", preset_bundle ? preset_bundle->fff_prints.system_preset_names() : std::vector()); flatten_configbundle_hierarchy(tree, "filament", preset_bundle ? preset_bundle->filaments.system_preset_names() : std::vector()); flatten_configbundle_hierarchy(tree, "sla_print", preset_bundle ? preset_bundle->sla_prints.system_preset_names() : std::vector()); flatten_configbundle_hierarchy(tree, "sla_material", preset_bundle ? preset_bundle->sla_materials.system_preset_names() : std::vector()); @@ -1104,7 +1104,7 @@ std::pair PresetBundle::load_configbundle( // 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files. // Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure. - std::vector loaded_prints; + std::vector loaded_fff_prints; std::vector loaded_filaments; std::vector loaded_sla_prints; std::vector loaded_sla_materials; @@ -1126,8 +1126,8 @@ std::pair PresetBundle::load_configbundle( PhysicalPrinterCollection *ph_printers = nullptr; std::string ph_printer_name; if (boost::starts_with(section.first, "print:")) { - presets = &this->prints; - loaded = &loaded_prints; + presets = &this->fff_prints; + loaded = &loaded_fff_prints; preset_name = section.first.substr(6); } else if (boost::starts_with(section.first, "filament:")) { presets = &this->filaments; @@ -1177,7 +1177,7 @@ std::pair PresetBundle::load_configbundle( for (auto &kvp : section.second) { std::vector *dst = nullptr; if (kvp.first == "print") - dst = &this->obsolete_presets.prints; + dst = &this->obsolete_presets.fff_prints; else if (kvp.first == "filament") dst = &this->obsolete_presets.filaments; else if (kvp.first == "sla_print") @@ -1384,7 +1384,7 @@ std::pair PresetBundle::load_configbundle( // 3) Activate the presets and physical printer if any exists. if (! flags.has(LoadConfigBundleAttribute::LoadSystem)) { if (! active_print.empty()) - prints.select_preset_by_name(active_print, true); + fff_prints.select_preset_by_name(active_print, true); if (! active_sla_print.empty()) sla_prints.select_preset_by_name(active_sla_print, true); if (! active_sla_material.empty()) @@ -1554,9 +1554,9 @@ void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_pri assert(printer_preset.config.has("default_print_profile")); assert(printer_preset.config.has("default_filament_profile")); const std::vector &prefered_filament_profiles = printer_preset.config.option("default_filament_profile")->values; - this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, - PreferedPrintProfileMatch(this->prints.get_edited_preset(), printer_preset.config.opt_string("default_print_profile"))); - const PresetWithVendorProfile print_preset_with_vendor_profile = this->prints.get_edited_preset_with_vendor_profile(); + this->fff_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible, + PreferedPrintProfileMatch(this->fff_prints.get_edited_preset(), printer_preset.config.opt_string("default_print_profile"))); + const PresetWithVendorProfile print_preset_with_vendor_profile = this->fff_prints.get_edited_preset_with_vendor_profile(); // Remember whether the filament profiles were compatible before updating the filament compatibility. std::vector filament_preset_was_compatible(this->filament_presets.size(), false); for (size_t idx = 0; idx < this->filament_presets.size(); ++ idx) { @@ -1613,7 +1613,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst // Export the print, filament and printer profiles. for (const PresetCollection *presets : { - (const PresetCollection*)&this->prints, (const PresetCollection*)&this->filaments, + (const PresetCollection*)&this->fff_prints, (const PresetCollection*)&this->filaments, (const PresetCollection*)&this->sla_prints, (const PresetCollection*)&this->sla_materials, (const PresetCollection*)&this->printers }) { for (const Preset &preset : (*presets)()) { @@ -1636,7 +1636,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst // Export the names of the active presets. c << std::endl << "[presets]" << std::endl; - c << "print = " << this->prints.get_selected_preset_name() << std::endl; + c << "print = " << this->fff_prints.get_selected_preset_name() << std::endl; c << "sla_print = " << this->sla_prints.get_selected_preset_name() << std::endl; c << "sla_material = " << this->sla_materials.get_selected_preset_name() << std::endl; c << "printer = " << this->printers.get_selected_preset_name() << std::endl; @@ -1673,7 +1673,7 @@ void PresetBundle::set_filament_preset(size_t idx, const std::string &name) void PresetBundle::set_default_suppressed(bool default_suppressed) { - prints.set_default_suppressed(default_suppressed); + fff_prints.set_default_suppressed(default_suppressed); filaments.set_default_suppressed(default_suppressed); sla_prints.set_default_suppressed(default_suppressed); sla_materials.set_default_suppressed(default_suppressed); diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index cd26a0968..d54cec73a 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -32,10 +32,12 @@ public: // Export selections (current print, current filaments, current printer) into config.ini void export_selections(AppConfig &config); - PresetCollection prints; + PresetCollection fff_prints; PresetCollection sla_prints; PresetCollection filaments; PresetCollection sla_materials; + PresetCollection& prints(PrinterTechnology pt) { return pt == ptFFF ? this->fff_prints : this->sla_prints; } + const PresetCollection& prints(PrinterTechnology pt) const { return pt == ptFFF ? this->fff_prints : this->sla_prints; } PresetCollection& materials(PrinterTechnology pt) { return pt == ptFFF ? this->filaments : this->sla_materials; } const PresetCollection& materials(PrinterTechnology pt) const { return pt == ptFFF ? this->filaments : this->sla_materials; } PrinterPresetCollection printers; @@ -54,7 +56,7 @@ public: VendorMap vendors; struct ObsoletePresets { - std::vector prints; + std::vector fff_prints; std::vector sla_prints; std::vector filaments; std::vector sla_materials; @@ -63,7 +65,7 @@ public: ObsoletePresets obsolete_presets; bool has_defauls_only() const - { return prints.has_defaults_only() && filaments.has_defaults_only() && printers.has_defaults_only(); } + { return fff_prints.has_defaults_only() && filaments.has_defaults_only() && printers.has_defaults_only(); } DynamicPrintConfig full_config() const; // full_config() with the "printhost_apikey" and "printhost_cafile" removed. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c0716d7f5..b83a6bf57 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -291,7 +291,8 @@ bool Print::invalidate_state_by_config_options(const std::vector Print::validate() const double max_layer_height = config().max_layer_height.values[extruder_id]; double nozzle_diameter = config().nozzle_diameter.values[extruder_id]; if (max_layer_height < EPSILON) max_layer_height = nozzle_diameter * 0.75; - double skirt_width = Flow::new_from_config_width(frPerimeter, *Flow::extrusion_option("skirt_extrusion_width", m_default_region_config), (float)m_config.nozzle_diameter.get_at(extruder_id), print_first_layer_height).width; + double skirt_width = Flow::new_from_config_width(frPerimeter, + *Flow::extrusion_option("skirt_extrusion_width", m_default_region_config), + (float)m_config.nozzle_diameter.get_at(extruder_id), + print_first_layer_height, + 1,0 //don't care, all i want if width from width + ).width; //check first layer if (object->region_volumes[region_id].front().first.first < object_first_layer_height) { if (object_first_layer_height + EPSILON < min_layer_height) @@ -1717,7 +1723,9 @@ Flow Print::brim_flow(size_t extruder_id, const PrintObjectConfig& brim_config) frPerimeter, *Flow::extrusion_option("brim_extrusion_width", tempConf), (float)m_config.nozzle_diameter.get_at(extruder_id), - (float)get_first_layer_height() + (float)get_first_layer_height(), + (extruder_id < m_config.nozzle_diameter.values.size()) ? brim_config.get_computed_value("filament_max_overlap", extruder_id) : 1, + 0 ); } @@ -1750,7 +1758,9 @@ Flow Print::skirt_flow(size_t extruder_id, bool first_layer/*=false*/) const frPerimeter, *Flow::extrusion_option("skirt_extrusion_width", m_default_region_config), (float)max_nozzle_diam, - (float)get_first_layer_height() + (float)get_first_layer_height(), + 1, // hard to say what extruder we have here(many) m_default_region_config.get_computed_value("filament_max_overlap", extruder -1), + 0 ); } @@ -2290,7 +2300,7 @@ void Print::_make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolyg else object_islands.emplace_back(brim_offset == 0 ? to_expolygon(expoly.contour) : offset_ex(to_expolygon(expoly.contour), brim_offset)[0]); if (!object->support_layers().empty()) { - Polygons polys = object->support_layers().front()->support_fills.polygons_covered_by_spacing(float(SCALED_EPSILON)); + Polygons polys = object->support_layers().front()->support_fills.polygons_covered_by_spacing(flow.spacing_ratio, float(SCALED_EPSILON)); for (Polygon poly : polys) { object_islands.emplace_back(brim_offset == 0 ? ExPolygon{ poly } : offset_ex(poly, brim_offset)[0]); } @@ -2405,7 +2415,7 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex object_islands.emplace_back(brim_offset == 0 ? to_expolygon(expoly.contour) : offset_ex(to_expolygon(expoly.contour), brim_offset)[0]); if (!object->support_layers().empty()) { - Polygons polys = object->support_layers().front()->support_fills.polygons_covered_by_spacing(float(SCALED_EPSILON)); + Polygons polys = object->support_layers().front()->support_fills.polygons_covered_by_spacing(flow.spacing_ratio, float(SCALED_EPSILON)); for (Polygon poly : polys) { //don't put ears over supports unless it's 100% fill if (object->config().support_material_solid_first_layer) { @@ -2566,7 +2576,7 @@ void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects object_islands.push_back(brim_offset == 0 ? expoly : offset_ex(expoly, brim_offset)[0]); if (!object->support_layers().empty()) { spacing = scaled(object->config().support_material_interface_spacing.value) + support_material_flow(object, float(get_first_layer_height())).scaled_width() * 1.5; - Polygons polys = offset2(object->support_layers().front()->support_fills.polygons_covered_by_spacing(float(SCALED_EPSILON)), spacing, -spacing); + Polygons polys = offset2(object->support_layers().front()->support_fills.polygons_covered_by_spacing(flow.spacing_ratio, float(SCALED_EPSILON)), spacing, -spacing); for (Polygon poly : polys) { object_islands.push_back(brim_offset == 0 ? ExPolygon{ poly } : offset_ex(poly, brim_offset)[0]); } @@ -2718,7 +2728,8 @@ Polygons Print::first_layer_islands() const for (ExPolygon &expoly : object->m_layers.front()->lslices) 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)); + //was polygons_covered_by_spacing, but is it really important? + object->support_layers().front()->support_fills.polygons_covered_by_width(object_islands, float(SCALED_EPSILON)); islands.reserve(islands.size() + object_islands.size() * object->instances().size()); for (const PrintInstance &instance : object->instances()) for (Polygon &poly : object_islands) { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index e875d8e29..72ab45c5b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1558,15 +1558,28 @@ void PrintConfigDef::init_fff_params() def = this->add("filament_shrink", coPercents); def->label = L("Shrinkage"); def->tooltip = L("Enter the shrinkage percentage that the filament will get after cooling (94% if you measure 94mm instead of 100mm)." - " The part will be scaled in xy to compensate." - " Only the filament used for the perimeter is taken into account." - "\nBe sure to allow enough space between objects, as this compensation is done after the checks."); + " The part will be scaled in xy to compensate." + " Only the filament used for the perimeter is taken into account." + "\nBe sure to allow enough space between objects, as this compensation is done after the checks."); def->sidetext = L("%"); + def->ratio_over = ""; def->min = 10; def->mode = comExpert; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionPercents{ 100 }); + def = this->add("filament_max_overlap", coPercents); + def->label = L("Max line overlap"); + def->tooltip = L("This settign will ensure that all overlap are no hgher than this value." + " This is useful for filament that are too viscous, as the line can't flow under the previous one."); + def->sidetext = L("%"); + def->ratio_over = ""; + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionPercents{ 100 }); + def = this->add("filament_density", coFloats); def->label = L("Density"); def->category = OptionCategory::filament; @@ -5678,6 +5691,7 @@ std::unordered_set prusa_export_to_remove_keys = { "filament_max_speed", "filament_max_wipe_tower_speed", "filament_melt_zone_pause", +"filament_max_overlap", "filament_shrink", "filament_skinnydip_distance", "filament_toolchange_part_fan_speed", @@ -5962,13 +5976,17 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei if (skirts > 0 && ref_height == 0) skirts += config->option("skirt_brim")->getInt(); if (skirts > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) { + float overlap_ratio = 1; + if (config->option("filament_max_overlap")) overlap_ratio = config->get_computed_value("filament_max_overlap"); if (ref_height == 0) { skirt_dist = config->option("skirt_distance")->getFloat(); Flow skirt_flow = Flow::new_from_config_width( frPerimeter, *Flow::extrusion_option("skirt_extrusion_width", *config), (float)max_nozzle_diam, - (float)first_layer_height + (float)first_layer_height, + overlap_ratio, + 0 ); skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1)); base_dist = std::max(base_dist, skirt_dist + 1); @@ -5982,7 +6000,9 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei frPerimeter, *Flow::extrusion_option("skirt_extrusion_width", *config), (float)max_nozzle_diam, - (float)first_layer_height + (float)first_layer_height, + overlap_ratio, + 0 ); skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1)); } @@ -6112,7 +6132,7 @@ std::string DynamicPrintConfig::validate() } template -const TYPE* find_option(const t_config_option_key &opt_key, DynamicPrintConfig* default_config, const std::vector &other_config) { +const TYPE* find_option(const t_config_option_key &opt_key, DynamicPrintConfig* default_config, const std::vector &other_config) { const TYPE* option = default_config->option(opt_key); if (option) return option; @@ -6124,8 +6144,8 @@ const TYPE* find_option(const t_config_option_key &opt_key, DynamicPrintConfig* return nullptr; } -bool DynamicPrintConfig::update_phony(const std::vector config_collection) { - bool something_changed = false; +std::set DynamicPrintConfig::update_phony(const std::vector config_collection) { + std::set something_changed; //update width/spacing links const char* widths[] = { "", "external_perimeter_", "perimeter_", "infill_", "solid_infill_", "top_infill_", "support_material_", "first_layer_", "skirt_" }; for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++i) { @@ -6135,21 +6155,34 @@ bool DynamicPrintConfig::update_phony(const std::vectoroption(key_width); ConfigOptionFloatOrPercent* spacing_option = this->option(key_spacing); - if (width_option && spacing_option) + if (width_option && spacing_option){ + std::set returned_values; if (!spacing_option->is_phony() && width_option->is_phony()) - something_changed |= value_changed(key_spacing, config_collection); - else - something_changed |= value_changed(key_width, config_collection); + returned_values = value_changed(key_spacing, config_collection); + else + returned_values = value_changed(key_width, config_collection); + something_changed.insert(returned_values.begin(), returned_values.end()); + } } return something_changed; } //note: width<-> spacing conversion is done via float, so max 6-7 digit of precision. -bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const std::vector config_collection) { +std::set DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const std::vector config_collection) { if (opt_key == "layer_height") { - update_phony(config_collection); + if (!update_phony(config_collection).empty()) + return { this }; + return {}; + } + if (opt_key == "filament_max_overlap") { + for (auto conf : config_collection) { + if (conf->option("extrusion_width")) + if (!conf->update_phony(config_collection).empty()) + return { conf }; + } + return {}; } bool something_changed = false; @@ -6164,7 +6197,10 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const for (double dmr : nozzle_diameter_option->values) max_nozzle_diameter = std::max(max_nozzle_diameter, dmr); double spacing_value = spacing_option->get_abs_value(max_nozzle_diameter); - Flow flow = Flow::new_from_spacing(spacing_value, max_nozzle_diameter,layer_height_option->value, false); + float overlap_ratio = 1; + const ConfigOptionPercents* filament_max_overlap_option = find_option("filament_max_overlap", this, config_collection); + if (filament_max_overlap_option) overlap_ratio = filament_max_overlap_option->get_abs_value(0, 1.); + Flow flow = Flow::new_from_spacing(spacing_value, max_nozzle_diameter,layer_height_option->value, overlap_ratio, false); //test for valid height. If too high, revert to round shape if (flow.height > spacing_value / (1 - (1. - 0.25 * PI) * flow.spacing_ratio)) { flow.width = spacing_value / (1 - (1. - 0.25 * PI) * flow.spacing_ratio); @@ -6196,7 +6232,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option && perimeter_overlap_option) { width_option->set_phony(true); spacing_option->set_phony(false); - flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1); + flow.spacing_ratio = std::min(flow.spacing_ratio, float(perimeter_overlap_option->get_abs_value(1))); flow.width = spacing_option->get_abs_value(max_nozzle_diameter) + layer_height_option->value * (1. - 0.25 * PI) * flow.spacing_ratio; width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000); width_option->percent = spacing_option->percent; @@ -6204,12 +6240,13 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const } } if (opt_key == "external_perimeter_extrusion_spacing") { + const ConfigOptionPercent* perimeter_overlap_option = find_option("perimeter_overlap", this, config_collection); const ConfigOptionPercent* external_perimeter_overlap_option = find_option("external_perimeter_overlap", this, config_collection); ConfigOptionFloatOrPercent* width_option = this->option("external_perimeter_extrusion_width"); if (width_option && external_perimeter_overlap_option) { width_option->set_phony(true); spacing_option->set_phony(false); - flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5); + flow.spacing_ratio = std::min(flow.spacing_ratio * 0.5f, float(external_perimeter_overlap_option->get_abs_value(0.25) + perimeter_overlap_option->get_abs_value(0.25))); flow.width = spacing_option->get_abs_value(max_nozzle_diameter) + layer_height_option->value * (1. - 0.25 * PI) * flow.spacing_ratio; width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000); width_option->percent = spacing_option->percent; @@ -6266,6 +6303,9 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const const ConfigOptionFloats* nozzle_diameter_option = find_option("nozzle_diameter", this, config_collection); const ConfigOptionFloat* layer_height_option = find_option("layer_height", this, config_collection); ConfigOptionFloatOrPercent* width_option = this->option(opt_key); + float overlap_ratio = 1; + const ConfigOptionPercents* filament_max_overlap_option = find_option("filament_max_overlap", this, config_collection); + if (filament_max_overlap_option) overlap_ratio = filament_max_overlap_option->get_abs_value(0, 1.); if (layer_height_option && width_option && nozzle_diameter_option) { //compute spacing with current height and change the width float max_nozzle_diameter = 0; @@ -6278,7 +6318,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; @@ -6290,7 +6330,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; @@ -6303,23 +6343,24 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option && perimeter_overlap_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; - flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1); + flow.spacing_ratio = std::min(flow.spacing_ratio, (float)perimeter_overlap_option->get_abs_value(1)); spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; something_changed = true; } } if (opt_key == "external_perimeter_extrusion_width") { + const ConfigOptionPercent* perimeter_overlap_option = find_option("perimeter_overlap", this, config_collection); const ConfigOptionPercent* external_perimeter_overlap_option = find_option("external_perimeter_overlap", this, config_collection); spacing_option = this->option("external_perimeter_extrusion_spacing"); if (width_option && external_perimeter_overlap_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (ext_perimeter_flow.width < ext_perimeter_flow.height) ext_perimeter_flow.height = ext_perimeter_flow.width; - ext_perimeter_flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5); + ext_perimeter_flow.spacing_ratio = std::min(ext_perimeter_flow.spacing_ratio * 0.5f, float(external_perimeter_overlap_option->get_abs_value(0.25) + perimeter_overlap_option->get_abs_value(0.25))); spacing_option->value = (width_option->percent) ? std::round(100 * ext_perimeter_flow.spacing() / max_nozzle_diameter) : (std::round(ext_perimeter_flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; something_changed = true; @@ -6330,7 +6371,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; @@ -6342,7 +6383,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; @@ -6354,7 +6395,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const if (width_option) { width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); if (flow.width < flow.height) flow.height = flow.width; spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; @@ -6383,7 +6424,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const spacing_option->set_phony(false); spacing_option->value = 100; spacing_option->percent = true; - Flow flow = Flow::new_from_spacing(spacing_option->get_abs_value(max_nozzle_diameter), max_nozzle_diameter, layer_height_option->value, false); + Flow flow = Flow::new_from_spacing(spacing_option->get_abs_value(max_nozzle_diameter), max_nozzle_diameter, layer_height_option->value, overlap_ratio, false); width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000); width_option->percent = spacing_option->percent; something_changed = true; @@ -6392,7 +6433,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const width_option->percent = true; width_option->set_phony(false); spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, overlap_ratio, 0); spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); spacing_option->percent = width_option->percent; something_changed = true; @@ -6400,7 +6441,9 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const } } } - return something_changed; + if(something_changed) + return { this }; + return {}; } //FIXME localize this function. diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index ea6f18673..a15d1a0ec 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -468,8 +468,9 @@ public: /// callback to changed other settings that are linked (like width & spacing) /// /// name of the changed option - bool value_changed(const t_config_option_key& opt_key, const std::vector config_collection); - bool update_phony(const std::vector config_collection); + /// configs that have at least a change + std::set value_changed(const t_config_option_key& opt_key, const std::vector config_collection); + std::set update_phony(const std::vector config_collection); }; class StaticPrintConfig : public StaticConfig @@ -1304,6 +1305,7 @@ public: ConfigOptionInts fan_below_layer_time; ConfigOptionStrings filament_colour; ConfigOptionStrings filament_notes; + ConfigOptionPercents filament_max_overlap; ConfigOptionPercents filament_shrink; ConfigOptionFloatOrPercent first_layer_acceleration; ConfigOptionInts first_layer_bed_temperature; @@ -1405,6 +1407,7 @@ protected: OPT_PTR(fan_below_layer_time); OPT_PTR(filament_colour); OPT_PTR(filament_notes); + OPT_PTR(filament_max_overlap); OPT_PTR(filament_shrink); OPT_PTR(first_layer_acceleration); OPT_PTR(first_layer_bed_temperature); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 3296f3eb6..6d78a58b8 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -861,6 +861,7 @@ namespace Slic3r { || opt_key == "external_perimeter_overlap" || opt_key == "gap_fill_overlap" || opt_key == "no_perimeter_unsupported_algo" + || opt_key == "filament_max_overlap" || opt_key == "perimeters" || opt_key == "perimeter_overlap" || opt_key == "solid_infill_extrusion_spacing" diff --git a/src/libslic3r/PrintRegion.cpp b/src/libslic3r/PrintRegion.cpp index 94f1a65f3..1f5b6783f 100644 --- a/src/libslic3r/PrintRegion.cpp +++ b/src/libslic3r/PrintRegion.cpp @@ -55,7 +55,9 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir // Get the configured nozzle_diameter for the extruder associated to the flow role requested. // Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right. double nozzle_diameter = m_print->config().nozzle_diameter.get_at(this->extruder(role, object) - 1); - return Flow::new_from_config_width(role, config_width, (float)nozzle_diameter, (float)layer_height, bridge ? (float)m_config.bridge_flow_ratio.get_abs_value(1) : 0.0f); + return Flow::new_from_config_width(role, config_width, (float)nozzle_diameter, (float)layer_height, + this->config().get_computed_value("filament_max_overlap", this->extruder(role, object) - 1), + bridge ? (float)m_config.bridge_flow_ratio.get_abs_value(1) : 0.0f); } float PrintRegion::width(FlowRole role, bool first_layer, const PrintObject& object) const diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index f7d751b14..c8e8d2f2a 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -3051,7 +3051,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( //FIXME misusing contact_polygons for support columns. ((raft_layer.contact_polygons == nullptr) ? Polygons() : *raft_layer.contact_polygons); if (! to_infill_polygons.empty()) { - Flow flow(float(m_support_material_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, raft_layer.bridging); + Flow flow(float(m_support_material_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, m_support_material_flow.spacing_ratio, raft_layer.bridging); // find centerline of the external loop/extrusions ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ? // union_ex(base_polygons, true) : @@ -3108,7 +3108,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // We don't use $base_flow->spacing because we need a constant spacing // value that guarantees that all layers are correctly aligned. spacing = m_support_material_flow.spacing(); - flow = Flow(float(m_support_material_interface_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, raft_layer.bridging); + flow = Flow(float(m_support_material_interface_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, m_support_material_flow.spacing_ratio, raft_layer.bridging); density = float(interface_density); } else continue; @@ -3225,6 +3225,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( float(layer_ex.layer->bridging ? layer_ex.layer->height : (interface_as_base ? m_support_material_flow.width : m_support_material_interface_flow.width)), float(layer_ex.layer->height), m_support_material_interface_flow.nozzle_diameter, + m_support_material_interface_flow.spacing_ratio, layer_ex.layer->bridging); Fill *filler = i == 2 ? filler_intermediate_interface.get() : filler_interface.get(); float density = interface_density; @@ -3267,6 +3268,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( float(base_layer.layer->bridging ? base_layer.layer->height : m_support_material_flow.width), float(base_layer.layer->height), m_support_material_flow.nozzle_diameter, + m_support_material_flow.spacing_ratio, base_layer.layer->bridging); coordf_t spacing = m_support_material_flow.spacing(); filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / support_density)); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 532c5d29b..c115a5e2e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -339,7 +339,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("fill_pattern", new ConfigOptionEnum(ipRectilinear)); fill_density = 100; } else - fill_density = wxGetApp().preset_bundle->prints.get_selected_preset().config.option("fill_density")->value; + fill_density = wxGetApp().preset_bundle->fff_prints.get_selected_preset().config.option("fill_density")->value; new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density)); apply(config, &new_conf); if (cb_value_change) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 2fc92f503..f020e739a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2778,7 +2778,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized) const PrintConfig& config = print.config(); size_t extruders_count = config.nozzle_diameter.size(); if ((extruders_count > 1) && config.wipe_tower && !config.complete_objects) { - const DynamicPrintConfig& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig& print_config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; double layer_height = print_config.opt_float("layer_height"); double first_layer_height = print_config.get_abs_value("first_layer_height", layer_height); double nozzle_diameter = print.config().nozzle_diameter.values[0]; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2157709e9..9abb4915e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2245,7 +2245,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const Print *print = m_process->fff_print(); - const DynamicPrintConfig &print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig &print_config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; double layer_height = print_config.opt_float("layer_height"); double first_layer_height = print_config.get_abs_value("first_layer_height", layer_height); double nozzle_diameter = print->config().nozzle_diameter.values[0]; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 670d88661..a06231ef5 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1495,9 +1495,7 @@ void ObjectList::get_settings_choice(const wxString& category_name) for (auto sel : selections) selected_options.push_back((*settings_list)[sel].first); - const DynamicPrintConfig& from_config = printer_technology() == ptFFF ? - wxGetApp().preset_bundle->prints.get_edited_preset().config : - wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; + const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints(printer_technology()).get_edited_preset().config; for (auto& setting : (*settings_list)) { @@ -1562,7 +1560,7 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) _(L("Add Settings Bundle for Object")); take_snapshot(snapshot_text); - const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints(printer_technology()).get_edited_preset().config; for (auto& opt_key : options) { if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end()) { @@ -2830,7 +2828,7 @@ DynamicPrintConfig ObjectList::get_default_layer_config(const int obj_idx) DynamicPrintConfig config; coordf_t layer_height = object(obj_idx)->config.has("layer_height") ? object(obj_idx)->config.opt_float("layer_height") : - wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("layer_height"); + wxGetApp().preset_bundle->prints(printer_technology()).get_edited_preset().config.opt_float("layer_height"); config.set_key_value("layer_height",new ConfigOptionFloat(layer_height)); config.set_key_value("extruder", new ConfigOptionInt(0)); diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index dbd3bc4a9..d2217f2ab 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -212,9 +212,7 @@ void ObjectSettings::update_config_values(ModelConfig* config) return; // update config values according to configuration hierarchy - DynamicPrintConfig main_config = printer_technology == ptFFF ? - wxGetApp().preset_bundle->prints.get_edited_preset().config : - wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; + DynamicPrintConfig main_config = wxGetApp().preset_bundle->prints(printer_technology).get_edited_preset().config; auto load_config = [this, config, &main_config]() { diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 207b8f597..6a711f7f6 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -644,7 +644,7 @@ wxBoxSizer* Preview::create_layers_slider_sizer() m_layers_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100); m_layers_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA, - wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects")); + wxGetApp().preset_bundle->fff_prints.get_edited_preset().config.opt_bool("complete_objects")); m_layers_slider->enable_action_icon(wxGetApp().is_editor()); sizer->Add(m_layers_slider, 0, wxEXPAND, 0); @@ -783,7 +783,7 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee m_layers_slider->SetTicksValues(ticks_info_from_model); bool sla_print_technology = plater->printer_technology() == ptSLA; - bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects"); + bool sequential_print = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config.opt_bool("complete_objects"); m_layers_slider->SetDrawMode(sla_print_technology, sequential_print); m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config()); if (sla_print_technology) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 266212877..a3b8af809 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -236,7 +236,7 @@ void GLGizmosManager::update_data() } else if (is_wipe_tower) { - DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + DynamicPrintConfig& config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; set_scale(Vec3d::Ones()); set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast(config.option("wipe_tower_rotation_angle"))->value)); set_flattening_data(nullptr); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fcd568603..a3e099e5a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -292,7 +292,7 @@ void FreqChangedParams::msw_rescale() FreqChangedParams::FreqChangedParams(wxWindow* parent) : OG_Settings(parent, false) { - DynamicPrintConfig* config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; + DynamicPrintConfig* config = &wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; // Frequently changed parameters for FFF_technology m_og->set_config(config); @@ -4660,7 +4660,7 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config. // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config. if (this->printer_technology == ptFFF) { - const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig &config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y")); model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); } @@ -4716,7 +4716,7 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config. // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config. if (this->printer_technology == ptFFF) { - const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig &config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y")); model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); } @@ -4772,7 +4772,7 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator //FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower. // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config. if (this->printer_technology == ptFFF) { - const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->fff_prints.get_edited_preset().config; Vec2d current_position(current_config.opt_float("wipe_tower_x"), current_config.opt_float("wipe_tower_y")); double current_rotation = current_config.opt_float("wipe_tower_rotation_angle"); if (current_position != model.wipe_tower.position || current_rotation != model.wipe_tower.rotation) { diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index d5ac676a9..e85b468c3 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -79,7 +79,7 @@ PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const switch (m_type) { case Preset::TYPE_FFF_PRINT: { - m_collection = &m_preset_bundle->prints; + m_collection = &m_preset_bundle->fff_prints; m_main_bitmap_name = "cog"; break; } diff --git a/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp index 0955bbcd9..74cab20a0 100644 --- a/src/slic3r/GUI/PresetHints.cpp +++ b/src/slic3r/GUI/PresetHints.cpp @@ -161,9 +161,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle // The current filament preset is not active for any extruder. idx_extruder = -1; - const DynamicPrintConfig &print_config = preset_bundle.prints .get_edited_preset().config; - const DynamicPrintConfig &filament_config = preset_bundle.filaments.get_edited_preset().config; - const DynamicPrintConfig &printer_config = preset_bundle.printers .get_edited_preset().config; + const DynamicPrintConfig &print_config = preset_bundle.fff_prints.get_edited_preset().config; + const DynamicPrintConfig &filament_config = preset_bundle.filaments .get_edited_preset().config; + const DynamicPrintConfig &printer_config = preset_bundle.printers .get_edited_preset().config; // Current printer values. float nozzle_diameter = (float)printer_config.opt_float("nozzle_diameter", idx_extruder); @@ -249,13 +249,15 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle } return (speed_normal > 0.) ? speed_normal : speed_max; }; + float filament_max_overlap = filament_config.get_computed_value("filament_max_overlap", std::max(0, idx_extruder)); if (perimeter_extruder_active) { Flow external_flow = Flow::new_from_config_width(frExternalPerimeter, first_positive(first_layer_extrusion_width_ptr, external_perimeter_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + std::min(filament_max_overlap, (float)print_config.opt("external_perimeter_overlap")->get_abs_value(1)), + bfr); if (external_flow.height > external_flow.width) external_flow.height = external_flow.width; - external_flow.spacing_ratio = print_config.opt("external_perimeter_overlap")->get_abs_value(1); double external_perimeter_rate = external_flow.mm3_per_mm() * (bridging ? bridge_speed : limit_by_first_layer_speed(std::max(external_perimeter_speed, small_perimeter_speed), max_print_speed)); @@ -265,10 +267,11 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle } Flow perimeter_flow = Flow::new_from_config_width(frPerimeter, first_positive(first_layer_extrusion_width_ptr, perimeter_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + std::min(filament_max_overlap, (float)print_config.opt("perimeter_overlap")->get_abs_value(1)), + bfr); if (perimeter_flow.height > perimeter_flow.width) perimeter_flow.height = perimeter_flow.width; - perimeter_flow.spacing_ratio = print_config.opt("perimeter_overlap")->get_abs_value(1); double perimeter_rate = perimeter_flow.mm3_per_mm() * (bridging ? bridge_speed : limit_by_first_layer_speed(std::max(perimeter_speed, small_perimeter_speed), max_print_speed)); @@ -280,7 +283,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (! bridging && infill_extruder_active) { Flow infill_flow = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, infill_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + filament_max_overlap, + bfr); if (infill_flow.height > infill_flow.width) infill_flow.height = infill_flow.width; double infill_rate = infill_flow.mm3_per_mm() * limit_infill_by_first_layer_speed(infill_speed, max_print_speed); @@ -292,7 +297,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (solid_infill_extruder_active) { Flow solid_infill_flow = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, solid_infill_extrusion_width, extrusion_width), - nozzle_diameter, lh, 0); + nozzle_diameter, lh, + filament_max_overlap, + 0); if (solid_infill_flow.height > solid_infill_flow.width) solid_infill_flow.height = solid_infill_flow.width; double solid_infill_rate = solid_infill_flow.mm3_per_mm() * @@ -304,7 +311,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (! bridging) { Flow top_solid_infill_flow = Flow::new_from_config_width(frInfill, first_positive(first_layer_extrusion_width_ptr, top_infill_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + filament_max_overlap, + bfr); if (top_solid_infill_flow.height > top_solid_infill_flow.width) top_solid_infill_flow.height = top_solid_infill_flow.width; double top_solid_infill_rate = top_solid_infill_flow.mm3_per_mm() * limit_infill_by_first_layer_speed(top_solid_infill_speed, max_print_speed); @@ -317,7 +326,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (support_material_extruder_active) { Flow support_material_flow = Flow::new_from_config_width(frSupportMaterial, first_positive(first_layer_extrusion_width_ptr, support_material_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + filament_max_overlap, + bfr); if (support_material_flow.height > support_material_flow.width) support_material_flow.height = support_material_flow.width; double support_material_rate = support_material_flow.mm3_per_mm() * @@ -330,7 +341,9 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle if (support_material_interface_extruder_active) { Flow support_material_interface_flow = Flow::new_from_config_width(frSupportMaterialInterface, first_positive(first_layer_extrusion_width_ptr, support_material_extrusion_width, extrusion_width), - nozzle_diameter, lh, bfr); + nozzle_diameter, lh, + filament_max_overlap, + bfr); if (support_material_interface_flow.height > support_material_interface_flow.width) support_material_interface_flow.height = support_material_interface_flow.width; double support_material_interface_rate = support_material_interface_flow.mm3_per_mm() * @@ -363,7 +376,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle& preset_bundle) { - const DynamicPrintConfig& print_config = preset_bundle.prints.get_edited_preset().config; + const DynamicPrintConfig& print_config = preset_bundle.fff_prints.get_edited_preset().config; const DynamicPrintConfig& printer_config = preset_bundle.printers.get_edited_preset().config; float layer_height = float(print_config.opt_float("layer_height")); @@ -377,14 +390,22 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle& pre return out; } + const DynamicPrintConfig& filament_config = preset_bundle.filaments.get_edited_preset().config; + float filament_max_overlap = filament_config.get_computed_value("filament_max_overlap", 0); Flow external_perimeter_flow = Flow::new_from_config_width( frExternalPerimeter, *print_config.opt("external_perimeter_extrusion_width"), - nozzle_diameter, layer_height, false); + nozzle_diameter, + layer_height, + filament_max_overlap, + false); Flow perimeter_flow = Flow::new_from_config_width( frPerimeter, *print_config.opt("perimeter_extrusion_width"), - nozzle_diameter, layer_height, false); + nozzle_diameter, + layer_height, + filament_max_overlap, + false); // failsafe for too big height if (external_perimeter_flow.height > external_perimeter_flow.width) @@ -421,7 +442,7 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle& pre std::string PresetHints::recommended_extrusion_width(const PresetBundle& preset_bundle) { - const DynamicPrintConfig& print_config = preset_bundle.prints.get_edited_preset().config; + const DynamicPrintConfig& print_config = preset_bundle.fff_prints.get_edited_preset().config; const DynamicPrintConfig& printer_config = preset_bundle.printers.get_edited_preset().config; int nb_nozzles = printer_config.option("nozzle_diameter")->values.size(); @@ -434,8 +455,10 @@ std::string PresetHints::recommended_extrusion_width(const PresetBundle& preset_ std::string out; - Flow first_layer_flow = Flow::new_from_spacing(nozzle_diameter, nozzle_diameter, first_layer_height, false); - Flow layer_flow = Flow::new_from_spacing(nozzle_diameter, nozzle_diameter, layer_height, false); + const DynamicPrintConfig& filament_config = preset_bundle.filaments.get_edited_preset().config; + float filament_max_overlap = filament_config.get_computed_value("filament_max_overlap", 0); + Flow first_layer_flow = Flow::new_from_spacing(nozzle_diameter, nozzle_diameter, first_layer_height, filament_max_overlap, false); + Flow layer_flow = Flow::new_from_spacing(nozzle_diameter, nozzle_diameter, layer_height, filament_max_overlap, false); out += _utf8(L("Ideally, the spacing between two extrusions shouldn't be lower than the nozzle diameter. Below are the extrusion widths for a spacing equal to the nozzle diameter.\n")); out += (boost::format(_utf8(L("Recommended min extrusion width for the first layer (with a first layer height of %1%) is %2$.3f mm (or %3%%%)\n"))) @@ -452,8 +475,8 @@ std::string PresetHints::recommended_extrusion_width(const PresetBundle& preset_ // on the active layer height. std::string PresetHints::top_bottom_shell_thickness_explanation(const PresetBundle &preset_bundle) { - const DynamicPrintConfig &print_config = preset_bundle.prints .get_edited_preset().config; - const DynamicPrintConfig &printer_config = preset_bundle.printers .get_edited_preset().config; + const DynamicPrintConfig &print_config = preset_bundle.fff_prints.get_edited_preset().config; + const DynamicPrintConfig &printer_config = preset_bundle.printers .get_edited_preset().config; std::string out; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 5ea82a7dd..bb451140e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1187,20 +1187,47 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) //wxGetApp().preset_bundle->value_changed(opt_key); // update phony fields - if (m_config->value_changed(opt_key, { wxGetApp().plater()->config() })) { + + //auto thing = wxGetApp().plater()-> + std::set changed = m_config->value_changed(opt_key, { + &wxGetApp().preset_bundle->prints(wxGetApp().plater()->printer_technology()).get_edited_preset().config, + &wxGetApp().preset_bundle->materials(wxGetApp().plater()->printer_technology()).get_edited_preset().config, + &wxGetApp().preset_bundle->printers.get_edited_preset().config, + /*&wxGetApp().preset_bundle->full_config()*/ }); + if (changed.find(m_config) != changed.end()) { update_dirty(); //# Initialize UI components with the config values. reload_config(); } + if (changed.find(&wxGetApp().preset_bundle->fff_prints.get_edited_preset().config) != changed.end()) { + wxGetApp().get_tab(Preset::Type::TYPE_FFF_PRINT)->update_dirty(); + wxGetApp().get_tab(Preset::Type::TYPE_FFF_PRINT)->reload_config(); + } + if (changed.find(&wxGetApp().preset_bundle->sla_prints.get_edited_preset().config) != changed.end()) { + wxGetApp().get_tab(Preset::Type::TYPE_SLA_PRINT)->update_dirty(); + wxGetApp().get_tab(Preset::Type::TYPE_SLA_PRINT)->reload_config(); + } + if (changed.find(&wxGetApp().preset_bundle->filaments.get_edited_preset().config) != changed.end()) { + wxGetApp().get_tab(Preset::Type::TYPE_FFF_FILAMENT)->update_dirty(); + wxGetApp().get_tab(Preset::Type::TYPE_FFF_FILAMENT)->reload_config(); + } + if (changed.find(&wxGetApp().preset_bundle->sla_materials.get_edited_preset().config) != changed.end()) { + wxGetApp().get_tab(Preset::Type::TYPE_SLA_MATERIAL)->update_dirty(); + wxGetApp().get_tab(Preset::Type::TYPE_SLA_MATERIAL)->reload_config(); + } + if (changed.find(&wxGetApp().preset_bundle->printers.get_edited_preset().config) != changed.end()) { + wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->update_dirty(); + wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->reload_config(); + } update(); } // Show/hide the 'purging volumes' button void Tab::update_wiping_button_visibility() { - if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + if (m_preset_bundle->printers.get_selected_preset().printer_technology() != ptFFF) return; // ys_FIXME - bool wipe_tower_enabled = dynamic_cast( (m_preset_bundle->prints.get_edited_preset().config ).option("wipe_tower"))->value; + bool wipe_tower_enabled = dynamic_cast( (m_preset_bundle->fff_prints.get_edited_preset().config ).option("wipe_tower"))->value; bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; auto wiping_dialog_button = wxGetApp().sidebar().get_wiping_dialog_button(); @@ -2129,7 +2156,7 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page) void TabPrint::build() { - m_presets = &m_preset_bundle->prints; + m_presets = &m_preset_bundle->fff_prints; load_initial_data(); if (create_pages("print.ui")) return; @@ -3128,7 +3155,11 @@ void Tab::load_current_preset() //update width/spacing links if (m_type == Preset::TYPE_FFF_PRINT) { //verify that spacings are set - if (m_config && m_config->update_phony({ wxGetApp().plater()->config() })) { + if (m_config && !m_config->update_phony({ + &wxGetApp().preset_bundle->prints(wxGetApp().plater()->printer_technology()).get_edited_preset().config, + &wxGetApp().preset_bundle->materials(wxGetApp().plater()->printer_technology()).get_edited_preset().config, + &wxGetApp().preset_bundle->printers.get_edited_preset().config + }).empty()) { update_dirty(); reload_config(); } @@ -3273,9 +3304,9 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, bool new_preset_compatible; }; std::vector updates = { - { Preset::Type::TYPE_FFF_PRINT, &m_preset_bundle->prints, ptFFF }, + { Preset::Type::TYPE_FFF_PRINT, &m_preset_bundle->fff_prints, ptFFF }, { Preset::Type::TYPE_SLA_PRINT, &m_preset_bundle->sla_prints, ptSLA }, - { Preset::Type::TYPE_FFF_FILAMENT, &m_preset_bundle->filaments, ptFFF }, + { Preset::Type::TYPE_FFF_FILAMENT, &m_preset_bundle->filaments, ptFFF }, { Preset::Type::TYPE_SLA_MATERIAL, &m_preset_bundle->sla_materials,ptSLA } }; for (PresetUpdate &pu : updates) { @@ -3382,8 +3413,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, wxGetApp().mainframe->plater()->canvas3D()->set_arrange_settings(m_presets->get_edited_preset().config, m_presets->get_edited_preset().printer_technology()); } if (m_type == Preset::TYPE_PRINTER) { - wxGetApp().mainframe->plater()->canvas3D()->set_arrange_settings(m_preset_bundle->prints.get_edited_preset().config, m_presets->get_edited_preset().printer_technology()); - + wxGetApp().mainframe->plater()->canvas3D()->set_arrange_settings(m_preset_bundle->prints(m_presets->get_edited_preset().printer_technology()).get_edited_preset().config, m_presets->get_edited_preset().printer_technology()); } } @@ -3805,8 +3835,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep { // Collect names of non-default non-external profiles. PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); - PresetCollection &depending_presets = (deps.type == Preset::TYPE_PRINTER) ? m_preset_bundle->printers : - (printer_technology == ptFFF) ? m_preset_bundle->prints : m_preset_bundle->sla_prints; + PresetCollection &depending_presets = (deps.type == Preset::TYPE_PRINTER) ? m_preset_bundle->printers : m_preset_bundle->prints(printer_technology); wxArrayString presets; for (size_t idx = 0; idx < depending_presets.size(); ++ idx) { diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 076504243..bf952bb8c 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -677,21 +677,21 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons // Throw when parsing invalid configuration. Only valid configuration is supposed to be provided over the air. bundle.load_configbundle(update.source.string(), PresetBundle::LoadConfigBundleAttribute::LoadSystem, ForwardCompatibilitySubstitutionRule::Disable); - BOOST_LOG_TRIVIAL(info) << format("Deleting %1% conflicting presets", bundle.prints.size() + bundle.filaments.size() + bundle.printers.size()); + BOOST_LOG_TRIVIAL(info) << format("Deleting %1% conflicting presets", bundle.fff_prints.size() + bundle.filaments.size() + bundle.printers.size()); auto preset_remover = [](const Preset &preset) { BOOST_LOG_TRIVIAL(info) << '\t' << preset.file; fs::remove(preset.file); }; - for (const auto &preset : bundle.prints) { preset_remover(preset); } + for (const auto &preset : bundle.fff_prints){ preset_remover(preset); } for (const auto &preset : bundle.filaments) { preset_remover(preset); } for (const auto &preset : bundle.printers) { preset_remover(preset); } // Also apply the `obsolete_presets` property, removing obsolete ini files BOOST_LOG_TRIVIAL(info) << format("Deleting %1% obsolete presets", - bundle.obsolete_presets.prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size()); + bundle.obsolete_presets.fff_prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size()); auto obsolete_remover = [](const char *subdir, const std::string &preset) { auto path = fs::path(Slic3r::data_dir()) / subdir / preset; @@ -700,7 +700,7 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons fs::remove(path); }; - for (const auto &name : bundle.obsolete_presets.prints) { obsolete_remover("print", name); } + for (const auto &name : bundle.obsolete_presets.fff_prints) { obsolete_remover("print", name); } for (const auto &name : bundle.obsolete_presets.filaments) { obsolete_remover("filament", name); } for (const auto &name : bundle.obsolete_presets.sla_prints) { obsolete_remover("sla_print", name); } for (const auto &name : bundle.obsolete_presets.sla_materials/*filaments*/) { obsolete_remover("sla_material", name); }