ENH: enable wireframe

This reverts commit ed6e149381240fd83b61da70891127d400f30a39.

Change-Id: I010871fcf22322214c627fe907539c0916fa6ff5
This commit is contained in:
lane.wei 2022-10-22 21:37:48 +08:00 committed by Lane.Wei
parent 5e024f75b9
commit 79b5c94f4f
10 changed files with 263 additions and 38 deletions

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -869,10 +869,6 @@ void GLVolume::render(bool with_outline) const
std::array<float, 4> 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());

View File

@ -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<GLGizmoPainterBase*>(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<GLGizmoPainterBase*>(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();
}

View File

@ -45,7 +45,7 @@ std::pair<bool, std::string> 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<bool, std::string> 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" });

View File

@ -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<int> 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<float>& 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<int>& triangle_indices = m_triangle_patches[buffer_idx].triangle_indices;
m_triangle_indices_sizes[buffer_idx] = triangle_indices.size();
if (!triangle_indices.empty()) {

View File

@ -112,6 +112,7 @@ protected:
// BBS
struct TrianglePatch {
std::vector<float> patch_vertices;
std::vector<int> triangle_indices;
std::vector<int> 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<float> m_patch_vertices;
//std::vector<float> m_patch_vertices;
std::vector<TrianglePatch> 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<unsigned int> m_vertices_VBO_ids;
std::vector<unsigned int> m_triangle_indices_VBO_ids;
std::vector<std::array<float, 4>> m_ebt_colors;

View File

@ -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();

View File

@ -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)) {}

View File

@ -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);