diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 5d49c3675..aa1e49e83 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -44,6 +44,8 @@ #define ENABLE_RENDER_SELECTION_CENTER (0 && ENABLE_1_42_0) // Show visual hints in the 3D scene when sidebar matrix fields have focus #define ENABLE_SIDEBAR_VISUAL_HINTS (1 && ENABLE_1_42_0) +// Separate rendering for opaque and transparent volumes +#define ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 961d4822a..b801b6679 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -797,6 +797,9 @@ int GLVolumeCollection::load_object_volume( color[2] = 1.0f; } color[3] = model_volume->is_model_part() ? 1.f : 0.5f; */ +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + color[3] = model_volume->is_model_part() ? 1.f : 0.5f; +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); v.set_color_from_model_volume(model_volume); @@ -953,12 +956,54 @@ int GLVolumeCollection::load_wipe_tower_preview( return int(this->volumes.size() - 1); } +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +typedef std::pair GLVolumeWithZ; +typedef std::vector GLVolumesWithZList; +GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type) +{ + GLVolumesWithZList list; + + for (GLVolume* volume : volumes) + { + bool is_transparent = (volume->render_color[3] < 1.0f); + if (((type == GLVolumeCollection::Opaque) && !is_transparent) || + ((type == GLVolumeCollection::Transparent) && is_transparent) || + (type == GLVolumeCollection::All)) + list.push_back(std::make_pair(volume, 0.0)); + } + + if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) + { + Transform3d modelview_matrix; + ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); + + for (GLVolumeWithZ& volume : list) + { + volume.second = volume.first->bounding_box.transformed(modelview_matrix * volume.first->world_matrix()).max(2); + } + + std::sort(list.begin(), list.end(), + [](const GLVolumeWithZ& v1, const GLVolumeWithZ& v2) -> bool { return v1.second < v2.second; } + ); + } + + return list; +} + +void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface) const +#else void GLVolumeCollection::render_VBOs() const +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING { ::glEnable(GL_BLEND); ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ::glCullFace(GL_BACK); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glDisable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + ::glEnableClientState(GL_VERTEX_ARRAY); ::glEnableClientState(GL_NORMAL_ARRAY); @@ -980,6 +1025,18 @@ void GLVolumeCollection::render_VBOs() const if (z_range_id != -1) ::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + GLVolumesWithZList to_render = volumes_to_render(this->volumes, type); + for (GLVolumeWithZ& volume : to_render) + { + if (volume.first->layer_height_texture_data.can_use()) + volume.first->generate_layer_height_texture(volume.first->layer_height_texture_data.print_object, false); + else + volume.first->set_render_color(); + + volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); + } +#else for (GLVolume *volume : this->volumes) { if (volume->layer_height_texture_data.can_use()) @@ -989,6 +1046,7 @@ void GLVolumeCollection::render_VBOs() const volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); } +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING ::glBindBuffer(GL_ARRAY_BUFFER, 0); ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -996,27 +1054,55 @@ void GLVolumeCollection::render_VBOs() const ::glDisableClientState(GL_VERTEX_ARRAY); ::glDisableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glEnable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + ::glDisable(GL_BLEND); } +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const +#else void GLVolumeCollection::render_legacy() const +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glCullFace(GL_BACK); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glDisable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + GLVolumesWithZList to_render = volumes_to_render(this->volumes, type); + for (GLVolumeWithZ& volume : to_render) + { + volume.first->set_render_color(); + volume.first->render_legacy(); + } +#else for (GLVolume *volume : this->volumes) { volume->set_render_color(); volume->render_legacy(); } +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glEnable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + glDisable(GL_BLEND); } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 76cacabbd..b5ae5b965 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -500,6 +500,17 @@ typedef std::vector GLVolumePtrs; class GLVolumeCollection { +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +public: + enum ERenderType : unsigned char + { + Opaque, + Transparent, + All + }; + +private: +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // min and max vertex of the print box volume float print_box_min[3]; float print_box_max[3]; @@ -544,8 +555,13 @@ public: int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width); // Render the volumes by OpenGL. +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + void render_VBOs(ERenderType type, bool disable_cullface) const; + void render_legacy(ERenderType type, bool disable_cullface) const; +#else void render_VBOs() const; void render_legacy() const; +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 0283b7c29..9855806be 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -172,12 +172,14 @@ void Field::get_value_by_opt_type(wxString& str) show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits"))); set_value(double_to_string(val), true); } - else if (val > 1) + else if (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max || + m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1) { + std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; const int nVal = int(val); - wxString msg_text = wxString::Format(_(L("Do you mean %d%% instead of %dmm?\n" + wxString msg_text = wxString::Format(_(L("Do you mean %d%% instead of %d %s?\n" "Select YES if you want to change this value to %d%%, \n" - "or NO if you are sure that %dmm is a correct value.")), nVal, nVal, nVal, nVal); + "or NO if you are sure that %d %s is a correct value.")), nVal, nVal, sidetext, nVal, nVal, sidetext); auto dialog = new wxMessageDialog(m_parent, msg_text, _(L("Parameter validation")), wxICON_WARNING | wxYES | wxNO); if (dialog->ShowModal() == wxID_YES) { set_value(wxString::Format("%s%%", str), true); @@ -274,7 +276,6 @@ void TextCtrl::BUILD() { e.Skip(); temp->GetToolTip()->Enable(true); #endif // __WXGTK__ -// if (!is_defined_input_value()) if (is_defined_input_value(window, m_opt.type)) on_change_field(); else @@ -399,10 +400,11 @@ void SpinCtrl::BUILD() { auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, 0, min_val, max_val, default_value); -// temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId()); - +#ifndef __WXOSX__ // #ys_FIXME_KILL_FOCUS - // wxEVT_KILL_FOCUS doesn't handled on OSX now + // wxEVT_KILL_FOCUS doesn't handled on OSX now (wxWidgets 3.1.1) + // So, we will update values on KILL_FOCUS & SPINCTRL events under MSW and GTK + // and on TEXT event under OSX temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { if (tmp_value < 0) @@ -413,6 +415,9 @@ void SpinCtrl::BUILD() { } }), temp->GetId()); + temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); +#endif + temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { // # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value @@ -424,9 +429,7 @@ void SpinCtrl::BUILD() { if (is_matched(value, "^\\d+$")) tmp_value = std::stoi(value); else tmp_value = -9999; -// on_change_field(); #ifdef __WXOSX__ - // #ys_FIXME_KILL_FOCUS so call on_change_field() inside wxEVT_TEXT if (tmp_value < 0) { if (m_on_kill_focus != nullptr) m_on_kill_focus(m_opt_id); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 66d4622fe..c650db329 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4313,7 +4313,13 @@ void GLCanvas3D::render() ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _render_background(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // textured bed needs to be rendered after objects if the texture is transparent + bool early_bed_render = is_custom_bed || (theta <= 90.0f); + if (early_bed_render) +#else if (is_custom_bed) // untextured bed needs to be rendered before objects +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING _render_bed(theta); _render_objects(); @@ -4322,7 +4328,11 @@ void GLCanvas3D::render() _render_axes(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (!early_bed_render) +#else if (!is_custom_bed) // textured bed needs to be rendered after objects +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING _render_bed(theta); #if ENABLE_RENDER_SELECTION_CENTER @@ -6119,7 +6129,7 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co // margin factor to give some empty space around the bbox double margin_factor = 1.25; - for (const Vec3d v : vertices) + for (const Vec3d& v : vertices) { // project vertex on the plane perpendicular to camera forward axis Vec3d pos(v(0) - bb_center(0), v(1) - bb_center(1), v(2) - bb_center(2)); @@ -6328,8 +6338,10 @@ void GLCanvas3D::_render_objects() const m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height")); m_volumes.check_outside_state(m_config, nullptr); } +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // do not cull backfaces to show broken geometry, if any ::glDisable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING } if (m_use_clipping_planes) @@ -6338,11 +6350,19 @@ void GLCanvas3D::_render_objects() const m_volumes.set_z_range(-FLT_MAX, FLT_MAX); m_shader.start_using(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // do not cull backfaces to show broken geometry, if any + m_volumes.render_VBOs(GLVolumeCollection::Opaque, m_picking_enabled); + m_volumes.render_VBOs(GLVolumeCollection::Transparent, false); +#else m_volumes.render_VBOs(); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING m_shader.stop_using(); +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_picking_enabled) ::glEnable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING } else { @@ -6354,14 +6374,24 @@ void GLCanvas3D::_render_objects() const ::glEnable(GL_CLIP_PLANE1); } +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // do not cull backfaces to show broken geometry, if any if (m_picking_enabled) ::glDisable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // do not cull backfaces to show broken geometry, if any + m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled); + m_volumes.render_legacy(GLVolumeCollection::Transparent, false); +#else m_volumes.render_legacy(); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_picking_enabled) ::glEnable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_use_clipping_planes) { diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 74ea52c64..6c24acd66 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -554,6 +554,13 @@ ConfigMenuIDs GUI_App::get_view_mode() mode == "simple" ? ConfigMenuModeSimple : ConfigMenuModeAdvanced; } +ConfigOptionMode GUI_App::get_opt_mode() { + const ConfigMenuIDs mode = wxGetApp().get_view_mode(); + + return mode == ConfigMenuModeSimple ? comSimple : + mode == ConfigMenuModeExpert ? comExpert : comAdvanced; +} + // Update view mode according to selected menu void GUI_App::update_mode() { @@ -568,10 +575,8 @@ void GUI_App::update_mode() sidebar().Layout(); - ConfigOptionMode opt_mode = mode == ConfigMenuModeSimple ? comSimple : - mode == ConfigMenuModeExpert ? comExpert : comAdvanced; for (auto tab : tabs_list) - tab->update_visibility(opt_mode); + tab->update_visibility(); plater()->update_object_menu(); } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index bd64a3ac5..e388910d7 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -135,6 +135,7 @@ public: Tab* get_tab(Preset::Type type); ConfigMenuIDs get_view_mode(); + ConfigOptionMode get_opt_mode(); void update_mode(); void add_config_menu(wxMenuBar *menu); diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 12929b2cc..6ebb1ef66 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -99,7 +99,7 @@ void KBShortcutsDialog::fill_shortcuts() main_shortcuts.reserve(25); main_shortcuts.push_back(Shortcut(ctrl+"O" ,L("Open project STL/OBJ/AMF/3MF with config, delete bed"))); - main_shortcuts.push_back(Shortcut(ctrl+"I" ,L("Import STL//OBJ/AMF/3MF without config, keep bed"))); + main_shortcuts.push_back(Shortcut(ctrl+"I" ,L("Import STL/OBJ/AMF/3MF without config, keep bed"))); main_shortcuts.push_back(Shortcut(ctrl+"L" ,L("Load Config from .ini/amf/3mf/gcode"))); main_shortcuts.push_back(Shortcut(ctrl+"G" ,L("Export Gcode"))); main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)"))); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 5b38129de..41339262b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -811,7 +811,7 @@ void MainFrame::on_value_changed(wxCommandEvent& event) void MainFrame::update_ui_from_settings() { bool bp_on = wxGetApp().app_config->get("background_processing") == "1"; - m_menu_item_reslice_now->Enable(bp_on); + m_menu_item_reslice_now->Enable(!bp_on); m_plater->sidebar().show_reslice(!bp_on); m_plater->sidebar().Layout(); if (m_plater) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 11894adf8..bcf66b603 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -224,7 +224,8 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : if (marker == LABEL_ITEM_MARKER) { this->SetSelection(this->last_selected); evt.StopPropagation(); - } else if (this->last_selected != selected_item) { + } else if ( this->last_selected != selected_item || + wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) { this->last_selected = selected_item; evt.SetInt(this->preset_type); evt.Skip(); @@ -945,6 +946,7 @@ struct Plater::priv void select_view(const std::string& direction); #if ENABLE_REMOVE_TABS_FROM_PLATER void select_view_3D(const std::string& name); + void select_next_view_3D(); #endif // ENABLE_REMOVE_TABS_FROM_PLATER void update_ui_from_settings(); ProgressStatusBar* statusbar(); @@ -1118,8 +1120,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D = new View3D(q, &model, config, &background_process); preview = new Preview(q, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); }); // Let the Tab key switch between the 3D view and the layer preview. - view3D->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->q->select_view_3D("Preview"); }); - preview->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->q->select_view_3D("3D"); }); + view3D->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->select_next_view_3D(); }); + preview->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->select_next_view_3D(); }); panels.push_back(view3D); panels.push_back(preview); @@ -1300,10 +1302,14 @@ void Plater::priv::select_view_3D(const std::string& name) set_current_panel(view3D); else if (name == "Preview") set_current_panel(preview); +} -#if !ENABLE_TOOLBAR_BACKGROUND_TEXTURE - view_toolbar.set_selection(name); -#endif // !ENABLE_TOOLBAR_BACKGROUND_TEXTURE +void Plater::priv::select_next_view_3D() +{ + if (current_panel == view3D) + set_current_panel(preview); + else if (current_panel == preview) + set_current_panel(view3D); } #else void Plater::priv::select_view(const std::string& direction) @@ -2243,13 +2249,17 @@ void Plater::priv::set_current_panel(wxPanel* panel) } // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) view3D->set_as_dirty(); + view_toolbar.select_item("3D"); } else if (current_panel == preview) { this->q->reslice(); preview->reload_print(); preview->set_canvas_as_dirty(); + view_toolbar.select_item("Preview"); } + + current_panel->SetFocusFromKbd(); } #else void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a4796778a..ae17eed38 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -667,8 +667,9 @@ void Tab::reload_config() Thaw(); } -void Tab::update_visibility(ConfigOptionMode mode) +void Tab::update_visibility() { + const ConfigOptionMode mode = wxGetApp().get_opt_mode(); Freeze(); for (auto page : m_pages) @@ -1988,6 +1989,7 @@ PageShp TabPrinter::build_kinematics_page() def.type = coString; def.width = 150; def.gui_type = "legend"; + def.mode = comAdvanced; def.tooltip = L("Values in this column are for Full Power mode"); def.default_value = new ConfigOptionString{ L("Full Power") }; @@ -2345,12 +2347,15 @@ void Tab::load_current_preset() init_options_list(); update_changed_ui(); }); + update_page_tree_visibility(); } //Regerenerate content of the page tree. void Tab::rebuild_page_tree(bool tree_sel_change_event /*= false*/) { Freeze(); + update_visibility(); + // get label of the currently selected item const auto sel_item = m_treectrl->GetSelection(); const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; @@ -2363,8 +2368,8 @@ void Tab::rebuild_page_tree(bool tree_sel_change_event /*= false*/) auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); if (p->title() == selected) { - if (!(p->title() == _(L("Machine limits")) || p->title() == _(L("Single extruder MM setup")))) // These Pages have to be updated inside OnTreeSelChange - m_disable_tree_sel_changed_event = !tree_sel_change_event; +// if (!(p->title() == _(L("Machine limits")) || p->title() == _(L("Single extruder MM setup")))) // These Pages have to be updated inside OnTreeSelChange +// m_disable_tree_sel_changed_event = !tree_sel_change_event; m_treectrl->SelectItem(itemId); m_disable_tree_sel_changed_event = false; have_selection = 1; @@ -2924,14 +2929,15 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la auto extra_column = [](wxWindow* parent, const Line& line) { std::string bmp_name; - if (line.get_options().size() == 0) - bmp_name = "error.png"; + const std::vector