diff --git a/resources/icons/mode_expert_.png b/resources/icons/mode_expert_.png
new file mode 100644
index 000000000..4d78bcccf
Binary files /dev/null and b/resources/icons/mode_expert_.png differ
diff --git a/resources/icons/mode_middle_.png b/resources/icons/mode_middle_.png
new file mode 100644
index 000000000..d98d8f709
Binary files /dev/null and b/resources/icons/mode_middle_.png differ
diff --git a/resources/icons/mode_simple_.png b/resources/icons/mode_simple_.png
new file mode 100644
index 000000000..aac2b61b0
Binary files /dev/null and b/resources/icons/mode_simple_.png differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6b7d621a8..dbc4ecd21 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -119,28 +119,28 @@ if (MSVC)
         foreach (CONF ${CMAKE_CONFIGURATION_TYPES})
             file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR)
             file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}/resources" WIN_RESOURCES_SYMLINK)
-            add_custom_target("resources_symlink_${CONF}" ALL
-                DEPENDS slic3r
+            add_custom_command(TARGET slic3r POST_BUILD
                 COMMAND if exist "${WIN_CONF_OUTPUT_DIR}" "("
                         if not exist "${WIN_RESOURCES_SYMLINK}" "("
                             mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}"
                         ")"
                     ")"
+                COMMENT "Symlinking the resources directory into the build tree"
                 VERBATIM
             )
         endforeach ()
     else ()
         file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/resources" WIN_RESOURCES_SYMLINK)
