diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 016d162d8..75952e4c2 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -69,7 +69,9 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) { group_attrib[i].is_solid = true; group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width; - group_attrib[i].pattern = surface.is_external() ? layerm.region()->config().external_fill_pattern.value : ipRectilinear; + group_attrib[i].pattern = surface.is_external() ? + (surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) : + ipRectilinear; } } // Loop through solid groups, find compatible groups and append them to this one. @@ -161,7 +163,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) if (surface.is_solid()) { density = 100.; fill_pattern = (surface.is_external() && ! is_bridge) ? - layerm.region()->config().external_fill_pattern.value : + (surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) : ipRectilinear; } else if (density <= 0) continue; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 745223906..7286c5cd8 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -362,12 +362,11 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); - def = this->add("external_fill_pattern", coEnum); - def->label = L("Top/bottom fill pattern"); + auto def_top_fill_pattern = def = this->add("top_fill_pattern", coEnum); + def->label = L("Top fill pattern"); def->category = L("Infill"); - def->tooltip = L("Fill pattern for top/bottom infill. This only affects the external visible layer, " - "and not its adjacent solid shells."); - def->cli = "external-fill-pattern|solid-fill-pattern=s"; + def->tooltip = L("Fill pattern for top infill. This only affects the top visible layer, and not its adjacent solid shells."); + def->cli = "top-fill-pattern|external-fill-pattern|solid-fill-pattern=s"; def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("rectilinear"); def->enum_values.push_back("concentric"); @@ -379,8 +378,15 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Hilbert Curve")); def->enum_labels.push_back(L("Archimedean Chords")); def->enum_labels.push_back(L("Octagram Spiral")); - // solid_fill_pattern is an obsolete equivalent to external_fill_pattern. - def->aliases = { "solid_fill_pattern" }; + // solid_fill_pattern is an obsolete equivalent to top_fill_pattern/bottom_fill_pattern. + def->aliases = { "solid_fill_pattern", "external_fill_pattern" }; + def->default_value = new ConfigOptionEnum(ipRectilinear); + + def = this->add("bottom_fill_pattern", coEnum); + *def = *def_top_fill_pattern; + def->label = L("Bottom Pattern"); + def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells."); + def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern=s"; def->default_value = new ConfigOptionEnum(ipRectilinear); def = this->add("external_perimeter_extrusion_width", coFloatOrPercent); @@ -2939,13 +2945,17 @@ std::string FullPrintConfig::validate() if (! print_config_def.get("fill_pattern")->has_enum_value(this->fill_pattern.serialize())) return "Invalid value for --fill-pattern"; - // --external-fill-pattern - if (! print_config_def.get("external_fill_pattern")->has_enum_value(this->external_fill_pattern.serialize())) - return "Invalid value for --external-fill-pattern"; + // --top-fill-pattern + if (! print_config_def.get("top_fill_pattern")->has_enum_value(this->top_fill_pattern.serialize())) + return "Invalid value for --top-fill-pattern"; + + // --bottom-fill-pattern + if (! print_config_def.get("bottom_fill_pattern")->has_enum_value(this->bottom_fill_pattern.serialize())) + return "Invalid value for --bottom-fill-pattern"; // --fill-density if (fabs(this->fill_density.value - 100.) < EPSILON && - ! print_config_def.get("external_fill_pattern")->has_enum_value(this->fill_pattern.serialize())) + ! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize())) return "The selected fill pattern is not supposed to work at 100% density"; // --infill-every-layers diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 221eac220..1ea556773 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -462,7 +462,8 @@ public: ConfigOptionFloat bridge_flow_ratio; ConfigOptionFloat bridge_speed; ConfigOptionBool ensure_vertical_shell_thickness; - ConfigOptionEnum external_fill_pattern; + ConfigOptionEnum top_fill_pattern; + ConfigOptionEnum bottom_fill_pattern; ConfigOptionFloatOrPercent external_perimeter_extrusion_width; ConfigOptionFloatOrPercent external_perimeter_speed; ConfigOptionBool external_perimeters_first; @@ -504,7 +505,8 @@ protected: OPT_PTR(bridge_flow_ratio); OPT_PTR(bridge_speed); OPT_PTR(ensure_vertical_shell_thickness); - OPT_PTR(external_fill_pattern); + OPT_PTR(top_fill_pattern); + OPT_PTR(bottom_fill_pattern); OPT_PTR(external_perimeter_extrusion_width); OPT_PTR(external_perimeter_speed); OPT_PTR(external_perimeters_first); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d516153a9..8fa143681 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -498,7 +498,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorsurface_type == stInternalVoid; } +bool +Surface::is_top() const +{ + return this->surface_type == stTop; +} + bool Surface::is_bottom() const { diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index c2cec3793..e0f7e1ea3 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -98,6 +98,7 @@ public: bool is_solid() const; bool is_external() const; bool is_internal() const; + bool is_top() const; bool is_bottom() const; bool is_bridge() const; }; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 3cd056f2d..d514615f2 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -638,7 +638,7 @@ void Choice::set_value(const boost::any& value, bool change_event) } case coEnum: { int val = boost::any_cast(value); - if (m_opt_id.compare("external_fill_pattern") == 0) + if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern") { if (!m_opt.enum_values.empty()) { std::string key; @@ -707,7 +707,7 @@ boost::any& Choice::get_value() if (m_opt.type == coEnum) { int ret_enum = static_cast(window)->GetSelection(); - if (m_opt_id.compare("external_fill_pattern") == 0) + if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern") { if (!m_opt.enum_values.empty()) { std::string key = m_opt.enum_values[ret_enum]; diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index a15f50032..e09ce2466 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -211,8 +211,9 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt } break; case coEnum:{ - if (opt_key.compare("external_fill_pattern") == 0 || - opt_key.compare("fill_pattern") == 0) + if (opt_key == "top_fill_pattern" || + 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("gcode_flavor") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index b63f434f0..0e9fcd75e 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -559,8 +559,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config ret = config.opt_int(opt_key, idx); break; case coEnum:{ - if (opt_key.compare("external_fill_pattern") == 0 || - opt_key.compare("fill_pattern") == 0 ) { + if (opt_key == "top_fill_pattern" || + opt_key == "bottom_fill_pattern" || + opt_key == "fill_pattern" ) { ret = static_cast(config.option>(opt_key)->value); } else if (opt_key.compare("gcode_flavor") == 0 ) { diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index b8623eeac..86d5db2a7 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -356,7 +356,7 @@ const std::vector& Preset::print_options() static std::vector s_opts { "layer_height", "first_layer_height", "perimeters", "spiral_vase", "top_solid_layers", "bottom_solid_layers", "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "external_fill_pattern", + "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", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 839e7b74d..52d7f8526 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -971,7 +971,8 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Infill"))); optgroup->append_single_option_line("fill_density"); optgroup->append_single_option_line("fill_pattern"); - optgroup->append_single_option_line("external_fill_pattern"); + optgroup->append_single_option_line("top_fill_pattern"); + optgroup->append_single_option_line("bottom_fill_pattern"); optgroup = page->new_optgroup(_(L("Reducing printing time"))); optgroup->append_single_option_line("infill_every_layers"); @@ -1280,7 +1281,7 @@ void TabPrint::update() } } if (!str_fill_pattern.empty()) { - const std::vector &external_fill_pattern = m_config->def()->get("external_fill_pattern")->enum_values; + const std::vector &external_fill_pattern = m_config->def()->get("top_fill_pattern")->enum_values; bool correct_100p_fill = false; for (const std::string &fill : external_fill_pattern) { @@ -1321,7 +1322,7 @@ void TabPrint::update() bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; // solid_infill_extruder uses the same logic as in Print::extruders() - for (auto el : {"external_fill_pattern", "infill_first", "solid_infill_extruder", + for (auto el : {"top_fill_pattern", "bottom_fill_pattern", "infill_first", "solid_infill_extruder", "solid_infill_extrusion_width", "solid_infill_speed" }) get_field(el)->toggle(have_solid_infill);