From cd1322ce3ffbdc3b3b34bc9ab619f6f3b233b179 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 14 Jan 2021 13:00:54 +0100 Subject: [PATCH] FDM supports gizmo 'autoset by angle' improvements: - Extra dialog for autosetting by angle in FDM supports gizmo was removed - Highlighting facets by angle is now controlled by a slider in the main gizmo dialog - User is allowed to paint even when using the slope highlighter - The button to turn highlighted facets to blockers was removed, it made no sense - Highlighted facets are now rendered in light blue --- resources/shaders/gouraud.fs | 16 +- src/libslic3r/TriangleSelector.cpp | 30 +- src/libslic3r/TriangleSelector.hpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 317 ++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp | 3 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 26 +- 6 files changed, 212 insertions(+), 188 deletions(-) diff --git a/resources/shaders/gouraud.fs b/resources/shaders/gouraud.fs index 40182a14b..6dbd0e6fe 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/gouraud.fs @@ -32,22 +32,22 @@ varying vec3 delta_box_max; varying float world_normal_z; varying vec3 eye_normal; -vec3 slope_color() -{ - return (world_normal_z > slope.normal_z - EPSILON) ? GREEN : RED; -} - void main() { if (any(lessThan(clipping_planes_dots, ZERO))) discard; - vec3 color = slope.actived ? slope_color() : uniform_color.rgb; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + if (slope.actived && world_normal_z < slope.normal_z - EPSILON) { + color = vec3(0.7f, 0.7f, 1.f); + alpha = 1.f; + } // if the fragment is outside the print volume -> use darker color color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; #ifdef ENABLE_ENVIRONMENT_MAP if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, uniform_color.a); + gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); else #endif - gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, uniform_color.a); + gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); } diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 3fe688195..f29d97388 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -425,8 +425,11 @@ void TriangleSelector::reset() m_triangles.clear(); for (const stl_vertex& vert : m_mesh->its.vertices) m_vertices.emplace_back(vert); - for (const stl_triangle_vertex_indices& ind : m_mesh->its.indices) - push_triangle(ind[0], ind[1], ind[2]); + for (size_t i=0; iits.indices.size(); ++i) { + const stl_triangle_vertex_indices& ind = m_mesh->its.indices[i]; + const Vec3f& normal = m_mesh->stl.facet_start[i].normal; + push_triangle(ind[0], ind[1], ind[2], normal); + } m_orig_size_vertices = m_vertices.size(); m_orig_size_indices = m_triangles.size(); m_invalid_triangles = 0; @@ -451,19 +454,20 @@ void TriangleSelector::set_edge_limit(float edge_limit) -void TriangleSelector::push_triangle(int a, int b, int c) +void TriangleSelector::push_triangle(int a, int b, int c, const Vec3f& normal) { for (int i : {a, b, c}) { assert(i >= 0 && i < int(m_vertices.size())); ++m_vertices[i].ref_cnt; } - m_triangles.emplace_back(a, b, c); + m_triangles.emplace_back(a, b, c, normal); } void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_state) { Triangle* tr = &m_triangles[facet_idx]; + const Vec3f normal = tr->normal; assert(tr->is_split()); @@ -483,8 +487,8 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat m_vertices.emplace_back((m_vertices[verts_idxs[1]].v + m_vertices[verts_idxs[2]].v)/2.); verts_idxs.insert(verts_idxs.begin()+2, m_vertices.size() - 1); - push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2]); - push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0]); + push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2], normal); + push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0], normal); } if (sides_to_split == 2) { @@ -494,9 +498,9 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[3]].v)/2.); verts_idxs.insert(verts_idxs.begin()+4, m_vertices.size() - 1); - push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4]); - push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4]); - push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4]); + push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4], normal); + push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4], normal); + push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4], normal); } if (sides_to_split == 3) { @@ -507,10 +511,10 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat m_vertices.emplace_back((m_vertices[verts_idxs[4]].v + m_vertices[verts_idxs[0]].v)/2.); verts_idxs.insert(verts_idxs.begin()+5, m_vertices.size() - 1); - push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5]); - push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3]); - push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5]); - push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5]); + push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5], normal); + push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3], normal); + push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5], normal); + push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5], normal); } tr = &m_triangles[facet_idx]; // may have been invalidated diff --git a/src/libslic3r/TriangleSelector.hpp b/src/libslic3r/TriangleSelector.hpp index 11387c766..9d1590070 100644 --- a/src/libslic3r/TriangleSelector.hpp +++ b/src/libslic3r/TriangleSelector.hpp @@ -63,8 +63,9 @@ protected: public: // Use TriangleSelector::push_triangle to create a new triangle. // It increments/decrements reference counter on vertices. - Triangle(int a, int b, int c) + Triangle(int a, int b, int c, const Vec3f& normal_) : verts_idxs{a, b, c}, + normal{normal_}, state{EnforcerBlockerType(0)}, number_of_splits{0}, special_side_idx{0}, @@ -73,6 +74,9 @@ protected: // Indices into m_vertices. std::array verts_idxs; + // Triangle normal (a shader might need it). + Vec3f normal; + // Is this triangle valid or marked to be removed? bool valid{true}; @@ -158,7 +162,7 @@ protected: void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant. bool is_pointer_in_triangle(int facet_idx) const; bool is_edge_inside_cursor(int facet_idx) const; - void push_triangle(int a, int b, int c); + void push_triangle(int a, int b, int c, const Vec3f& normal); void perform_split(int facet_idx, EnforcerBlockerType old_state); }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 8f2703faa..f3f87cc33 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -20,10 +20,8 @@ namespace GUI { void GLGizmoFdmSupports::on_shutdown() { - if (m_setting_angle) { - m_setting_angle = false; - m_parent.use_slope(false); - } + m_angle_threshold_deg = 0.f; + m_parent.use_slope(false); } @@ -52,6 +50,9 @@ bool GLGizmoFdmSupports::on_init() m_desc["remove_all"] = _L("Remove all selection"); m_desc["circle"] = _L("Circle"); m_desc["sphere"] = _L("Sphere"); + m_desc["highlight_by_angle"] = _L("Highlight by angle"); + m_desc["enforce_button"] = _L("Enforce"); + m_desc["cancel"] = _L("Cancel"); return true; } @@ -65,8 +66,7 @@ void GLGizmoFdmSupports::render_painter_gizmo() const glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); - if (! m_setting_angle) - render_triangles(selection); + render_triangles(selection); m_c->object_clipper()->render_cut(); render_cursor(); @@ -81,179 +81,183 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l if (! m_c->selection_info()->model_object()) return; - const float approx_height = m_imgui->scaled(14.0f); + const float approx_height = m_imgui->scaled(17.0f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - if (! m_setting_angle) { - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + 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 cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x - + m_imgui->scaled(2.5f); - const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x - + m_imgui->scaled(2.5f); - 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); + // 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 autoset_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).x + m_imgui->scaled(1.f); + const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f); + const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x + + m_imgui->scaled(2.5f); + const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x + + m_imgui->scaled(2.5f); + const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); + const float button_enforce_width = m_imgui->calc_text_size(m_desc.at("enforce_button")).x; + const float button_cancel_width = m_imgui->calc_text_size(m_desc.at("cancel")).x; + const float buttons_width = std::max(button_enforce_width, button_cancel_width) + m_imgui->scaled(0.5f); + const float minimal_slider_width = m_imgui->scaled(4.f); - 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); + 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); - 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); - window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); + float window_width = minimal_slider_width + std::max(autoset_slider_left, 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); + window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); + window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f)); - auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { - m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, caption); - ImGui::SameLine(caption_max); - m_imgui->text(text); - }; + auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { + m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, caption); + ImGui::SameLine(caption_max); + m_imgui->text(text); + }; - for (const std::string& t : {"enforce", "block", "remove"}) - draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); + for (const std::string& t : {"enforce", "block", "remove"}) + draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); - m_imgui->text(""); + m_imgui->text(""); + ImGui::Separator(); - if (m_imgui->button(_L("Autoset by angle") + "...")) { - m_setting_angle = true; - } - - ImGui::SameLine(); - - if (m_imgui->button(m_desc.at("remove_all"))) { - Plater::TakeSnapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); - ModelObject* mo = m_c->selection_info()->model_object(); - int idx = -1; - for (ModelVolume* mv : mo->volumes) { - if (mv->is_model_part()) { - ++idx; - m_triangle_selectors[idx]->reset(); - } - } - - update_model_object(); + m_imgui->text(m_desc["highlight_by_angle"] + ":"); + ImGui::AlignTextToFramePadding(); + std::string format_str = std::string("%.f") + I18N::translate_utf8("°", + "Degree sign to use in the respective slider in FDM supports gizmo," + "placed after the number with no whitespace in between."); + ImGui::SameLine(autoset_slider_left); + ImGui::PushItemWidth(window_width - autoset_slider_left); + if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) { + m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg); + if (! m_parent.is_using_slope()) { + m_parent.use_slope(true); m_parent.set_as_dirty(); } + } - const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; + m_imgui->disabled_begin(m_angle_threshold_deg == 0.f); + ImGui::NewLine(); + ImGui::SameLine(window_width - 2.f*buttons_width - m_imgui->scaled(0.5f)); + if (m_imgui->button(m_desc["enforce_button"], buttons_width, 0.f)) { + select_facets_by_angle(m_angle_threshold_deg, false); + m_angle_threshold_deg = 0.f; + } + ImGui::SameLine(window_width - buttons_width); + if (m_imgui->button(m_desc["cancel"], buttons_width, 0.f)) { + m_angle_threshold_deg = 0.f; + m_parent.use_slope(false); + } + m_imgui->disabled_end(); - ImGui::AlignTextToFramePadding(); - m_imgui->text(m_desc.at("cursor_size")); - ImGui::SameLine(cursor_slider_left); - ImGui::PushItemWidth(window_width - cursor_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(); - - ImGui::AlignTextToFramePadding(); - m_imgui->text(m_desc.at("cursor_type")); - ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width1); - - bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; - if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) - sphere_sel = true; - - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - - ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(cursor_type_radio_width2); - - if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) - sphere_sel = false; - - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(max_tooltip_width); - ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - - m_cursor_type = sphere_sel - ? TriangleSelector::CursorType::SPHERE - : TriangleSelector::CursorType::CIRCLE; - - - - - ImGui::Separator(); - if (m_c->object_clipper()->get_position() == 0.f) { - ImGui::AlignTextToFramePadding(); - 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); - }); + if (m_imgui->button(m_desc.at("remove_all"))) { + Plater::TakeSnapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); + ModelObject* mo = m_c->selection_info()->model_object(); + int idx = -1; + for (ModelVolume* mv : mo->volumes) { + if (mv->is_model_part()) { + ++idx; + m_triangle_selectors[idx]->reset(); } } - 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(); - } + update_model_object(); + m_parent.set_as_dirty(); + } - m_imgui->end(); + + const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("cursor_size")); + ImGui::SameLine(cursor_slider_left); + ImGui::PushItemWidth(window_width - cursor_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::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("cursor_type")); + ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width1); + + bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; + if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) + sphere_sel = true; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); + ImGui::PushItemWidth(cursor_type_radio_width2); + + if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) + sphere_sel = false; + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(max_tooltip_width); + ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + m_cursor_type = sphere_sel + ? TriangleSelector::CursorType::SPHERE + : TriangleSelector::CursorType::CIRCLE; + + + + + ImGui::Separator(); + if (m_c->object_clipper()->get_position() == 0.f) { + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("clipping_of_view")); } else { - m_imgui->begin(_L("Autoset custom supports"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); - ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Threshold:")); - std::string format_str = std::string("%.f") + I18N::translate_utf8("°", - "Degree sign to use in the respective slider in FDM supports gizmo," - "placed after the number with no whitespace in between."); - ImGui::SameLine(); - if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) - m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg); - if (m_imgui->button(_L("Enforce"))) - select_facets_by_angle(m_angle_threshold_deg, false); - ImGui::SameLine(); - if (m_imgui->button(_L("Block"))) - select_facets_by_angle(m_angle_threshold_deg, true); - ImGui::SameLine(); - if (m_imgui->button(_L("Cancel"))) - m_setting_angle = false; - m_imgui->end(); - bool needs_update = !(m_setting_angle && m_parent.is_using_slope()); - if (needs_update) { - m_parent.use_slope(m_setting_angle); - m_parent.set_as_dirty(); + 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(); } @@ -296,7 +300,6 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) : _L("Add supports by angle")); update_model_object(); m_parent.set_as_dirty(); - m_setting_angle = false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index fc9770787..41e4cc514 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -30,8 +30,7 @@ private: PainterGizmoType get_painter_type() const override; void select_facets_by_angle(float threshold, bool block); - float m_angle_threshold_deg = 45.f; - bool m_setting_angle = false; + float m_angle_threshold_deg = 0.f; // 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. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 819d014e8..91aef75d9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -540,7 +540,9 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) va.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]), double(m_vertices[tr.verts_idxs[i]].v[1]), double(m_vertices[tr.verts_idxs[i]].v[2]), - 0., 0., 1.); + double(tr.normal[0]), + double(tr.normal[1]), + double(tr.normal[2])); va.push_triangle(cnt, cnt+1, cnt+2); @@ -550,14 +552,26 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) m_iva_enforcers.finalize_geometry(true); m_iva_blockers.finalize_geometry(true); - if (m_iva_enforcers.has_VBOs()) { - ::glColor4f(0.f, 0.f, 1.f, 0.4f); + bool render_enf = m_iva_enforcers.has_VBOs(); + bool render_blc = m_iva_blockers.has_VBOs(); + + auto* shader = wxGetApp().get_shader("gouraud"); + if (! shader) + return; + + shader->start_using(); + ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + shader->set_uniform("slope.actived", false); + + if (render_enf) { + std::array color = { 0.47f, 0.47f, 1.f, 1.f }; + shader->set_uniform("uniform_color", color); m_iva_enforcers.render(); } - - if (m_iva_blockers.has_VBOs()) { - ::glColor4f(1.f, 0.f, 0.f, 0.4f); + if (render_blc) { + std::array color = { 1.f, 0.44f, 0.44f, 1.f }; + shader->set_uniform("uniform_color", color); m_iva_blockers.render(); }