-        add_custom_target(resources_symlink ALL
-            DEPENDS slic3r
+        add_custom_command(TARGET slic3r POST_BUILD
             COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" "(" mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")"
+            COMMENT "Symlinking the resources directory into the build tree"
             VERBATIM
         )
     endif ()
 else ()
-    add_custom_target(resources_symlink ALL
-        DEPENDS slic3r
+    add_custom_command(TARGET slic3r POST_BUILD
         COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources"
+        COMMENT "Symlinking the resources directory into the build tree"
         VERBATIM
     )
 endif()
diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp
index bf94db6b1..085f55b9b 100644
--- a/src/libslic3r/Format/3mf.cpp
+++ b/src/libslic3r/Format/3mf.cpp
@@ -1249,14 +1249,25 @@ namespace Slic3r {
 
     void _3MF_Importer::_apply_transform(ModelInstance& instance, const Transform3d& transform)
     {
-        // slic3r ModelInstance cannot be transformed using a matrix
-        // we extract from the given matrix only the values currently used
-
         // translation
         Vec3d offset = transform.matrix().block(0, 3, 3, 1);
 
-        // scale
         Eigen::Matrix<double, 3, 3, Eigen::DontAlign> m3x3 = transform.matrix().block(0, 0, 3, 3);
+#if ENABLE_MIRROR
+        // mirror
+        // it is impossible to reconstruct the original mirroring factors from a matrix,
+        // we can only detect if the matrix contains a left handed reference system
+        // in which case we reorient it back to right handed by mirroring the x axis
+        Vec3d mirror = Vec3d::Ones();
+        if (m3x3.col(0).dot(m3x3.col(1).cross(m3x3.col(2))) < 0.0)
+        {
+            mirror(0) = -1.0;
+            // remove mirror
+            m3x3.col(0) *= -1.0;
+        }
+
+        // scale
+#endif // ENABLE_MIRROR
         Vec3d scale(m3x3.col(0).norm(), m3x3.col(1).norm(), m3x3.col(2).norm());
 
         // invalid scale value, return
@@ -1273,6 +1284,9 @@ namespace Slic3r {
         instance.set_offset(offset);
         instance.set_scaling_factor(scale);
         instance.set_rotation(rotation);
+#if ENABLE_MIRROR
+        instance.set_mirror(mirror);
+#endif // ENABLE_MIRROR
     }
 
     bool _3MF_Importer::_handle_start_config(const char** attributes, unsigned int num_attributes)
diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp
index 00ed0d937..be0261634 100644
--- a/src/libslic3r/Format/AMF.cpp
+++ b/src/libslic3r/Format/AMF.cpp
@@ -32,6 +32,9 @@
 // 2 : Added z component of offset
 //     Added x and y components of rotation
 //     Added x, y and z components of scale
+#if ENABLE_MIRROR
+//     Added x, y and z components of mirror
+#endif // ENABLE_MIRROR
 const unsigned int VERSION_AMF = 2;
 const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version";
 
@@ -126,14 +129,27 @@ struct AMFParserContext
         NODE_TYPE_RY,                   // amf/constellation/instance/ry
         NODE_TYPE_RZ,                   // amf/constellation/instance/rz
         NODE_TYPE_SCALE,                // amf/constellation/instance/scale
-        NODE_TYPE_SCALEX,                // amf/constellation/instance/scalex
-        NODE_TYPE_SCALEY,                // amf/constellation/instance/scaley
-        NODE_TYPE_SCALEZ,                // amf/constellation/instance/scalez
+        NODE_TYPE_SCALEX,               // amf/constellation/instance/scalex
+        NODE_TYPE_SCALEY,               // amf/constellation/instance/scaley
+        NODE_TYPE_SCALEZ,               // amf/constellation/instance/scalez
+#if ENABLE_MIRROR
+        NODE_TYPE_MIRRORX,              // amf/constellation/instance/mirrorx
+        NODE_TYPE_MIRRORY,              // amf/constellation/instance/mirrory
+        NODE_TYPE_MIRRORZ,              // amf/constellation/instance/mirrorz
+#endif // ENABLE_MIRROR
         NODE_TYPE_METADATA,             // anywhere under amf/*/metadata
     };
 
     struct Instance {
+#if ENABLE_MIRROR
+        Instance()
+            : deltax_set(false), deltay_set(false), deltaz_set(false)
+            , rx_set(false), ry_set(false), rz_set(false)
+            , scalex_set(false), scaley_set(false), scalez_set(false)
+            , mirrorx_set(false), mirrory_set(false), mirrorz_set(false) {}
+#else
         Instance() : deltax_set(false), deltay_set(false), deltaz_set(false), rx_set(false), ry_set(false), rz_set(false), scalex_set(false), scaley_set(false), scalez_set(false)  {}
+#endif // ENABLE_MIRROR
         // Shift in the X axis.
         float deltax;
         bool  deltax_set;
@@ -159,6 +175,15 @@ struct AMFParserContext
         bool  scaley_set;
         float scalez;
         bool  scalez_set;
+#if ENABLE_MIRROR
+        // Mirroring factors
+        float mirrorx;
+        bool  mirrorx_set;
+        float mirrory;
+        bool  mirrory_set;
+        float mirrorz;
+        bool  mirrorz_set;
+#endif // ENABLE_MIRROR
     };
 
     struct Object {
@@ -289,6 +314,14 @@ void AMFParserContext::startElement(const char *name, const char **atts)
                 node_type_new = NODE_TYPE_SCALEZ;
             else if (strcmp(name, "scale") == 0)
                 node_type_new = NODE_TYPE_SCALE;
+#if ENABLE_MIRROR
+            else if (strcmp(name, "mirrorx") == 0)
+                node_type_new = NODE_TYPE_MIRRORX;
+            else if (strcmp(name, "mirrory") == 0)
+                node_type_new = NODE_TYPE_MIRRORY;
+            else if (strcmp(name, "mirrorz") == 0)
+                node_type_new = NODE_TYPE_MIRRORZ;
+#endif // ENABLE_MIRROR
         }
         break;
     case 4:
@@ -345,16 +378,23 @@ void AMFParserContext::characters(const XML_Char *s, int len)
     {
         switch (m_path.size()) {
         case 4:
-            if (m_path.back() == NODE_TYPE_DELTAX || 
-                m_path.back() == NODE_TYPE_DELTAY || 
-                m_path.back() == NODE_TYPE_DELTAZ || 
+            if (m_path.back() == NODE_TYPE_DELTAX ||
+                m_path.back() == NODE_TYPE_DELTAY ||
+                m_path.back() == NODE_TYPE_DELTAZ ||
                 m_path.back() == NODE_TYPE_RX ||
                 m_path.back() == NODE_TYPE_RY ||
                 m_path.back() == NODE_TYPE_RZ ||
                 m_path.back() == NODE_TYPE_SCALEX ||
                 m_path.back() == NODE_TYPE_SCALEY ||
                 m_path.back() == NODE_TYPE_SCALEZ ||
+#if ENABLE_MIRROR
+                m_path.back() == NODE_TYPE_SCALE ||
+                m_path.back() == NODE_TYPE_MIRRORX ||
+                m_path.back() == NODE_TYPE_MIRRORY ||
+                m_path.back() == NODE_TYPE_MIRRORZ)
+#else
                 m_path.back() == NODE_TYPE_SCALE)
+#endif // ENABLE_MIRROR
                 m_value[0].append(s, len);
             break;
         case 6:
@@ -446,6 +486,26 @@ void AMFParserContext::endElement(const char * /* name */)
         m_instance->scalez_set = true;
         m_value[0].clear();
         break;
+#if ENABLE_MIRROR
+    case NODE_TYPE_MIRRORX:
+        assert(m_instance);
+        m_instance->mirrorx = float(atof(m_value[0].c_str()));
+        m_instance->mirrorx_set = true;
+        m_value[0].clear();
+        break;
+    case NODE_TYPE_MIRRORY:
+        assert(m_instance);
+        m_instance->mirrory = float(atof(m_value[0].c_str()));
+        m_instance->mirrory_set = true;
+        m_value[0].clear();
+        break;
+    case NODE_TYPE_MIRRORZ:
+        assert(m_instance);
+        m_instance->mirrorz = float(atof(m_value[0].c_str()));
+        m_instance->mirrorz_set = true;
+        m_value[0].clear();
+        break;
+#endif // ENABLE_MIRROR
 
     // Object vertices:
     case NODE_TYPE_VERTEX:
@@ -585,6 +645,9 @@ void AMFParserContext::endDocument()
                 mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0));
                 mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0));
                 mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0));
