From 79b5c94f4f5c9401f174e125201c1c300845601f Mon Sep 17 00:00:00 2001 From: "lane.wei" Date: Sat, 22 Oct 2022 21:37:48 +0800 Subject: [PATCH] ENH: enable wireframe This reverts commit ed6e149381240fd83b61da70891127d400f30a39. Change-Id: I010871fcf22322214c627fe907539c0916fa6ff5 --- resources/shaders/mm_gouraud_130.fs | 103 +++++++++++++++++++ resources/shaders/mm_gouraud_130.vs | 36 +++++++ src/slic3r/GUI/3DScene.cpp | 4 - src/slic3r/GUI/GLCanvas3D.cpp | 21 +++- src/slic3r/GUI/GLShadersManager.cpp | 18 +++- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 67 +++++++++--- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 10 +- src/slic3r/GUI/MainFrame.cpp | 29 +++--- src/slic3r/GUI/Plater.cpp | 11 ++ src/slic3r/GUI/Plater.hpp | 2 + 10 files changed, 263 insertions(+), 38 deletions(-) create mode 100644 resources/shaders/mm_gouraud_130.fs create mode 100644 resources/shaders/mm_gouraud_130.vs diff --git a/resources/shaders/mm_gouraud_130.fs b/resources/shaders/mm_gouraud_130.fs new file mode 100644 index 000000000..34da36a1f --- /dev/null +++ b/resources/shaders/mm_gouraud_130.fs @@ -0,0 +1,103 @@ +#version 130 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const float EPSILON = 0.0001; +//BBS: add grey and orange +//const vec3 GREY = vec3(0.9, 0.9, 0.9); +const vec3 ORANGE = vec3(0.8, 0.4, 0.0); + +uniform vec4 uniform_color; + +varying vec3 clipping_planes_dots; +varying vec4 model_pos; + +uniform bool volume_mirrored; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; +uniform SlopeDetection slope; + +//BBS: add wireframe logic +varying vec3 barycentric_coordinates; +float edgeFactor(float lineWidth) { + vec3 d = fwidth(barycentric_coordinates); + vec3 a3 = smoothstep(vec3(0.0), d * lineWidth, barycentric_coordinates); + return min(min(a3.x, a3.y), a3.z); +} + +vec3 wireframe(vec3 fill, vec3 stroke, float lineWidth) { + return mix(stroke, fill, edgeFactor(lineWidth)); +} + +vec3 getWireframeColor(vec3 fill) { + float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b; + return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988); +} +uniform bool show_wireframe; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz))); +#ifdef FLIP_TRIANGLE_NORMALS + triangle_normal = -triangle_normal; +#endif + + vec3 transformed_normal = normalize(slope.volume_world_normal_matrix * triangle_normal); + if (slope.actived && transformed_normal.z < slope.normal_z - EPSILON) { + //color = vec3(0.7, 0.7, 1.0); + color = color * 0.5 + ORANGE * 0.5; + alpha = 1.0; + } + + if (volume_mirrored) + triangle_normal = -triangle_normal; + + // First transform the normal into camera space and normalize the result. + vec3 eye_normal = normalize(gl_NormalMatrix * triangle_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + // x = diffuse, y = specular; + vec2 intensity = vec2(0.0, 0.0); + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec3 position = (gl_ModelViewMatrix * model_pos).xyz; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + if (show_wireframe) { + vec3 wireframeColor = show_wireframe ? getWireframeColor(color) : color; + vec3 triangleColor = wireframe(color, wireframeColor, 1.0); + gl_FragColor = vec4(vec3(intensity.y) + triangleColor * intensity.x, alpha); + } + else { + gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + } +} diff --git a/resources/shaders/mm_gouraud_130.vs b/resources/shaders/mm_gouraud_130.vs new file mode 100644 index 000000000..658acbf83 --- /dev/null +++ b/resources/shaders/mm_gouraud_130.vs @@ -0,0 +1,36 @@ +#version 130 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +uniform mat4 volume_world_matrix; +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +varying vec3 clipping_planes_dots; +varying vec4 model_pos; + +varying vec3 barycentric_coordinates; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; +uniform SlopeDetection slope; +void main() +{ + model_pos = gl_Vertex; + // Point in homogenous coordinates. + vec4 world_pos = volume_world_matrix * gl_Vertex; + + gl_Position = ftransform(); + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + + //compute the Barycentric Coordinates + int vertexMod3 = gl_VertexID % 3; + barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); +} diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index a6ea563e1..8f48579a4 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -869,10 +869,6 @@ void GLVolume::render(bool with_outline) const std::array body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red shader->set_uniform("uniform_color", body_color); - //if (GUI::wxGetApp().plater()->is_show_wireframe()) - // shader->set_uniform("show_wireframe", true); - //else - // shader->set_uniform("show_wireframe", false); shader->set_uniform("is_outline", true); glsafe(::glPopMatrix()); glsafe(::glPushMatrix()); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ecb49861d..9dfe9d203 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -731,6 +731,8 @@ bool GLCanvas3D::init() Bed3D::load_render_colors(); #endif + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) + wxGetApp().plater()->enable_wireframe(true); m_initialized = true; return true; @@ -2670,10 +2672,8 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) #endif } else if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_RETURN) { -#if !BBL_RELEASE_TO_PUBLIC wxGetApp().plater()->toggle_show_wireframe(); m_dirty = true; -#endif } else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { // Enable switching between 3D and Preview with Tab @@ -5762,6 +5762,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with // GLGizmosManager::EType type = gm.get_current_type(); if (dynamic_cast(gm.get_current()) == nullptr) { + if (wxGetApp().plater()->is_wireframe_enabled()) { + if (wxGetApp().plater()->is_show_wireframe()) + shader->set_uniform("show_wireframe", true); + else + shader->set_uniform("show_wireframe", false); + } //BBS:add assemble view related logic // do not cull backfaces to show broken geometry, if any m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { @@ -5777,7 +5783,6 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with // In case a painting gizmo is open, it should render the painted triangles // before transparent objects are rendered. Otherwise they would not be // visible when inside modifier meshes etc. - // GLGizmosManager::EType type = gm.get_current_type(); if (dynamic_cast(gm.get_current())) { shader->stop_using(); @@ -5790,6 +5795,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with } case GLVolumeCollection::ERenderType::Transparent: { + if (wxGetApp().plater()->is_wireframe_enabled()) { + if (wxGetApp().plater()->is_show_wireframe()) + shader->set_uniform("show_wireframe", true); + else + shader->set_uniform("show_wireframe", false); + } //BBS:add assemble view related logic m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { @@ -5809,6 +5820,10 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with } } + if (wxGetApp().plater()->is_wireframe_enabled()) { + shader->set_uniform("show_wireframe", false); + } + shader->stop_using(); } diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 74668fb20..e6076b6ce 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -45,7 +45,7 @@ std::pair GLShadersManager::init() // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor - if (0) { + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) { valid &= append_shader("gouraud", { "gouraud_130.vs", "gouraud_130.fs" } #if ENABLE_ENVIRONMENT_MAP , { "ENABLE_ENVIRONMENT_MAP"sv } @@ -69,10 +69,18 @@ std::pair GLShadersManager::init() // Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU. // Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed // triangle normals inside fragment shader have the right direction. - if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) - valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); - else - valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}); + if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) { + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) + valid &= append_shader("mm_gouraud", {"mm_gouraud_130.vs", "mm_gouraud_130.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); + else + valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); + } + else { + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) + valid &= append_shader("mm_gouraud", {"mm_gouraud_130.vs", "mm_gouraud_130.fs"}); + else + valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}); + } //BBS: add shader for outline valid &= append_shader("outline", { "outline.vs", "outline.fs" }); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 549972119..fb54dc76a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -1076,6 +1076,12 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui) if (!shader) return; assert(shader->get_name() == "mm_gouraud"); + if (wxGetApp().plater()->is_wireframe_enabled()) { + if (wxGetApp().plater()->is_show_wireframe()) + shader->set_uniform("show_wireframe", true); + else + shader->set_uniform("show_wireframe", false); + } for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { if (this->has_VBOs(buffer_idx)) { @@ -1130,7 +1136,15 @@ void TriangleSelectorPatch::update_triangles_per_type() int state = (int)triangle.get_state(); auto& patch = m_triangle_patches[state]; - patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); + //patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); + for (int i = 0; i < 3; ++i) { + int j = triangle.verts_idxs[i]; + int index = int(patch.patch_vertices.size()/3); + patch.patch_vertices.emplace_back(m_vertices[j].v(0)); + patch.patch_vertices.emplace_back(m_vertices[j].v(1)); + patch.patch_vertices.emplace_back(m_vertices[j].v(2)); + patch.triangle_indices.emplace_back( index); + } } } @@ -1202,7 +1216,15 @@ void TriangleSelectorPatch::update_triangles_per_patch() if (!visited[current_facet]) { Triangle& triangle = m_triangles[current_facet]; - patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); + for (int i = 0; i < 3; ++i) { + int j = triangle.verts_idxs[i]; + int index = int(patch.patch_vertices.size()/3); + patch.patch_vertices.emplace_back(m_vertices[j].v(0)); + patch.patch_vertices.emplace_back(m_vertices[j].v(1)); + patch.patch_vertices.emplace_back(m_vertices[j].v(2)); + patch.triangle_indices.emplace_back( index); + } + //patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); patch.facet_indices.push_back(current_facet); std::vector touching_triangles = get_all_touching_triangles(current_facet, neighbors[current_facet], neighbors_propagated[current_facet]); @@ -1246,16 +1268,16 @@ void TriangleSelectorPatch::set_filter_state(bool is_filter_state) void TriangleSelectorPatch::update_render_data() { - if (m_paint_changed || m_vertices_VBO_id == 0) { + if (m_paint_changed || (m_triangle_patches.size() == 0)) { this->release_geometry(); - m_patch_vertices.reserve(m_vertices.size() * 3); + /*m_patch_vertices.reserve(m_vertices.size() * 3); for (const Vertex& vr : m_vertices) { m_patch_vertices.emplace_back(vr.v.x()); m_patch_vertices.emplace_back(vr.v.y()); m_patch_vertices.emplace_back(vr.v.z()); } - this->finalize_vertices(); + this->finalize_vertices();*/ if (m_filter_state) update_triangles_per_patch(); @@ -1290,11 +1312,17 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) { assert(triangle_indices_idx < this->m_triangle_indices_VBO_ids.size()); assert(this->m_triangle_patches.size() == this->m_triangle_indices_VBO_ids.size()); - assert(this->m_vertices_VBO_id != 0); + //assert(this->m_vertices_VBO_id != 0); + assert(this->m_triangle_patches.size() == this->m_vertices_VBO_ids.size()); + assert(this->m_vertices_VBO_ids[triangle_indices_idx] != 0); assert(this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float)))); + //glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); + //glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float)))); + if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) { + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_ids[triangle_indices_idx])); + glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); + } glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); @@ -1307,14 +1335,19 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void TriangleSelectorPatch::release_geometry() { - if (m_vertices_VBO_id) { + /*if (m_vertices_VBO_id) { glsafe(::glDeleteBuffers(1, &m_vertices_VBO_id)); m_vertices_VBO_id = 0; + }*/ + for (auto& vertice_VBO_id : m_vertices_VBO_ids) { + glsafe(::glDeleteBuffers(1, &vertice_VBO_id)); + vertice_VBO_id = 0; } for (auto& triangle_indices_VBO_id : m_triangle_indices_VBO_ids) { glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); @@ -1325,23 +1358,33 @@ void TriangleSelectorPatch::release_geometry() void TriangleSelectorPatch::finalize_vertices() { - assert(m_vertices_VBO_id == 0); + /*assert(m_vertices_VBO_id == 0); if (!this->m_patch_vertices.empty()) { glsafe(::glGenBuffers(1, &this->m_vertices_VBO_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, this->m_patch_vertices.size() * sizeof(float), this->m_patch_vertices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); this->m_patch_vertices.clear(); - } + }*/ } void TriangleSelectorPatch::finalize_triangle_indices() { + m_vertices_VBO_ids.resize(m_triangle_patches.size()); m_triangle_indices_VBO_ids.resize(m_triangle_patches.size()); m_triangle_indices_sizes.resize(m_triangle_patches.size()); assert(std::all_of(m_triangle_indices_VBO_ids.cbegin(), m_triangle_indices_VBO_ids.cend(), [](const auto& ti_VBO_id) { return ti_VBO_id == 0; })); for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { + std::vector& patch_vertices = m_triangle_patches[buffer_idx].patch_vertices; + if (!patch_vertices.empty()) { + glsafe(::glGenBuffers(1, &m_vertices_VBO_ids[buffer_idx])); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices_VBO_ids[buffer_idx])); + glsafe(::glBufferData(GL_ARRAY_BUFFER, patch_vertices.size() * sizeof(float), patch_vertices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + patch_vertices.clear(); + } + std::vector& triangle_indices = m_triangle_patches[buffer_idx].triangle_indices; m_triangle_indices_sizes[buffer_idx] = triangle_indices.size(); if (!triangle_indices.empty()) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index a0791bb88..6e2b70686 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -112,6 +112,7 @@ protected: // BBS struct TrianglePatch { + std::vector patch_vertices; std::vector triangle_indices; std::vector facet_indices; EnforcerBlockerType type = EnforcerBlockerType::NONE; @@ -160,11 +161,15 @@ protected: void clear() { // BBS + this->m_vertices_VBO_ids.clear(); this->m_triangle_indices_VBO_ids.clear(); this->m_triangle_indices_sizes.clear(); for (TrianglePatch& patch : this->m_triangle_patches) + { + patch.patch_vertices.clear(); patch.triangle_indices.clear(); + } this->m_triangle_patches.clear(); } @@ -174,7 +179,7 @@ protected: return this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0; } - std::vector m_patch_vertices; + //std::vector m_patch_vertices; std::vector m_triangle_patches; // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects, @@ -183,7 +188,8 @@ protected: // IDs of the Vertex Array Objects, into which the geometry has been loaded. // Zero if the VBOs are not sent to GPU yet. - unsigned int m_vertices_VBO_id{ 0 }; + //unsigned int m_vertices_VBO_id{ 0 }; + std::vector m_vertices_VBO_ids; std::vector m_triangle_indices_VBO_ids; std::vector> m_ebt_colors; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 37c3c02e3..854986ff8 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -512,9 +512,9 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ return; } if (evt.CmdDown() && evt.GetKeyCode() == 'Q') { wxPostEvent(this, wxCloseEvent(wxEVT_CLOSE_WINDOW)); return;} - if (evt.CmdDown() && evt.RawControlDown() && evt.GetKeyCode() == 'F') { + if (evt.CmdDown() && evt.RawControlDown() && evt.GetKeyCode() == 'F') { EnableFullScreenView(true); - if (IsFullScreen()) { + if (IsFullScreen()) { ShowFullScreen(false); } else { ShowFullScreen(true); @@ -530,7 +530,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ #ifdef __APPLE__ if (evt.CmdDown() && evt.GetKeyCode() == ',') #else - if (evt.CmdDown() && evt.GetKeyCode() == 'P') + if (evt.CmdDown() && evt.GetKeyCode() == 'P') #endif { PreferencesDialog dlg(this); @@ -793,10 +793,10 @@ void MainFrame::shutdown() void MainFrame::update_title() { - return; + return; } -void MainFrame::update_title_colour_after_set_title() +void MainFrame::update_title_colour_after_set_title() { #ifdef __APPLE__ set_title_colour_after_set_title(GetHandle()); @@ -1241,7 +1241,7 @@ bool MainFrame::can_deselect() const bool MainFrame::can_delete() const { - return (m_plater != nullptr) && (m_tabpanel->GetSelection() == TabPosition::tp3DEditor) && !m_plater->is_selection_empty(); + return (m_plater != nullptr) && (m_tabpanel->GetSelection() == TabPosition::tp3DEditor) && !m_plater->is_selection_empty(); } bool MainFrame::can_delete_all() const @@ -1929,9 +1929,9 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(false); }, "menu_export_gcode", nullptr, [this]() {return can_export_gcode(); }, this); append_menu_item( - export_menu, wxID_ANY, _L("Export &Configs") + dots /* + "\tCtrl+E"*/, _L("Export current configuration to files"), + export_menu, wxID_ANY, _L("Export &Configs") + dots /* + "\tCtrl+E"*/, _L("Export current configuration to files"), [this](wxCommandEvent &) { export_config(); }, - "menu_export_config", nullptr, + "menu_export_config", nullptr, []() { return true; }, this); append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), ""); @@ -2093,6 +2093,11 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); + viewMenu->AppendSeparator(); + append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene"), + [this](wxCommandEvent&) { m_plater->toggle_show_wireframe(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this, + [this]() { return m_plater->is_wireframe_enabled(); }, [this]() { return m_plater->is_show_wireframe(); }, this); + //viewMenu->AppendSeparator(); ////BBS orthogonal view //append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"), @@ -2232,7 +2237,7 @@ void MainFrame::init_menubar_as_editor() // Help menu auto helpMenu = generate_help_menu(); - + #ifndef __APPLE__ m_topbar->SetFileMenu(fileMenu); if (editMenu) @@ -2240,7 +2245,7 @@ void MainFrame::init_menubar_as_editor() if (viewMenu) m_topbar->AddDropDownSubMenu(viewMenu, _L("View")); //BBS add Preference - + append_menu_item( m_topbar->GetTopMenu(), wxID_ANY, _L("Preferences") + "\tCtrl+P", _L(""), [this](wxCommandEvent &) { @@ -2424,7 +2429,7 @@ void MainFrame::export_config() }, false); if (!files.empty()) m_last_config = from_u8(files.back()); - MessageDialog dlg(this, wxString::Format(_L_PLURAL("There is %d config exported. (Only non-system configs)", + MessageDialog dlg(this, wxString::Format(_L_PLURAL("There is %d config exported. (Only non-system configs)", "There are %d configs exported. (Only non-system configs)", files.size()), files.size()), _L("Export result"), wxOK); dlg.ShowModal(); @@ -2464,7 +2469,7 @@ void MainFrame::load_config_file() wxGetApp().app_config->update_config_dir(get_dir_name(cfiles.back())); wxGetApp().load_current_presets(); } - MessageDialog dlg2(this, wxString::Format(_L_PLURAL("There is %d config imported. (Only non-system and compatible configs)", + MessageDialog dlg2(this, wxString::Format(_L_PLURAL("There is %d config imported. (Only non-system and compatible configs)", "There are %d configs imported. (Only non-system and compatible configs)", cfiles.size()), cfiles.size()), _L("Import result"), wxOK); dlg2.ShowModal(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 629279a04..118f81b42 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1632,6 +1632,7 @@ struct Plater::priv bool show_render_statistic_dialog{ false }; bool show_wireframe{ false }; + bool wireframe_enabled{ false }; static const std::regex pattern_bundle; static const std::regex pattern_3mf; @@ -10603,6 +10604,16 @@ bool Plater::is_show_wireframe() const return p->show_wireframe; } +void Plater::enable_wireframe(bool status) +{ + p->wireframe_enabled = status; +} + +bool Plater::is_wireframe_enabled() const +{ + return p->wireframe_enabled; +} + /*Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name) : TakeSnapshot(plater, from_u8(snapshot_name)) {} diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 36442e2bf..5a4ecdd1f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -624,6 +624,8 @@ public: void toggle_show_wireframe(); bool is_show_wireframe() const; + void enable_wireframe(bool status); + bool is_wireframe_enabled() const; // Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu. bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition);