diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
index 3e2996244..f78297912 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
@@ -523,6 +523,46 @@ void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
 }
 
 
+void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool overwrite, bool block)
+{
+    float threshold = (M_PI/180.)*threshold_deg;
+    const Selection& selection = m_parent.get_selection();
+    const ModelObject* mo = m_c->selection_info()->model_object();
+    const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
+
+    int mesh_id = -1;
+    for (const ModelVolume* mv : mo->volumes) {
+        if (! mv->is_model_part())
+            continue;
+
+        ++mesh_id;
+
+        const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
+        Vec3f down  = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
+        Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();
+
+        float dot_limit = limit.dot(down);
+
+        // Now calculate dot product of vert_direction and facets' normals.
+        int idx = -1;
+        for (const stl_facet& facet : mv->mesh().stl.facet_start) {
+            ++idx;
+            if (facet.normal.dot(down) > dot_limit && (overwrite || m_selected_facets[mesh_id][idx] == FacetSupportType::NONE))
+                m_selected_facets[mesh_id][idx] = block
+                        ? FacetSupportType::BLOCKER
+                        : FacetSupportType::ENFORCER;
+        }
+        update_vertex_buffers(mv, mesh_id, true, true);
+    }
+
+    Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
+                                                    : _L("Add supports by angle"));
+    update_model_object();
+    m_parent.set_as_dirty();
+    m_setting_angle = false;
+}
+
+
 void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
 {
     if (! m_c->selection_info()->model_object())
@@ -531,96 +571,124 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
     const float approx_height = m_imgui->scaled(18.0f);
     y = std::min(y, bottom_limit - approx_height);
     m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
-    m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
 
-    // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
-    const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
-    const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
-    const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
-    const float minimal_slider_width = m_imgui->scaled(4.f);
+    if (! m_setting_angle) {
+        m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
 
-    float caption_max = 0.f;
-    float total_text_max = 0.;
-    for (const std::string& t : {"enforce", "block", "remove"}) {
-        caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x);
-        total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x);
-    }
-    caption_max += m_imgui->scaled(1.f);
-    total_text_max += m_imgui->scaled(1.f);
+        // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
+        const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
+        const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
+        const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
+        const float minimal_slider_width = m_imgui->scaled(4.f);
 
-    float window_width = minimal_slider_width + std::max(cursor_slider_left, clipping_slider_left);
-    window_width = std::max(window_width, total_text_max);
-    window_width = std::max(window_width, button_width);
+        float caption_max = 0.f;
+        float total_text_max = 0.;
+        for (const std::string& t : {"enforce", "block", "remove"}) {
+            caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x);
+            total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x);
+        }
+        caption_max += m_imgui->scaled(1.f);
+        total_text_max += m_imgui->scaled(1.f);
 
-    auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
-        static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
-        ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-        m_imgui->text(caption);
-        ImGui::PopStyleColor();
-        ImGui::SameLine(caption_max);
-        m_imgui->text(text);
-    };
+        float window_width = minimal_slider_width + std::max(cursor_slider_left, clipping_slider_left);
+        window_width = std::max(window_width, total_text_max);
+        window_width = std::max(window_width, button_width);
 
-    for (const std::string& t : {"enforce", "block", "remove"})
-        draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
+        auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
+            static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
+            ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+            m_imgui->text(caption);
+            ImGui::PopStyleColor();
+            ImGui::SameLine(caption_max);
+            m_imgui->text(text);
+        };
 
-    m_imgui->text("");
+        for (const std::string& t : {"enforce", "block", "remove"})
+            draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
 
