diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 1e0a9af3e2..bdb21124d4 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -936,9 +936,16 @@ std::vector group_fills(const Layer &layer, LockRegionParam &lock_p region_config.sparse_infill_rotate_template.value); params.fixed_angle = !region_config.sparse_infill_rotate_template.value.empty(); } else { - params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value, - region_config.solid_infill_rotate_template.value); - params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty(); + const bool top_layer_direction_set = surface.is_top() && region_config.top_layer_direction.value >= 0.; + const bool bottom_layer_direction_set = surface.is_bottom() && region_config.bottom_layer_direction.value >= 0.; + if (top_layer_direction_set || bottom_layer_direction_set) { + params.angle = Geometry::deg2rad(top_layer_direction_set ? region_config.top_layer_direction.value : region_config.bottom_layer_direction.value); + params.fixed_angle = true; + } else { + params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value, + region_config.solid_infill_rotate_template.value); + params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty(); + } } params.bridge_angle = float(surface.bridge_angle); @@ -1599,16 +1606,20 @@ void Layer::make_ironing() ironing_params.height = default_layer_height * 0.01 * (!config.filament_ironing_flow.is_nil(extruder_idx) ? config.filament_ironing_flow.get_at(extruder_idx) : config.ironing_flow); - ironing_params.speed = (!config.filament_ironing_speed.is_nil(extruder_idx) - ? config.filament_ironing_speed.get_at(extruder_idx) - : config.ironing_speed); - double ironing_angle = (config.ironing_angle_fixed ? 0 : calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value)) + config.ironing_angle * M_PI / 180.; + ironing_params.speed = (!config.filament_ironing_speed.is_nil(extruder_idx) + ? config.filament_ironing_speed.get_at(extruder_idx) + : config.ironing_speed); + const bool top_layer_direction_set = config.top_layer_direction.value >= 0.; + const double top_layer_base_angle = top_layer_direction_set ? + Geometry::deg2rad(config.top_layer_direction.value) : + calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value); + double ironing_angle = (config.ironing_angle_fixed ? 0. : top_layer_base_angle) + config.ironing_angle * M_PI / 180.; if (config.align_infill_direction_to_model) { auto m = this->object()->trafo().matrix(); ironing_angle += atan2((double)m(1, 0), (double)m(0, 0)); } - ironing_params.angle = ironing_angle; - ironing_params.fixed_angle = config.ironing_angle_fixed || !config.solid_infill_rotate_template.value.empty(); + ironing_params.angle = ironing_angle; + ironing_params.fixed_angle = config.ironing_angle_fixed || top_layer_direction_set || !config.solid_infill_rotate_template.value.empty(); ironing_params.pattern = config.ironing_pattern; ironing_params.layerm = layerm; by_extruder.emplace_back(ironing_params); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index bc728f62e5..20b60b389d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1047,6 +1047,8 @@ static std::vector s_Preset_print_options{ "bottom_surface_pattern", "infill_direction", "solid_infill_direction", + "top_layer_direction", + "bottom_layer_direction", "counterbore_hole_bridging", "infill_shift_step", "sparse_infill_rotate_template", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8baa14ff39..5600785f59 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2984,6 +2984,26 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(45)); + def = this->add("top_layer_direction", coFloat); + def->label = L("Top layer direction"); + def->category = L("Strength"); + def->tooltip = L("Optional absolute angle for top-layer infill and ironing base direction. Set to -1 to use the current solid infill direction behavior."); + def->sidetext = u8"°"; // degrees, don't need translation + def->min = -1; + def->max = 360; + def->mode = comSimple; + def->set_default_value(new ConfigOptionFloat(-1)); + + def = this->add("bottom_layer_direction", coFloat); + def->label = L("Bottom layer direction"); + def->category = L("Strength"); + def->tooltip = L("Optional absolute angle for bottom-layer infill. Set to -1 to use the current solid infill direction behavior."); + def->sidetext = u8"°"; // degrees, don't need translation + def->min = -1; + def->max = 360; + def->mode = comSimple; + def->set_default_value(new ConfigOptionFloat(-1)); + def = this->add("sparse_infill_density", coPercent); def->label = L("Sparse infill density"); def->category = L("Strength"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b51eef8aa3..7117e3101d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1107,6 +1107,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatsNullable, outer_wall_speed)) ((ConfigOptionFloat, infill_direction)) ((ConfigOptionFloat, solid_infill_direction)) + ((ConfigOptionFloat, top_layer_direction)) + ((ConfigOptionFloat, bottom_layer_direction)) ((ConfigOptionString, solid_infill_rotate_template)) ((ConfigOptionBool, symmetric_infill_y_axis)) ((ConfigOptionFloat, infill_shift_step)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 07a6150af5..912a68be95 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1303,6 +1303,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "skeleton_infill_line_width" || opt_key == "infill_direction" || opt_key == "solid_infill_direction" + || opt_key == "top_layer_direction" + || opt_key == "bottom_layer_direction" || opt_key == "align_infill_direction_to_model" || opt_key == "extra_solid_infills" || opt_key == "ensure_vertical_shell_thickness" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index b70ccacc17..15da90b546 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -710,6 +710,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in toggle_field("bottom_surface_pattern", has_bottom_shell); toggle_field("top_surface_density", has_top_shell); toggle_field("bottom_surface_density", has_bottom_shell); + toggle_field("top_layer_direction", has_top_shell); + toggle_field("bottom_layer_direction", has_bottom_shell); for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap", "bridge_angle", "internal_bridge_angle", "relative_bridge_angle", diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 01cda17ad8..ccb6dedd29 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -141,6 +141,8 @@ std::map> SettingsFactory::PART_CATE {"infill_wall_overlap", "", 1}, {"top_bottom_infill_wall_overlap", "", 1}, {"solid_infill_direction", "", 1}, + {"top_layer_direction", "", 1}, + {"bottom_layer_direction", "", 1}, {"infill_direction", "", 1}, {"bridge_angle", "", 1}, {"internal_bridge_angle", "", 1}, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 39512eb396..d56247e2ea 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2741,10 +2741,12 @@ void TabPrint::build() optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness"); optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density"); optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern"); + optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-direction"); optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers"); optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness"); optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density"); optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern"); + optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#direction"); optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap"); optgroup = page->new_optgroup(L("Infill"), L"param_infill");