+#if ENABLE_MIRROR
+                mi->set_mirror(Vec3d(instance.mirrorx_set ? (double)instance.mirrorx : 1.0, instance.mirrory_set ? (double)instance.mirrory : 1.0, instance.mirrorz_set ? (double)instance.mirrorz : 1.0));
+#endif // ENABLE_MIRROR
             }
     }
 }
@@ -891,6 +954,11 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
                     "      <scalex>%lf</scalex>\n"
                     "      <scaley>%lf</scaley>\n"
                     "      <scalez>%lf</scalez>\n"
+#if ENABLE_MIRROR
+                    "      <mirrorx>%lf</mirrorx>\n"
+                    "      <mirrory>%lf</mirrory>\n"
+                    "      <mirrorz>%lf</mirrorz>\n"
+#endif // ENABLE_MIRROR
                     "    </instance>\n",
                     object_id,
                     instance->get_offset(X),
@@ -901,7 +969,14 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
                     instance->get_rotation(Z),
                     instance->get_scaling_factor(X),
                     instance->get_scaling_factor(Y),
+#if ENABLE_MIRROR
+                    instance->get_scaling_factor(Z),
+                    instance->get_mirror(X),
+                    instance->get_mirror(Y),
+                    instance->get_mirror(Z));
+#else
                     instance->get_scaling_factor(Z));
+#endif // ENABLE_MIRROR
 
                 //FIXME missing instance->scaling_factor
                 instances.append(buf);
diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp
index d001acedb..331d11833 100644
--- a/src/libslic3r/Model.cpp
+++ b/src/libslic3r/Model.cpp
@@ -711,9 +711,13 @@ void ModelObject::center_around_origin()
 
     if (!this->instances.empty()) {
         for (ModelInstance *i : this->instances) {
+#if ENABLE_MIRROR
+            i->set_offset(i->get_offset() - shift);
+#else
             // apply rotation and scaling to vector as well before translating instance,
             // in order to leave final position unaltered
             i->set_offset(i->get_offset() + i->transform_vector(-shift, true));
+#endif // ENABLE_MIRROR
         }
         this->invalidate_bounding_box();
     }
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 3f8fd80f0..d80d6df0d 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -11,7 +11,7 @@
 // New selections
 #define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0)
 // Add mirror components along the three axes in ModelInstance and GLVolume