-    if (m_imgui->button(m_desc.at("remove_all"))) {
-        ModelObject* mo = m_c->selection_info()->model_object();
-        int idx = -1;
-        for (ModelVolume* mv : mo->volumes) {
-            ++idx;
-            if (mv->is_model_part()) {
-                m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
-                mv->m_supported_facets.clear();
-                update_vertex_buffers(mv, idx, true, true);
-                m_parent.set_as_dirty();
+        m_imgui->text("");
+
+        if (m_imgui->button("Autoset by angle...")) {
+            m_setting_angle = true;
+        }
+
+        ImGui::SameLine();
+
+        if (m_imgui->button(m_desc.at("remove_all"))) {
+            ModelObject* mo = m_c->selection_info()->model_object();
+            int idx = -1;
+            for (ModelVolume* mv : mo->volumes) {
+                ++idx;
+                if (mv->is_model_part()) {
+                    m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
+                    mv->m_supported_facets.clear();
+                    update_vertex_buffers(mv, idx, true, true);
+                    m_parent.set_as_dirty();
+                }
             }
         }
-    }
 
-    const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
+        const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
 
-    m_imgui->text(m_desc.at("cursor_size"));
-    ImGui::SameLine(clipping_slider_left);
-    ImGui::PushItemWidth(window_width - clipping_slider_left);
-    ImGui::SliderFloat(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
-    if (ImGui::IsItemHovered()) {
-        ImGui::BeginTooltip();
-        ImGui::PushTextWrapPos(max_tooltip_width);
-        ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
-        ImGui::PopTextWrapPos();
-        ImGui::EndTooltip();
-    }
-
-    ImGui::Separator();
-    if (m_c->object_clipper()->get_position() == 0.f)
-        m_imgui->text(m_desc.at("clipping_of_view"));
-    else {
-        if (m_imgui->button(m_desc.at("reset_direction"))) {
-            wxGetApp().CallAfter([this](){
-                    m_c->object_clipper()->set_position(-1., false);
-                });
+        m_imgui->text(m_desc.at("cursor_size"));
+        ImGui::SameLine(clipping_slider_left);
+        ImGui::PushItemWidth(window_width - clipping_slider_left);
+        ImGui::SliderFloat(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
+        if (ImGui::IsItemHovered()) {
+            ImGui::BeginTooltip();
+            ImGui::PushTextWrapPos(max_tooltip_width);
+            ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
+            ImGui::PopTextWrapPos();
+            ImGui::EndTooltip();
         }
+
+        ImGui::Separator();
+        if (m_c->object_clipper()->get_position() == 0.f)
+            m_imgui->text(m_desc.at("clipping_of_view"));
+        else {
+            if (m_imgui->button(m_desc.at("reset_direction"))) {
+                wxGetApp().CallAfter([this](){
+                        m_c->object_clipper()->set_position(-1., false);
+                    });
+            }
+        }
+
+        ImGui::SameLine(clipping_slider_left);
+        ImGui::PushItemWidth(window_width - clipping_slider_left);
+        float clp_dist = m_c->object_clipper()->get_position();
+        if (ImGui::SliderFloat("  ", &clp_dist, 0.f, 1.f, "%.2f"))
+        m_c->object_clipper()->set_position(clp_dist, true);
+        if (ImGui::IsItemHovered()) {
+            ImGui::BeginTooltip();
+            ImGui::PushTextWrapPos(max_tooltip_width);
+            ImGui::TextUnformatted(_L("Ctrl + Mouse wheel").ToUTF8().data());
+            ImGui::PopTextWrapPos();
+            ImGui::EndTooltip();
+        }
+
+        m_imgui->end();
+        if (m_setting_angle)
+            m_parent.set_as_dirty();
     }
-
-    ImGui::SameLine(clipping_slider_left);
-    ImGui::PushItemWidth(window_width - clipping_slider_left);
-    float clp_dist = m_c->object_clipper()->get_position();
-    if (ImGui::SliderFloat("  ", &clp_dist, 0.f, 1.f, "%.2f"))
-    m_c->object_clipper()->set_position(clp_dist, true);
-    if (ImGui::IsItemHovered()) {
-        ImGui::BeginTooltip();
-        ImGui::PushTextWrapPos(max_tooltip_width);
-        ImGui::TextUnformatted(_L("Ctrl + Mouse wheel").ToUTF8().data());
-        ImGui::PopTextWrapPos();
-        ImGui::EndTooltip();
+    else {
+        std::string name = "Autoset custom supports";
+        m_imgui->begin(wxString(name), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
+        m_imgui->text("Threshold:");
+        ImGui::SameLine();
+        m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, "%.f");
+        m_imgui->checkbox(wxString("Overwrite already selected facets"), m_overwrite_selected);
+        if (m_imgui->button("Enforce"))
+            select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, false);
+        ImGui::SameLine();
+        if (m_imgui->button("Block"))
+            select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, true);
+        ImGui::SameLine();
+        if (m_imgui->button("Cancel"))
+            m_setting_angle = false;
+        m_imgui->end();
+        if (! m_setting_angle)
+            m_parent.set_as_dirty();
     }
-
-
-
-    m_imgui->end();
 }
 
 bool GLGizmoFdmSupports::on_is_activable() const
@@ -680,6 +748,7 @@ void GLGizmoFdmSupports::on_set_state()
     }
     if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
         // we are actually shutting down
+        m_setting_angle = false;
         wxGetApp().plater()->leave_gizmos_stack();
         {
             Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp
index e2f2e96a9..bed6d00a0 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp
@@ -61,10 +61,15 @@ private:
     void update_model_object() const;
     void update_from_model_object();
 
+    void select_facets_by_angle(float threshold, bool overwrite, bool block);
+    bool m_overwrite_selected = false;
+    float m_angle_threshold_deg = 45.f;
+
     bool is_mesh_point_clipped(const Vec3d& point) const;
 
     float m_clipping_plane_distance = 0.f;
     std::unique_ptr<ClippingPlane> m_clipping_plane;
+    bool m_setting_angle = false;
 
     // This map holds all translated description texts, so they can be easily referenced during layout calculations
     // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.