diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index c0d08c84b7..c482f7edba 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -312,6 +312,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role) case erOverhangPerimeter : return L("Overhang perimeter"); case erInternalInfill : return L("Internal infill"); case erSolidInfill : return L("Solid infill"); + case erIroning : return L("Ironing"); case erTopSolidInfill : return L("Top solid infill"); case erBridgeInfill : return L("Bridge infill"); case erGapFill : return L("Gap fill"); diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index b76991f1cc..879f564b6c 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -22,6 +22,7 @@ enum ExtrusionRole : uint8_t { erInternalInfill, erSolidInfill, erTopSolidInfill, + erIroning, erBridgeInfill, erGapFill, erSkirt, @@ -54,14 +55,16 @@ inline bool is_infill(ExtrusionRole role) return role == erBridgeInfill || role == erInternalInfill || role == erSolidInfill - || role == erTopSolidInfill; + || role == erTopSolidInfill + || role == erIroning; } inline bool is_solid_infill(ExtrusionRole role) { return role == erBridgeInfill || role == erSolidInfill - || role == erTopSolidInfill; + || role == erTopSolidInfill + || role == erIroning; } inline bool is_bridge(ExtrusionRole role) { diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 498abe89e5..f62b3ab258 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -10,6 +10,7 @@ #include "../Surface.hpp" #include "FillBase.hpp" +#include "FillRectilinear2.hpp" namespace Slic3r { @@ -388,8 +389,8 @@ void Layer::make_fills() flow_width = new_flow.width; } // Save into layer. - auto *eec = new ExtrusionEntityCollection(); - m_regions[surface_fill.region_id]->fills.entities.push_back(eec); + ExtrusionEntityCollection* eec = nullptr; + m_regions[surface_fill.region_id]->fills.entities.push_back(eec = new ExtrusionEntityCollection()); // Only concentric fills are not sorted. eec->no_sort = f->no_sort(); extrusion_entities_append_paths( @@ -418,4 +419,163 @@ void Layer::make_fills() #endif } +// Create ironing extrusions over top surfaces. +void Layer::make_ironing() +{ + // LayerRegion::slices contains surfaces marked with SurfaceType. + // Here we want to collect top surfaces extruded with the same extruder. + // A surface will be ironed with the same extruder to not contaminate the print with another material leaking from the nozzle. + + // First classify regions based on the extruder used. + struct IroningParams { + int extruder = -1; + bool just_infill = false; + // Spacing of the ironing lines, also to calculate the extrusion flow from. + double line_spacing; + // Height of the extrusion, to calculate the extrusion flow from. + double height; + double speed; + double angle; + + bool operator<(const IroningParams &rhs) const { + if (this->extruder < rhs.extruder) + return true; + if (this->extruder > rhs.extruder) + return false; + if (int(this->just_infill) < int(rhs.just_infill)) + return true; + if (int(this->just_infill) > int(rhs.just_infill)) + return false; + if (this->line_spacing < rhs.line_spacing) + return true; + if (this->line_spacing > rhs.line_spacing) + return false; + if (this->height < rhs.height) + return true; + if (this->height > rhs.height) + return false; + if (this->speed < rhs.speed) + return true; + if (this->speed > rhs.speed) + return false; + if (this->angle < rhs.angle) + return true; + if (this->angle > rhs.angle) + return false; + return false; + } + + bool operator==(const IroningParams &rhs) const { + return this->extruder == rhs.extruder && this->just_infill == rhs.just_infill && + this->line_spacing == rhs.line_spacing && this->height == rhs.height && this->speed == rhs.speed && + this->angle == rhs.angle; + } + + LayerRegion *layerm = nullptr; + + // IdeaMaker: ironing + // ironing flowrate (5% percent) + // ironing speed (10 mm/sec) + + // Kisslicer: + // iron off, Sweep, Group + // ironing speed: 15 mm/sec + + // Cura: + // Pattern (zig-zag / concentric) + // line spacing (0.1mm) + // flow: from normal layer height. 10% + // speed: 20 mm/sec + }; + + std::vector by_extruder; + bool extruder_dont_care = this->object()->config().wipe_into_objects; + double default_layer_height = this->object()->config().layer_height; + + for (LayerRegion *layerm : m_regions) + if (! layerm->slices.empty()) { + IroningParams ironing_params; + const PrintRegionConfig &config = layerm->region()->config(); + if (config.ironing_type == IroningType::AllSolid || + (config.top_solid_layers > 0 && + (config.ironing_type == IroningType::TopSurfaces || + (config.ironing_type == IroningType::TopmostOnly && layerm->layer()->upper_layer == nullptr)))) { + if (config.perimeter_extruder == config.solid_infill_extruder || config.perimeters == 0) { + // Iron the whole face. + ironing_params.extruder = config.solid_infill_extruder; + } else { + // Iron just the infill. + ironing_params.extruder = config.solid_infill_extruder; + } + } + if (ironing_params.extruder != -1) { + ironing_params.just_infill = false; + ironing_params.line_spacing = config.ironing_spacing; + ironing_params.height = default_layer_height * 0.01 * config.ironing_flowrate; + ironing_params.speed = config.ironing_speed; + ironing_params.angle = config.fill_angle * M_PI / 180.; + ironing_params.layerm = layerm; + by_extruder.emplace_back(ironing_params); + } + } + std::sort(by_extruder.begin(), by_extruder.end()); + + FillRectilinear2 fill; + FillParams fill_params; + fill.set_bounding_box(this->object()->bounding_box()); + fill.layer_id = this->id(); + fill.z = this->print_z; + fill.overlap = 0; + fill_params.density = 1.; + fill_params.dont_connect = true; + + for (size_t i = 0; i < by_extruder.size(); ++ i) { + // Find span of regions equivalent to the ironing operation. + IroningParams &ironing_params = by_extruder[i]; + size_t j = i; + for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ; + + // Create the ironing extrusions for regions object()->print()->config().nozzle_diameter.values[ironing_params.extruder - 1]; + if (ironing_params.just_infill) { + // Just infill. + } else { + // Infill and perimeter. + // Merge top surfaces with the same ironing parameters. + Polygons polys; + for (size_t k = i; k < j; ++ k) + for (const Surface &surface : by_extruder[k].layerm->slices.surfaces) + if (surface.surface_type == stTop) + polygons_append(polys, surface.expolygon); + // Trim the top surfaces with half the nozzle diameter. + ironing_areas = intersection_ex(polys, offset(this->lslices, - float(scale_(0.5 * nozzle_dmr)))); + } + + // Create the filler object. + fill.spacing = ironing_params.line_spacing; + fill.angle = float(ironing_params.angle + 0.25 * M_PI); + fill.link_max_length = (coord_t)scale_(3. * fill.spacing); + double height = ironing_params.height * fill.spacing / nozzle_dmr; + Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height), false); + double flow_mm3_per_mm = flow.mm3_per_mm(); + Surface surface_fill(stTop, ExPolygon()); + for (ExPolygon &expoly : ironing_areas) { + surface_fill.expolygon = std::move(expoly); + Polylines polylines = fill.fill_surface(&surface_fill, fill_params); + if (! polylines.empty()) { + // Save into layer. + ExtrusionEntityCollection *eec = nullptr; + ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection()); + //FIXME we may not want to sort a monotonous infill. + eec->no_sort = false; + extrusion_entities_append_paths( + eec->entities, std::move(polylines), + erIroning, + flow_mm3_per_mm, float(flow.width), float(height)); + } + } + } +} + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 517ce83838..5a9e927398 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -20,27 +20,21 @@ class Surface; struct FillParams { - FillParams() { - memset(this, 0, sizeof(FillParams)); - // Adjustment does not work. - dont_adjust = true; - } - bool full_infill() const { return density > 0.9999f; } // Fill density, fraction in <0, 1> - float density; + float density { 0.f }; // Don't connect the fill lines around the inner perimeter. - bool dont_connect; + bool dont_connect { false }; // Don't adjust spacing to fill the space evenly. - bool dont_adjust; + bool dont_adjust { true }; // For Honeycomb. // we were requested to complete each loop; // in this case we don't try to make more continuous paths - bool complete; + bool complete { false }; }; static_assert(IsTriviallyCopyable::value, "FillParams class is not POD (and it should be - see constructor)."); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3a90349b56..01a804ee78 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2246,12 +2246,14 @@ void GCode::process_layer( const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region; //FIXME the following code prints regions in the order they are defined, the path is not optimized in any way. if (print.config().infill_first) { - gcode += this->extrude_infill(print, by_region_specific); + gcode += this->extrude_infill(print, by_region_specific, false); gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]); } else { gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]); - gcode += this->extrude_infill(print,by_region_specific); + gcode += this->extrude_infill(print,by_region_specific, false); } + // ironing + gcode += this->extrude_infill(print,by_region_specific, true); } if (this->config().gcode_label_objects) gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n"; @@ -2873,22 +2875,30 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector &by_region) +std::string GCode::extrude_infill(const Print &print, const std::vector &by_region, bool ironing) { - std::string gcode; + std::string gcode; + ExtrusionEntitiesPtr extrusions; + const char* extrusion_name = ironing ? "ironing" : "infill"; for (const ObjectByExtruder::Island::Region ®ion : by_region) if (! region.infills.empty()) { - m_config.apply(print.regions()[®ion - &by_region.front()]->config()); - ExtrusionEntitiesPtr extrusions { region.infills }; - chain_and_reorder_extrusion_entities(extrusions, &m_last_pos); - for (const ExtrusionEntity *fill : extrusions) { - auto *eec = dynamic_cast(fill); - if (eec) { - for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities) - gcode += this->extrude_entity(*ee, "infill"); - } else - gcode += this->extrude_entity(*fill, "infill"); - } + extrusions.clear(); + extrusions.reserve(region.infills.size()); + for (ExtrusionEntity *ee : region.infills) + if ((ee->role() == erIroning) == ironing) + extrusions.emplace_back(ee); + if (! extrusions.empty()) { + m_config.apply(print.regions()[®ion - &by_region.front()]->config()); + chain_and_reorder_extrusion_entities(extrusions, &m_last_pos); + for (const ExtrusionEntity *fill : extrusions) { + auto *eec = dynamic_cast(fill); + if (eec) { + for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities) + gcode += this->extrude_entity(*ee, extrusion_name); + } else + gcode += this->extrude_entity(*fill, extrusion_name); + } + } } return gcode; } @@ -3027,6 +3037,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, speed = m_config.get_abs_value("solid_infill_speed"); } else if (path.role() == erTopSolidInfill) { speed = m_config.get_abs_value("top_solid_infill_speed"); + } else if (path.role() == erIroning) { + speed = m_config.get_abs_value("ironing_speed"); } else if (path.role() == erGapFill) { speed = m_config.get_abs_value("gap_fill_speed"); } else { diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 7fc75c92b6..2daf0fe16e 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -295,7 +295,7 @@ private: const size_t single_object_instance_idx); std::string extrude_perimeters(const Print &print, const std::vector &by_region, std::unique_ptr &lower_layer_edge_grid); - std::string extrude_infill(const Print &print, const std::vector &by_region); + std::string extrude_infill(const Print &print, const std::vector &by_region, bool ironing); std::string extrude_support(const ExtrusionEntityCollection &support_fills); std::string travel_to(const Point &point, ExtrusionRole role, std::string comment); diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index 8a9184e641..3aae15748d 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -117,6 +117,7 @@ const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] Color(1.0f, 1.0f, 0.0f, 1.0f), // erInternalInfill Color(1.0f, 0.0f, 1.0f, 1.0f), // erSolidInfill Color(0.0f, 1.0f, 1.0f, 1.0f), // erTopSolidInfill + Color(0.0f, 1.0f, 1.0f, 1.0f), // erIroning Color(0.5f, 0.5f, 0.5f, 1.0f), // erBridgeInfill Color(1.0f, 1.0f, 1.0f, 1.0f), // erGapFill Color(0.5f, 0.0f, 0.0f, 1.0f), // erSkirt diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index d66aa8f013..54e4baf2cc 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -36,11 +36,6 @@ public: // collection of surfaces for infill generation SurfaceCollection fill_surfaces; - // Collection of perimeter surfaces. This is a cached result of diff(slices, fill_surfaces). - // While not necessary, the memory consumption is meager and it speeds up calculation. - // The perimeter_surfaces keep the IDs of the slices (top/bottom/) - SurfaceCollection perimeter_surfaces; - // collection of expolygons representing the bridged areas (thus not // needing support material) Polygons bridged; @@ -140,6 +135,7 @@ public: } void make_perimeters(); void make_fills(); + void make_ironing(); void export_region_slices_to_svg(const char *path) const; void export_region_fill_surfaces_to_svg(const char *path) const; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 8631db624d..986b7fa09a 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1583,6 +1583,8 @@ void Print::process() this->set_status(70, L("Infilling layers")); for (PrintObject *obj : m_objects) obj->infill(); + for (PrintObject *obj : m_objects) + obj->ironing(); for (PrintObject *obj : m_objects) obj->generate_support_material(); if (this->set_started(psWipeTower)) { diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 7180bae17f..d4d3a1ddc5 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -41,7 +41,7 @@ enum PrintStep { enum PrintObjectStep { posSlice, posPerimeters, posPrepareInfill, - posInfill, posSupportMaterial, posCount, + posInfill, posIroning, posSupportMaterial, posCount, }; // A PrintRegion object represents a group of volumes to print @@ -218,6 +218,7 @@ private: void make_perimeters(); void prepare_infill(); void infill(); + void ironing(); void generate_support_material(); void _slice(const std::vector &layer_height_profile); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index c7a7a9c8e7..259b016e35 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1076,6 +1076,53 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); + def = this->add("ironing", coBool); + def->label = L("Enable ironing"); + def->tooltip = L("Enable ironing of the top layers with the hot print head for smooth surface"); + def->category = L("Ironing"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("ironing_type", coEnum); + def->label = L("Ironingy Type"); + def->tooltip = L("Ironingy Type"); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("top"); + def->enum_values.push_back("topmost"); + def->enum_values.push_back("solid"); + def->enum_labels.push_back("All top surfaces"); + def->enum_labels.push_back("Topmost surface only"); + def->enum_labels.push_back("All solid surfaces"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(IroningType::TopSurfaces)); + + def = this->add("ironing_flowrate", coPercent); + def->label = L("Flow rate"); + def->category = L("Ironing"); + def->tooltip = L("Percent of a flow rate relative to object's normal layer height."); + def->sidetext = L("%"); + def->ratio_over = "layer_height"; + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionPercent(15)); + + def = this->add("ironing_spacing", coFloat); + def->label = L("Spacing between ironing passes"); + def->tooltip = L("Distance between ironing lins"); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0.1)); + + def = this->add("ironing_speed", coFloat); + def->label = L("Ironing speed"); + def->category = L("Speed"); + def->tooltip = L("Ironing speed"); + def->sidetext = L("mm/s"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(60)); + def = this->add("layer_gcode", coString); def->label = L("After layer change G-code"); def->tooltip = L("This custom code is inserted at every layer change, right after the Z move " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index ca509e37a8..a7d2d82703 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -38,6 +38,13 @@ enum InfillPattern { ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipCount, }; +enum class IroningType { + TopSurfaces, + TopmostOnly, + AllSolid, + Count, +}; + enum SupportMaterialPattern { smpRectilinear, smpRectilinearGrid, smpHoneycomb, }; @@ -122,6 +129,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum::g return keys_map; } +template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["top"] = int(IroningType::TopSurfaces); + keys_map["topmost"] = int(IroningType::TopmostOnly); + keys_map["solid"] = int(IroningType::AllSolid); + } + return keys_map; +} + template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -485,6 +502,12 @@ public: ConfigOptionInt infill_every_layers; ConfigOptionFloatOrPercent infill_overlap; ConfigOptionFloat infill_speed; + // Ironing options + ConfigOptionBool ironing; + ConfigOptionEnum ironing_type; + ConfigOptionPercent ironing_flowrate; + ConfigOptionFloat ironing_spacing; + ConfigOptionFloat ironing_speed; // Detect bridging perimeters ConfigOptionBool overhangs; ConfigOptionInt perimeter_extruder; @@ -530,6 +553,11 @@ protected: OPT_PTR(infill_every_layers); OPT_PTR(infill_overlap); OPT_PTR(infill_speed); + OPT_PTR(ironing); + OPT_PTR(ironing_type); + OPT_PTR(ironing_flowrate); + OPT_PTR(ironing_spacing); + OPT_PTR(ironing_speed); OPT_PTR(overhangs); OPT_PTR(perimeter_extruder); OPT_PTR(perimeter_extrusion_width); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 5573f4ac38..a68a9605b0 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -387,6 +387,25 @@ void PrintObject::infill() } } +void PrintObject::ironing() +{ + if (this->set_started(posIroning)) { + BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - start"; + tbb::parallel_for( + tbb::blocked_range(1, m_layers.size()), + [this](const tbb::blocked_range& range) { + for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { + m_print->throw_if_canceled(); + m_layers[layer_idx]->make_ironing(); + } + } + ); + m_print->throw_if_canceled(); + BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - end"; + this->set_done(posIroning); + } +} + void PrintObject::generate_support_material() { if (this->set_started(posSupportMaterial)) { diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 8d1daeb8e3..d7f0a37b04 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -298,6 +298,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("support_material_extruder", have_support_material || have_skirt); toggle_field("support_material_speed", have_support_material || have_brim || have_skirt); + bool has_ironing = config->opt_bool("ironing"); + for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" }) + toggle_field(el, has_ironing); + bool have_sequential_printing = config->opt_bool("complete_objects"); for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" }) toggle_field(el, have_sequential_printing); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index a1a6583bcc..12699c37fb 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1027,6 +1027,8 @@ boost::any& Choice::get_value() } if (m_opt_id.compare("fill_pattern") == 0) m_value = static_cast(ret_enum); + else if (m_opt_id.compare("ironing_type") == 0) + m_value = static_cast(ret_enum); else if (m_opt_id.compare("gcode_flavor") == 0) m_value = static_cast(ret_enum); else if (m_opt_id.compare("support_material_pattern") == 0) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index caeb8da034..7deed0786b 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -188,6 +188,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern") config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("ironing_type") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("gcode_flavor") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("support_material_pattern") == 0) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 207d42b5b3..d561d8e2a1 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -680,6 +680,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config opt_key == "fill_pattern" ) { ret = static_cast(config.option>(opt_key)->value); } + else if (opt_key.compare("ironing_type") == 0 ) { + ret = static_cast(config.option>(opt_key)->value); + } else if (opt_key.compare("gcode_flavor") == 0 ) { ret = static_cast(config.option>(opt_key)->value); } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 3731f03de4..a1f83141a2 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -405,8 +405,9 @@ const std::vector& Preset::print_options() "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", - "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", - "max_volumetric_speed", + "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", + "ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", + "max_print_speed", "max_volumetric_speed", #ifdef HAS_PRESSURE_EQUALIZER "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", #endif /* HAS_PRESSURE_EQUALIZER */ diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 0c68979f19..2caa7baaf5 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1162,6 +1162,12 @@ void TabPrint::build() optgroup->append_single_option_line("top_fill_pattern"); optgroup->append_single_option_line("bottom_fill_pattern"); + optgroup = page->new_optgroup(_(L("Ironing"))); + optgroup->append_single_option_line("ironing"); + optgroup->append_single_option_line("ironing_type"); + optgroup->append_single_option_line("ironing_flowrate"); + optgroup->append_single_option_line("ironing_spacing"); + optgroup = page->new_optgroup(_(L("Reducing printing time"))); optgroup->append_single_option_line("infill_every_layers"); optgroup->append_single_option_line("infill_only_where_needed"); @@ -1222,6 +1228,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_material_interface_speed"); optgroup->append_single_option_line("bridge_speed"); optgroup->append_single_option_line("gap_fill_speed"); + optgroup->append_single_option_line("ironing_speed"); optgroup = page->new_optgroup(_(L("Speed for non-print moves"))); optgroup->append_single_option_line("travel_speed");