-#define ENABLE_MIRROR (0 && ENABLE_1_42_0)
+#define ENABLE_MIRROR (1 && ENABLE_1_42_0)
 
 #endif // _technologies_h_
 
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 4bb0f499f..7d47ff8f6 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -3432,7 +3432,6 @@ int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const
 #if ENABLE_EXTENDED_SELECTION
 void GLCanvas3D::mirror_selection(Axis axis)
 {
-    m_regenerate_volumes = false;
     m_selection.mirror(axis);
     _on_mirror();
     wxGetApp().obj_manipul()->update_settings_value(m_selection);
@@ -3457,7 +3456,12 @@ void GLCanvas3D::reload_scene(bool force)
 
 #if ENABLE_EXTENDED_SELECTION
     if (m_regenerate_volumes)
+    {
         reset_volumes();
+
+        // to update the toolbar
+        post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
+    }
 #endif // ENABLE_EXTENDED_SELECTION
 
     set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
@@ -3477,9 +3481,6 @@ void GLCanvas3D::reload_scene(bool force)
         {
             load_object(*m_model, obj_idx);
         }
-
-        // to update the toolbar
-        post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
     }
 
     update_gizmos_data();
@@ -3858,7 +3859,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         case Gizmos::Scale:
         {
 #if ENABLE_EXTENDED_SELECTION
-            m_regenerate_volumes = false;
             m_selection.scale(m_gizmos.get_scale());
             _on_scale();
 #else
@@ -3875,7 +3875,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         case Gizmos::Rotate:
         {
 #if ENABLE_EXTENDED_SELECTION
-            m_regenerate_volumes = false;
             m_selection.rotate(m_gizmos.get_rotation());
             _on_rotate();
 #else
@@ -3958,7 +3957,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             if (m_gizmos.get_current_type() == Gizmos::Flatten) {
                 // Rotate the object so the normal points downward:
 #if ENABLE_EXTENDED_SELECTION
-                m_regenerate_volumes = false;
                 m_selection.rotate(m_gizmos.get_flattening_rotation());
                 _on_flatten();
                 wxGetApp().obj_manipul()->update_settings_value(m_selection);
@@ -4397,7 +4395,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             case Gizmos::Scale:
             {
 #if ENABLE_EXTENDED_SELECTION
-                m_regenerate_volumes = false;
                 _on_scale();
 #endif // ENABLE_EXTENDED_SELECTION
                 break;
@@ -4405,7 +4402,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             case Gizmos::Rotate:
             {
 #if ENABLE_EXTENDED_SELECTION
-                m_regenerate_volumes = false;
                 _on_rotate();
 #else
                 post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation()));
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index c56e69670..56d01b7f5 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -4,6 +4,7 @@
 #include <wx/bitmap.h>
 #include <wx/dataview.h>
 #include <map>
+#include <vector>
 
 class wxBoxSizer;
 class PrusaObjectDataViewModel;
diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp
index fb494ed23..5a7ece586 100644
--- a/src/slic3r/GUI/GUI_Utils.cpp
+++ b/src/slic3r/GUI/GUI_Utils.cpp
@@ -28,6 +28,7 @@ CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
 
     auto* sizer = new wxBoxSizer(wxHORIZONTAL);
     cbox = new wxCheckBox(this, wxID_ANY, checkbox_label);
+    cbox->SetValue(true);
     sizer->AddSpacer(5);
     sizer->Add(this->cbox, 0, wxEXPAND | wxALL, 5);
     SetSizer(sizer);
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 6a202ad4c..5df19df80 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -296,11 +296,11 @@ void MainFrame::init_menubar()
     if (m_plater) {
         m_plater_menu = new wxMenu();
         append_menu_item(m_plater_menu, wxID_ANY, _(L("Export G-code...")), _(L("Export current plate as G-code")),
-            [this](wxCommandEvent&){ /*m_plater->export_gcode(); */}, "cog_go.png");
+            [this](wxCommandEvent&){ m_plater->export_gcode(); }, "cog_go.png");
         append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")),
-            [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png");
+            [this](wxCommandEvent&){ m_plater->export_stl(); }, "brick_go.png");
         append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")),
-            [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png");
+            [this](wxCommandEvent&){ m_plater->export_amf(); }, "brick_go.png");
         append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")),
             [this](wxCommandEvent&){ m_plater->export_3mf(); }, "brick_go.png");
     }
diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp
index 8ee78cee6..371747bc1 100644
--- a/src/slic3r/GUI/OptionsGroup.cpp
+++ b/src/slic3r/GUI/OptionsGroup.cpp
@@ -388,24 +388,32 @@ void ConfigOptionsGroup::reload_config(){
 }
 
 bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) {
+    if (m_options_mode.empty())
+        return true;
     if (m_grid_sizer->GetEffectiveRowsCount() != m_options_mode.size() &&
         m_options_mode.size() == 1)
         return m_options_mode[0] <= mode;
 
     sizer->ShowItems(true);
+#ifdef __WXGTK__
+    m_panel->Show(true);
+    m_grid_sizer->Show(true);
+#endif /* __WXGTK__ */
 
     int coef = 0;
+    int hidden_row_cnt = 0;
     const int cols = m_grid_sizer->GetCols();
     for (auto opt_mode : m_options_mode) {
 		const bool show = opt_mode <= mode;
         if (!show) {
+            hidden_row_cnt++;
             for (int i = 0; i < cols; ++i)
                 m_grid_sizer->Show(coef + i, show);
         }
         coef+= cols;
 	}
 
-    if (!sizer->IsShown(m_grid_sizer)) {
+    if (hidden_row_cnt == m_options_mode.size()) {
         sizer->ShowItems(false);
         return false;
     }
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index b5cb21625..ecf36595e 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -700,7 +700,7 @@ private:
     static const std::regex pattern_drop;
 };
 
-const std::regex PlaterDropTarget::pattern_drop("[.](stl|obj|amf|3mf|prusa)$", std::regex::icase);
+const std::regex PlaterDropTarget::pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase);
 
 bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
 {
@@ -850,13 +850,15 @@ private:
     bool layers_height_allowed() const;
     bool can_delete_all() const;
     bool can_arrange() const;
+#if ENABLE_MIRROR
     bool can_mirror() const;
+#endif // ENABLE_MIRROR
 #endif // ENABLE_EXTENDED_SELECTION
 };
 
-const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase);
-const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase);
-const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase);
+const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase);
+const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase);
+const std::regex Plater::priv::pattern_zip_amf(".*[.]zip[.]amf", std::regex::icase);
 
 Plater::priv::priv(Plater *q, MainFrame *main_frame) :
     q(q),
@@ -1258,7 +1260,8 @@ std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType
         case FT_STL:
         case FT_AMF:
         case FT_3MF:
-            wildcard = file_wildcards[FT_STL];
+        case FT_GCODE:
+            wildcard = file_wildcards[file_type];
         break;
 
         default:
@@ -1362,7 +1365,7 @@ void Plater::priv::selection_changed()
     _3DScene::enable_toolbar_item(canvas3D, "split", have_sel);
     _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel);
     _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel);
-    _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed);
+    _3DScene::enable_toolbar_item(canvas3D, "layersediting", have_sel && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D));
 #endif // ENABLE_EXTENDED_SELECTION
 
 #if ENABLE_EXTENDED_SELECTION
@@ -1474,6 +1477,9 @@ void Plater::priv::remove(size_t obj_idx)
     // Prevent toolpaths preview from rendering while we modify the Print object
     preview->set_enabled(false);
 
+    if (_3DScene::is_layers_editing_enabled(canvas3D))
+        _3DScene::enable_layers_editing(canvas3D, false);
+
 #if !ENABLE_EXTENDED_SELECTION
     objects.erase(objects.begin() + obj_idx);
 #endif // !ENABLE_EXTENDED_SELECTION
@@ -1497,6 +1503,9 @@ void Plater::priv::reset()
     // Prevent toolpaths preview from rendering while we modify the Print object
     preview->set_enabled(false);
 
+    if (_3DScene::is_layers_editing_enabled(canvas3D))
+        _3DScene::enable_layers_editing(canvas3D, false);
+
 #if !ENABLE_EXTENDED_SELECTION
     objects.clear();
 #endif // !ENABLE_EXTENDED_SELECTION
@@ -1774,7 +1783,10 @@ void Plater::priv::on_action_settings(SimpleEvent&)
 
 void Plater::priv::on_action_layersediting(SimpleEvent&)
 {
-    // TODO
+    bool enable = !_3DScene::is_layers_editing_enabled(canvas3D);
+    _3DScene::enable_layers_editing(canvas3D, enable);
+    if (enable && !_3DScene::is_layers_editing_enabled(canvas3D))
+        _3DScene::enable_toolbar_item(canvas3D, "layersediting", false);
 }
 
 #if !ENABLE_EXTENDED_SELECTION
@@ -1899,6 +1911,7 @@ bool Plater::priv::init_object_menu()
 
     object_menu.AppendSeparator();
     
+#if ENABLE_MIRROR
     wxMenu* mirror_menu = new wxMenu();
     if (mirror_menu == nullptr)
         return false;
@@ -1911,6 +1924,7 @@ bool Plater::priv::init_object_menu()
         [this](wxCommandEvent&){ mirror(Z); }, "bullet_blue.png", &object_menu);
 
     wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")));
+#endif // ENABLE_MIRROR
 
     wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")),
         [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png");
@@ -1919,7 +1933,9 @@ bool Plater::priv::init_object_menu()
     // ui updates needs to be binded to the parent panel
     if (q != nullptr)
     {
+#if ENABLE_MIRROR
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
+#endif // ENABLE_MIRROR
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId());
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId());
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId());
@@ -1963,7 +1979,8 @@ bool Plater::priv::can_cut_object() const
 
 bool Plater::priv::layers_height_allowed() const
 {
-    return config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D);
+    int obj_idx = get_selected_object_idx();
+    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D);
 }
 
 bool Plater::priv::can_delete_all() const
@@ -1976,10 +1993,12 @@ bool Plater::priv::can_arrange() const
     return !model.objects.empty();
 }
 
+#if ENABLE_MIRROR
 bool Plater::priv::can_mirror() const
 {
     return get_selection().is_from_single_instance();
 }
+#endif // ENABLE_MIRROR
 #endif // ENABLE_EXTENDED_SELECTION
 
 // Plater / Public
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index bb7aa3e9b..d4249ea23 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -476,14 +476,14 @@ void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool
 void Tab::update_changed_tree_ui()
 {
 	auto cur_item = m_treectrl->GetFirstVisibleItem();
-    if (!m_treectrl->IsVisible(cur_item))
+    if (!cur_item || !m_treectrl->IsVisible(cur_item))
         return;
 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
 	while (cur_item){
 		auto title = m_treectrl->GetItemText(cur_item);
 		for (auto page : m_pages)
 		{
-			if (page->title() != title)
+			if (page->title() != title) 
 				continue;
 			bool sys_page = true;
 			bool modified_page = false;
@@ -644,6 +644,11 @@ void Tab::update_visibility(ConfigOptionMode mode)
     Refresh();
 
 	Thaw();
+
+    // to update tree items color
+    wxTheApp->CallAfter([this]() {
+        update_changed_tree_ui();
+    });
 }
 
 Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const
@@ -1782,7 +1787,7 @@ void TabPrinter::build_sla()
     auto page = add_options_page(_(L("General")), "printer_empty.png");
     auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
 
-    Line line{ _(L("Bed shape")), "" };
+    Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
     line.widget = [this](wxWindow* parent){
         auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
         //			btn->SetFont(Slic3r::GUI::small_font);
@@ -2762,8 +2767,8 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
             bmp_name = "error.png";
         else {
             auto mode = line.get_options()[0].opt.mode;  //we assume that we have one option per line
-            bmp_name = mode == comExpert ? "mode_expert.png" :
-                       mode == comMiddle ? "mode_middle.png" : "mode_simple.png";
+            bmp_name = mode == comExpert ? "mode_expert_.png" :
+                       mode == comMiddle ? "mode_middle_.png" : "mode_simple_.png";
         }                               
         auto bmp = new wxStaticBitmap(parent, wxID_ANY, wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG));
         return bmp;
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index 4ff73027c..80a564fd0 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -12,6 +12,7 @@
 
 #include <vector>
 #include <set>
+#include <functional>
 
 wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
     std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr);